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
520 switch (conv->specifier) {
521 case SINT_CONV_CASES:
522 conv->specifier_cat = SPECIFIER_SINT;
523 goto int_conv;
524 case UINT_CONV_CASES:
525 conv->specifier_cat = SPECIFIER_UINT;
526 int_conv:
527 /* L length specifier not acceptable */
528 if (conv->length_mod == LENGTH_UPPER_L) {
529 conv->invalid = true;
530 }
531
532 /* For c LENGTH_NONE and LENGTH_L would be ok,
533 * but we don't support formatting wide characters.
534 */
535 if (conv->specifier == 'c') {
536 unsupported = (conv->length_mod != LENGTH_NONE);
537 } else if (!IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)) {
538 /* Disable conversion that might produce truncated
539 * results with buffers sized for 32 bits.
540 */
541 switch (conv->length_mod) {
542 case LENGTH_L:
543 unsupported = sizeof(long) > 4;
544 break;
545 case LENGTH_LL:
546 unsupported = sizeof(long long) > 4;
547 break;
548 case LENGTH_J:
549 unsupported = sizeof(uintmax_t) > 4;
550 break;
551 case LENGTH_Z:
552 unsupported = sizeof(size_t) > 4;
553 break;
554 case LENGTH_T:
555 unsupported = sizeof(ptrdiff_t) > 4;
556 break;
557 default:
558 /* Add an empty default with break, this is a defensive
559 * programming. Static analysis tool won't raise a violation
560 * if default is empty, but has that comment.
561 */
562 break;
563 }
564 } else {
565 ;
566 }
567 break;
568
569 case FP_CONV_CASES:
570 conv->specifier_cat = SPECIFIER_FP;
571
572 /* Don't support if disabled */
573 if (!IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) {
574 unsupported = true;
575 break;
576 }
577
578 /* When FP enabled %a support is still conditional. */
579 conv->specifier_a = (conv->specifier == 'a')
580 || (conv->specifier == 'A');
581 if (conv->specifier_a
582 && !IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)) {
583 unsupported = true;
584 break;
585 }
586
587 /* The l specifier has no effect. Otherwise length
588 * modifiers other than L are invalid.
589 */
590 if (conv->length_mod == LENGTH_L) {
591 conv->length_mod = LENGTH_NONE;
592 } else if ((conv->length_mod != LENGTH_NONE)
593 && (conv->length_mod != LENGTH_UPPER_L)) {
594 conv->invalid = true;
595 } else {
596 ;
597 }
598
599 break;
600
601 /* PTR cases are distinct */
602 case 'n':
603 conv->specifier_cat = SPECIFIER_PTR;
604 /* Anything except L */
605 if (conv->length_mod == LENGTH_UPPER_L) {
606 unsupported = true;
607 }
608 break;
609
610 case 's':
611 case 'p':
612 conv->specifier_cat = SPECIFIER_PTR;
613
614 /* p: only LENGTH_NONE
615 *
616 * s: LENGTH_NONE or LENGTH_L but wide
617 * characters not supported.
618 */
619 if (conv->length_mod != LENGTH_NONE) {
620 unsupported = true;
621 }
622 break;
623
624 default:
625 conv->invalid = true;
626 break;
627 }
628
629 conv->unsupported |= unsupported;
630
631 return sp;
632 }
633
634 /* Extract the complete C99 conversion specification.
635 *
636 * @param conv pointer to the conversion being defined.
637 *
638 * @param sp pointer to the % that introduces a conversion specification.
639 *
640 * @return pointer to the first character that follows the specification.
641 */
extract_conversion(struct conversion * conv,const char * sp)642 static inline const char *extract_conversion(struct conversion *conv,
643 const char *sp)
644 {
645 *conv = (struct conversion) {
646 .invalid = false,
647 };
648
649 /* Skip over the opening %. If the conversion specifier is %,
650 * that's the only thing that should be there, so
651 * fast-exit.
652 */
653 ++sp;
654 if (*sp == '%') {
655 conv->specifier = *sp++;
656 return sp;
657 }
658
659 sp = extract_flags(conv, sp);
660 sp = extract_width(conv, sp);
661 sp = extract_prec(conv, sp);
662 sp = extract_length(conv, sp);
663 sp = extract_specifier(conv, sp);
664
665 return sp;
666 }
667
668 #ifdef CONFIG_64BIT
669
_ldiv5(uint64_t * v)670 static void _ldiv5(uint64_t *v)
671 {
672 /* The compiler can optimize this on its own on 64-bit architectures */
673 *v /= 5U;
674 }
675
676 #else /* CONFIG_64BIT */
677
678 /*
679 * Tiny integer divide-by-five routine. The full 64 bit division
680 * implementations in libgcc are very large on some architectures, and
681 * currently nothing in Zephyr pulls it into the link. So it makes
682 * sense to define this much smaller special case here to avoid
683 * including it just for printf.
684 *
685 * It works by multiplying v by the reciprocal of 5 i.e.:
686 *
687 * result = v * ((1 << 64) / 5) / (1 << 64)
688 *
689 * This produces a 128-bit result, but we drop the bottom 64 bits which
690 * accounts for the division by (1 << 64). The product is kept to 64 bits
691 * by summing partial multiplications and shifting right by 32 which on
692 * most 32-bit architectures means only a register drop.
693 *
694 * Here the multiplier is: (1 << 64) / 5 = 0x3333333333333333
695 * i.e. a 62 bits value. To compensate for the reduced precision, we
696 * add an initial bias of 1 to v. This conveniently allows for keeping
697 * the multiplier in a single 32-bit register given its pattern.
698 * Enlarging the multiplier to 64 bits would also work but carry handling
699 * on the summing of partial mults would be necessary, and a final right
700 * shift would be needed, requiring more instructions.
701 */
_ldiv5(uint64_t * v)702 static void _ldiv5(uint64_t *v)
703 {
704 uint32_t v_lo = *v;
705 uint32_t v_hi = *v >> 32;
706 uint32_t m = 0x33333333;
707 uint64_t result;
708
709 /*
710 * Force the multiplier constant into a register and make it
711 * opaque to the compiler, otherwise gcc tries to be too smart
712 * for its own good with a large expansion of adds and shifts.
713 */
714 __asm__ ("" : "+r" (m));
715
716 /*
717 * Apply a bias of 1 to v. We can't add it to v as this would overflow
718 * it when at max range. Factor it out with the multiplier upfront.
719 */
720 result = ((uint64_t)m << 32) | m;
721
722 /* The actual multiplication. */
723 result += (uint64_t)v_lo * m;
724 result >>= 32;
725 result += (uint64_t)v_lo * m;
726 result += (uint64_t)v_hi * m;
727 result >>= 32;
728 result += (uint64_t)v_hi * m;
729
730 *v = result;
731 }
732
733 #endif /* CONFIG_64BIT */
734
735 /* Division by 10 */
_ldiv10(uint64_t * v)736 static void _ldiv10(uint64_t *v)
737 {
738 *v >>= 1;
739 _ldiv5(v);
740 }
741
742 /* Extract the next decimal character in the converted representation of a
743 * fractional component.
744 */
_get_digit(uint64_t * fr,int * digit_count)745 static char _get_digit(uint64_t *fr, int *digit_count)
746 {
747 char rval;
748
749 if (*digit_count > 0) {
750 --*digit_count;
751 *fr *= 10U;
752 rval = ((*fr >> 60) & 0xF) + '0';
753 *fr &= (BIT64(60) - 1U);
754 } else {
755 rval = '0';
756 }
757
758 return rval;
759 }
760
conversion_radix(char specifier)761 static inline size_t conversion_radix(char specifier)
762 {
763 switch (specifier) {
764 default:
765 case 'd':
766 case 'i':
767 case 'u':
768 return 10;
769 case 'o':
770 return 8;
771 case 'p':
772 case 'x':
773 case 'X':
774 return 16;
775 }
776 }
777
778 /* Writes the given value into the buffer in the specified base.
779 *
780 * Precision is applied *ONLY* within the space allowed.
781 *
782 * Alternate form value is applied to o, x, and X conversions.
783 *
784 * The buffer is filled backwards, so the input bpe is the end of the
785 * generated representation. The returned pointer is to the first
786 * character of the representation.
787 */
encode_uint(uint_value_type value,struct conversion * conv,char * bps,const char * bpe)788 static char *encode_uint(uint_value_type value,
789 struct conversion *conv,
790 char *bps,
791 const char *bpe)
792 {
793 bool upcase = isupper((int)conv->specifier) != 0;
794 const unsigned int radix = conversion_radix(conv->specifier);
795 char *bp = bps + (bpe - bps);
796
797 do {
798 unsigned int lsv = (unsigned int)(value % radix);
799
800 *--bp = (lsv <= 9) ? ('0' + lsv)
801 : upcase ? ('A' + lsv - 10) : ('a' + lsv - 10);
802 value /= radix;
803 } while ((value != 0) && (bps < bp));
804
805 /* Record required alternate forms. This can be determined
806 * from the radix without re-checking specifier.
807 */
808 if (conv->flag_hash) {
809 if (radix == 8) {
810 conv->altform_0 = true;
811 } else if (radix == 16) {
812 conv->altform_0c = true;
813 } else {
814 ;
815 }
816 }
817
818 return bp;
819 }
820
821 /* Number of bits in the fractional part of an IEEE 754-2008 double
822 * precision float.
823 */
824 #define FRACTION_BITS 52
825
826 /* Number of hex "digits" in the fractional part of an IEEE 754-2008
827 * double precision float.
828 */
829 #define FRACTION_HEX DIV_ROUND_UP(FRACTION_BITS, 4)
830
831 /* Number of bits in the exponent of an IEEE 754-2008 double precision
832 * float.
833 */
834 #define EXPONENT_BITS 11
835
836 /* Mask for the sign (negative) bit of an IEEE 754-2008 double precision
837 * float.
838 */
839 #define SIGN_MASK BIT64(63)
840
841 /* Mask for the high-bit of a uint64_t representation of a fractional
842 * value.
843 */
844 #define BIT_63 BIT64(63)
845
846 /* Convert the IEEE 754-2008 double to text format.
847 *
848 * @param value the 64-bit floating point value.
849 *
850 * @param conv details about how the conversion is to proceed. Some fields
851 * are adjusted based on the value being converted.
852 *
853 * @param precision the precision for the conversion (generally digits past
854 * the decimal point).
855 *
856 * @param bps pointer to the first character in a buffer that will hold the
857 * converted value.
858 *
859 * @param bpe On entry this points to the end of the buffer reserved to hold
860 * the converted value. On exit it is updated to point just past the
861 * converted value.
862 *
863 * return a pointer to the start of the converted value. This may not be @p
864 * bps but will be consistent with the exit value of *bpe.
865 */
encode_float(double value,struct conversion * conv,int precision,char * sign,char * bps,const char ** bpe)866 static char *encode_float(double value,
867 struct conversion *conv,
868 int precision,
869 char *sign,
870 char *bps,
871 const char **bpe)
872 {
873 union {
874 uint64_t u64;
875 double dbl;
876 } u = {
877 .dbl = value,
878 };
879 bool prune_zero = false;
880 char *buf = bps;
881
882 /* Prepend the sign: '-' if negative, flags control
883 * non-negative behavior.
884 */
885 if ((u.u64 & SIGN_MASK) != 0U) {
886 *sign = '-';
887 } else if (conv->flag_plus) {
888 *sign = '+';
889 } else if (conv->flag_space) {
890 *sign = ' ';
891 } else {
892 ;
893 }
894
895 /* Extract the non-negative offset exponent and fraction. Record
896 * whether the value is subnormal.
897 */
898 char c = conv->specifier;
899 int expo = (u.u64 >> FRACTION_BITS) & BIT_MASK(EXPONENT_BITS);
900 uint64_t fract = u.u64 & BIT64_MASK(FRACTION_BITS);
901 bool is_subnormal = (expo == 0) && (fract != 0);
902
903 /* Exponent of all-ones signals infinity or NaN, which are
904 * text constants regardless of specifier.
905 */
906 if (expo == BIT_MASK(EXPONENT_BITS)) {
907 if (fract == 0) {
908 if (isupper((unsigned char)c) != 0) {
909 *buf++ = 'I';
910 *buf++ = 'N';
911 *buf++ = 'F';
912 } else {
913 *buf++ = 'i';
914 *buf++ = 'n';
915 *buf++ = 'f';
916 }
917 } else {
918 if (isupper((unsigned char)c) != 0) {
919 *buf++ = 'N';
920 *buf++ = 'A';
921 *buf++ = 'N';
922 } else {
923 *buf++ = 'n';
924 *buf++ = 'a';
925 *buf++ = 'n';
926 }
927 }
928
929 /* No zero-padding with text values */
930 conv->flag_zero = false;
931
932 *bpe = buf;
933 return bps;
934 }
935
936 /* The case of an F specifier is no longer relevant. */
937 if (c == 'F') {
938 c = 'f';
939 }
940
941 /* Handle converting to the hex representation. */
942 if (IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)
943 && (IS_ENABLED(CONFIG_CBPRINTF_FP_ALWAYS_A)
944 || conv->specifier_a)) {
945 *buf++ = '0';
946 *buf++ = 'x';
947
948 /* Remove the offset from the exponent, and store the
949 * non-fractional value. Subnormals require increasing the
950 * exponent as first bit isn't the implicit bit.
951 */
952 expo -= 1023;
953 if (is_subnormal) {
954 *buf++ = '0';
955 ++expo;
956 } else {
957 *buf++ = '1';
958 }
959
960 /* If we didn't get precision from a %a specification then we
961 * treat it as from a %a specification with no precision: full
962 * range, zero-pruning enabled.
963 *
964 * Otherwise we have to cap the precision of the generated
965 * fraction, or possibly round it.
966 */
967 if (!(conv->specifier_a && conv->prec_present)) {
968 precision = FRACTION_HEX;
969 prune_zero = true;
970 } else if (precision > FRACTION_HEX) {
971 conv->pad0_pre_exp = precision - FRACTION_HEX;
972 conv->pad_fp = true;
973 precision = FRACTION_HEX;
974 } else if ((fract != 0)
975 && (precision < FRACTION_HEX)) {
976 size_t pos = 4 * (FRACTION_HEX - precision) - 1;
977 uint64_t mask = BIT64(pos);
978
979 /* Round only if the bit that would round is
980 * set.
981 */
982 if (fract & mask) {
983 fract += mask;
984 }
985 }
986
987 /* Record whether we must retain the decimal point even if we
988 * can prune zeros.
989 */
990 bool require_dp = ((fract != 0) || conv->flag_hash);
991
992 if (require_dp || (precision != 0)) {
993 *buf++ = '.';
994 }
995
996 /* Get the fractional value as a hexadecimal string, using x
997 * for a and X for A.
998 */
999 struct conversion aconv = {
1000 .specifier = isupper((unsigned char)c) != 0 ? 'X' : 'x',
1001 };
1002 const char *spe = *bpe;
1003 char *sp = bps + (spe - bps);
1004
1005 if (fract != 0) {
1006 sp = encode_uint(fract, &aconv, buf, spe);
1007 }
1008
1009 /* Pad out to full range since this is below the decimal
1010 * point.
1011 */
1012 while ((spe - sp) < FRACTION_HEX) {
1013 *--sp = '0';
1014 }
1015
1016 /* Append the leading significant "digits". */
1017 while ((sp < spe) && (precision > 0)) {
1018 *buf++ = *sp++;
1019 --precision;
1020 }
1021
1022 if (prune_zero) {
1023 while (*--buf == '0') {
1024 ;
1025 }
1026 if ((*buf != '.') || require_dp) {
1027 ++buf;
1028 }
1029 }
1030
1031 *buf++ = 'p';
1032 if (expo >= 0) {
1033 *buf++ = '+';
1034 } else {
1035 *buf++ = '-';
1036 expo = -expo;
1037 }
1038
1039 aconv.specifier = 'i';
1040 sp = encode_uint(expo, &aconv, buf, spe);
1041
1042 while (sp < spe) {
1043 *buf++ = *sp++;
1044 }
1045
1046 *bpe = buf;
1047 return bps;
1048 }
1049
1050 /* Remainder of code operates on a 64-bit fraction, so shift up (and
1051 * discard garbage from the exponent where the implicit 1 would be
1052 * stored).
1053 */
1054 fract <<= EXPONENT_BITS;
1055 fract &= ~SIGN_MASK;
1056
1057 /* Non-zero values need normalization. */
1058 if ((expo | fract) != 0) {
1059 if (is_subnormal) {
1060 /* Fraction is subnormal. Normalize it and correct
1061 * the exponent.
1062 */
1063 while (((fract <<= 1) & BIT_63) == 0) {
1064 expo--;
1065 }
1066 }
1067 /* Adjust the offset exponent to be signed rather than offset,
1068 * and set the implicit 1 bit in the (shifted) 53-bit
1069 * fraction.
1070 */
1071 expo -= (1023 - 1); /* +1 since .1 vs 1. */
1072 fract |= BIT_63;
1073 }
1074
1075 /*
1076 * Let's consider:
1077 *
1078 * value = fract * 2^expo * 10^decexp
1079 *
1080 * Initially decexp = 0. The goal is to bring exp between
1081 * 0 and -2 as the magnitude of a fractional decimal digit is 3 bits.
1082 */
1083 int decexp = 0;
1084
1085 while (expo < -2) {
1086 /*
1087 * Make room to allow a multiplication by 5 without overflow.
1088 * We test only the top part for faster code.
1089 */
1090 do {
1091 fract >>= 1;
1092 expo++;
1093 } while ((uint32_t)(fract >> 32) >= (UINT32_MAX / 5U));
1094
1095 /* Perform fract * 5 * 2 / 10 */
1096 fract *= 5U;
1097 expo++;
1098 decexp--;
1099 }
1100
1101 while (expo > 0) {
1102 /*
1103 * Perform fract / 5 / 2 * 10.
1104 * The +2 is there to do round the result of the division
1105 * by 5 not to lose too much precision in extreme cases.
1106 */
1107 fract += 2;
1108 _ldiv5(&fract);
1109 expo--;
1110 decexp++;
1111
1112 /* Bring back our fractional number to full scale */
1113 do {
1114 fract <<= 1;
1115 expo--;
1116 } while (!(fract & BIT_63));
1117 }
1118
1119 /*
1120 * The binary fractional point is located somewhere above bit 63.
1121 * Move it between bits 59 and 60 to give 4 bits of room to the
1122 * integer part.
1123 */
1124 fract >>= (4 - expo);
1125
1126 if ((c == 'g') || (c == 'G')) {
1127 /* Use the specified precision and exponent to select the
1128 * representation and correct the precision and zero-pruning
1129 * in accordance with the ISO C rule.
1130 */
1131 if (decexp < (-4 + 1) || decexp > precision) {
1132 c += 'e' - 'g'; /* e or E */
1133 if (precision > 0) {
1134 precision--;
1135 }
1136 } else {
1137 c = 'f';
1138 precision -= decexp;
1139 }
1140 if (!conv->flag_hash && (precision > 0)) {
1141 prune_zero = true;
1142 }
1143 }
1144
1145 int decimals;
1146 if (c == 'f') {
1147 decimals = precision + decexp;
1148 if (decimals < 0) {
1149 decimals = 0;
1150 }
1151 } else {
1152 decimals = precision + 1;
1153 }
1154
1155 int digit_count = 16;
1156
1157 if (decimals > 16) {
1158 decimals = 16;
1159 }
1160
1161 /* Round the value to the last digit being printed. */
1162 uint64_t round = BIT64(59); /* 0.5 */
1163 while (decimals--) {
1164 _ldiv10(&round);
1165 }
1166 fract += round;
1167 /* Make sure rounding didn't make fract >= 1.0 */
1168 if (fract >= BIT64(60)) {
1169 _ldiv10(&fract);
1170 decexp++;
1171 }
1172
1173 if (c == 'f') {
1174 if (decexp > 0) {
1175 /* Emit the digits above the decimal point. */
1176 while (decexp > 0 && digit_count > 0) {
1177 *buf++ = _get_digit(&fract, &digit_count);
1178 decexp--;
1179 }
1180
1181 conv->pad0_value = decexp;
1182
1183 decexp = 0;
1184 } else {
1185 *buf++ = '0';
1186 }
1187
1188 /* Emit the decimal point only if required by the alternative
1189 * format, or if more digits are to follow.
1190 */
1191 if (conv->flag_hash || (precision > 0)) {
1192 *buf++ = '.';
1193 }
1194
1195 if (decexp < 0 && precision > 0) {
1196 conv->pad0_value = -decexp;
1197 if (conv->pad0_value > precision) {
1198 conv->pad0_value = precision;
1199 }
1200
1201 precision -= conv->pad0_value;
1202 conv->pad_postdp = (conv->pad0_value > 0);
1203 }
1204 } else { /* e or E */
1205 /* Emit the one digit before the decimal. If it's not zero,
1206 * this is significant so reduce the base-10 exponent.
1207 */
1208 *buf = _get_digit(&fract, &digit_count);
1209 if (*buf++ != '0') {
1210 decexp--;
1211 }
1212
1213 /* Emit the decimal point only if required by the alternative
1214 * format, or if more digits are to follow.
1215 */
1216 if (conv->flag_hash || (precision > 0)) {
1217 *buf++ = '.';
1218 }
1219 }
1220
1221 while (precision > 0 && digit_count > 0) {
1222 *buf++ = _get_digit(&fract, &digit_count);
1223 precision--;
1224 }
1225
1226 conv->pad0_pre_exp = precision;
1227
1228 if (prune_zero) {
1229 conv->pad0_pre_exp = 0;
1230 while (*--buf == '0') {
1231 ;
1232 }
1233 if (*buf != '.') {
1234 buf++;
1235 }
1236 }
1237
1238 /* Emit the explicit exponent, if format requires it. */
1239 if ((c == 'e') || (c == 'E')) {
1240 *buf++ = c;
1241 if (decexp < 0) {
1242 decexp = -decexp;
1243 *buf++ = '-';
1244 } else {
1245 *buf++ = '+';
1246 }
1247
1248 /* At most 3 digits to the decimal. Spit them out. */
1249 if (decexp >= 100) {
1250 *buf++ = (decexp / 100) + '0';
1251 decexp %= 100;
1252 }
1253
1254 *buf++ = (decexp / 10) + '0';
1255 *buf++ = (decexp % 10) + '0';
1256 }
1257
1258 /* Cache whether there's padding required */
1259 conv->pad_fp = (conv->pad0_value > 0)
1260 || (conv->pad0_pre_exp > 0);
1261
1262 /* Set the end of the encoded sequence, and return its start. Also
1263 * store EOS as a non-digit/non-decimal value so we don't have to
1264 * check against bpe when iterating in multiple places.
1265 */
1266 *bpe = buf;
1267 *buf = 0;
1268 return bps;
1269 }
1270
1271 /* Store a count into the pointer provided in a %n specifier.
1272 *
1273 * @param conv the specifier that indicates the size of the value into which
1274 * the count will be stored.
1275 *
1276 * @param dp where the count should be stored.
1277 *
1278 * @param count the count to be stored.
1279 */
store_count(const struct conversion * conv,void * dp,int count)1280 static inline void store_count(const struct conversion *conv,
1281 void *dp,
1282 int count)
1283 {
1284 switch ((enum length_mod_enum)conv->length_mod) {
1285 case LENGTH_NONE:
1286 *(int *)dp = count;
1287 break;
1288 case LENGTH_HH:
1289 *(signed char *)dp = (signed char)count;
1290 break;
1291 case LENGTH_H:
1292 *(short *)dp = (short)count;
1293 break;
1294 case LENGTH_L:
1295 *(long *)dp = (long)count;
1296 break;
1297 case LENGTH_LL:
1298 *(long long *)dp = (long long)count;
1299 break;
1300 case LENGTH_J:
1301 *(intmax_t *)dp = (intmax_t)count;
1302 break;
1303 case LENGTH_Z:
1304 *(size_t *)dp = (size_t)count;
1305 break;
1306 case LENGTH_T:
1307 *(ptrdiff_t *)dp = (ptrdiff_t)count;
1308 break;
1309 default:
1310 /* Add an empty default with break, this is a defensive programming.
1311 * Static analysis tool won't raise a violation if default is empty,
1312 * but has that comment.
1313 */
1314 break;
1315 }
1316 }
1317
1318 /* Outline function to emit all characters in [sp, ep). */
outs(cbprintf_cb out,void * ctx,const char * sp,const char * ep)1319 static int outs(cbprintf_cb out,
1320 void *ctx,
1321 const char *sp,
1322 const char *ep)
1323 {
1324 size_t count = 0;
1325
1326 while ((sp < ep) || ((ep == NULL) && *sp)) {
1327 int rc = out((int)*sp++, ctx);
1328
1329 if (rc < 0) {
1330 return rc;
1331 }
1332 ++count;
1333 }
1334
1335 return (int)count;
1336 }
1337
z_cbvprintf_impl(cbprintf_cb out,void * ctx,const char * fp,va_list ap,uint32_t flags)1338 int z_cbvprintf_impl(cbprintf_cb out, void *ctx, const char *fp,
1339 va_list ap, uint32_t flags)
1340 {
1341 char buf[CONVERTED_BUFLEN];
1342 size_t count = 0;
1343 sint_value_type sint;
1344
1345 const bool tagged_ap = (flags & Z_CBVPRINTF_PROCESS_FLAG_TAGGED_ARGS)
1346 == Z_CBVPRINTF_PROCESS_FLAG_TAGGED_ARGS;
1347
1348 /* Output character, returning EOF if output failed, otherwise
1349 * updating count.
1350 *
1351 * NB: c is evaluated exactly once: side-effects are OK
1352 */
1353 #define OUTC(c) do { \
1354 int rc = (*out)((int)(c), ctx); \
1355 \
1356 if (rc < 0) { \
1357 return rc; \
1358 } \
1359 ++count; \
1360 } while (false)
1361
1362 /* Output sequence of characters, returning a negative error if output
1363 * failed.
1364 */
1365
1366 #define OUTS(_sp, _ep) do { \
1367 int rc = outs(out, ctx, _sp, _ep); \
1368 \
1369 if (rc < 0) { \
1370 return rc; \
1371 } \
1372 count += rc; \
1373 } while (false)
1374
1375 while (*fp != 0) {
1376 if (*fp != '%') {
1377 OUTC(*fp++);
1378 continue;
1379 }
1380
1381 /* Force union into RAM with conversion state to
1382 * mitigate LLVM code generation bug.
1383 */
1384 struct {
1385 union argument_value value;
1386 struct conversion conv;
1387 } state = {
1388 .value = {
1389 .uint = 0,
1390 },
1391 };
1392 struct conversion *const conv = &state.conv;
1393 union argument_value *const value = &state.value;
1394 const char *sp = fp;
1395 int width = -1;
1396 int precision = -1;
1397 const char *bps = NULL;
1398 const char *bpe = buf + sizeof(buf);
1399 char sign = 0;
1400
1401 fp = extract_conversion(conv, sp);
1402
1403 if (conv->specifier_cat != SPECIFIER_INVALID) {
1404 if (IS_ENABLED(CONFIG_CBPRINTF_PACKAGE_SUPPORT_TAGGED_ARGUMENTS)
1405 && tagged_ap) {
1406 /* Skip over the argument tag as it is not being
1407 * used here.
1408 */
1409 (void)va_arg(ap, int);
1410 }
1411 }
1412
1413 /* If dynamic width is specified, process it,
1414 * otherwise set width if present.
1415 */
1416 if (conv->width_star) {
1417 width = va_arg(ap, int);
1418
1419 if (width < 0) {
1420 conv->flag_dash = true;
1421 width = -width;
1422 }
1423 } else if (conv->width_present) {
1424 width = conv->width_value;
1425 } else {
1426 ;
1427 }
1428
1429 /* If dynamic precision is specified, process it, otherwise
1430 * set precision if present. For floating point where
1431 * precision is not present use 6.
1432 */
1433 if (conv->prec_star) {
1434 int arg = va_arg(ap, int);
1435
1436 if (arg < 0) {
1437 conv->prec_present = false;
1438 } else {
1439 precision = arg;
1440 }
1441 } else if (conv->prec_present) {
1442 precision = conv->prec_value;
1443 } else {
1444 ;
1445 }
1446
1447 /* Reuse width and precision memory in conv for value
1448 * padding counts.
1449 */
1450 conv->pad0_value = 0;
1451 conv->pad0_pre_exp = 0;
1452
1453 /* FP conversion requires knowing the precision. */
1454 if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)
1455 && (conv->specifier_cat == SPECIFIER_FP)
1456 && !conv->prec_present) {
1457 if (conv->specifier_a) {
1458 precision = FRACTION_HEX;
1459 } else {
1460 precision = 6;
1461 }
1462 }
1463
1464 /* Get the value to be converted from the args.
1465 *
1466 * This can't be extracted to a helper function because
1467 * passing a pointer to va_list doesn't work on x86_64. See
1468 * https://stackoverflow.com/a/8048892.
1469 */
1470 enum specifier_cat_enum specifier_cat
1471 = (enum specifier_cat_enum)conv->specifier_cat;
1472 enum length_mod_enum length_mod
1473 = (enum length_mod_enum)conv->length_mod;
1474
1475 /* Extract the value based on the argument category and length.
1476 *
1477 * Note that the length modifier doesn't affect the value of a
1478 * pointer argument.
1479 */
1480 if (specifier_cat == SPECIFIER_SINT) {
1481 switch (length_mod) {
1482 default:
1483 case LENGTH_NONE:
1484 case LENGTH_HH:
1485 case LENGTH_H:
1486 value->sint = va_arg(ap, int);
1487 break;
1488 case LENGTH_L:
1489 if (WCHAR_IS_SIGNED
1490 && (conv->specifier == 'c')) {
1491 value->sint = (wchar_t)va_arg(ap,
1492 WINT_TYPE);
1493 } else {
1494 value->sint = va_arg(ap, long);
1495 }
1496 break;
1497 case LENGTH_LL:
1498 value->sint =
1499 (sint_value_type)va_arg(ap, long long);
1500 break;
1501 case LENGTH_J:
1502 value->sint =
1503 (sint_value_type)va_arg(ap, intmax_t);
1504 break;
1505 case LENGTH_Z: /* size_t */
1506 case LENGTH_T: /* ptrdiff_t */
1507 /* Though ssize_t is the signed equivalent of
1508 * size_t for POSIX, there is no uptrdiff_t.
1509 * Assume that size_t and ptrdiff_t are the
1510 * unsigned and signed equivalents of each
1511 * other. This can be checked in a platform
1512 * test.
1513 */
1514 value->sint =
1515 (sint_value_type)va_arg(ap, ptrdiff_t);
1516 break;
1517 }
1518 if (length_mod == LENGTH_HH) {
1519 value->sint = (signed char)value->sint;
1520 } else if (length_mod == LENGTH_H) {
1521 value->sint = (short)value->sint;
1522 }
1523 } else if (specifier_cat == SPECIFIER_UINT) {
1524 switch (length_mod) {
1525 default:
1526 case LENGTH_NONE:
1527 case LENGTH_HH:
1528 case LENGTH_H:
1529 value->uint = va_arg(ap, unsigned int);
1530 break;
1531 case LENGTH_L:
1532 if ((!WCHAR_IS_SIGNED)
1533 && (conv->specifier == 'c')) {
1534 value->uint = (wchar_t)va_arg(ap,
1535 WINT_TYPE);
1536 } else {
1537 value->uint = va_arg(ap, unsigned long);
1538 }
1539 break;
1540 case LENGTH_LL:
1541 value->uint =
1542 (uint_value_type)va_arg(ap,
1543 unsigned long long);
1544 break;
1545 case LENGTH_J:
1546 value->uint =
1547 (uint_value_type)va_arg(ap,
1548 uintmax_t);
1549 break;
1550 case LENGTH_Z: /* size_t */
1551 case LENGTH_T: /* ptrdiff_t */
1552 value->uint =
1553 (uint_value_type)va_arg(ap, size_t);
1554 break;
1555 }
1556 if (length_mod == LENGTH_HH) {
1557 value->uint = (unsigned char)value->uint;
1558 } else if (length_mod == LENGTH_H) {
1559 value->uint = (unsigned short)value->uint;
1560 }
1561 } else if (specifier_cat == SPECIFIER_FP) {
1562 if (length_mod == LENGTH_UPPER_L) {
1563 value->ldbl = va_arg(ap, long double);
1564 } else {
1565 value->dbl = va_arg(ap, double);
1566 }
1567 } else if (specifier_cat == SPECIFIER_PTR) {
1568 value->ptr = va_arg(ap, void *);
1569 }
1570
1571 /* We've now consumed all arguments related to this
1572 * specification. If the conversion is invalid, or is
1573 * something we don't support, then output the original
1574 * specification and move on.
1575 */
1576 if (conv->invalid || conv->unsupported) {
1577 OUTS(sp, fp);
1578 continue;
1579 }
1580
1581 /* Do formatting, either into the buffer or
1582 * referencing external data.
1583 */
1584 switch (conv->specifier) {
1585 case '%':
1586 OUTC('%');
1587 break;
1588 case 's': {
1589 bps = (const char *)value->ptr;
1590
1591 size_t len;
1592
1593 if (precision >= 0) {
1594 len = strnlen(bps, precision);
1595 } else {
1596 len = strlen(bps);
1597 }
1598
1599 bpe = bps + len;
1600 precision = -1;
1601
1602 break;
1603 }
1604 case 'c':
1605 bps = buf;
1606 buf[0] = CHAR_IS_SIGNED ? value->sint : value->uint;
1607 bpe = buf + 1;
1608 break;
1609 case 'd':
1610 case 'i':
1611 if (conv->flag_plus) {
1612 sign = '+';
1613 } else if (conv->flag_space) {
1614 sign = ' ';
1615 }
1616
1617 /* sint/uint overlay in the union, and so
1618 * can't appear in read and write operations
1619 * in the same statement.
1620 */
1621 sint = value->sint;
1622 if (sint < 0) {
1623 sign = '-';
1624 value->uint = (uint_value_type)-sint;
1625 } else {
1626 value->uint = (uint_value_type)sint;
1627 }
1628
1629 __fallthrough;
1630 case 'o':
1631 case 'u':
1632 case 'x':
1633 case 'X':
1634 bps = encode_uint(value->uint, conv, buf, bpe);
1635
1636 prec_int_pad0:
1637 /* Update pad0 values based on precision and converted
1638 * length. Note that a non-empty sign is not in the
1639 * converted sequence, but it does not affect the
1640 * padding size.
1641 */
1642 if (precision >= 0) {
1643 size_t len = bpe - bps;
1644
1645 /* Zero-padding flag is ignored for integer
1646 * conversions with precision.
1647 */
1648 conv->flag_zero = false;
1649
1650 /* Set pad0_value to satisfy precision */
1651 if (len < (size_t)precision) {
1652 conv->pad0_value = precision - (int)len;
1653 }
1654 }
1655
1656 break;
1657 case 'p':
1658 /* Implementation-defined: null is "(nil)", non-null
1659 * has 0x prefix followed by significant address hex
1660 * digits, no leading zeros.
1661 */
1662 if (value->ptr != NULL) {
1663 bps = encode_uint((uintptr_t)value->ptr, conv,
1664 buf, bpe);
1665
1666 /* Use 0x prefix */
1667 conv->altform_0c = true;
1668 conv->specifier = 'x';
1669
1670 goto prec_int_pad0;
1671 }
1672
1673 bps = "(nil)";
1674 bpe = bps + 5;
1675
1676 break;
1677 case 'n':
1678 if (IS_ENABLED(CONFIG_CBPRINTF_N_SPECIFIER)) {
1679 store_count(conv, value->ptr, count);
1680 }
1681
1682 break;
1683
1684 case FP_CONV_CASES:
1685 if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) {
1686 bps = encode_float(value->dbl, conv, precision,
1687 &sign, buf, &bpe);
1688 }
1689 break;
1690 default:
1691 /* Add an empty default with break, this is a defensive
1692 * programming. Static analysis tool won't raise a violation
1693 * if default is empty, but has that comment.
1694 */
1695 break;
1696 }
1697
1698 /* If we don't have a converted value to emit, move
1699 * on.
1700 */
1701 if (bps == NULL) {
1702 continue;
1703 }
1704
1705 /* The converted value is now stored in [bps, bpe), excluding
1706 * any required zero padding.
1707 *
1708 * The unjustified output will be:
1709 *
1710 * * any sign character (sint-only)
1711 * * any altform prefix
1712 * * for FP:
1713 * * any pre-decimal content from the converted value
1714 * * any pad0_value padding (!postdp)
1715 * * any decimal point in the converted value
1716 * * any pad0_value padding (postdp)
1717 * * any pre-exponent content from the converted value
1718 * * any pad0_pre_exp padding
1719 * * any exponent content from the converted value
1720 * * for non-FP:
1721 * * any pad0_prefix
1722 * * the converted value
1723 */
1724 size_t nj_len = (bpe - bps);
1725 int pad_len = 0;
1726
1727 if (sign != 0) {
1728 nj_len += 1U;
1729 }
1730
1731 if (conv->altform_0c) {
1732 nj_len += 2U;
1733 } else if (conv->altform_0) {
1734 nj_len += 1U;
1735 }
1736
1737 nj_len += conv->pad0_value;
1738 if (conv->pad_fp) {
1739 nj_len += conv->pad0_pre_exp;
1740 }
1741
1742 /* If we have a width update width to hold the padding we need
1743 * for justification. The result may be negative, which will
1744 * result in no padding.
1745 *
1746 * If a non-negative padding width is present and we're doing
1747 * right-justification, emit the padding now.
1748 */
1749 if (width > 0) {
1750 width -= (int)nj_len;
1751
1752 if (!conv->flag_dash) {
1753 char pad = ' ';
1754
1755 /* If we're zero-padding we have to emit the
1756 * sign first.
1757 */
1758 if (conv->flag_zero) {
1759 if (sign != 0) {
1760 OUTC(sign);
1761 sign = 0;
1762 }
1763 pad = '0';
1764 }
1765
1766 while (width-- > 0) {
1767 OUTC(pad);
1768 }
1769 }
1770 }
1771
1772 /* If we have a sign that hasn't been emitted, now's the
1773 * time....
1774 */
1775 if (sign != 0) {
1776 OUTC(sign);
1777 }
1778
1779 if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT) && conv->pad_fp) {
1780 const char *cp = bps;
1781
1782 if (conv->specifier_a) {
1783 /* Only padding is pre_exp */
1784 while (*cp != 'p') {
1785 OUTC(*cp++);
1786 }
1787 } else {
1788 while (isdigit((unsigned char)*cp) != 0) {
1789 OUTC(*cp++);
1790 }
1791
1792 pad_len = conv->pad0_value;
1793 if (!conv->pad_postdp) {
1794 while (pad_len-- > 0) {
1795 OUTC('0');
1796 }
1797 }
1798
1799 if (*cp == '.') {
1800 OUTC(*cp++);
1801 /* Remaining padding is
1802 * post-dp.
1803 */
1804 while (pad_len-- > 0) {
1805 OUTC('0');
1806 }
1807 }
1808 while (isdigit((unsigned char)*cp) != 0) {
1809 OUTC(*cp++);
1810 }
1811 }
1812
1813 pad_len = conv->pad0_pre_exp;
1814 while (pad_len-- > 0) {
1815 OUTC('0');
1816 }
1817
1818 OUTS(cp, bpe);
1819 } else {
1820 if (conv->altform_0c | conv->altform_0) {
1821 OUTC('0');
1822 }
1823
1824 if (conv->altform_0c) {
1825 OUTC(conv->specifier);
1826 }
1827
1828 pad_len = conv->pad0_value;
1829 while (pad_len-- > 0) {
1830 OUTC('0');
1831 }
1832
1833 OUTS(bps, bpe);
1834 }
1835
1836 /* Finish left justification */
1837 while (width > 0) {
1838 OUTC(' ');
1839 --width;
1840 }
1841 }
1842
1843 return count;
1844 #undef OUTS
1845 #undef OUTC
1846 }
1847