diff options
Diffstat (limited to 'lib/isc/print.c')
-rw-r--r-- | lib/isc/print.c | 353 |
1 files changed, 215 insertions, 138 deletions
diff --git a/lib/isc/print.c b/lib/isc/print.c index 06719e83a547..21b9096c1076 100644 --- a/lib/isc/print.c +++ b/lib/isc/print.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2010, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: print.c,v 1.37 2010/10/18 23:47:08 tbox Exp $ */ - /*! \file */ #include <config.h> @@ -24,6 +22,7 @@ #include <ctype.h> #include <stdio.h> /* for sprintf() */ #include <string.h> /* for strlen() */ +#include <assert.h> /* for assert() */ #define ISC__PRINT_SOURCE /* Used to get the isc_print_* prototypes. */ @@ -34,14 +33,79 @@ #include <isc/stdlib.h> #include <isc/util.h> +/* + * We use the system's sprintf so we undef it here. + */ +#undef sprintf + +static int +isc__print_printf(void (*emit)(char, void *), void *arg, + const char *format, va_list ap); + +static void +file_emit(char c, void *arg) { + FILE *fp = arg; + int i = c & 0xff; + + putc(i, fp); +} + +#if 0 +static int +isc_print_vfprintf(FILE *fp, const char *format, va_list ap) { + assert(fp != NULL); + assert(format != NULL); + + return (isc__print_printf(file_emit, fp, format, ap)); +} +#endif + +int +isc_print_printf(const char *format, ...) { + va_list ap; + int n; + + assert(format != NULL); + + va_start(ap, format); + n = isc__print_printf(file_emit, stdout, format, ap); + va_end(ap); + return (n); +} + +int +isc_print_fprintf(FILE *fp, const char *format, ...) { + va_list ap; + int n; + + assert(fp != NULL); + assert(format != NULL); + + va_start(ap, format); + n = isc__print_printf(file_emit, fp, format, ap); + va_end(ap); + return (n); +} + +static void +nocheck_emit(char c, void *arg) { + struct { char *str; } *a = arg; + + *(a->str)++ = c; +} + int isc_print_sprintf(char *str, const char *format, ...) { + struct { char *str; } arg; + int n; va_list ap; + arg.str = str; + va_start(ap, format); - vsprintf(str, format, ap); + n = isc__print_printf(nocheck_emit, &arg, format, ap); va_end(ap); - return (strlen(str)); + return (n); } /*! @@ -54,7 +118,7 @@ isc_print_snprintf(char *str, size_t size, const char *format, ...) { int ret; va_start(ap, format); - ret = vsnprintf(str, size, format, ap); + ret = isc_print_vsnprintf(str, size, format, ap); va_end(ap); return (ret); @@ -64,10 +128,40 @@ isc_print_snprintf(char *str, size_t size, const char *format, ...) { * Return length of string that would have been written if not truncated. */ +static void +string_emit(char c, void *arg) { + struct { char *str; size_t size; } *p = arg; + + if (p->size > 0U) { + *(p->str)++ = c; + p->size--; + } +} + int isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { + struct { char *str; size_t size; } arg; + int n; + + assert(str != NULL); + assert(format != NULL); + + arg.str = str; + arg.size = size; + + n = isc__print_printf(string_emit, &arg, format, ap); + if (arg.size > 0U) + *arg.str = '\0'; + return (n); +} + +static int +isc__print_printf(void (*emit)(char, void *), void *arg, + const char *format, va_list ap) +{ int h; int l; + int z; int q; int alt; int zero; @@ -83,7 +177,6 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { char buf[1024]; char c; void *v; - char *save = str; const char *cp; const char *head; int count = 0; @@ -91,22 +184,20 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { int zeropad; int dot; double dbl; + isc_boolean_t precision_set; #ifdef HAVE_LONG_DOUBLE long double ldbl; #endif char fmt[32]; - INSIST(str != NULL); - INSIST(format != NULL); + assert(emit != NULL); + assert(arg != NULL); + assert(format != NULL); while (*format != '\0') { if (*format != '%') { - if (size > 1) { - *str++ = *format; - size--; - } + emit(*format++, arg); count++; - format++; continue; } format++; @@ -114,10 +205,11 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { /* * Reset flags. */ - dot = neg = space = plus = left = zero = alt = h = l = q = 0; + dot = neg = space = plus = left = zero = alt = h = l = q = z = 0; width = precision = 0; head = ""; pad = zeropad = 0; + precision_set = ISC_FALSE; do { if (*format == '#') { @@ -163,10 +255,12 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { dot = 1; if (*format == '*') { precision = va_arg(ap, int); + precision_set = ISC_TRUE; format++; } else if (isdigit((unsigned char)*format)) { char *e; precision = strtoul(format, &e, 10); + precision_set = ISC_TRUE; format = e; } } @@ -175,10 +269,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { case '\0': continue; case '%': - if (size > 1) { - *str++ = *format; - size--; - } + emit(*format, arg); count++; break; case 'q': @@ -197,6 +288,10 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { format++; } goto doint; + case 'z': + z = 1; + format++; + goto doint; case 'n': case 'i': case 'd': @@ -205,25 +300,30 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { case 'x': case 'X': doint: - if (precision != 0) + if (precision != 0U) zero = 0; switch (*format) { case 'n': if (h) { short int *p; p = va_arg(ap, short *); - REQUIRE(p != NULL); - *p = str - save; + assert(p != NULL); + *p = count; } else if (l) { long int *p; p = va_arg(ap, long *); - REQUIRE(p != NULL); - *p = str - save; + assert(p != NULL); + *p = count; + } else if (z) { + size_t *p; + p = va_arg(ap, size_t *); + assert(p != NULL); + *p = count; } else { int *p; p = va_arg(ap, int *); - REQUIRE(p != NULL); - *p = str - save; + assert(p != NULL); + *p = count; } break; case 'i': @@ -232,6 +332,8 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpi = va_arg(ap, isc_int64_t); else if (l) tmpi = va_arg(ap, long int); + else if (z) + tmpi = va_arg(ap, ssize_t); else tmpi = va_arg(ap, int); if (tmpi < 0) { @@ -257,12 +359,14 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpui /= 1000000000; mid = tmpui % 1000000000; hi = tmpui / 1000000000; - if (hi != 0) + if (hi != 0U) { sprintf(buf, "%lu", hi); - else - buf[0] = '\0'; - sprintf(buf + strlen(buf), "%lu", mid); - sprintf(buf + strlen(buf), "%lu", lo); + sprintf(buf + strlen(buf), + "%09lu", mid); + } else + sprintf(buf, "%lu", mid); + sprintf(buf + strlen(buf), "%09lu", + lo); } goto printint; case 'o': @@ -270,6 +374,8 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpui = va_arg(ap, isc_uint64_t); else if (l) tmpui = va_arg(ap, long int); + else if (z) + tmpui = va_arg(ap, size_t); else tmpui = va_arg(ap, int); if (tmpui <= 0xffffffffU) @@ -283,17 +389,17 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpui /= 010000000000; mid = tmpui % 010000000000; hi = tmpui / 010000000000; - if (hi != 0) { + if (hi != 0U) { sprintf(buf, alt ? "%#lo" : "%lo", hi); sprintf(buf + strlen(buf), - "%lo", mid); + "%09lo", mid); } else sprintf(buf, alt ? "%#lo" : "%lo", mid); - sprintf(buf + strlen(buf), "%lo", lo); + sprintf(buf + strlen(buf), "%09lo", lo); } goto printint; case 'u': @@ -301,6 +407,8 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpui = va_arg(ap, isc_uint64_t); else if (l) tmpui = va_arg(ap, unsigned long int); + else if (z) + tmpui = va_arg(ap, size_t); else tmpui = va_arg(ap, unsigned int); if (tmpui <= 0xffffffffU) @@ -314,12 +422,14 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpui /= 1000000000; mid = tmpui % 1000000000; hi = tmpui / 1000000000; - if (hi != 0) + if (hi != 0U) { sprintf(buf, "%lu", hi); - else - buf[0] = '\0'; - sprintf(buf + strlen(buf), "%lu", mid); - sprintf(buf + strlen(buf), "%lu", lo); + sprintf(buf + strlen(buf), + "%09lu", mid); + } else + sprintf(buf, "%lu", mid); + sprintf(buf + strlen(buf), "%09lu", + lo); } goto printint; case 'x': @@ -327,11 +437,13 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpui = va_arg(ap, isc_uint64_t); else if (l) tmpui = va_arg(ap, unsigned long int); + else if (z) + tmpui = va_arg(ap, size_t); else tmpui = va_arg(ap, unsigned int); if (alt) { head = "0x"; - if (precision > 2) + if (precision > 2U) precision -= 2; } if (tmpui <= 0xffffffffU) @@ -341,7 +453,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { unsigned long hi = tmpui>>32; unsigned long lo = tmpui & 0xffffffff; sprintf(buf, "%lx", hi); - sprintf(buf + strlen(buf), "%lx", lo); + sprintf(buf + strlen(buf), "%08lx", lo); } goto printint; case 'X': @@ -349,11 +461,13 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpui = va_arg(ap, isc_uint64_t); else if (l) tmpui = va_arg(ap, unsigned long int); + else if (z) + tmpui = va_arg(ap, size_t); else tmpui = va_arg(ap, unsigned int); if (alt) { head = "0X"; - if (precision > 2) + if (precision > 2U) precision -= 2; } if (tmpui <= 0xffffffffU) @@ -363,17 +477,17 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { unsigned long hi = tmpui>>32; unsigned long lo = tmpui & 0xffffffff; sprintf(buf, "%lX", hi); - sprintf(buf + strlen(buf), "%lX", lo); + sprintf(buf + strlen(buf), "%08lX", lo); } goto printint; printint: - if (precision != 0 || width != 0) { + if (precision_set || width != 0U) { length = strlen(buf); if (length < precision) zeropad = precision - length; else if (length < width && zero) zeropad = width - length; - if (width != 0) { + if (width != 0U) { pad = width - length - zeropad - strlen(head); if (pad < 0) @@ -383,30 +497,23 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { count += strlen(head) + strlen(buf) + pad + zeropad; if (!left) { - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (pad > 0) { + emit(' ', arg); pad--; } } cp = head; - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (zeropad > 0 && size > 1) { - *str++ = '0'; - size--; + while (*cp != '\0') + emit(*cp++, arg); + while (zeropad > 0) { + emit('0', arg); zeropad--; } cp = buf; - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (*cp != '\0') + emit(*cp++, arg); + while (pad > 0) { + emit(' ', arg); pad--; } break; @@ -416,76 +523,63 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { break; case 's': cp = va_arg(ap, char *); - REQUIRE(cp != NULL); - if (precision != 0) { + if (precision_set) { /* * cp need not be NULL terminated. */ const char *tp; unsigned long n; + if (precision != 0U) + assert(cp != NULL); n = precision; tp = cp; - while (n != 0 && *tp != '\0') + while (n != 0U && *tp != '\0') n--, tp++; length = precision - n; } else { + assert(cp != NULL); length = strlen(cp); } - if (width != 0) { + if (width != 0U) { pad = width - length; if (pad < 0) pad = 0; } count += pad + length; if (!left) - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (pad > 0) { + emit(' ', arg); pad--; } - if (precision != 0) - while (precision > 0 && *cp != '\0' && - size > 1) { - *str++ = *cp++; - size--; + if (precision_set) + while (precision > 0U && *cp != '\0') { + emit(*cp++, arg); precision--; } else - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (*cp != '\0') + emit(*cp++, arg); + while (pad > 0) { + emit(' ', arg); pad--; } break; case 'c': c = va_arg(ap, int); - if (width > 0) { + if (width > 0U) { count += width; width--; - if (left && size > 1) { - *str++ = c; - size--; - } - while (width-- > 0 && size > 1) { - *str++ = ' '; - size--; - } - if (!left && size > 1) { - *str++ = c; - size--; - } + if (left) + emit(c, arg); + while (width-- > 0U) + emit(' ', arg); + if (!left) + emit(c, arg); } else { count++; - if (size > 1) { - *str++ = c; - size--; - } + emit(c, arg); } break; case 'p': @@ -494,57 +588,46 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { length = strlen(buf); if (precision > length) zeropad = precision - length; - if (width > 0) { + if (width > 0U) { pad = width - length - zeropad; if (pad < 0) pad = 0; } count += length + pad + zeropad; if (!left) - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (pad > 0) { + emit(' ', arg); pad--; } cp = buf; if (zeropad > 0 && buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) { - if (size > 1) { - *str++ = *cp++; - size--; - } - if (size > 1) { - *str++ = *cp++; - size--; - } - while (zeropad > 0 && size > 1) { - *str++ = '0'; - size--; + emit(*cp++, arg); + emit(*cp++, arg); + while (zeropad > 0) { + emit('0', arg); zeropad--; } } - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (*cp != '\0') + emit(*cp++, arg); + while (pad > 0) { + emit(' ', arg); pad--; } break; case 'D': /*deprecated*/ - INSIST("use %ld instead of %D" == NULL); + assert("use %ld instead of %D" == NULL); case 'O': /*deprecated*/ - INSIST("use %lo instead of %O" == NULL); + assert("use %lo instead of %O" == NULL); case 'U': /*deprecated*/ - INSIST("use %lu instead of %U" == NULL); + assert("use %lu instead of %U" == NULL); case 'L': #ifdef HAVE_LONG_DOUBLE l = 1; #else - INSIST("long doubles are not supported" == NULL); + assert("long doubles are not supported" == NULL); #endif /*FALLTHROUGH*/ case 'e': @@ -564,7 +647,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { * if we cap the precision at 512 we will not * overflow buf. */ - if (precision > 512) + if (precision > 512U) precision = 512; sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "", plus ? "+" : space ? " " : "", @@ -586,26 +669,22 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { sprintf(buf, fmt, dbl); } length = strlen(buf); - if (width > 0) { + if (width > 0U) { pad = width - length; if (pad < 0) pad = 0; } count += length + pad; if (!left) - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (pad > 0) { + emit(' ', arg); pad--; } cp = buf; - while (*cp != ' ' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (*cp != ' ') + emit(*cp++, arg); + while (pad > 0) { + emit(' ', arg); pad--; } break; @@ -618,7 +697,5 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { } format++; } - if (size > 0) - *str = '\0'; return (count); } |