Annotation of embedaddon/ntp/lib/isc/print.c, revision 1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>