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