snprintf.c 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031
  1. /* $Id: snprintf.c,v 1.9 2008/01/20 14:02:00 holger Exp $ */
  2. /*
  3. * Copyright (c) 1995 Patrick Powell.
  4. *
  5. * This code is based on code written by Patrick Powell <papowell@astart.com>.
  6. * It may be used for any purpose as long as this notice remains intact on all
  7. * source code distributions.
  8. */
  9. /*
  10. * Copyright (c) 2008 Holger Weiss.
  11. *
  12. * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>.
  13. * My changes to the code may freely be used, modified and/or redistributed for
  14. * any purpose. It would be nice if additions and fixes to this file (including
  15. * trivial code cleanups) would be sent back in order to let me include them in
  16. * the version available at <http://www.jhweiss.de/software/snprintf.html>.
  17. * However, this is not a requirement for using or redistributing (possibly
  18. * modified) versions of this file, nor is leaving this notice intact mandatory.
  19. */
  20. /*
  21. * History
  22. *
  23. * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1:
  24. *
  25. * Fixed the detection of infinite floating point values on IRIX (and
  26. * possibly other systems) and applied another few minor cleanups.
  27. *
  28. * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0:
  29. *
  30. * Added a lot of new features, fixed many bugs, and incorporated various
  31. * improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery
  32. * <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller
  33. * <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH
  34. * projects. The additions include: support the "e", "E", "g", "G", and
  35. * "F" conversion specifiers (and use conversion style "f" or "F" for the
  36. * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
  37. * "t", and "z" length modifiers; support the "#" flag and the (non-C99)
  38. * "'" flag; use localeconv(3) (if available) to get both the current
  39. * locale's decimal point character and the separator between groups of
  40. * digits; fix the handling of various corner cases of field width and
  41. * precision specifications; fix various floating point conversion bugs;
  42. * handle infinite and NaN floating point values; don't attempt to write to
  43. * the output buffer (which may be NULL) if a size of zero was specified;
  44. * check for integer overflow of the field width, precision, and return
  45. * values and during the floating point conversion; use the OUTCHAR() macro
  46. * instead of a function for better performance; provide asprintf(3) and
  47. * vasprintf(3) functions; add new test cases. The replacement functions
  48. * have been renamed to use an "rpl_" prefix, the function calls in the
  49. * main project (and in this file) must be redefined accordingly for each
  50. * replacement function which is needed (by using Autoconf or other means).
  51. * Various other minor improvements have been applied and the coding style
  52. * was cleaned up for consistency.
  53. *
  54. * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13:
  55. *
  56. * C99 compliant snprintf(3) and vsnprintf(3) functions return the number
  57. * of characters that would have been written to a sufficiently sized
  58. * buffer (excluding the '\0'). The original code simply returned the
  59. * length of the resulting output string, so that's been fixed.
  60. *
  61. * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8:
  62. *
  63. * The original code assumed that both snprintf(3) and vsnprintf(3) were
  64. * missing. Some systems only have snprintf(3) but not vsnprintf(3), so
  65. * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
  66. *
  67. * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i:
  68. *
  69. * The PGP code was using unsigned hexadecimal formats. Unfortunately,
  70. * unsigned formats simply didn't work.
  71. *
  72. * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1:
  73. *
  74. * Ok, added some minimal floating point support, which means this probably
  75. * requires libm on most operating systems. Don't yet support the exponent
  76. * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just
  77. * wasn't being exercised in ways which showed it, so that's been fixed.
  78. * Also, formatted the code to Mutt conventions, and removed dead code left
  79. * over from the original. Also, there is now a builtin-test, run with:
  80. * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
  81. *
  82. * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43:
  83. *
  84. * This was ugly. It is still ugly. I opted out of floating point
  85. * numbers, but the formatter understands just about everything from the
  86. * normal C string format, at least as far as I can tell from the Solaris
  87. * 2.5 printf(3S) man page.
  88. */
  89. /*
  90. * ToDo
  91. *
  92. * - Add wide character support.
  93. * - Add support for "%a" and "%A" conversions.
  94. * - Create test routines which predefine the expected results. Our test cases
  95. * usually expose bugs in system implementations rather than in ours :-)
  96. */
  97. /*
  98. * Usage
  99. *
  100. * 1) The following preprocessor macros should be defined to 1 if the feature or
  101. * file in question is available on the target system (by using Autoconf or
  102. * other means), though basic functionality should be available as long as
  103. * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly:
  104. *
  105. * HAVE_VSNPRINTF
  106. * HAVE_SNPRINTF
  107. * HAVE_VASPRINTF
  108. * HAVE_ASPRINTF
  109. * HAVE_STDARG_H
  110. * HAVE_STDDEF_H
  111. * HAVE_STDINT_H
  112. * HAVE_STDLIB_H
  113. * HAVE_INTTYPES_H
  114. * HAVE_LOCALE_H
  115. * HAVE_LOCALECONV
  116. * HAVE_LCONV_DECIMAL_POINT
  117. * HAVE_LCONV_THOUSANDS_SEP
  118. * HAVE_LONG_DOUBLE
  119. * HAVE_LONG_LONG_INT
  120. * HAVE_UNSIGNED_LONG_LONG_INT
  121. * HAVE_INTMAX_T
  122. * HAVE_UINTMAX_T
  123. * HAVE_UINTPTR_T
  124. * HAVE_PTRDIFF_T
  125. * HAVE_VA_COPY
  126. * HAVE___VA_COPY
  127. *
  128. * 2) The calls to the functions which should be replaced must be redefined
  129. * throughout the project files (by using Autoconf or other means):
  130. *
  131. * #define vsnprintf rpl_vsnprintf
  132. * #define snprintf rpl_snprintf
  133. * #define vasprintf rpl_vasprintf
  134. * #define asprintf rpl_asprintf
  135. *
  136. * 3) The required replacement functions should be declared in some header file
  137. * included throughout the project files:
  138. *
  139. * #if HAVE_CONFIG_H
  140. * #include <config.h>
  141. * #endif
  142. * #if HAVE_STDARG_H
  143. * #include <stdarg.h>
  144. * #if !HAVE_VSNPRINTF
  145. * int rpl_vsnprintf(char *, size_t, const char *, va_list);
  146. * #endif
  147. * #if !HAVE_SNPRINTF
  148. * int rpl_snprintf(char *, size_t, const char *, ...);
  149. * #endif
  150. * #if !HAVE_VASPRINTF
  151. * int rpl_vasprintf(char **, const char *, va_list);
  152. * #endif
  153. * #if !HAVE_ASPRINTF
  154. * int rpl_asprintf(char **, const char *, ...);
  155. * #endif
  156. * #endif
  157. *
  158. * Autoconf macros for handling step 1 and step 2 are available at
  159. * <http://www.jhweiss.de/software/snprintf.html>.
  160. */
  161. #if HAVE_CONFIG_H
  162. #include <config.h>
  163. #endif /* HAVE_CONFIG_H */
  164. #if TEST_SNPRINTF
  165. #include <math.h> /* For pow(3), NAN, and INFINITY. */
  166. #if defined(__NetBSD__) || \
  167. defined(__FreeBSD__) || \
  168. defined(__OpenBSD__) || \
  169. defined(__NeXT__) || \
  170. defined(__bsd__)
  171. #define OS_BSD 1
  172. #elif defined(sgi) || defined(__sgi)
  173. #ifndef __c99
  174. #define __c99 /* Force C99 mode to get <stdint.h> included on IRIX 6.5.30. */
  175. #endif /* !defined(__c99) */
  176. #define OS_IRIX 1
  177. #define OS_SYSV 1
  178. #elif defined(__svr4__)
  179. #define OS_SYSV 1
  180. #elif defined(__linux__)
  181. #define OS_LINUX 1
  182. #endif /* defined(__NetBSD__) || defined(__FreeBSD__) || [...] */
  183. #if HAVE_CONFIG_H /* Undefine definitions possibly done in config.h. */
  184. #ifdef HAVE_SNPRINTF
  185. #undef HAVE_SNPRINTF
  186. #endif /* defined(HAVE_SNPRINTF) */
  187. #ifdef HAVE_VSNPRINTF
  188. #undef HAVE_VSNPRINTF
  189. #endif /* defined(HAVE_VSNPRINTF) */
  190. #ifdef snprintf
  191. #undef snprintf
  192. #endif /* defined(snprintf) */
  193. #ifdef vsnprintf
  194. #undef vsnprintf
  195. #endif /* defined(vsnprintf) */
  196. #else /* By default, we assume a modern system for testing. */
  197. #ifndef HAVE_STDARG_H
  198. #define HAVE_STDARG_H 1
  199. #endif /* HAVE_STDARG_H */
  200. #ifndef HAVE_STDDEF_H
  201. #define HAVE_STDDEF_H 1
  202. #endif /* HAVE_STDDEF_H */
  203. #ifndef HAVE_STDINT_H
  204. #define HAVE_STDINT_H 1
  205. #endif /* HAVE_STDINT_H */
  206. #ifndef HAVE_STDLIB_H
  207. #define HAVE_STDLIB_H 1
  208. #endif /* HAVE_STDLIB_H */
  209. #ifndef HAVE_INTTYPES_H
  210. #define HAVE_INTTYPES_H 1
  211. #endif /* HAVE_INTTYPES_H */
  212. #ifndef HAVE_LOCALE_H
  213. #define HAVE_LOCALE_H 1
  214. #endif /* HAVE_LOCALE_H */
  215. #ifndef HAVE_LOCALECONV
  216. #define HAVE_LOCALECONV 1
  217. #endif /* !defined(HAVE_LOCALECONV) */
  218. #ifndef HAVE_LCONV_DECIMAL_POINT
  219. #define HAVE_LCONV_DECIMAL_POINT 1
  220. #endif /* HAVE_LCONV_DECIMAL_POINT */
  221. #ifndef HAVE_LCONV_THOUSANDS_SEP
  222. #define HAVE_LCONV_THOUSANDS_SEP 1
  223. #endif /* HAVE_LCONV_THOUSANDS_SEP */
  224. #ifndef HAVE_LONG_DOUBLE
  225. #define HAVE_LONG_DOUBLE 1
  226. #endif /* !defined(HAVE_LONG_DOUBLE) */
  227. #ifndef HAVE_LONG_LONG_INT
  228. #define HAVE_LONG_LONG_INT 1
  229. #endif /* !defined(HAVE_LONG_LONG_INT) */
  230. #ifndef HAVE_UNSIGNED_LONG_LONG_INT
  231. #define HAVE_UNSIGNED_LONG_LONG_INT 1
  232. #endif /* !defined(HAVE_UNSIGNED_LONG_LONG_INT) */
  233. #ifndef HAVE_INTMAX_T
  234. #define HAVE_INTMAX_T 1
  235. #endif /* !defined(HAVE_INTMAX_T) */
  236. #ifndef HAVE_UINTMAX_T
  237. #define HAVE_UINTMAX_T 1
  238. #endif /* !defined(HAVE_UINTMAX_T) */
  239. #ifndef HAVE_UINTPTR_T
  240. #define HAVE_UINTPTR_T 1
  241. #endif /* !defined(HAVE_UINTPTR_T) */
  242. #ifndef HAVE_PTRDIFF_T
  243. #define HAVE_PTRDIFF_T 1
  244. #endif /* !defined(HAVE_PTRDIFF_T) */
  245. #ifndef HAVE_VA_COPY
  246. #define HAVE_VA_COPY 1
  247. #endif /* !defined(HAVE_VA_COPY) */
  248. #ifndef HAVE___VA_COPY
  249. #define HAVE___VA_COPY 1
  250. #endif /* !defined(HAVE___VA_COPY) */
  251. #endif /* HAVE_CONFIG_H */
  252. #define snprintf rpl_snprintf
  253. #define vsnprintf rpl_vsnprintf
  254. #endif /* TEST_SNPRINTF */
  255. #if !HAVE_SNPRINTF || !HAVE_VSNPRINTF
  256. #include <stdio.h> /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */
  257. #include <string.h> /* For strcmp(3) and memset(3). */
  258. #ifdef VA_START
  259. #undef VA_START
  260. #endif /* defined(VA_START) */
  261. #ifdef VA_SHIFT
  262. #undef VA_SHIFT
  263. #endif /* defined(VA_SHIFT) */
  264. #if HAVE_STDARG_H
  265. #include <stdarg.h>
  266. #define VA_START(ap, last) va_start(ap, last)
  267. #define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
  268. #else /* Assume <varargs.h> is available. */
  269. #include <varargs.h>
  270. #define VA_START(ap, last) va_start(ap) /* "last" is ignored. */
  271. #define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
  272. #endif /* HAVE_STDARG_H */
  273. #if !HAVE_VSNPRINTF
  274. #include <errno.h> /* For ERANGE and errno. */
  275. #include <limits.h> /* For *_MAX. */
  276. #if HAVE_INTTYPES_H
  277. #include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */
  278. #endif /* HAVE_INTTYPES_H */
  279. #if HAVE_LOCALE_H
  280. #include <locale.h> /* For localeconv(3). */
  281. #endif /* HAVE_LOCALE_H */
  282. #if HAVE_STDDEF_H
  283. #include <stddef.h> /* For ptrdiff_t. */
  284. #endif /* HAVE_STDDEF_H */
  285. #if HAVE_STDINT_H
  286. #include <stdint.h> /* For intmax_t. */
  287. #endif /* HAVE_STDINT_H */
  288. /* Support for unsigned long long int. We may also need ULLONG_MAX. */
  289. #ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */
  290. #ifdef UINT_MAX
  291. #define ULONG_MAX UINT_MAX
  292. #else
  293. #define ULONG_MAX INT_MAX
  294. #endif /* defined(UINT_MAX) */
  295. #endif /* !defined(ULONG_MAX) */
  296. #ifdef ULLONG
  297. #undef ULLONG
  298. #endif /* defined(ULLONG) */
  299. #if HAVE_UNSIGNED_LONG_LONG_INT
  300. #define ULLONG unsigned long long int
  301. #ifndef ULLONG_MAX
  302. #define ULLONG_MAX ULONG_MAX
  303. #endif /* !defined(ULLONG_MAX) */
  304. #else
  305. #define ULLONG unsigned long int
  306. #ifdef ULLONG_MAX
  307. #undef ULLONG_MAX
  308. #endif /* defined(ULLONG_MAX) */
  309. #define ULLONG_MAX ULONG_MAX
  310. #endif /* HAVE_LONG_LONG_INT */
  311. /* Support for uintmax_t. We also need UINTMAX_MAX. */
  312. #ifdef UINTMAX_T
  313. #undef UINTMAX_T
  314. #endif /* defined(UINTMAX_T) */
  315. #if defined(HAVE_UINTMAX_T) || defined(uintmax_t)
  316. #define UINTMAX_T uintmax_t
  317. #ifndef UINTMAX_MAX
  318. #define UINTMAX_MAX ULLONG_MAX
  319. #endif /* !defined(UINTMAX_MAX) */
  320. #else
  321. #define UINTMAX_T ULLONG
  322. #ifdef UINTMAX_MAX
  323. #undef UINTMAX_MAX
  324. #endif /* defined(UINTMAX_MAX) */
  325. #define UINTMAX_MAX ULLONG_MAX
  326. #endif /* HAVE_UINTMAX_T || defined(uintmax_t) */
  327. /* Support for long double. */
  328. #ifndef LDOUBLE
  329. #if HAVE_LONG_DOUBLE
  330. #define LDOUBLE long double
  331. #else
  332. #define LDOUBLE double
  333. #endif /* HAVE_LONG_DOUBLE */
  334. #endif /* !defined(LDOUBLE) */
  335. /* Support for long long int. */
  336. #ifndef LLONG
  337. #if HAVE_LONG_LONG_INT
  338. #define LLONG long long int
  339. #else
  340. #define LLONG long int
  341. #endif /* HAVE_LONG_LONG_INT */
  342. #endif /* !defined(LLONG) */
  343. /* Support for intmax_t. */
  344. #ifndef INTMAX_T
  345. #if defined(HAVE_INTMAX_T) || defined(intmax_t)
  346. #define INTMAX_T intmax_t
  347. #else
  348. #define INTMAX_T LLONG
  349. #endif /* HAVE_INTMAX_T || defined(intmax_t) */
  350. #endif /* !defined(INTMAX_T) */
  351. /* Support for uintptr_t. */
  352. #ifndef UINTPTR_T
  353. #if defined(HAVE_UINTPTR_T) || defined(uintptr_t)
  354. #define UINTPTR_T uintptr_t
  355. #else
  356. #define UINTPTR_T unsigned long int
  357. #endif /* HAVE_UINTPTR_T || defined(uintptr_t) */
  358. #endif /* !defined(UINTPTR_T) */
  359. /* Support for ptrdiff_t. */
  360. #ifndef PTRDIFF_T
  361. #if defined(HAVE_PTRDIFF_T) || defined(ptrdiff_t)
  362. #define PTRDIFF_T ptrdiff_t
  363. #else
  364. #define PTRDIFF_T long int
  365. #endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
  366. #endif /* !defined(PTRDIFF_T) */
  367. /*
  368. * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
  369. * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an
  370. * unsigned type if necessary. This should work just fine in practice.
  371. */
  372. #ifndef UPTRDIFF_T
  373. #define UPTRDIFF_T PTRDIFF_T
  374. #endif /* !defined(UPTRDIFF_T) */
  375. /*
  376. * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
  377. * However, we'll simply use size_t and convert it to a signed type if
  378. * necessary. This should work just fine in practice.
  379. */
  380. #ifndef SSIZE_T
  381. #define SSIZE_T size_t
  382. #endif /* !defined(SSIZE_T) */
  383. /* Either ERANGE or E2BIG should be available everywhere. */
  384. #ifndef ERANGE
  385. #define ERANGE E2BIG
  386. #endif /* !defined(ERANGE) */
  387. #ifndef EOVERFLOW
  388. #define EOVERFLOW ERANGE
  389. #endif /* !defined(EOVERFLOW) */
  390. /*
  391. * Buffer size to hold the octal string representation of UINT128_MAX without
  392. * nul-termination ("3777777777777777777777777777777777777777777").
  393. */
  394. #ifdef MAX_CONVERT_LENGTH
  395. #undef MAX_CONVERT_LENGTH
  396. #endif /* defined(MAX_CONVERT_LENGTH) */
  397. #define MAX_CONVERT_LENGTH 43
  398. /* Format read states. */
  399. #define PRINT_S_DEFAULT 0
  400. #define PRINT_S_FLAGS 1
  401. #define PRINT_S_WIDTH 2
  402. #define PRINT_S_DOT 3
  403. #define PRINT_S_PRECISION 4
  404. #define PRINT_S_MOD 5
  405. #define PRINT_S_CONV 6
  406. /* Format flags. */
  407. #define PRINT_F_MINUS (1 << 0)
  408. #define PRINT_F_PLUS (1 << 1)
  409. #define PRINT_F_SPACE (1 << 2)
  410. #define PRINT_F_NUM (1 << 3)
  411. #define PRINT_F_ZERO (1 << 4)
  412. #define PRINT_F_QUOTE (1 << 5)
  413. #define PRINT_F_UP (1 << 6)
  414. #define PRINT_F_UNSIGNED (1 << 7)
  415. #define PRINT_F_TYPE_G (1 << 8)
  416. #define PRINT_F_TYPE_E (1 << 9)
  417. /* Conversion flags. */
  418. #define PRINT_C_CHAR 1
  419. #define PRINT_C_SHORT 2
  420. #define PRINT_C_LONG 3
  421. /*#define PRINT_C_LLONG 4 */
  422. #define PRINT_C_LDOUBLE 5
  423. #define PRINT_C_SIZE 6
  424. #define PRINT_C_PTRDIFF 7
  425. #define PRINT_C_INTMAX 8
  426. #ifndef MAX
  427. #define MAX(x, y) ((x >= y) ? x : y)
  428. #endif /* !defined(MAX) */
  429. #ifndef CHARTOINT
  430. #define CHARTOINT(ch) (ch - '0')
  431. #endif /* !defined(CHARTOINT) */
  432. #ifndef ISDIGIT
  433. #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
  434. #endif /* !defined(ISDIGIT) */
  435. #ifndef ISNAN
  436. #define ISNAN(x) (x != x)
  437. #endif /* !defined(ISNAN) */
  438. #ifndef ISINF
  439. #define ISINF(x) (x != 0.0 && x + x == x)
  440. #endif /* !defined(ISINF) */
  441. #ifdef OUTCHAR
  442. #undef OUTCHAR
  443. #endif /* defined(OUTCHAR) */
  444. #define OUTCHAR(str, len, size, ch) \
  445. do { \
  446. if (len + 1 < size) \
  447. str[len] = ch; \
  448. (len)++; \
  449. } while (/* CONSTCOND */ 0)
  450. static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
  451. static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
  452. static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
  453. static void printsep(char *, size_t *, size_t);
  454. static int getnumsep(int);
  455. static int getexponent(LDOUBLE);
  456. static int convert(UINTMAX_T, char *, size_t, int, int);
  457. static UINTMAX_T cast(LDOUBLE);
  458. static UINTMAX_T myround(LDOUBLE);
  459. static LDOUBLE mypow10(int);
  460. #if HAVE_VSNPRINTF
  461. /* errno is imported from <errno.h> when available.
  462. * Otherwise we declare it ourselves.
  463. **/
  464. extern int errno;
  465. #endif
  466. int
  467. rpl_vsnprintf(char *str, size_t size, const char *format, va_list args)
  468. {
  469. LDOUBLE fvalue;
  470. INTMAX_T value;
  471. unsigned char cvalue;
  472. const char *strvalue;
  473. INTMAX_T *intmaxptr;
  474. PTRDIFF_T *ptrdiffptr;
  475. SSIZE_T *sizeptr;
  476. /* Disabling, as long long is not supported in C90.
  477. LLONG *llongptr;
  478. */
  479. long int *longptr;
  480. int *intptr;
  481. short int *shortptr;
  482. signed char *charptr;
  483. size_t len = 0;
  484. int overflow = 0;
  485. int base = 0;
  486. int cflags = 0;
  487. int flags = 0;
  488. int width = 0;
  489. int precision = -1;
  490. int state = PRINT_S_DEFAULT;
  491. char ch = *format++;
  492. /*
  493. * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
  494. * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer
  495. * even if a size larger than zero was specified. At least NetBSD's
  496. * snprintf(3) does the same, as well as other versions of this file.
  497. * (Though some of these versions will write to a non-NULL buffer even
  498. * if a size of zero was specified, which violates the standard.)
  499. */
  500. if (str == NULL && size != 0)
  501. size = 0;
  502. while (ch != '\0')
  503. switch (state) {
  504. case PRINT_S_DEFAULT:
  505. if (ch == '%')
  506. state = PRINT_S_FLAGS;
  507. else
  508. OUTCHAR(str, len, size, ch);
  509. ch = *format++;
  510. break;
  511. case PRINT_S_FLAGS:
  512. switch (ch) {
  513. case '-':
  514. flags |= PRINT_F_MINUS;
  515. ch = *format++;
  516. break;
  517. case '+':
  518. flags |= PRINT_F_PLUS;
  519. ch = *format++;
  520. break;
  521. case ' ':
  522. flags |= PRINT_F_SPACE;
  523. ch = *format++;
  524. break;
  525. case '#':
  526. flags |= PRINT_F_NUM;
  527. ch = *format++;
  528. break;
  529. case '0':
  530. flags |= PRINT_F_ZERO;
  531. ch = *format++;
  532. break;
  533. case '\'': /* SUSv2 flag (not in C99). */
  534. flags |= PRINT_F_QUOTE;
  535. ch = *format++;
  536. break;
  537. default:
  538. state = PRINT_S_WIDTH;
  539. break;
  540. }
  541. break;
  542. case PRINT_S_WIDTH:
  543. if (ISDIGIT(ch)) {
  544. ch = CHARTOINT(ch);
  545. if (width > (INT_MAX - ch) / 10) {
  546. overflow = 1;
  547. goto out;
  548. }
  549. width = 10 * width + ch;
  550. ch = *format++;
  551. } else if (ch == '*') {
  552. /*
  553. * C99 says: "A negative field width argument is
  554. * taken as a `-' flag followed by a positive
  555. * field width." (7.19.6.1, 5)
  556. */
  557. if ((width = va_arg(args, int)) < 0) {
  558. flags |= PRINT_F_MINUS;
  559. width = -width;
  560. }
  561. ch = *format++;
  562. state = PRINT_S_DOT;
  563. } else
  564. state = PRINT_S_DOT;
  565. break;
  566. case PRINT_S_DOT:
  567. if (ch == '.') {
  568. state = PRINT_S_PRECISION;
  569. ch = *format++;
  570. } else
  571. state = PRINT_S_MOD;
  572. break;
  573. case PRINT_S_PRECISION:
  574. if (precision == -1)
  575. precision = 0;
  576. if (ISDIGIT(ch)) {
  577. ch = CHARTOINT(ch);
  578. if (precision > (INT_MAX - ch) / 10) {
  579. overflow = 1;
  580. goto out;
  581. }
  582. precision = 10 * precision + ch;
  583. ch = *format++;
  584. } else if (ch == '*') {
  585. /*
  586. * C99 says: "A negative precision argument is
  587. * taken as if the precision were omitted."
  588. * (7.19.6.1, 5)
  589. */
  590. if ((precision = va_arg(args, int)) < 0)
  591. precision = -1;
  592. ch = *format++;
  593. state = PRINT_S_MOD;
  594. } else
  595. state = PRINT_S_MOD;
  596. break;
  597. case PRINT_S_MOD:
  598. switch (ch) {
  599. case 'h':
  600. ch = *format++;
  601. if (ch == 'h') { /* It's a char. */
  602. ch = *format++;
  603. cflags = PRINT_C_CHAR;
  604. } else
  605. cflags = PRINT_C_SHORT;
  606. break;
  607. case 'l':
  608. ch = *format++;
  609. /*
  610. if (ch == 'l') }
  611. ch = *format++;
  612. cflags = PRINT_C_LLONG;
  613. } else */
  614. cflags = PRINT_C_LONG;
  615. break;
  616. case 'L':
  617. cflags = PRINT_C_LDOUBLE;
  618. ch = *format++;
  619. break;
  620. case 'j':
  621. cflags = PRINT_C_INTMAX;
  622. ch = *format++;
  623. break;
  624. case 't':
  625. cflags = PRINT_C_PTRDIFF;
  626. ch = *format++;
  627. break;
  628. case 'z':
  629. cflags = PRINT_C_SIZE;
  630. ch = *format++;
  631. break;
  632. default:
  633. /* Lenght modifier is invalid */
  634. break;
  635. }
  636. state = PRINT_S_CONV;
  637. break;
  638. case PRINT_S_CONV:
  639. switch (ch) {
  640. case 'd':
  641. /* FALLTHROUGH */
  642. case 'i':
  643. switch (cflags) {
  644. case PRINT_C_CHAR:
  645. value = (signed char)va_arg(args, int);
  646. break;
  647. case PRINT_C_SHORT:
  648. value = (short int)va_arg(args, int);
  649. break;
  650. case PRINT_C_LONG:
  651. value = va_arg(args, long int);
  652. break;
  653. /*
  654. case PRINT_C_LLONG:
  655. value = va_arg(args, LLONG);
  656. break;
  657. */
  658. case PRINT_C_SIZE:
  659. value = va_arg(args, SSIZE_T);
  660. break;
  661. case PRINT_C_INTMAX:
  662. value = va_arg(args, INTMAX_T);
  663. break;
  664. case PRINT_C_PTRDIFF:
  665. value = va_arg(args, PTRDIFF_T);
  666. break;
  667. default:
  668. value = va_arg(args, int);
  669. break;
  670. }
  671. fmtint(str, &len, size, value, 10, width,
  672. precision, flags);
  673. break;
  674. case 'X':
  675. flags |= PRINT_F_UP;
  676. /* FALLTHROUGH */
  677. case 'x':
  678. base = 16;
  679. /* FALLTHROUGH */
  680. case 'o':
  681. if (base == 0)
  682. base = 8;
  683. /* FALLTHROUGH */
  684. case 'u':
  685. if (base == 0)
  686. base = 10;
  687. flags |= PRINT_F_UNSIGNED;
  688. switch (cflags) {
  689. case PRINT_C_CHAR:
  690. value = (unsigned char)va_arg(args,
  691. unsigned int);
  692. break;
  693. case PRINT_C_SHORT:
  694. value = (unsigned short int)va_arg(args,
  695. unsigned int);
  696. break;
  697. case PRINT_C_LONG:
  698. value = va_arg(args, unsigned long int);
  699. break;
  700. /*
  701. case PRINT_C_LLONG:
  702. value = va_arg(args, ULLONG);
  703. break;
  704. */
  705. case PRINT_C_SIZE:
  706. value = va_arg(args, size_t);
  707. break;
  708. case PRINT_C_INTMAX:
  709. value = va_arg(args, UINTMAX_T);
  710. break;
  711. case PRINT_C_PTRDIFF:
  712. value = va_arg(args, UPTRDIFF_T);
  713. break;
  714. default:
  715. value = va_arg(args, unsigned int);
  716. break;
  717. }
  718. fmtint(str, &len, size, value, base, width,
  719. precision, flags);
  720. break;
  721. case 'A':
  722. /* Not yet supported, we'll use "%F". */
  723. /* FALLTHROUGH */
  724. case 'F':
  725. flags |= PRINT_F_UP;
  726. case 'a':
  727. /* Not yet supported, we'll use "%f". */
  728. /* FALLTHROUGH */
  729. case 'f':
  730. if (cflags == PRINT_C_LDOUBLE)
  731. fvalue = va_arg(args, LDOUBLE);
  732. else
  733. fvalue = va_arg(args, double);
  734. fmtflt(str, &len, size, fvalue, width,
  735. precision, flags, &overflow);
  736. if (overflow)
  737. goto out;
  738. break;
  739. case 'E':
  740. flags |= PRINT_F_UP;
  741. /* FALLTHROUGH */
  742. case 'e':
  743. flags |= PRINT_F_TYPE_E;
  744. if (cflags == PRINT_C_LDOUBLE)
  745. fvalue = va_arg(args, LDOUBLE);
  746. else
  747. fvalue = va_arg(args, double);
  748. fmtflt(str, &len, size, fvalue, width,
  749. precision, flags, &overflow);
  750. if (overflow)
  751. goto out;
  752. break;
  753. case 'G':
  754. flags |= PRINT_F_UP;
  755. /* FALLTHROUGH */
  756. case 'g':
  757. flags |= PRINT_F_TYPE_G;
  758. if (cflags == PRINT_C_LDOUBLE)
  759. fvalue = va_arg(args, LDOUBLE);
  760. else
  761. fvalue = va_arg(args, double);
  762. /*
  763. * If the precision is zero, it is treated as
  764. * one (cf. C99: 7.19.6.1, 8).
  765. */
  766. if (precision == 0)
  767. precision = 1;
  768. fmtflt(str, &len, size, fvalue, width,
  769. precision, flags, &overflow);
  770. if (overflow)
  771. goto out;
  772. break;
  773. case 'c':
  774. cvalue = va_arg(args, int);
  775. OUTCHAR(str, len, size, cvalue);
  776. break;
  777. case 's':
  778. strvalue = va_arg(args, char *);
  779. fmtstr(str, &len, size, strvalue, width,
  780. precision, flags);
  781. break;
  782. case 'p':
  783. /*
  784. * C99 says: "The value of the pointer is
  785. * converted to a sequence of printing
  786. * characters, in an implementation-defined
  787. * manner." (C99: 7.19.6.1, 8)
  788. */
  789. if ((strvalue = (const char *)va_arg(args, void *)) == NULL)
  790. /*
  791. * We use the glibc format. BSD prints
  792. * "0x0", SysV "0".
  793. */
  794. fmtstr(str, &len, size, "(nil)", width,
  795. -1, flags);
  796. else {
  797. /*
  798. * We use the BSD/glibc format. SysV
  799. * omits the "0x" prefix (which we emit
  800. * using the PRINT_F_NUM flag).
  801. */
  802. flags |= PRINT_F_NUM;
  803. flags |= PRINT_F_UNSIGNED;
  804. fmtint(str, &len, size,
  805. (UINTPTR_T)strvalue, 16, width,
  806. precision, flags);
  807. }
  808. break;
  809. case 'n':
  810. switch (cflags) {
  811. case PRINT_C_CHAR:
  812. charptr = va_arg(args, signed char *);
  813. *charptr = len;
  814. break;
  815. case PRINT_C_SHORT:
  816. shortptr = va_arg(args, short int *);
  817. *shortptr = len;
  818. break;
  819. case PRINT_C_LONG:
  820. longptr = va_arg(args, long int *);
  821. *longptr = len;
  822. break;
  823. /*
  824. case PRINT_C_LLONG:
  825. llongptr = va_arg(args, LLONG *);
  826. *llongptr = len;
  827. break;
  828. */
  829. case PRINT_C_SIZE:
  830. /*
  831. * C99 says that with the "z" length
  832. * modifier, "a following `n' conversion
  833. * specifier applies to a pointer to a
  834. * signed integer type corresponding to
  835. * size_t argument." (7.19.6.1, 7)
  836. */
  837. sizeptr = va_arg(args, SSIZE_T *);
  838. *sizeptr = len;
  839. break;
  840. case PRINT_C_INTMAX:
  841. intmaxptr = va_arg(args, INTMAX_T *);
  842. *intmaxptr = len;
  843. break;
  844. case PRINT_C_PTRDIFF:
  845. ptrdiffptr = va_arg(args, PTRDIFF_T *);
  846. *ptrdiffptr = len;
  847. break;
  848. default:
  849. intptr = va_arg(args, int *);
  850. *intptr = len;
  851. break;
  852. }
  853. break;
  854. case '%': /* Print a "%" character verbatim. */
  855. OUTCHAR(str, len, size, ch);
  856. break;
  857. default: /* Skip other characters. */
  858. break;
  859. }
  860. ch = *format++;
  861. state = PRINT_S_DEFAULT;
  862. base = cflags = flags = width = 0;
  863. precision = -1;
  864. break;
  865. default:
  866. /* This is an invalid state, should not get here */
  867. break;
  868. }
  869. out:
  870. if (len < size)
  871. str[len] = '\0';
  872. else if (size > 0)
  873. str[size - 1] = '\0';
  874. if (overflow || len >= INT_MAX) {
  875. errno = overflow ? EOVERFLOW : ERANGE;
  876. return -1;
  877. }
  878. return (int)len;
  879. }
  880. static void
  881. fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
  882. int precision, int flags)
  883. {
  884. int padlen, strln; /* Amount to pad. */
  885. int noprecision = (precision == -1);
  886. if (value == NULL) /* We're forgiving. */
  887. value = "(null)";
  888. /* If a precision was specified, don't read the string past it. */
  889. for (strln = 0; value[strln] != '\0' &&
  890. (noprecision || strln < precision); strln++)
  891. continue;
  892. if ((padlen = width - strln) < 0)
  893. padlen = 0;
  894. if (flags & PRINT_F_MINUS) /* Left justify. */
  895. padlen = -padlen;
  896. while (padlen > 0) { /* Leading spaces. */
  897. OUTCHAR(str, *len, size, ' ');
  898. padlen--;
  899. }
  900. while (*value != '\0' && (noprecision || precision-- > 0)) {
  901. OUTCHAR(str, *len, size, *value);
  902. value++;
  903. }
  904. while (padlen < 0) { /* Trailing spaces. */
  905. OUTCHAR(str, *len, size, ' ');
  906. padlen++;
  907. }
  908. }
  909. static void
  910. fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
  911. int precision, int flags)
  912. {
  913. UINTMAX_T uvalue;
  914. char iconvert[MAX_CONVERT_LENGTH];
  915. char sign = 0;
  916. char hexprefix = 0;
  917. int spadlen = 0; /* Amount to space pad. */
  918. int zpadlen = 0; /* Amount to zero pad. */
  919. int pos;
  920. int separators = (flags & PRINT_F_QUOTE);
  921. int noprecision = (precision == -1);
  922. if (flags & PRINT_F_UNSIGNED)
  923. uvalue = value;
  924. else {
  925. uvalue = (value >= 0) ? value : -value;
  926. if (value < 0)
  927. sign = '-';
  928. else if (flags & PRINT_F_PLUS) /* Do a sign. */
  929. sign = '+';
  930. else if (flags & PRINT_F_SPACE)
  931. sign = ' ';
  932. }
  933. pos = convert(uvalue, iconvert, sizeof(iconvert), base,
  934. flags & PRINT_F_UP);
  935. if (flags & PRINT_F_NUM && uvalue != 0) {
  936. /*
  937. * C99 says: "The result is converted to an `alternative form'.
  938. * For `o' conversion, it increases the precision, if and only
  939. * if necessary, to force the first digit of the result to be a
  940. * zero (if the value and precision are both 0, a single 0 is
  941. * printed). For `x' (or `X') conversion, a nonzero result has
  942. * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
  943. */
  944. switch (base) {
  945. case 8:
  946. if (precision <= pos)
  947. precision = pos + 1;
  948. break;
  949. case 16:
  950. hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
  951. break;
  952. default:
  953. /* Invalid base */
  954. break;
  955. }
  956. }
  957. if (separators) /* Get the number of group separators we'll print. */
  958. separators = getnumsep(pos);
  959. zpadlen = precision - pos - separators;
  960. spadlen = width /* Minimum field width. */
  961. - separators /* Number of separators. */
  962. - MAX(precision, pos) /* Number of integer digits. */
  963. - ((sign != 0) ? 1 : 0) /* Will we print a sign? */
  964. - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */
  965. if (zpadlen < 0)
  966. zpadlen = 0;
  967. if (spadlen < 0)
  968. spadlen = 0;
  969. /*
  970. * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
  971. * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a
  972. * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
  973. */
  974. if (flags & PRINT_F_MINUS) /* Left justify. */
  975. spadlen = -spadlen;
  976. else if (flags & PRINT_F_ZERO && noprecision) {
  977. zpadlen += spadlen;
  978. spadlen = 0;
  979. }
  980. while (spadlen > 0) { /* Leading spaces. */
  981. OUTCHAR(str, *len, size, ' ');
  982. spadlen--;
  983. }
  984. if (sign != 0) /* Sign. */
  985. OUTCHAR(str, *len, size, sign);
  986. if (hexprefix != 0) { /* A "0x" or "0X" prefix. */
  987. OUTCHAR(str, *len, size, '0');
  988. OUTCHAR(str, *len, size, hexprefix);
  989. }
  990. while (zpadlen > 0) { /* Leading zeros. */
  991. OUTCHAR(str, *len, size, '0');
  992. zpadlen--;
  993. }
  994. while (pos > 0) { /* The actual digits. */
  995. pos--;
  996. OUTCHAR(str, *len, size, iconvert[pos]);
  997. if (separators > 0 && pos > 0 && pos % 3 == 0)
  998. printsep(str, len, size);
  999. }
  1000. while (spadlen < 0) { /* Trailing spaces. */
  1001. OUTCHAR(str, *len, size, ' ');
  1002. spadlen++;
  1003. }
  1004. }
  1005. static void
  1006. fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
  1007. int precision, int flags, int *overflow)
  1008. {
  1009. LDOUBLE ufvalue;
  1010. UINTMAX_T intpart;
  1011. UINTMAX_T fracpart;
  1012. UINTMAX_T mask;
  1013. const char *infnan = NULL;
  1014. char iconvert[MAX_CONVERT_LENGTH];
  1015. char fconvert[MAX_CONVERT_LENGTH];
  1016. char econvert[4]; /* "e-12" (without nul-termination). */
  1017. char esign = 0;
  1018. char sign = 0;
  1019. int leadfraczeros = 0;
  1020. int exponent = 0;
  1021. int emitpoint = 0;
  1022. int omitzeros = 0;
  1023. int omitcount = 0;
  1024. int padlen = 0;
  1025. int epos = 0;
  1026. int fpos = 0;
  1027. int ipos = 0;
  1028. int separators = (flags & PRINT_F_QUOTE);
  1029. int estyle = (flags & PRINT_F_TYPE_E);
  1030. #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
  1031. struct lconv *lc = localeconv();
  1032. #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
  1033. /* Initialize with memset because `var[n]={0}` is not supported by C90. */
  1034. memset(iconvert, '\0', MAX_CONVERT_LENGTH);
  1035. memset(fconvert, '\0', MAX_CONVERT_LENGTH);
  1036. /*
  1037. * AIX' man page says the default is 0, but C99 and at least Solaris'
  1038. * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
  1039. * defaults to 6.
  1040. */
  1041. if (precision == -1)
  1042. precision = 6;
  1043. if (fvalue < 0.0)
  1044. sign = '-';
  1045. else if (flags & PRINT_F_PLUS) /* Do a sign. */
  1046. sign = '+';
  1047. else if (flags & PRINT_F_SPACE)
  1048. sign = ' ';
  1049. if (ISNAN(fvalue))
  1050. infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
  1051. else if (ISINF(fvalue))
  1052. infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
  1053. if (infnan != NULL) {
  1054. if (sign != 0)
  1055. iconvert[ipos++] = sign;
  1056. while (*infnan != '\0')
  1057. iconvert[ipos++] = *infnan++;
  1058. fmtstr(str, len, size, iconvert, width, ipos, flags);
  1059. return;
  1060. }
  1061. /* "%e" (or "%E") or "%g" (or "%G") conversion. */
  1062. if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
  1063. if (flags & PRINT_F_TYPE_G) {
  1064. /*
  1065. * For "%g" (and "%G") conversions, the precision
  1066. * specifies the number of significant digits, which
  1067. * includes the digits in the integer part. The
  1068. * conversion will or will not be using "e-style" (like
  1069. * "%e" or "%E" conversions) depending on the precision
  1070. * and on the exponent. However, the exponent can be
  1071. * affected by rounding the converted value, so we'll
  1072. * leave this decision for later. Until then, we'll
  1073. * assume that we're going to do an "e-style" conversion
  1074. * (in order to get the exponent calculated). For
  1075. * "e-style", the precision must be decremented by one.
  1076. */
  1077. precision--;
  1078. /*
  1079. * For "%g" (and "%G") conversions, trailing zeros are
  1080. * removed from the fractional portion of the result
  1081. * unless the "#" flag was specified.
  1082. */
  1083. if (!(flags & PRINT_F_NUM))
  1084. omitzeros = 1;
  1085. }
  1086. exponent = getexponent(fvalue);
  1087. estyle = 1;
  1088. }
  1089. again:
  1090. /*
  1091. * Sorry, we only support 9, 19, or 38 digits (that is, the number of
  1092. * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
  1093. * minus one) past the decimal point due to our conversion method.
  1094. */
  1095. switch (sizeof(UINTMAX_T)) {
  1096. case 16:
  1097. if (precision > 38)
  1098. precision = 38;
  1099. break;
  1100. case 8:
  1101. if (precision > 19)
  1102. precision = 19;
  1103. break;
  1104. default:
  1105. if (precision > 9)
  1106. precision = 9;
  1107. break;
  1108. }
  1109. ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
  1110. if (estyle) /* We want exactly one integer digit. */
  1111. ufvalue /= mypow10(exponent);
  1112. if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
  1113. *overflow = 1;
  1114. return;
  1115. }
  1116. /*
  1117. * Factor of ten with the number of digits needed for the fractional
  1118. * part. For example, if the precision is 3, the mask will be 1000.
  1119. */
  1120. mask = mypow10(precision);
  1121. /*
  1122. * We "cheat" by converting the fractional part to integer by
  1123. * multiplying by a factor of ten.
  1124. */
  1125. if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
  1126. /*
  1127. * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
  1128. * (because precision = 3). Now, myround(1000 * 0.99962) will
  1129. * return 1000. So, the integer part must be incremented by one
  1130. * and the fractional part must be set to zero.
  1131. */
  1132. intpart++;
  1133. fracpart = 0;
  1134. if (estyle && intpart == 10) {
  1135. /*
  1136. * The value was rounded up to ten, but we only want one
  1137. * integer digit if using "e-style". So, the integer
  1138. * part must be set to one and the exponent must be
  1139. * incremented by one.
  1140. */
  1141. intpart = 1;
  1142. exponent++;
  1143. }
  1144. }
  1145. /*
  1146. * Now that we know the real exponent, we can check whether or not to
  1147. * use "e-style" for "%g" (and "%G") conversions. If we don't need
  1148. * "e-style", the precision must be adjusted and the integer and
  1149. * fractional parts must be recalculated from the original value.
  1150. *
  1151. * C99 says: "Let P equal the precision if nonzero, 6 if the precision
  1152. * is omitted, or 1 if the precision is zero. Then, if a conversion
  1153. * with style `E' would have an exponent of X:
  1154. *
  1155. * - if P > X >= -4, the conversion is with style `f' (or `F') and
  1156. * precision P - (X + 1).
  1157. *
  1158. * - otherwise, the conversion is with style `e' (or `E') and precision
  1159. * P - 1." (7.19.6.1, 8)
  1160. *
  1161. * Note that we had decremented the precision by one.
  1162. */
  1163. if (flags & PRINT_F_TYPE_G && estyle &&
  1164. precision + 1 > exponent && exponent >= -4) {
  1165. precision -= exponent;
  1166. estyle = 0;
  1167. goto again;
  1168. }
  1169. if (estyle) {
  1170. if (exponent < 0) {
  1171. exponent = -exponent;
  1172. esign = '-';
  1173. } else
  1174. esign = '+';
  1175. /*
  1176. * Convert the exponent. The sizeof(econvert) is 4. So, the
  1177. * econvert buffer can hold e.g. "e+99" and "e-99". We don't
  1178. * support an exponent which contains more than two digits.
  1179. * Therefore, the following stores are safe.
  1180. */
  1181. epos = convert(exponent, econvert, 2, 10, 0);
  1182. /*
  1183. * C99 says: "The exponent always contains at least two digits,
  1184. * and only as many more digits as necessary to represent the
  1185. * exponent." (7.19.6.1, 8)
  1186. */
  1187. if (epos == 1)
  1188. econvert[epos++] = '0';
  1189. econvert[epos++] = esign;
  1190. econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
  1191. }
  1192. /* Convert the integer part and the fractional part. */
  1193. ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
  1194. if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */
  1195. fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
  1196. leadfraczeros = precision - fpos;
  1197. if (omitzeros) {
  1198. if (fpos > 0) /* Omit trailing fractional part zeros. */
  1199. while (omitcount < fpos && fconvert[omitcount] == '0')
  1200. omitcount++;
  1201. else { /* The fractional part is zero, omit it completely. */
  1202. omitcount = precision;
  1203. leadfraczeros = 0;
  1204. }
  1205. precision -= omitcount;
  1206. }
  1207. /*
  1208. * Print a decimal point if either the fractional part is non-zero
  1209. * and/or the "#" flag was specified.
  1210. */
  1211. if (precision > 0 || flags & PRINT_F_NUM)
  1212. emitpoint = 1;
  1213. if (separators) /* Get the number of group separators we'll print. */
  1214. separators = getnumsep(ipos);
  1215. padlen = width /* Minimum field width. */
  1216. - ipos /* Number of integer digits. */
  1217. - epos /* Number of exponent characters. */
  1218. - precision /* Number of fractional digits. */
  1219. - separators /* Number of group separators. */
  1220. - (emitpoint ? 1 : 0) /* Will we print a decimal point? */
  1221. - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */
  1222. if (padlen < 0)
  1223. padlen = 0;
  1224. /*
  1225. * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
  1226. * ignored." (7.19.6.1, 6)
  1227. */
  1228. if (flags & PRINT_F_MINUS) /* Left justifty. */
  1229. padlen = -padlen;
  1230. else if (flags & PRINT_F_ZERO && padlen > 0) {
  1231. if (sign != 0) { /* Sign. */
  1232. OUTCHAR(str, *len, size, sign);
  1233. sign = 0;
  1234. }
  1235. while (padlen > 0) { /* Leading zeros. */
  1236. OUTCHAR(str, *len, size, '0');
  1237. padlen--;
  1238. }
  1239. }
  1240. while (padlen > 0) { /* Leading spaces. */
  1241. OUTCHAR(str, *len, size, ' ');
  1242. padlen--;
  1243. }
  1244. if (sign != 0) /* Sign. */
  1245. OUTCHAR(str, *len, size, sign);
  1246. while (ipos > 0) { /* Integer part. */
  1247. ipos--;
  1248. OUTCHAR(str, *len, size, iconvert[ipos]);
  1249. if (separators > 0 && ipos > 0 && ipos % 3 == 0)
  1250. printsep(str, len, size);
  1251. }
  1252. if (emitpoint) { /* Decimal point. */
  1253. #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
  1254. if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
  1255. OUTCHAR(str, *len, size, *lc->decimal_point);
  1256. else /* We'll always print some decimal point character. */
  1257. #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
  1258. OUTCHAR(str, *len, size, '.');
  1259. }
  1260. while (leadfraczeros > 0) { /* Leading fractional part zeros. */
  1261. OUTCHAR(str, *len, size, '0');
  1262. leadfraczeros--;
  1263. }
  1264. while (fpos > omitcount) { /* The remaining fractional part. */
  1265. fpos--;
  1266. OUTCHAR(str, *len, size, fconvert[fpos]);
  1267. }
  1268. while (epos > 0) { /* Exponent. */
  1269. epos--;
  1270. OUTCHAR(str, *len, size, econvert[epos]);
  1271. }
  1272. while (padlen < 0) { /* Trailing spaces. */
  1273. OUTCHAR(str, *len, size, ' ');
  1274. padlen++;
  1275. }
  1276. }
  1277. static void
  1278. printsep(char *str, size_t *len, size_t size)
  1279. {
  1280. #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
  1281. struct lconv *lc = localeconv();
  1282. int i;
  1283. if (lc->thousands_sep != NULL)
  1284. for (i = 0; lc->thousands_sep[i] != '\0'; i++)
  1285. OUTCHAR(str, *len, size, lc->thousands_sep[i]);
  1286. else
  1287. #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
  1288. OUTCHAR(str, *len, size, ',');
  1289. }
  1290. static int
  1291. getnumsep(int digits)
  1292. {
  1293. int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
  1294. #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
  1295. int strln;
  1296. struct lconv *lc = localeconv();
  1297. /* We support an arbitrary separator length (including zero). */
  1298. if (lc->thousands_sep != NULL) {
  1299. for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
  1300. continue;
  1301. separators *= strln;
  1302. }
  1303. #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
  1304. return separators;
  1305. }
  1306. static int
  1307. getexponent(LDOUBLE value)
  1308. {
  1309. LDOUBLE tmp = (value >= 0.0) ? value : -value;
  1310. int exponent = 0;
  1311. /*
  1312. * We check for 99 > exponent > -99 in order to work around possible
  1313. * endless loops which could happen (at least) in the second loop (at
  1314. * least) if we're called with an infinite value. However, we checked
  1315. * for infinity before calling this function using our ISINF() macro, so
  1316. * this might be somewhat paranoid.
  1317. */
  1318. while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
  1319. tmp *= 10;
  1320. while (tmp >= 10.0 && ++exponent < 99)
  1321. tmp /= 10;
  1322. return exponent;
  1323. }
  1324. static int
  1325. convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
  1326. {
  1327. const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
  1328. size_t pos = 0;
  1329. /* We return an unterminated buffer with the digits in reverse order. */
  1330. do {
  1331. buf[pos++] = digits[value % base];
  1332. value /= base;
  1333. } while (value != 0 && pos < size);
  1334. return (int)pos;
  1335. }
  1336. static UINTMAX_T
  1337. cast(LDOUBLE value)
  1338. {
  1339. UINTMAX_T result;
  1340. /*
  1341. * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
  1342. * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
  1343. * it may be increased to the nearest higher representable value for the
  1344. * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE
  1345. * value although converting the latter to UINTMAX_T would overflow.
  1346. */
  1347. if (value >= UINTMAX_MAX)
  1348. return UINTMAX_MAX;
  1349. result = value;
  1350. /*
  1351. * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
  1352. * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
  1353. * the standard). Sigh.
  1354. */
  1355. return (result <= value) ? result : result - 1;
  1356. }
  1357. static UINTMAX_T
  1358. myround(LDOUBLE value)
  1359. {
  1360. UINTMAX_T intpart = cast(value);
  1361. return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
  1362. }
  1363. static LDOUBLE
  1364. mypow10(int exponent)
  1365. {
  1366. LDOUBLE result = 1;
  1367. while (exponent > 0) {
  1368. result *= 10;
  1369. exponent--;
  1370. }
  1371. while (exponent < 0) {
  1372. result /= 10;
  1373. exponent++;
  1374. }
  1375. return result;
  1376. }
  1377. #endif /* !HAVE_VSNPRINTF */
  1378. #if !HAVE_SNPRINTF
  1379. #if HAVE_STDARG_H
  1380. int
  1381. rpl_snprintf(char *str, size_t size, const char *format, ...)
  1382. #else
  1383. int
  1384. rpl_snprintf(va_alist) va_dcl
  1385. #endif /* HAVE_STDARG_H */
  1386. {
  1387. #if !HAVE_STDARG_H
  1388. char *str;
  1389. size_t size;
  1390. char *format;
  1391. #endif /* HAVE_STDARG_H */
  1392. va_list ap;
  1393. int len;
  1394. VA_START(ap, format);
  1395. VA_SHIFT(ap, str, char *);
  1396. VA_SHIFT(ap, size, size_t);
  1397. VA_SHIFT(ap, format, const char *);
  1398. len = vsnprintf(str, size, format, ap);
  1399. va_end(ap);
  1400. return len;
  1401. }
  1402. #endif /* !HAVE_SNPRINTF */
  1403. #else /* Dummy declaration to avoid empty translation unit warnings. */
  1404. int main(void);
  1405. #endif /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF*/
  1406. #if TEST_SNPRINTF
  1407. int
  1408. main(void)
  1409. {
  1410. const char *float_fmt[] = {
  1411. /* "%E" and "%e" formats. */
  1412. #if HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX
  1413. "%.16e",
  1414. "%22.16e",
  1415. "%022.16e",
  1416. "%-22.16e",
  1417. "%#+'022.16e",
  1418. #endif /* HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX */
  1419. "foo|%#+0123.9E|bar",
  1420. "%-123.9e",
  1421. "%123.9e",
  1422. "%+23.9e",
  1423. "%+05.8e",
  1424. "%-05.8e",
  1425. "%05.8e",
  1426. "%+5.8e",
  1427. "%-5.8e",
  1428. "% 5.8e",
  1429. "%5.8e",
  1430. "%+4.9e",
  1431. #if !OS_LINUX /* glibc sometimes gets these wrong. */
  1432. "%+#010.0e",
  1433. "%#10.1e",
  1434. "%10.5e",
  1435. "% 10.5e",
  1436. "%5.0e",
  1437. "%5.e",
  1438. "%#5.0e",
  1439. "%#5.e",
  1440. "%3.2e",
  1441. "%3.1e",
  1442. "%-1.5e",
  1443. "%1.5e",
  1444. "%01.3e",
  1445. "%1.e",
  1446. "%.1e",
  1447. "%#.0e",
  1448. "%+.0e",
  1449. "% .0e",
  1450. "%.0e",
  1451. "%#.e",
  1452. "%+.e",
  1453. "% .e",
  1454. "%.e",
  1455. "%4e",
  1456. "%e",
  1457. "%E",
  1458. #endif /* !OS_LINUX */
  1459. /* "%F" and "%f" formats. */
  1460. #if !OS_BSD && !OS_IRIX
  1461. "% '022f",
  1462. "%+'022f",
  1463. "%-'22f",
  1464. "%'22f",
  1465. #if HAVE_LONG_LONG_INT
  1466. "%.16f",
  1467. "%22.16f",
  1468. "%022.16f",
  1469. "%-22.16f",
  1470. "%#+'022.16f",
  1471. #endif /* HAVE_LONG_LONG_INT */
  1472. #endif /* !OS_BSD && !OS_IRIX */
  1473. "foo|%#+0123.9F|bar",
  1474. "%-123.9f",
  1475. "%123.9f",
  1476. "%+23.9f",
  1477. "%+#010.0f",
  1478. "%#10.1f",
  1479. "%10.5f",
  1480. "% 10.5f",
  1481. "%+05.8f",
  1482. "%-05.8f",
  1483. "%05.8f",
  1484. "%+5.8f",
  1485. "%-5.8f",
  1486. "% 5.8f",
  1487. "%5.8f",
  1488. "%5.0f",
  1489. "%5.f",
  1490. "%#5.0f",
  1491. "%#5.f",
  1492. "%+4.9f",
  1493. "%3.2f",
  1494. "%3.1f",
  1495. "%-1.5f",
  1496. "%1.5f",
  1497. "%01.3f",
  1498. "%1.f",
  1499. "%.1f",
  1500. "%#.0f",
  1501. "%+.0f",
  1502. "% .0f",
  1503. "%.0f",
  1504. "%#.f",
  1505. "%+.f",
  1506. "% .f",
  1507. "%.f",
  1508. "%4f",
  1509. "%f",
  1510. "%F",
  1511. /* "%G" and "%g" formats. */
  1512. #if !OS_BSD && !OS_IRIX && !OS_LINUX
  1513. "% '022g",
  1514. "%+'022g",
  1515. "%-'22g",
  1516. "%'22g",
  1517. #if HAVE_LONG_LONG_INT
  1518. "%.16g",
  1519. "%22.16g",
  1520. "%022.16g",
  1521. "%-22.16g",
  1522. "%#+'022.16g",
  1523. #endif /* HAVE_LONG_LONG_INT */
  1524. #endif /* !OS_BSD && !OS_IRIX && !OS_LINUX */
  1525. "foo|%#+0123.9G|bar",
  1526. "%-123.9g",
  1527. "%123.9g",
  1528. "%+23.9g",
  1529. "%+05.8g",
  1530. "%-05.8g",
  1531. "%05.8g",
  1532. "%+5.8g",
  1533. "%-5.8g",
  1534. "% 5.8g",
  1535. "%5.8g",
  1536. "%+4.9g",
  1537. #if !OS_LINUX /* glibc sometimes gets these wrong. */
  1538. "%+#010.0g",
  1539. "%#10.1g",
  1540. "%10.5g",
  1541. "% 10.5g",
  1542. "%5.0g",
  1543. "%5.g",
  1544. "%#5.0g",
  1545. "%#5.g",
  1546. "%3.2g",
  1547. "%3.1g",
  1548. "%-1.5g",
  1549. "%1.5g",
  1550. "%01.3g",
  1551. "%1.g",
  1552. "%.1g",
  1553. "%#.0g",
  1554. "%+.0g",
  1555. "% .0g",
  1556. "%.0g",
  1557. "%#.g",
  1558. "%+.g",
  1559. "% .g",
  1560. "%.g",
  1561. "%4g",
  1562. "%g",
  1563. "%G",
  1564. #endif /* !OS_LINUX */
  1565. NULL
  1566. };
  1567. double float_val[] = {
  1568. -4.136,
  1569. -134.52,
  1570. -5.04030201,
  1571. -3410.01234,
  1572. -999999.999999,
  1573. -913450.29876,
  1574. -913450.2,
  1575. -91345.2,
  1576. -9134.2,
  1577. -913.2,
  1578. -91.2,
  1579. -9.2,
  1580. -9.9,
  1581. 4.136,
  1582. 134.52,
  1583. 5.04030201,
  1584. 3410.01234,
  1585. 999999.999999,
  1586. 913450.29876,
  1587. 913450.2,
  1588. 91345.2,
  1589. 9134.2,
  1590. 913.2,
  1591. 91.2,
  1592. 9.2,
  1593. 9.9,
  1594. 9.96,
  1595. 9.996,
  1596. 9.9996,
  1597. 9.99996,
  1598. 9.999996,
  1599. 9.9999996,
  1600. 9.99999996,
  1601. 0.99999996,
  1602. 0.99999999,
  1603. 0.09999999,
  1604. 0.00999999,
  1605. 0.00099999,
  1606. 0.00009999,
  1607. 0.00000999,
  1608. 0.00000099,
  1609. 0.00000009,
  1610. 0.00000001,
  1611. 0.0000001,
  1612. 0.000001,
  1613. 0.00001,
  1614. 0.0001,
  1615. 0.001,
  1616. 0.01,
  1617. 0.1,
  1618. 1.0,
  1619. 1.5,
  1620. -1.5,
  1621. -1.0,
  1622. -0.1,
  1623. #if !OS_BSD /* BSD sometimes gets these wrong. */
  1624. #ifdef INFINITY
  1625. INFINITY,
  1626. -INFINITY,
  1627. #endif /* defined(INFINITY) */
  1628. #ifdef NAN
  1629. NAN,
  1630. #endif /* defined(NAN) */
  1631. #endif /* !OS_BSD */
  1632. 0
  1633. };
  1634. const char *long_fmt[] = {
  1635. "foo|%0123ld|bar",
  1636. #if !OS_IRIX
  1637. "% '0123ld",
  1638. "%+'0123ld",
  1639. "%-'123ld",
  1640. "%'123ld",
  1641. #endif /* !OS_IRiX */
  1642. "%123.9ld",
  1643. "% 123.9ld",
  1644. "%+123.9ld",
  1645. "%-123.9ld",
  1646. "%0123ld",
  1647. "% 0123ld",
  1648. "%+0123ld",
  1649. "%-0123ld",
  1650. "%10.5ld",
  1651. "% 10.5ld",
  1652. "%+10.5ld",
  1653. "%-10.5ld",
  1654. "%010ld",
  1655. "% 010ld",
  1656. "%+010ld",
  1657. "%-010ld",
  1658. "%4.2ld",
  1659. "% 4.2ld",
  1660. "%+4.2ld",
  1661. "%-4.2ld",
  1662. "%04ld",
  1663. "% 04ld",
  1664. "%+04ld",
  1665. "%-04ld",
  1666. "%5.5ld",
  1667. "%+22.33ld",
  1668. "%01.3ld",
  1669. "%1.5ld",
  1670. "%-1.5ld",
  1671. "%44ld",
  1672. "%4ld",
  1673. "%4.0ld",
  1674. "%4.ld",
  1675. "%.44ld",
  1676. "%.4ld",
  1677. "%.0ld",
  1678. "%.ld",
  1679. "%ld",
  1680. NULL
  1681. };
  1682. long int long_val[] = {
  1683. #ifdef LONG_MAX
  1684. LONG_MAX,
  1685. #endif /* LONG_MAX */
  1686. #ifdef LONG_MIN
  1687. LONG_MIN,
  1688. #endif /* LONG_MIN */
  1689. -91340,
  1690. 91340,
  1691. 341,
  1692. 134,
  1693. 0203,
  1694. -1,
  1695. 1,
  1696. 0
  1697. };
  1698. const char *ulong_fmt[] = {
  1699. /* "%u" formats. */
  1700. "foo|%0123lu|bar",
  1701. #if !OS_IRIX
  1702. "% '0123lu",
  1703. "%+'0123lu",
  1704. "%-'123lu",
  1705. "%'123lu",
  1706. #endif /* !OS_IRiX */
  1707. "%123.9lu",
  1708. "% 123.9lu",
  1709. "%+123.9lu",
  1710. "%-123.9lu",
  1711. "%0123lu",
  1712. "% 0123lu",
  1713. "%+0123lu",
  1714. "%-0123lu",
  1715. "%5.5lu",
  1716. "%+22.33lu",
  1717. "%01.3lu",
  1718. "%1.5lu",
  1719. "%-1.5lu",
  1720. "%44lu",
  1721. "%lu",
  1722. /* "%o" formats. */
  1723. "foo|%#0123lo|bar",
  1724. "%#123.9lo",
  1725. "%# 123.9lo",
  1726. "%#+123.9lo",
  1727. "%#-123.9lo",
  1728. "%#0123lo",
  1729. "%# 0123lo",
  1730. "%#+0123lo",
  1731. "%#-0123lo",
  1732. "%#5.5lo",
  1733. "%#+22.33lo",
  1734. "%#01.3lo",
  1735. "%#1.5lo",
  1736. "%#-1.5lo",
  1737. "%#44lo",
  1738. "%#lo",
  1739. "%123.9lo",
  1740. "% 123.9lo",
  1741. "%+123.9lo",
  1742. "%-123.9lo",
  1743. "%0123lo",
  1744. "% 0123lo",
  1745. "%+0123lo",
  1746. "%-0123lo",
  1747. "%5.5lo",
  1748. "%+22.33lo",
  1749. "%01.3lo",
  1750. "%1.5lo",
  1751. "%-1.5lo",
  1752. "%44lo",
  1753. "%lo",
  1754. /* "%X" and "%x" formats. */
  1755. "foo|%#0123lX|bar",
  1756. "%#123.9lx",
  1757. "%# 123.9lx",
  1758. "%#+123.9lx",
  1759. "%#-123.9lx",
  1760. "%#0123lx",
  1761. "%# 0123lx",
  1762. "%#+0123lx",
  1763. "%#-0123lx",
  1764. "%#5.5lx",
  1765. "%#+22.33lx",
  1766. "%#01.3lx",
  1767. "%#1.5lx",
  1768. "%#-1.5lx",
  1769. "%#44lx",
  1770. "%#lx",
  1771. "%#lX",
  1772. "%123.9lx",
  1773. "% 123.9lx",
  1774. "%+123.9lx",
  1775. "%-123.9lx",
  1776. "%0123lx",
  1777. "% 0123lx",
  1778. "%+0123lx",
  1779. "%-0123lx",
  1780. "%5.5lx",
  1781. "%+22.33lx",
  1782. "%01.3lx",
  1783. "%1.5lx",
  1784. "%-1.5lx",
  1785. "%44lx",
  1786. "%lx",
  1787. "%lX",
  1788. NULL
  1789. };
  1790. unsigned long int ulong_val[] = {
  1791. #ifdef ULONG_MAX
  1792. ULONG_MAX,
  1793. #endif /* ULONG_MAX */
  1794. 91340,
  1795. 341,
  1796. 134,
  1797. 0203,
  1798. 1,
  1799. 0
  1800. };
  1801. const char *llong_fmt[] = {
  1802. "foo|%0123lld|bar",
  1803. "%123.9lld",
  1804. "% 123.9lld",
  1805. "%+123.9lld",
  1806. "%-123.9lld",
  1807. "%0123lld",
  1808. "% 0123lld",
  1809. "%+0123lld",
  1810. "%-0123lld",
  1811. "%5.5lld",
  1812. "%+22.33lld",
  1813. "%01.3lld",
  1814. "%1.5lld",
  1815. "%-1.5lld",
  1816. "%44lld",
  1817. "%lld",
  1818. NULL
  1819. };
  1820. LLONG llong_val[] = {
  1821. #ifdef LLONG_MAX
  1822. LLONG_MAX,
  1823. #endif /* LLONG_MAX */
  1824. #ifdef LLONG_MIN
  1825. LLONG_MIN,
  1826. #endif /* LLONG_MIN */
  1827. -91340,
  1828. 91340,
  1829. 341,
  1830. 134,
  1831. 0203,
  1832. -1,
  1833. 1,
  1834. 0
  1835. };
  1836. const char *string_fmt[] = {
  1837. "foo|%10.10s|bar",
  1838. "%-10.10s",
  1839. "%10.10s",
  1840. "%10.5s",
  1841. "%5.10s",
  1842. "%10.1s",
  1843. "%1.10s",
  1844. "%10.0s",
  1845. "%0.10s",
  1846. "%-42.5s",
  1847. "%2.s",
  1848. "%.10s",
  1849. "%.1s",
  1850. "%.0s",
  1851. "%.s",
  1852. "%4s",
  1853. "%s",
  1854. NULL
  1855. };
  1856. const char *string_val[] = {
  1857. "Hello",
  1858. "Hello, world!",
  1859. "Sound check: One, two, three.",
  1860. "This string is a little longer than the other strings.",
  1861. "1",
  1862. "",
  1863. NULL
  1864. };
  1865. #if !OS_SYSV /* SysV uses a different format than we do. */
  1866. const char *pointer_fmt[] = {
  1867. "foo|%p|bar",
  1868. "%42p",
  1869. "%p",
  1870. NULL
  1871. };
  1872. const char *pointer_val[] = {
  1873. *pointer_fmt,
  1874. *string_fmt,
  1875. *string_val,
  1876. NULL
  1877. };
  1878. #endif /* !OS_SYSV */
  1879. char buf1[1024], buf2[1024];
  1880. double value, digits = 9.123456789012345678901234567890123456789;
  1881. int i, j, r1, r2, failed = 0, num = 0;
  1882. /*
  1883. * Use -DTEST_NILS in order to also test the conversion of nil values. Might
  1884. * segfault on systems which don't support converting a NULL pointer with "%s"
  1885. * and lets some test cases fail against BSD and glibc due to bugs in their
  1886. * implementations.
  1887. */
  1888. #ifndef TEST_NILS
  1889. #define TEST_NILS 0
  1890. #elif TEST_NILS
  1891. #undef TEST_NILS
  1892. #define TEST_NILS 1
  1893. #endif /* !defined(TEST_NILS) */
  1894. #ifdef TEST
  1895. #undef TEST
  1896. #endif /* defined(TEST) */
  1897. #define TEST(fmt, val) \
  1898. do { \
  1899. for (i = 0; fmt[i] != NULL; i++) \
  1900. for (j = 0; j == 0 || val[j - TEST_NILS] != 0; j++) { \
  1901. r1 = sprintf(buf1, fmt[i], val[j]); \
  1902. r2 = snprintf(buf2, sizeof(buf2), fmt[i], val[j]); \
  1903. if (strcmp(buf1, buf2) != 0 || r1 != r2) { \
  1904. (void)printf("Results don't match, " \
  1905. "format string: %s\n" \
  1906. "\t sprintf(3): [%s] (%d)\n" \
  1907. "\tsnprintf(3): [%s] (%d)\n", \
  1908. fmt[i], buf1, r1, buf2, r2); \
  1909. failed++; \
  1910. } \
  1911. num++; \
  1912. } \
  1913. } while (/* CONSTCOND */ 0)
  1914. #if HAVE_LOCALE_H
  1915. (void)setlocale(LC_ALL, "");
  1916. #endif /* HAVE_LOCALE_H */
  1917. (void)puts("Testing our snprintf(3) against your system's sprintf(3).");
  1918. TEST(float_fmt, float_val);
  1919. TEST(long_fmt, long_val);
  1920. TEST(ulong_fmt, ulong_val);
  1921. TEST(llong_fmt, llong_val);
  1922. TEST(string_fmt, string_val);
  1923. #if !OS_SYSV /* SysV uses a different format than we do. */
  1924. TEST(pointer_fmt, pointer_val);
  1925. #endif /* !OS_SYSV */
  1926. (void)printf("Result: %d out of %d tests failed.\n", failed, num);
  1927. (void)fputs("Checking how many digits we support: ", stdout);
  1928. for (i = 0; i < 100; i++) {
  1929. value = pow(10, i) * digits;
  1930. (void)sprintf(buf1, "%.1f", value);
  1931. (void)snprintf(buf2, sizeof(buf2), "%.1f", value);
  1932. if (strcmp(buf1, buf2) != 0) {
  1933. (void)printf("apparently %d.\n", i);
  1934. break;
  1935. }
  1936. }
  1937. return (failed == 0) ? 0 : 1;
  1938. }
  1939. #endif /* TEST_SNPRINTF */
  1940. /* vim: set joinspaces textwidth=80: */