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