• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1995 Patrick Powell.
3  *
4  * This code is based on code written by Patrick Powell <papowell@astart.com>.
5  * It may be used for any purpose as long as this notice remains intact on all
6  * source code distributions.
7  */
8 
9 /*
10  * Copyright (c) 2008 Holger Weiss.
11  *
12  * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>.
13  * My changes to the code may freely be used, modified and/or redistributed for
14  * any purpose.  It would be nice if additions and fixes to this file (including
15  * trivial code cleanups) would be sent back in order to let me include them in
16  * the version available at <http://www.jhweiss.de/software/snprintf.html>.
17  * However, this is not a requirement for using or redistributing (possibly
18  * modified) versions of this file, nor is leaving this notice intact mandatory.
19  */
20 
21 #include <stdarg.h>
22 #include <limits.h>	/* For *_MAX. */
23 #include <inttypes.h>	/* For intmax_t (if not defined in <stdint.h>). */
24 #include <stddef.h>	/* For ptrdiff_t. */
25 #include <stdint.h>	/* For intmax_t. */
26 #include <math.h>	/* For pow(3), NAN, and INFINITY. */
27 #include <string.h>	/* For strcmp(3). */
28 #include <os/mem.h>
29 #include "bk_uart.h"
30 #include <components/system.h>
31 
32 #define VA_START(ap, last) va_start(ap, last)
33 #define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
34 
35 /* Support for unsigned long long int.  We may also need ULLONG_MAX. */
36 #ifndef ULONG_MAX	/* We may need ULONG_MAX as a fallback. */
37 #ifdef UINT_MAX
38 #define ULONG_MAX UINT_MAX
39 #else
40 #define ULONG_MAX INT_MAX
41 #endif	/* defined(UINT_MAX) */
42 #endif	/* !defined(ULONG_MAX) */
43 #ifdef ULLONG
44 #undef ULLONG
45 #endif	/* defined(ULLONG) */
46 #if HAVE_UNSIGNED_LONG_LONG_INT
47 #define ULLONG unsigned long long int
48 #ifndef ULLONG_MAX
49 #define ULLONG_MAX ULONG_MAX
50 #endif	/* !defined(ULLONG_MAX) */
51 #else
52 #define ULLONG unsigned long int
53 #ifdef ULLONG_MAX
54 #undef ULLONG_MAX
55 #endif	/* defined(ULLONG_MAX) */
56 #define ULLONG_MAX ULONG_MAX
57 #endif	/* HAVE_LONG_LONG_INT */
58 
59 /* Support for uintmax_t.  We also need UINTMAX_MAX. */
60 #ifdef UINTMAX_T
61 #undef UINTMAX_T
62 #endif	/* defined(UINTMAX_T) */
63 #if HAVE_UINTMAX_T || defined(uintmax_t)
64 #define UINTMAX_T uintmax_t
65 #ifndef UINTMAX_MAX
66 #define UINTMAX_MAX ULLONG_MAX
67 #endif	/* !defined(UINTMAX_MAX) */
68 #else
69 #define UINTMAX_T ULLONG
70 #ifdef UINTMAX_MAX
71 #undef UINTMAX_MAX
72 #endif	/* defined(UINTMAX_MAX) */
73 #define UINTMAX_MAX ULLONG_MAX
74 #endif	/* HAVE_UINTMAX_T || defined(uintmax_t) */
75 
76 /* Support for long double. */
77 #ifndef LDOUBLE
78 #if HAVE_LONG_DOUBLE
79 #define LDOUBLE long double
80 #else
81 #define LDOUBLE double
82 #endif	/* HAVE_LONG_DOUBLE */
83 #endif	/* !defined(LDOUBLE) */
84 
85 /* Support for long long int. */
86 #ifndef LLONG
87 #if HAVE_LONG_LONG_INT
88 #define LLONG long long int
89 #else
90 #define LLONG long int
91 #endif	/* HAVE_LONG_LONG_INT */
92 #endif	/* !defined(LLONG) */
93 
94 /* Support for intmax_t. */
95 #ifndef INTMAX_T
96 #if HAVE_INTMAX_T || defined(intmax_t)
97 #define INTMAX_T intmax_t
98 #else
99 #define INTMAX_T LLONG
100 #endif	/* HAVE_INTMAX_T || defined(intmax_t) */
101 #endif	/* !defined(INTMAX_T) */
102 
103 /* Support for uintptr_t. */
104 #ifndef UINTPTR_T
105 #if HAVE_UINTPTR_T || defined(uintptr_t)
106 #define UINTPTR_T uintptr_t
107 #else
108 #define UINTPTR_T unsigned long int
109 #endif	/* HAVE_UINTPTR_T || defined(uintptr_t) */
110 #endif	/* !defined(UINTPTR_T) */
111 
112 /* Support for ptrdiff_t. */
113 #ifndef PTRDIFF_T
114 #if HAVE_PTRDIFF_T || defined(ptrdiff_t)
115 #define PTRDIFF_T ptrdiff_t
116 #else
117 #define PTRDIFF_T long int
118 #endif	/* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
119 #endif	/* !defined(PTRDIFF_T) */
120 
121 /*
122  * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
123  * 7.19.6.1, 7).  However, we'll simply use PTRDIFF_T and convert it to an
124  * unsigned type if necessary.  This should work just fine in practice.
125  */
126 #ifndef UPTRDIFF_T
127 #define UPTRDIFF_T PTRDIFF_T
128 #endif	/* !defined(UPTRDIFF_T) */
129 
130 /*
131  * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
132  * However, we'll simply use size_t and convert it to a signed type if
133  * necessary.  This should work just fine in practice.
134  */
135 #ifndef SSIZE_T
136 #define SSIZE_T size_t
137 #endif	/* !defined(SSIZE_T) */
138 
139 /*
140  * Buffer size to hold the octal string representation of UINT128_MAX without
141  * nul-termination ("3777777777777777777777777777777777777777777").
142  */
143 #ifdef MAX_CONVERT_LENGTH
144 #undef MAX_CONVERT_LENGTH
145 #endif	/* defined(MAX_CONVERT_LENGTH) */
146 #define MAX_CONVERT_LENGTH      43
147 
148 /* Format read states. */
149 #define PRINT_S_DEFAULT         0
150 #define PRINT_S_FLAGS           1
151 #define PRINT_S_WIDTH           2
152 #define PRINT_S_DOT             3
153 #define PRINT_S_PRECISION       4
154 #define PRINT_S_MOD             5
155 #define PRINT_S_CONV            6
156 
157 /* Format flags. */
158 #define PRINT_F_MINUS           (1 << 0)
159 #define PRINT_F_PLUS            (1 << 1)
160 #define PRINT_F_SPACE           (1 << 2)
161 #define PRINT_F_NUM             (1 << 3)
162 #define PRINT_F_ZERO            (1 << 4)
163 #define PRINT_F_QUOTE           (1 << 5)
164 #define PRINT_F_UP              (1 << 6)
165 #define PRINT_F_UNSIGNED        (1 << 7)
166 #define PRINT_F_TYPE_G          (1 << 8)
167 #define PRINT_F_TYPE_E          (1 << 9)
168 
169 /* Conversion flags. */
170 #define PRINT_C_CHAR            1
171 #define PRINT_C_SHORT           2
172 #define PRINT_C_LONG            3
173 #define PRINT_C_LLONG           4
174 #define PRINT_C_LDOUBLE         5
175 #define PRINT_C_SIZE            6
176 #define PRINT_C_PTRDIFF         7
177 #define PRINT_C_INTMAX          8
178 
179 #ifndef MAX
180 #define MAX(x, y) ((x >= y) ? x : y)
181 #endif	/* !defined(MAX) */
182 #ifndef CHARTOINT
183 #define CHARTOINT(ch) (ch - '0')
184 #endif	/* !defined(CHARTOINT) */
185 #ifndef ISDIGIT
186 #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
187 #endif	/* !defined(ISDIGIT) */
188 #ifndef ISNAN
189 #define ISNAN(x) (x != x)
190 #endif	/* !defined(ISNAN) */
191 #ifndef ISINF
192 #define ISINF(x) (x != 0.0 && x + x == x)
193 #endif	/* !defined(ISINF) */
194 
195 #ifdef OUTCHAR
196 #undef OUTCHAR
197 #endif	/* defined(OUTCHAR) */
198 #define OUTCHAR(str, len, size, ch)                                          \
199 	do {                                                                         \
200 		if (len + 1 < size)                                                  \
201 			str[len] = ch;                                               \
202 		(len)++;                                                             \
203 	} while (/* CONSTCOND */ 0)
204 
205 static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
206 static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
207 static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
208 static void printsep(char *, size_t *, size_t);
209 static int getnumsep(int);
210 static int getexponent(LDOUBLE);
211 static int convert(UINTMAX_T, char *, size_t, int, int);
212 static UINTMAX_T cast(LDOUBLE);
213 static UINTMAX_T myround(LDOUBLE);
214 static LDOUBLE mypow10(int);
215 static void fmtmac(char *buf, size_t *len, size_t size, const unsigned char *mac, int caps);
216 static void fmtip(char *buf, size_t *len, size_t size, unsigned int value);
217 
__wrap_vsnprintf(char * str,size_t size,const char * format,va_list args)218 int __wrap_vsnprintf(char *str, size_t size, const char *format, va_list args)
219 {
220 	LDOUBLE fvalue;
221 	INTMAX_T value;
222 	unsigned char cvalue;
223 	const char *strvalue;
224 	INTMAX_T *intmaxptr;
225 	PTRDIFF_T *ptrdiffptr;
226 	SSIZE_T *sizeptr;
227 	LLONG *llongptr;
228 	long int *longptr;
229 	int *intptr;
230 	short int *shortptr;
231 	signed char *charptr;
232 	size_t len = 0;
233 	int overflow = 0;
234 	int base = 0;
235 	int cflags = 0;
236 	int flags = 0;
237 	int width = 0;
238 	int precision = -1;
239 	int state = PRINT_S_DEFAULT;
240 	char ch = *format++;
241 
242 	/*
243 	 * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
244 	 * pointer." (7.19.6.5, 2)  We're forgiving and allow a NULL pointer
245 	 * even if a size larger than zero was specified.  At least NetBSD's
246 	 * snprintf(3) does the same, as well as other versions of this file.
247 	 * (Though some of these versions will write to a non-NULL buffer even
248 	 * if a size of zero was specified, which violates the standard.)
249 	 */
250 	if (str == NULL && size != 0)
251 		size = 0;
252 
253 	while (ch != '\0') {
254 		switch (state) {
255 		case PRINT_S_DEFAULT:
256 			if (ch == '%')
257 				state = PRINT_S_FLAGS;
258 			else
259 				OUTCHAR(str, len, size, ch);
260 			ch = *format++;
261 			break;
262 		case PRINT_S_FLAGS:
263 			switch (ch) {
264 			case '-':
265 				flags |= PRINT_F_MINUS;
266 				ch = *format++;
267 				break;
268 			case '+':
269 				flags |= PRINT_F_PLUS;
270 				ch = *format++;
271 				break;
272 			case ' ':
273 				flags |= PRINT_F_SPACE;
274 				ch = *format++;
275 				break;
276 			case '#':
277 				flags |= PRINT_F_NUM;
278 				ch = *format++;
279 				break;
280 			case '0':
281 				flags |= PRINT_F_ZERO;
282 				ch = *format++;
283 				break;
284 			case '\'':	/* SUSv2 flag (not in C99). */
285 				flags |= PRINT_F_QUOTE;
286 				ch = *format++;
287 				break;
288 			default:
289 				state = PRINT_S_WIDTH;
290 				break;
291 			}
292 			break;
293 		case PRINT_S_WIDTH:
294 			if (ISDIGIT(ch)) {
295 				ch = CHARTOINT(ch);
296 				if (width > (INT_MAX - ch) / 10) {
297 					overflow = 1;
298 					goto out;
299 				}
300 				width = 10 * width + ch;
301 				ch = *format++;
302 			} else if (ch == '*') {
303 				/*
304 				 * C99 says: "A negative field width argument is
305 				 * taken as a `-' flag followed by a positive
306 				 * field width." (7.19.6.1, 5)
307 				 */
308 				if ((width = va_arg(args, int)) < 0) {
309 					flags |= PRINT_F_MINUS;
310 					width = -width;
311 				}
312 				ch = *format++;
313 				state = PRINT_S_DOT;
314 			} else
315 				state = PRINT_S_DOT;
316 			break;
317 		case PRINT_S_DOT:
318 			if (ch == '.') {
319 				state = PRINT_S_PRECISION;
320 				ch = *format++;
321 			} else
322 				state = PRINT_S_MOD;
323 			break;
324 		case PRINT_S_PRECISION:
325 			if (precision == -1)
326 				precision = 0;
327 			if (ISDIGIT(ch)) {
328 				ch = CHARTOINT(ch);
329 				if (precision > (INT_MAX - ch) / 10) {
330 					overflow = 1;
331 					goto out;
332 				}
333 				precision = 10 * precision + ch;
334 				ch = *format++;
335 			} else if (ch == '*') {
336 				/*
337 				 * C99 says: "A negative precision argument is
338 				 * taken as if the precision were omitted."
339 				 * (7.19.6.1, 5)
340 				 */
341 				if ((precision = va_arg(args, int)) < 0)
342 					precision = -1;
343 				ch = *format++;
344 				state = PRINT_S_MOD;
345 			} else
346 				state = PRINT_S_MOD;
347 			break;
348 		case PRINT_S_MOD:
349 			switch (ch) {
350 			case 'h':
351 				ch = *format++;
352 				if (ch == 'h') {	/* It's a char. */
353 					ch = *format++;
354 					cflags = PRINT_C_CHAR;
355 				} else
356 					cflags = PRINT_C_SHORT;
357 				break;
358 			case 'l':
359 				ch = *format++;
360 				if (ch == 'l') {	/* It's a long long. */
361 					ch = *format++;
362 					cflags = PRINT_C_LLONG;
363 				} else
364 					cflags = PRINT_C_LONG;
365 				break;
366 			case 'L':
367 				cflags = PRINT_C_LDOUBLE;
368 				ch = *format++;
369 				break;
370 			case 'j':
371 				cflags = PRINT_C_INTMAX;
372 				ch = *format++;
373 				break;
374 			case 't':
375 				cflags = PRINT_C_PTRDIFF;
376 				ch = *format++;
377 				break;
378 			case 'z':
379 				cflags = PRINT_C_SIZE;
380 				ch = *format++;
381 				break;
382 			}
383 			state = PRINT_S_CONV;
384 			break;
385 		case PRINT_S_CONV:
386 			switch (ch) {
387 			case 'd':
388 			/* FALLTHROUGH */
389 			case 'i':
390 				switch (cflags) {
391 				case PRINT_C_CHAR:
392 					value = (signed char)va_arg(args, int);
393 					break;
394 				case PRINT_C_SHORT:
395 					value = (short int)va_arg(args, int);
396 					break;
397 				case PRINT_C_LONG:
398 					value = va_arg(args, long int);
399 					break;
400 				case PRINT_C_LLONG:
401 					value = va_arg(args, LLONG);
402 					break;
403 				case PRINT_C_SIZE:
404 					value = va_arg(args, SSIZE_T);
405 					break;
406 				case PRINT_C_INTMAX:
407 					value = va_arg(args, INTMAX_T);
408 					break;
409 				case PRINT_C_PTRDIFF:
410 					value = va_arg(args, PTRDIFF_T);
411 					break;
412 				default:
413 					value = va_arg(args, int);
414 					break;
415 				}
416 				fmtint(str, &len, size, value, 10, width,
417 					   precision, flags);
418 				break;
419 			case 'X':
420 				flags |= PRINT_F_UP;
421 			/* FALLTHROUGH */
422 			case 'x':
423 				base = 16;
424 			/* FALLTHROUGH */
425 			case 'o':
426 				if (base == 0)
427 					base = 8;
428 			/* FALLTHROUGH */
429 			case 'u':
430 				if (base == 0)
431 					base = 10;
432 				flags |= PRINT_F_UNSIGNED;
433 				switch (cflags) {
434 				case PRINT_C_CHAR:
435 					value = (unsigned char)va_arg(args,
436 												  unsigned int);
437 					break;
438 				case PRINT_C_SHORT:
439 					value = (unsigned short int)va_arg(args,
440 													   unsigned int);
441 					break;
442 				case PRINT_C_LONG:
443 					value = va_arg(args, unsigned long int);
444 					break;
445 				case PRINT_C_LLONG:
446 					value = va_arg(args, ULLONG);
447 					break;
448 				case PRINT_C_SIZE:
449 					value = va_arg(args, size_t);
450 					break;
451 				case PRINT_C_INTMAX:
452 					value = va_arg(args, UINTMAX_T);
453 					break;
454 				case PRINT_C_PTRDIFF:
455 					value = va_arg(args, UPTRDIFF_T);
456 					break;
457 				default:
458 					value = va_arg(args, unsigned int);
459 					break;
460 				}
461 				fmtint(str, &len, size, (UINTMAX_T)value, base, width,
462 					   precision, flags);
463 				break;
464 			case 'A':
465 			/* Not yet supported, we'll use "%F". */
466 			/* FALLTHROUGH */
467 			case 'F':
468 				flags |= PRINT_F_UP;
469 			case 'a':
470 			/* Not yet supported, we'll use "%f". */
471 			/* FALLTHROUGH */
472 			case 'f':
473 				if (cflags == PRINT_C_LDOUBLE)
474 					fvalue = va_arg(args, LDOUBLE);
475 				else
476 					fvalue = va_arg(args, double);
477 				fmtflt(str, &len, size, fvalue, width,
478 					   precision, flags, &overflow);
479 				if (overflow)
480 					goto out;
481 				break;
482 			case 'E':
483 				flags |= PRINT_F_UP;
484 			/* FALLTHROUGH */
485 			case 'e':
486 				flags |= PRINT_F_TYPE_E;
487 				if (cflags == PRINT_C_LDOUBLE)
488 					fvalue = va_arg(args, LDOUBLE);
489 				else
490 					fvalue = va_arg(args, double);
491 				fmtflt(str, &len, size, fvalue, width,
492 					   precision, flags, &overflow);
493 				if (overflow)
494 					goto out;
495 				break;
496 			case 'G':
497 				flags |= PRINT_F_UP;
498 			/* FALLTHROUGH */
499 			case 'g':
500 				flags |= PRINT_F_TYPE_G;
501 				if (cflags == PRINT_C_LDOUBLE)
502 					fvalue = va_arg(args, LDOUBLE);
503 				else
504 					fvalue = va_arg(args, double);
505 				/*
506 				 * If the precision is zero, it is treated as
507 				 * one (cf. C99: 7.19.6.1, 8).
508 				 */
509 				if (precision == 0)
510 					precision = 1;
511 				fmtflt(str, &len, size, fvalue, width,
512 					   precision, flags, &overflow);
513 				if (overflow)
514 					goto out;
515 				break;
516 			case 'c':
517 				cvalue = va_arg(args, int);
518 				OUTCHAR(str, len, size, cvalue);
519 				break;
520 			case 's':
521 				strvalue = va_arg(args, char *);
522 				fmtstr(str, &len, size, strvalue, width,
523 					   precision, flags);
524 				break;
525 			case 'p':
526 				/*
527 				 * C99 says: "The value of the pointer is
528 				 * converted to a sequence of printing
529 				 * characters, in an implementation-defined
530 				 * manner." (C99: 7.19.6.1, 8)
531 				 */
532 				if (*format == 'm' || *format == 'M') {
533 					unsigned char *macstr;
534 					if (*format == 'M')
535 						flags |= PRINT_F_UP;
536 					format++;
537 					if ((macstr = va_arg(args, unsigned char *)) == NULL)
538 						macstr = (unsigned char *)"\x00\x00\x00\x00\x00\x00";
539 					fmtmac(str, &len, size, macstr, flags & PRINT_F_UP);
540 
541 					break;
542 				} else if (*format == 'i' || *format == 'I') {
543 					format++;
544 					value = va_arg(args, unsigned int);
545 					fmtip(str, &len, size, (unsigned int)value);
546 					break;
547 				} else {
548 					if ((strvalue = va_arg(args, void *)) == NULL) {
549 						/*
550 						 * We use the glibc format.  BSD prints
551 						 * "0x0", SysV "0".
552 						 */
553 						fmtstr(str, &len, size, "(nil)", width,
554 							   -1, flags);
555 					} else {
556 						/*
557 						 * We use the BSD/glibc format.  SysV
558 						 * omits the "0x" prefix (which we emit
559 						 * using the PRINT_F_NUM flag).
560 						 */
561 						flags |= PRINT_F_NUM;
562 						flags |= PRINT_F_UNSIGNED;
563 						fmtint(str, &len, size,
564 							   (UINTPTR_T)strvalue, 16, width,
565 							   precision, flags);
566 					}
567 				}
568 				break;
569 			case 'n':
570 				switch (cflags) {
571 				case PRINT_C_CHAR:
572 					charptr = va_arg(args, signed char *);
573 					*charptr = len;
574 					break;
575 				case PRINT_C_SHORT:
576 					shortptr = va_arg(args, short int *);
577 					*shortptr = len;
578 					break;
579 				case PRINT_C_LONG:
580 					longptr = va_arg(args, long int *);
581 					*longptr = len;
582 					break;
583 				case PRINT_C_LLONG:
584 					llongptr = va_arg(args, LLONG *);
585 					*llongptr = len;
586 					break;
587 				case PRINT_C_SIZE:
588 					/*
589 					 * C99 says that with the "z" length
590 					 * modifier, "a following `n' conversion
591 					 * specifier applies to a pointer to a
592 					 * signed integer type corresponding to
593 					 * size_t argument." (7.19.6.1, 7)
594 					 */
595 					sizeptr = va_arg(args, SSIZE_T *);
596 					*sizeptr = len;
597 					break;
598 				case PRINT_C_INTMAX:
599 					intmaxptr = va_arg(args, INTMAX_T *);
600 					*intmaxptr = len;
601 					break;
602 				case PRINT_C_PTRDIFF:
603 					ptrdiffptr = va_arg(args, PTRDIFF_T *);
604 					*ptrdiffptr = len;
605 					break;
606 				default:
607 					intptr = va_arg(args, int *);
608 					*intptr = len;
609 					break;
610 				}
611 				break;
612 			case '%':	/* Print a "%" character verbatim. */
613 				OUTCHAR(str, len, size, ch);
614 				break;
615 			default:	/* Skip other characters. */
616 				break;
617 			}
618 			ch = *format++;
619 			state = PRINT_S_DEFAULT;
620 			base = cflags = flags = width = 0;
621 			precision = -1;
622 			break;
623 		}
624 	}
625 out:
626 	if (len < size)
627 		str[len] = '\0';
628 	else if (size > 0)
629 		str[size - 1] = '\0';
630 
631 	if (overflow || len >= INT_MAX) {
632 		//errno = overflow ? EOVERFLOW : ERANGE;
633 		return -1;
634 	}
635 	return (int)len;
636 }
637 
fmtstr(char * str,size_t * len,size_t size,const char * value,int width,int precision,int flags)638 static void fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
639 				   int precision, int flags)
640 {
641 	int padlen, strln;	/* Amount to pad. */
642 	int noprecision = (precision == -1);
643 
644 	if (value == NULL)	/* We're forgiving. */
645 		value = "(null)";
646 
647 	/* If a precision was specified, don't read the string past it. */
648 	for (strln = 0; value[strln] != '\0' &&
649 		 (noprecision || strln < precision); strln++)
650 		continue;
651 
652 	if ((padlen = width - strln) < 0)
653 		padlen = 0;
654 	if (flags & PRINT_F_MINUS)	/* Left justify. */
655 		padlen = -padlen;
656 
657 	while (padlen > 0) {	/* Leading spaces. */
658 		OUTCHAR(str, *len, size, ' ');
659 		padlen--;
660 	}
661 	while (*value != '\0' && (noprecision || precision-- > 0)) {
662 		OUTCHAR(str, *len, size, *value);
663 		value++;
664 	}
665 	while (padlen < 0) {	/* Trailing spaces. */
666 		OUTCHAR(str, *len, size, ' ');
667 		padlen++;
668 	}
669 }
670 
fmtint(char * str,size_t * len,size_t size,INTMAX_T value,int base,int width,int precision,int flags)671 static void fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
672 				   int precision, int flags)
673 {
674 	UINTMAX_T uvalue;
675 	char iconvert[MAX_CONVERT_LENGTH];
676 	char sign = 0;
677 	char hexprefix = 0;
678 	int spadlen = 0;	/* Amount to space pad. */
679 	int zpadlen = 0;	/* Amount to zero pad. */
680 	int pos;
681 	int separators = (flags & PRINT_F_QUOTE);
682 	int noprecision = (precision == -1);
683 
684 	if (flags & PRINT_F_UNSIGNED)
685 		uvalue = value;
686 	else {
687 		uvalue = (value >= 0) ? value : -value;
688 		if (value < 0)
689 			sign = '-';
690 		else if (flags & PRINT_F_PLUS)	/* Do a sign. */
691 			sign = '+';
692 		else if (flags & PRINT_F_SPACE)
693 			sign = ' ';
694 	}
695 
696 	pos = convert(uvalue, iconvert, sizeof(iconvert), base,
697 				  flags & PRINT_F_UP);
698 
699 	if (flags & PRINT_F_NUM && uvalue != 0) {
700 		/*
701 		 * C99 says: "The result is converted to an `alternative form'.
702 		 * For `o' conversion, it increases the precision, if and only
703 		 * if necessary, to force the first digit of the result to be a
704 		 * zero (if the value and precision are both 0, a single 0 is
705 		 * printed).  For `x' (or `X') conversion, a nonzero result has
706 		 * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
707 		 */
708 		switch (base) {
709 		case 8:
710 			if (precision <= pos)
711 				precision = pos + 1;
712 			break;
713 		case 16:
714 			hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
715 			break;
716 		}
717 	}
718 
719 	if (separators)	/* Get the number of group separators we'll print. */
720 		separators = getnumsep(pos);
721 
722 	zpadlen = precision - pos - separators;
723 	spadlen = width                         /* Minimum field width. */
724 			  - separators                        /* Number of separators. */
725 			  - MAX(precision, pos)               /* Number of integer digits. */
726 			  - ((sign != 0) ? 1 : 0)             /* Will we print a sign? */
727 			  - ((hexprefix != 0) ? 2 : 0);       /* Will we print a prefix? */
728 
729 	if (zpadlen < 0)
730 		zpadlen = 0;
731 	if (spadlen < 0)
732 		spadlen = 0;
733 
734 	/*
735 	 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
736 	 * ignored.  For `d', `i', `o', `u', `x', and `X' conversions, if a
737 	 * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
738 	 */
739 	if (flags & PRINT_F_MINUS)	/* Left justify. */
740 		spadlen = -spadlen;
741 	else if (flags & PRINT_F_ZERO && noprecision) {
742 		zpadlen += spadlen;
743 		spadlen = 0;
744 	}
745 	while (spadlen > 0) {	/* Leading spaces. */
746 		OUTCHAR(str, *len, size, ' ');
747 		spadlen--;
748 	}
749 	if (sign != 0)	/* Sign. */
750 		OUTCHAR(str, *len, size, sign);
751 	if (hexprefix != 0) {	/* A "0x" or "0X" prefix. */
752 		OUTCHAR(str, *len, size, '0');
753 		OUTCHAR(str, *len, size, hexprefix);
754 	}
755 	while (zpadlen > 0) {	/* Leading zeros. */
756 		OUTCHAR(str, *len, size, '0');
757 		zpadlen--;
758 	}
759 	while (pos > 0) {	/* The actual digits. */
760 		pos--;
761 		OUTCHAR(str, *len, size, iconvert[pos]);
762 		if (separators > 0 && pos > 0 && pos % 3 == 0)
763 			printsep(str, len, size);
764 	}
765 	while (spadlen < 0) {	/* Trailing spaces. */
766 		OUTCHAR(str, *len, size, ' ');
767 		spadlen++;
768 	}
769 }
770 
fmtflt(char * str,size_t * len,size_t size,LDOUBLE fvalue,int width,int precision,int flags,int * overflow)771 static void fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
772 				   int precision, int flags, int *overflow)
773 {
774 	LDOUBLE ufvalue;
775 	UINTMAX_T intpart;
776 	UINTMAX_T fracpart;
777 	UINTMAX_T mask;
778 	const char *infnan = NULL;
779 	char iconvert[MAX_CONVERT_LENGTH];
780 	char fconvert[MAX_CONVERT_LENGTH];
781 	char econvert[4];	/* "e-12" (without nul-termination). */
782 	char esign = 0;
783 	char sign = 0;
784 	int leadfraczeros = 0;
785 	int exponent = 0;
786 	int emitpoint = 0;
787 	int omitzeros = 0;
788 	int omitcount = 0;
789 	int padlen = 0;
790 	int epos = 0;
791 	int fpos = 0;
792 	int ipos = 0;
793 	int separators = (flags & PRINT_F_QUOTE);
794 	int estyle = (flags & PRINT_F_TYPE_E);
795 
796 	/*
797 	 * AIX' man page says the default is 0, but C99 and at least Solaris'
798 	 * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
799 	 * defaults to 6.
800 	 */
801 	if (precision == -1)
802 		precision = 6;
803 
804 	if (fvalue < 0.0)
805 		sign = '-';
806 	else if (flags & PRINT_F_PLUS)	/* Do a sign. */
807 		sign = '+';
808 	else if (flags & PRINT_F_SPACE)
809 		sign = ' ';
810 
811 	if (ISNAN(fvalue))
812 		infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
813 	else if (ISINF(fvalue))
814 		infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
815 
816 	if (infnan != NULL) {
817 		if (sign != 0)
818 			iconvert[ipos++] = sign;
819 		while (*infnan != '\0')
820 			iconvert[ipos++] = *infnan++;
821 		fmtstr(str, len, size, iconvert, width, ipos, flags);
822 		return;
823 	}
824 
825 	/* "%e" (or "%E") or "%g" (or "%G") conversion. */
826 	if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
827 		if (flags & PRINT_F_TYPE_G) {
828 			/*
829 			 * For "%g" (and "%G") conversions, the precision
830 			 * specifies the number of significant digits, which
831 			 * includes the digits in the integer part.  The
832 			 * conversion will or will not be using "e-style" (like
833 			 * "%e" or "%E" conversions) depending on the precision
834 			 * and on the exponent.  However, the exponent can be
835 			 * affected by rounding the converted value, so we'll
836 			 * leave this decision for later.  Until then, we'll
837 			 * assume that we're going to do an "e-style" conversion
838 			 * (in order to get the exponent calculated).  For
839 			 * "e-style", the precision must be decremented by one.
840 			 */
841 			precision--;
842 			/*
843 			 * For "%g" (and "%G") conversions, trailing zeros are
844 			 * removed from the fractional portion of the result
845 			 * unless the "#" flag was specified.
846 			 */
847 			if (!(flags & PRINT_F_NUM))
848 				omitzeros = 1;
849 		}
850 		exponent = getexponent(fvalue);
851 		estyle = 1;
852 	}
853 
854 again:
855 	/*
856 	 * Sorry, we only support 9, 19, or 38 digits (that is, the number of
857 	 * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
858 	 * minus one) past the decimal point due to our conversion method.
859 	 */
860 	switch (sizeof(UINTMAX_T)) {
861 	case 16:
862 		if (precision > 38)
863 			precision = 38;
864 		break;
865 	case 8:
866 		if (precision > 19)
867 			precision = 19;
868 		break;
869 	default:
870 		if (precision > 9)
871 			precision = 9;
872 		break;
873 	}
874 
875 	ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
876 	if (estyle)	/* We want exactly one integer digit. */
877 		ufvalue /= mypow10(exponent);
878 
879 	if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
880 		*overflow = 1;
881 		return;
882 	}
883 
884 	/*
885 	 * Factor of ten with the number of digits needed for the fractional
886 	 * part.  For example, if the precision is 3, the mask will be 1000.
887 	 */
888 	mask = mypow10(precision);
889 	/*
890 	 * We "cheat" by converting the fractional part to integer by
891 	 * multiplying by a factor of ten.
892 	 */
893 	if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
894 		/*
895 		 * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
896 		 * (because precision = 3).  Now, myround(1000 * 0.99962) will
897 		 * return 1000.  So, the integer part must be incremented by one
898 		 * and the fractional part must be set to zero.
899 		 */
900 		intpart++;
901 		fracpart = 0;
902 		if (estyle && intpart == 10) {
903 			/*
904 			 * The value was rounded up to ten, but we only want one
905 			 * integer digit if using "e-style".  So, the integer
906 			 * part must be set to one and the exponent must be
907 			 * incremented by one.
908 			 */
909 			intpart = 1;
910 			exponent++;
911 		}
912 	}
913 
914 	/*
915 	 * Now that we know the real exponent, we can check whether or not to
916 	 * use "e-style" for "%g" (and "%G") conversions.  If we don't need
917 	 * "e-style", the precision must be adjusted and the integer and
918 	 * fractional parts must be recalculated from the original value.
919 	 *
920 	 * C99 says: "Let P equal the precision if nonzero, 6 if the precision
921 	 * is omitted, or 1 if the precision is zero.  Then, if a conversion
922 	 * with style `E' would have an exponent of X:
923 	 *
924 	 * - if P > X >= -4, the conversion is with style `f' (or `F') and
925 	 *   precision P - (X + 1).
926 	 *
927 	 * - otherwise, the conversion is with style `e' (or `E') and precision
928 	 *   P - 1." (7.19.6.1, 8)
929 	 *
930 	 * Note that we had decremented the precision by one.
931 	 */
932 	if (flags & PRINT_F_TYPE_G && estyle &&
933 		precision + 1 > exponent && exponent >= -4) {
934 		precision -= exponent;
935 		estyle = 0;
936 		goto again;
937 	}
938 
939 	if (estyle) {
940 		if (exponent < 0) {
941 			exponent = -exponent;
942 			esign = '-';
943 		} else
944 			esign = '+';
945 
946 		/*
947 		 * Convert the exponent.  The sizeof(econvert) is 4.  So, the
948 		 * econvert buffer can hold e.g. "e+99" and "e-99".  We don't
949 		 * support an exponent which contains more than two digits.
950 		 * Therefore, the following stores are safe.
951 		 */
952 		epos = convert(exponent, econvert, 2, 10, 0);
953 		/*
954 		 * C99 says: "The exponent always contains at least two digits,
955 		 * and only as many more digits as necessary to represent the
956 		 * exponent." (7.19.6.1, 8)
957 		 */
958 		if (epos == 1)
959 			econvert[epos++] = '0';
960 		econvert[epos++] = esign;
961 		econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
962 	}
963 
964 	/* Convert the integer part and the fractional part. */
965 	ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
966 	if (fracpart != 0)	/* convert() would return 1 if fracpart == 0. */
967 		fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
968 
969 	leadfraczeros = precision - fpos;
970 
971 	if (omitzeros) {
972 		if (fpos > 0)	/* Omit trailing fractional part zeros. */
973 			while (omitcount < fpos && fconvert[omitcount] == '0')
974 				omitcount++;
975 		else {	/* The fractional part is zero, omit it completely. */
976 			omitcount = precision;
977 			leadfraczeros = 0;
978 		}
979 		precision -= omitcount;
980 	}
981 
982 	/*
983 	 * Print a decimal point if either the fractional part is non-zero
984 	 * and/or the "#" flag was specified.
985 	 */
986 	if (precision > 0 || flags & PRINT_F_NUM)
987 		emitpoint = 1;
988 	if (separators)	/* Get the number of group separators we'll print. */
989 		separators = getnumsep(ipos);
990 
991 	padlen = width                  /* Minimum field width. */
992 			 - ipos                      /* Number of integer digits. */
993 			 - epos                      /* Number of exponent characters. */
994 			 - precision                 /* Number of fractional digits. */
995 			 - separators                /* Number of group separators. */
996 			 - (emitpoint ? 1 : 0)       /* Will we print a decimal point? */
997 			 - ((sign != 0) ? 1 : 0);    /* Will we print a sign character? */
998 
999 	if (padlen < 0)
1000 		padlen = 0;
1001 
1002 	/*
1003 	 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
1004 	 * ignored." (7.19.6.1, 6)
1005 	 */
1006 	if (flags & PRINT_F_MINUS)	/* Left justifty. */
1007 		padlen = -padlen;
1008 	else if (flags & PRINT_F_ZERO && padlen > 0) {
1009 		if (sign != 0) {	/* Sign. */
1010 			OUTCHAR(str, *len, size, sign);
1011 			sign = 0;
1012 		}
1013 		while (padlen > 0) {	/* Leading zeros. */
1014 			OUTCHAR(str, *len, size, '0');
1015 			padlen--;
1016 		}
1017 	}
1018 	while (padlen > 0) {	/* Leading spaces. */
1019 		OUTCHAR(str, *len, size, ' ');
1020 		padlen--;
1021 	}
1022 	if (sign != 0)	/* Sign. */
1023 		OUTCHAR(str, *len, size, sign);
1024 	while (ipos > 0) {	/* Integer part. */
1025 		ipos--;
1026 		OUTCHAR(str, *len, size, iconvert[ipos]);
1027 		if (separators > 0 && ipos > 0 && ipos % 3 == 0)
1028 			printsep(str, len, size);
1029 	}
1030 	if (emitpoint) 	/* Decimal point. */
1031 		OUTCHAR(str, *len, size, '.');
1032 	while (leadfraczeros > 0) {	/* Leading fractional part zeros. */
1033 		OUTCHAR(str, *len, size, '0');
1034 		leadfraczeros--;
1035 	}
1036 	while (fpos > omitcount) {	/* The remaining fractional part. */
1037 		fpos--;
1038 		OUTCHAR(str, *len, size, fconvert[fpos]);
1039 	}
1040 	while (epos > 0) {	/* Exponent. */
1041 		epos--;
1042 		OUTCHAR(str, *len, size, econvert[epos]);
1043 	}
1044 	while (padlen < 0) {	/* Trailing spaces. */
1045 		OUTCHAR(str, *len, size, ' ');
1046 		padlen++;
1047 	}
1048 }
1049 
printsep(char * str,size_t * len,size_t size)1050 static void printsep(char *str, size_t *len, size_t size)
1051 {
1052 	OUTCHAR(str, *len, size, ',');
1053 }
1054 
getnumsep(int digits)1055 static int getnumsep(int digits)
1056 {
1057 	int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
1058 
1059 	return separators;
1060 }
1061 
getexponent(LDOUBLE value)1062 static int getexponent(LDOUBLE value)
1063 {
1064 	LDOUBLE tmp = (value >= 0.0) ? value : -value;
1065 	int exponent = 0;
1066 
1067 	/*
1068 	 * We check for 99 > exponent > -99 in order to work around possible
1069 	 * endless loops which could happen (at least) in the second loop (at
1070 	 * least) if we're called with an infinite value.  However, we checked
1071 	 * for infinity before calling this function using our ISINF() macro, so
1072 	 * this might be somewhat paranoid.
1073 	 */
1074 	while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
1075 		tmp *= 10;
1076 	while (tmp >= 10.0 && ++exponent < 99)
1077 		tmp /= 10;
1078 
1079 	return exponent;
1080 }
1081 
convert(UINTMAX_T value,char * buf,size_t size,int base,int caps)1082 static int convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
1083 {
1084 	const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
1085 	size_t pos = 0;
1086 
1087 	/* We return an unterminated buffer with the digits in reverse order. */
1088 	do {
1089 		buf[pos++] = digits[value % base];
1090 		value /= base;
1091 	} while (value != 0 && pos < size);
1092 
1093 	return (int)pos;
1094 }
1095 
convert_ip(unsigned int value,char * buf,size_t size)1096 static int convert_ip(unsigned int value, char *buf, size_t size)
1097 {
1098 	const char *digits = "0123456789";
1099 	int i;
1100 	unsigned char c;
1101 	size_t pos = 0;
1102 
1103 	for (i = 0; i < 4; i++) {
1104 		c = (value >> (i * 8)) & 0xff;
1105 
1106 		/* We return an unterminated buffer with the digits in reverse order. */
1107 		do {
1108 			buf[pos++] = digits[c % 10];
1109 			c /= 10;
1110 		} while (c != 0 && pos < size);
1111 
1112 		if (i != 3 && pos < size)
1113 			buf[pos++] = '.';
1114 	}
1115 
1116 	return (int)pos;
1117 }
1118 
1119 /* TODO: IPv6 */
fmtip(char * buf,size_t * len,size_t size,unsigned int value)1120 static void fmtip(char *buf, size_t *len, size_t size, unsigned int value)
1121 {
1122 	int pos;
1123 	char ip_buf[18];
1124 
1125 	pos = convert_ip(value, ip_buf, sizeof(ip_buf));
1126 	if (pos > 0) pos--;
1127 	for (; pos >= 0; pos--)
1128 		OUTCHAR(buf, *len, size, ip_buf[pos]);
1129 }
1130 
fmtmac(char * buf,size_t * len,size_t size,const unsigned char * mac,int caps)1131 static void fmtmac(char *buf, size_t *len, size_t size, const unsigned char *mac, int caps)
1132 {
1133 	const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
1134 	int i;
1135 	unsigned char c;
1136 
1137 	for (i = 0; i < 6; i++) {
1138 		c = mac[i];
1139 		OUTCHAR(buf, *len, size, digits[(c >> 4) & 0xf]);
1140 		OUTCHAR(buf, *len, size, digits[c & 0xf]);
1141 		if (i != 5)
1142 			OUTCHAR(buf, *len, size, ':');
1143 	}
1144 }
1145 
cast(LDOUBLE value)1146 static UINTMAX_T cast(LDOUBLE value)
1147 {
1148 	UINTMAX_T result;
1149 
1150 	/*
1151 	 * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
1152 	 * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
1153 	 * it may be increased to the nearest higher representable value for the
1154 	 * comparison (cf. C99: 6.3.1.4, 2).  It might then equal the LDOUBLE
1155 	 * value although converting the latter to UINTMAX_T would overflow.
1156 	 */
1157 	if (value >= UINTMAX_MAX)
1158 		return UINTMAX_MAX;
1159 
1160 	result = value;
1161 	/*
1162 	 * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
1163 	 * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
1164 	 * the standard).  Sigh.
1165 	 */
1166 	return (result <= value) ? result : result - 1;
1167 }
1168 
myround(LDOUBLE value)1169 static UINTMAX_T myround(LDOUBLE value)
1170 {
1171 	UINTMAX_T intpart = cast(value);
1172 
1173 	return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
1174 }
1175 
mypow10(int exponent)1176 static LDOUBLE mypow10(int exponent)
1177 {
1178 	LDOUBLE result = 1;
1179 
1180 	while (exponent > 0) {
1181 		result *= 10;
1182 		exponent--;
1183 	}
1184 	while (exponent < 0) {
1185 		result /= 10;
1186 		exponent++;
1187 	}
1188 	return result;
1189 }
1190 
__wrap_vasprintf(char ** ret,const char * format,va_list ap)1191 int __wrap_vasprintf(char **ret, const char *format, va_list ap)
1192 {
1193 	size_t size;
1194 	int len;
1195 	va_list aq;
1196 
1197 	va_copy(aq, ap);
1198 	len = __wrap_vsnprintf(NULL, 0, format, aq);
1199 	va_end(aq);
1200 
1201 	if (len < 0 || (*ret = os_malloc(size = len + 1)) == NULL)
1202 		return -1;
1203 
1204 	return __wrap_vsnprintf(*ret, size, format, ap);
1205 }
1206 
__wrap_snprintf(char * str,size_t size,const char * format,...)1207 int __wrap_snprintf(char *str, size_t size, const char *format, ...)
1208 {
1209 	va_list ap;
1210 	int len;
1211 
1212 	va_start(ap, format);
1213 	len = __wrap_vsnprintf(str, size, format, ap);
1214 	va_end(ap);
1215 
1216 	return len;
1217 }
1218 
__wrap_asprintf(char ** ret,const char * format,...)1219 int __wrap_asprintf(char **ret, const char *format, ...)
1220 {
1221 	va_list ap;
1222 	int len;
1223 
1224 	va_start(ap, format);
1225 	len = __wrap_vasprintf(ret, format, ap);
1226 	va_end(ap);
1227 	return len;
1228 }
1229 
__wrap_sprintf(char * str,const char * format,...)1230 int __wrap_sprintf(char *str, const char *format, ...)
1231 {
1232 	va_list ap;
1233 	int len;
1234 
1235 	va_start(ap, format);
1236 	len = __wrap_vsnprintf(str, INT_MAX, format, ap);
1237 	va_end(ap);
1238 
1239 	return len;
1240 }
1241 
1242 
1243 
__wrap_puts(const char * s)1244 int __wrap_puts(const char *s)
1245 {
1246 	uart_write_string(bk_get_printf_port(), s);
1247 
1248 	return 1;	/* non-negative value returned */
1249 }
1250 
1251