1 /*
2 * Copyright (c) 1997-2010, 2012-2015 Wind River Systems, Inc.
3 * Copyright (c) 2020 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <ctype.h>
9 #include <errno.h>
10 #include <inttypes.h>
11 #include <limits.h>
12 #include <stdarg.h>
13 #include <stdbool.h>
14 #include <stddef.h>
15 #include <stdint.h>
16 #include <string.h>
17 #include <zephyr/toolchain.h>
18 #include <sys/types.h>
19 #include <zephyr/sys/util.h>
20 #include <zephyr/sys/cbprintf.h>
21
22 /* newlib doesn't declare this function unless __POSIX_VISIBLE >= 200809. No
23 * idea how to make that happen, so lets put it right here.
24 */
25 size_t strnlen(const char *s, size_t maxlen);
26
27 /* Provide typedefs used for signed and unsigned integral types
28 * capable of holding all convertible integral values.
29 */
30 #ifdef CONFIG_CBPRINTF_FULL_INTEGRAL
31 typedef intmax_t sint_value_type;
32 typedef uintmax_t uint_value_type;
33 #else
34 typedef int32_t sint_value_type;
35 typedef uint32_t uint_value_type;
36 #endif
37
38 /* The maximum buffer size required is for octal formatting: one character for
39 * every 3 bits. Neither EOS nor alternate forms are required.
40 */
41 #define CONVERTED_INT_BUFLEN ((CHAR_BIT * sizeof(uint_value_type) + 2) / 3)
42
43 /* The float code may extract up to 16 digits, plus a prefix, a
44 * leading 0, a dot, and an exponent in the form e+xxx for a total of
45 * 24. Add a trailing NULL so the buffer length required is 25.
46 */
47 #define CONVERTED_FP_BUFLEN 25U
48
49 #ifdef CONFIG_CBPRINTF_FP_SUPPORT
50 #define CONVERTED_BUFLEN MAX(CONVERTED_INT_BUFLEN, CONVERTED_FP_BUFLEN)
51 #else
52 #define CONVERTED_BUFLEN CONVERTED_INT_BUFLEN
53 #endif
54
55 /* The allowed types of length modifier. */
56 enum length_mod_enum {
57 LENGTH_NONE, /* int */
58 LENGTH_HH, /* char */
59 LENGTH_H, /* short */
60 LENGTH_L, /* long */
61 LENGTH_LL, /* long long */
62 LENGTH_J, /* intmax */
63 LENGTH_Z, /* size_t */
64 LENGTH_T, /* ptrdiff_t */
65 LENGTH_UPPER_L, /* long double */
66 };
67
68 /* Categories of conversion specifiers. */
69 enum specifier_cat_enum {
70 /* unrecognized */
71 SPECIFIER_INVALID,
72 /* d, i */
73 SPECIFIER_SINT,
74 /* c, o, u, x, X */
75 SPECIFIER_UINT,
76 /* n, p, s */
77 SPECIFIER_PTR,
78 /* a, A, e, E, f, F, g, G */
79 SPECIFIER_FP,
80 };
81
82 #define CHAR_IS_SIGNED (CHAR_MIN != 0)
83 #if CHAR_IS_SIGNED
84 #define CASE_SINT_CHAR case 'c':
85 #define CASE_UINT_CHAR
86 #else
87 #define CASE_SINT_CHAR
88 #define CASE_UINT_CHAR case 'c':
89 #endif
90
91 /* We need two pieces of information about wchar_t:
92 * * WCHAR_IS_SIGNED: whether it's signed or unsigned;
93 * * WINT_TYPE: the type to use when extracting it from va_args
94 *
95 * The former can be determined from the value of WCHAR_MIN if it's defined.
96 * It's not for minimal libc, so treat it as whatever char is.
97 *
98 * The latter should be wint_t, but minimal libc doesn't provide it. We can
99 * substitute wchar_t as long as that type does not undergo default integral
100 * promotion as an argument. But it does for at least one toolchain (xtensa),
101 * and where it does we need to use the promoted type in va_arg() to avoid
102 * build errors, otherwise we can use the base type. We can tell that
103 * integral promotion occurs if WCHAR_MAX is strictly less than INT_MAX.
104 */
105 #ifndef WCHAR_MIN
106 #define WCHAR_IS_SIGNED CHAR_IS_SIGNED
107 #if WCHAR_IS_SIGNED
108 #define WINT_TYPE int
109 #else /* wchar signed */
110 #define WINT_TYPE unsigned int
111 #endif /* wchar signed */
112 #else /* WCHAR_MIN defined */
113 #define WCHAR_IS_SIGNED ((WCHAR_MIN - 0) != 0)
114 #if WCHAR_MAX < INT_MAX
115 /* Signed or unsigned, it'll be int */
116 #define WINT_TYPE int
117 #else /* wchar rank vs int */
118 #define WINT_TYPE wchar_t
119 #endif /* wchar rank vs int */
120 #endif /* WCHAR_MIN defined */
121
122 /* Case label to identify conversions for signed integral values. The
123 * corresponding argument_value tag is sint and category is
124 * SPECIFIER_SINT.
125 */
126 #define SINT_CONV_CASES \
127 'd': \
128 CASE_SINT_CHAR \
129 case 'i'
130
131 /* Case label to identify conversions for signed integral arguments.
132 * The corresponding argument_value tag is uint and category is
133 * SPECIFIER_UINT.
134 */
135 #define UINT_CONV_CASES \
136 'o': \
137 CASE_UINT_CHAR \
138 case 'u': \
139 case 'x': \
140 case 'X'
141
142 /* Case label to identify conversions for floating point arguments.
143 * The corresponding argument_value tag is either dbl or ldbl,
144 * depending on length modifier, and the category is SPECIFIER_FP.
145 */
146 #define FP_CONV_CASES \
147 'a': \
148 case 'A': \
149 case 'e': \
150 case 'E': \
151 case 'f': \
152 case 'F': \
153 case 'g': \
154 case 'G'
155
156 /* Case label to identify conversions for pointer arguments. The
157 * corresponding argument_value tag is ptr and the category is
158 * SPECIFIER_PTR.
159 */
160 #define PTR_CONV_CASES \
161 'n': \
162 case 'p': \
163 case 's'
164
165 /* Storage for an argument value. */
166 union argument_value {
167 /* For SINT conversions */
168 sint_value_type sint;
169
170 /* For UINT conversions */
171 uint_value_type uint;
172
173 /* For FP conversions without L length */
174 double dbl;
175
176 /* For FP conversions with L length */
177 long double ldbl;
178
179 /* For PTR conversions */
180 void *ptr;
181 };
182
183 /* Structure capturing all attributes of a conversion
184 * specification.
185 *
186 * Initial values come from the specification, but are updated during
187 * the conversion.
188 */
189 struct conversion {
190 /** Indicates flags are inconsistent */
191 bool invalid: 1;
192
193 /** Indicates flags are valid but not supported */
194 bool unsupported: 1;
195
196 /** Left-justify value in width */
197 bool flag_dash: 1;
198
199 /** Explicit sign */
200 bool flag_plus: 1;
201
202 /** Space for non-negative sign */
203 bool flag_space: 1;
204
205 /** Alternative form */
206 bool flag_hash: 1;
207
208 /** Pad with leading zeroes */
209 bool flag_zero: 1;
210
211 /** Width field present */
212 bool width_present: 1;
213
214 /** Width value from int argument
215 *
216 * width_value is set to the absolute value of the argument.
217 * If the argument is negative flag_dash is also set.
218 */
219 bool width_star: 1;
220
221 /** Precision field present */
222 bool prec_present: 1;
223
224 /** Precision from int argument
225 *
226 * prec_value is set to the value of a non-negative argument.
227 * If the argument is negative prec_present is cleared.
228 */
229 bool prec_star: 1;
230
231 /** Length modifier (value from length_mod_enum) */
232 unsigned int length_mod: 4;
233
234 /** Indicates an a or A conversion specifier.
235 *
236 * This affects how precision is handled.
237 */
238 bool specifier_a: 1;
239
240 /** Conversion specifier category (value from specifier_cat_enum) */
241 unsigned int specifier_cat: 3;
242
243 /** If set alternate form requires 0 before octal. */
244 bool altform_0: 1;
245
246 /** If set alternate form requires 0x before hex. */
247 bool altform_0c: 1;
248
249 /** Set when pad0_value zeroes are to be to be inserted after
250 * the decimal point in a floating point conversion.
251 */
252 bool pad_postdp: 1;
253
254 /** Set for floating point values that have a non-zero
255 * pad0_prefix or pad0_pre_exp.
256 */
257 bool pad_fp: 1;
258
259 /** Conversion specifier character */
260 unsigned char specifier;
261
262 union {
263 /** Width value from specification.
264 *
265 * Valid until conversion begins.
266 */
267 int width_value;
268
269 /** Number of extra zeroes to be inserted around a
270 * formatted value:
271 *
272 * * before a formatted integer value due to precision
273 * and flag_zero; or
274 * * before a floating point mantissa decimal point
275 * due to precision; or
276 * * after a floating point mantissa decimal point due
277 * to precision.
278 *
279 * For example for zero-padded hexadecimal integers
280 * this would insert where the angle brackets are in:
281 * 0x<>hhhh.
282 *
283 * For floating point numbers this would insert at
284 * either <1> or <2> depending on #pad_postdp:
285 * VVV<1>.<2>FFFFeEEE
286 *
287 * Valid after conversion begins.
288 */
289 int pad0_value;
290 };
291
292 union {
293 /** Precision from specification.
294 *
295 * Valid until conversion begins.
296 */
297 int prec_value;
298
299 /** Number of extra zeros to be inserted after a decimal
300 * point due to precision.
301 *
302 * Inserts at <> in: VVVV.FFFF<>eEE
303 *
304 * Valid after conversion begins.
305 */
306 int pad0_pre_exp;
307 };
308 };
309
310 /** Get a size represented as a sequence of decimal digits.
311 *
312 * @param[inout] str where to read from. Updated to point to the first
313 * unconsumed character. There must be at least one non-digit character in
314 * the referenced text.
315 *
316 * @return the decoded integer value.
317 */
extract_decimal(const char ** str)318 static size_t extract_decimal(const char **str)
319 {
320 const char *sp = *str;
321 size_t val = 0;
322
323 while (isdigit((int)(unsigned char)*sp) != 0) {
324 val = 10U * val + *sp++ - '0';
325 }
326 *str = sp;
327 return val;
328 }
329
330 /** Extract C99 conversion specification flags.
331 *
332 * @param conv pointer to the conversion being defined.
333 *
334 * @param sp pointer to the first character after the % of a conversion
335 * specifier.
336 *
337 * @return a pointer the first character that follows the flags.
338 */
extract_flags(struct conversion * conv,const char * sp)339 static inline const char *extract_flags(struct conversion *conv,
340 const char *sp)
341 {
342 bool loop = true;
343
344 do {
345 switch (*sp) {
346 case '-':
347 conv->flag_dash = true;
348 break;
349 case '+':
350 conv->flag_plus = true;
351 break;
352 case ' ':
353 conv->flag_space = true;
354 break;
355 case '#':
356 conv->flag_hash = true;
357 break;
358 case '0':
359 conv->flag_zero = true;
360 break;
361 default:
362 loop = false;
363 }
364 if (loop) {
365 ++sp;
366 }
367 } while (loop);
368
369 /* zero && dash => !zero */
370 if (conv->flag_zero && conv->flag_dash) {
371 conv->flag_zero = false;
372 }
373
374 /* space && plus => !plus, handled in emitter code */
375
376 return sp;
377 }
378
379 /** Extract a C99 conversion specification width.
380 *
381 * @param conv pointer to the conversion being defined.
382 *
383 * @param sp pointer to the first character after the flags element of a
384 * conversion specification.
385 *
386 * @return a pointer the first character that follows the width.
387 */
extract_width(struct conversion * conv,const char * sp)388 static inline const char *extract_width(struct conversion *conv,
389 const char *sp)
390 {
391 conv->width_present = true;
392
393 if (*sp == '*') {
394 conv->width_star = true;
395 return ++sp;
396 }
397
398 const char *wp = sp;
399 size_t width = extract_decimal(&sp);
400
401 if (sp != wp) {
402 conv->width_present = true;
403 conv->width_value = width;
404 conv->unsupported |= ((conv->width_value < 0)
405 || (width != (size_t)conv->width_value));
406 }
407
408 return sp;
409 }
410
411 /** Extract a C99 conversion specification precision.
412 *
413 * @param conv pointer to the conversion being defined.
414 *
415 * @param sp pointer to the first character after the width element of a
416 * conversion specification.
417 *
418 * @return a pointer the first character that follows the precision.
419 */
extract_prec(struct conversion * conv,const char * sp)420 static inline const char *extract_prec(struct conversion *conv,
421 const char *sp)
422 {
423 conv->prec_present = (*sp == '.');
424
425 if (!conv->prec_present) {
426 return sp;
427 }
428 ++sp;
429
430 if (*sp == '*') {
431 conv->prec_star = true;
432 return ++sp;
433 }
434
435 size_t prec = extract_decimal(&sp);
436
437 conv->prec_value = prec;
438 conv->unsupported |= ((conv->prec_value < 0)
439 || (prec != (size_t)conv->prec_value));
440
441 return sp;
442 }
443
444 /** Extract a C99 conversion specification length.
445 *
446 * @param conv pointer to the conversion being defined.
447 *
448 * @param sp pointer to the first character after the precision element of a
449 * conversion specification.
450 *
451 * @return a pointer the first character that follows the precision.
452 */
extract_length(struct conversion * conv,const char * sp)453 static inline const char *extract_length(struct conversion *conv,
454 const char *sp)
455 {
456 switch (*sp) {
457 case 'h':
458 if (*++sp == 'h') {
459 conv->length_mod = LENGTH_HH;
460 ++sp;
461 } else {
462 conv->length_mod = LENGTH_H;
463 }
464 break;
465 case 'l':
466 if (*++sp == 'l') {
467 conv->length_mod = LENGTH_LL;
468 ++sp;
469 } else {
470 conv->length_mod = LENGTH_L;
471 }
472 break;
473 case 'j':
474 conv->length_mod = LENGTH_J;
475 ++sp;
476 break;
477 case 'z':
478 conv->length_mod = LENGTH_Z;
479 ++sp;
480 break;
481 case 't':
482 conv->length_mod = LENGTH_T;
483 ++sp;
484 break;
485 case 'L':
486 conv->length_mod = LENGTH_UPPER_L;
487 ++sp;
488
489 /* We recognize and consume these, but can't format
490 * them.
491 */
492 conv->unsupported = true;
493 break;
494 default:
495 conv->length_mod = LENGTH_NONE;
496 break;
497 }
498 return sp;
499 }
500
501 /* Extract a C99 conversion specifier.
502 *
503 * This is the character that identifies the representation of the converted
504 * value.
505 *
506 * @param conv pointer to the conversion being defined.
507 *
508 * @param sp pointer to the first character after the length element of a
509 * conversion specification.
510 *
511 * @return a pointer the first character that follows the specifier.
512 */
extract_specifier(struct conversion * conv,const char * sp)513 static inline const char *extract_specifier(struct conversion *conv,
514 const char *sp)
515 {
516 bool unsupported = false;
517
518 conv->specifier = *sp;
519 ++sp;
520
521 switch (conv->specifier) {
522 case SINT_CONV_CASES:
523 conv->specifier_cat = SPECIFIER_SINT;
524 goto int_conv;
525 case UINT_CONV_CASES:
526 conv->specifier_cat = SPECIFIER_UINT;
527 int_conv:
528 /* L length specifier not acceptable */
529 if (conv->length_mod == LENGTH_UPPER_L) {
530 conv->invalid = true;
531 }
532
533 /* For c LENGTH_NONE and LENGTH_L would be ok,
534 * but we don't support formatting wide characters.
535 */
536 if (conv->specifier == 'c') {
537 unsupported = (conv->length_mod != LENGTH_NONE);
538 } else if (!IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)) {
539 /* Disable conversion that might produce truncated
540 * results with buffers sized for 32 bits.
541 */
542 switch (conv->length_mod) {
543 case LENGTH_L:
544 unsupported = sizeof(long) > 4;
545 break;
546 case LENGTH_LL:
547 unsupported = sizeof(long long) > 4;
548 break;
549 case LENGTH_J:
550 unsupported = sizeof(uintmax_t) > 4;
551 break;
552 case LENGTH_Z:
553 unsupported = sizeof(size_t) > 4;
554 break;
555 case LENGTH_T:
556 unsupported = sizeof(ptrdiff_t) > 4;
557 break;
558 default:
559 /* Add an empty default with break, this is a defensive
560 * programming. Static analysis tool won't raise a violation
561 * if default is empty, but has that comment.
562 */
563 break;
564 }
565 } else {
566 ;
567 }
568 break;
569
570 case FP_CONV_CASES:
571 conv->specifier_cat = SPECIFIER_FP;
572
573 /* Don't support if disabled */
574 if (!IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) {
575 unsupported = true;
576 break;
577 }
578
579 /* When FP enabled %a support is still conditional. */
580 conv->specifier_a = (conv->specifier == 'a')
581 || (conv->specifier == 'A');
582 if (conv->specifier_a
583 && !IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)) {
584 unsupported = true;
585 break;
586 }
587
588 /* The l specifier has no effect. Otherwise length
589 * modifiers other than L are invalid.
590 */
591 if (conv->length_mod == LENGTH_L) {
592 conv->length_mod = LENGTH_NONE;
593 } else if ((conv->length_mod != LENGTH_NONE)
594 && (conv->length_mod != LENGTH_UPPER_L)) {
595 conv->invalid = true;
596 } else {
597 ;
598 }
599
600 break;
601
602 /* PTR cases are distinct */
603 case 'n':
604 conv->specifier_cat = SPECIFIER_PTR;
605 /* Anything except L */
606 if (conv->length_mod == LENGTH_UPPER_L) {
607 unsupported = true;
608 }
609 break;
610
611 case 's':
612 case 'p':
613 conv->specifier_cat = SPECIFIER_PTR;
614
615 /* p: only LENGTH_NONE
616 *
617 * s: LENGTH_NONE or LENGTH_L but wide
618 * characters not supported.
619 */
620 if (conv->length_mod != LENGTH_NONE) {
621 unsupported = true;
622 }
623 break;
624
625 default:
626 conv->invalid = true;
627 break;
628 }
629
630 conv->unsupported |= unsupported;
631
632 return sp;
633 }
634
635 /* Extract the complete C99 conversion specification.
636 *
637 * @param conv pointer to the conversion being defined.
638 *
639 * @param sp pointer to the % that introduces a conversion specification.
640 *
641 * @return pointer to the first character that follows the specification.
642 */
extract_conversion(struct conversion * conv,const char * sp)643 static inline const char *extract_conversion(struct conversion *conv,
644 const char *sp)
645 {
646 *conv = (struct conversion) {
647 .invalid = false,
648 };
649
650 /* Skip over the opening %. If the conversion specifier is %,
651 * that's the only thing that should be there, so
652 * fast-exit.
653 */
654 ++sp;
655 if (*sp == '%') {
656 conv->specifier = *sp;
657 ++sp;
658 return sp;
659 }
660
661 sp = extract_flags(conv, sp);
662 sp = extract_width(conv, sp);
663 sp = extract_prec(conv, sp);
664 sp = extract_length(conv, sp);
665 sp = extract_specifier(conv, sp);
666
667 return sp;
668 }
669
670 #ifdef CONFIG_64BIT
671
_ldiv5(uint64_t * v)672 static void _ldiv5(uint64_t *v)
673 {
674 /* The compiler can optimize this on its own on 64-bit architectures */
675 *v /= 5U;
676 }
677
678 #else /* CONFIG_64BIT */
679
680 /*
681 * Tiny integer divide-by-five routine. The full 64 bit division
682 * implementations in libgcc are very large on some architectures, and
683 * currently nothing in Zephyr pulls it into the link. So it makes
684 * sense to define this much smaller special case here to avoid
685 * including it just for printf.
686 *
687 * It works by multiplying v by the reciprocal of 5 i.e.:
688 *
689 * result = v * ((1 << 64) / 5) / (1 << 64)
690 *
691 * This produces a 128-bit result, but we drop the bottom 64 bits which
692 * accounts for the division by (1 << 64). The product is kept to 64 bits
693 * by summing partial multiplications and shifting right by 32 which on
694 * most 32-bit architectures means only a register drop.
695 *
696 * Here the multiplier is: (1 << 64) / 5 = 0x3333333333333333
697 * i.e. a 62 bits value. To compensate for the reduced precision, we
698 * add an initial bias of 1 to v. This conveniently allows for keeping
699 * the multiplier in a single 32-bit register given its pattern.
700 * Enlarging the multiplier to 64 bits would also work but carry handling
701 * on the summing of partial mults would be necessary, and a final right
702 * shift would be needed, requiring more instructions.
703 */
_ldiv5(uint64_t * v)704 static void _ldiv5(uint64_t *v)
705 {
706 uint32_t v_lo = *v;
707 uint32_t v_hi = *v >> 32;
708 uint32_t m = 0x33333333;
709 uint64_t result;
710
711 /*
712 * Force the multiplier constant into a register and make it
713 * opaque to the compiler, otherwise gcc tries to be too smart
714 * for its own good with a large expansion of adds and shifts.
715 */
716 __asm__ ("" : "+r" (m));
717
718 /*
719 * Apply a bias of 1 to v. We can't add it to v as this would overflow
720 * it when at max range. Factor it out with the multiplier upfront.
721 */
722 result = ((uint64_t)m << 32) | m;
723
724 /* The actual multiplication. */
725 result += (uint64_t)v_lo * m;
726 result >>= 32;
727 result += (uint64_t)v_lo * m;
728 result += (uint64_t)v_hi * m;
729 result >>= 32;
730 result += (uint64_t)v_hi * m;
731
732 *v = result;
733 }
734
735 #endif /* CONFIG_64BIT */
736
737 /* Division by 10 */
_ldiv10(uint64_t * v)738 static void _ldiv10(uint64_t *v)
739 {
740 *v >>= 1;
741 _ldiv5(v);
742 }
743
744 /* Extract the next decimal character in the converted representation of a
745 * fractional component.
746 */
_get_digit(uint64_t * fr,int * digit_count)747 static char _get_digit(uint64_t *fr, int *digit_count)
748 {
749 char rval;
750
751 if (*digit_count > 0) {
752 --*digit_count;
753 *fr *= 10U;
754 rval = ((*fr >> 60) & 0xF) + '0';
755 *fr &= (BIT64(60) - 1U);
756 } else {
757 rval = '0';
758 }
759
760 return rval;
761 }
762
conversion_radix(char specifier)763 static inline size_t conversion_radix(char specifier)
764 {
765 switch (specifier) {
766 default:
767 case 'd':
768 case 'i':
769 case 'u':
770 return 10;
771 case 'o':
772 return 8;
773 case 'p':
774 case 'x':
775 case 'X':
776 return 16;
777 }
778 }
779
780 /* Writes the given value into the buffer in the specified base.
781 *
782 * Precision is applied *ONLY* within the space allowed.
783 *
784 * Alternate form value is applied to o, x, and X conversions.
785 *
786 * The buffer is filled backwards, so the input bpe is the end of the
787 * generated representation. The returned pointer is to the first
788 * character of the representation.
789 */
encode_uint(uint_value_type value,struct conversion * conv,char * bps,const char * bpe)790 static char *encode_uint(uint_value_type value,
791 struct conversion *conv,
792 char *bps,
793 const char *bpe)
794 {
795 bool upcase = isupper((int)conv->specifier) != 0;
796 const unsigned int radix = conversion_radix(conv->specifier);
797 char *bp = bps + (bpe - bps);
798
799 do {
800 unsigned int lsv = (unsigned int)(value % radix);
801
802 --bp;
803 *bp = (lsv <= 9) ? ('0' + lsv)
804 : upcase ? ('A' + lsv - 10) : ('a' + lsv - 10);
805 value /= radix;
806 } while ((value != 0) && (bps < bp));
807
808 /* Record required alternate forms. This can be determined
809 * from the radix without re-checking specifier.
810 */
811 if (conv->flag_hash) {
812 if (radix == 8) {
813 conv->altform_0 = true;
814 } else if (radix == 16) {
815 conv->altform_0c = true;
816 } else {
817 ;
818 }
819 }
820
821 return bp;
822 }
823
824 /* Number of bits in the fractional part of an IEEE 754-2008 double
825 * precision float.
826 */
827 #define FRACTION_BITS 52
828
829 /* Number of hex "digits" in the fractional part of an IEEE 754-2008
830 * double precision float.
831 */
832 #define FRACTION_HEX DIV_ROUND_UP(FRACTION_BITS, 4)
833
834 /* Number of bits in the exponent of an IEEE 754-2008 double precision
835 * float.
836 */
837 #define EXPONENT_BITS 11
838
839 /* Mask for the sign (negative) bit of an IEEE 754-2008 double precision
840 * float.
841 */
842 #define SIGN_MASK BIT64(63)
843
844 /* Mask for the high-bit of a uint64_t representation of a fractional
845 * value.
846 */
847 #define BIT_63 BIT64(63)
848
849 /* Convert the IEEE 754-2008 double to text format.
850 *
851 * @param value the 64-bit floating point value.
852 *
853 * @param conv details about how the conversion is to proceed. Some fields
854 * are adjusted based on the value being converted.
855 *
856 * @param precision the precision for the conversion (generally digits past
857 * the decimal point).
858 *
859 * @param bps pointer to the first character in a buffer that will hold the
860 * converted value.
861 *
862 * @param bpe On entry this points to the end of the buffer reserved to hold
863 * the converted value. On exit it is updated to point just past the
864 * converted value.
865 *
866 * return a pointer to the start of the converted value. This may not be @p
867 * bps but will be consistent with the exit value of *bpe.
868 */
encode_float(double value,struct conversion * conv,int precision,char * sign,char * bps,const char ** bpe)869 static char *encode_float(double value,
870 struct conversion *conv,
871 int precision,
872 char *sign,
873 char *bps,
874 const char **bpe)
875 {
876 union {
877 uint64_t u64;
878 double dbl;
879 } u = {
880 .dbl = value,
881 };
882 bool prune_zero = false;
883 char *buf = bps;
884
885 /* Prepend the sign: '-' if negative, flags control
886 * non-negative behavior.
887 */
888 if ((u.u64 & SIGN_MASK) != 0U) {
889 *sign = '-';
890 } else if (conv->flag_plus) {
891 *sign = '+';
892 } else if (conv->flag_space) {
893 *sign = ' ';
894 } else {
895 ;
896 }
897
898 /* Extract the non-negative offset exponent and fraction. Record
899 * whether the value is subnormal.
900 */
901 char c = conv->specifier;
902 int expo = (u.u64 >> FRACTION_BITS) & BIT_MASK(EXPONENT_BITS);
903 uint64_t fract = u.u64 & BIT64_MASK(FRACTION_BITS);
904 bool is_subnormal = (expo == 0) && (fract != 0);
905
906 /* Exponent of all-ones signals infinity or NaN, which are
907 * text constants regardless of specifier.
908 */
909 if (expo == BIT_MASK(EXPONENT_BITS)) {
910 if (fract == 0) {
911 if (isupper((unsigned char)c) != 0) {
912 buf[0] = 'I';
913 buf[1] = 'N';
914 buf[2] = 'F';
915 buf += 3;
916 } else {
917 buf[0] = 'i';
918 buf[1] = 'n';
919 buf[2] = 'f';
920 buf += 3;
921 }
922 } else {
923 if (isupper((unsigned char)c) != 0) {
924 buf[0] = 'N';
925 buf[1] = 'A';
926 buf[2] = 'N';
927 buf += 3;
928 } else {
929 buf[0] = 'n';
930 buf[1] = 'a';
931 buf[2] = 'n';
932 buf += 3;
933 }
934 }
935
936 /* No zero-padding with text values */
937 conv->flag_zero = false;
938
939 *bpe = buf;
940 return bps;
941 }
942
943 /* The case of an F specifier is no longer relevant. */
944 if (c == 'F') {
945 c = 'f';
946 }
947
948 /* Handle converting to the hex representation. */
949 if (IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)
950 && (IS_ENABLED(CONFIG_CBPRINTF_FP_ALWAYS_A)
951 || conv->specifier_a)) {
952 buf[0] = '0';
953 buf[1] = 'x';
954 buf += 2;
955
956 /* Remove the offset from the exponent, and store the
957 * non-fractional value. Subnormals require increasing the
958 * exponent as first bit isn't the implicit bit.
959 */
960 expo -= 1023;
961 if (is_subnormal) {
962 *buf = '0';
963 ++buf;
964 ++expo;
965 } else {
966 *buf = '1';
967 ++buf;
968 }
969
970 /* If we didn't get precision from a %a specification then we
971 * treat it as from a %a specification with no precision: full
972 * range, zero-pruning enabled.
973 *
974 * Otherwise we have to cap the precision of the generated
975 * fraction, or possibly round it.
976 */
977 if (!(conv->specifier_a && conv->prec_present)) {
978 precision = FRACTION_HEX;
979 prune_zero = true;
980 } else if (precision > FRACTION_HEX) {
981 conv->pad0_pre_exp = precision - FRACTION_HEX;
982 conv->pad_fp = true;
983 precision = FRACTION_HEX;
984 } else if ((fract != 0)
985 && (precision < FRACTION_HEX)) {
986 size_t pos = 4 * (FRACTION_HEX - precision) - 1;
987 uint64_t mask = BIT64(pos);
988
989 /* Round only if the bit that would round is
990 * set.
991 */
992 if ((fract & mask) != 0ULL) {
993 fract += mask;
994 }
995 }
996
997 /* Record whether we must retain the decimal point even if we
998 * can prune zeros.
999 */
1000 bool require_dp = ((fract != 0) || conv->flag_hash);
1001
1002 if (require_dp || (precision != 0)) {
1003 *buf = '.';
1004 ++buf;
1005 }
1006
1007 /* Get the fractional value as a hexadecimal string, using x
1008 * for a and X for A.
1009 */
1010 struct conversion aconv = {
1011 .specifier = isupper((unsigned char)c) != 0 ? 'X' : 'x',
1012 };
1013 const char *spe = *bpe;
1014 char *sp = bps + (spe - bps);
1015
1016 if (fract != 0) {
1017 sp = encode_uint(fract, &aconv, buf, spe);
1018 }
1019
1020 /* Pad out to full range since this is below the decimal
1021 * point.
1022 */
1023 while ((spe - sp) < FRACTION_HEX) {
1024 --sp;
1025 *sp = '0';
1026 }
1027
1028 /* Append the leading significant "digits". */
1029 while ((sp < spe) && (precision > 0)) {
1030 *buf = *sp;
1031 ++buf;
1032 ++sp;
1033 --precision;
1034 }
1035
1036 if (prune_zero) {
1037 while (*--buf == '0') {
1038 ;
1039 }
1040 if ((*buf != '.') || require_dp) {
1041 ++buf;
1042 }
1043 }
1044
1045 *buf = 'p';
1046 ++buf;
1047 if (expo >= 0) {
1048 *buf = '+';
1049 ++buf;
1050 } else {
1051 *buf = '-';
1052 ++buf;
1053 expo = -expo;
1054 }
1055
1056 aconv.specifier = 'i';
1057 sp = encode_uint(expo, &aconv, buf, spe);
1058
1059 while (sp < spe) {
1060 *buf = *sp;
1061 ++buf;
1062 ++sp;
1063 }
1064
1065 *bpe = buf;
1066 return bps;
1067 }
1068
1069 /* Remainder of code operates on a 64-bit fraction, so shift up (and
1070 * discard garbage from the exponent where the implicit 1 would be
1071 * stored).
1072 */
1073 fract <<= EXPONENT_BITS;
1074 fract &= ~SIGN_MASK;
1075
1076 /* Non-zero values need normalization. */
1077 if ((expo | fract) != 0) {
1078 if (is_subnormal) {
1079 /* Fraction is subnormal. Normalize it and correct
1080 * the exponent.
1081 */
1082 for (fract <<= 1; (fract & BIT_63) == 0; fract <<= 1) {
1083 expo--;
1084 }
1085 }
1086 /* Adjust the offset exponent to be signed rather than offset,
1087 * and set the implicit 1 bit in the (shifted) 53-bit
1088 * fraction.
1089 */
1090 expo -= (1023 - 1); /* +1 since .1 vs 1. */
1091 fract |= BIT_63;
1092 }
1093
1094 /*
1095 * Let's consider:
1096 *
1097 * value = fract * 2^expo * 10^decexp
1098 *
1099 * Initially decexp = 0. The goal is to bring exp between
1100 * 0 and -2 as the magnitude of a fractional decimal digit is 3 bits.
1101 */
1102 int decexp = 0;
1103
1104 while (expo < -2) {
1105 /*
1106 * Make room to allow a multiplication by 5 without overflow.
1107 * We test only the top part for faster code.
1108 */
1109 do {
1110 fract >>= 1;
1111 expo++;
1112 } while ((uint32_t)(fract >> 32) >= (UINT32_MAX / 5U));
1113
1114 /* Perform fract * 5 * 2 / 10 */
1115 fract *= 5U;
1116 expo++;
1117 decexp--;
1118 }
1119
1120 while (expo > 0) {
1121 /*
1122 * Perform fract / 5 / 2 * 10.
1123 * The +2 is there to do round the result of the division
1124 * by 5 not to lose too much precision in extreme cases.
1125 */
1126 fract += 2;
1127 _ldiv5(&fract);
1128 expo--;
1129 decexp++;
1130
1131 /* Bring back our fractional number to full scale */
1132 do {
1133 fract <<= 1;
1134 expo--;
1135 } while (!(fract & BIT_63));
1136 }
1137
1138 /*
1139 * The binary fractional point is located somewhere above bit 63.
1140 * Move it between bits 59 and 60 to give 4 bits of room to the
1141 * integer part.
1142 */
1143 fract >>= (4 - expo);
1144
1145 if ((c == 'g') || (c == 'G')) {
1146 /* Use the specified precision and exponent to select the
1147 * representation and correct the precision and zero-pruning
1148 * in accordance with the ISO C rule.
1149 */
1150 if ((decexp < (-4 + 1)) || (decexp > precision)) {
1151 c += 'e' - 'g'; /* e or E */
1152 if (precision > 0) {
1153 precision--;
1154 }
1155 } else {
1156 c = 'f';
1157 precision -= decexp;
1158 }
1159 if (!conv->flag_hash && (precision > 0)) {
1160 prune_zero = true;
1161 }
1162 }
1163
1164 int decimals;
1165 if (c == 'f') {
1166 decimals = precision + decexp;
1167 if (decimals < 0) {
1168 decimals = 0;
1169 }
1170 } else {
1171 decimals = precision + 1;
1172 }
1173
1174 int digit_count = 16;
1175
1176 if (decimals > 16) {
1177 decimals = 16;
1178 }
1179
1180 /* Round the value to the last digit being printed. */
1181 uint64_t round = BIT64(59); /* 0.5 */
1182 while (decimals-- != 0) {
1183 _ldiv10(&round);
1184 }
1185 fract += round;
1186 /* Make sure rounding didn't make fract >= 1.0 */
1187 if (fract >= BIT64(60)) {
1188 _ldiv10(&fract);
1189 decexp++;
1190 }
1191
1192 if (c == 'f') {
1193 if (decexp > 0) {
1194 /* Emit the digits above the decimal point. */
1195 while ((decexp > 0) && (digit_count > 0)) {
1196 *buf = _get_digit(&fract, &digit_count);
1197 ++buf;
1198 decexp--;
1199 }
1200
1201 conv->pad0_value = decexp;
1202
1203 decexp = 0;
1204 } else {
1205 *buf = '0';
1206 ++buf;
1207 }
1208
1209 /* Emit the decimal point only if required by the alternative
1210 * format, or if more digits are to follow.
1211 */
1212 if (conv->flag_hash || (precision > 0)) {
1213 *buf = '.';
1214 ++buf;
1215 }
1216
1217 if ((decexp < 0) && (precision > 0)) {
1218 conv->pad0_value = -decexp;
1219 if (conv->pad0_value > precision) {
1220 conv->pad0_value = precision;
1221 }
1222
1223 precision -= conv->pad0_value;
1224 conv->pad_postdp = (conv->pad0_value > 0);
1225 }
1226 } else { /* e or E */
1227 /* Emit the one digit before the decimal. If it's not zero,
1228 * this is significant so reduce the base-10 exponent.
1229 */
1230 *buf = _get_digit(&fract, &digit_count);
1231 if (*buf++ != '0') {
1232 decexp--;
1233 }
1234
1235 /* Emit the decimal point only if required by the alternative
1236 * format, or if more digits are to follow.
1237 */
1238 if (conv->flag_hash || (precision > 0)) {
1239 *buf = '.';
1240 ++buf;
1241 }
1242 }
1243
1244 while ((precision > 0) && (digit_count > 0)) {
1245 *buf = _get_digit(&fract, &digit_count);
1246 ++buf;
1247 precision--;
1248 }
1249
1250 conv->pad0_pre_exp = precision;
1251
1252 if (prune_zero) {
1253 conv->pad0_pre_exp = 0;
1254 do {
1255 --buf;
1256 } while (*buf == '0');
1257 if (*buf != '.') {
1258 ++buf;
1259 }
1260 }
1261
1262 /* Emit the explicit exponent, if format requires it. */
1263 if ((c == 'e') || (c == 'E')) {
1264 *buf = c;
1265 ++buf;
1266 if (decexp < 0) {
1267 decexp = -decexp;
1268 *buf = '-';
1269 ++buf;
1270 } else {
1271 *buf = '+';
1272 ++buf;
1273 }
1274
1275 /* At most 3 digits to the decimal. Spit them out. */
1276 if (decexp >= 100) {
1277 *buf = (decexp / 100) + '0';
1278 ++buf;
1279 decexp %= 100;
1280 }
1281
1282 buf[0] = (decexp / 10) + '0';
1283 buf[1] = (decexp % 10) + '0';
1284 buf += 2;
1285 }
1286
1287 /* Cache whether there's padding required */
1288 conv->pad_fp = (conv->pad0_value > 0)
1289 || (conv->pad0_pre_exp > 0);
1290
1291 /* Set the end of the encoded sequence, and return its start. Also
1292 * store EOS as a non-digit/non-decimal value so we don't have to
1293 * check against bpe when iterating in multiple places.
1294 */
1295 *bpe = buf;
1296 *buf = 0;
1297 return bps;
1298 }
1299
1300 /* Store a count into the pointer provided in a %n specifier.
1301 *
1302 * @param conv the specifier that indicates the size of the value into which
1303 * the count will be stored.
1304 *
1305 * @param dp where the count should be stored.
1306 *
1307 * @param count the count to be stored.
1308 */
store_count(const struct conversion * conv,void * dp,int count)1309 static inline void store_count(const struct conversion *conv,
1310 void *dp,
1311 int count)
1312 {
1313 switch ((enum length_mod_enum)conv->length_mod) {
1314 case LENGTH_NONE:
1315 *(int *)dp = count;
1316 break;
1317 case LENGTH_HH:
1318 *(signed char *)dp = (signed char)count;
1319 break;
1320 case LENGTH_H:
1321 *(short *)dp = (short)count;
1322 break;
1323 case LENGTH_L:
1324 *(long *)dp = (long)count;
1325 break;
1326 case LENGTH_LL:
1327 *(long long *)dp = (long long)count;
1328 break;
1329 case LENGTH_J:
1330 *(intmax_t *)dp = (intmax_t)count;
1331 break;
1332 case LENGTH_Z:
1333 *(size_t *)dp = (size_t)count;
1334 break;
1335 case LENGTH_T:
1336 *(ptrdiff_t *)dp = (ptrdiff_t)count;
1337 break;
1338 default:
1339 /* Add an empty default with break, this is a defensive programming.
1340 * Static analysis tool won't raise a violation if default is empty,
1341 * but has that comment.
1342 */
1343 break;
1344 }
1345 }
1346
1347 /* Outline function to emit all characters in [sp, ep). */
outs(cbprintf_cb __out,void * ctx,const char * sp,const char * ep)1348 static int outs(cbprintf_cb __out,
1349 void *ctx,
1350 const char *sp,
1351 const char *ep)
1352 {
1353 size_t count = 0;
1354 cbprintf_cb_local out = __out;
1355
1356 while ((sp < ep) || ((ep == NULL) && *sp)) {
1357 int rc = out((int)*sp, ctx);
1358 ++sp;
1359
1360 if (rc < 0) {
1361 return rc;
1362 }
1363 ++count;
1364 }
1365
1366 return (int)count;
1367 }
1368
z_cbvprintf_impl(cbprintf_cb __out,void * ctx,const char * fp,va_list ap,uint32_t flags)1369 int z_cbvprintf_impl(cbprintf_cb __out, void *ctx, const char *fp,
1370 va_list ap, uint32_t flags)
1371 {
1372 char buf[CONVERTED_BUFLEN];
1373 size_t count = 0;
1374 sint_value_type sint;
1375 cbprintf_cb_local out = __out;
1376
1377 const bool tagged_ap = (flags & Z_CBVPRINTF_PROCESS_FLAG_TAGGED_ARGS)
1378 == Z_CBVPRINTF_PROCESS_FLAG_TAGGED_ARGS;
1379
1380 /* Output character, returning EOF if output failed, otherwise
1381 * updating count.
1382 *
1383 * NB: c is evaluated exactly once: side-effects are OK
1384 */
1385 #define OUTC(c) do { \
1386 int rc = (*out)((int)(c), ctx); \
1387 \
1388 if (rc < 0) { \
1389 return rc; \
1390 } \
1391 ++count; \
1392 } while (false)
1393
1394 /* Output sequence of characters, returning a negative error if output
1395 * failed.
1396 */
1397
1398 #define OUTS(_sp, _ep) do { \
1399 int rc = outs(out, ctx, (_sp), (_ep)); \
1400 \
1401 if (rc < 0) { \
1402 return rc; \
1403 } \
1404 count += rc; \
1405 } while (false)
1406
1407 while (*fp != 0) {
1408 if (*fp != '%') {
1409 OUTC(*fp);
1410 ++fp;
1411 continue;
1412 }
1413
1414 /* Force union into RAM with conversion state to
1415 * mitigate LLVM code generation bug.
1416 */
1417 struct {
1418 union argument_value value;
1419 struct conversion conv;
1420 } state = {
1421 .value = {
1422 .uint = 0,
1423 },
1424 };
1425 struct conversion *const conv = &state.conv;
1426 union argument_value *const value = &state.value;
1427 const char *sp = fp;
1428 int width = -1;
1429 int precision = -1;
1430 const char *bps = NULL;
1431 const char *bpe = buf + sizeof(buf);
1432 char sign = 0;
1433
1434 fp = extract_conversion(conv, sp);
1435
1436 if (conv->specifier_cat != SPECIFIER_INVALID) {
1437 if (IS_ENABLED(CONFIG_CBPRINTF_PACKAGE_SUPPORT_TAGGED_ARGUMENTS)
1438 && tagged_ap) {
1439 /* Skip over the argument tag as it is not being
1440 * used here.
1441 */
1442 (void)va_arg(ap, int);
1443 }
1444 }
1445
1446 /* If dynamic width is specified, process it,
1447 * otherwise set width if present.
1448 */
1449 if (conv->width_star) {
1450 width = va_arg(ap, int);
1451
1452 if (width < 0) {
1453 conv->flag_dash = true;
1454 width = -width;
1455 }
1456 } else if (conv->width_present) {
1457 width = conv->width_value;
1458 } else {
1459 ;
1460 }
1461
1462 /* If dynamic precision is specified, process it, otherwise
1463 * set precision if present. For floating point where
1464 * precision is not present use 6.
1465 */
1466 if (conv->prec_star) {
1467 int arg = va_arg(ap, int);
1468
1469 if (arg < 0) {
1470 conv->prec_present = false;
1471 } else {
1472 precision = arg;
1473 }
1474 } else if (conv->prec_present) {
1475 precision = conv->prec_value;
1476 } else {
1477 ;
1478 }
1479
1480 /* Reuse width and precision memory in conv for value
1481 * padding counts.
1482 */
1483 conv->pad0_value = 0;
1484 conv->pad0_pre_exp = 0;
1485
1486 /* FP conversion requires knowing the precision. */
1487 if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)
1488 && (conv->specifier_cat == SPECIFIER_FP)
1489 && !conv->prec_present) {
1490 if (conv->specifier_a) {
1491 precision = FRACTION_HEX;
1492 } else {
1493 precision = 6;
1494 }
1495 }
1496
1497 /* Get the value to be converted from the args.
1498 *
1499 * This can't be extracted to a helper function because
1500 * passing a pointer to va_list doesn't work on x86_64. See
1501 * https://stackoverflow.com/a/8048892.
1502 */
1503 enum specifier_cat_enum specifier_cat
1504 = (enum specifier_cat_enum)conv->specifier_cat;
1505 enum length_mod_enum length_mod
1506 = (enum length_mod_enum)conv->length_mod;
1507
1508 /* Extract the value based on the argument category and length.
1509 *
1510 * Note that the length modifier doesn't affect the value of a
1511 * pointer argument.
1512 */
1513 if (specifier_cat == SPECIFIER_SINT) {
1514 switch (length_mod) {
1515 default:
1516 case LENGTH_NONE:
1517 case LENGTH_HH:
1518 case LENGTH_H:
1519 value->sint = va_arg(ap, int);
1520 break;
1521 case LENGTH_L:
1522 if (WCHAR_IS_SIGNED
1523 && (conv->specifier == 'c')) {
1524 value->sint = (wchar_t)va_arg(ap,
1525 WINT_TYPE);
1526 } else {
1527 value->sint = va_arg(ap, long);
1528 }
1529 break;
1530 case LENGTH_LL:
1531 value->sint =
1532 (sint_value_type)va_arg(ap, long long);
1533 break;
1534 case LENGTH_J:
1535 value->sint =
1536 (sint_value_type)va_arg(ap, intmax_t);
1537 break;
1538 case LENGTH_Z: /* size_t */
1539 case LENGTH_T: /* ptrdiff_t */
1540 /* Though ssize_t is the signed equivalent of
1541 * size_t for POSIX, there is no uptrdiff_t.
1542 * Assume that size_t and ptrdiff_t are the
1543 * unsigned and signed equivalents of each
1544 * other. This can be checked in a platform
1545 * test.
1546 */
1547 value->sint =
1548 (sint_value_type)va_arg(ap, ptrdiff_t);
1549 break;
1550 }
1551 if (length_mod == LENGTH_HH) {
1552 value->sint = (signed char)value->sint;
1553 } else if (length_mod == LENGTH_H) {
1554 value->sint = (short)value->sint;
1555 }
1556 } else if (specifier_cat == SPECIFIER_UINT) {
1557 switch (length_mod) {
1558 default:
1559 case LENGTH_NONE:
1560 case LENGTH_HH:
1561 case LENGTH_H:
1562 value->uint = va_arg(ap, unsigned int);
1563 break;
1564 case LENGTH_L:
1565 if ((!WCHAR_IS_SIGNED)
1566 && (conv->specifier == 'c')) {
1567 value->uint = (wchar_t)va_arg(ap,
1568 WINT_TYPE);
1569 } else {
1570 value->uint = va_arg(ap, unsigned long);
1571 }
1572 break;
1573 case LENGTH_LL:
1574 value->uint =
1575 (uint_value_type)va_arg(ap,
1576 unsigned long long);
1577 break;
1578 case LENGTH_J:
1579 value->uint =
1580 (uint_value_type)va_arg(ap,
1581 uintmax_t);
1582 break;
1583 case LENGTH_Z: /* size_t */
1584 case LENGTH_T: /* ptrdiff_t */
1585 value->uint =
1586 (uint_value_type)va_arg(ap, size_t);
1587 break;
1588 }
1589 if (length_mod == LENGTH_HH) {
1590 value->uint = (unsigned char)value->uint;
1591 } else if (length_mod == LENGTH_H) {
1592 value->uint = (unsigned short)value->uint;
1593 }
1594 } else if (specifier_cat == SPECIFIER_FP) {
1595 if (length_mod == LENGTH_UPPER_L) {
1596 value->ldbl = va_arg(ap, long double);
1597 } else {
1598 value->dbl = va_arg(ap, double);
1599 }
1600 } else if (specifier_cat == SPECIFIER_PTR) {
1601 value->ptr = va_arg(ap, void *);
1602 }
1603
1604 /* We've now consumed all arguments related to this
1605 * specification. If the conversion is invalid, or is
1606 * something we don't support, then output the original
1607 * specification and move on.
1608 */
1609 if (conv->invalid || conv->unsupported) {
1610 OUTS(sp, fp);
1611 continue;
1612 }
1613
1614 /* Do formatting, either into the buffer or
1615 * referencing external data.
1616 */
1617 switch (conv->specifier) {
1618 case '%':
1619 OUTC('%');
1620 break;
1621 case 's': {
1622 bps = (const char *)value->ptr;
1623
1624 size_t len;
1625
1626 if (precision >= 0) {
1627 len = strnlen(bps, precision);
1628 } else {
1629 len = strlen(bps);
1630 }
1631
1632 bpe = bps + len;
1633 precision = -1;
1634
1635 break;
1636 }
1637 case 'p':
1638 /* Implementation-defined: null is "(nil)", non-null
1639 * has 0x prefix followed by significant address hex
1640 * digits, no leading zeros.
1641 */
1642 if (value->ptr != NULL) {
1643 bps = encode_uint((uintptr_t)value->ptr, conv,
1644 buf, bpe);
1645
1646 /* Use 0x prefix */
1647 conv->altform_0c = true;
1648 conv->specifier = 'x';
1649
1650 goto prec_int_pad0;
1651 }
1652
1653 bps = "(nil)";
1654 bpe = bps + 5;
1655
1656 break;
1657 case 'c':
1658 bps = buf;
1659 buf[0] = CHAR_IS_SIGNED ? value->sint : value->uint;
1660 bpe = buf + 1;
1661 break;
1662 case 'd':
1663 case 'i':
1664 if (conv->flag_plus) {
1665 sign = '+';
1666 } else if (conv->flag_space) {
1667 sign = ' ';
1668 }
1669
1670 /* sint/uint overlay in the union, and so
1671 * can't appear in read and write operations
1672 * in the same statement.
1673 */
1674 sint = value->sint;
1675 if (sint < 0) {
1676 sign = '-';
1677 value->uint = (uint_value_type)-sint;
1678 } else {
1679 value->uint = (uint_value_type)sint;
1680 }
1681
1682 __fallthrough;
1683 case 'o':
1684 case 'u':
1685 case 'x':
1686 case 'X':
1687 bps = encode_uint(value->uint, conv, buf, bpe);
1688
1689 prec_int_pad0:
1690 /* Update pad0 values based on precision and converted
1691 * length. Note that a non-empty sign is not in the
1692 * converted sequence, but it does not affect the
1693 * padding size.
1694 */
1695 if (precision >= 0) {
1696 size_t len = bpe - bps;
1697
1698 /* Zero-padding flag is ignored for integer
1699 * conversions with precision.
1700 */
1701 conv->flag_zero = false;
1702
1703 /* Set pad0_value to satisfy precision */
1704 if (len < (size_t)precision) {
1705 conv->pad0_value = precision - (int)len;
1706 }
1707 }
1708
1709 break;
1710 case 'n':
1711 if (IS_ENABLED(CONFIG_CBPRINTF_N_SPECIFIER)) {
1712 store_count(conv, value->ptr, count);
1713 }
1714
1715 break;
1716
1717 case FP_CONV_CASES:
1718 if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) {
1719 bps = encode_float(value->dbl, conv, precision,
1720 &sign, buf, &bpe);
1721 }
1722 break;
1723 default:
1724 /* Add an empty default with break, this is a defensive
1725 * programming. Static analysis tool won't raise a violation
1726 * if default is empty, but has that comment.
1727 */
1728 break;
1729 }
1730
1731 /* If we don't have a converted value to emit, move
1732 * on.
1733 */
1734 if (bps == NULL) {
1735 continue;
1736 }
1737
1738 /* The converted value is now stored in [bps, bpe), excluding
1739 * any required zero padding.
1740 *
1741 * The unjustified output will be:
1742 *
1743 * * any sign character (sint-only)
1744 * * any altform prefix
1745 * * for FP:
1746 * * any pre-decimal content from the converted value
1747 * * any pad0_value padding (!postdp)
1748 * * any decimal point in the converted value
1749 * * any pad0_value padding (postdp)
1750 * * any pre-exponent content from the converted value
1751 * * any pad0_pre_exp padding
1752 * * any exponent content from the converted value
1753 * * for non-FP:
1754 * * any pad0_prefix
1755 * * the converted value
1756 */
1757 size_t nj_len = (bpe - bps);
1758 int pad_len = 0;
1759
1760 if (sign != 0) {
1761 nj_len += 1U;
1762 }
1763
1764 if (conv->altform_0c) {
1765 nj_len += 2U;
1766 } else if (conv->altform_0) {
1767 nj_len += 1U;
1768 }
1769
1770 nj_len += conv->pad0_value;
1771 if (conv->pad_fp) {
1772 nj_len += conv->pad0_pre_exp;
1773 }
1774
1775 /* If we have a width update width to hold the padding we need
1776 * for justification. The result may be negative, which will
1777 * result in no padding.
1778 *
1779 * If a non-negative padding width is present and we're doing
1780 * right-justification, emit the padding now.
1781 */
1782 if (width > 0) {
1783 width -= (int)nj_len;
1784
1785 if (!conv->flag_dash) {
1786 char pad = ' ';
1787
1788 /* If we're zero-padding we have to emit the
1789 * sign first.
1790 */
1791 if (conv->flag_zero) {
1792 if (sign != 0) {
1793 OUTC(sign);
1794 sign = 0;
1795 }
1796 pad = '0';
1797 }
1798
1799 while (width-- > 0) {
1800 OUTC(pad);
1801 }
1802 }
1803 }
1804
1805 /* If we have a sign that hasn't been emitted, now's the
1806 * time....
1807 */
1808 if (sign != 0) {
1809 OUTC(sign);
1810 }
1811
1812 if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT) && conv->pad_fp) {
1813 const char *cp = bps;
1814
1815 if (conv->specifier_a) {
1816 /* Only padding is pre_exp */
1817 while (*cp != 'p') {
1818 OUTC(*cp);
1819 ++cp;
1820 }
1821 } else {
1822 while (isdigit((unsigned char)*cp) != 0) {
1823 OUTC(*cp);
1824 ++cp;
1825 }
1826
1827 pad_len = conv->pad0_value;
1828 if (!conv->pad_postdp) {
1829 while (pad_len-- > 0) {
1830 OUTC('0');
1831 }
1832 }
1833
1834 if (*cp == '.') {
1835 OUTC(*cp);
1836 ++cp;
1837 /* Remaining padding is
1838 * post-dp.
1839 */
1840 while (pad_len-- > 0) {
1841 OUTC('0');
1842 }
1843 }
1844 while (isdigit((unsigned char)*cp) != 0) {
1845 OUTC(*cp);
1846 ++cp;
1847 }
1848 }
1849
1850 pad_len = conv->pad0_pre_exp;
1851 while (pad_len-- > 0) {
1852 OUTC('0');
1853 }
1854
1855 OUTS(cp, bpe);
1856 } else {
1857 if ((conv->altform_0c | conv->altform_0) != 0) {
1858 OUTC('0');
1859 }
1860
1861 if (conv->altform_0c) {
1862 OUTC(conv->specifier);
1863 }
1864
1865 pad_len = conv->pad0_value;
1866 while (pad_len-- > 0) {
1867 OUTC('0');
1868 }
1869
1870 OUTS(bps, bpe);
1871 }
1872
1873 /* Finish left justification */
1874 while (width > 0) {
1875 OUTC(' ');
1876 --width;
1877 }
1878 }
1879
1880 return count;
1881 #undef OUTS
1882 #undef OUTC
1883 }
1884