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