Imported Upstream version 1.7.6p1
[debian/sudo] / snprintf.c
1 /*
2  * Copyright (c) 1999-2005, 2008, 2010
3  *      Todd C. Miller <Todd.Miller@courtesan.com>
4  * Copyright (c) 1990, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Chris Torek.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * From: @(#)vfprintf.c 8.1 (Berkeley) 6/4/93
35  */
36
37 /*
38  * v?snprintf/v?asprintf based on 4.4BSD stdio.
39  * NOTE: does not support floating point.
40  */
41
42 #include <config.h>
43
44 #include <sys/types.h>
45 #include <sys/param.h>
46
47 #include <stdio.h>
48 #ifdef STDC_HEADERS
49 # include <stdlib.h>
50 # include <stddef.h>
51 #else
52 # ifdef HAVE_STDLIB_H
53 #  include <stdlib.h>
54 # endif
55 #endif /* STDC_HEADERS */
56 #ifdef HAVE_STDINT_H
57 # include <stdint.h>
58 #endif
59 #ifdef HAVE_STRING_H
60 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
61 #  include <memory.h>
62 # endif
63 # include <string.h>
64 #endif /* HAVE_STRING_H */
65 #ifdef HAVE_STRINGS_H
66 # include <strings.h>
67 #endif /* HAVE_STRINGS_H */
68 #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
69 # include <malloc.h>
70 #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
71 #include <limits.h>
72
73 #ifdef __STDC__
74 # include <stdarg.h>
75 #else
76 # include <varargs.h>
77 #endif
78
79 #include "missing.h"
80
81 static int xxxprintf     __P((char **, size_t, int, const char *, va_list));
82
83 /*
84  * Some systems may not have these defined in <limits.h>
85  */
86 #ifndef ULONG_MAX
87 # define ULONG_MAX      ((unsigned long)-1)
88 #endif
89 #ifndef LONG_MAX
90 # define LONG_MAX       (ULONG_MAX / 2)
91 #endif
92 #ifdef HAVE_LONG_LONG_INT
93 # ifndef ULLONG_MAX
94 #  ifdef UQUAD_MAX
95 #   define ULLONG_MAX   UQUAD_MAX
96 #  else
97 #   define ULLONG_MAX   ((unsigned long long)-1)
98 #  endif
99 # endif
100 # ifndef LLONG_MAX
101 #  ifdef QUAD_MAX
102 #   define LLONG_MAX    QUAD_MAX
103 #  else
104 #   define LLONG_MAX    (ULLONG_MAX / 2)
105 #  endif
106 # endif
107 #endif /* HAVE_LONG_LONG_INT */
108
109 /*
110  * Macros for converting digits to letters and vice versa
111  */
112 #define to_digit(c)     ((c) - '0')
113 #define is_digit(c)     ((unsigned int)to_digit(c) <= 9)
114 #define to_char(n)      ((n) + '0')
115
116 /*
117  * Flags used during conversion.
118  */
119 #define ALT             0x001           /* alternate form */
120 #define HEXPREFIX       0x002           /* add 0x or 0X prefix */
121 #define LADJUST         0x004           /* left adjustment */
122 #define LONGDBL         0x008           /* long double; unimplemented */
123 #define LONGINT         0x010           /* long integer */
124 #define QUADINT         0x020           /* quad integer */
125 #define SHORTINT        0x040           /* short integer */
126 #define ZEROPAD         0x080           /* zero (as opposed to blank) pad */
127
128 #define BUF             68
129
130 #ifndef HAVE_MEMCHR
131 void *
132 memchr(s, c, n)
133         const void *s;
134         unsigned char c;
135         size_t n;
136 {
137         if (n != 0) {
138                 const unsigned char *p = s;
139
140                 do {
141                         if (*p++ == c)
142                                 return (void *)(p - 1);
143                 } while (--n != 0);
144         }
145         return NULL;
146 }
147 #endif /* !HAVE_MEMCHR */
148
149 /*
150  * Convert an unsigned long to ASCII for printf purposes, returning
151  * a pointer to the first character of the string representation.
152  * Octal numbers can be forced to have a leading zero; hex numbers
153  * use the given digits.
154  */
155 static char *
156 __ultoa(val, endp, base, octzero, xdigs)
157         unsigned long val;
158         char *endp;
159         int base, octzero;
160         char *xdigs;
161 {
162         char *cp = endp;
163         long sval;
164
165         /*
166          * Handle the three cases separately, in the hope of getting
167          * better/faster code.
168          */
169         switch (base) {
170         case 10:
171                 if (val < 10) { /* many numbers are 1 digit */
172                         *--cp = to_char(val);
173                         return cp;
174                 }
175                 /*
176                  * On many machines, unsigned arithmetic is harder than
177                  * signed arithmetic, so we do at most one unsigned mod and
178                  * divide; this is sufficient to reduce the range of
179                  * the incoming value to where signed arithmetic works.
180                  */
181                 if (val > LONG_MAX) {
182                         *--cp = to_char(val % 10);
183                         sval = val / 10;
184                 } else
185                         sval = val;
186                 do {
187                         *--cp = to_char(sval % 10);
188                         sval /= 10;
189                 } while (sval != 0);
190                 break;
191
192         case 8:
193                 do {
194                         *--cp = to_char(val & 7);
195                         val >>= 3;
196                 } while (val);
197                 if (octzero && *cp != '0')
198                         *--cp = '0';
199                 break;
200
201         case 16:
202                 do {
203                         *--cp = xdigs[val & 15];
204                         val >>= 4;
205                 } while (val);
206                 break;
207
208         default:                        /* oops */
209                 abort();
210         }
211         return cp;
212 }
213
214 /* Identical to __ultoa, but for quads. */
215 #ifdef HAVE_LONG_LONG_INT
216 # if SIZEOF_LONG_INT == 8
217 #  define __uqtoa(v, e, b, o, x) __ultoa((unsigned long)(v), (e), (b), (o), (x))
218 # else
219 static char *
220 __uqtoa(val, endp, base, octzero, xdigs)
221         unsigned long long val;
222         char *endp;
223         int base, octzero;
224         char *xdigs;
225 {
226         char *cp = endp;
227         long long sval;
228
229         /* quick test for small values; __ultoa is typically much faster */
230         /* (perhaps instead we should run until small, then call __ultoa?) */
231         if (val <= (unsigned long long)ULONG_MAX)
232                 return __ultoa((unsigned long)val, endp, base, octzero, xdigs);
233         switch (base) {
234         case 10:
235                 if (val < 10) {
236                         *--cp = to_char(val % 10);
237                         return cp;
238                 }
239                 if (val > LLONG_MAX) {
240                         *--cp = to_char(val % 10);
241                         sval = val / 10;
242                 } else
243                         sval = val;
244                 do {
245                         *--cp = to_char(sval % 10);
246                         sval /= 10;
247                 } while (sval != 0);
248                 break;
249
250         case 8:
251                 do {
252                         *--cp = to_char(val & 7);
253                         val >>= 3;
254                 } while (val);
255                 if (octzero && *cp != '0')
256                         *--cp = '0';
257                 break;
258
259         case 16:
260                 do {
261                         *--cp = xdigs[val & 15];
262                         val >>= 4;
263                 } while (val);
264                 break;
265
266         default:                        /* oops */
267                 abort();
268         }
269         return cp;
270 }
271 # endif /* !SIZEOF_LONG_INT */
272 #endif /* HAVE_LONG_LONG_INT */
273
274 /*
275  * Actual printf innards.
276  */
277 static int
278 xxxprintf(strp, strsize, alloc, fmt0, ap)
279         char **strp;
280         size_t strsize;
281         int alloc;
282         const char *fmt0;
283         va_list ap;
284 {
285         char *fmt;              /* format string */
286         int ch;                 /* character from fmt */
287         int n;                  /* handy integer (short term usage) */
288         char *cp;               /* handy char pointer (short term usage) */
289         int flags;              /* flags as above */
290         int ret;                /* return value accumulator */
291         int width;              /* width from format (%8d), or 0 */
292         int prec;               /* precision from format (%.3d), or -1 */
293         char sign;              /* sign prefix (' ', '+', '-', or \0) */
294         unsigned long ulval = 0; /* integer arguments %[diouxX] */
295 #ifdef HAVE_LONG_LONG_INT
296         unsigned long long uqval = 0; /* %q (quad) integers */
297 #endif
298         int base;               /* base for [diouxX] conversion */
299         int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
300         int fieldsz;            /* field size expanded by sign, etc */
301         int realsz;             /* field size expanded by dprec */
302         int size;               /* size of converted field or string */
303         char *xdigs = "";       /* digits for [xX] conversion */
304         char buf[BUF];          /* space for %c, %[diouxX], %[eEfgG] */
305         char ox[2];             /* space for 0x hex-prefix */
306         char *str;              /* pointer to string to fill */
307         char *estr;             /* pointer to last char in str */
308
309         /*
310          * Choose PADSIZE to trade efficiency vs. size.  If larger printf
311          * fields occur frequently, increase PADSIZE and make the initialisers
312          * below longer.
313          */
314 #define PADSIZE 16              /* pad chunk size */
315         static char blanks[PADSIZE] =
316          {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
317         static char zeroes[PADSIZE] =
318          {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
319
320         /* Print chars to "str", (allocate as needed if alloc is set). */
321 #define PRINT(ptr, len) do { \
322         const char *p = ptr; \
323         const char *endp = ptr + len; \
324         while (p < endp && (str < estr || alloc)) { \
325                 if (alloc && str >= estr) { \
326                         char *t; \
327                         strsize = (strsize << 1) + 1; \
328                         if (!(t = (char *)realloc(*strp, strsize))) { \
329                                 free(str); \
330                                 *strp = NULL; \
331                                 ret = -1; \
332                                 goto done; \
333                         } \
334                         str = t + (str - *strp); \
335                         estr = t + strsize - 1; \
336                         *strp = t; \
337                 } \
338                 *str++ = *p++; \
339         } \
340 } while (0)
341
342         /* BEWARE, PAD uses `n'. */
343 #define PAD(plen, pstr) do { \
344         if ((n = (plen)) > 0) { \
345                 while (n > PADSIZE) { \
346                         PRINT(pstr, PADSIZE); \
347                         n -= PADSIZE; \
348                 } \
349                 PRINT(pstr, n); \
350         } \
351 } while (0)
352
353         /*
354          * To extend shorts properly, we need both signed and unsigned
355          * argument extraction methods.
356          */
357 #define SARG() \
358         (flags&LONGINT ? va_arg(ap, long) : \
359             flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
360             (long)va_arg(ap, int))
361 #define UARG() \
362         (flags&LONGINT ? va_arg(ap, unsigned long) : \
363             flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \
364             (unsigned long)va_arg(ap, unsigned int))
365
366         fmt = (char *)fmt0;
367         ret = 0;
368
369         if (alloc) {
370                 strsize = 128;
371                 *strp = str = (char *)malloc(strsize);
372                 if (str == NULL) {
373                         ret = -1;
374                         goto done;
375                 }
376                 estr = str + 127;
377         } else {
378                 str = *strp;
379                 if (strsize)
380                         estr = str + strsize - 1;
381                 else
382                         estr = NULL;
383         }
384
385         /*
386          * Scan the format for conversions (`%' character).
387          */
388         for (;;) {
389                 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
390                         /* void */;
391                 if ((n = fmt - cp) != 0) {
392                         PRINT(cp, n);
393                         ret += n;
394                 }
395                 if (ch == '\0')
396                         goto done;
397                 fmt++;          /* skip over '%' */
398
399                 flags = 0;
400                 dprec = 0;
401                 width = 0;
402                 prec = -1;
403                 sign = '\0';
404
405 rflag:          ch = *fmt++;
406 reswitch:       switch (ch) {
407                 case ' ':
408                         /*
409                          * ``If the space and + flags both appear, the space
410                          * flag will be ignored.''
411                          *      -- ANSI X3J11
412                          */
413                         if (!sign)
414                                 sign = ' ';
415                         goto rflag;
416                 case '#':
417                         flags |= ALT;
418                         goto rflag;
419                 case '*':
420                         /*
421                          * ``A negative field width argument is taken as a
422                          * - flag followed by a positive field width.''
423                          *      -- ANSI X3J11
424                          * They don't exclude field widths read from args.
425                          */
426                         if ((width = va_arg(ap, int)) >= 0)
427                                 goto rflag;
428                         width = -width;
429                         /* FALLTHROUGH */
430                 case '-':
431                         flags |= LADJUST;
432                         goto rflag;
433                 case '+':
434                         sign = '+';
435                         goto rflag;
436                 case '.':
437                         if ((ch = *fmt++) == '*') {
438                                 n = va_arg(ap, int);
439                                 prec = n < 0 ? -1 : n;
440                                 goto rflag;
441                         }
442                         n = 0;
443                         while (is_digit(ch)) {
444                                 n = 10 * n + to_digit(ch);
445                                 ch = *fmt++;
446                         }
447                         prec = n < 0 ? -1 : n;
448                         goto reswitch;
449                 case '0':
450                         /*
451                          * ``Note that 0 is taken as a flag, not as the
452                          * beginning of a field width.''
453                          *      -- ANSI X3J11
454                          */
455                         flags |= ZEROPAD;
456                         goto rflag;
457                 case '1': case '2': case '3': case '4':
458                 case '5': case '6': case '7': case '8': case '9':
459                         n = 0;
460                         do {
461                                 n = 10 * n + to_digit(ch);
462                                 ch = *fmt++;
463                         } while (is_digit(ch));
464                         width = n;
465                         goto reswitch;
466                 case 'h':
467                         flags |= SHORTINT;
468                         goto rflag;
469                 case 'l':
470                         flags |= LONGINT;
471                         goto rflag;
472 #ifdef HAVE_LONG_LONG_INT
473                 case 'q':
474                         flags |= QUADINT;
475                         goto rflag;
476 #endif /* HAVE_LONG_LONG_INT */
477                 case 'c':
478                         *(cp = buf) = va_arg(ap, int);
479                         size = 1;
480                         sign = '\0';
481                         break;
482                 case 'D':
483                         flags |= LONGINT;
484                         /*FALLTHROUGH*/
485                 case 'd':
486                 case 'i':
487 #ifdef HAVE_LONG_LONG_INT
488                         if (flags & QUADINT) {
489                                 uqval = va_arg(ap, long long);
490                                 if ((long long)uqval < 0) {
491                                         uqval = -uqval;
492                                         sign = '-';
493                                 }
494                         }
495                         else
496 #endif /* HAVE_LONG_LONG_INT */
497                         {
498                                 ulval = SARG();
499                                 if ((long)ulval < 0) {
500                                         ulval = -ulval;
501                                         sign = '-';
502                                 }
503                         }
504                         base = 10;
505                         goto number;
506                 case 'n':
507 #ifdef HAVE_LONG_LONG_INT
508                         if (flags & QUADINT)
509                                 *va_arg(ap, long long *) = ret;
510                         else
511 #endif /* HAVE_LONG_LONG_INT */
512                         if (flags & LONGINT)
513                                 *va_arg(ap, long *) = ret;
514                         else if (flags & SHORTINT)
515                                 *va_arg(ap, short *) = ret;
516                         else
517                                 *va_arg(ap, int *) = ret;
518                         continue;       /* no output */
519                 case 'O':
520                         flags |= LONGINT;
521                         /*FALLTHROUGH*/
522                 case 'o':
523 #ifdef HAVE_LONG_LONG_INT
524                         if (flags & QUADINT)
525                                 uqval = va_arg(ap, unsigned long long);
526                         else
527 #endif /* HAVE_LONG_LONG_INT */
528                                 ulval = UARG();
529                         base = 8;
530                         goto nosign;
531                 case 'p':
532                         /*
533                          * ``The argument shall be a pointer to void.  The
534                          * value of the pointer is converted to a sequence
535                          * of printable characters, in an implementation-
536                          * defined manner.''
537                          *      -- ANSI X3J11
538                          */
539                         ulval = (unsigned long)va_arg(ap, void *);
540                         base = 16;
541                         xdigs = "0123456789abcdef";
542                         flags = (flags & ~QUADINT) | HEXPREFIX;
543                         ch = 'x';
544                         goto nosign;
545                 case 's':
546                         if ((cp = va_arg(ap, char *)) == NULL)
547                                 cp = "(null)";
548                         if (prec >= 0) {
549                                 /*
550                                  * can't use strlen; can only look for the
551                                  * NUL in the first `prec' characters, and
552                                  * strlen() will go further.
553                                  */
554                                 char *p = memchr(cp, 0, prec);
555
556                                 if (p != NULL) {
557                                         size = p - cp;
558                                         if (size > prec)
559                                                 size = prec;
560                                 } else
561                                         size = prec;
562                         } else
563                                 size = strlen(cp);
564                         sign = '\0';
565                         break;
566                 case 'U':
567                         flags |= LONGINT;
568                         /*FALLTHROUGH*/
569                 case 'u':
570 #ifdef HAVE_LONG_LONG_INT
571                         if (flags & QUADINT)
572                                 uqval = va_arg(ap, unsigned long long);
573                         else
574 #endif /* HAVE_LONG_LONG_INT */
575                                 ulval = UARG();
576                         base = 10;
577                         goto nosign;
578                 case 'X':
579                         xdigs = "0123456789ABCDEF";
580                         goto hex;
581                 case 'x':
582                         xdigs = "0123456789abcdef";
583 hex:
584 #ifdef HAVE_LONG_LONG_INT
585                         if (flags & QUADINT)
586                                 uqval = va_arg(ap, unsigned long long);
587                         else
588 #endif /* HAVE_LONG_LONG_INT */
589                                 ulval = UARG();
590                         base = 16;
591                         /* leading 0x/X only if non-zero */
592                         if (flags & ALT &&
593 #ifdef HAVE_LONG_LONG_INT
594                             (flags & QUADINT ? uqval != 0 : ulval != 0))
595 #else
596                             ulval != 0)
597 #endif /* HAVE_LONG_LONG_INT */
598                                 flags |= HEXPREFIX;
599
600                         /* unsigned conversions */
601 nosign:                 sign = '\0';
602                         /*
603                          * ``... diouXx conversions ... if a precision is
604                          * specified, the 0 flag will be ignored.''
605                          *      -- ANSI X3J11
606                          */
607 number:                 if ((dprec = prec) >= 0)
608                                 flags &= ~ZEROPAD;
609
610                         /*
611                          * ``The result of converting a zero value with an
612                          * explicit precision of zero is no characters.''
613                          *      -- ANSI X3J11
614                          */
615                         cp = buf + BUF;
616 #ifdef HAVE_LONG_LONG_INT
617                         if (flags & QUADINT) {
618                                 if (uqval != 0 || prec != 0)
619                                         cp = __uqtoa(uqval, cp, base,
620                                             flags & ALT, xdigs);
621                         }
622                         else
623 #endif /* HAVE_LONG_LONG_INT */
624                         {
625                                 if (ulval != 0 || prec != 0)
626                                         cp = __ultoa(ulval, cp, base,
627                                             flags & ALT, xdigs);
628                         }
629                         size = buf + BUF - cp;
630                         break;
631                 default:        /* "%?" prints ?, unless ? is NUL */
632                         if (ch == '\0')
633                                 goto done;
634                         /* pretend it was %c with argument ch */
635                         cp = buf;
636                         *cp = ch;
637                         size = 1;
638                         sign = '\0';
639                         break;
640                 }
641
642                 /*
643                  * All reasonable formats wind up here.  At this point, `cp'
644                  * points to a string which (if not flags&LADJUST) should be
645                  * padded out to `width' places.  If flags&ZEROPAD, it should
646                  * first be prefixed by any sign or other prefix; otherwise,
647                  * it should be blank padded before the prefix is emitted.
648                  * After any left-hand padding and prefixing, emit zeroes
649                  * required by a decimal [diouxX] precision, then print the
650                  * string proper, then emit zeroes required by any leftover
651                  * floating precision; finally, if LADJUST, pad with blanks.
652                  *
653                  * Compute actual size, so we know how much to pad.
654                  * fieldsz excludes decimal prec; realsz includes it.
655                  */
656                 fieldsz = size;
657                 if (sign)
658                         fieldsz++;
659                 else if (flags & HEXPREFIX)
660                         fieldsz += 2;
661                 realsz = dprec > fieldsz ? dprec : fieldsz;
662
663                 /* right-adjusting blank padding */
664                 if ((flags & (LADJUST|ZEROPAD)) == 0)
665                         PAD(width - realsz, blanks);
666
667                 /* prefix */
668                 if (sign) {
669                         PRINT(&sign, 1);
670                 } else if (flags & HEXPREFIX) {
671                         ox[0] = '0';
672                         ox[1] = ch;
673                         PRINT(ox, 2);
674                 }
675
676                 /* right-adjusting zero padding */
677                 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
678                         PAD(width - realsz, zeroes);
679
680                 /* leading zeroes from decimal precision */
681                 PAD(dprec - fieldsz, zeroes);
682
683                 /* the string or number proper */
684                 PRINT(cp, size);
685
686                 /* left-adjusting padding (always blank) */
687                 if (flags & LADJUST)
688                         PAD(width - realsz, blanks);
689
690                 /* finally, adjust ret */
691                 ret += width > realsz ? width : realsz;
692         }
693 done:
694         if (strsize)
695                 *str = '\0';
696         return ret;
697         /* NOTREACHED */
698 }
699
700 #ifndef HAVE_VSNPRINTF
701 int
702 vsnprintf(str, n, fmt, ap)
703         char *str;
704         size_t n;
705         const char *fmt;
706         va_list ap;
707 {
708
709         return xxxprintf(&str, n, 0, fmt, ap);
710 }
711 #endif /* HAVE_VSNPRINTF */
712
713 #ifndef HAVE_SNPRINTF
714 int
715 #ifdef __STDC__
716 snprintf(char *str, size_t n, char const *fmt, ...)
717 #else
718 snprintf(str, n, fmt, va_alist)
719         char *str;
720         size_t n;
721         char const *fmt;
722         va_dcl
723 #endif
724 {
725         int ret;
726         va_list ap;
727
728 #ifdef __STDC__
729         va_start(ap, fmt);
730 #else
731         va_start(ap);
732 #endif
733         ret = xxxprintf(&str, n, 0, fmt, ap);
734         va_end(ap);
735         return ret;
736 }
737 #endif /* HAVE_SNPRINTF */
738
739 #ifndef HAVE_VASPRINTF
740 int
741 vasprintf(str, fmt, ap)
742         char **str;
743         const char *fmt;
744         va_list ap;
745 {
746
747         return xxxprintf(str, 0, 1, fmt, ap);
748 }
749 #endif /* HAVE_VASPRINTF */
750
751 #ifndef HAVE_ASPRINTF
752 int
753 #ifdef __STDC__
754 asprintf(char **str, char const *fmt, ...)
755 #else
756 asprintf(str, fmt, va_alist)
757         char **str;
758         char const *fmt;
759         va_dcl
760 #endif
761 {
762         int ret;
763         va_list ap;
764
765 #ifdef __STDC__
766         va_start(ap, fmt);
767 #else
768         va_start(ap);
769 #endif
770         ret = xxxprintf(str, 0, 1, fmt, ap);
771         va_end(ap);
772         return ret;
773 }
774 #endif /* HAVE_ASPRINTF */