Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 0
  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. /* WinCE5.0 does not have uintptr_t defined */
  338. #if (_WIN32_WCE < 600)
  339. #ifdef UINTPTR_T
  340. #undef UINTPTR_T
  341. #endif
  342. #define UINTPTR_T unsigned long int
  343. #endif
  344.  
  345.  
  346. /* Support for ptrdiff_t. */
  347. #ifndef PTRDIFF_T
  348. #if HAVE_PTRDIFF_T || defined(ptrdiff_t)
  349. #define PTRDIFF_T ptrdiff_t
  350. #else
  351. #define PTRDIFF_T long int
  352. #endif  /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
  353. #endif  /* !defined(PTRDIFF_T) */
  354.  
  355. /*
  356.  * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
  357.  * 7.19.6.1, 7).  However, we'll simply use PTRDIFF_T and convert it to an
  358.  * unsigned type if necessary.  This should work just fine in practice.
  359.  */
  360. #ifndef UPTRDIFF_T
  361. #define UPTRDIFF_T PTRDIFF_T
  362. #endif  /* !defined(UPTRDIFF_T) */
  363.  
  364. /*
  365.  * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
  366.  * However, we'll simply use size_t and convert it to a signed type if
  367.  * necessary.  This should work just fine in practice.
  368.  */
  369. #ifndef SSIZE_T
  370. #define SSIZE_T size_t
  371. #endif  /* !defined(SSIZE_T) */
  372.  
  373. /* Either ERANGE or E2BIG should be available everywhere. */
  374. #ifndef ERANGE
  375. #define ERANGE E2BIG
  376. #endif  /* !defined(ERANGE) */
  377. #ifndef EOVERFLOW
  378. #define EOVERFLOW ERANGE
  379. #endif  /* !defined(EOVERFLOW) */
  380.  
  381. /*
  382.  * Buffer size to hold the octal string representation of UINT128_MAX without
  383.  * nul-termination ("3777777777777777777777777777777777777777777").
  384.  */
  385. #ifdef MAX_CONVERT_LENGTH
  386. #undef MAX_CONVERT_LENGTH
  387. #endif  /* defined(MAX_CONVERT_LENGTH) */
  388. #define MAX_CONVERT_LENGTH      43
  389.  
  390. /* Format read states. */
  391. #define PRINT_S_DEFAULT         0
  392. #define PRINT_S_FLAGS           1
  393. #define PRINT_S_WIDTH           2
  394. #define PRINT_S_DOT             3
  395. #define PRINT_S_PRECISION       4
  396. #define PRINT_S_MOD             5
  397. #define PRINT_S_CONV            6
  398.  
  399. /* Format flags. */
  400. #define PRINT_F_MINUS           (1 << 0)
  401. #define PRINT_F_PLUS            (1 << 1)
  402. #define PRINT_F_SPACE           (1 << 2)
  403. #define PRINT_F_NUM             (1 << 3)
  404. #define PRINT_F_ZERO            (1 << 4)
  405. #define PRINT_F_QUOTE           (1 << 5)
  406. #define PRINT_F_UP              (1 << 6)
  407. #define PRINT_F_UNSIGNED        (1 << 7)
  408. #define PRINT_F_TYPE_G          (1 << 8)
  409. #define PRINT_F_TYPE_E          (1 << 9)
  410.  
  411. /* Conversion flags. */
  412. #define PRINT_C_CHAR            1
  413. #define PRINT_C_SHORT           2
  414. #define PRINT_C_LONG            3
  415. #define PRINT_C_LLONG           4
  416. #define PRINT_C_LDOUBLE         5
  417. #define PRINT_C_SIZE            6
  418. #define PRINT_C_PTRDIFF         7
  419. #define PRINT_C_INTMAX          8
  420.  
  421. #ifndef MAX
  422. #define MAX(x, y) ((x >= y) ? x : y)
  423. #endif  /* !defined(MAX) */
  424. #ifndef CHARTOINT
  425. #define CHARTOINT(ch) (ch - '0')
  426. #endif  /* !defined(CHARTOINT) */
  427. #ifndef ISDIGIT
  428. #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
  429. #endif  /* !defined(ISDIGIT) */
  430. #ifndef ISNAN
  431. #define ISNAN(x) (x != x)
  432. #endif  /* !defined(ISNAN) */
  433. #ifndef ISINF
  434. #define ISINF(x) (x != 0.0 && x + x == x)
  435. #endif  /* !defined(ISINF) */
  436.  
  437. #ifdef OUTCHAR
  438. #undef OUTCHAR
  439. #endif  /* defined(OUTCHAR) */
  440. #define OUTCHAR(str, len, size, ch)                                          \
  441. do {                                                                         \
  442.         if (len + 1 < size)                                                  \
  443.                 str[len] = ch;                                               \
  444.         (len)++;                                                             \
  445. } while (/* CONSTCOND */ 0)
  446.  
  447. static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
  448. static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
  449. static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
  450. static void printsep(char *, size_t *, size_t);
  451. static int getnumsep(int);
  452. static int getexponent(LDOUBLE);
  453. static int convert(UINTMAX_T, char *, size_t, int, int);
  454. static UINTMAX_T cast(LDOUBLE);
  455. static UINTMAX_T myround(LDOUBLE);
  456. static LDOUBLE mypow10(int);
  457.  
  458. int
  459. util_vsnprintf(char *str, size_t size, const char *format, va_list args)
  460. {
  461.         LDOUBLE fvalue;
  462.         INTMAX_T value;
  463.         unsigned char cvalue;
  464.         const char *strvalue;
  465.         INTMAX_T *intmaxptr;
  466.         PTRDIFF_T *ptrdiffptr;
  467.         SSIZE_T *sizeptr;
  468.         LLONG *llongptr;
  469.         long int *longptr;
  470.         int *intptr;
  471.         short int *shortptr;
  472.         signed char *charptr;
  473.         size_t len = 0;
  474.         int overflow = 0;
  475.         int base = 0;
  476.         int cflags = 0;
  477.         int flags = 0;
  478.         int width = 0;
  479.         int precision = -1;
  480.         int state = PRINT_S_DEFAULT;
  481.         char ch = *format++;
  482.  
  483.         /*
  484.          * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
  485.          * pointer." (7.19.6.5, 2)  We're forgiving and allow a NULL pointer
  486.          * even if a size larger than zero was specified.  At least NetBSD's
  487.          * snprintf(3) does the same, as well as other versions of this file.
  488.          * (Though some of these versions will write to a non-NULL buffer even
  489.          * if a size of zero was specified, which violates the standard.)
  490.          */
  491.         if (str == NULL && size != 0)
  492.                 size = 0;
  493.  
  494.         while (ch != '\0')
  495.                 switch (state) {
  496.                 case PRINT_S_DEFAULT:
  497.                         if (ch == '%')
  498.                                 state = PRINT_S_FLAGS;
  499.                         else
  500.                                 OUTCHAR(str, len, size, ch);
  501.                         ch = *format++;
  502.                         break;
  503.                 case PRINT_S_FLAGS:
  504.                         switch (ch) {
  505.                         case '-':
  506.                                 flags |= PRINT_F_MINUS;
  507.                                 ch = *format++;
  508.                                 break;
  509.                         case '+':
  510.                                 flags |= PRINT_F_PLUS;
  511.                                 ch = *format++;
  512.                                 break;
  513.                         case ' ':
  514.                                 flags |= PRINT_F_SPACE;
  515.                                 ch = *format++;
  516.                                 break;
  517.                         case '#':
  518.                                 flags |= PRINT_F_NUM;
  519.                                 ch = *format++;
  520.                                 break;
  521.                         case '0':
  522.                                 flags |= PRINT_F_ZERO;
  523.                                 ch = *format++;
  524.                                 break;
  525.                         case '\'':      /* SUSv2 flag (not in C99). */
  526.                                 flags |= PRINT_F_QUOTE;
  527.                                 ch = *format++;
  528.                                 break;
  529.                         default:
  530.                                 state = PRINT_S_WIDTH;
  531.                                 break;
  532.                         }
  533.                         break;
  534.                 case PRINT_S_WIDTH:
  535.                         if (ISDIGIT(ch)) {
  536.                                 ch = CHARTOINT(ch);
  537.                                 if (width > (INT_MAX - ch) / 10) {
  538.                                         overflow = 1;
  539.                                         goto out;
  540.                                 }
  541.                                 width = 10 * width + ch;
  542.                                 ch = *format++;
  543.                         } else if (ch == '*') {
  544.                                 /*
  545.                                  * C99 says: "A negative field width argument is
  546.                                  * taken as a `-' flag followed by a positive
  547.                                  * field width." (7.19.6.1, 5)
  548.                                  */
  549.                                 if ((width = va_arg(args, int)) < 0) {
  550.                                         flags |= PRINT_F_MINUS;
  551.                                         width = -width;
  552.                                 }
  553.                                 ch = *format++;
  554.                                 state = PRINT_S_DOT;
  555.                         } else
  556.                                 state = PRINT_S_DOT;
  557.                         break;
  558.                 case PRINT_S_DOT:
  559.                         if (ch == '.') {
  560.                                 state = PRINT_S_PRECISION;
  561.                                 ch = *format++;
  562.                         } else
  563.                                 state = PRINT_S_MOD;
  564.                         break;
  565.                 case PRINT_S_PRECISION:
  566.                         if (precision == -1)
  567.                                 precision = 0;
  568.                         if (ISDIGIT(ch)) {
  569.                                 ch = CHARTOINT(ch);
  570.                                 if (precision > (INT_MAX - ch) / 10) {
  571.                                         overflow = 1;
  572.                                         goto out;
  573.                                 }
  574.                                 precision = 10 * precision + ch;
  575.                                 ch = *format++;
  576.                         } else if (ch == '*') {
  577.                                 /*
  578.                                  * C99 says: "A negative precision argument is
  579.                                  * taken as if the precision were omitted."
  580.                                  * (7.19.6.1, 5)
  581.                                  */
  582.                                 if ((precision = va_arg(args, int)) < 0)
  583.                                         precision = -1;
  584.                                 ch = *format++;
  585.                                 state = PRINT_S_MOD;
  586.                         } else
  587.                                 state = PRINT_S_MOD;
  588.                         break;
  589.                 case PRINT_S_MOD:
  590.                         switch (ch) {
  591.                         case 'h':
  592.                                 ch = *format++;
  593.                                 if (ch == 'h') {        /* It's a char. */
  594.                                         ch = *format++;
  595.                                         cflags = PRINT_C_CHAR;
  596.                                 } else
  597.                                         cflags = PRINT_C_SHORT;
  598.                                 break;
  599.                         case 'l':
  600.                                 ch = *format++;
  601.                                 if (ch == 'l') {        /* It's a long long. */
  602.                                         ch = *format++;
  603.                                         cflags = PRINT_C_LLONG;
  604.                                 } else
  605.                                         cflags = PRINT_C_LONG;
  606.                                 break;
  607.                         case 'L':
  608.                                 cflags = PRINT_C_LDOUBLE;
  609.                                 ch = *format++;
  610.                                 break;
  611.                         case 'j':
  612.                                 cflags = PRINT_C_INTMAX;
  613.                                 ch = *format++;
  614.                                 break;
  615.                         case 't':
  616.                                 cflags = PRINT_C_PTRDIFF;
  617.                                 ch = *format++;
  618.                                 break;
  619.                         case 'z':
  620.                                 cflags = PRINT_C_SIZE;
  621.                                 ch = *format++;
  622.                                 break;
  623.                         }
  624.                         state = PRINT_S_CONV;
  625.                         break;
  626.                 case PRINT_S_CONV:
  627.                         switch (ch) {
  628.                         case 'd':
  629.                                 /* FALLTHROUGH */
  630.                         case 'i':
  631.                                 switch (cflags) {
  632.                                 case PRINT_C_CHAR:
  633.                                         value = (signed char)va_arg(args, int);
  634.                                         break;
  635.                                 case PRINT_C_SHORT:
  636.                                         value = (short int)va_arg(args, int);
  637.                                         break;
  638.                                 case PRINT_C_LONG:
  639.                                         value = va_arg(args, long int);
  640.                                         break;
  641.                                 case PRINT_C_LLONG:
  642.                                         value = va_arg(args, LLONG);
  643.                                         break;
  644.                                 case PRINT_C_SIZE:
  645.                                         value = va_arg(args, SSIZE_T);
  646.                                         break;
  647.                                 case PRINT_C_INTMAX:
  648.                                         value = va_arg(args, INTMAX_T);
  649.                                         break;
  650.                                 case PRINT_C_PTRDIFF:
  651.                                         value = va_arg(args, PTRDIFF_T);
  652.                                         break;
  653.                                 default:
  654.                                         value = va_arg(args, int);
  655.                                         break;
  656.                                 }
  657.                                 fmtint(str, &len, size, value, 10, width,
  658.                                     precision, flags);
  659.                                 break;
  660.                         case 'X':
  661.                                 flags |= PRINT_F_UP;
  662.                                 /* FALLTHROUGH */
  663.                         case 'x':
  664.                                 base = 16;
  665.                                 /* FALLTHROUGH */
  666.                         case 'o':
  667.                                 if (base == 0)
  668.                                         base = 8;
  669.                                 /* FALLTHROUGH */
  670.                         case 'u':
  671.                                 if (base == 0)
  672.                                         base = 10;
  673.                                 flags |= PRINT_F_UNSIGNED;
  674.                                 switch (cflags) {
  675.                                 case PRINT_C_CHAR:
  676.                                         value = (unsigned char)va_arg(args,
  677.                                             unsigned int);
  678.                                         break;
  679.                                 case PRINT_C_SHORT:
  680.                                         value = (unsigned short int)va_arg(args,
  681.                                             unsigned int);
  682.                                         break;
  683.                                 case PRINT_C_LONG:
  684.                                         value = va_arg(args, unsigned long int);
  685.                                         break;
  686.                                 case PRINT_C_LLONG:
  687.                                         value = va_arg(args, ULLONG);
  688.                                         break;
  689.                                 case PRINT_C_SIZE:
  690.                                         value = va_arg(args, size_t);
  691.                                         break;
  692.                                 case PRINT_C_INTMAX:
  693.                                         value = va_arg(args, UINTMAX_T);
  694.                                         break;
  695.                                 case PRINT_C_PTRDIFF:
  696.                                         value = va_arg(args, UPTRDIFF_T);
  697.                                         break;
  698.                                 default:
  699.                                         value = va_arg(args, unsigned int);
  700.                                         break;
  701.                                 }
  702.                                 fmtint(str, &len, size, value, base, width,
  703.                                     precision, flags);
  704.                                 break;
  705.                         case 'A':
  706.                                 /* Not yet supported, we'll use "%F". */
  707.                                 /* FALLTHROUGH */
  708.                         case 'F':
  709.                                 flags |= PRINT_F_UP;
  710.                         case 'a':
  711.                                 /* Not yet supported, we'll use "%f". */
  712.                                 /* FALLTHROUGH */
  713.                         case 'f':
  714.                                 if (cflags == PRINT_C_LDOUBLE)
  715.                                         fvalue = va_arg(args, LDOUBLE);
  716.                                 else
  717.                                         fvalue = va_arg(args, double);
  718.                                 fmtflt(str, &len, size, fvalue, width,
  719.                                     precision, flags, &overflow);
  720.                                 if (overflow)
  721.                                         goto out;
  722.                                 break;
  723.                         case 'E':
  724.                                 flags |= PRINT_F_UP;
  725.                                 /* FALLTHROUGH */
  726.                         case 'e':
  727.                                 flags |= PRINT_F_TYPE_E;
  728.                                 if (cflags == PRINT_C_LDOUBLE)
  729.                                         fvalue = va_arg(args, LDOUBLE);
  730.                                 else
  731.                                         fvalue = va_arg(args, double);
  732.                                 fmtflt(str, &len, size, fvalue, width,
  733.                                     precision, flags, &overflow);
  734.                                 if (overflow)
  735.                                         goto out;
  736.                                 break;
  737.                         case 'G':
  738.                                 flags |= PRINT_F_UP;
  739.                                 /* FALLTHROUGH */
  740.                         case 'g':
  741.                                 flags |= PRINT_F_TYPE_G;
  742.                                 if (cflags == PRINT_C_LDOUBLE)
  743.                                         fvalue = va_arg(args, LDOUBLE);
  744.                                 else
  745.                                         fvalue = va_arg(args, double);
  746.                                 /*
  747.                                  * If the precision is zero, it is treated as
  748.                                  * one (cf. C99: 7.19.6.1, 8).
  749.                                  */
  750.                                 if (precision == 0)
  751.                                         precision = 1;
  752.                                 fmtflt(str, &len, size, fvalue, width,
  753.                                     precision, flags, &overflow);
  754.                                 if (overflow)
  755.                                         goto out;
  756.                                 break;
  757.                         case 'c':
  758.                                 cvalue = (unsigned char)va_arg(args, int);
  759.                                 OUTCHAR(str, len, size, cvalue);
  760.                                 break;
  761.                         case 's':
  762.                                 strvalue = va_arg(args, char *);
  763.                                 fmtstr(str, &len, size, strvalue, width,
  764.                                     precision, flags);
  765.                                 break;
  766.                         case 'p':
  767.                                 /*
  768.                                  * C99 says: "The value of the pointer is
  769.                                  * converted to a sequence of printing
  770.                                  * characters, in an implementation-defined
  771.                                  * manner." (C99: 7.19.6.1, 8)
  772.                                  */
  773.                                 if ((strvalue = va_arg(args, void *)) == NULL)
  774.                                         /*
  775.                                          * We use the glibc format.  BSD prints
  776.                                          * "0x0", SysV "0".
  777.                                          */
  778.                                         fmtstr(str, &len, size, "(nil)", width,
  779.                                             -1, flags);
  780.                                 else {
  781.                                         /*
  782.                                          * We use the BSD/glibc format.  SysV
  783.                                          * omits the "0x" prefix (which we emit
  784.                                          * using the PRINT_F_NUM flag).
  785.                                          */
  786.                                         flags |= PRINT_F_NUM;
  787.                                         flags |= PRINT_F_UNSIGNED;
  788.                                         fmtint(str, &len, size,
  789.                                             (UINTPTR_T)strvalue, 16, width,
  790.                                             precision, flags);
  791.                                 }
  792.                                 break;
  793.                         case 'n':
  794.                                 switch (cflags) {
  795.                                 case PRINT_C_CHAR:
  796.                                         charptr = va_arg(args, signed char *);
  797.                                         *charptr = (signed char)len;
  798.                                         break;
  799.                                 case PRINT_C_SHORT:
  800.                                         shortptr = va_arg(args, short int *);
  801.                                         *shortptr = (short int)len;
  802.                                         break;
  803.                                 case PRINT_C_LONG:
  804.                                         longptr = va_arg(args, long int *);
  805.                                         *longptr = (long int)len;
  806.                                         break;
  807.                                 case PRINT_C_LLONG:
  808.                                         llongptr = va_arg(args, LLONG *);
  809.                                         *llongptr = (LLONG)len;
  810.                                         break;
  811.                                 case PRINT_C_SIZE:
  812.                                         /*
  813.                                          * C99 says that with the "z" length
  814.                                          * modifier, "a following `n' conversion
  815.                                          * specifier applies to a pointer to a
  816.                                          * signed integer type corresponding to
  817.                                          * size_t argument." (7.19.6.1, 7)
  818.                                          */
  819.                                         sizeptr = va_arg(args, SSIZE_T *);
  820.                                         *sizeptr = len;
  821.                                         break;
  822.                                 case PRINT_C_INTMAX:
  823.                                         intmaxptr = va_arg(args, INTMAX_T *);
  824.                                         *intmaxptr = len;
  825.                                         break;
  826.                                 case PRINT_C_PTRDIFF:
  827.                                         ptrdiffptr = va_arg(args, PTRDIFF_T *);
  828.                                         *ptrdiffptr = len;
  829.                                         break;
  830.                                 default:
  831.                                         intptr = va_arg(args, int *);
  832.                                         *intptr = (int)len;
  833.                                         break;
  834.                                 }
  835.                                 break;
  836.                         case '%':       /* Print a "%" character verbatim. */
  837.                                 OUTCHAR(str, len, size, ch);
  838.                                 break;
  839.                         default:        /* Skip other characters. */
  840.                                 break;
  841.                         }
  842.                         ch = *format++;
  843.                         state = PRINT_S_DEFAULT;
  844.                         base = cflags = flags = width = 0;
  845.                         precision = -1;
  846.                         break;
  847.                 }
  848. out:
  849.         if (len < size)
  850.                 str[len] = '\0';
  851.         else if (size > 0)
  852.                 str[size - 1] = '\0';
  853.  
  854.         if (overflow || len >= INT_MAX) {
  855.                 return -1;
  856.         }
  857.         return (int)len;
  858. }
  859.  
  860. static void
  861. fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
  862.        int precision, int flags)
  863. {
  864.         int padlen, strln;      /* Amount to pad. */
  865.         int noprecision = (precision == -1);
  866.  
  867.         if (value == NULL)      /* We're forgiving. */
  868.                 value = "(null)";
  869.  
  870.         /* If a precision was specified, don't read the string past it. */
  871.         for (strln = 0; value[strln] != '\0' &&
  872.             (noprecision || strln < precision); strln++)
  873.                 continue;
  874.  
  875.         if ((padlen = width - strln) < 0)
  876.                 padlen = 0;
  877.         if (flags & PRINT_F_MINUS)      /* Left justify. */
  878.                 padlen = -padlen;
  879.  
  880.         while (padlen > 0) {    /* Leading spaces. */
  881.                 OUTCHAR(str, *len, size, ' ');
  882.                 padlen--;
  883.         }
  884.         while (*value != '\0' && (noprecision || precision-- > 0)) {
  885.                 OUTCHAR(str, *len, size, *value);
  886.                 value++;
  887.         }
  888.         while (padlen < 0) {    /* Trailing spaces. */
  889.                 OUTCHAR(str, *len, size, ' ');
  890.                 padlen++;
  891.         }
  892. }
  893.  
  894. static void
  895. fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
  896.        int precision, int flags)
  897. {
  898.         UINTMAX_T uvalue;
  899.         char iconvert[MAX_CONVERT_LENGTH];
  900.         char sign = 0;
  901.         char hexprefix = 0;
  902.         int spadlen = 0;        /* Amount to space pad. */
  903.         int zpadlen = 0;        /* Amount to zero pad. */
  904.         int pos;
  905.         int separators = (flags & PRINT_F_QUOTE);
  906.         int noprecision = (precision == -1);
  907.  
  908.         if (flags & PRINT_F_UNSIGNED)
  909.                 uvalue = value;
  910.         else {
  911.                 uvalue = (value >= 0) ? value : -value;
  912.                 if (value < 0)
  913.                         sign = '-';
  914.                 else if (flags & PRINT_F_PLUS)  /* Do a sign. */
  915.                         sign = '+';
  916.                 else if (flags & PRINT_F_SPACE)
  917.                         sign = ' ';
  918.         }
  919.  
  920.         pos = convert(uvalue, iconvert, sizeof(iconvert), base,
  921.             flags & PRINT_F_UP);
  922.  
  923.         if (flags & PRINT_F_NUM && uvalue != 0) {
  924.                 /*
  925.                  * C99 says: "The result is converted to an `alternative form'.
  926.                  * For `o' conversion, it increases the precision, if and only
  927.                  * if necessary, to force the first digit of the result to be a
  928.                  * zero (if the value and precision are both 0, a single 0 is
  929.                  * printed).  For `x' (or `X') conversion, a nonzero result has
  930.                  * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
  931.                  */
  932.                 switch (base) {
  933.                 case 8:
  934.                         if (precision <= pos)
  935.                                 precision = pos + 1;
  936.                         break;
  937.                 case 16:
  938.                         hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
  939.                         break;
  940.                 }
  941.         }
  942.  
  943.         if (separators) /* Get the number of group separators we'll print. */
  944.                 separators = getnumsep(pos);
  945.  
  946.         zpadlen = precision - pos - separators;
  947.         spadlen = width                         /* Minimum field width. */
  948.             - separators                        /* Number of separators. */
  949.             - MAX(precision, pos)               /* Number of integer digits. */
  950.             - ((sign != 0) ? 1 : 0)             /* Will we print a sign? */
  951.             - ((hexprefix != 0) ? 2 : 0);       /* Will we print a prefix? */
  952.  
  953.         if (zpadlen < 0)
  954.                 zpadlen = 0;
  955.         if (spadlen < 0)
  956.                 spadlen = 0;
  957.  
  958.         /*
  959.          * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
  960.          * ignored.  For `d', `i', `o', `u', `x', and `X' conversions, if a
  961.          * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
  962.          */
  963.         if (flags & PRINT_F_MINUS)      /* Left justify. */
  964.                 spadlen = -spadlen;
  965.         else if (flags & PRINT_F_ZERO && noprecision) {
  966.                 zpadlen += spadlen;
  967.                 spadlen = 0;
  968.         }
  969.         while (spadlen > 0) {   /* Leading spaces. */
  970.                 OUTCHAR(str, *len, size, ' ');
  971.                 spadlen--;
  972.         }
  973.         if (sign != 0)  /* Sign. */
  974.                 OUTCHAR(str, *len, size, sign);
  975.         if (hexprefix != 0) {   /* A "0x" or "0X" prefix. */
  976.                 OUTCHAR(str, *len, size, '0');
  977.                 OUTCHAR(str, *len, size, hexprefix);
  978.         }
  979.         while (zpadlen > 0) {   /* Leading zeros. */
  980.                 OUTCHAR(str, *len, size, '0');
  981.                 zpadlen--;
  982.         }
  983.         while (pos > 0) {       /* The actual digits. */
  984.                 pos--;
  985.                 OUTCHAR(str, *len, size, iconvert[pos]);
  986.                 if (separators > 0 && pos > 0 && pos % 3 == 0)
  987.                         printsep(str, len, size);
  988.         }
  989.         while (spadlen < 0) {   /* Trailing spaces. */
  990.                 OUTCHAR(str, *len, size, ' ');
  991.                 spadlen++;
  992.         }
  993. }
  994.  
  995. static void
  996. fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
  997.        int precision, int flags, int *overflow)
  998. {
  999.         LDOUBLE ufvalue;
  1000.         UINTMAX_T intpart;
  1001.         UINTMAX_T fracpart;
  1002.         UINTMAX_T mask;
  1003.         const char *infnan = NULL;
  1004.         char iconvert[MAX_CONVERT_LENGTH];
  1005.         char fconvert[MAX_CONVERT_LENGTH];
  1006.         char econvert[4];       /* "e-12" (without nul-termination). */
  1007.         char esign = 0;
  1008.         char sign = 0;
  1009.         int leadfraczeros = 0;
  1010.         int exponent = 0;
  1011.         int emitpoint = 0;
  1012.         int omitzeros = 0;
  1013.         int omitcount = 0;
  1014.         int padlen = 0;
  1015.         int epos = 0;
  1016.         int fpos = 0;
  1017.         int ipos = 0;
  1018.         int separators = (flags & PRINT_F_QUOTE);
  1019.         int estyle = (flags & PRINT_F_TYPE_E);
  1020. #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
  1021.         struct lconv *lc = localeconv();
  1022. #endif  /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
  1023.  
  1024.         /*
  1025.          * AIX' man page says the default is 0, but C99 and at least Solaris'
  1026.          * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
  1027.          * defaults to 6.
  1028.          */
  1029.         if (precision == -1)
  1030.                 precision = 6;
  1031.  
  1032.         if (fvalue < 0.0)
  1033.                 sign = '-';
  1034.         else if (flags & PRINT_F_PLUS)  /* Do a sign. */
  1035.                 sign = '+';
  1036.         else if (flags & PRINT_F_SPACE)
  1037.                 sign = ' ';
  1038.  
  1039.         if (ISNAN(fvalue))
  1040.                 infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
  1041.         else if (ISINF(fvalue))
  1042.                 infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
  1043.  
  1044.         if (infnan != NULL) {
  1045.                 if (sign != 0)
  1046.                         iconvert[ipos++] = sign;
  1047.                 while (*infnan != '\0')
  1048.                         iconvert[ipos++] = *infnan++;
  1049.                 fmtstr(str, len, size, iconvert, width, ipos, flags);
  1050.                 return;
  1051.         }
  1052.  
  1053.         /* "%e" (or "%E") or "%g" (or "%G") conversion. */
  1054.         if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
  1055.                 if (flags & PRINT_F_TYPE_G) {
  1056.                         /*
  1057.                          * For "%g" (and "%G") conversions, the precision
  1058.                          * specifies the number of significant digits, which
  1059.                          * includes the digits in the integer part.  The
  1060.                          * conversion will or will not be using "e-style" (like
  1061.                          * "%e" or "%E" conversions) depending on the precision
  1062.                          * and on the exponent.  However, the exponent can be
  1063.                          * affected by rounding the converted value, so we'll
  1064.                          * leave this decision for later.  Until then, we'll
  1065.                          * assume that we're going to do an "e-style" conversion
  1066.                          * (in order to get the exponent calculated).  For
  1067.                          * "e-style", the precision must be decremented by one.
  1068.                          */
  1069.                         precision--;
  1070.                         /*
  1071.                          * For "%g" (and "%G") conversions, trailing zeros are
  1072.                          * removed from the fractional portion of the result
  1073.                          * unless the "#" flag was specified.
  1074.                          */
  1075.                         if (!(flags & PRINT_F_NUM))
  1076.                                 omitzeros = 1;
  1077.                 }
  1078.                 exponent = getexponent(fvalue);
  1079.                 estyle = 1;
  1080.         }
  1081.  
  1082. again:
  1083.         /*
  1084.          * Sorry, we only support 9, 19, or 38 digits (that is, the number of
  1085.          * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
  1086.          * minus one) past the decimal point due to our conversion method.
  1087.          */
  1088.         switch (sizeof(UINTMAX_T)) {
  1089.         case 16:
  1090.                 if (precision > 38)
  1091.                         precision = 38;
  1092.                 break;
  1093.         case 8:
  1094.                 if (precision > 19)
  1095.                         precision = 19;
  1096.                 break;
  1097.         default:
  1098.                 if (precision > 9)
  1099.                         precision = 9;
  1100.                 break;
  1101.         }
  1102.  
  1103.         ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
  1104.         if (estyle)     /* We want exactly one integer digit. */
  1105.                 ufvalue /= mypow10(exponent);
  1106.  
  1107.         if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
  1108.                 *overflow = 1;
  1109.                 return;
  1110.         }
  1111.  
  1112.         /*
  1113.          * Factor of ten with the number of digits needed for the fractional
  1114.          * part.  For example, if the precision is 3, the mask will be 1000.
  1115.          */
  1116.         mask = (UINTMAX_T)mypow10(precision);
  1117.         /*
  1118.          * We "cheat" by converting the fractional part to integer by
  1119.          * multiplying by a factor of ten.
  1120.          */
  1121.         if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
  1122.                 /*
  1123.                  * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
  1124.                  * (because precision = 3).  Now, myround(1000 * 0.99962) will
  1125.                  * return 1000.  So, the integer part must be incremented by one
  1126.                  * and the fractional part must be set to zero.
  1127.                  */
  1128.                 intpart++;
  1129.                 fracpart = 0;
  1130.                 if (estyle && intpart == 10) {
  1131.                         /*
  1132.                          * The value was rounded up to ten, but we only want one
  1133.                          * integer digit if using "e-style".  So, the integer
  1134.                          * part must be set to one and the exponent must be
  1135.                          * incremented by one.
  1136.                          */
  1137.                         intpart = 1;
  1138.                         exponent++;
  1139.                 }
  1140.         }
  1141.  
  1142.         /*
  1143.          * Now that we know the real exponent, we can check whether or not to
  1144.          * use "e-style" for "%g" (and "%G") conversions.  If we don't need
  1145.          * "e-style", the precision must be adjusted and the integer and
  1146.          * fractional parts must be recalculated from the original value.
  1147.          *
  1148.          * C99 says: "Let P equal the precision if nonzero, 6 if the precision
  1149.          * is omitted, or 1 if the precision is zero.  Then, if a conversion
  1150.          * with style `E' would have an exponent of X:
  1151.          *
  1152.          * - if P > X >= -4, the conversion is with style `f' (or `F') and
  1153.          *   precision P - (X + 1).
  1154.          *
  1155.          * - otherwise, the conversion is with style `e' (or `E') and precision
  1156.          *   P - 1." (7.19.6.1, 8)
  1157.          *
  1158.          * Note that we had decremented the precision by one.
  1159.          */
  1160.         if (flags & PRINT_F_TYPE_G && estyle &&
  1161.             precision + 1 > exponent && exponent >= -4) {
  1162.                 precision -= exponent;
  1163.                 estyle = 0;
  1164.                 goto again;
  1165.         }
  1166.  
  1167.         if (estyle) {
  1168.                 if (exponent < 0) {
  1169.                         exponent = -exponent;
  1170.                         esign = '-';
  1171.                 } else
  1172.                         esign = '+';
  1173.  
  1174.                 /*
  1175.                  * Convert the exponent.  The sizeof(econvert) is 4.  So, the
  1176.                  * econvert buffer can hold e.g. "e+99" and "e-99".  We don't
  1177.                  * support an exponent which contains more than two digits.
  1178.                  * Therefore, the following stores are safe.
  1179.                  */
  1180.                 epos = convert(exponent, econvert, 2, 10, 0);
  1181.                 /*
  1182.                  * C99 says: "The exponent always contains at least two digits,
  1183.                  * and only as many more digits as necessary to represent the
  1184.                  * exponent." (7.19.6.1, 8)
  1185.                  */
  1186.                 if (epos == 1)
  1187.                         econvert[epos++] = '0';
  1188.                 econvert[epos++] = esign;
  1189.                 econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
  1190.         }
  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.  
  1197.         leadfraczeros = precision - fpos;
  1198.  
  1199.         if (omitzeros) {
  1200.                 if (fpos > 0)   /* Omit trailing fractional part zeros. */
  1201.                         while (omitcount < fpos && fconvert[omitcount] == '0')
  1202.                                 omitcount++;
  1203.                 else {  /* The fractional part is zero, omit it completely. */
  1204.                         omitcount = precision;
  1205.                         leadfraczeros = 0;
  1206.                 }
  1207.                 precision -= omitcount;
  1208.         }
  1209.  
  1210.         /*
  1211.          * Print a decimal point if either the fractional part is non-zero
  1212.          * and/or the "#" flag was specified.
  1213.          */
  1214.         if (precision > 0 || flags & PRINT_F_NUM)
  1215.                 emitpoint = 1;
  1216.         if (separators) /* Get the number of group separators we'll print. */
  1217.                 separators = getnumsep(ipos);
  1218.  
  1219.         padlen = width                  /* Minimum field width. */
  1220.             - ipos                      /* Number of integer digits. */
  1221.             - epos                      /* Number of exponent characters. */
  1222.             - precision                 /* Number of fractional digits. */
  1223.             - separators                /* Number of group separators. */
  1224.             - (emitpoint ? 1 : 0)       /* Will we print a decimal point? */
  1225.             - ((sign != 0) ? 1 : 0);    /* Will we print a sign character? */
  1226.  
  1227.         if (padlen < 0)
  1228.                 padlen = 0;
  1229.  
  1230.         /*
  1231.          * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
  1232.          * ignored." (7.19.6.1, 6)
  1233.          */
  1234.         if (flags & PRINT_F_MINUS)      /* Left justifty. */
  1235.                 padlen = -padlen;
  1236.         else if (flags & PRINT_F_ZERO && padlen > 0) {
  1237.                 if (sign != 0) {        /* Sign. */
  1238.                         OUTCHAR(str, *len, size, sign);
  1239.                         sign = 0;
  1240.                 }
  1241.                 while (padlen > 0) {    /* Leading zeros. */
  1242.                         OUTCHAR(str, *len, size, '0');
  1243.                         padlen--;
  1244.                 }
  1245.         }
  1246.         while (padlen > 0) {    /* Leading spaces. */
  1247.                 OUTCHAR(str, *len, size, ' ');
  1248.                 padlen--;
  1249.         }
  1250.         if (sign != 0)  /* Sign. */
  1251.                 OUTCHAR(str, *len, size, sign);
  1252.         while (ipos > 0) {      /* Integer part. */
  1253.                 ipos--;
  1254.                 OUTCHAR(str, *len, size, iconvert[ipos]);
  1255.                 if (separators > 0 && ipos > 0 && ipos % 3 == 0)
  1256.                         printsep(str, len, size);
  1257.         }
  1258.         if (emitpoint) {        /* Decimal point. */
  1259. #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
  1260.                 if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
  1261.                         OUTCHAR(str, *len, size, *lc->decimal_point);
  1262.                 else    /* We'll always print some decimal point character. */
  1263. #endif  /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
  1264.                         OUTCHAR(str, *len, size, '.');
  1265.         }
  1266.         while (leadfraczeros > 0) {     /* Leading fractional part zeros. */
  1267.                 OUTCHAR(str, *len, size, '0');
  1268.                 leadfraczeros--;
  1269.         }
  1270.         while (fpos > omitcount) {      /* The remaining fractional part. */
  1271.                 fpos--;
  1272.                 OUTCHAR(str, *len, size, fconvert[fpos]);
  1273.         }
  1274.         while (epos > 0) {      /* Exponent. */
  1275.                 epos--;
  1276.                 OUTCHAR(str, *len, size, econvert[epos]);
  1277.         }
  1278.         while (padlen < 0) {    /* Trailing spaces. */
  1279.                 OUTCHAR(str, *len, size, ' ');
  1280.                 padlen++;
  1281.         }
  1282. }
  1283.  
  1284. static void
  1285. printsep(char *str, size_t *len, size_t size)
  1286. {
  1287. #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
  1288.         struct lconv *lc = localeconv();
  1289.         int i;
  1290.  
  1291.         if (lc->thousands_sep != NULL)
  1292.                 for (i = 0; lc->thousands_sep[i] != '\0'; i++)
  1293.                         OUTCHAR(str, *len, size, lc->thousands_sep[i]);
  1294.         else
  1295. #endif  /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
  1296.                 OUTCHAR(str, *len, size, ',');
  1297. }
  1298.  
  1299. static int
  1300. getnumsep(int digits)
  1301. {
  1302.         int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
  1303. #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
  1304.         int strln;
  1305.         struct lconv *lc = localeconv();
  1306.  
  1307.         /* We support an arbitrary separator length (including zero). */
  1308.         if (lc->thousands_sep != NULL) {
  1309.                 for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
  1310.                         continue;
  1311.                 separators *= strln;
  1312.         }
  1313. #endif  /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
  1314.         return separators;
  1315. }
  1316.  
  1317. static int
  1318. getexponent(LDOUBLE value)
  1319. {
  1320.         LDOUBLE tmp = (value >= 0.0) ? value : -value;
  1321.         int exponent = 0;
  1322.  
  1323.         /*
  1324.          * We check for 99 > exponent > -99 in order to work around possible
  1325.          * endless loops which could happen (at least) in the second loop (at
  1326.          * least) if we're called with an infinite value.  However, we checked
  1327.          * for infinity before calling this function using our ISINF() macro, so
  1328.          * this might be somewhat paranoid.
  1329.          */
  1330.         while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
  1331.                 tmp *= 10;
  1332.         while (tmp >= 10.0 && ++exponent < 99)
  1333.                 tmp /= 10;
  1334.  
  1335.         return exponent;
  1336. }
  1337.  
  1338. static int
  1339. convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
  1340. {
  1341.         const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
  1342.         size_t pos = 0;
  1343.  
  1344.         /* We return an unterminated buffer with the digits in reverse order. */
  1345.         do {
  1346.                 buf[pos++] = digits[value % base];
  1347.                 value /= base;
  1348.         } while (value != 0 && pos < size);
  1349.  
  1350.         return (int)pos;
  1351. }
  1352.  
  1353. static UINTMAX_T
  1354. cast(LDOUBLE value)
  1355. {
  1356.         UINTMAX_T result;
  1357.  
  1358.         /*
  1359.          * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
  1360.          * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
  1361.          * it may be increased to the nearest higher representable value for the
  1362.          * comparison (cf. C99: 6.3.1.4, 2).  It might then equal the LDOUBLE
  1363.          * value although converting the latter to UINTMAX_T would overflow.
  1364.          */
  1365.         if (value >= UINTMAX_MAX)
  1366.                 return UINTMAX_MAX;
  1367.  
  1368.         result = (UINTMAX_T)value;
  1369.         /*
  1370.          * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
  1371.          * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
  1372.          * the standard).  Sigh.
  1373.          */
  1374.         return (result <= value) ? result : result - 1;
  1375. }
  1376.  
  1377. static UINTMAX_T
  1378. myround(LDOUBLE value)
  1379. {
  1380.         UINTMAX_T intpart = cast(value);
  1381.  
  1382.         return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
  1383. }
  1384.  
  1385. static LDOUBLE
  1386. mypow10(int exponent)
  1387. {
  1388.         LDOUBLE result = 1;
  1389.  
  1390.         while (exponent > 0) {
  1391.                 result *= 10;
  1392.                 exponent--;
  1393.         }
  1394.         while (exponent < 0) {
  1395.                 result /= 10;
  1396.                 exponent++;
  1397.         }
  1398.         return result;
  1399. }
  1400. #endif  /* !HAVE_VSNPRINTF */
  1401.  
  1402. #if !HAVE_VASPRINTF
  1403. #if NEED_MYMEMCPY
  1404. void *
  1405. mymemcpy(void *dst, void *src, size_t len)
  1406. {
  1407.         const char *from = src;
  1408.         char *to = dst;
  1409.  
  1410.         /* No need for optimization, we use this only to replace va_copy(3). */
  1411.         while (len-- > 0)
  1412.                 *to++ = *from++;
  1413.         return dst;
  1414. }
  1415. #endif  /* NEED_MYMEMCPY */
  1416.  
  1417. int
  1418. util_vasprintf(char **ret, const char *format, va_list ap)
  1419. {
  1420.         size_t size;
  1421.         int len;
  1422.         va_list aq;
  1423.  
  1424.         VA_COPY(aq, ap);
  1425.         len = vsnprintf(NULL, 0, format, aq);
  1426.         VA_END_COPY(aq);
  1427.         if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
  1428.                 return -1;
  1429.         return vsnprintf(*ret, size, format, ap);
  1430. }
  1431. #endif  /* !HAVE_VASPRINTF */
  1432.  
  1433. #if !HAVE_SNPRINTF
  1434. #if HAVE_STDARG_H
  1435. int
  1436. util_snprintf(char *str, size_t size, const char *format, ...)
  1437. #else
  1438. int
  1439. util_snprintf(va_alist) va_dcl
  1440. #endif  /* HAVE_STDARG_H */
  1441. {
  1442. #if !HAVE_STDARG_H
  1443.         char *str;
  1444.         size_t size;
  1445.         char *format;
  1446. #endif  /* HAVE_STDARG_H */
  1447.         va_list ap;
  1448.         int len;
  1449.  
  1450.         VA_START(ap, format);
  1451.         VA_SHIFT(ap, str, char *);
  1452.         VA_SHIFT(ap, size, size_t);
  1453.         VA_SHIFT(ap, format, const char *);
  1454.         len = vsnprintf(str, size, format, ap);
  1455.         va_end(ap);
  1456.         return len;
  1457. }
  1458. #endif  /* !HAVE_SNPRINTF */
  1459.  
  1460. #if !HAVE_ASPRINTF
  1461. #if HAVE_STDARG_H
  1462. int
  1463. util_asprintf(char **ret, const char *format, ...)
  1464. #else
  1465. int
  1466. util_asprintf(va_alist) va_dcl
  1467. #endif  /* HAVE_STDARG_H */
  1468. {
  1469. #if !HAVE_STDARG_H
  1470.         char **ret;
  1471.         char *format;
  1472. #endif  /* HAVE_STDARG_H */
  1473.         va_list ap;
  1474.         int len;
  1475.  
  1476.         VA_START(ap, format);
  1477.         VA_SHIFT(ap, ret, char **);
  1478.         VA_SHIFT(ap, format, const char *);
  1479.         len = vasprintf(ret, format, ap);
  1480.         va_end(ap);
  1481.         return len;
  1482. }
  1483. #endif  /* !HAVE_ASPRINTF */
  1484. #else   /* Dummy declaration to avoid empty translation unit warnings. */
  1485. int main(void);
  1486. #endif  /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */
  1487.  
  1488.  
  1489. /* vim: set joinspaces textwidth=80: */
  1490.