File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / lib / isc / print.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    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.1.1.1 2012/05/29 12:08:38 misho 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>