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