MySQL: fix build on Fedora 27, where MariaDB version information has become unavailable
[exim.git] / src / src / string.c
index 4850fd958776875c7e6ef1a51482ea2576df0b86..f3bf343150b499b4135587808f14774ae7540ba0 100644 (file)
@@ -968,21 +968,43 @@ else
 *listptr = s;
 return buffer;
 }
-#endif  /* COMPILE_UTILITY */
 
 
-#ifndef COMPILE_UTILITY
+static const uschar *
+Ustrnchr(const uschar * s, int c, unsigned * len)
+{
+unsigned siz = *len;
+while (siz)
+  {
+  if (!*s) return NULL;
+  if (*s == c)
+    {
+    *len = siz;
+    return s;
+    }
+  s++;
+  siz--;
+  }
+return NULL;
+}
+
+
 /************************************************
 *      Add element to separated list           *
 ************************************************/
-/* This function is used to build a list, returning
-an allocated null-terminated growable string. The
-given element has any embedded separator characters
+/* This function is used to build a list, returning an allocated null-terminated
+growable string. The given element has any embedded separator characters
 doubled.
 
+Despite having the same growable-string interface as string_cat() the list is
+always returned null-terminated.
+
 Arguments:
   list points to the start of the list that is being built, or NULL
        if this is a new list that has no contents yet
+  sz    (ptr to) amount of memory allocated for list; zero for a new list
+  off   (ptr to) current list length in chars (insert point for next addition),
+        zero for a new list
   sep  list separator character
   ele  new element to be appended to the list
 
@@ -990,78 +1012,49 @@ Returns:  pointer to the start of the list, changed if copied for expansion.
 */
 
 uschar *
-string_append_listele(uschar * list, uschar sep, const uschar * ele)
+string_append_listele(uschar * list, int * sz, int * off,
+  uschar sep, const uschar * ele)
 {
-uschar * new = NULL;
-int sz = 0, off = 0;
 uschar * sp;
 
 if (list)
-  {
-  new = string_cat (new, &sz, &off, list);
-  new = string_catn(new, &sz, &off, &sep, 1);
-  }
+  list = string_catn(list, sz, off, &sep, 1);
 
 while((sp = Ustrchr(ele, sep)))
   {
-  new = string_catn(new, &sz, &off, ele, sp-ele+1);
-  new = string_catn(new, &sz, &off, &sep, 1);
+  list = string_catn(list, sz, off, ele, sp-ele+1);
+  list = string_catn(list, sz, off, &sep, 1);
   ele = sp+1;
   }
-new = string_cat(new, &sz, &off, ele);
-new[off] = '\0';
-return new;
+list = string_cat(list, sz, off, ele);
+list[*off] = '\0';
+return list;
 }
 
 
-static const uschar *
-Ustrnchr(const uschar * s, int c, unsigned * len)
-{
-unsigned siz = *len;
-while (siz)
-  {
-  if (!*s) return NULL;
-  if (*s == c)
-    {
-    *len = siz;
-    return s;
-    }
-  s++;
-  siz--;
-  }
-return NULL;
-}
-
 uschar *
-string_append_listele_n(uschar * list, uschar sep, const uschar * ele,
-  unsigned len)
+string_append_listele_n(uschar * list, int * sz, int * off,
+  uschar sep, const uschar * ele, unsigned len)
 {
-uschar * new = NULL;
-int sz = 0, off = 0;
 const uschar * sp;
 
 if (list)
-  {
-  new = string_cat (new, &sz, &off, list);
-  new = string_catn(new, &sz, &off, &sep, 1);
-  }
+  list = string_catn(list, sz, off, &sep, 1);
 
 while((sp = Ustrnchr(ele, sep, &len)))
   {
-  new = string_catn(new, &sz, &off, ele, sp-ele+1);
-  new = string_catn(new, &sz, &off, &sep, 1);
+  list = string_catn(list, sz, off, ele, sp-ele+1);
+  list = string_catn(list, sz, off, &sep, 1);
   ele = sp+1;
   len--;
   }
-new = string_catn(new, &sz, &off, ele, len);
-new[off] = '\0';
-return new;
+list = string_catn(list, sz, off, ele, len);
+list[*off] = '\0';
+return list;
 }
-#endif  /* COMPILE_UTILITY */
 
 
 
-#ifndef COMPILE_UTILITY
 /*************************************************
 *             Add chars to string                *
 *************************************************/
@@ -1081,7 +1074,7 @@ Arguments:
              characters, updated to the new offset
   s        points to characters to add
   count    count of characters to add; must not exceed the length of s, if s
-             is a C string.  If -1 given, strlen(s) is used.
+             is a C string.
 
 If string is given as NULL, *size and *ptr should both be zero.
 
@@ -1362,20 +1355,28 @@ while (*fp != 0)
     switch(length)
       {
       case L_SHORT:
-      case L_NORMAL:   sprintf(CS p, newformat, va_arg(ap, int)); break;
-      case L_LONG:     sprintf(CS p, newformat, va_arg(ap, long int)); break;
-      case L_LONGLONG: sprintf(CS p, newformat, va_arg(ap, LONGLONG_T)); break;
-      case L_SIZE:     sprintf(CS p, newformat, va_arg(ap, size_t)); break;
+      case L_NORMAL:   p += sprintf(CS p, newformat, va_arg(ap, int)); break;
+      case L_LONG:     p += sprintf(CS p, newformat, va_arg(ap, long int)); break;
+      case L_LONGLONG: p += sprintf(CS p, newformat, va_arg(ap, LONGLONG_T)); break;
+      case L_SIZE:     p += sprintf(CS p, newformat, va_arg(ap, size_t)); break;
       }
-    while (*p) p++;
     break;
 
     case 'p':
-    if (p >= last - 24) { yield = FALSE; goto END_FORMAT; }
-    strncpy(newformat, item_start, fp - item_start);
-    newformat[fp - item_start] = 0;
-    sprintf(CS p, newformat, va_arg(ap, void *));
-    while (*p) p++;
+      {
+      void * ptr;
+      if (p >= last - 24) { yield = FALSE; goto END_FORMAT; }
+      /* sprintf() saying "(nil)" for a null pointer seems unreliable.
+      Handle it explicitly. */
+      if ((ptr = va_arg(ap, void *)))
+       {
+       strncpy(newformat, item_start, fp - item_start);
+       newformat[fp - item_start] = 0;
+       p += sprintf(CS p, newformat, ptr);
+       }
+      else
+       p += sprintf(CS p, "(nil)");
+      }
     break;
 
     /* %f format is inherently insecure if the numbers that it may be
@@ -1395,10 +1396,9 @@ while (*fp != 0)
     strncpy(newformat, item_start, fp - item_start);
     newformat[fp-item_start] = 0;
     if (length == L_LONGDOUBLE)
-      sprintf(CS p, newformat, va_arg(ap, long double));
+      p += sprintf(CS p, newformat, va_arg(ap, long double));
     else
-      sprintf(CS p, newformat, va_arg(ap, double));
-    while (*p) p++;
+      p += sprintf(CS p, newformat, va_arg(ap, double));
     break;
 
     /* String types */