Return to print.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / lib / isc |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") ! 3: * Copyright (C) 1999-2001, 2003 Internet Software Consortium. ! 4: * ! 5: * Permission to use, copy, modify, and/or distribute this software for any ! 6: * purpose with or without fee is hereby granted, provided that the above ! 7: * copyright notice and this permission notice appear in all copies. ! 8: * ! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH ! 10: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ! 11: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, ! 12: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ! 13: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ! 14: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ! 15: * PERFORMANCE OF THIS SOFTWARE. ! 16: */ ! 17: ! 18: /* $Id: print.c,v 1.35 2008/02/18 23:46:59 tbox Exp $ */ ! 19: ! 20: /*! \file */ ! 21: ! 22: #include <config.h> ! 23: ! 24: #include <ctype.h> ! 25: #include <stdio.h> /* for sprintf() */ ! 26: #include <string.h> /* for strlen() */ ! 27: ! 28: #define ISC__PRINT_SOURCE /* Used to get the isc_print_* prototypes. */ ! 29: ! 30: #include <isc/assertions.h> ! 31: #include <isc/int.h> ! 32: #include <isc/msgs.h> ! 33: #include <isc/print.h> ! 34: #include <isc/stdlib.h> ! 35: #include <isc/util.h> ! 36: ! 37: int ! 38: isc_print_sprintf(char *str, const char *format, ...) { ! 39: va_list ap; ! 40: ! 41: va_start(ap, format); ! 42: vsprintf(str, format, ap); ! 43: va_end(ap); ! 44: return (strlen(str)); ! 45: } ! 46: ! 47: /*! ! 48: * Return length of string that would have been written if not truncated. ! 49: */ ! 50: ! 51: int ! 52: isc_print_snprintf(char *str, size_t size, const char *format, ...) { ! 53: va_list ap; ! 54: int ret; ! 55: ! 56: va_start(ap, format); ! 57: ret = vsnprintf(str, size, format, ap); ! 58: va_end(ap); ! 59: return (ret); ! 60: ! 61: } ! 62: ! 63: /*! ! 64: * Return length of string that would have been written if not truncated. ! 65: */ ! 66: ! 67: int ! 68: isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { ! 69: int h; ! 70: int l; ! 71: int q; ! 72: int alt; ! 73: int zero; ! 74: int left; ! 75: int plus; ! 76: int space; ! 77: int neg; ! 78: isc_int64_t tmpi; ! 79: isc_uint64_t tmpui; ! 80: unsigned long width; ! 81: unsigned long precision; ! 82: unsigned int length; ! 83: char buf[1024]; ! 84: char c; ! 85: void *v; ! 86: char *save = str; ! 87: const char *cp; ! 88: const char *head; ! 89: int count = 0; ! 90: int pad; ! 91: int zeropad; ! 92: int dot; ! 93: double dbl; ! 94: #ifdef HAVE_LONG_DOUBLE ! 95: long double ldbl; ! 96: #endif ! 97: char fmt[32]; ! 98: ! 99: INSIST(str != NULL); ! 100: INSIST(format != NULL); ! 101: ! 102: while (*format != '\0') { ! 103: if (*format != '%') { ! 104: if (size > 1) { ! 105: *str++ = *format; ! 106: size--; ! 107: } ! 108: count++; ! 109: format++; ! 110: continue; ! 111: } ! 112: format++; ! 113: ! 114: /* ! 115: * Reset flags. ! 116: */ ! 117: dot = neg = space = plus = left = zero = alt = h = l = q = 0; ! 118: width = precision = 0; ! 119: head = ""; ! 120: length = pad = zeropad = 0; ! 121: ! 122: do { ! 123: if (*format == '#') { ! 124: alt = 1; ! 125: format++; ! 126: } else if (*format == '-') { ! 127: left = 1; ! 128: zero = 0; ! 129: format++; ! 130: } else if (*format == ' ') { ! 131: if (!plus) ! 132: space = 1; ! 133: format++; ! 134: } else if (*format == '+') { ! 135: plus = 1; ! 136: space = 0; ! 137: format++; ! 138: } else if (*format == '0') { ! 139: if (!left) ! 140: zero = 1; ! 141: format++; ! 142: } else ! 143: break; ! 144: } while (1); ! 145: ! 146: /* ! 147: * Width. ! 148: */ ! 149: if (*format == '*') { ! 150: width = va_arg(ap, int); ! 151: format++; ! 152: } else if (isdigit((unsigned char)*format)) { ! 153: char *e; ! 154: width = strtoul(format, &e, 10); ! 155: format = e; ! 156: } ! 157: ! 158: /* ! 159: * Precision. ! 160: */ ! 161: if (*format == '.') { ! 162: format++; ! 163: dot = 1; ! 164: if (*format == '*') { ! 165: precision = va_arg(ap, int); ! 166: format++; ! 167: } else if (isdigit((unsigned char)*format)) { ! 168: char *e; ! 169: precision = strtoul(format, &e, 10); ! 170: format = e; ! 171: } ! 172: } ! 173: ! 174: switch (*format) { ! 175: case '\0': ! 176: continue; ! 177: case '%': ! 178: if (size > 1) { ! 179: *str++ = *format; ! 180: size--; ! 181: } ! 182: count++; ! 183: break; ! 184: case 'q': ! 185: q = 1; ! 186: format++; ! 187: goto doint; ! 188: case 'h': ! 189: h = 1; ! 190: format++; ! 191: goto doint; ! 192: case 'l': ! 193: l = 1; ! 194: format++; ! 195: if (*format == 'l') { ! 196: q = 1; ! 197: format++; ! 198: } ! 199: goto doint; ! 200: case 'n': ! 201: case 'i': ! 202: case 'd': ! 203: case 'o': ! 204: case 'u': ! 205: case 'x': ! 206: case 'X': ! 207: doint: ! 208: if (precision != 0) ! 209: zero = 0; ! 210: switch (*format) { ! 211: case 'n': ! 212: if (h) { ! 213: short int *p; ! 214: p = va_arg(ap, short *); ! 215: REQUIRE(p != NULL); ! 216: *p = str - save; ! 217: } else if (l) { ! 218: long int *p; ! 219: p = va_arg(ap, long *); ! 220: REQUIRE(p != NULL); ! 221: *p = str - save; ! 222: } else { ! 223: int *p; ! 224: p = va_arg(ap, int *); ! 225: REQUIRE(p != NULL); ! 226: *p = str - save; ! 227: } ! 228: break; ! 229: case 'i': ! 230: case 'd': ! 231: if (q) ! 232: tmpi = va_arg(ap, isc_int64_t); ! 233: else if (l) ! 234: tmpi = va_arg(ap, long int); ! 235: else ! 236: tmpi = va_arg(ap, int); ! 237: if (tmpi < 0) { ! 238: head = "-"; ! 239: tmpui = -tmpi; ! 240: } else { ! 241: if (plus) ! 242: head = "+"; ! 243: else if (space) ! 244: head = " "; ! 245: else ! 246: head = ""; ! 247: tmpui = tmpi; ! 248: } ! 249: if (tmpui <= 0xffffffffU) ! 250: sprintf(buf, "%lu", ! 251: (unsigned long)tmpui); ! 252: else { ! 253: unsigned long mid; ! 254: unsigned long lo; ! 255: unsigned long hi; ! 256: lo = tmpui % 1000000000; ! 257: tmpui /= 1000000000; ! 258: mid = tmpui % 1000000000; ! 259: hi = tmpui / 1000000000; ! 260: if (hi != 0) ! 261: sprintf(buf, "%lu", hi); ! 262: else ! 263: buf[0] = '\n'; ! 264: sprintf(buf + strlen(buf), "%lu", mid); ! 265: sprintf(buf + strlen(buf), "%lu", lo); ! 266: } ! 267: goto printint; ! 268: case 'o': ! 269: if (q) ! 270: tmpui = va_arg(ap, isc_uint64_t); ! 271: else if (l) ! 272: tmpui = va_arg(ap, long int); ! 273: else ! 274: tmpui = va_arg(ap, int); ! 275: if (tmpui <= 0xffffffffU) ! 276: sprintf(buf, alt ? "%#lo" : "%lo", ! 277: (unsigned long)tmpui); ! 278: else { ! 279: unsigned long mid; ! 280: unsigned long lo; ! 281: unsigned long hi; ! 282: lo = tmpui % 010000000000; ! 283: tmpui /= 010000000000; ! 284: mid = tmpui % 010000000000; ! 285: hi = tmpui / 010000000000; ! 286: if (hi != 0) { ! 287: sprintf(buf, ! 288: alt ? "%#lo" : "%lo", ! 289: hi); ! 290: sprintf(buf + strlen(buf), ! 291: "%lo", mid); ! 292: } else ! 293: sprintf(buf, ! 294: alt ? "%#lo" : "%lo", ! 295: mid); ! 296: sprintf(buf + strlen(buf), "%lo", lo); ! 297: } ! 298: goto printint; ! 299: case 'u': ! 300: if (q) ! 301: tmpui = va_arg(ap, isc_uint64_t); ! 302: else if (l) ! 303: tmpui = va_arg(ap, unsigned long int); ! 304: else ! 305: tmpui = va_arg(ap, unsigned int); ! 306: if (tmpui <= 0xffffffffU) ! 307: sprintf(buf, "%lu", ! 308: (unsigned long)tmpui); ! 309: else { ! 310: unsigned long mid; ! 311: unsigned long lo; ! 312: unsigned long hi; ! 313: lo = tmpui % 1000000000; ! 314: tmpui /= 1000000000; ! 315: mid = tmpui % 1000000000; ! 316: hi = tmpui / 1000000000; ! 317: if (hi != 0) ! 318: sprintf(buf, "%lu", hi); ! 319: else ! 320: buf[0] = '\n'; ! 321: sprintf(buf + strlen(buf), "%lu", mid); ! 322: sprintf(buf + strlen(buf), "%lu", lo); ! 323: } ! 324: goto printint; ! 325: case 'x': ! 326: if (q) ! 327: tmpui = va_arg(ap, isc_uint64_t); ! 328: else if (l) ! 329: tmpui = va_arg(ap, unsigned long int); ! 330: else ! 331: tmpui = va_arg(ap, unsigned int); ! 332: if (alt) { ! 333: head = "0x"; ! 334: if (precision > 2) ! 335: precision -= 2; ! 336: } ! 337: if (tmpui <= 0xffffffffU) ! 338: sprintf(buf, "%lx", ! 339: (unsigned long)tmpui); ! 340: else { ! 341: unsigned long hi = tmpui>>32; ! 342: unsigned long lo = tmpui & 0xffffffff; ! 343: sprintf(buf, "%lx", hi); ! 344: sprintf(buf + strlen(buf), "%lx", lo); ! 345: } ! 346: goto printint; ! 347: case 'X': ! 348: if (q) ! 349: tmpui = va_arg(ap, isc_uint64_t); ! 350: else if (l) ! 351: tmpui = va_arg(ap, unsigned long int); ! 352: else ! 353: tmpui = va_arg(ap, unsigned int); ! 354: if (alt) { ! 355: head = "0X"; ! 356: if (precision > 2) ! 357: precision -= 2; ! 358: } ! 359: if (tmpui <= 0xffffffffU) ! 360: sprintf(buf, "%lX", ! 361: (unsigned long)tmpui); ! 362: else { ! 363: unsigned long hi = tmpui>>32; ! 364: unsigned long lo = tmpui & 0xffffffff; ! 365: sprintf(buf, "%lX", hi); ! 366: sprintf(buf + strlen(buf), "%lX", lo); ! 367: } ! 368: goto printint; ! 369: printint: ! 370: if (precision != 0 || width != 0) { ! 371: length = strlen(buf); ! 372: if (length < precision) ! 373: zeropad = precision - length; ! 374: else if (length < width && zero) ! 375: zeropad = width - length; ! 376: if (width != 0) { ! 377: pad = width - length - ! 378: zeropad - strlen(head); ! 379: if (pad < 0) ! 380: pad = 0; ! 381: } ! 382: } ! 383: count += strlen(head) + strlen(buf) + pad + ! 384: zeropad; ! 385: if (!left) { ! 386: while (pad > 0 && size > 1) { ! 387: *str++ = ' '; ! 388: size--; ! 389: pad--; ! 390: } ! 391: } ! 392: cp = head; ! 393: while (*cp != '\0' && size > 1) { ! 394: *str++ = *cp++; ! 395: size--; ! 396: } ! 397: while (zeropad > 0 && size > 1) { ! 398: *str++ = '0'; ! 399: size--; ! 400: zeropad--; ! 401: } ! 402: cp = buf; ! 403: while (*cp != '\0' && size > 1) { ! 404: *str++ = *cp++; ! 405: size--; ! 406: } ! 407: while (pad > 0 && size > 1) { ! 408: *str++ = ' '; ! 409: size--; ! 410: pad--; ! 411: } ! 412: break; ! 413: default: ! 414: break; ! 415: } ! 416: break; ! 417: case 's': ! 418: cp = va_arg(ap, char *); ! 419: REQUIRE(cp != NULL); ! 420: ! 421: if (precision != 0) { ! 422: /* ! 423: * cp need not be NULL terminated. ! 424: */ ! 425: const char *tp; ! 426: unsigned long n; ! 427: ! 428: n = precision; ! 429: tp = cp; ! 430: while (n != 0 && *tp != '\0') ! 431: n--, tp++; ! 432: length = precision - n; ! 433: } else { ! 434: length = strlen(cp); ! 435: } ! 436: if (width != 0) { ! 437: pad = width - length; ! 438: if (pad < 0) ! 439: pad = 0; ! 440: } ! 441: count += pad + length; ! 442: if (!left) ! 443: while (pad > 0 && size > 1) { ! 444: *str++ = ' '; ! 445: size--; ! 446: pad--; ! 447: } ! 448: if (precision != 0) ! 449: while (precision > 0 && *cp != '\0' && ! 450: size > 1) { ! 451: *str++ = *cp++; ! 452: size--; ! 453: precision--; ! 454: } ! 455: else ! 456: while (*cp != '\0' && size > 1) { ! 457: *str++ = *cp++; ! 458: size--; ! 459: } ! 460: while (pad > 0 && size > 1) { ! 461: *str++ = ' '; ! 462: size--; ! 463: pad--; ! 464: } ! 465: break; ! 466: case 'c': ! 467: c = va_arg(ap, int); ! 468: if (width > 0) { ! 469: count += width; ! 470: width--; ! 471: if (left) { ! 472: *str++ = c; ! 473: size--; ! 474: } ! 475: while (width-- > 0 && size > 1) { ! 476: *str++ = ' '; ! 477: size--; ! 478: } ! 479: if (!left && size > 1) { ! 480: *str++ = c; ! 481: size--; ! 482: } ! 483: } else { ! 484: count++; ! 485: if (size > 1) { ! 486: *str++ = c; ! 487: size--; ! 488: } ! 489: } ! 490: break; ! 491: case 'p': ! 492: v = va_arg(ap, void *); ! 493: sprintf(buf, "%p", v); ! 494: length = strlen(buf); ! 495: if (precision > length) ! 496: zeropad = precision - length; ! 497: if (width > 0) { ! 498: pad = width - length - zeropad; ! 499: if (pad < 0) ! 500: pad = 0; ! 501: } ! 502: count += length + pad + zeropad; ! 503: if (!left) ! 504: while (pad > 0 && size > 1) { ! 505: *str++ = ' '; ! 506: size--; ! 507: pad--; ! 508: } ! 509: cp = buf; ! 510: if (zeropad > 0 && buf[0] == '0' && ! 511: (buf[1] == 'x' || buf[1] == 'X')) { ! 512: if (size > 1) { ! 513: *str++ = *cp++; ! 514: size--; ! 515: } ! 516: if (size > 1) { ! 517: *str++ = *cp++; ! 518: size--; ! 519: } ! 520: while (zeropad > 0 && size > 1) { ! 521: *str++ = '0'; ! 522: size--; ! 523: zeropad--; ! 524: } ! 525: } ! 526: while (*cp != '\0' && size > 1) { ! 527: *str++ = *cp++; ! 528: size--; ! 529: } ! 530: while (pad > 0 && size > 1) { ! 531: *str++ = ' '; ! 532: size--; ! 533: pad--; ! 534: } ! 535: break; ! 536: case 'D': /*deprecated*/ ! 537: INSIST("use %ld instead of %D" == NULL); ! 538: case 'O': /*deprecated*/ ! 539: INSIST("use %lo instead of %O" == NULL); ! 540: case 'U': /*deprecated*/ ! 541: INSIST("use %lu instead of %U" == NULL); ! 542: ! 543: case 'L': ! 544: #ifdef HAVE_LONG_DOUBLE ! 545: l = 1; ! 546: #else ! 547: INSIST("long doubles are not supported" == NULL); ! 548: #endif ! 549: /*FALLTHROUGH*/ ! 550: case 'e': ! 551: case 'E': ! 552: case 'f': ! 553: case 'g': ! 554: case 'G': ! 555: if (!dot) ! 556: precision = 6; ! 557: /* ! 558: * IEEE floating point. ! 559: * MIN 2.2250738585072014E-308 ! 560: * MAX 1.7976931348623157E+308 ! 561: * VAX floating point has a smaller range than IEEE. ! 562: * ! 563: * precisions > 324 don't make much sense. ! 564: * if we cap the precision at 512 we will not ! 565: * overflow buf. ! 566: */ ! 567: if (precision > 512) ! 568: precision = 512; ! 569: sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "", ! 570: plus ? "+" : space ? " " : "", ! 571: precision, l ? "L" : "", *format); ! 572: switch (*format) { ! 573: case 'e': ! 574: case 'E': ! 575: case 'f': ! 576: case 'g': ! 577: case 'G': ! 578: #ifdef HAVE_LONG_DOUBLE ! 579: if (l) { ! 580: ldbl = va_arg(ap, long double); ! 581: sprintf(buf, fmt, ldbl); ! 582: } else ! 583: #endif ! 584: { ! 585: dbl = va_arg(ap, double); ! 586: sprintf(buf, fmt, dbl); ! 587: } ! 588: length = strlen(buf); ! 589: if (width > 0) { ! 590: pad = width - length; ! 591: if (pad < 0) ! 592: pad = 0; ! 593: } ! 594: count += length + pad; ! 595: if (!left) ! 596: while (pad > 0 && size > 1) { ! 597: *str++ = ' '; ! 598: size--; ! 599: pad--; ! 600: } ! 601: cp = buf; ! 602: while (*cp != ' ' && size > 1) { ! 603: *str++ = *cp++; ! 604: size--; ! 605: } ! 606: while (pad > 0 && size > 1) { ! 607: *str++ = ' '; ! 608: size--; ! 609: pad--; ! 610: } ! 611: break; ! 612: default: ! 613: continue; ! 614: } ! 615: break; ! 616: default: ! 617: continue; ! 618: } ! 619: format++; ! 620: } ! 621: if (size > 0) ! 622: *str = '\0'; ! 623: return (count); ! 624: }