Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 1995 Patrick Powell.
  3.  *
  4.  * This code is based on code written by Patrick Powell <papowell@astart.com>.
  5.  * It may be used for any purpose as long as this notice remains intact on all
  6.  * source code distributions.
  7.  */
  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. /*
  22.  * History
  23.  *
  24.  * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1:
  25.  *
  26.  *      Fixed the detection of infinite floating point values on IRIX (and
  27.  *      possibly other systems) and applied another few minor cleanups.
  28.  *
  29.  * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0:
  30.  *
  31.  *      Added a lot of new features, fixed many bugs, and incorporated various
  32.  *      improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery
  33.  *      <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller
  34.  *      <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH
  35.  *      projects.  The additions include: support the "e", "E", "g", "G", and
  36.  *      "F" conversion specifiers (and use conversion style "f" or "F" for the
  37.  *      still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
  38.  *      "t", and "z" length modifiers; support the "#" flag and the (non-C99)
  39.  *      "'" flag; use localeconv(3) (if available) to get both the current
  40.  *      locale's decimal point character and the separator between groups of
  41.  *      digits; fix the handling of various corner cases of field width and
  42.  *      precision specifications; fix various floating point conversion bugs;
  43.  *      handle infinite and NaN floating point values; don't attempt to write to
  44.  *      the output buffer (which may be NULL) if a size of zero was specified;
  45.  *      check for integer overflow of the field width, precision, and return
  46.  *      values and during the floating point conversion; use the OUTCHAR() macro
  47.  *      instead of a function for better performance; provide asprintf(3) and
  48.  *      vasprintf(3) functions; add new test cases.  The replacement functions
  49.  *      have been renamed to use an "rpl_" prefix, the function calls in the
  50.  *      main project (and in this file) must be redefined accordingly for each
  51.  *      replacement function which is needed (by using Autoconf or other means).
  52.  *      Various other minor improvements have been applied and the coding style
  53.  *      was cleaned up for consistency.
  54.  *
  55.  * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13:
  56.  *
  57.  *      C99 compliant snprintf(3) and vsnprintf(3) functions return the number
  58.  *      of characters that would have been written to a sufficiently sized
  59.  *      buffer (excluding the '\0').  The original code simply returned the
  60.  *      length of the resulting output string, so that's been fixed.
  61.  *
  62.  * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8:
  63.  *
  64.  *      The original code assumed that both snprintf(3) and vsnprintf(3) were
  65.  *      missing.  Some systems only have snprintf(3) but not vsnprintf(3), so
  66.  *      the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
  67.  *
  68.  * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i:
  69.  *
  70.  *      The PGP code was using unsigned hexadecimal formats.  Unfortunately,
  71.  *      unsigned formats simply didn't work.
  72.  *
  73.  * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1:
  74.  *
  75.  *      Ok, added some minimal floating point support, which means this probably
  76.  *      requires libm on most operating systems.  Don't yet support the exponent
  77.  *      (e,E) and sigfig (g,G).  Also, fmtint() was pretty badly broken, it just
  78.  *      wasn't being exercised in ways which showed it, so that's been fixed.
  79.  *      Also, formatted the code to Mutt conventions, and removed dead code left
  80.  *      over from the original.  Also, there is now a builtin-test, run with:
  81.  *      gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
  82.  *
  83.  * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43:
  84.  *
  85.  *      This was ugly.  It is still ugly.  I opted out of floating point
  86.  *      numbers, but the formatter understands just about everything from the
  87.  *      normal C string format, at least as far as I can tell from the Solaris
  88.  *      2.5 printf(3S) man page.
  89.  */
  90.  
  91. /*
  92.  * ToDo
  93.  *
  94.  * - Add wide character support.
  95.  * - Add support for "%a" and "%A" conversions.
  96.  * - Create test routines which predefine the expected results.  Our test cases
  97.  *   usually expose bugs in system implementations rather than in ours :-)
  98.  */
  99.  
  100. /*
  101.  * Usage
  102.  *
  103.  * 1) The following preprocessor macros should be defined to 1 if the feature or
  104.  *    file in question is available on the target system (by using Autoconf or
  105.  *    other means), though basic functionality should be available as long as
  106.  *    HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly:
  107.  *
  108.  *      HAVE_VSNPRINTF
  109.  *      HAVE_SNPRINTF
  110.  *      HAVE_VASPRINTF
  111.  *      HAVE_ASPRINTF
  112.  *      HAVE_STDARG_H
  113.  *      HAVE_STDDEF_H
  114.  *      HAVE_STDINT_H
  115.  *      HAVE_STDLIB_H
  116.  *      HAVE_INTTYPES_H
  117.  *      HAVE_LOCALE_H
  118.  *      HAVE_LOCALECONV
  119.  *      HAVE_LCONV_DECIMAL_POINT
  120.  *      HAVE_LCONV_THOUSANDS_SEP
  121.  *      HAVE_LONG_DOUBLE
  122.  *      HAVE_LONG_LONG_INT
  123.  *      HAVE_UNSIGNED_LONG_LONG_INT
  124.  *      HAVE_INTMAX_T
  125.  *      HAVE_UINTMAX_T
  126.  *      HAVE_UINTPTR_T
  127.  *      HAVE_PTRDIFF_T
  128.  *      HAVE_VA_COPY
  129.  *      HAVE___VA_COPY
  130.  *
  131.  * 2) The calls to the functions which should be replaced must be redefined
  132.  *    throughout the project files (by using Autoconf or other means):
  133.  *
  134.  *      #define vsnprintf rpl_vsnprintf
  135.  *      #define snprintf rpl_snprintf
  136.  *      #define vasprintf rpl_vasprintf
  137.  *      #define asprintf rpl_asprintf
  138.  *
  139.  * 3) The required replacement functions should be declared in some header file
  140.  *    included throughout the project files:
  141.  *
  142.  *      #if HAVE_CONFIG_H
  143.  *      #include <config.h>
  144.  *      #endif
  145.  *      #if HAVE_STDARG_H
  146.  *      #include <stdarg.h>
  147.  *      #if !HAVE_VSNPRINTF
  148.  *      int rpl_vsnprintf(char *, size_t, const char *, va_list);
  149.  *      #endif
  150.  *      #if !HAVE_SNPRINTF
  151.  *      int rpl_snprintf(char *, size_t, const char *, ...);
  152.  *      #endif
  153.  *      #if !HAVE_VASPRINTF
  154.  *      int rpl_vasprintf(char **, const char *, va_list);
  155.  *      #endif
  156.  *      #if !HAVE_ASPRINTF
  157.  *      int rpl_asprintf(char **, const char *, ...);
  158.  *      #endif
  159.  *      #endif
  160.  *
  161.  * Autoconf macros for handling step 1 and step 2 are available at
  162.  * <http://www.jhweiss.de/software/snprintf.html>.
  163.  */
  164.  
  165. #include "pipe/p_config.h"
  166.  
  167. #if HAVE_CONFIG_H
  168. #include <config.h>
  169. #else
  170. #ifdef _MSC_VER
  171. #define vsnprintf util_vsnprintf
  172. #define snprintf util_snprintf
  173. #define HAVE_VSNPRINTF 0
  174. #define HAVE_SNPRINTF 0
  175. #define HAVE_VASPRINTF 1 /* not needed */
  176. #define HAVE_ASPRINTF 1 /* not needed */
  177. #define HAVE_STDARG_H 1
  178. #define HAVE_STDDEF_H 1
  179. #define HAVE_STDINT_H 1
  180. #define HAVE_STDLIB_H 1
  181. #define HAVE_INTTYPES_H 0
  182. #define HAVE_LOCALE_H 0
  183. #define HAVE_LOCALECONV 0
  184. #define HAVE_LCONV_DECIMAL_POINT 0
  185. #define HAVE_LCONV_THOUSANDS_SEP 0
  186. #define HAVE_LONG_DOUBLE 0
  187. #define HAVE_LONG_LONG_INT 1
  188. #define HAVE_UNSIGNED_LONG_LONG_INT 1
  189. #define HAVE_INTMAX_T 0
  190. #define HAVE_UINTMAX_T 0
  191. #define HAVE_UINTPTR_T 1
  192. #define HAVE_PTRDIFF_T 1
  193. #define HAVE_VA_COPY 0
  194. #define HAVE___VA_COPY 0
  195. #else
  196. #define HAVE_VSNPRINTF 1
  197. #define HAVE_SNPRINTF 1
  198. #define HAVE_VASPRINTF 1
  199. #define HAVE_ASPRINTF 1
  200. #endif
  201. #endif  /* HAVE_CONFIG_H */
  202.  
  203. #if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF
  204. #include <stdio.h>      /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */
  205. #ifdef VA_START
  206. #undef VA_START
  207. #endif  /* defined(VA_START) */
  208. #ifdef VA_SHIFT
  209. #undef VA_SHIFT
  210. #endif  /* defined(VA_SHIFT) */
  211. #if HAVE_STDARG_H
  212. #include <stdarg.h>
  213. #define VA_START(ap, last) va_start(ap, last)
  214. #define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
  215. #else   /* Assume <varargs.h> is available. */
  216. #include <varargs.h>
  217. #define VA_START(ap, last) va_start(ap) /* "last" is ignored. */
  218. #define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
  219. #endif  /* HAVE_STDARG_H */
  220.  
  221. #if !HAVE_VASPRINTF
  222. #if HAVE_STDLIB_H
  223. #include <stdlib.h>     /* For malloc(3). */
  224. #endif  /* HAVE_STDLIB_H */
  225. #ifdef VA_COPY
  226. #undef VA_COPY
  227. #endif  /* defined(VA_COPY) */
  228. #ifdef VA_END_COPY
  229. #undef VA_END_COPY
  230. #endif  /* defined(VA_END_COPY) */
  231. #if HAVE_VA_COPY
  232. #define VA_COPY(dest, src) va_copy(dest, src)
  233. #define VA_END_COPY(ap) va_end(ap)
  234. #elif HAVE___VA_COPY
  235. #define VA_COPY(dest, src) __va_copy(dest, src)
  236. #define VA_END_COPY(ap) va_end(ap)
  237. #else
  238. #define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list))
  239. #define VA_END_COPY(ap) /* No-op. */
  240. #define NEED_MYMEMCPY 1
  241. static void *mymemcpy(void *, void *, size_t);
  242. #endif  /* HAVE_VA_COPY */
  243. #endif  /* !HAVE_VASPRINTF */
  244.  
  245. #if !HAVE_VSNPRINTF
  246. #include <limits.h>     /* For *_MAX. */
  247. #if HAVE_INTTYPES_H
  248. #include <inttypes.h>   /* For intmax_t (if not defined in <stdint.h>). */
  249. #endif  /* HAVE_INTTYPES_H */
  250. #if HAVE_LOCALE_H
  251. #include <locale.h>     /* For localeconv(3). */
  252. #endif  /* HAVE_LOCALE_H */
  253. #if HAVE_STDDEF_H
  254. #include <stddef.h>     /* For ptrdiff_t. */
  255. #endif  /* HAVE_STDDEF_H */
  256. #if HAVE_STDINT_H
  257. #include <stdint.h>     /* For intmax_t. */
  258. #endif  /* HAVE_STDINT_H */
  259.  
  260. /* Support for unsigned long long int.  We may also need ULLONG_MAX. */
  261. #ifndef ULONG_MAX       /* We may need ULONG_MAX as a fallback. */
  262. #ifdef UINT_MAX
  263. #define ULONG_MAX UINT_MAX
  264. #else
  265. #define ULONG_MAX INT_MAX
  266. #endif  /* defined(UINT_MAX) */
  267. #endif  /* !defined(ULONG_MAX) */
  268. #ifdef ULLONG
  269. #undef ULLONG
  270. #endif  /* defined(ULLONG) */
  271. #if HAVE_UNSIGNED_LONG_LONG_INT
  272. #define ULLONG unsigned long long int
  273. #ifndef ULLONG_MAX
  274. #define ULLONG_MAX ULONG_MAX
  275. #endif  /* !defined(ULLONG_MAX) */
  276. #else
  277. #define ULLONG unsigned long int
  278. #ifdef ULLONG_MAX
  279. #undef ULLONG_MAX
  280. #endif  /* defined(ULLONG_MAX) */
  281. #define ULLONG_MAX ULONG_MAX
  282. #endif  /* HAVE_LONG_LONG_INT */
  283.  
  284. /* Support for uintmax_t.  We also need UINTMAX_MAX. */
  285. #ifdef UINTMAX_T
  286. #undef UINTMAX_T
  287. #endif  /* defined(UINTMAX_T) */
  288. #if HAVE_UINTMAX_T || defined(uintmax_t)
  289. #define UINTMAX_T uintmax_t
  290. #ifndef UINTMAX_MAX
  291. #define UINTMAX_MAX ULLONG_MAX
  292. #endif  /* !defined(UINTMAX_MAX) */
  293. #else
  294. #define UINTMAX_T ULLONG
  295. #ifdef UINTMAX_MAX
  296. #undef UINTMAX_MAX
  297. #endif  /* defined(UINTMAX_MAX) */
  298. #define UINTMAX_MAX ULLONG_MAX
  299. #endif  /* HAVE_UINTMAX_T || defined(uintmax_t) */
  300.  
  301. /* Support for long double. */
  302. #ifndef LDOUBLE
  303. #if HAVE_LONG_DOUBLE
  304. #define LDOUBLE long double
  305. #else
  306. #define LDOUBLE double
  307. #endif  /* HAVE_LONG_DOUBLE */
  308. #endif  /* !defined(LDOUBLE) */
  309.  
  310. /* Support for long long int. */
  311. #ifndef LLONG
  312. #if HAVE_LONG_LONG_INT
  313. #define LLONG long long int
  314. #else
  315. #define LLONG long int
  316. #endif  /* HAVE_LONG_LONG_INT */
  317. #endif  /* !defined(LLONG) */
  318.  
  319. /* Support for intmax_t. */
  320. #ifndef INTMAX_T
  321. #if HAVE_INTMAX_T || defined(intmax_t)
  322. #define INTMAX_T intmax_t
  323. #else
  324. #define INTMAX_T LLONG
  325. #endif  /* HAVE_INTMAX_T || defined(intmax_t) */
  326. #endif  /* !defined(INTMAX_T) */
  327.  
  328. /* Support for uintptr_t. */
  329. #ifndef UINTPTR_T
  330. #if HAVE_UINTPTR_T || defined(uintptr_t)
  331. #define UINTPTR_T uintptr_t
  332. #else
  333. #define UINTPTR_T unsigned long int
  334. #endif  /* HAVE_UINTPTR_T || defined(uintptr_t) */
  335. #endif  /* !defined(UINTPTR_T) */
  336.  
  337. /* Support for ptrdiff_t. */
  338. #ifndef PTRDIFF_T
  339. #if HAVE_PTRDIFF_T || defined(ptrdiff_t)
  340. #define PTRDIFF_T ptrdiff_t
  341. #else
  342. #define PTRDIFF_T long int
  343. #endif  /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
  344. #endif  /* !defined(PTRDIFF_T) */
  345.  
  346. /*
  347.  * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
  348.  * 7.19.6.1, 7).  However, we'll simply use PTRDIFF_T and convert it to an
  349.  * unsigned type if necessary.  This should work just fine in practice.
  350.  */
  351. #ifndef UPTRDIFF_T
  352. #define UPTRDIFF_T PTRDIFF_T
  353. #endif  /* !defined(UPTRDIFF_T) */
  354.  
  355. /*
  356.  * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
  357.  * However, we'll simply use size_t and convert it to a signed type if
  358.  * necessary.  This should work just fine in practice.
  359.  */
  360. #ifndef SSIZE_T
  361. #define SSIZE_T size_t
  362. #endif  /* !defined(SSIZE_T) */
  363.  
  364. /* Either ERANGE or E2BIG should be available everywhere. */
  365. #ifndef ERANGE
  366. #define ERANGE E2BIG
  367. #endif  /* !defined(ERANGE) */
  368. #ifndef EOVERFLOW
  369. #define EOVERFLOW ERANGE
  370. #endif  /* !defined(EOVERFLOW) */
  371.  
  372. /*
  373.  * Buffer size to hold the octal string representation of UINT128_MAX without
  374.  * nul-termination ("3777777777777777777777777777777777777777777").
  375.  */
  376. #ifdef MAX_CONVERT_LENGTH
  377. #undef MAX_CONVERT_LENGTH
  378. #endif  /* defined(MAX_CONVERT_LENGTH) */
  379. #define MAX_CONVERT_LENGTH      43
  380.  
  381. /* Format read states. */
  382. #define PRINT_S_DEFAULT         0
  383. #define PRINT_S_FLAGS           1
  384. #define PRINT_S_WIDTH           2
  385. #define PRINT_S_DOT             3
  386. #define PRINT_S_PRECISION       4
  387. #define PRINT_S_MOD             5
  388. #define PRINT_S_CONV            6
  389.  
  390. /* Format flags. */
  391. #define PRINT_F_MINUS           (1 << 0)
  392. #define PRINT_F_PLUS            (1 << 1)
  393. #define PRINT_F_SPACE           (1 << 2)
  394. #define PRINT_F_NUM             (1 << 3)
  395. #define PRINT_F_ZERO            (1 << 4)
  396. #define PRINT_F_QUOTE           (1 << 5)
  397. #define PRINT_F_UP              (1 << 6)
  398. #define PRINT_F_UNSIGNED        (1 << 7)
  399. #define PRINT_F_TYPE_G          (1 << 8)
  400. #define PRINT_F_TYPE_E          (1 << 9)
  401.  
  402. /* Conversion flags. */
  403. #define PRINT_C_CHAR            1
  404. #define PRINT_C_SHORT           2
  405. #define PRINT_C_LONG            3
  406. #define PRINT_C_LLONG           4
  407. #define PRINT_C_LDOUBLE         5
  408. #define PRINT_C_SIZE            6
  409. #define PRINT_C_PTRDIFF         7
  410. #define PRINT_C_INTMAX          8
  411.  
  412. #ifndef MAX
  413. #define MAX(x, y) ((x >= y) ? x : y)
  414. #endif  /* !defined(MAX) */
  415. #ifndef CHARTOINT
  416. #define CHARTOINT(ch) (ch - '0')
  417. #endif  /* !defined(CHARTOINT) */
  418. #ifndef ISDIGIT
  419. #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
  420. #endif  /* !defined(ISDIGIT) */
  421. #ifndef ISNAN
  422. #define ISNAN(x) (x != x)
  423. #endif  /* !defined(ISNAN) */
  424. #ifndef ISINF
  425. #define ISINF(x) (x != 0.0 && x + x == x)
  426. #endif  /* !defined(ISINF) */
  427.  
  428. #ifdef OUTCHAR
  429. #undef OUTCHAR
  430. #endif  /* defined(OUTCHAR) */
  431. #define OUTCHAR(str, len, size, ch)                                          \
  432. do {                                                                         \
  433.         if (len + 1 < size)                                                  \
  434.                 str[len] = ch;                                               \
  435.         (len)++;                                                             \
  436. } while (/* CONSTCOND */ 0)
  437.  
  438. static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
  439. static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
  440. static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
  441. static void printsep(char *, size_t *, size_t);
  442. static int getnumsep(int);
  443. static int getexponent(LDOUBLE);
  444. static int convert(UINTMAX_T, char *, size_t, int, int);
  445. static UINTMAX_T cast(LDOUBLE);
  446. static UINTMAX_T myround(LDOUBLE);
  447. static LDOUBLE mypow10(int);
  448.  
  449. int
  450. util_vsnprintf(char *str, size_t size, const char *format, va_list args)
  451. {
  452.         LDOUBLE fvalue;
  453.         INTMAX_T value;
  454.         unsigned char cvalue;
  455.         const char *strvalue;
  456.         INTMAX_T *intmaxptr;
  457.         PTRDIFF_T *ptrdiffptr;
  458.         SSIZE_T *sizeptr;
  459.         LLONG *llongptr;
  460.         long int *longptr;
  461.         int *intptr;
  462.         short int *shortptr;
  463.         signed char *charptr;
  464.         size_t len = 0;
  465.         int overflow = 0;
  466.         int base = 0;
  467.         int cflags = 0;
  468.         int flags = 0;
  469.         int width = 0;
  470.         int precision = -1;
  471.         int state = PRINT_S_DEFAULT;
  472.         char ch = *format++;
  473.  
  474.         /*
  475.          * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
  476.          * pointer." (7.19.6.5, 2)  We're forgiving and allow a NULL pointer
  477.          * even if a size larger than zero was specified.  At least NetBSD's
  478.          * snprintf(3) does the same, as well as other versions of this file.
  479.          * (Though some of these versions will write to a non-NULL buffer even
  480.          * if a size of zero was specified, which violates the standard.)
  481.          */
  482.         if (str == NULL && size != 0)
  483.                 size = 0;
  484.  
  485.         while (ch != '\0')
  486.                 switch (state) {
  487.                 case PRINT_S_DEFAULT:
  488.                         if (ch == '%')
  489.                                 state = PRINT_S_FLAGS;
  490.                         else
  491.                                 OUTCHAR(str, len, size, ch);
  492.                         ch = *format++;
  493.                         break;
  494.                 case PRINT_S_FLAGS:
  495.                         switch (ch) {
  496.                         case '-':
  497.                                 flags |= PRINT_F_MINUS;
  498.                                 ch = *format++;
  499.                                 break;
  500.                         case '+':
  501.                                 flags |= PRINT_F_PLUS;
  502.                                 ch = *format++;
  503.                                 break;
  504.                         case ' ':
  505.                                 flags |= PRINT_F_SPACE;
  506.                                 ch = *format++;
  507.                                 break;
  508.                         case '#':
  509.                                 flags |= PRINT_F_NUM;
  510.                                 ch = *format++;
  511.                                 break;
  512.                         case '0':
  513.                                 flags |= PRINT_F_ZERO;
  514.                                 ch = *format++;
  515.                                 break;
  516.                         case '\'':      /* SUSv2 flag (not in C99). */
  517.                                 flags |= PRINT_F_QUOTE;
  518.                                 ch = *format++;
  519.                                 break;
  520.                         default:
  521.                                 state = PRINT_S_WIDTH;
  522.                                 break;
  523.                         }
  524.                         break;
  525.                 case PRINT_S_WIDTH:
  526.                         if (ISDIGIT(ch)) {
  527.                                 ch = CHARTOINT(ch);
  528.                                 if (width > (INT_MAX - ch) / 10) {
  529.                                         overflow = 1;
  530.                                         goto out;
  531.                                 }
  532.                                 width = 10 * width + ch;
  533.                                 ch = *format++;
  534.                         } else if (ch == '*') {
  535.                                 /*
  536.                                  * C99 says: "A negative field width argument is
  537.                                  * taken as a `-' flag followed by a positive
  538.                                  * field width." (7.19.6.1, 5)
  539.                                  */
  540.                                 if ((width = va_arg(args, int)) < 0) {
  541.                                         flags |= PRINT_F_MINUS;
  542.                                         width = -width;
  543.                                 }
  544.                                 ch = *format++;
  545.                                 state = PRINT_S_DOT;
  546.                         } else
  547.                                 state = PRINT_S_DOT;
  548.                         break;
  549.                 case PRINT_S_DOT:
  550.                         if (ch == '.') {
  551.                                 state = PRINT_S_PRECISION;
  552.                                 ch = *format++;
  553.                         } else
  554.                                 state = PRINT_S_MOD;
  555.                         break;
  556.                 case PRINT_S_PRECISION:
  557.                         if (precision == -1)
  558.                                 precision = 0;
  559.                         if (ISDIGIT(ch)) {
  560.                                 ch = CHARTOINT(ch);
  561.                                 if (precision > (INT_MAX - ch) / 10) {
  562.                                         overflow = 1;
  563.                                         goto out;
  564.                                 }
  565.                                 precision = 10 * precision + ch;
  566.                                 ch = *format++;
  567.                         } else if (ch == '*') {
  568.                                 /*
  569.                                  * C99 says: "A negative precision argument is
  570.                                  * taken as if the precision were omitted."
  571.                                  * (7.19.6.1, 5)
  572.                                  */
  573.                                 if ((precision = va_arg(args, int)) < 0)
  574.                                         precision = -1;
  575.                                 ch = *format++;
  576.                                 state = PRINT_S_MOD;
  577.                         } else
  578.                                 state = PRINT_S_MOD;
  579.                         break;
  580.                 case PRINT_S_MOD:
  581.                         switch (ch) {
  582.                         case 'h':
  583.                                 ch = *format++;
  584.                                 if (ch == 'h') {        /* It's a char. */
  585.                                         ch = *format++;
  586.                                         cflags = PRINT_C_CHAR;
  587.                                 } else
  588.                                         cflags = PRINT_C_SHORT;
  589.                                 break;
  590.                         case 'l':
  591.                                 ch = *format++;
  592.                                 if (ch == 'l') {        /* It's a long long. */
  593.                                         ch = *format++;
  594.                                         cflags = PRINT_C_LLONG;
  595.                                 } else
  596.                                         cflags = PRINT_C_LONG;
  597.                                 break;
  598.                         case 'L':
  599.                                 cflags = PRINT_C_LDOUBLE;
  600.                                 ch = *format++;
  601.                                 break;
  602.                         case 'j':
  603.                                 cflags = PRINT_C_INTMAX;
  604.                                 ch = *format++;
  605.                                 break;
  606.                         case 't':
  607.                                 cflags = PRINT_C_PTRDIFF;
  608.                                 ch = *format++;
  609.                                 break;
  610.                         case 'z':
  611.                                 cflags = PRINT_C_SIZE;
  612.                                 ch = *format++;
  613.                                 break;
  614.                         }
  615.                         state = PRINT_S_CONV;
  616.                         break;
  617.                 case PRINT_S_CONV:
  618.                         switch (ch) {
  619.                         case 'd':
  620.                                 /* FALLTHROUGH */
  621.                         case 'i':
  622.                                 switch (cflags) {
  623.                                 case PRINT_C_CHAR:
  624.                                         value = (signed char)va_arg(args, int);
  625.                                         break;
  626.                                 case PRINT_C_SHORT:
  627.                                         value = (short int)va_arg(args, int);
  628.                                         break;
  629.                                 case PRINT_C_LONG:
  630.                                         value = va_arg(args, long int);
  631.                                         break;
  632.                                 case PRINT_C_LLONG:
  633.                                         value = va_arg(args, LLONG);
  634.                                         break;
  635.                                 case PRINT_C_SIZE:
  636.                                         value = va_arg(args, SSIZE_T);
  637.                                         break;
  638.                                 case PRINT_C_INTMAX:
  639.                                         value = va_arg(args, INTMAX_T);
  640.                                         break;
  641.                                 case PRINT_C_PTRDIFF:
  642.                                         value = va_arg(args, PTRDIFF_T);
  643.                                         break;
  644.                                 default:
  645.                                         value = va_arg(args, int);
  646.                                         break;
  647.                                 }
  648.                                 fmtint(str, &len, size, value, 10, width,
  649.                                     precision, flags);
  650.                                 break;
  651.                         case 'X':
  652.                                 flags |= PRINT_F_UP;
  653.                                 /* FALLTHROUGH */
  654.                         case 'x':
  655.                                 base = 16;
  656.                                 /* FALLTHROUGH */
  657.                         case 'o':
  658.                                 if (base == 0)
  659.                                         base = 8;
  660.                                 /* FALLTHROUGH */
  661.                         case 'u':
  662.                                 if (base == 0)
  663.                                         base = 10;
  664.                                 flags |= PRINT_F_UNSIGNED;
  665.                                 switch (cflags) {
  666.                                 case PRINT_C_CHAR:
  667.                                         value = (unsigned char)va_arg(args,
  668.                                             unsigned int);
  669.                                         break;
  670.                                 case PRINT_C_SHORT:
  671.                                         value = (unsigned short int)va_arg(args,
  672.                                             unsigned int);
  673.                                         break;
  674.                                 case PRINT_C_LONG:
  675.                                         value = va_arg(args, unsigned long int);
  676.                                         break;
  677.                                 case PRINT_C_LLONG:
  678.                                         value = va_arg(args, ULLONG);
  679.                                         break;
  680.                                 case PRINT_C_SIZE:
  681.                                         value = va_arg(args, size_t);
  682.                                         break;
  683.                                 case PRINT_C_INTMAX:
  684.                                         value = va_arg(args, UINTMAX_T);
  685.                                         break;
  686.                                 case PRINT_C_PTRDIFF:
  687.                                         value = va_arg(args, UPTRDIFF_T);
  688.                                         break;
  689.                                 default:
  690.                                         value = va_arg(args, unsigned int);
  691.                                         break;
  692.                                 }
  693.                                 fmtint(str, &len, size, value, base, width,
  694.                                     precision, flags);
  695.                                 break;
  696.                         case 'A':
  697.                                 /* Not yet supported, we'll use "%F". */
  698.                                 /* FALLTHROUGH */
  699.                         case 'F':
  700.                                 flags |= PRINT_F_UP;
  701.                         case 'a':
  702.                                 /* Not yet supported, we'll use "%f". */
  703.                                 /* FALLTHROUGH */
  704.                         case 'f':
  705.                                 if (cflags == PRINT_C_LDOUBLE)
  706.                                         fvalue = va_arg(args, LDOUBLE);
  707.                                 else
  708.                                         fvalue = va_arg(args, double);
  709.                                 fmtflt(str, &len, size, fvalue, width,
  710.                                     precision, flags, &overflow);
  711.                                 if (overflow)
  712.                                         goto out;
  713.                                 break;
  714.                         case 'E':
  715.                                 flags |= PRINT_F_UP;
  716.                                 /* FALLTHROUGH */
  717.                         case 'e':
  718.                                 flags |= PRINT_F_TYPE_E;
  719.                                 if (cflags == PRINT_C_LDOUBLE)
  720.                                         fvalue = va_arg(args, LDOUBLE);
  721.                                 else
  722.                                         fvalue = va_arg(args, double);
  723.                                 fmtflt(str, &len, size, fvalue, width,
  724.                                     precision, flags, &overflow);
  725.                                 if (overflow)
  726.                                         goto out;
  727.                                 break;
  728.                         case 'G':
  729.                                 flags |= PRINT_F_UP;
  730.                                 /* FALLTHROUGH */
  731.                         case 'g':
  732.                                 flags |= PRINT_F_TYPE_G;
  733.                                 if (cflags == PRINT_C_LDOUBLE)
  734.                                         fvalue = va_arg(args, LDOUBLE);
  735.                                 else
  736.                                         fvalue = va_arg(args, double);
  737.                                 /*
  738.                                  * If the precision is zero, it is treated as
  739.                                  * one (cf. C99: 7.19.6.1, 8).
  740.                                  */
  741.                                 if (precision == 0)
  742.                                         precision = 1;
  743.                                 fmtflt(str, &len, size, fvalue, width,
  744.                                     precision, flags, &overflow);
  745.                                 if (overflow)
  746.                                         goto out;
  747.                                 break;
  748.                         case 'c':
  749.                                 cvalue = (unsigned char)va_arg(args, int);
  750.                                 OUTCHAR(str, len, size, cvalue);
  751.                                 break;
  752.                         case 's':
  753.                                 strvalue = va_arg(args, char *);
  754.                                 fmtstr(str, &len, size, strvalue, width,
  755.                                     precision, flags);
  756.                                 break;
  757.                         case 'p':
  758.                                 /*
  759.                                  * C99 says: "The value of the pointer is
  760.                                  * converted to a sequence of printing
  761.                                  * characters, in an implementation-defined
  762.                                  * manner." (C99: 7.19.6.1, 8)
  763.                                  */
  764.                                 if ((strvalue = va_arg(args, void *)) == NULL)
  765.                                         /*
  766.                                          * We use the glibc format.  BSD prints
  767.                                          * "0x0", SysV "0".
  768.                                          */
  769.                                         fmtstr(str, &len, size, "(nil)", width,
  770.                                             -1, flags);
  771.                                 else {
  772.                                         /*
  773.                                          * We use the BSD/glibc format.  SysV
  774.                                          * omits the "0x" prefix (which we emit
  775.                                          * using the PRINT_F_NUM flag).
  776.                                          */
  777.                                         flags |= PRINT_F_NUM;
  778.                                         flags |= PRINT_F_UNSIGNED;
  779.                                         fmtint(str, &len, size,
  780.                                             (UINTPTR_T)strvalue, 16, width,
  781.                                             precision, flags);
  782.                                 }
  783.                                 break;
  784.                         case 'n':
  785.                                 switch (cflags) {
  786.                                 case PRINT_C_CHAR:
  787.                                         charptr = va_arg(args, signed char *);
  788.                                         *charptr = (signed char)len;
  789.                                         break;
  790.                                 case PRINT_C_SHORT:
  791.                                         shortptr = va_arg(args, short int *);
  792.                                         *shortptr = (short int)len;
  793.                                         break;
  794.                                 case PRINT_C_LONG:
  795.                                         longptr = va_arg(args, long int *);
  796.                                         *longptr = (long int)len;
  797.                                         break;
  798.                                 case PRINT_C_LLONG:
  799.                                         llongptr = va_arg(args, LLONG *);
  800.                                         *llongptr = (LLONG)len;
  801.                                         break;
  802.                                 case PRINT_C_SIZE:
  803.                                         /*
  804.                                          * C99 says that with the "z" length
  805.                                          * modifier, "a following `n' conversion
  806.                                          * specifier applies to a pointer to a
  807.                                          * signed integer type corresponding to
  808.                                          * size_t argument." (7.19.6.1, 7)
  809.                                          */
  810.                                         sizeptr = va_arg(args, SSIZE_T *);
  811.                                         *sizeptr = len;
  812.                                         break;
  813.                                 case PRINT_C_INTMAX:
  814.                                         intmaxptr = va_arg(args, INTMAX_T *);
  815.                                         *intmaxptr = len;
  816.                                         break;
  817.                                 case PRINT_C_PTRDIFF:
  818.                                         ptrdiffptr = va_arg(args, PTRDIFF_T *);
  819.                                         *ptrdiffptr = len;
  820.                                         break;
  821.                                 default:
  822.                                         intptr = va_arg(args, int *);
  823.                                         *intptr = (int)len;
  824.                                         break;
  825.                                 }
  826.                                 break;
  827.                         case '%':       /* Print a "%" character verbatim. */
  828.                                 OUTCHAR(str, len, size, ch);
  829.                                 break;
  830.                         default:        /* Skip other characters. */
  831.                                 break;
  832.                         }
  833.                         ch = *format++;
  834.                         state = PRINT_S_DEFAULT;
  835.                         base = cflags = flags = width = 0;
  836.                         precision = -1;
  837.                         break;
  838.                 }
  839. out:
  840.         if (len < size)
  841.                 str[len] = '\0';
  842.         else if (size > 0)
  843.                 str[size - 1] = '\0';
  844.  
  845.         if (overflow || len >= INT_MAX) {
  846.                 return -1;
  847.         }
  848.         return (int)len;
  849. }
  850.  
  851. static void
  852. fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
  853.        int precision, int flags)
  854. {
  855.         int padlen, strln;      /* Amount to pad. */
  856.         int noprecision = (precision == -1);
  857.  
  858.         if (value == NULL)      /* We're forgiving. */
  859.                 value = "(null)";
  860.  
  861.         /* If a precision was specified, don't read the string past it. */
  862.         for (strln = 0; value[strln] != '\0' &&
  863.             (noprecision || strln < precision); strln++)
  864.                 continue;
  865.  
  866.         if ((padlen = width - strln) < 0)
  867.                 padlen = 0;
  868.         if (flags & PRINT_F_MINUS)      /* Left justify. */
  869.                 padlen = -padlen;
  870.  
  871.         while (padlen > 0) {    /* Leading spaces. */
  872.                 OUTCHAR(str, *len, size, ' ');
  873.                 padlen--;
  874.         }
  875.         while (*value != '\0' && (noprecision || precision-- > 0)) {
  876.                 OUTCHAR(str, *len, size, *value);
  877.                 value++;
  878.         }
  879.         while (padlen < 0) {    /* Trailing spaces. */
  880.                 OUTCHAR(str, *len, size, ' ');
  881.                 padlen++;
  882.         }
  883. }
  884.  
  885. static void
  886. fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
  887.        int precision, int flags)
  888. {
  889.         UINTMAX_T uvalue;
  890.         char iconvert[MAX_CONVERT_LENGTH];
  891.         char sign = 0;
  892.         char hexprefix = 0;
  893.         int spadlen = 0;        /* Amount to space pad. */
  894.         int zpadlen = 0;        /* Amount to zero pad. */
  895.         int pos;
  896.         int separators = (flags & PRINT_F_QUOTE);
  897.         int noprecision = (precision == -1);
  898.  
  899.         if (flags & PRINT_F_UNSIGNED)
  900.                 uvalue = value;
  901.         else {
  902.                 uvalue = (value >= 0) ? value : -value;
  903.                 if (value < 0)
  904.                         sign = '-';
  905.                 else if (flags & PRINT_F_PLUS)  /* Do a sign. */
  906.                         sign = '+';
  907.                 else if (flags & PRINT_F_SPACE)
  908.                         sign = ' ';
  909.         }
  910.  
  911.         pos = convert(uvalue, iconvert, sizeof(iconvert), base,
  912.             flags & PRINT_F_UP);
  913.  
  914.         if (flags & PRINT_F_NUM && uvalue != 0) {
  915.                 /*
  916.                  * C99 says: "The result is converted to an `alternative form'.
  917.                  * For `o' conversion, it increases the precision, if and only
  918.                  * if necessary, to force the first digit of the result to be a
  919.                  * zero (if the value and precision are both 0, a single 0 is
  920.                  * printed).  For `x' (or `X') conversion, a nonzero result has
  921.                  * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
  922.                  */
  923.                 switch (base) {
  924.                 case 8:
  925.                         if (precision <= pos)
  926.                                 precision = pos + 1;
  927.                         break;
  928.                 case 16:
  929.                         hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
  930.                         break;
  931.                 }
  932.         }
  933.  
  934.         if (separators) /* Get the number of group separators we'll print. */
  935.                 separators = getnumsep(pos);
  936.  
  937.         zpadlen = precision - pos - separators;
  938.         spadlen = width                         /* Minimum field width. */
  939.             - separators                        /* Number of separators. */
  940.             - MAX(precision, pos)               /* Number of integer digits. */
  941.             - ((sign != 0) ? 1 : 0)             /* Will we print a sign? */
  942.             - ((hexprefix != 0) ? 2 : 0);       /* Will we print a prefix? */
  943.  
  944.         if (zpadlen < 0)
  945.                 zpadlen = 0;
  946.         if (spadlen < 0)
  947.                 spadlen = 0;
  948.  
  949.         /*
  950.          * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
  951.          * ignored.  For `d', `i', `o', `u', `x', and `X' conversions, if a
  952.          * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
  953.          */
  954.         if (flags & PRINT_F_MINUS)      /* Left justify. */
  955.                 spadlen = -spadlen;
  956.         else if (flags & PRINT_F_ZERO && noprecision) {
  957.                 zpadlen += spadlen;
  958.                 spadlen = 0;
  959.         }
  960.         while (spadlen > 0) {   /* Leading spaces. */
  961.                 OUTCHAR(str, *len, size, ' ');
  962.                 spadlen--;
  963.         }
  964.         if (sign != 0)  /* Sign. */
  965.                 OUTCHAR(str, *len, size, sign);
  966.         if (hexprefix != 0) {   /* A "0x" or "0X" prefix. */
  967.                 OUTCHAR(str, *len, size, '0');
  968.                 OUTCHAR(str, *len, size, hexprefix);
  969.         }
  970.         while (zpadlen > 0) {   /* Leading zeros. */
  971.                 OUTCHAR(str, *len, size, '0');
  972.                 zpadlen--;
  973.         }
  974.         while (pos > 0) {       /* The actual digits. */
  975.                 pos--;
  976.                 OUTCHAR(str, *len, size, iconvert[pos]);
  977.                 if (separators > 0 && pos > 0 && pos % 3 == 0)
  978.                         printsep(str, len, size);
  979.         }
  980.         while (spadlen < 0) {   /* Trailing spaces. */
  981.                 OUTCHAR(str, *len, size, ' ');
  982.                 spadlen++;
  983.         }
  984. }
  985.  
  986. static void
  987. fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
  988.        int precision, int flags, int *overflow)
  989. {
  990.         LDOUBLE ufvalue;
  991.         UINTMAX_T intpart;
  992.         UINTMAX_T fracpart;
  993.         UINTMAX_T mask;
  994.         const char *infnan = NULL;
  995.         char iconvert[MAX_CONVERT_LENGTH];
  996.         char fconvert[MAX_CONVERT_LENGTH];
  997.         char econvert[4];       /* "e-12" (without nul-termination). */
  998.         char esign = 0;
  999.         char sign = 0;
  1000.         int leadfraczeros = 0;
  1001.         int exponent = 0;
  1002.         int emitpoint = 0;
  1003.         int omitzeros = 0;
  1004.         int omitcount = 0;
  1005.         int padlen = 0;
  1006.         int epos = 0;
  1007.         int fpos = 0;
  1008.         int ipos = 0;
  1009.         int separators = (flags & PRINT_F_QUOTE);
  1010.         int estyle = (flags & PRINT_F_TYPE_E);
  1011. #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
  1012.         struct lconv *lc = localeconv();
  1013. #endif  /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
  1014.  
  1015.         /*
  1016.          * AIX' man page says the default is 0, but C99 and at least Solaris'
  1017.          * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
  1018.          * defaults to 6.
  1019.          */
  1020.         if (precision == -1)
  1021.                 precision = 6;
  1022.  
  1023.         if (fvalue < 0.0)
  1024.                 sign = '-';
  1025.         else if (flags & PRINT_F_PLUS)  /* Do a sign. */
  1026.                 sign = '+';
  1027.         else if (flags & PRINT_F_SPACE)
  1028.                 sign = ' ';
  1029.  
  1030.         if (ISNAN(fvalue))
  1031.                 infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
  1032.         else if (ISINF(fvalue))
  1033.                 infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
  1034.  
  1035.         if (infnan != NULL) {
  1036.                 if (sign != 0)
  1037.                         iconvert[ipos++] = sign;
  1038.                 while (*infnan != '\0')
  1039.                         iconvert[ipos++] = *infnan++;
  1040.                 fmtstr(str, len, size, iconvert, width, ipos, flags);
  1041.                 return;
  1042.         }
  1043.  
  1044.         /* "%e" (or "%E") or "%g" (or "%G") conversion. */
  1045.         if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
  1046.                 if (flags & PRINT_F_TYPE_G) {
  1047.                         /*
  1048.                          * For "%g" (and "%G") conversions, the precision
  1049.                          * specifies the number of significant digits, which
  1050.                          * includes the digits in the integer part.  The
  1051.                          * conversion will or will not be using "e-style" (like
  1052.                          * "%e" or "%E" conversions) depending on the precision
  1053.                          * and on the exponent.  However, the exponent can be
  1054.                          * affected by rounding the converted value, so we'll
  1055.                          * leave this decision for later.  Until then, we'll
  1056.                          * assume that we're going to do an "e-style" conversion
  1057.                          * (in order to get the exponent calculated).  For
  1058.                          * "e-style", the precision must be decremented by one.
  1059.                          */
  1060.                         precision--;
  1061.                         /*
  1062.                          * For "%g" (and "%G") conversions, trailing zeros are
  1063.                          * removed from the fractional portion of the result
  1064.                          * unless the "#" flag was specified.
  1065.                          */
  1066.                         if (!(flags & PRINT_F_NUM))
  1067.                                 omitzeros = 1;
  1068.                 }
  1069.                 exponent = getexponent(fvalue);
  1070.                 estyle = 1;
  1071.         }
  1072.  
  1073. again:
  1074.         /*
  1075.          * Sorry, we only support 9, 19, or 38 digits (that is, the number of
  1076.          * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
  1077.          * minus one) past the decimal point due to our conversion method.
  1078.          */
  1079.         switch (sizeof(UINTMAX_T)) {
  1080.         case 16:
  1081.                 if (precision > 38)
  1082.                         precision = 38;
  1083.                 break;
  1084.         case 8:
  1085.                 if (precision > 19)
  1086.                         precision = 19;
  1087.                 break;
  1088.         default:
  1089.                 if (precision > 9)
  1090.                         precision = 9;
  1091.                 break;
  1092.         }
  1093.  
  1094.         ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
  1095.         if (estyle)     /* We want exactly one integer digit. */
  1096.                 ufvalue /= mypow10(exponent);
  1097.  
  1098.         if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
  1099.                 *overflow = 1;
  1100.                 return;
  1101.         }
  1102.  
  1103.         /*
  1104.          * Factor of ten with the number of digits needed for the fractional
  1105.          * part.  For example, if the precision is 3, the mask will be 1000.
  1106.          */
  1107.         mask = (UINTMAX_T)mypow10(precision);
  1108.         /*
  1109.          * We "cheat" by converting the fractional part to integer by
  1110.          * multiplying by a factor of ten.
  1111.          */
  1112.         if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
  1113.                 /*
  1114.                  * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
  1115.                  * (because precision = 3).  Now, myround(1000 * 0.99962) will
  1116.                  * return 1000.  So, the integer part must be incremented by one
  1117.                  * and the fractional part must be set to zero.
  1118.                  */
  1119.                 intpart++;
  1120.                 fracpart = 0;
  1121.                 if (estyle && intpart == 10) {
  1122.                         /*
  1123.                          * The value was rounded up to ten, but we only want one
  1124.                          * integer digit if using "e-style".  So, the integer
  1125.                          * part must be set to one and the exponent must be
  1126.                          * incremented by one.
  1127.                          */
  1128.                         intpart = 1;
  1129.                         exponent++;
  1130.                 }
  1131.         }
  1132.  
  1133.         /*
  1134.          * Now that we know the real exponent, we can check whether or not to
  1135.          * use "e-style" for "%g" (and "%G") conversions.  If we don't need
  1136.          * "e-style", the precision must be adjusted and the integer and
  1137.          * fractional parts must be recalculated from the original value.
  1138.          *
  1139.          * C99 says: "Let P equal the precision if nonzero, 6 if the precision
  1140.          * is omitted, or 1 if the precision is zero.  Then, if a conversion
  1141.          * with style `E' would have an exponent of X:
  1142.          *
  1143.          * - if P > X >= -4, the conversion is with style `f' (or `F') and
  1144.          *   precision P - (X + 1).
  1145.          *
  1146.          * - otherwise, the conversion is with style `e' (or `E') and precision
  1147.          *   P - 1." (7.19.6.1, 8)
  1148.          *
  1149.          * Note that we had decremented the precision by one.
  1150.          */
  1151.         if (flags & PRINT_F_TYPE_G && estyle &&
  1152.             precision + 1 > exponent && exponent >= -4) {
  1153.                 precision -= exponent;
  1154.                 estyle = 0;
  1155.                 goto again;
  1156.         }
  1157.  
  1158.         if (estyle) {
  1159.                 if (exponent < 0) {
  1160.                         exponent = -exponent;
  1161.                         esign = '-';
  1162.                 } else
  1163.                         esign = '+';
  1164.  
  1165.                 /*
  1166.                  * Convert the exponent.  The sizeof(econvert) is 4.  So, the
  1167.                  * econvert buffer can hold e.g. "e+99" and "e-99".  We don't
  1168.                  * support an exponent which contains more than two digits.
  1169.                  * Therefore, the following stores are safe.
  1170.                  */
  1171.                 epos = convert(exponent, econvert, 2, 10, 0);
  1172.                 /*
  1173.                  * C99 says: "The exponent always contains at least two digits,
  1174.                  * and only as many more digits as necessary to represent the
  1175.                  * exponent." (7.19.6.1, 8)
  1176.                  */
  1177.                 if (epos == 1)
  1178.                         econvert[epos++] = '0';
  1179.                 econvert[epos++] = esign;
  1180.                 econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
  1181.         }
  1182.  
  1183.         /* Convert the integer part and the fractional part. */
  1184.         ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
  1185.         if (fracpart != 0)      /* convert() would return 1 if fracpart == 0. */
  1186.                 fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
  1187.  
  1188.         leadfraczeros = precision - fpos;
  1189.  
  1190.         if (omitzeros) {
  1191.                 if (fpos > 0)   /* Omit trailing fractional part zeros. */
  1192.                         while (omitcount < fpos && fconvert[omitcount] == '0')
  1193.                                 omitcount++;
  1194.                 else {  /* The fractional part is zero, omit it completely. */
  1195.                         omitcount = precision;
  1196.                         leadfraczeros = 0;
  1197.                 }
  1198.                 precision -= omitcount;
  1199.         }
  1200.  
  1201.         /*
  1202.          * Print a decimal point if either the fractional part is non-zero
  1203.          * and/or the "#" flag was specified.
  1204.          */
  1205.         if (precision > 0 || flags & PRINT_F_NUM)
  1206.                 emitpoint = 1;
  1207.         if (separators) /* Get the number of group separators we'll print. */
  1208.                 separators = getnumsep(ipos);
  1209.  
  1210.         padlen = width                  /* Minimum field width. */
  1211.             - ipos                      /* Number of integer digits. */
  1212.             - epos                      /* Number of exponent characters. */
  1213.             - precision                 /* Number of fractional digits. */
  1214.             - separators                /* Number of group separators. */
  1215.             - (emitpoint ? 1 : 0)       /* Will we print a decimal point? */
  1216.             - ((sign != 0) ? 1 : 0);    /* Will we print a sign character? */
  1217.  
  1218.         if (padlen < 0)
  1219.                 padlen = 0;
  1220.  
  1221.         /*
  1222.          * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
  1223.          * ignored." (7.19.6.1, 6)
  1224.          */
  1225.         if (flags & PRINT_F_MINUS)      /* Left justifty. */
  1226.                 padlen = -padlen;
  1227.         else if (flags & PRINT_F_ZERO && padlen > 0) {
  1228.                 if (sign != 0) {        /* Sign. */
  1229.                         OUTCHAR(str, *len, size, sign);
  1230.                         sign = 0;
  1231.                 }
  1232.                 while (padlen > 0) {    /* Leading zeros. */
  1233.                         OUTCHAR(str, *len, size, '0');
  1234.                         padlen--;
  1235.                 }
  1236.         }
  1237.         while (padlen > 0) {    /* Leading spaces. */
  1238.                 OUTCHAR(str, *len, size, ' ');
  1239.                 padlen--;
  1240.         }
  1241.         if (sign != 0)  /* Sign. */
  1242.                 OUTCHAR(str, *len, size, sign);
  1243.         while (ipos > 0) {      /* Integer part. */
  1244.                 ipos--;
  1245.                 OUTCHAR(str, *len, size, iconvert[ipos]);
  1246.                 if (separators > 0 && ipos > 0 && ipos % 3 == 0)
  1247.                         printsep(str, len, size);
  1248.         }
  1249.         if (emitpoint) {        /* Decimal point. */
  1250. #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
  1251.                 if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
  1252.                         OUTCHAR(str, *len, size, *lc->decimal_point);
  1253.                 else    /* We'll always print some decimal point character. */
  1254. #endif  /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
  1255.                         OUTCHAR(str, *len, size, '.');
  1256.         }
  1257.         while (leadfraczeros > 0) {     /* Leading fractional part zeros. */
  1258.                 OUTCHAR(str, *len, size, '0');
  1259.                 leadfraczeros--;
  1260.         }
  1261.         while (fpos > omitcount) {      /* The remaining fractional part. */
  1262.                 fpos--;
  1263.                 OUTCHAR(str, *len, size, fconvert[fpos]);
  1264.         }
  1265.         while (epos > 0) {      /* Exponent. */
  1266.                 epos--;
  1267.                 OUTCHAR(str, *len, size, econvert[epos]);
  1268.         }
  1269.         while (padlen < 0) {    /* Trailing spaces. */
  1270.                 OUTCHAR(str, *len, size, ' ');
  1271.                 padlen++;
  1272.         }
  1273. }
  1274.  
  1275. static void
  1276. printsep(char *str, size_t *len, size_t size)
  1277. {
  1278. #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
  1279.         struct lconv *lc = localeconv();
  1280.         int i;
  1281.  
  1282.         if (lc->thousands_sep != NULL)
  1283.                 for (i = 0; lc->thousands_sep[i] != '\0'; i++)
  1284.                         OUTCHAR(str, *len, size, lc->thousands_sep[i]);
  1285.         else
  1286. #endif  /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
  1287.                 OUTCHAR(str, *len, size, ',');
  1288. }
  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.  
  1298.         /* We support an arbitrary separator length (including zero). */
  1299.         if (lc->thousands_sep != NULL) {
  1300.                 for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
  1301.                         continue;
  1302.                 separators *= strln;
  1303.         }
  1304. #endif  /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
  1305.         return separators;
  1306. }
  1307.  
  1308. static int
  1309. getexponent(LDOUBLE value)
  1310. {
  1311.         LDOUBLE tmp = (value >= 0.0) ? value : -value;
  1312.         int exponent = 0;
  1313.  
  1314.         /*
  1315.          * We check for 99 > exponent > -99 in order to work around possible
  1316.          * endless loops which could happen (at least) in the second loop (at
  1317.          * least) if we're called with an infinite value.  However, we checked
  1318.          * for infinity before calling this function using our ISINF() macro, so
  1319.          * this might be somewhat paranoid.
  1320.          */
  1321.         while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
  1322.                 tmp *= 10;
  1323.         while (tmp >= 10.0 && ++exponent < 99)
  1324.                 tmp /= 10;
  1325.  
  1326.         return exponent;
  1327. }
  1328.  
  1329. static int
  1330. convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
  1331. {
  1332.         const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
  1333.         size_t pos = 0;
  1334.  
  1335.         /* We return an unterminated buffer with the digits in reverse order. */
  1336.         do {
  1337.                 buf[pos++] = digits[value % base];
  1338.                 value /= base;
  1339.         } while (value != 0 && pos < size);
  1340.  
  1341.         return (int)pos;
  1342. }
  1343.  
  1344. static UINTMAX_T
  1345. cast(LDOUBLE value)
  1346. {
  1347.         UINTMAX_T result;
  1348.  
  1349.         /*
  1350.          * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
  1351.          * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
  1352.          * it may be increased to the nearest higher representable value for the
  1353.          * comparison (cf. C99: 6.3.1.4, 2).  It might then equal the LDOUBLE
  1354.          * value although converting the latter to UINTMAX_T would overflow.
  1355.          */
  1356.         if (value >= UINTMAX_MAX)
  1357.                 return UINTMAX_MAX;
  1358.  
  1359.         result = (UINTMAX_T)value;
  1360.         /*
  1361.          * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
  1362.          * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
  1363.          * the standard).  Sigh.
  1364.          */
  1365.         return (result <= value) ? result : result - 1;
  1366. }
  1367.  
  1368. static UINTMAX_T
  1369. myround(LDOUBLE value)
  1370. {
  1371.         UINTMAX_T intpart = cast(value);
  1372.  
  1373.         return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
  1374. }
  1375.  
  1376. static LDOUBLE
  1377. mypow10(int exponent)
  1378. {
  1379.         LDOUBLE result = 1;
  1380.  
  1381.         while (exponent > 0) {
  1382.                 result *= 10;
  1383.                 exponent--;
  1384.         }
  1385.         while (exponent < 0) {
  1386.                 result /= 10;
  1387.                 exponent++;
  1388.         }
  1389.         return result;
  1390. }
  1391. #endif  /* !HAVE_VSNPRINTF */
  1392.  
  1393. #if !HAVE_VASPRINTF
  1394. #if NEED_MYMEMCPY
  1395. void *
  1396. mymemcpy(void *dst, void *src, size_t len)
  1397. {
  1398.         const char *from = src;
  1399.         char *to = dst;
  1400.  
  1401.         /* No need for optimization, we use this only to replace va_copy(3). */
  1402.         while (len-- > 0)
  1403.                 *to++ = *from++;
  1404.         return dst;
  1405. }
  1406. #endif  /* NEED_MYMEMCPY */
  1407.  
  1408. int
  1409. util_vasprintf(char **ret, const char *format, va_list ap)
  1410. {
  1411.         size_t size;
  1412.         int len;
  1413.         va_list aq;
  1414.  
  1415.         VA_COPY(aq, ap);
  1416.         len = vsnprintf(NULL, 0, format, aq);
  1417.         VA_END_COPY(aq);
  1418.         if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
  1419.                 return -1;
  1420.         return vsnprintf(*ret, size, format, ap);
  1421. }
  1422. #endif  /* !HAVE_VASPRINTF */
  1423.  
  1424. #if !HAVE_SNPRINTF
  1425. #if HAVE_STDARG_H
  1426. int
  1427. util_snprintf(char *str, size_t size, const char *format, ...)
  1428. #else
  1429. int
  1430. util_snprintf(va_alist) va_dcl
  1431. #endif  /* HAVE_STDARG_H */
  1432. {
  1433. #if !HAVE_STDARG_H
  1434.         char *str;
  1435.         size_t size;
  1436.         char *format;
  1437. #endif  /* HAVE_STDARG_H */
  1438.         va_list ap;
  1439.         int len;
  1440.  
  1441.         VA_START(ap, format);
  1442.         VA_SHIFT(ap, str, char *);
  1443.         VA_SHIFT(ap, size, size_t);
  1444.         VA_SHIFT(ap, format, const char *);
  1445.         len = vsnprintf(str, size, format, ap);
  1446.         va_end(ap);
  1447.         return len;
  1448. }
  1449. #endif  /* !HAVE_SNPRINTF */
  1450.  
  1451. #if !HAVE_ASPRINTF
  1452. #if HAVE_STDARG_H
  1453. int
  1454. util_asprintf(char **ret, const char *format, ...)
  1455. #else
  1456. int
  1457. util_asprintf(va_alist) va_dcl
  1458. #endif  /* HAVE_STDARG_H */
  1459. {
  1460. #if !HAVE_STDARG_H
  1461.         char **ret;
  1462.         char *format;
  1463. #endif  /* HAVE_STDARG_H */
  1464.         va_list ap;
  1465.         int len;
  1466.  
  1467.         VA_START(ap, format);
  1468.         VA_SHIFT(ap, ret, char **);
  1469.         VA_SHIFT(ap, format, const char *);
  1470.         len = vasprintf(ret, format, ap);
  1471.         va_end(ap);
  1472.         return len;
  1473. }
  1474. #endif  /* !HAVE_ASPRINTF */
  1475. #else   /* Dummy declaration to avoid empty translation unit warnings. */
  1476. int main(void);
  1477. #endif  /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */
  1478.  
  1479.  
  1480. /* vim: set joinspaces textwidth=80: */
  1481.