rt_vsnprintf_std.c 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-11-27 Meco Man porting for rt_vsnprintf as the fully functional version
  9. * 2024-11-19 Meco Man move to klibc
  10. */
  11. /**
  12. * @author (c) Eyal Rozenberg <eyalroz1@gmx.com>
  13. * 2021-2022, Haifa, Palestine/Israel
  14. * @author (c) Marco Paland (info@paland.com)
  15. * 2014-2019, PALANDesign Hannover, Germany
  16. *
  17. * @note Others have made smaller contributions to this file: see the
  18. * contributors page at https://github.com/eyalroz/printf/graphs/contributors
  19. * or ask one of the authors. The original code for exponential specifiers was
  20. * contributed by Martijn Jasperse <m.jasperse@gmail.com>.
  21. *
  22. * @brief Small stand-alone implementation of the printf family of functions
  23. * (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems with
  24. * a very limited resources.
  25. *
  26. * @note the implementations are thread-safe; re-entrant; use no functions from
  27. * the standard library; and do not dynamically allocate any memory.
  28. *
  29. * @license The MIT License (MIT)
  30. *
  31. * Permission is hereby granted, free of charge, to any person obtaining a copy
  32. * of this software and associated documentation files (the "Software"), to deal
  33. * in the Software without restriction, including without limitation the rights
  34. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  35. * copies of the Software, and to permit persons to whom the Software is
  36. * furnished to do so, subject to the following conditions:
  37. *
  38. * The above copyright notice and this permission notice shall be included in
  39. * all copies or substantial portions of the Software.
  40. *
  41. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  42. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  43. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  44. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  45. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  46. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  47. * THE SOFTWARE.
  48. */
  49. #include <rtthread.h>
  50. #include <stdio.h>
  51. #include <stdint.h>
  52. #include <limits.h>
  53. #include <stdbool.h>
  54. // 'ntoa' conversion buffer size, this must be big enough to hold one converted
  55. // numeric number including padded zeros (dynamically created on stack)
  56. #ifndef RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE
  57. #define RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE 32
  58. #endif
  59. // size of the fixed (on-stack) buffer for printing individual decimal numbers.
  60. // this must be big enough to hold one converted floating-point value including
  61. // padded zeros.
  62. #ifndef RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE
  63. #define RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE 32
  64. #endif
  65. // Support for the decimal notation floating point conversion specifiers (%f, %F)
  66. #ifndef RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS
  67. #define RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS
  68. #endif
  69. // Support for the exponential notation floating point conversion specifiers (%e, %g, %E, %G)
  70. #ifndef RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
  71. #define RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
  72. #endif
  73. // Support for the length write-back specifier (%n)
  74. #ifndef RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER
  75. #define RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER
  76. #endif
  77. // Default precision for the floating point conversion specifiers (the C standard sets this at 6)
  78. #ifndef RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION
  79. #define RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION 6
  80. #endif
  81. // According to the C languages standard, printf() and related functions must be able to print any
  82. // integral number in floating-point notation, regardless of length, when using the %f specifier -
  83. // possibly hundreds of characters, potentially overflowing your buffers. In this implementation,
  84. // all values beyond this threshold are switched to exponential notation.
  85. #ifndef RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL
  86. #define RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9
  87. #endif
  88. // Support for the long long integral types (with the ll, z and t length modifiers for specifiers
  89. // %d,%i,%o,%x,%X,%u, and with the %p specifier). Note: 'L' (long double) is not supported.
  90. #ifndef RT_KLIBC_USING_VSNPRINTF_LONGLONG
  91. #define RT_KLIBC_USING_VSNPRINTF_LONGLONG
  92. #endif
  93. // The number of terms in a Taylor series expansion of log_10(x) to
  94. // use for approximation - including the power-zero term (i.e. the
  95. // value at the point of expansion).
  96. #ifndef RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS
  97. #define RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS 4
  98. #endif
  99. // Be extra-safe, and don't assume format specifiers are completed correctly
  100. // before the format string end.
  101. #if !defined(RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER) || defined(RT_USING_DEBUG)
  102. #define RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER
  103. #endif
  104. #if RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS <= 1
  105. #error "At least one non-constant Taylor expansion is necessary for the log10() calculation"
  106. #endif
  107. ///////////////////////////////////////////////////////////////////////////////
  108. #define PRINTF_PREFER_DECIMAL false
  109. #define PRINTF_PREFER_EXPONENTIAL true
  110. // The following will convert the number-of-digits into an exponential-notation literal
  111. #define PRINTF_CONCATENATE(s1, s2) s1##s2
  112. #define PRINTF_EXPAND_THEN_CONCATENATE(s1, s2) PRINTF_CONCATENATE(s1, s2)
  113. #define PRINTF_FLOAT_NOTATION_THRESHOLD PRINTF_EXPAND_THEN_CONCATENATE(1e,RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL)
  114. // internal flag definitions
  115. #define FLAGS_ZEROPAD (1U << 0U)
  116. #define FLAGS_LEFT (1U << 1U)
  117. #define FLAGS_PLUS (1U << 2U)
  118. #define FLAGS_SPACE (1U << 3U)
  119. #define FLAGS_HASH (1U << 4U)
  120. #define FLAGS_UPPERCASE (1U << 5U)
  121. #define FLAGS_CHAR (1U << 6U)
  122. #define FLAGS_SHORT (1U << 7U)
  123. #define FLAGS_INT (1U << 8U)
  124. // Only used with RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS
  125. #define FLAGS_LONG (1U << 9U)
  126. #define FLAGS_LONG_LONG (1U << 10U)
  127. #define FLAGS_PRECISION (1U << 11U)
  128. #define FLAGS_ADAPT_EXP (1U << 12U)
  129. #define FLAGS_POINTER (1U << 13U)
  130. // Note: Similar, but not identical, effect as FLAGS_HASH
  131. #define FLAGS_SIGNED (1U << 14U)
  132. // Only used with RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS
  133. #ifdef RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS
  134. #define FLAGS_INT8 FLAGS_CHAR
  135. #if (SHRT_MAX == 32767LL)
  136. #define FLAGS_INT16 FLAGS_SHORT
  137. #elif (INT_MAX == 32767LL)
  138. #define FLAGS_INT16 FLAGS_INT
  139. #elif (LONG_MAX == 32767LL)
  140. #define FLAGS_INT16 FLAGS_LONG
  141. #elif (LLONG_MAX == 32767LL)
  142. #define FLAGS_INT16 FLAGS_LONG_LONG
  143. #else
  144. #error "No basic integer type has a size of 16 bits exactly"
  145. #endif
  146. #if (SHRT_MAX == 2147483647LL)
  147. #define FLAGS_INT32 FLAGS_SHORT
  148. #elif (INT_MAX == 2147483647LL)
  149. #define FLAGS_INT32 FLAGS_INT
  150. #elif (LONG_MAX == 2147483647LL)
  151. #define FLAGS_INT32 FLAGS_LONG
  152. #elif (LLONG_MAX == 2147483647LL)
  153. #define FLAGS_INT32 FLAGS_LONG_LONG
  154. #else
  155. #error "No basic integer type has a size of 32 bits exactly"
  156. #endif
  157. #if (SHRT_MAX == 9223372036854775807LL)
  158. #define FLAGS_INT64 FLAGS_SHORT
  159. #elif (INT_MAX == 9223372036854775807LL)
  160. #define FLAGS_INT64 FLAGS_INT
  161. #elif (LONG_MAX == 9223372036854775807LL)
  162. #define FLAGS_INT64 FLAGS_LONG
  163. #elif (LLONG_MAX == 9223372036854775807LL)
  164. #define FLAGS_INT64 FLAGS_LONG_LONG
  165. #else
  166. #error "No basic integer type has a size of 64 bits exactly"
  167. #endif
  168. #endif // RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS
  169. typedef unsigned int printf_flags_t;
  170. #define BASE_BINARY 2
  171. #define BASE_OCTAL 8
  172. #define BASE_DECIMAL 10
  173. #define BASE_HEX 16
  174. typedef uint8_t numeric_base_t;
  175. #ifdef RT_KLIBC_USING_VSNPRINTF_LONGLONG
  176. typedef unsigned long long printf_unsigned_value_t;
  177. typedef long long printf_signed_value_t;
  178. #else
  179. typedef unsigned long printf_unsigned_value_t;
  180. typedef long printf_signed_value_t;
  181. #endif
  182. // The printf()-family functions return an `int`; it is therefore
  183. // unnecessary/inappropriate to use size_t - often larger than int
  184. // in practice - for non-negative related values, such as widths,
  185. // precisions, offsets into buffers used for printing and the sizes
  186. // of these buffers. instead, we use:
  187. typedef unsigned int printf_size_t;
  188. #define PRINTF_MAX_POSSIBLE_BUFFER_SIZE INT_MAX
  189. // If we were to nitpick, this would actually be INT_MAX + 1,
  190. // since INT_MAX is the maximum return value, which excludes the
  191. // trailing '\0'.
  192. #if defined(RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS) || defined(RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS)
  193. #include <float.h>
  194. #if FLT_RADIX != 2
  195. #error "Non-binary-radix floating-point types are unsupported."
  196. #endif
  197. #if DBL_MANT_DIG == 24
  198. #define DOUBLE_SIZE_IN_BITS 32
  199. typedef uint32_t double_uint_t;
  200. #define DOUBLE_EXPONENT_MASK 0xFFU
  201. #define DOUBLE_BASE_EXPONENT 127
  202. #define DOUBLE_MAX_SUBNORMAL_EXPONENT_OF_10 -38
  203. #define DOUBLE_MAX_SUBNORMAL_POWER_OF_10 1e-38
  204. #elif DBL_MANT_DIG == 53
  205. #define DOUBLE_SIZE_IN_BITS 64
  206. typedef uint64_t double_uint_t;
  207. #define DOUBLE_EXPONENT_MASK 0x7FFU
  208. #define DOUBLE_BASE_EXPONENT 1023
  209. #define DOUBLE_MAX_SUBNORMAL_EXPONENT_OF_10 -308
  210. #define DOUBLE_MAX_SUBNORMAL_POWER_OF_10 ((double)1e-308L)
  211. #else
  212. #error "Unsupported double type configuration"
  213. #endif
  214. #define DOUBLE_STORED_MANTISSA_BITS (DBL_MANT_DIG - 1)
  215. typedef union {
  216. double_uint_t U;
  217. double F;
  218. } double_with_bit_access;
  219. // This is unnecessary in C99, since compound initializers can be used,
  220. // but:
  221. // 1. Some compilers are finicky about this;
  222. // 2. Some people may want to convert this to C89;
  223. // 3. If you try to use it as C++, only C++20 supports compound literals
  224. static inline double_with_bit_access get_bit_access(double x)
  225. {
  226. double_with_bit_access dwba;
  227. dwba.F = x;
  228. return dwba;
  229. }
  230. static inline int get_sign_bit(double x)
  231. {
  232. // The sign is stored in the highest bit
  233. return (int) (get_bit_access(x).U >> (DOUBLE_SIZE_IN_BITS - 1));
  234. }
  235. static inline int get_exp2(double_with_bit_access x)
  236. {
  237. // The exponent in an IEEE-754 floating-point number occupies a contiguous
  238. // sequence of bits (e.g. 52..62 for 64-bit doubles), but with a non-trivial representation: An
  239. // unsigned offset from some negative value (with the extremal offset values reserved for
  240. // special use).
  241. return (int)((x.U >> DOUBLE_STORED_MANTISSA_BITS ) & DOUBLE_EXPONENT_MASK) - DOUBLE_BASE_EXPONENT;
  242. }
  243. #define PRINTF_ABS(_x) ( (_x) > 0 ? (_x) : -(_x) )
  244. #endif // (RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS || RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS)
  245. // Note in particular the behavior here on LONG_MIN or LLONG_MIN; it is valid
  246. // and well-defined, but if you're not careful you can easily trigger undefined
  247. // behavior with -LONG_MIN or -LLONG_MIN
  248. #define ABS_FOR_PRINTING(_x) ((printf_unsigned_value_t) ( (_x) > 0 ? (_x) : -((printf_signed_value_t)_x) ))
  249. // wrapper (used as buffer) for output function type
  250. //
  251. // One of the following must hold:
  252. // 1. max_chars is 0
  253. // 2. buffer is non-null
  254. // 3. function is non-null
  255. //
  256. // ... otherwise bad things will happen.
  257. typedef struct {
  258. void (*function)(char c, void* extra_arg);
  259. void* extra_function_arg;
  260. char* buffer;
  261. printf_size_t pos;
  262. printf_size_t max_chars;
  263. } output_gadget_t;
  264. // Note: This function currently assumes it is not passed a '\0' c,
  265. // or alternatively, that '\0' can be passed to the function in the output
  266. // gadget. The former assumption holds within the printf library. It also
  267. // assumes that the output gadget has been properly initialized.
  268. static inline void putchar_via_gadget(output_gadget_t* gadget, char c)
  269. {
  270. printf_size_t write_pos = gadget->pos++;
  271. // We're _always_ increasing pos, so as to count how may characters
  272. // _would_ have been written if not for the max_chars limitation
  273. if (write_pos >= gadget->max_chars) {
  274. return;
  275. }
  276. if (gadget->function != NULL) {
  277. // No check for c == '\0' .
  278. gadget->function(c, gadget->extra_function_arg);
  279. }
  280. else {
  281. // it must be the case that gadget->buffer != NULL , due to the constraint
  282. // on output_gadget_t ; and note we're relying on write_pos being non-negative.
  283. gadget->buffer[write_pos] = c;
  284. }
  285. }
  286. // Possibly-write the string-terminating '\0' character
  287. static inline void append_termination_with_gadget(output_gadget_t* gadget)
  288. {
  289. if (gadget->function != NULL || gadget->max_chars == 0) {
  290. return;
  291. }
  292. if (gadget->buffer == NULL) {
  293. return;
  294. }
  295. printf_size_t null_char_pos = gadget->pos < gadget->max_chars ? gadget->pos : gadget->max_chars - 1;
  296. gadget->buffer[null_char_pos] = '\0';
  297. }
  298. static inline output_gadget_t discarding_gadget(void)
  299. {
  300. output_gadget_t gadget;
  301. gadget.function = NULL;
  302. gadget.extra_function_arg = NULL;
  303. gadget.buffer = NULL;
  304. gadget.pos = 0;
  305. gadget.max_chars = 0;
  306. return gadget;
  307. }
  308. static inline output_gadget_t buffer_gadget(char* buffer, size_t buffer_size)
  309. {
  310. printf_size_t usable_buffer_size = (buffer_size > PRINTF_MAX_POSSIBLE_BUFFER_SIZE) ?
  311. PRINTF_MAX_POSSIBLE_BUFFER_SIZE : (printf_size_t) buffer_size;
  312. output_gadget_t result = discarding_gadget();
  313. if (buffer != NULL) {
  314. result.buffer = buffer;
  315. result.max_chars = usable_buffer_size;
  316. }
  317. return result;
  318. }
  319. // internal secure strlen
  320. // @return The length of the string (excluding the terminating 0) limited by 'maxsize'
  321. // @note strlen uses size_t, but wes only use this function with printf_size_t
  322. // variables - hence the signature.
  323. static inline printf_size_t strnlen_s_(const char* str, printf_size_t maxsize)
  324. {
  325. const char* s;
  326. for (s = str; *s && maxsize--; ++s);
  327. return (printf_size_t)(s - str);
  328. }
  329. // internal test if char is a digit (0-9)
  330. // @return true if char is a digit
  331. static inline bool is_digit_(char ch)
  332. {
  333. return (ch >= '0') && (ch <= '9');
  334. }
  335. // internal ASCII string to printf_size_t conversion
  336. static printf_size_t atou_(const char** str)
  337. {
  338. printf_size_t i = 0U;
  339. while (is_digit_(**str)) {
  340. i = i * 10U + (printf_size_t)(*((*str)++) - '0');
  341. }
  342. return i;
  343. }
  344. // output the specified string in reverse, taking care of any zero-padding
  345. static void out_rev_(output_gadget_t* output, const char* buf, printf_size_t len, printf_size_t width, printf_flags_t flags)
  346. {
  347. const printf_size_t start_pos = output->pos;
  348. // pad spaces up to given width
  349. if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
  350. for (printf_size_t i = len; i < width; i++) {
  351. putchar_via_gadget(output, ' ');
  352. }
  353. }
  354. // reverse string
  355. while (len) {
  356. putchar_via_gadget(output, buf[--len]);
  357. }
  358. // append pad spaces up to given width
  359. if (flags & FLAGS_LEFT) {
  360. while (output->pos - start_pos < width) {
  361. putchar_via_gadget(output, ' ');
  362. }
  363. }
  364. }
  365. // Invoked by print_integer after the actual number has been printed, performing necessary
  366. // work on the number's prefix (as the number is initially printed in reverse order)
  367. 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)
  368. {
  369. printf_size_t unpadded_len = len;
  370. // pad with leading zeros
  371. {
  372. if (!(flags & FLAGS_LEFT)) {
  373. if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
  374. width--;
  375. }
  376. while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE)) {
  377. buf[len++] = '0';
  378. }
  379. }
  380. while ((len < precision) && (len < RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE)) {
  381. buf[len++] = '0';
  382. }
  383. if (base == BASE_OCTAL && (len > unpadded_len)) {
  384. // Since we've written some zeros, we've satisfied the alternative format leading space requirement
  385. flags &= ~FLAGS_HASH;
  386. }
  387. }
  388. // handle hash
  389. if (flags & (FLAGS_HASH | FLAGS_POINTER)) {
  390. if (!(flags & FLAGS_PRECISION) && len && ((len == precision) || (len == width))) {
  391. // Let's take back some padding digits to fit in what will eventually
  392. // be the format-specific prefix
  393. if (unpadded_len < len) {
  394. len--; // This should suffice for BASE_OCTAL
  395. }
  396. if (len && (base == BASE_HEX || base == BASE_BINARY) && (unpadded_len < len)) {
  397. len--; // ... and an extra one for 0x or 0b
  398. }
  399. }
  400. if ((base == BASE_HEX) && !(flags & FLAGS_UPPERCASE) && (len < RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE)) {
  401. buf[len++] = 'x';
  402. }
  403. else if ((base == BASE_HEX) && (flags & FLAGS_UPPERCASE) && (len < RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE)) {
  404. buf[len++] = 'X';
  405. }
  406. else if ((base == BASE_BINARY) && (len < RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE)) {
  407. buf[len++] = 'b';
  408. }
  409. if (len < RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE) {
  410. buf[len++] = '0';
  411. }
  412. }
  413. if (len < RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE) {
  414. if (negative) {
  415. buf[len++] = '-';
  416. }
  417. else if (flags & FLAGS_PLUS) {
  418. buf[len++] = '+'; // ignore the space if the '+' exists
  419. }
  420. else if (flags & FLAGS_SPACE) {
  421. buf[len++] = ' ';
  422. }
  423. }
  424. out_rev_(output, buf, len, width, flags);
  425. }
  426. // An internal itoa-like function
  427. 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)
  428. {
  429. char buf[RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE];
  430. printf_size_t len = 0U;
  431. if (!value) {
  432. if ( !(flags & FLAGS_PRECISION) ) {
  433. buf[len++] = '0';
  434. flags &= ~FLAGS_HASH;
  435. // We drop this flag this since either the alternative and regular modes of the specifier
  436. // don't differ on 0 values, or (in the case of octal) we've already provided the special
  437. // handling for this mode.
  438. }
  439. else if (base == BASE_HEX) {
  440. flags &= ~FLAGS_HASH;
  441. // We drop this flag this since either the alternative and regular modes of the specifier
  442. // don't differ on 0 values
  443. }
  444. }
  445. else {
  446. do {
  447. const char digit = (char)(value % base);
  448. buf[len++] = (char)(digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10);
  449. value /= base;
  450. } while (value && (len < RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE));
  451. }
  452. print_integer_finalization(output, buf, len, negative, base, precision, width, flags);
  453. }
  454. #if defined(RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS) || defined(RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS)
  455. // Stores a fixed-precision representation of a double relative
  456. // to a fixed precision (which cannot be determined by examining this structure)
  457. struct double_components {
  458. int_fast64_t integral;
  459. int_fast64_t fractional;
  460. // ... truncation of the actual fractional part of the double value, scaled
  461. // by the precision value
  462. bool is_negative;
  463. };
  464. #define NUM_DECIMAL_DIGITS_IN_INT64_T 18
  465. #define PRINTF_MAX_PRECOMPUTED_POWER_OF_10 NUM_DECIMAL_DIGITS_IN_INT64_T
  466. static const double powers_of_10[NUM_DECIMAL_DIGITS_IN_INT64_T] = {
  467. 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08,
  468. 1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17
  469. };
  470. #define PRINTF_MAX_SUPPORTED_PRECISION NUM_DECIMAL_DIGITS_IN_INT64_T - 1
  471. // Break up a double number - which is known to be a finite non-negative number -
  472. // into its base-10 parts: integral - before the decimal point, and fractional - after it.
  473. // Taken the precision into account, but does not change it even internally.
  474. static struct double_components get_components(double number, printf_size_t precision)
  475. {
  476. struct double_components number_;
  477. number_.is_negative = get_sign_bit(number);
  478. double abs_number = (number_.is_negative) ? -number : number;
  479. number_.integral = (int_fast64_t)abs_number;
  480. double remainder = (abs_number - (double) number_.integral) * powers_of_10[precision];
  481. number_.fractional = (int_fast64_t)remainder;
  482. remainder -= (double) number_.fractional;
  483. if (remainder > 0.5) {
  484. ++number_.fractional;
  485. // handle rollover, e.g. case 0.99 with precision 1 is 1.0
  486. if ((double) number_.fractional >= powers_of_10[precision]) {
  487. number_.fractional = 0;
  488. ++number_.integral;
  489. }
  490. }
  491. else if ((remainder == 0.5) && ((number_.fractional == 0U) || (number_.fractional & 1U))) {
  492. // if halfway, round up if odd OR if last digit is 0
  493. ++number_.fractional;
  494. }
  495. if (precision == 0U) {
  496. remainder = abs_number - (double) number_.integral;
  497. if ((!(remainder < 0.5) || (remainder > 0.5)) && (number_.integral & 1)) {
  498. // exactly 0.5 and ODD, then round up
  499. // 1.5 -> 2, but 2.5 -> 2
  500. ++number_.integral;
  501. }
  502. }
  503. return number_;
  504. }
  505. #ifdef RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
  506. struct scaling_factor {
  507. double raw_factor;
  508. bool multiply; // if true, need to multiply by raw_factor; otherwise need to divide by it
  509. };
  510. static double apply_scaling(double num, struct scaling_factor normalization)
  511. {
  512. return normalization.multiply ? num * normalization.raw_factor : num / normalization.raw_factor;
  513. }
  514. static double unapply_scaling(double normalized, struct scaling_factor normalization)
  515. {
  516. #if defined(__GNUC__) && !defined(__clang__) && !defined(__ARMCC_VERSION) /* GCC */
  517. // accounting for a static analysis bug in GCC 6.x and earlier
  518. #pragma GCC diagnostic push
  519. #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  520. #endif
  521. return normalization.multiply ? normalized / normalization.raw_factor : normalized * normalization.raw_factor;
  522. #if defined(__GNUC__) && !defined(__clang__) && !defined(__ARMCC_VERSION) /* GCC */
  523. #pragma GCC diagnostic pop
  524. #endif
  525. }
  526. static struct scaling_factor update_normalization(struct scaling_factor sf, double extra_multiplicative_factor)
  527. {
  528. struct scaling_factor result;
  529. if (sf.multiply) {
  530. result.multiply = true;
  531. result.raw_factor = sf.raw_factor * extra_multiplicative_factor;
  532. }
  533. else {
  534. int factor_exp2 = get_exp2(get_bit_access(sf.raw_factor));
  535. int extra_factor_exp2 = get_exp2(get_bit_access(extra_multiplicative_factor));
  536. // Divide the larger-exponent raw raw_factor by the smaller
  537. if (PRINTF_ABS(factor_exp2) > PRINTF_ABS(extra_factor_exp2)) {
  538. result.multiply = false;
  539. result.raw_factor = sf.raw_factor / extra_multiplicative_factor;
  540. }
  541. else {
  542. result.multiply = true;
  543. result.raw_factor = extra_multiplicative_factor / sf.raw_factor;
  544. }
  545. }
  546. return result;
  547. }
  548. static struct double_components get_normalized_components(bool negative, printf_size_t precision, double non_normalized, struct scaling_factor normalization, int floored_exp10)
  549. {
  550. struct double_components components;
  551. components.is_negative = negative;
  552. double scaled = apply_scaling(non_normalized, normalization);
  553. bool close_to_representation_extremum = ( (-floored_exp10 + (int) precision) >= DBL_MAX_10_EXP - 1 );
  554. if (close_to_representation_extremum) {
  555. // We can't have a normalization factor which also accounts for the precision, i.e. moves
  556. // some decimal digits into the mantissa, since it's unrepresentable, or nearly unrepresentable.
  557. // So, we'll give up early on getting extra precision...
  558. return get_components(negative ? -scaled : scaled, precision);
  559. }
  560. components.integral = (int_fast64_t) scaled;
  561. double remainder = non_normalized - unapply_scaling((double) components.integral, normalization);
  562. double prec_power_of_10 = powers_of_10[precision];
  563. struct scaling_factor account_for_precision = update_normalization(normalization, prec_power_of_10);
  564. double scaled_remainder = apply_scaling(remainder, account_for_precision);
  565. double rounding_threshold = 0.5;
  566. components.fractional = (int_fast64_t) scaled_remainder; // when precision == 0, the assigned value should be 0
  567. scaled_remainder -= (double) components.fractional; //when precision == 0, this will not change scaled_remainder
  568. components.fractional += (scaled_remainder >= rounding_threshold);
  569. if (scaled_remainder == rounding_threshold) {
  570. // banker's rounding: Round towards the even number (making the mean error 0)
  571. components.fractional &= ~((int_fast64_t) 0x1);
  572. }
  573. // handle rollover, e.g. the case of 0.99 with precision 1 becoming (0,100),
  574. // and must then be corrected into (1, 0).
  575. // Note: for precision = 0, this will "translate" the rounding effect from
  576. // the fractional part to the integral part where it should actually be
  577. // felt (as prec_power_of_10 is 1)
  578. if ((double) components.fractional >= prec_power_of_10) {
  579. components.fractional = 0;
  580. ++components.integral;
  581. }
  582. return components;
  583. }
  584. #endif // RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
  585. static void print_broken_up_decimal(
  586. struct double_components number_, output_gadget_t* output, printf_size_t precision,
  587. printf_size_t width, printf_flags_t flags, char *buf, printf_size_t len)
  588. {
  589. if (precision != 0U) {
  590. // do fractional part, as an unsigned number
  591. printf_size_t count = precision;
  592. // %g/%G mandates we skip the trailing 0 digits...
  593. if ((flags & FLAGS_ADAPT_EXP) && !(flags & FLAGS_HASH) && (number_.fractional > 0)) {
  594. while(true) {
  595. int_fast64_t digit = number_.fractional % 10U;
  596. if (digit != 0) {
  597. break;
  598. }
  599. --count;
  600. number_.fractional /= 10U;
  601. }
  602. // ... and even the decimal point if there are no
  603. // non-zero fractional part digits (see below)
  604. }
  605. if (number_.fractional > 0 || !(flags & FLAGS_ADAPT_EXP) || (flags & FLAGS_HASH) ) {
  606. while (len < RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE) {
  607. --count;
  608. buf[len++] = (char)('0' + number_.fractional % 10U);
  609. if (!(number_.fractional /= 10U)) {
  610. break;
  611. }
  612. }
  613. // add extra 0s
  614. while ((len < RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE) && (count > 0U)) {
  615. buf[len++] = '0';
  616. --count;
  617. }
  618. if (len < RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE) {
  619. buf[len++] = '.';
  620. }
  621. }
  622. }
  623. else {
  624. if ((flags & FLAGS_HASH) && (len < RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE)) {
  625. buf[len++] = '.';
  626. }
  627. }
  628. // Write the integer part of the number (it comes after the fractional
  629. // since the character order is reversed)
  630. while (len < RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE) {
  631. buf[len++] = (char)('0' + (number_.integral % 10));
  632. if (!(number_.integral /= 10)) {
  633. break;
  634. }
  635. }
  636. // pad leading zeros
  637. if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
  638. if (width && (number_.is_negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
  639. width--;
  640. }
  641. while ((len < width) && (len < RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE)) {
  642. buf[len++] = '0';
  643. }
  644. }
  645. if (len < RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE) {
  646. if (number_.is_negative) {
  647. buf[len++] = '-';
  648. }
  649. else if (flags & FLAGS_PLUS) {
  650. buf[len++] = '+'; // ignore the space if the '+' exists
  651. }
  652. else if (flags & FLAGS_SPACE) {
  653. buf[len++] = ' ';
  654. }
  655. }
  656. out_rev_(output, buf, len, width, flags);
  657. }
  658. // internal ftoa for fixed decimal floating point
  659. 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)
  660. {
  661. struct double_components value_ = get_components(number, precision);
  662. print_broken_up_decimal(value_, output, precision, width, flags, buf, len);
  663. }
  664. #ifdef RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
  665. // A floor function - but one which only works for numbers whose
  666. // floor value is representable by an int.
  667. static int bastardized_floor(double x)
  668. {
  669. if (x >= 0) { return (int) x; }
  670. int n = (int) x;
  671. return ( ((double) n) == x ) ? n : n-1;
  672. }
  673. // Computes the base-10 logarithm of the input number - which must be an actual
  674. // positive number (not infinity or NaN, nor a sub-normal)
  675. static double log10_of_positive(double positive_number)
  676. {
  677. // The implementation follows David Gay (https://www.ampl.com/netlib/fp/dtoa.c).
  678. //
  679. // Since log_10 ( M * 2^x ) = log_10(M) + x , we can separate the components of
  680. // our input number, and need only solve log_10(M) for M between 1 and 2 (as
  681. // the base-2 mantissa is always 1-point-something). In that limited range, a
  682. // Taylor series expansion of log10(x) should serve us well enough; and we'll
  683. // take the mid-point, 1.5, as the point of expansion.
  684. double_with_bit_access dwba = get_bit_access(positive_number);
  685. // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
  686. int exp2 = get_exp2(dwba);
  687. // drop the exponent, so dwba.F comes into the range [1,2)
  688. dwba.U = (dwba.U & (((double_uint_t) (1) << DOUBLE_STORED_MANTISSA_BITS) - 1U)) |
  689. ((double_uint_t) DOUBLE_BASE_EXPONENT << DOUBLE_STORED_MANTISSA_BITS);
  690. double z = (dwba.F - 1.5);
  691. return (
  692. // Taylor expansion around 1.5:
  693. 0.1760912590556812420 // Expansion term 0: ln(1.5) / ln(10)
  694. + z * 0.2895296546021678851 // Expansion term 1: (M - 1.5) * 2/3 / ln(10)
  695. #if RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS > 2
  696. - z*z * 0.0965098848673892950 // Expansion term 2: (M - 1.5)^2 * 2/9 / ln(10)
  697. #if RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS > 3
  698. + z*z*z * 0.0428932821632841311 // Expansion term 2: (M - 1.5)^3 * 8/81 / ln(10)
  699. #endif
  700. #endif
  701. // exact log_2 of the exponent x, with logarithm base change
  702. + exp2 * 0.30102999566398119521 // = exp2 * log_10(2) = exp2 * ln(2)/ln(10)
  703. );
  704. }
  705. static double pow10_of_int(int floored_exp10)
  706. {
  707. // A crude hack for avoiding undesired behavior with barely-normal or slightly-subnormal values.
  708. if (floored_exp10 == DOUBLE_MAX_SUBNORMAL_EXPONENT_OF_10) {
  709. return DOUBLE_MAX_SUBNORMAL_POWER_OF_10;
  710. }
  711. // Compute 10^(floored_exp10) but (try to) make sure that doesn't overflow
  712. double_with_bit_access dwba;
  713. int exp2 = bastardized_floor(floored_exp10 * 3.321928094887362 + 0.5);
  714. const double z = floored_exp10 * 2.302585092994046 - exp2 * 0.6931471805599453;
  715. const double z2 = z * z;
  716. dwba.U = ((double_uint_t)(exp2) + DOUBLE_BASE_EXPONENT) << DOUBLE_STORED_MANTISSA_BITS;
  717. // compute exp(z) using continued fractions,
  718. // see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
  719. dwba.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
  720. return dwba.F;
  721. }
  722. 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)
  723. {
  724. const bool negative = get_sign_bit(number);
  725. // This number will decrease gradually (by factors of 10) as we "extract" the exponent out of it
  726. double abs_number = negative ? -number : number;
  727. int floored_exp10;
  728. bool abs_exp10_covered_by_powers_table;
  729. struct scaling_factor normalization;
  730. // Determine the decimal exponent
  731. if (abs_number == 0.0) {
  732. // TODO: This is a special-case for 0.0 (and -0.0); but proper handling is required for denormals more generally.
  733. floored_exp10 = 0; // ... and no need to set a normalization factor or check the powers table
  734. }
  735. else {
  736. double exp10 = log10_of_positive(abs_number);
  737. floored_exp10 = bastardized_floor(exp10);
  738. double p10 = pow10_of_int(floored_exp10);
  739. // correct for rounding errors
  740. if (abs_number < p10) {
  741. floored_exp10--;
  742. p10 /= 10;
  743. }
  744. abs_exp10_covered_by_powers_table = PRINTF_ABS(floored_exp10) < PRINTF_MAX_PRECOMPUTED_POWER_OF_10;
  745. normalization.raw_factor = abs_exp10_covered_by_powers_table ? powers_of_10[PRINTF_ABS(floored_exp10)] : p10;
  746. }
  747. // We now begin accounting for the widths of the two parts of our printed field:
  748. // the decimal part after decimal exponent extraction, and the base-10 exponent part.
  749. // For both of these, the value of 0 has a special meaning, but not the same one:
  750. // a 0 exponent-part width means "don't print the exponent"; a 0 decimal-part width
  751. // means "use as many characters as necessary".
  752. bool fall_back_to_decimal_only_mode = false;
  753. if (flags & FLAGS_ADAPT_EXP) {
  754. int required_significant_digits = (precision == 0) ? 1 : (int) precision;
  755. // Should we want to fall-back to "%f" mode, and only print the decimal part?
  756. fall_back_to_decimal_only_mode = (floored_exp10 >= -4 && floored_exp10 < required_significant_digits);
  757. // Now, let's adjust the precision
  758. // This also decided how we adjust the precision value - as in "%g" mode,
  759. // "precision" is the number of _significant digits_, and this is when we "translate"
  760. // the precision value to an actual number of decimal digits.
  761. int precision_ = fall_back_to_decimal_only_mode ?
  762. (int) precision - 1 - floored_exp10 :
  763. (int) precision - 1; // the presence of the exponent ensures only one significant digit comes before the decimal point
  764. precision = (precision_ > 0 ? (unsigned) precision_ : 0U);
  765. flags |= FLAGS_PRECISION; // make sure print_broken_up_decimal respects our choice above
  766. }
  767. normalization.multiply = (floored_exp10 < 0 && abs_exp10_covered_by_powers_table);
  768. bool should_skip_normalization = (fall_back_to_decimal_only_mode || floored_exp10 == 0);
  769. struct double_components decimal_part_components =
  770. should_skip_normalization ?
  771. get_components(negative ? -abs_number : abs_number, precision) :
  772. get_normalized_components(negative, precision, abs_number, normalization, floored_exp10);
  773. // Account for roll-over, e.g. rounding from 9.99 to 100.0 - which effects
  774. // the exponent and may require additional tweaking of the parts
  775. if (fall_back_to_decimal_only_mode) {
  776. if ((flags & FLAGS_ADAPT_EXP) && floored_exp10 >= -1 && decimal_part_components.integral == powers_of_10[floored_exp10 + 1]) {
  777. floored_exp10++; // Not strictly necessary, since floored_exp10 is no longer really used
  778. precision--;
  779. // ... and it should already be the case that decimal_part_components.fractional == 0
  780. }
  781. // TODO: What about rollover strictly within the fractional part?
  782. }
  783. else {
  784. if (decimal_part_components.integral >= 10) {
  785. floored_exp10++;
  786. decimal_part_components.integral = 1;
  787. decimal_part_components.fractional = 0;
  788. }
  789. }
  790. // the floored_exp10 format is "E%+03d" and largest possible floored_exp10 value for a 64-bit double
  791. // is "307" (for 2^1023), so we set aside 4-5 characters overall
  792. printf_size_t exp10_part_width = fall_back_to_decimal_only_mode ? 0U : (PRINTF_ABS(floored_exp10) < 100) ? 4U : 5U;
  793. printf_size_t decimal_part_width =
  794. ((flags & FLAGS_LEFT) && exp10_part_width) ?
  795. // We're padding on the right, so the width constraint is the exponent part's
  796. // problem, not the decimal part's, so we'll use as many characters as we need:
  797. 0U :
  798. // We're padding on the left; so the width constraint is the decimal part's
  799. // problem. Well, can both the decimal part and the exponent part fit within our overall width?
  800. ((width > exp10_part_width) ?
  801. // Yes, so we limit our decimal part's width.
  802. // (Note this is trivially valid even if we've fallen back to "%f" mode)
  803. width - exp10_part_width :
  804. // No; we just give up on any restriction on the decimal part and use as many
  805. // characters as we need
  806. 0U);
  807. const printf_size_t printed_exponential_start_pos = output->pos;
  808. print_broken_up_decimal(decimal_part_components, output, precision, decimal_part_width, flags, buf, len);
  809. if (! fall_back_to_decimal_only_mode) {
  810. putchar_via_gadget(output, (flags & FLAGS_UPPERCASE) ? 'E' : 'e');
  811. print_integer(output,
  812. ABS_FOR_PRINTING(floored_exp10),
  813. floored_exp10 < 0, 10, 0, exp10_part_width - 1,
  814. FLAGS_ZEROPAD | FLAGS_PLUS);
  815. if (flags & FLAGS_LEFT) {
  816. // We need to right-pad with spaces to meet the width requirement
  817. while (output->pos - printed_exponential_start_pos < width) {
  818. putchar_via_gadget(output, ' ');
  819. }
  820. }
  821. }
  822. }
  823. #endif // RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
  824. 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)
  825. {
  826. char buf[RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE];
  827. printf_size_t len = 0U;
  828. // test for special values
  829. if (value != value) {
  830. out_rev_(output, "nan", 3, width, flags);
  831. return;
  832. }
  833. if (value < -DBL_MAX) {
  834. out_rev_(output, "fni-", 4, width, flags);
  835. return;
  836. }
  837. if (value > DBL_MAX) {
  838. out_rev_(output, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
  839. return;
  840. }
  841. if (!prefer_exponential &&
  842. ((value > PRINTF_FLOAT_NOTATION_THRESHOLD) || (value < -PRINTF_FLOAT_NOTATION_THRESHOLD))) {
  843. // The required behavior of standard printf is to print _every_ integral-part digit -- which could mean
  844. // printing hundreds of characters, overflowing any fixed internal buffer and necessitating a more complicated
  845. // implementation.
  846. #ifdef RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
  847. print_exponential_number(output, value, precision, width, flags, buf, len);
  848. #endif
  849. return;
  850. }
  851. // set default precision, if not set explicitly
  852. if (!(flags & FLAGS_PRECISION)) {
  853. precision = RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION;
  854. }
  855. // limit precision so that our integer holding the fractional part does not overflow
  856. while ((len < RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE) && (precision > PRINTF_MAX_SUPPORTED_PRECISION)) {
  857. buf[len++] = '0'; // This respects the precision in terms of result length only
  858. precision--;
  859. }
  860. #ifdef RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
  861. if (prefer_exponential)
  862. print_exponential_number(output, value, precision, width, flags, buf, len);
  863. else
  864. #endif
  865. print_decimal_number(output, value, precision, width, flags, buf, len);
  866. }
  867. #endif // (RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS || RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS)
  868. // Advances the format pointer past the flags, and returns the parsed flags
  869. // due to the characters passed
  870. static printf_flags_t parse_flags(const char** format)
  871. {
  872. printf_flags_t flags = 0U;
  873. do {
  874. switch (**format) {
  875. case '0': flags |= FLAGS_ZEROPAD; (*format)++; break;
  876. case '-': flags |= FLAGS_LEFT; (*format)++; break;
  877. case '+': flags |= FLAGS_PLUS; (*format)++; break;
  878. case ' ': flags |= FLAGS_SPACE; (*format)++; break;
  879. case '#': flags |= FLAGS_HASH; (*format)++; break;
  880. default : return flags;
  881. }
  882. } while (true);
  883. }
  884. static inline void format_string_loop(output_gadget_t* output, const char* format, va_list args)
  885. {
  886. #ifdef RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER
  887. #define ADVANCE_IN_FORMAT_STRING(cptr_) do { (cptr_)++; if (!*(cptr_)) return; } while(0)
  888. #else
  889. #define ADVANCE_IN_FORMAT_STRING(cptr_) (cptr_)++
  890. #endif
  891. while (*format)
  892. {
  893. if (*format != '%') {
  894. // A regular content character
  895. putchar_via_gadget(output, *format);
  896. format++;
  897. continue;
  898. }
  899. // We're parsing a format specifier: %[flags][width][.precision][length]
  900. ADVANCE_IN_FORMAT_STRING(format);
  901. printf_flags_t flags = parse_flags(&format);
  902. // evaluate width field
  903. printf_size_t width = 0U;
  904. if (is_digit_(*format)) {
  905. width = (printf_size_t) atou_(&format);
  906. }
  907. else if (*format == '*') {
  908. const int w = va_arg(args, int);
  909. if (w < 0) {
  910. flags |= FLAGS_LEFT; // reverse padding
  911. width = (printf_size_t)-w;
  912. }
  913. else {
  914. width = (printf_size_t)w;
  915. }
  916. ADVANCE_IN_FORMAT_STRING(format);
  917. }
  918. // evaluate precision field
  919. printf_size_t precision = 0U;
  920. if (*format == '.') {
  921. flags |= FLAGS_PRECISION;
  922. ADVANCE_IN_FORMAT_STRING(format);
  923. if (is_digit_(*format)) {
  924. precision = (printf_size_t) atou_(&format);
  925. }
  926. else if (*format == '*') {
  927. const int precision_ = va_arg(args, int);
  928. precision = precision_ > 0 ? (printf_size_t) precision_ : 0U;
  929. ADVANCE_IN_FORMAT_STRING(format);
  930. }
  931. }
  932. // evaluate length field
  933. switch (*format) {
  934. #ifdef RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS
  935. case 'I' : {
  936. ADVANCE_IN_FORMAT_STRING(format);
  937. // Greedily parse for size in bits: 8, 16, 32 or 64
  938. switch(*format) {
  939. case '8': flags |= FLAGS_INT8;
  940. ADVANCE_IN_FORMAT_STRING(format);
  941. break;
  942. case '1':
  943. ADVANCE_IN_FORMAT_STRING(format);
  944. if (*format == '6') { format++; flags |= FLAGS_INT16; }
  945. break;
  946. case '3':
  947. ADVANCE_IN_FORMAT_STRING(format);
  948. if (*format == '2') { ADVANCE_IN_FORMAT_STRING(format); flags |= FLAGS_INT32; }
  949. break;
  950. case '6':
  951. ADVANCE_IN_FORMAT_STRING(format);
  952. if (*format == '4') { ADVANCE_IN_FORMAT_STRING(format); flags |= FLAGS_INT64; }
  953. break;
  954. default: break;
  955. }
  956. break;
  957. }
  958. #endif
  959. case 'l' :
  960. flags |= FLAGS_LONG;
  961. ADVANCE_IN_FORMAT_STRING(format);
  962. if (*format == 'l') {
  963. flags |= FLAGS_LONG_LONG;
  964. ADVANCE_IN_FORMAT_STRING(format);
  965. }
  966. break;
  967. case 'h' :
  968. flags |= FLAGS_SHORT;
  969. ADVANCE_IN_FORMAT_STRING(format);
  970. if (*format == 'h') {
  971. flags |= FLAGS_CHAR;
  972. ADVANCE_IN_FORMAT_STRING(format);
  973. }
  974. break;
  975. case 't' :
  976. flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
  977. ADVANCE_IN_FORMAT_STRING(format);
  978. break;
  979. case 'j' :
  980. flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
  981. ADVANCE_IN_FORMAT_STRING(format);
  982. break;
  983. case 'z' :
  984. flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
  985. ADVANCE_IN_FORMAT_STRING(format);
  986. break;
  987. default:
  988. break;
  989. }
  990. // evaluate specifier
  991. switch (*format) {
  992. case 'd' :
  993. case 'i' :
  994. case 'u' :
  995. case 'x' :
  996. case 'X' :
  997. case 'o' :
  998. case 'b' : {
  999. if (*format == 'd' || *format == 'i') {
  1000. flags |= FLAGS_SIGNED;
  1001. }
  1002. numeric_base_t base;
  1003. if (*format == 'x' || *format == 'X') {
  1004. base = BASE_HEX;
  1005. }
  1006. else if (*format == 'o') {
  1007. base = BASE_OCTAL;
  1008. }
  1009. else if (*format == 'b') {
  1010. base = BASE_BINARY;
  1011. }
  1012. else {
  1013. base = BASE_DECIMAL;
  1014. flags &= ~FLAGS_HASH; // decimal integers have no alternative presentation
  1015. }
  1016. if (*format == 'X') {
  1017. flags |= FLAGS_UPPERCASE;
  1018. }
  1019. format++;
  1020. // ignore '0' flag when precision is given
  1021. if (flags & FLAGS_PRECISION) {
  1022. flags &= ~FLAGS_ZEROPAD;
  1023. }
  1024. if (flags & FLAGS_SIGNED) {
  1025. // A signed specifier: d, i or possibly I + bit size if enabled
  1026. if (flags & FLAGS_LONG_LONG) {
  1027. #ifdef RT_KLIBC_USING_VSNPRINTF_LONGLONG
  1028. const long long value = va_arg(args, long long);
  1029. print_integer(output, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags);
  1030. #endif
  1031. }
  1032. else if (flags & FLAGS_LONG) {
  1033. const long value = va_arg(args, long);
  1034. print_integer(output, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags);
  1035. }
  1036. else {
  1037. // We never try to interpret the argument as something potentially-smaller than int,
  1038. // due to integer promotion rules: Even if the user passed a short int, short unsigned
  1039. // etc. - these will come in after promotion, as int's (or unsigned for the case of
  1040. // short unsigned when it has the same size as int)
  1041. const int value =
  1042. (flags & FLAGS_CHAR) ? (signed char) va_arg(args, int) :
  1043. (flags & FLAGS_SHORT) ? (short int) va_arg(args, int) :
  1044. va_arg(args, int);
  1045. print_integer(output, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags);
  1046. }
  1047. }
  1048. else {
  1049. // An unsigned specifier: u, x, X, o, b
  1050. flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
  1051. if (flags & FLAGS_LONG_LONG) {
  1052. #ifdef RT_KLIBC_USING_VSNPRINTF_LONGLONG
  1053. print_integer(output, (printf_unsigned_value_t) va_arg(args, unsigned long long), false, base, precision, width, flags);
  1054. #endif
  1055. }
  1056. else if (flags & FLAGS_LONG) {
  1057. print_integer(output, (printf_unsigned_value_t) va_arg(args, unsigned long), false, base, precision, width, flags);
  1058. }
  1059. else {
  1060. const unsigned int value =
  1061. (flags & FLAGS_CHAR) ? (unsigned char)va_arg(args, unsigned int) :
  1062. (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(args, unsigned int) :
  1063. va_arg(args, unsigned int);
  1064. print_integer(output, (printf_unsigned_value_t) value, false, base, precision, width, flags);
  1065. }
  1066. }
  1067. break;
  1068. }
  1069. #ifdef RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS
  1070. case 'f' :
  1071. case 'F' :
  1072. if (*format == 'F') flags |= FLAGS_UPPERCASE;
  1073. print_floating_point(output, va_arg(args, double), precision, width, flags, PRINTF_PREFER_DECIMAL);
  1074. format++;
  1075. break;
  1076. #endif
  1077. #ifdef RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
  1078. case 'e':
  1079. case 'E':
  1080. case 'g':
  1081. case 'G':
  1082. if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
  1083. if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
  1084. print_floating_point(output, va_arg(args, double), precision, width, flags, PRINTF_PREFER_EXPONENTIAL);
  1085. format++;
  1086. break;
  1087. #endif // RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
  1088. case 'c' : {
  1089. printf_size_t l = 1U;
  1090. // pre padding
  1091. if (!(flags & FLAGS_LEFT)) {
  1092. while (l++ < width) {
  1093. putchar_via_gadget(output, ' ');
  1094. }
  1095. }
  1096. // char output
  1097. putchar_via_gadget(output, (char) va_arg(args, int) );
  1098. // post padding
  1099. if (flags & FLAGS_LEFT) {
  1100. while (l++ < width) {
  1101. putchar_via_gadget(output, ' ');
  1102. }
  1103. }
  1104. format++;
  1105. break;
  1106. }
  1107. case 's' : {
  1108. const char* p = va_arg(args, char*);
  1109. if (p == NULL) {
  1110. out_rev_(output, ")llun(", 6, width, flags);
  1111. }
  1112. else {
  1113. printf_size_t l = strnlen_s_(p, precision ? precision : PRINTF_MAX_POSSIBLE_BUFFER_SIZE);
  1114. // pre padding
  1115. if (flags & FLAGS_PRECISION) {
  1116. l = (l < precision ? l : precision);
  1117. }
  1118. if (!(flags & FLAGS_LEFT)) {
  1119. while (l++ < width) {
  1120. putchar_via_gadget(output, ' ');
  1121. }
  1122. }
  1123. // string output
  1124. while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision)) {
  1125. putchar_via_gadget(output, *(p++));
  1126. --precision;
  1127. }
  1128. // post padding
  1129. if (flags & FLAGS_LEFT) {
  1130. while (l++ < width) {
  1131. putchar_via_gadget(output, ' ');
  1132. }
  1133. }
  1134. }
  1135. format++;
  1136. break;
  1137. }
  1138. case 'p' : {
  1139. width = sizeof(void*) * 2U + 2; // 2 hex chars per byte + the "0x" prefix
  1140. flags |= FLAGS_ZEROPAD | FLAGS_POINTER;
  1141. uintptr_t value = (uintptr_t)va_arg(args, void*);
  1142. (value == (uintptr_t) NULL) ?
  1143. out_rev_(output, ")lin(", 5, width, flags) :
  1144. print_integer(output, (printf_unsigned_value_t) value, false, BASE_HEX, precision, width, flags);
  1145. format++;
  1146. break;
  1147. }
  1148. case '%' :
  1149. putchar_via_gadget(output, '%');
  1150. format++;
  1151. break;
  1152. // Many people prefer to disable support for %n, as it lets the caller
  1153. // engineer a write to an arbitrary location, of a value the caller
  1154. // effectively controls - which could be a security concern in some cases.
  1155. #ifdef RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER
  1156. case 'n' : {
  1157. if (flags & FLAGS_CHAR) *(va_arg(args, char*)) = (char) output->pos;
  1158. else if (flags & FLAGS_SHORT) *(va_arg(args, short*)) = (short) output->pos;
  1159. else if (flags & FLAGS_LONG) *(va_arg(args, long*)) = (long) output->pos;
  1160. #ifdef RT_KLIBC_USING_VSNPRINTF_LONGLONG
  1161. else if (flags & FLAGS_LONG_LONG) *(va_arg(args, long long*)) = (long long int) output->pos;
  1162. #endif // RT_KLIBC_USING_VSNPRINTF_LONGLONG
  1163. else *(va_arg(args, int*)) = (int) output->pos;
  1164. format++;
  1165. break;
  1166. }
  1167. #endif // RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER
  1168. default :
  1169. putchar_via_gadget(output, *format);
  1170. format++;
  1171. break;
  1172. }
  1173. }
  1174. }
  1175. // internal vsnprintf - used for implementing _all library functions
  1176. static int vsnprintf_impl(output_gadget_t* output, const char* format, va_list args)
  1177. {
  1178. // Note: The library only calls vsnprintf_impl() with output->pos being 0. However, it is
  1179. // possible to call this function with a non-zero pos value for some "remedial printing".
  1180. format_string_loop(output, format, args);
  1181. // termination
  1182. append_termination_with_gadget(output);
  1183. // return written chars without terminating \0
  1184. return (int)output->pos;
  1185. }
  1186. ///////////////////////////////////////////////////////////////////////////////
  1187. /**
  1188. * @brief This function will fill a formatted string to buffer.
  1189. *
  1190. * @param buf is the buffer to save formatted string.
  1191. *
  1192. * @param size is the size of buffer.
  1193. *
  1194. * @param fmt is the format parameters.
  1195. *
  1196. * @param args is a list of variable parameters.
  1197. *
  1198. * @return The number of characters actually written to buffer.
  1199. */
  1200. int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args)
  1201. {
  1202. output_gadget_t gadget = buffer_gadget(buf, size);
  1203. return vsnprintf_impl(&gadget, fmt, args);
  1204. }