PS2SDK
PS2 Homebrew Libraries
printf.c
1 
40 #ifdef __cplusplus
41 #include <cstdint>
42 #include <climits>
43 extern "C" {
44 #else
45 #define SYSCLIB_DISABLE_BUILTINS
46 #include <sysclib.h>
47 #include <stdbool.h>
48 #include <stdint.h>
49 #include <limits.h>
50 #endif // __cplusplus
51 
52 // Define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
53 // printf_config.h header file
54 #if PRINTF_INCLUDE_CONFIG_H
55 #include "printf_config.h"
56 #endif
57 
58 #include <stdbool.h>
59 #include <stdint.h>
60 
61 #include "printf.h"
62 
63 #if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
64 # define printf_ printf
65 # define sprintf_ sprintf
66 # define vsprintf_ vsprintf
67 # define snprintf_ snprintf
68 # define vsnprintf_ vsnprintf
69 # define vprintf_ vprintf
70 #endif
71 
72 
73 // 'ntoa' conversion buffer size, this must be big enough to hold one converted
74 // numeric number including padded zeros (dynamically created on stack)
75 #ifndef PRINTF_INTEGER_BUFFER_SIZE
76 #define PRINTF_INTEGER_BUFFER_SIZE 32
77 #endif
78 
79 // size of the fixed (on-stack) buffer for printing individual decimal numbers.
80 // this must be big enough to hold one converted floating-point value including
81 // padded zeros.
82 #ifndef PRINTF_DECIMAL_BUFFER_SIZE
83 #define PRINTF_DECIMAL_BUFFER_SIZE 32
84 #endif
85 
86 // Support for the decimal notation floating point conversion specifiers (%f, %F)
87 #ifndef PRINTF_SUPPORT_DECIMAL_SPECIFIERS
88 #define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 1
89 #endif
90 
91 // Support for the exponential notation floating point conversion specifiers (%e, %g, %E, %G)
92 #ifndef PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
93 #define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 1
94 #endif
95 
96 // Support for the length write-back specifier (%n)
97 #ifndef PRINTF_SUPPORT_WRITEBACK_SPECIFIER
98 #define PRINTF_SUPPORT_WRITEBACK_SPECIFIER 1
99 #endif
100 
101 // Default precision for the floating point conversion specifiers (the C standard sets this at 6)
102 #ifndef PRINTF_DEFAULT_FLOAT_PRECISION
103 #define PRINTF_DEFAULT_FLOAT_PRECISION 6
104 #endif
105 
106 // According to the C languages standard, printf() and related functions must be able to print any
107 // integral number in floating-point notation, regardless of length, when using the %f specifier -
108 // possibly hundreds of characters, potentially overflowing your buffers. In this implementation,
109 // all values beyond this threshold are switched to exponential notation.
110 #ifndef PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL
111 #define PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9
112 #endif
113 
114 // Support for the long long integral types (with the ll, z and t length modifiers for specifiers
115 // %d,%i,%o,%x,%X,%u, and with the %p specifier). Note: 'L' (long double) is not supported.
116 #ifndef PRINTF_SUPPORT_LONG_LONG
117 #define PRINTF_SUPPORT_LONG_LONG 1
118 #endif
119 
120 // The number of terms in a Taylor series expansion of log_10(x) to
121 // use for approximation - including the power-zero term (i.e. the
122 // value at the point of expansion).
123 #ifndef PRINTF_LOG10_TAYLOR_TERMS
124 #define PRINTF_LOG10_TAYLOR_TERMS 4
125 #endif
126 
127 #if PRINTF_LOG10_TAYLOR_TERMS <= 1
128 #error "At least one non-constant Taylor expansion is necessary for the log10() calculation"
129 #endif
130 
131 
132 #define PRINTF_PREFER_DECIMAL false
133 #define PRINTF_PREFER_EXPONENTIAL true
134 
136 
137 // The following will convert the number-of-digits into an exponential-notation literal
138 #define PRINTF_CONCATENATE(s1, s2) s1##s2
139 #define PRINTF_EXPAND_THEN_CONCATENATE(s1, s2) PRINTF_CONCATENATE(s1, s2)
140 #define PRINTF_FLOAT_NOTATION_THRESHOLD PRINTF_EXPAND_THEN_CONCATENATE(1e,PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL)
141 
142 // internal flag definitions
143 #define FLAGS_ZEROPAD (1U << 0U)
144 #define FLAGS_LEFT (1U << 1U)
145 #define FLAGS_PLUS (1U << 2U)
146 #define FLAGS_SPACE (1U << 3U)
147 #define FLAGS_HASH (1U << 4U)
148 #define FLAGS_UPPERCASE (1U << 5U)
149 #define FLAGS_CHAR (1U << 6U)
150 #define FLAGS_SHORT (1U << 7U)
151 #define FLAGS_INT (1U << 8U)
152  // Only used with PRINTF_SUPPORT_MSVC_STYLE_INTEGER_SPECIFIERS
153 #define FLAGS_LONG (1U << 9U)
154 #define FLAGS_LONG_LONG (1U << 10U)
155 #define FLAGS_PRECISION (1U << 11U)
156 #define FLAGS_ADAPT_EXP (1U << 12U)
157 #define FLAGS_POINTER (1U << 13U)
158  // Note: Similar, but not identical, effect as FLAGS_HASH
159 #define FLAGS_SIGNED (1U << 14U)
160  // Only used with PRINTF_SUPPORT_MSVC_STYLE_INTEGER_SPECIFIERS
161 
162 #ifdef PRINTF_SUPPORT_MSVC_STYLE_INTEGER_SPECIFIERS
163 
164 #define FLAGS_INT8 FLAGS_CHAR
165 
166 
167 #if (SHRT_MAX == 32767LL)
168 #define FLAGS_INT16 FLAGS_SHORT
169 #elif (INT_MAX == 32767LL)
170 #define FLAGS_INT16 FLAGS_INT
171 #elif (LONG_MAX == 32767LL)
172 #define FLAGS_INT16 FLAGS_LONG
173 #elif (LLONG_MAX == 32767LL)
174 #define FLAGS_INT16 FLAGS_LONG_LONG
175 #else
176 #error "No basic integer type has a size of 16 bits exactly"
177 #endif
178 
179 #if (SHRT_MAX == 2147483647LL)
180 #define FLAGS_INT32 FLAGS_SHORT
181 #elif (INT_MAX == 2147483647LL)
182 #define FLAGS_INT32 FLAGS_INT
183 #elif (LONG_MAX == 2147483647LL)
184 #define FLAGS_INT32 FLAGS_LONG
185 #elif (LLONG_MAX == 2147483647LL)
186 #define FLAGS_INT32 FLAGS_LONG_LONG
187 #else
188 #error "No basic integer type has a size of 32 bits exactly"
189 #endif
190 
191 #if (SHRT_MAX == 9223372036854775807LL)
192 #define FLAGS_INT64 FLAGS_SHORT
193 #elif (INT_MAX == 9223372036854775807LL)
194 #define FLAGS_INT64 FLAGS_INT
195 #elif (LONG_MAX == 9223372036854775807LL)
196 #define FLAGS_INT64 FLAGS_LONG
197 #elif (LLONG_MAX == 9223372036854775807LL)
198 #define FLAGS_INT64 FLAGS_LONG_LONG
199 #else
200 #error "No basic integer type has a size of 64 bits exactly"
201 #endif
202 
203 #endif // PRINTF_SUPPORT_MSVC_STYLE_INTEGER_SPECIFIERS
204 
205 
206 typedef unsigned int printf_flags_t;
207 
208 #define BASE_BINARY 2
209 #define BASE_OCTAL 8
210 #define BASE_DECIMAL 10
211 #define BASE_HEX 16
212 
213 typedef uint8_t numeric_base_t;
214 
215 #if PRINTF_SUPPORT_LONG_LONG
216 typedef unsigned long long printf_unsigned_value_t;
217 typedef long long printf_signed_value_t;
218 #else
219 typedef unsigned long printf_unsigned_value_t;
220 typedef long printf_signed_value_t;
221 #endif
222 
223 // The printf()-family functions return an `int`; it is therefore
224 // unnecessary/inappropriate to use size_t - often larger than int
225 // in practice - for non-negative related values, such as widths,
226 // precisions, offsets into buffers used for printing and the sizes
227 // of these buffers. instead, we use:
228 typedef unsigned int printf_size_t;
229 #define PRINTF_MAX_POSSIBLE_BUFFER_SIZE INT_MAX
230  // If we were to nitpick, this would actually be INT_MAX + 1,
231  // since INT_MAX is the maximum return value, which excludes the
232  // trailing '\0'.
233 
234 #if (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
235 #include <float.h>
236 #if FLT_RADIX != 2
237 #error "Non-binary-radix floating-point types are unsupported."
238 #endif
239 
240 #if DBL_MANT_DIG == 24
241 
242 #define DOUBLE_SIZE_IN_BITS 32
243 typedef uint32_t double_uint_t;
244 #define DOUBLE_EXPONENT_MASK 0xFFU
245 #define DOUBLE_BASE_EXPONENT 127
246 #define DOUBLE_MAX_SUBNORMAL_EXPONENT_OF_10 -38
247 #define DOUBLE_MAX_SUBNORMAL_POWER_OF_10 1e-38
248 
249 #elif DBL_MANT_DIG == 53
250 
251 #define DOUBLE_SIZE_IN_BITS 64
252 typedef uint64_t double_uint_t;
253 #define DOUBLE_EXPONENT_MASK 0x7FFU
254 #define DOUBLE_BASE_EXPONENT 1023
255 #define DOUBLE_MAX_SUBNORMAL_EXPONENT_OF_10 -308
256 #define DOUBLE_MAX_SUBNORMAL_POWER_OF_10 1e-308
257 
258 #else
259 #error "Unsupported double type configuration"
260 #endif
261 #define DOUBLE_STORED_MANTISSA_BITS (DBL_MANT_DIG - 1)
262 
263 typedef union {
264  double_uint_t U;
265  double F;
267 
268 // This is unnecessary in C99, since compound initializers can be used,
269 // but:
270 // 1. Some compilers are finicky about this;
271 // 2. Some people may want to convert this to C89;
272 // 3. If you try to use it as C++, only C++20 supports compound literals
273 static inline double_with_bit_access get_bit_access(double x)
274 {
276  dwba.F = x;
277  return dwba;
278 }
279 
280 static inline int get_sign_bit(double x)
281 {
282  // The sign is stored in the highest bit
283  return (int) (get_bit_access(x).U >> (DOUBLE_SIZE_IN_BITS - 1));
284 }
285 
286 static inline int get_exp2(double_with_bit_access x)
287 {
288  // The exponent in an IEEE-754 floating-point number occupies a contiguous
289  // sequence of bits (e.g. 52..62 for 64-bit doubles), but with a non-trivial representation: An
290  // unsigned offset from some negative value (with the extremal offset values reserved for
291  // special use).
292  return (int)((x.U >> DOUBLE_STORED_MANTISSA_BITS ) & DOUBLE_EXPONENT_MASK) - DOUBLE_BASE_EXPONENT;
293 }
294 #define PRINTF_ABS(_x) ( (_x) > 0 ? (_x) : -(_x) )
295 
296 #endif // (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
297 
298 // Note in particular the behavior here on LONG_MIN or LLONG_MIN; it is valid
299 // and well-defined, but if you're not careful you can easily trigger undefined
300 // behavior with -LONG_MIN or -LLONG_MIN
301 #define ABS_FOR_PRINTING(_x) ((printf_unsigned_value_t) ( (_x) > 0 ? (_x) : -((printf_signed_value_t)_x) ))
302 
303 // wrapper (used as buffer) for output function type
304 //
305 // One of the following must hold:
306 // 1. max_chars is 0
307 // 2. buffer is non-null
308 // 3. function is non-null
309 //
310 // ... otherwise bad things will happen.
311 typedef struct {
312  void (*function)(char c, void* extra_arg);
313  void* extra_function_arg;
314  char* buffer;
315  printf_size_t pos;
316  printf_size_t max_chars;
318 
319 // Note: This function currently assumes it is not passed a '\0' c,
320 // or alternatively, that '\0' can be passed to the function in the output
321 // gadget. The former assumption holds within the printf library. It also
322 // assumes that the output gadget has been properly initialized.
323 static inline void putchar_via_gadget(output_gadget_t* gadget, char c)
324 {
325  printf_size_t write_pos = gadget->pos++;
326  // We're _always_ increasing pos, so as to count how may characters
327  // _would_ have been written if not for the max_chars limitation
328  if (write_pos >= gadget->max_chars) {
329  return;
330  }
331  if (gadget->function != NULL) {
332  // No check for c == '\0' .
333  gadget->function(c, gadget->extra_function_arg);
334  }
335  else {
336  // it must be the case that gadget->buffer != NULL , due to the constraint
337  // on output_gadget_t ; and note we're relying on write_pos being non-negative.
338  gadget->buffer[write_pos] = c;
339  }
340 }
341 
342 // Possibly-write the string-terminating '\0' character
343 static inline void append_termination_with_gadget(output_gadget_t* gadget)
344 {
345  if (gadget->function != NULL || gadget->max_chars == 0) {
346  return;
347  }
348  if (gadget->buffer == NULL) {
349  return;
350  }
351  printf_size_t null_char_pos = gadget->pos < gadget->max_chars ? gadget->pos : gadget->max_chars - 1;
352  gadget->buffer[null_char_pos] = '\0';
353 }
354 
355 #if 0
356 // We can't use putchar_ as is, since our output gadget
357 // only takes pointers to functions with an extra argument
358 static inline void putchar_wrapper(char c, void* unused)
359 {
360  (void) unused;
361  putchar_(c);
362 }
363 #endif
364 
365 static inline output_gadget_t discarding_gadget()
366 {
367  output_gadget_t gadget;
368  gadget.function = NULL;
369  gadget.extra_function_arg = NULL;
370  gadget.buffer = NULL;
371  gadget.pos = 0;
372  gadget.max_chars = 0;
373  return gadget;
374 }
375 
376 static inline output_gadget_t buffer_gadget(char* buffer, size_t buffer_size)
377 {
378  printf_size_t usable_buffer_size = (buffer_size > PRINTF_MAX_POSSIBLE_BUFFER_SIZE) ?
379  PRINTF_MAX_POSSIBLE_BUFFER_SIZE : (printf_size_t) buffer_size;
380  output_gadget_t result = discarding_gadget();
381  if (buffer != NULL) {
382  result.buffer = buffer;
383  result.max_chars = usable_buffer_size;
384  }
385  return result;
386 }
387 
388 static inline output_gadget_t function_gadget(void (*function)(char c, void *extra_arg), void* extra_arg)
389 {
390  output_gadget_t result = discarding_gadget();
391  result.function = function;
392  result.extra_function_arg = extra_arg;
393  result.max_chars = PRINTF_MAX_POSSIBLE_BUFFER_SIZE;
394  return result;
395 }
396 
397 #if 0
398 static inline output_gadget_t extern_putchar_gadget()
399 {
400  return function_gadget(putchar_wrapper, NULL);
401 }
402 #endif
403 
404 // internal secure strlen
405 // @return The length of the string (excluding the terminating 0) limited by 'maxsize'
406 // @note strlen uses size_t, but wes only use this function with printf_size_t
407 // variables - hence the signature.
408 static inline printf_size_t strnlen_s_(const char* str, printf_size_t maxsize)
409 {
410  const char* s;
411  for (s = str; *s && maxsize--; ++s);
412  return (printf_size_t)(s - str);
413 }
414 
415 
416 // internal test if char is a digit (0-9)
417 // @return true if char is a digit
418 static inline bool is_digit_(char ch)
419 {
420  return (ch >= '0') && (ch <= '9');
421 }
422 
423 
424 // internal ASCII string to printf_size_t conversion
425 static printf_size_t atou_(const char** str)
426 {
427  printf_size_t i = 0U;
428  while (is_digit_(**str)) {
429  i = i * 10U + (printf_size_t)(*((*str)++) - '0');
430  }
431  return i;
432 }
433 
434 
435 // output the specified string in reverse, taking care of any zero-padding
436 static void out_rev_(output_gadget_t* output, const char* buf, printf_size_t len, printf_size_t width, printf_flags_t flags)
437 {
438  const printf_size_t start_pos = output->pos;
439 
440  // pad spaces up to given width
441  if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
442  for (printf_size_t i = len; i < width; i++) {
443  putchar_via_gadget(output, ' ');
444  }
445  }
446 
447  // reverse string
448  while (len) {
449  putchar_via_gadget(output, buf[--len]);
450  }
451 
452  // append pad spaces up to given width
453  if (flags & FLAGS_LEFT) {
454  while (output->pos - start_pos < width) {
455  putchar_via_gadget(output, ' ');
456  }
457  }
458 }
459 
460 
461 // Invoked by print_integer after the actual number has been printed, performing necessary
462 // work on the number's prefix (as the number is initially printed in reverse order)
463 static void print_integer_finalization(output_gadget_t* output, char* buf, printf_size_t len, bool negative, numeric_base_t base, printf_size_t precision, printf_size_t width, printf_flags_t flags)
464 {
465  printf_size_t unpadded_len = len;
466 
467  // pad with leading zeros
468  {
469  if (!(flags & FLAGS_LEFT)) {
470  if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
471  width--;
472  }
473  while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_INTEGER_BUFFER_SIZE)) {
474  buf[len++] = '0';
475  }
476  }
477 
478  while ((len < precision) && (len < PRINTF_INTEGER_BUFFER_SIZE)) {
479  buf[len++] = '0';
480  }
481 
482  if (base == BASE_OCTAL && (len > unpadded_len)) {
483  // Since we've written some zeros, we've satisfied the alternative format leading space requirement
484  flags &= ~FLAGS_HASH;
485  }
486  }
487 
488  // handle hash
489  if (flags & (FLAGS_HASH | FLAGS_POINTER)) {
490  if (!(flags & FLAGS_PRECISION) && len && ((len == precision) || (len == width))) {
491  // Let's take back some padding digits to fit in what will eventually
492  // be the format-specific prefix
493  if (unpadded_len < len) {
494  len--; // This should suffice for BASE_OCTAL
495  }
496  if (len && (base == BASE_HEX || base == BASE_BINARY) && (unpadded_len < len)) {
497  len--; // ... and an extra one for 0x or 0b
498  }
499  }
500  if ((base == BASE_HEX) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_INTEGER_BUFFER_SIZE)) {
501  buf[len++] = 'x';
502  }
503  else if ((base == BASE_HEX) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_INTEGER_BUFFER_SIZE)) {
504  buf[len++] = 'X';
505  }
506  else if ((base == BASE_BINARY) && (len < PRINTF_INTEGER_BUFFER_SIZE)) {
507  buf[len++] = 'b';
508  }
509  if (len < PRINTF_INTEGER_BUFFER_SIZE) {
510  buf[len++] = '0';
511  }
512  }
513 
514  if (len < PRINTF_INTEGER_BUFFER_SIZE) {
515  if (negative) {
516  buf[len++] = '-';
517  }
518  else if (flags & FLAGS_PLUS) {
519  buf[len++] = '+'; // ignore the space if the '+' exists
520  }
521  else if (flags & FLAGS_SPACE) {
522  buf[len++] = ' ';
523  }
524  }
525 
526  out_rev_(output, buf, len, width, flags);
527 }
528 
529 // An internal itoa-like function
530 static void print_integer(output_gadget_t* output, printf_unsigned_value_t value, bool negative, numeric_base_t base, printf_size_t precision, printf_size_t width, printf_flags_t flags)
531 {
532  char buf[PRINTF_INTEGER_BUFFER_SIZE];
533  printf_size_t len = 0U;
534 
535  if (!value) {
536  if ( !(flags & FLAGS_PRECISION) ) {
537  buf[len++] = '0';
538  flags &= ~FLAGS_HASH;
539  // We drop this flag this since either the alternative and regular modes of the specifier
540  // don't differ on 0 values, or (in the case of octal) we've already provided the special
541  // handling for this mode.
542  }
543  else if (base == BASE_HEX) {
544  flags &= ~FLAGS_HASH;
545  // We drop this flag this since either the alternative and regular modes of the specifier
546  // don't differ on 0 values
547  }
548  }
549  else {
550  do {
551  const char digit = (char)(value % base);
552  buf[len++] = (char)(digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10);
553  value /= base;
554  } while (value && (len < PRINTF_INTEGER_BUFFER_SIZE));
555  }
556 
557  print_integer_finalization(output, buf, len, negative, base, precision, width, flags);
558 }
559 
560 #if (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
561 
562 // Stores a fixed-precision representation of a double relative
563 // to a fixed precision (which cannot be determined by examining this structure)
565  int_fast64_t integral;
566  int_fast64_t fractional;
567  // ... truncation of the actual fractional part of the double value, scaled
568  // by the precision value
569  bool is_negative;
570 };
571 
572 #define NUM_DECIMAL_DIGITS_IN_INT64_T 18
573 #define PRINTF_MAX_PRECOMPUTED_POWER_OF_10 NUM_DECIMAL_DIGITS_IN_INT64_T
574 static const double powers_of_10[NUM_DECIMAL_DIGITS_IN_INT64_T] = {
575  1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08,
576  1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17
577 };
578 
579 #define PRINTF_MAX_SUPPORTED_PRECISION NUM_DECIMAL_DIGITS_IN_INT64_T - 1
580 
581 
582 // Break up a double number - which is known to be a finite non-negative number -
583 // into its base-10 parts: integral - before the decimal point, and fractional - after it.
584 // Taken the precision into account, but does not change it even internally.
585 static struct double_components get_components(double number, printf_size_t precision)
586 {
587  struct double_components number_;
588  number_.is_negative = get_sign_bit(number);
589  double abs_number = (number_.is_negative) ? -number : number;
590  number_.integral = (int_fast64_t)abs_number;
591  double remainder = (abs_number - (double) number_.integral) * powers_of_10[precision];
592  number_.fractional = (int_fast64_t)remainder;
593 
594  remainder -= (double) number_.fractional;
595 
596  if (remainder > 0.5) {
597  ++number_.fractional;
598  // handle rollover, e.g. case 0.99 with precision 1 is 1.0
599  if ((double) number_.fractional >= powers_of_10[precision]) {
600  number_.fractional = 0;
601  ++number_.integral;
602  }
603  }
604  else if ((remainder == 0.5) && ((number_.fractional == 0U) || (number_.fractional & 1U))) {
605  // if halfway, round up if odd OR if last digit is 0
606  ++number_.fractional;
607  }
608 
609  if (precision == 0U) {
610  remainder = abs_number - (double) number_.integral;
611  if ((!(remainder < 0.5) || (remainder > 0.5)) && (number_.integral & 1)) {
612  // exactly 0.5 and ODD, then round up
613  // 1.5 -> 2, but 2.5 -> 2
614  ++number_.integral;
615  }
616  }
617  return number_;
618 }
619 
620 #if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
622  double raw_factor;
623  bool multiply; // if true, need to multiply by raw_factor; otherwise need to divide by it
624 };
625 
626 static double apply_scaling(double num, struct scaling_factor normalization)
627 {
628  return normalization.multiply ? num * normalization.raw_factor : num / normalization.raw_factor;
629 }
630 
631 static double unapply_scaling(double normalized, struct scaling_factor normalization)
632 {
633  return normalization.multiply ? normalized / normalization.raw_factor : normalized * normalization.raw_factor;
634 }
635 
636 static struct scaling_factor update_normalization(struct scaling_factor sf, double extra_multiplicative_factor)
637 {
638  struct scaling_factor result;
639  if (sf.multiply) {
640  result.multiply = true;
641  result.raw_factor = sf.raw_factor * extra_multiplicative_factor;
642  }
643  else {
644  int factor_exp2 = get_exp2(get_bit_access(sf.raw_factor));
645  int extra_factor_exp2 = get_exp2(get_bit_access(extra_multiplicative_factor));
646 
647  // Divide the larger-exponent raw raw_factor by the smaller
648  if (PRINTF_ABS(factor_exp2) > PRINTF_ABS(extra_factor_exp2)) {
649  result.multiply = false;
650  result.raw_factor = sf.raw_factor / extra_multiplicative_factor;
651  }
652  else {
653  result.multiply = true;
654  result.raw_factor = extra_multiplicative_factor / sf.raw_factor;
655  }
656  }
657  return result;
658 }
659 
660 static struct double_components get_normalized_components(bool negative, printf_size_t precision, double non_normalized, struct scaling_factor normalization, int floored_exp10)
661 {
662  struct double_components components;
663  components.is_negative = negative;
664  double scaled = apply_scaling(non_normalized, normalization);
665 
666  bool close_to_representation_extremum = ( (-floored_exp10 + (int) precision) >= DBL_MAX_10_EXP - 1 );
667  if (close_to_representation_extremum) {
668  // We can't have a normalization factor which also accounts for the precision, i.e. moves
669  // some decimal digits into the mantissa, since it's unrepresentable, or nearly unrepresentable.
670  // So, we'll give up early on getting extra precision...
671  return get_components(negative ? -scaled : scaled, precision);
672  }
673  components.integral = (int_fast64_t) scaled;
674  double remainder = non_normalized - unapply_scaling((double) components.integral, normalization);
675  double prec_power_of_10 = powers_of_10[precision];
676  struct scaling_factor account_for_precision = update_normalization(normalization, prec_power_of_10);
677  double scaled_remainder = apply_scaling(remainder, account_for_precision);
678  double rounding_threshold = 0.5;
679 
680  components.fractional = (int_fast64_t) scaled_remainder; // when precision == 0, the assigned value should be 0
681  scaled_remainder -= (double) components.fractional; //when precision == 0, this will not change scaled_remainder
682 
683  components.fractional += (scaled_remainder >= rounding_threshold);
684  if (scaled_remainder == rounding_threshold) {
685  // banker's rounding: Round towards the even number (making the mean error 0)
686  components.fractional &= ~((int_fast64_t) 0x1);
687  }
688  // handle rollover, e.g. the case of 0.99 with precision 1 becoming (0,100),
689  // and must then be corrected into (1, 0).
690  // Note: for precision = 0, this will "translate" the rounding effect from
691  // the fractional part to the integral part where it should actually be
692  // felt (as prec_power_of_10 is 1)
693  if ((double) components.fractional >= prec_power_of_10) {
694  components.fractional = 0;
695  ++components.integral;
696  }
697  return components;
698 }
699 #endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
700 
701 static void print_broken_up_decimal(
702  struct double_components number_, output_gadget_t* output, printf_size_t precision,
703  printf_size_t width, printf_flags_t flags, char *buf, printf_size_t len)
704 {
705  if (precision != 0U) {
706  // do fractional part, as an unsigned number
707 
708  printf_size_t count = precision;
709 
710  // %g/%G mandates we skip the trailing 0 digits...
711  if ((flags & FLAGS_ADAPT_EXP) && !(flags & FLAGS_HASH) && (number_.fractional > 0)) {
712  while(true) {
713  int_fast64_t digit = number_.fractional % 10U;
714  if (digit != 0) {
715  break;
716  }
717  --count;
718  number_.fractional /= 10U;
719 
720  }
721  // ... and even the decimal point if there are no
722  // non-zero fractional part digits (see below)
723  }
724 
725  if (number_.fractional > 0 || !(flags & FLAGS_ADAPT_EXP) || (flags & FLAGS_HASH) ) {
726  while (len < PRINTF_DECIMAL_BUFFER_SIZE) {
727  --count;
728  buf[len++] = (char)('0' + number_.fractional % 10U);
729  if (!(number_.fractional /= 10U)) {
730  break;
731  }
732  }
733  // add extra 0s
734  while ((len < PRINTF_DECIMAL_BUFFER_SIZE) && (count > 0U)) {
735  buf[len++] = '0';
736  --count;
737  }
738  if (len < PRINTF_DECIMAL_BUFFER_SIZE) {
739  buf[len++] = '.';
740  }
741  }
742  }
743  else {
744  if ((flags & FLAGS_HASH) && (len < PRINTF_DECIMAL_BUFFER_SIZE)) {
745  buf[len++] = '.';
746  }
747  }
748 
749  // Write the integer part of the number (it comes after the fractional
750  // since the character order is reversed)
751  while (len < PRINTF_DECIMAL_BUFFER_SIZE) {
752  buf[len++] = (char)('0' + (number_.integral % 10));
753  if (!(number_.integral /= 10)) {
754  break;
755  }
756  }
757 
758  // pad leading zeros
759  if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
760  if (width && (number_.is_negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
761  width--;
762  }
763  while ((len < width) && (len < PRINTF_DECIMAL_BUFFER_SIZE)) {
764  buf[len++] = '0';
765  }
766  }
767 
768  if (len < PRINTF_DECIMAL_BUFFER_SIZE) {
769  if (number_.is_negative) {
770  buf[len++] = '-';
771  }
772  else if (flags & FLAGS_PLUS) {
773  buf[len++] = '+'; // ignore the space if the '+' exists
774  }
775  else if (flags & FLAGS_SPACE) {
776  buf[len++] = ' ';
777  }
778  }
779 
780  out_rev_(output, buf, len, width, flags);
781 }
782 
783  // internal ftoa for fixed decimal floating point
784 static void print_decimal_number(output_gadget_t* output, double number, printf_size_t precision, printf_size_t width, printf_flags_t flags, char* buf, printf_size_t len)
785 {
786  struct double_components value_ = get_components(number, precision);
787  print_broken_up_decimal(value_, output, precision, width, flags, buf, len);
788 }
789 
790 #if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
791 
792 // A floor function - but one which only works for numbers whose
793 // floor value is representable by an int.
794 static int bastardized_floor(double x)
795 {
796  if (x >= 0) { return (int) x; }
797  int n = (int) x;
798  return ( ((double) n) == x ) ? n : n-1;
799 }
800 
801 // Computes the base-10 logarithm of the input number - which must be an actual
802 // positive number (not infinity or NaN, nor a sub-normal)
803 static double log10_of_positive(double positive_number)
804 {
805  // The implementation follows David Gay (https://www.ampl.com/netlib/fp/dtoa.c).
806  //
807  // Since log_10 ( M * 2^x ) = log_10(M) + x , we can separate the components of
808  // our input number, and need only solve log_10(M) for M between 1 and 2 (as
809  // the base-2 mantissa is always 1-point-something). In that limited range, a
810  // Taylor series expansion of log10(x) should serve us well enough; and we'll
811  // take the mid-point, 1.5, as the point of expansion.
812 
813  double_with_bit_access dwba = get_bit_access(positive_number);
814  // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
815  int exp2 = get_exp2(dwba);
816  // drop the exponent, so dwba.F comes into the range [1,2)
817  dwba.U = (dwba.U & (((double_uint_t) (1) << DOUBLE_STORED_MANTISSA_BITS) - 1U)) |
818  ((double_uint_t) DOUBLE_BASE_EXPONENT << DOUBLE_STORED_MANTISSA_BITS);
819  double z = (dwba.F - 1.5);
820  return (
821  // Taylor expansion around 1.5:
822  0.1760912590556812420 // Expansion term 0: ln(1.5) / ln(10)
823  + z * 0.2895296546021678851 // Expansion term 1: (M - 1.5) * 2/3 / ln(10)
824 #if PRINTF_LOG10_TAYLOR_TERMS > 2
825  - z*z * 0.0965098848673892950 // Expansion term 2: (M - 1.5)^2 * 2/9 / ln(10)
826 #if PRINTF_LOG10_TAYLOR_TERMS > 3
827  + z*z*z * 0.0428932821632841311 // Expansion term 2: (M - 1.5)^3 * 8/81 / ln(10)
828 #endif
829 #endif
830  // exact log_2 of the exponent x, with logarithm base change
831  + exp2 * 0.30102999566398119521 // = exp2 * log_10(2) = exp2 * ln(2)/ln(10)
832  );
833 }
834 
835 
836 static double pow10_of_int(int floored_exp10)
837 {
838  // A crude hack for avoiding undesired behavior with barely-normal or slightly-subnormal values.
839  if (floored_exp10 == DOUBLE_MAX_SUBNORMAL_EXPONENT_OF_10) {
840  return DOUBLE_MAX_SUBNORMAL_POWER_OF_10;
841  }
842  // Compute 10^(floored_exp10) but (try to) make sure that doesn't overflow
844  int exp2 = bastardized_floor(floored_exp10 * 3.321928094887362 + 0.5);
845  const double z = floored_exp10 * 2.302585092994046 - exp2 * 0.6931471805599453;
846  const double z2 = z * z;
847  dwba.U = ((double_uint_t)(exp2) + DOUBLE_BASE_EXPONENT) << DOUBLE_STORED_MANTISSA_BITS;
848  // compute exp(z) using continued fractions,
849  // see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
850  dwba.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
851  return dwba.F;
852 }
853 
854 static void print_exponential_number(output_gadget_t* output, double number, printf_size_t precision, printf_size_t width, printf_flags_t flags, char* buf, printf_size_t len)
855 {
856  const bool negative = get_sign_bit(number);
857  // This number will decrease gradually (by factors of 10) as we "extract" the exponent out of it
858  double abs_number = negative ? -number : number;
859 
860  int floored_exp10;
861  bool abs_exp10_covered_by_powers_table;
862  struct scaling_factor normalization;
863 
864 
865  // Determine the decimal exponent
866  if (abs_number == 0.0) {
867  // TODO: This is a special-case for 0.0 (and -0.0); but proper handling is required for denormals more generally.
868  floored_exp10 = 0; // ... and no need to set a normalization factor or check the powers table
869  }
870  else {
871  double exp10 = log10_of_positive(abs_number);
872  floored_exp10 = bastardized_floor(exp10);
873  double p10 = pow10_of_int(floored_exp10);
874  // correct for rounding errors
875  if (abs_number < p10) {
876  floored_exp10--;
877  p10 /= 10;
878  }
879  abs_exp10_covered_by_powers_table = PRINTF_ABS(floored_exp10) < PRINTF_MAX_PRECOMPUTED_POWER_OF_10;
880  normalization.raw_factor = abs_exp10_covered_by_powers_table ? powers_of_10[PRINTF_ABS(floored_exp10)] : p10;
881  }
882 
883  // We now begin accounting for the widths of the two parts of our printed field:
884  // the decimal part after decimal exponent extraction, and the base-10 exponent part.
885  // For both of these, the value of 0 has a special meaning, but not the same one:
886  // a 0 exponent-part width means "don't print the exponent"; a 0 decimal-part width
887  // means "use as many characters as necessary".
888 
889  bool fall_back_to_decimal_only_mode = false;
890  if (flags & FLAGS_ADAPT_EXP) {
891  int required_significant_digits = (precision == 0) ? 1 : (int) precision;
892  // Should we want to fall-back to "%f" mode, and only print the decimal part?
893  fall_back_to_decimal_only_mode = (floored_exp10 >= -4 && floored_exp10 < required_significant_digits);
894  // Now, let's adjust the precision
895  // This also decided how we adjust the precision value - as in "%g" mode,
896  // "precision" is the number of _significant digits_, and this is when we "translate"
897  // the precision value to an actual number of decimal digits.
898  int precision_ = fall_back_to_decimal_only_mode ?
899  (int) precision - 1 - floored_exp10 :
900  (int) precision - 1; // the presence of the exponent ensures only one significant digit comes before the decimal point
901  precision = (precision_ > 0 ? (unsigned) precision_ : 0U);
902  flags |= FLAGS_PRECISION; // make sure print_broken_up_decimal respects our choice above
903  }
904 
905  normalization.multiply = (floored_exp10 < 0 && abs_exp10_covered_by_powers_table);
906  bool should_skip_normalization = (fall_back_to_decimal_only_mode || floored_exp10 == 0);
907  struct double_components decimal_part_components =
908  should_skip_normalization ?
909  get_components(negative ? -abs_number : abs_number, precision) :
910  get_normalized_components(negative, precision, abs_number, normalization, floored_exp10);
911 
912  // Account for roll-over, e.g. rounding from 9.99 to 100.0 - which effects
913  // the exponent and may require additional tweaking of the parts
914  if (fall_back_to_decimal_only_mode) {
915  if ((flags & FLAGS_ADAPT_EXP) && floored_exp10 >= -1 && decimal_part_components.integral == powers_of_10[floored_exp10 + 1]) {
916  floored_exp10++; // Not strictly necessary, since floored_exp10 is no longer really used
917  precision--;
918  // ... and it should already be the case that decimal_part_components.fractional == 0
919  }
920  // TODO: What about rollover strictly within the fractional part?
921  }
922  else {
923  if (decimal_part_components.integral >= 10) {
924  floored_exp10++;
925  decimal_part_components.integral = 1;
926  decimal_part_components.fractional = 0;
927  }
928  }
929 
930  // the floored_exp10 format is "E%+03d" and largest possible floored_exp10 value for a 64-bit double
931  // is "307" (for 2^1023), so we set aside 4-5 characters overall
932  printf_size_t exp10_part_width = fall_back_to_decimal_only_mode ? 0U : (PRINTF_ABS(floored_exp10) < 100) ? 4U : 5U;
933 
934  printf_size_t decimal_part_width =
935  ((flags & FLAGS_LEFT) && exp10_part_width) ?
936  // We're padding on the right, so the width constraint is the exponent part's
937  // problem, not the decimal part's, so we'll use as many characters as we need:
938  0U :
939  // We're padding on the left; so the width constraint is the decimal part's
940  // problem. Well, can both the decimal part and the exponent part fit within our overall width?
941  ((width > exp10_part_width) ?
942  // Yes, so we limit our decimal part's width.
943  // (Note this is trivially valid even if we've fallen back to "%f" mode)
944  width - exp10_part_width :
945  // No; we just give up on any restriction on the decimal part and use as many
946  // characters as we need
947  0U);
948 
949  const printf_size_t printed_exponential_start_pos = output->pos;
950  print_broken_up_decimal(decimal_part_components, output, precision, decimal_part_width, flags, buf, len);
951 
952  if (! fall_back_to_decimal_only_mode) {
953  putchar_via_gadget(output, (flags & FLAGS_UPPERCASE) ? 'E' : 'e');
954  print_integer(output,
955  ABS_FOR_PRINTING(floored_exp10),
956  floored_exp10 < 0, 10, 0, exp10_part_width - 1,
957  FLAGS_ZEROPAD | FLAGS_PLUS);
958  if (flags & FLAGS_LEFT) {
959  // We need to right-pad with spaces to meet the width requirement
960  while (output->pos - printed_exponential_start_pos < width) {
961  putchar_via_gadget(output, ' ');
962  }
963  }
964  }
965 }
966 #endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
967 
968 static void print_floating_point(output_gadget_t* output, double value, printf_size_t precision, printf_size_t width, printf_flags_t flags, bool prefer_exponential)
969 {
970  char buf[PRINTF_DECIMAL_BUFFER_SIZE];
971  printf_size_t len = 0U;
972 
973  // test for special values
974  if (value != value) {
975  out_rev_(output, "nan", 3, width, flags);
976  return;
977  }
978  if (value < -DBL_MAX) {
979  out_rev_(output, "fni-", 4, width, flags);
980  return;
981  }
982  if (value > DBL_MAX) {
983  out_rev_(output, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
984  return;
985  }
986 
987  if (!prefer_exponential &&
988  ((value > PRINTF_FLOAT_NOTATION_THRESHOLD) || (value < -PRINTF_FLOAT_NOTATION_THRESHOLD))) {
989  // The required behavior of standard printf is to print _every_ integral-part digit -- which could mean
990  // printing hundreds of characters, overflowing any fixed internal buffer and necessitating a more complicated
991  // implementation.
992 #if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
993  print_exponential_number(output, value, precision, width, flags, buf, len);
994 #endif
995  return;
996  }
997 
998  // set default precision, if not set explicitly
999  if (!(flags & FLAGS_PRECISION)) {
1000  precision = PRINTF_DEFAULT_FLOAT_PRECISION;
1001  }
1002 
1003  // limit precision so that our integer holding the fractional part does not overflow
1004  while ((len < PRINTF_DECIMAL_BUFFER_SIZE) && (precision > PRINTF_MAX_SUPPORTED_PRECISION)) {
1005  buf[len++] = '0'; // This respects the precision in terms of result length only
1006  precision--;
1007  }
1008 
1009 #if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
1010  if (prefer_exponential)
1011  print_exponential_number(output, value, precision, width, flags, buf, len);
1012  else
1013 #endif
1014  print_decimal_number(output, value, precision, width, flags, buf, len);
1015 }
1016 
1017 #endif // (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
1018 
1019 // Advances the format pointer past the flags, and returns the parsed flags
1020 // due to the characters passed
1021 static printf_flags_t parse_flags(const char** format)
1022 {
1023  printf_flags_t flags = 0U;
1024  do {
1025  switch (**format) {
1026  case '0': flags |= FLAGS_ZEROPAD; (*format)++; break;
1027  case '-': flags |= FLAGS_LEFT; (*format)++; break;
1028  case '+': flags |= FLAGS_PLUS; (*format)++; break;
1029  case ' ': flags |= FLAGS_SPACE; (*format)++; break;
1030  case '#': flags |= FLAGS_HASH; (*format)++; break;
1031  default : return flags;
1032  }
1033  } while (true);
1034 }
1035 
1036 // internal vsnprintf - used for implementing _all library functions
1037 // Note: We don't like the C standard's parameter names, so using more informative parameter names
1038 // here instead.
1039 static int _vsnprintf(output_gadget_t* output, const char* format, va_list args)
1040 {
1041  // Note: The library only calls _vsnprintf() with output->pos being 0. However, it is
1042  // possible to call this function with a non-zero pos value for some "remedial printing".
1043 
1044  while (*format)
1045  {
1046  // format specifier? %[flags][width][.precision][length]
1047  if (*format != '%') {
1048  // no
1049  putchar_via_gadget(output, *format);
1050  format++;
1051  continue;
1052  }
1053  else {
1054  // yes, evaluate it
1055  format++;
1056  }
1057 
1058  printf_flags_t flags = parse_flags(&format);
1059 
1060  // evaluate width field
1061  printf_size_t width = 0U;
1062  if (is_digit_(*format)) {
1063  width = (printf_size_t) atou_(&format);
1064  }
1065  else if (*format == '*') {
1066  const int w = va_arg(args, int);
1067  if (w < 0) {
1068  flags |= FLAGS_LEFT; // reverse padding
1069  width = (printf_size_t)-w;
1070  }
1071  else {
1072  width = (printf_size_t)w;
1073  }
1074  format++;
1075  }
1076 
1077  // evaluate precision field
1078  printf_size_t precision = 0U;
1079  if (*format == '.') {
1080  flags |= FLAGS_PRECISION;
1081  format++;
1082  if (is_digit_(*format)) {
1083  precision = (printf_size_t) atou_(&format);
1084  }
1085  else if (*format == '*') {
1086  const int precision_ = va_arg(args, int);
1087  precision = precision_ > 0 ? (printf_size_t) precision_ : 0U;
1088  format++;
1089  }
1090  }
1091 
1092  // evaluate length field
1093  switch (*format) {
1094 #ifdef PRINTF_SUPPORT_MSVC_STYLE_INTEGER_SPECIFIERS
1095  case 'I' : {
1096  format++;
1097  // Greedily parse for size in bits: 8, 16, 32 or 64
1098  switch(*format) {
1099  case '8': flags |= FLAGS_INT8;
1100  format++;
1101  break;
1102  case '1':
1103  format++;
1104  if (*format == '6') { format++; flags |= FLAGS_INT16; }
1105  break;
1106  case '3':
1107  format++;
1108  if (*format == '2') { format++; flags |= FLAGS_INT32; }
1109  break;
1110  case '6':
1111  format++;
1112  if (*format == '4') { format++; flags |= FLAGS_INT64; }
1113  break;
1114  default: break;
1115  }
1116  break;
1117  }
1118 #endif
1119  case 'l' :
1120  flags |= FLAGS_LONG;
1121  format++;
1122  if (*format == 'l') {
1123  flags |= FLAGS_LONG_LONG;
1124  format++;
1125  }
1126  break;
1127  case 'h' :
1128  flags |= FLAGS_SHORT;
1129  format++;
1130  if (*format == 'h') {
1131  flags |= FLAGS_CHAR;
1132  format++;
1133  }
1134  break;
1135  case 't' :
1136  flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
1137  format++;
1138  break;
1139  case 'j' :
1140  flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
1141  format++;
1142  break;
1143  case 'z' :
1144  flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
1145  format++;
1146  break;
1147  default:
1148  break;
1149  }
1150 
1151  // evaluate specifier
1152  switch (*format) {
1153  case 'd' :
1154  case 'i' :
1155  case 'u' :
1156  case 'x' :
1157  case 'X' :
1158  case 'o' :
1159  case 'b' : {
1160 
1161  if (*format == 'd' || *format == 'i') {
1162  flags |= FLAGS_SIGNED;
1163  }
1164 
1165  numeric_base_t base;
1166  if (*format == 'x' || *format == 'X') {
1167  base = BASE_HEX;
1168  }
1169  else if (*format == 'o') {
1170  base = BASE_OCTAL;
1171  }
1172  else if (*format == 'b') {
1173  base = BASE_BINARY;
1174  }
1175  else {
1176  base = BASE_DECIMAL;
1177  flags &= ~FLAGS_HASH; // decimal integers have no alternative presentation
1178  }
1179 
1180  if (*format == 'X') {
1181  flags |= FLAGS_UPPERCASE;
1182  }
1183 
1184  format++;
1185  // ignore '0' flag when precision is given
1186  if (flags & FLAGS_PRECISION) {
1187  flags &= ~FLAGS_ZEROPAD;
1188  }
1189 
1190  if (flags & FLAGS_SIGNED) {
1191  // A signed specifier: d, i or possibly I + bit size if enabled
1192 
1193  if (flags & FLAGS_LONG_LONG) {
1194 #if PRINTF_SUPPORT_LONG_LONG
1195  const long long value = va_arg(args, long long);
1196  print_integer(output, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags);
1197 #endif
1198  }
1199  else if (flags & FLAGS_LONG) {
1200  const long value = va_arg(args, long);
1201  print_integer(output, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags);
1202  }
1203  else {
1204  // We never try to interpret the argument as something potentially-smaller than int,
1205  // due to integer promotion rules: Even if the user passed a short int, short unsigned
1206  // etc. - these will come in after promotion, as int's (or unsigned for the case of
1207  // short unsigned when it has the same size as int)
1208  const int value =
1209  (flags & FLAGS_CHAR) ? (signed char) va_arg(args, int) :
1210  (flags & FLAGS_SHORT) ? (short int) va_arg(args, int) :
1211  va_arg(args, int);
1212  print_integer(output, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags);
1213  }
1214  }
1215  else {
1216  // An unsigned specifier: u, x, X, o, b
1217 
1218  flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
1219 
1220  if (flags & FLAGS_LONG_LONG) {
1221 #if PRINTF_SUPPORT_LONG_LONG
1222  print_integer(output, (printf_unsigned_value_t) va_arg(args, unsigned long long), false, base, precision, width, flags);
1223 #endif
1224  }
1225  else if (flags & FLAGS_LONG) {
1226  print_integer(output, (printf_unsigned_value_t) va_arg(args, unsigned long), false, base, precision, width, flags);
1227  }
1228  else {
1229  const unsigned int value =
1230  (flags & FLAGS_CHAR) ? (unsigned char)va_arg(args, unsigned int) :
1231  (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(args, unsigned int) :
1232  va_arg(args, unsigned int);
1233  print_integer(output, (printf_unsigned_value_t) value, false, base, precision, width, flags);
1234  }
1235  }
1236  break;
1237  }
1238 #if PRINTF_SUPPORT_DECIMAL_SPECIFIERS
1239  case 'f' :
1240  case 'F' :
1241  if (*format == 'F') flags |= FLAGS_UPPERCASE;
1242  print_floating_point(output, va_arg(args, double), precision, width, flags, PRINTF_PREFER_DECIMAL);
1243  format++;
1244  break;
1245 #endif
1246 #if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
1247  case 'e':
1248  case 'E':
1249  case 'g':
1250  case 'G':
1251  if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
1252  if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
1253  print_floating_point(output, va_arg(args, double), precision, width, flags, PRINTF_PREFER_EXPONENTIAL);
1254  format++;
1255  break;
1256 #endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
1257  case 'c' : {
1258  printf_size_t l = 1U;
1259  // pre padding
1260  if (!(flags & FLAGS_LEFT)) {
1261  while (l++ < width) {
1262  putchar_via_gadget(output, ' ');
1263  }
1264  }
1265  // char output
1266  putchar_via_gadget(output, (char) va_arg(args, int) );
1267  // post padding
1268  if (flags & FLAGS_LEFT) {
1269  while (l++ < width) {
1270  putchar_via_gadget(output, ' ');
1271  }
1272  }
1273  format++;
1274  break;
1275  }
1276 
1277  case 's' : {
1278  const char* p = va_arg(args, char*);
1279  if (p == NULL) {
1280  out_rev_(output, ")llun(", 6, width, flags);
1281  }
1282  else {
1283  printf_size_t l = strnlen_s_(p, precision ? precision : PRINTF_MAX_POSSIBLE_BUFFER_SIZE);
1284  // pre padding
1285  if (flags & FLAGS_PRECISION) {
1286  l = (l < precision ? l : precision);
1287  }
1288  if (!(flags & FLAGS_LEFT)) {
1289  while (l++ < width) {
1290  putchar_via_gadget(output, ' ');
1291  }
1292  }
1293  // string output
1294  while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision)) {
1295  putchar_via_gadget(output, *(p++));
1296  --precision;
1297  }
1298  // post padding
1299  if (flags & FLAGS_LEFT) {
1300  while (l++ < width) {
1301  putchar_via_gadget(output, ' ');
1302  }
1303  }
1304  }
1305  format++;
1306  break;
1307  }
1308 
1309  case 'p' : {
1310  width = sizeof(void*) * 2U + 2; // 2 hex chars per byte + the "0x" prefix
1311  flags |= FLAGS_ZEROPAD | FLAGS_POINTER;
1312  uintptr_t value = (uintptr_t)va_arg(args, void*);
1313  (value == (uintptr_t) NULL) ?
1314  out_rev_(output, ")lin(", 5, width, flags) :
1315  print_integer(output, (printf_unsigned_value_t) value, false, BASE_HEX, precision, width, flags);
1316  format++;
1317  break;
1318  }
1319 
1320  case '%' :
1321  putchar_via_gadget(output, '%');
1322  format++;
1323  break;
1324 
1325  // Many people prefer to disable support for %n, as it lets the caller
1326  // engineer a write to an arbitrary location, of a value the caller
1327  // effectively controls - which could be a security concern in some cases.
1328 #if PRINTF_SUPPORT_WRITEBACK_SPECIFIER
1329  case 'n' : {
1330  if (flags & FLAGS_CHAR) *(va_arg(args, char*)) = (char) output->pos;
1331  else if (flags & FLAGS_SHORT) *(va_arg(args, short*)) = (short) output->pos;
1332  else if (flags & FLAGS_LONG) *(va_arg(args, long*)) = (long) output->pos;
1333 #if PRINTF_SUPPORT_LONG_LONG
1334  else if (flags & FLAGS_LONG_LONG) *(va_arg(args, long long*)) = (long long int) output->pos;
1335 #endif // PRINTF_SUPPORT_LONG_LONG
1336  else *(va_arg(args, int*)) = (int) output->pos;
1337  format++;
1338  break;
1339  }
1340 #endif // PRINTF_SUPPORT_WRITEBACK_SPECIFIER
1341 
1342  default :
1343  putchar_via_gadget(output, *format);
1344  format++;
1345  break;
1346  }
1347  }
1348 
1349  // termination
1350  append_termination_with_gadget(output);
1351 
1352  // return written chars without terminating \0
1353  return (int)output->pos;
1354 }
1355 
1356 
1358 
1359 #if 0
1360 int vprintf_(const char* format, va_list arg)
1361 {
1362  output_gadget_t gadget = extern_putchar_gadget();
1363  return _vsnprintf(&gadget, format, arg);
1364 }
1365 #endif
1366 
1367 int vsnprintf_(char* s, size_t n, const char* format, va_list arg)
1368 {
1369  output_gadget_t gadget = buffer_gadget(s, n);
1370  return _vsnprintf(&gadget, format, arg);
1371 }
1372 
1373 int vsprintf_(char* s, const char* format, va_list arg)
1374 {
1375  return vsnprintf_(s, PRINTF_MAX_POSSIBLE_BUFFER_SIZE, format, arg);
1376 }
1377 
1378 int vfctprintf(void (*out)(char c, void* extra_arg), void* extra_arg, const char* format, va_list arg)
1379 {
1380  output_gadget_t gadget = function_gadget(out, extra_arg);
1381  return _vsnprintf(&gadget, format, arg);
1382 }
1383 
1384 #if 0
1385 int printf_(const char* format, ...)
1386 {
1387  va_list args;
1388  va_start(args, format);
1389  const int ret = vprintf_(format, args);
1390  va_end(args);
1391  return ret;
1392 }
1393 #endif
1394 
1395 int sprintf_(char* s, const char* format, ...)
1396 {
1397  va_list args;
1398  va_start(args, format);
1399  const int ret = vsprintf_(s, format, args);
1400  va_end(args);
1401  return ret;
1402 }
1403 
1404 int snprintf_(char* s, size_t n, const char* format, ...)
1405 {
1406  va_list args;
1407  va_start(args, format);
1408  const int ret = vsnprintf_(s, n, format, args);
1409  va_end(args);
1410  return ret;
1411 }
1412 
1413 int fctprintf(void (*out)(char c, void* extra_arg), void* extra_arg, const char* format, ...)
1414 {
1415  va_list args;
1416  va_start(args, format);
1417  const int ret = vfctprintf(out, extra_arg, format, args);
1418  va_end(args);
1419  return ret;
1420 }
1421 
1422 // wrapper (used as buffer) for output function type
1423 typedef struct {
1424  print_callback_t prnt_callback;
1425  void* arg;
1427 
1428 // We need to swap arguments
1429 static inline void prnt_wrapper(char c, void* extra_arg)
1430 {
1431  ((out_prnt_wrap_type *)extra_arg)->prnt_callback(((out_prnt_wrap_type *)extra_arg)->arg, c);
1432 }
1433 
1434 // non-standard function
1435 int prnt(print_callback_t out, void *context, const char * format, va_list ap)
1436 {
1437  const out_prnt_wrap_type out_prnt_wrap = { out, context };
1438  int ret;
1439 
1440  ret = vfctprintf(&prnt_wrapper, (void *)&out_prnt_wrap, format, ap);
1441  // In STDIO module, this flushes the current contents of the 64-byte temporary buffer to the output.
1442  out(context, 513);
1443  // In STDIO module, this sets the amount of bytes currently in the 64-byte temporary buffer to 0.
1444  out(context, 512);
1445  return ret;
1446 }
1447 
1448 #ifdef __cplusplus
1449 } // extern "C"
1450 #endif
double_with_bit_access
Definition: printf.c:263
sysclib.h
output_gadget_t
Definition: printf.c:311
count
u32 count
start sector of fragmented bd/file
Definition: usbhdfsd-common.h:3
out_prnt_wrap_type
Definition: printf.c:1423
scaling_factor
Definition: printf.c:621
double_components
Definition: printf.c:564