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