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