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