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