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