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