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