-/* $Cambridge: exim/src/src/string.c,v 1.3 2005/05/23 16:58:56 fanf2 Exp $ */
+/* $Cambridge: exim/src/src/string.c,v 1.8 2006/02/07 11:19:00 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2006 */
/* See the file NOTICE for conditions of use and distribution. */
/* Miscellaneous string-handling functions. Some are not required for
as a va_list item.
The formats are the usual printf() ones, with some omissions (never used) and
-two additions for strings: %S forces lower case, %#s or %#S prints nothing for
-a NULL string. Without the # "NULL" is printed (useful in debugging). There is
-also the addition of %D, which inserts the date in the form used for
+two additions for strings: %S forces lower case, and %#s or %#S prints nothing
+for a NULL string. Without the # "NULL" is printed (useful in debugging). There
+is also the addition of %D, which inserts the date in the form used for
datestamped log files.
Arguments:
BOOL
string_vformat(uschar *buffer, int buflen, char *format, va_list ap)
{
+enum { L_NORMAL, L_SHORT, L_LONG, L_LONGLONG, L_LONGDOUBLE };
+
BOOL yield = TRUE;
int width, precision;
char *fp = format; /* Deliberately not unsigned */
while (*fp != 0)
{
+ int length = L_NORMAL;
int *nptr;
int slen;
char *null = "NULL"; /* ) These variables */
}
}
- if (strchr("hlL", *fp) != NULL) fp++;
+ /* Skip over 'h', 'L', 'l', and 'll', remembering the item length */
+
+ if (*fp == 'h')
+ { fp++; length = L_SHORT; }
+ else if (*fp == 'L')
+ { fp++; length = L_LONGDOUBLE; }
+ else if (*fp == 'l')
+ {
+ if (fp[1] == 'l')
+ {
+ fp += 2;
+ length = L_LONGLONG;
+ }
+ else
+ {
+ fp++;
+ length = L_LONG;
+ }
+ }
/* Handle each specific format type. */
case 'u':
case 'x':
case 'X':
- if (p >= last - 12) { yield = FALSE; goto END_FORMAT; }
+ if (p >= last - ((length > L_LONG)? 24 : 12))
+ { yield = FALSE; goto END_FORMAT; }
strncpy(newformat, item_start, fp - item_start);
newformat[fp - item_start] = 0;
- sprintf(CS p, newformat, va_arg(ap, int));
+
+ /* Short int is promoted to int when passing through ..., so we must use
+ int for va_arg(). */
+
+ 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;
+ }
while (*p) p++;
break;
if (p >= last - precision - 8) { yield = FALSE; goto END_FORMAT; }
strncpy(newformat, item_start, fp - item_start);
newformat[fp-item_start] = 0;
- sprintf(CS p, newformat, va_arg(ap, double));
+ if (length == L_LONGDOUBLE)
+ sprintf(CS p, newformat, va_arg(ap, long double));
+ else
+ sprintf(CS p, newformat, va_arg(ap, double));
while (*p) p++;
break;