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