-/* $Cambridge: exim/src/src/string.c,v 1.15 2009/11/16 19:50:37 nm4 Exp $ */
-
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2012 */
/* See the file NOTICE for conditions of use and distribution. */
/* Miscellaneous string-handling functions. Some are not required for
-#ifndef COMPILE_UTILITY
/*************************************************
* Interpret escape sequence *
*************************************************/
int
string_interpret_escape(uschar **pp)
{
+#ifdef COMPILE_UTILITY
+const uschar *hex_digits= CUS"0123456789abcdef";
+#endif
int ch;
uschar *p = *pp;
ch = *(++p);
}
else switch(ch)
{
+ case 'b': ch = '\b'; break;
+ case 'f': ch = '\f'; break;
case 'n': ch = '\n'; break;
case 'r': ch = '\r'; break;
case 't': ch = '\t'; break;
+ case 'v': ch = '\v'; break;
case 'x':
ch = 0;
if (isxdigit(p[1]))
*pp = p;
return ch;
}
-#endif /* COMPILE_UTILITY */
}
#endif /* COMPILE_UTILITY */
+/*************************************************
+* Undo printing escapes in string *
+*************************************************/
+
+/* This function is the reverse of string_printing2. It searches for
+backslash characters and if any are found, it makes a new copy of the
+string with escape sequences parsed. Otherwise it returns the original
+string.
+
+Arguments:
+ s the input string
+
+Returns: string with printing escapes parsed back
+*/
+
+uschar *
+string_unprinting(uschar *s)
+{
+uschar *p, *q, *r, *ss;
+int len, off;
+
+p = Ustrchr(s, '\\');
+if (!p) return s;
+
+len = Ustrlen(s) + 1;
+ss = store_get(len);
+
+q = ss;
+off = p - s;
+if (off)
+ {
+ memcpy(q, s, off);
+ q += off;
+ }
+
+while (*p)
+ {
+ if (*p == '\\')
+ {
+ *q = string_interpret_escape(&p);
+ }
+ else
+ {
+ r = Ustrchr(p, '\\');
+ if (!r)
+ {
+ off = Ustrlen(p);
+ memcpy(q, p, off);
+ p += off;
+ q += off;
+ break;
+ }
+ else
+ {
+ off = r - p;
+ memcpy(q, p, off);
+ q += off;
+ p = r;
+ }
+ }
+ }
+*q = '\0';
+
+return ss;
+}
+
*/
uschar *
-string_copy(uschar *s)
+string_copy(const uschar *s)
{
int len = Ustrlen(s) + 1;
uschar *ss = store_get(len);
va_start(ap, format);
if (!string_vformat(buffer, sizeof(buffer), format, ap))
log_write(0, LOG_MAIN|LOG_PANIC_DIE,
- "string_sprintf expansion was longer than %d", sizeof(buffer));
+ "string_sprintf expansion was longer than " SIZE_T_FMT, sizeof(buffer));
va_end(ap);
return string_copy(buffer);
}
BOOL
string_vformat(uschar *buffer, int buflen, const char *format, va_list ap)
{
-enum { L_NORMAL, L_SHORT, L_LONG, L_LONGLONG, L_LONGDOUBLE };
+/* We assume numbered ascending order, C does not guarantee that */
+enum { L_NORMAL=1, L_SHORT=2, L_LONG=3, L_LONGLONG=4, L_LONGDOUBLE=5, L_SIZE=6 };
BOOL yield = TRUE;
int width, precision;
}
}
- /* Skip over 'h', 'L', 'l', and 'll', remembering the item length */
+ /* Skip over 'h', 'L', 'l', 'll' and 'z', remembering the item length */
if (*fp == 'h')
{ fp++; length = L_SHORT; }
length = L_LONG;
}
}
+ else if (*fp == 'z')
+ { fp++; length = L_SIZE; }
/* Handle each specific format type. */
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;
}
while (*p) p++;
break;