Annotation of embedaddon/sudo/compat/snprintf.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 1999-2005, 2008, 2010-2011
                      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: #include <stdarg.h>
                     73: 
                     74: #include "missing.h"
                     75: 
                     76: static int xxxprintf(char **, size_t, int, const char *, va_list);
                     77: 
                     78: /*
                     79:  * Some systems may not have these defined in <limits.h>
                     80:  */
                     81: #ifndef ULONG_MAX
                     82: # define ULONG_MAX     ((unsigned long)-1)
                     83: #endif
                     84: #ifndef LONG_MAX
                     85: # define LONG_MAX      (ULONG_MAX / 2)
                     86: #endif
                     87: #ifdef HAVE_LONG_LONG_INT
                     88: # ifndef ULLONG_MAX
                     89: #  ifdef UQUAD_MAX
                     90: #   define ULLONG_MAX  UQUAD_MAX
                     91: #  else
                     92: #   define ULLONG_MAX  ((unsigned long long)-1)
                     93: #  endif
                     94: # endif
                     95: # ifndef LLONG_MAX
                     96: #  ifdef QUAD_MAX
                     97: #   define LLONG_MAX   QUAD_MAX
                     98: #  else
                     99: #   define LLONG_MAX   (ULLONG_MAX / 2)
                    100: #  endif
                    101: # endif
                    102: #endif /* HAVE_LONG_LONG_INT */
                    103: 
                    104: /*
                    105:  * Macros for converting digits to letters and vice versa
                    106:  */
                    107: #define        to_digit(c)     ((c) - '0')
                    108: #define is_digit(c)    ((unsigned int)to_digit(c) <= 9)
                    109: #define        to_char(n)      ((n) + '0')
                    110: 
                    111: /*
                    112:  * Flags used during conversion.
                    113:  */
                    114: #define        ALT             0x001           /* alternate form */
                    115: #define        HEXPREFIX       0x002           /* add 0x or 0X prefix */
                    116: #define        LADJUST         0x004           /* left adjustment */
                    117: #define        LONGDBL         0x008           /* long double; unimplemented */
                    118: #define        LONGINT         0x010           /* long integer */
                    119: #define        QUADINT         0x020           /* quad integer */
                    120: #define        SHORTINT        0x040           /* short integer */
                    121: #define        ZEROPAD         0x080           /* zero (as opposed to blank) pad */
                    122: 
                    123: #define BUF            68
                    124: 
                    125: /*
                    126:  * Convert an unsigned long to ASCII for printf purposes, returning
                    127:  * a pointer to the first character of the string representation.
                    128:  * Octal numbers can be forced to have a leading zero; hex numbers
                    129:  * use the given digits.
                    130:  */
                    131: static char *
                    132: __ultoa(unsigned long val, char *endp, int base, int octzero, char *xdigs)
                    133: {
                    134:        char *cp = endp;
                    135:        long sval;
                    136: 
                    137:        /*
                    138:         * Handle the three cases separately, in the hope of getting
                    139:         * better/faster code.
                    140:         */
                    141:        switch (base) {
                    142:        case 10:
                    143:                if (val < 10) { /* many numbers are 1 digit */
                    144:                        *--cp = to_char(val);
                    145:                        return cp;
                    146:                }
                    147:                /*
                    148:                 * On many machines, unsigned arithmetic is harder than
                    149:                 * signed arithmetic, so we do at most one unsigned mod and
                    150:                 * divide; this is sufficient to reduce the range of
                    151:                 * the incoming value to where signed arithmetic works.
                    152:                 */
                    153:                if (val > LONG_MAX) {
                    154:                        *--cp = to_char(val % 10);
                    155:                        sval = val / 10;
                    156:                } else
                    157:                        sval = val;
                    158:                do {
                    159:                        *--cp = to_char(sval % 10);
                    160:                        sval /= 10;
                    161:                } while (sval != 0);
                    162:                break;
                    163: 
                    164:        case 8:
                    165:                do {
                    166:                        *--cp = to_char(val & 7);
                    167:                        val >>= 3;
                    168:                } while (val);
                    169:                if (octzero && *cp != '0')
                    170:                        *--cp = '0';
                    171:                break;
                    172: 
                    173:        case 16:
                    174:                do {
                    175:                        *--cp = xdigs[val & 15];
                    176:                        val >>= 4;
                    177:                } while (val);
                    178:                break;
                    179: 
                    180:        default:                        /* oops */
                    181:                abort();
                    182:        }
                    183:        return cp;
                    184: }
                    185: 
                    186: /* Identical to __ultoa, but for quads. */
                    187: #ifdef HAVE_LONG_LONG_INT
                    188: # if SIZEOF_LONG_INT == 8
                    189: #  define __uqtoa(v, e, b, o, x) __ultoa((unsigned long)(v), (e), (b), (o), (x))
                    190: # else
                    191: static char *
                    192: __uqtoa(unsigned long long val, char *endp, int base, int octzero, char *xdigs)
                    193: {
                    194:        char *cp = endp;
                    195:        long long sval;
                    196: 
                    197:        /* quick test for small values; __ultoa is typically much faster */
                    198:        /* (perhaps instead we should run until small, then call __ultoa?) */
                    199:        if (val <= (unsigned long long)ULONG_MAX)
                    200:                return __ultoa((unsigned long)val, endp, base, octzero, xdigs);
                    201:        switch (base) {
                    202:        case 10:
                    203:                if (val < 10) {
                    204:                        *--cp = to_char(val % 10);
                    205:                        return cp;
                    206:                }
                    207:                if (val > LLONG_MAX) {
                    208:                        *--cp = to_char(val % 10);
                    209:                        sval = val / 10;
                    210:                } else
                    211:                        sval = val;
                    212:                do {
                    213:                        *--cp = to_char(sval % 10);
                    214:                        sval /= 10;
                    215:                } while (sval != 0);
                    216:                break;
                    217: 
                    218:        case 8:
                    219:                do {
                    220:                        *--cp = to_char(val & 7);
                    221:                        val >>= 3;
                    222:                } while (val);
                    223:                if (octzero && *cp != '0')
                    224:                        *--cp = '0';
                    225:                break;
                    226: 
                    227:        case 16:
                    228:                do {
                    229:                        *--cp = xdigs[val & 15];
                    230:                        val >>= 4;
                    231:                } while (val);
                    232:                break;
                    233: 
                    234:        default:                        /* oops */
                    235:                abort();
                    236:        }
                    237:        return cp;
                    238: }
                    239: # endif /* !SIZEOF_LONG_INT */
                    240: #endif /* HAVE_LONG_LONG_INT */
                    241: 
                    242: /*
                    243:  * Actual printf innards.
                    244:  */
                    245: static int
                    246: xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap)
                    247: {
                    248:        char *fmt;              /* format string */
                    249:        int ch;                 /* character from fmt */
                    250:        int n;                  /* handy integer (short term usage) */
                    251:        char *cp;               /* handy char pointer (short term usage) */
                    252:        int flags;              /* flags as above */
                    253:        int ret;                /* return value accumulator */
                    254:        int width;              /* width from format (%8d), or 0 */
                    255:        int prec;               /* precision from format (%.3d), or -1 */
                    256:        char sign;              /* sign prefix (' ', '+', '-', or \0) */
                    257:        unsigned long ulval = 0; /* integer arguments %[diouxX] */
                    258: #ifdef HAVE_LONG_LONG_INT
                    259:        unsigned long long uqval = 0; /* %q (quad) integers */
                    260: #endif
                    261:        int base;               /* base for [diouxX] conversion */
                    262:        int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
                    263:        int fieldsz;            /* field size expanded by sign, etc */
                    264:        int realsz;             /* field size expanded by dprec */
                    265:        int size;               /* size of converted field or string */
                    266:        char *xdigs = "";       /* digits for [xX] conversion */
                    267:        char buf[BUF];          /* space for %c, %[diouxX], %[eEfgG] */
                    268:        char ox[2];             /* space for 0x hex-prefix */
                    269:        char *str;              /* pointer to string to fill */
                    270:        char *estr;             /* pointer to last char in str */
                    271: 
                    272:        /*
                    273:         * Choose PADSIZE to trade efficiency vs. size.  If larger printf
                    274:         * fields occur frequently, increase PADSIZE and make the initialisers
                    275:         * below longer.
                    276:         */
                    277: #define        PADSIZE 16              /* pad chunk size */
                    278:        static char blanks[PADSIZE] =
                    279:         {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
                    280:        static char zeroes[PADSIZE] =
                    281:         {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
                    282: 
                    283:        /* Print chars to "str", (allocate as needed if alloc is set). */
                    284: #define        PRINT(ptr, len) do { \
                    285:        const char *p = ptr; \
                    286:        const char *endp = ptr + len; \
                    287:        while (p < endp && (str < estr || alloc)) { \
                    288:                if (alloc && str >= estr) { \
                    289:                        char *t; \
                    290:                        strsize = (strsize << 1) + 1; \
                    291:                        if (!(t = (char *)realloc(*strp, strsize))) { \
                    292:                                free(str); \
                    293:                                *strp = NULL; \
                    294:                                ret = -1; \
                    295:                                goto done; \
                    296:                        } \
                    297:                        str = t + (str - *strp); \
                    298:                        estr = t + strsize - 1; \
                    299:                        *strp = t; \
                    300:                } \
                    301:                *str++ = *p++; \
                    302:        } \
                    303: } while (0)
                    304: 
                    305:        /* BEWARE, PAD uses `n'. */
                    306: #define        PAD(plen, pstr) do { \
                    307:        if ((n = (plen)) > 0) { \
                    308:                while (n > PADSIZE) { \
                    309:                        PRINT(pstr, PADSIZE); \
                    310:                        n -= PADSIZE; \
                    311:                } \
                    312:                PRINT(pstr, n); \
                    313:        } \
                    314: } while (0)
                    315: 
                    316:        /*
                    317:         * To extend shorts properly, we need both signed and unsigned
                    318:         * argument extraction methods.
                    319:         */
                    320: #define        SARG() \
                    321:        (flags&LONGINT ? va_arg(ap, long) : \
                    322:            flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
                    323:            (long)va_arg(ap, int))
                    324: #define        UARG() \
                    325:        (flags&LONGINT ? va_arg(ap, unsigned long) : \
                    326:            flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \
                    327:            (unsigned long)va_arg(ap, unsigned int))
                    328: 
                    329:        fmt = (char *)fmt0;
                    330:        ret = 0;
                    331: 
                    332:        if (alloc) {
                    333:                strsize = 128;
                    334:                *strp = str = (char *)malloc(strsize);
                    335:                if (str == NULL) {
                    336:                        ret = -1;
                    337:                        goto done;
                    338:                }
                    339:                estr = str + 127;
                    340:        } else {
                    341:                str = *strp;
                    342:                if (strsize)
                    343:                        estr = str + strsize - 1;
                    344:                else
                    345:                        estr = NULL;
                    346:        }
                    347: 
                    348:        /*
                    349:         * Scan the format for conversions (`%' character).
                    350:         */
                    351:        for (;;) {
                    352:                for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
                    353:                        /* void */;
                    354:                if ((n = fmt - cp) != 0) {
                    355:                        PRINT(cp, n);
                    356:                        ret += n;
                    357:                }
                    358:                if (ch == '\0')
                    359:                        goto done;
                    360:                fmt++;          /* skip over '%' */
                    361: 
                    362:                flags = 0;
                    363:                dprec = 0;
                    364:                width = 0;
                    365:                prec = -1;
                    366:                sign = '\0';
                    367: 
                    368: rflag:         ch = *fmt++;
                    369: reswitch:      switch (ch) {
                    370:                case ' ':
                    371:                        /*
                    372:                         * ``If the space and + flags both appear, the space
                    373:                         * flag will be ignored.''
                    374:                         *      -- ANSI X3J11
                    375:                         */
                    376:                        if (!sign)
                    377:                                sign = ' ';
                    378:                        goto rflag;
                    379:                case '#':
                    380:                        flags |= ALT;
                    381:                        goto rflag;
                    382:                case '*':
                    383:                        /*
                    384:                         * ``A negative field width argument is taken as a
                    385:                         * - flag followed by a positive field width.''
                    386:                         *      -- ANSI X3J11
                    387:                         * They don't exclude field widths read from args.
                    388:                         */
                    389:                        if ((width = va_arg(ap, int)) >= 0)
                    390:                                goto rflag;
                    391:                        width = -width;
                    392:                        /* FALLTHROUGH */
                    393:                case '-':
                    394:                        flags |= LADJUST;
                    395:                        goto rflag;
                    396:                case '+':
                    397:                        sign = '+';
                    398:                        goto rflag;
                    399:                case '.':
                    400:                        if ((ch = *fmt++) == '*') {
                    401:                                n = va_arg(ap, int);
                    402:                                prec = n < 0 ? -1 : n;
                    403:                                goto rflag;
                    404:                        }
                    405:                        n = 0;
                    406:                        while (is_digit(ch)) {
                    407:                                n = 10 * n + to_digit(ch);
                    408:                                ch = *fmt++;
                    409:                        }
                    410:                        prec = n < 0 ? -1 : n;
                    411:                        goto reswitch;
                    412:                case '0':
                    413:                        /*
                    414:                         * ``Note that 0 is taken as a flag, not as the
                    415:                         * beginning of a field width.''
                    416:                         *      -- ANSI X3J11
                    417:                         */
                    418:                        flags |= ZEROPAD;
                    419:                        goto rflag;
                    420:                case '1': case '2': case '3': case '4':
                    421:                case '5': case '6': case '7': case '8': case '9':
                    422:                        n = 0;
                    423:                        do {
                    424:                                n = 10 * n + to_digit(ch);
                    425:                                ch = *fmt++;
                    426:                        } while (is_digit(ch));
                    427:                        width = n;
                    428:                        goto reswitch;
                    429:                case 'h':
                    430:                        flags |= SHORTINT;
                    431:                        goto rflag;
                    432:                case 'l':
                    433:                        flags |= LONGINT;
                    434:                        goto rflag;
                    435: #ifdef HAVE_LONG_LONG_INT
                    436:                case 'q':
                    437:                        flags |= QUADINT;
                    438:                        goto rflag;
                    439: #endif /* HAVE_LONG_LONG_INT */
                    440:                case 'c':
                    441:                        *(cp = buf) = va_arg(ap, int);
                    442:                        size = 1;
                    443:                        sign = '\0';
                    444:                        break;
                    445:                case 'D':
                    446:                        flags |= LONGINT;
                    447:                        /*FALLTHROUGH*/
                    448:                case 'd':
                    449:                case 'i':
                    450: #ifdef HAVE_LONG_LONG_INT
                    451:                        if (flags & QUADINT) {
                    452:                                uqval = va_arg(ap, long long);
                    453:                                if ((long long)uqval < 0) {
                    454:                                        uqval = -uqval;
                    455:                                        sign = '-';
                    456:                                }
                    457:                        }
                    458:                        else
                    459: #endif /* HAVE_LONG_LONG_INT */
                    460:                        {
                    461:                                ulval = SARG();
                    462:                                if ((long)ulval < 0) {
                    463:                                        ulval = -ulval;
                    464:                                        sign = '-';
                    465:                                }
                    466:                        }
                    467:                        base = 10;
                    468:                        goto number;
                    469:                case 'n':
                    470: #ifdef HAVE_LONG_LONG_INT
                    471:                        if (flags & QUADINT)
                    472:                                *va_arg(ap, long long *) = ret;
                    473:                        else
                    474: #endif /* HAVE_LONG_LONG_INT */
                    475:                        if (flags & LONGINT)
                    476:                                *va_arg(ap, long *) = ret;
                    477:                        else if (flags & SHORTINT)
                    478:                                *va_arg(ap, short *) = ret;
                    479:                        else
                    480:                                *va_arg(ap, int *) = ret;
                    481:                        continue;       /* no output */
                    482:                case 'O':
                    483:                        flags |= LONGINT;
                    484:                        /*FALLTHROUGH*/
                    485:                case 'o':
                    486: #ifdef HAVE_LONG_LONG_INT
                    487:                        if (flags & QUADINT)
                    488:                                uqval = va_arg(ap, unsigned long long);
                    489:                        else
                    490: #endif /* HAVE_LONG_LONG_INT */
                    491:                                ulval = UARG();
                    492:                        base = 8;
                    493:                        goto nosign;
                    494:                case 'p':
                    495:                        /*
                    496:                         * ``The argument shall be a pointer to void.  The
                    497:                         * value of the pointer is converted to a sequence
                    498:                         * of printable characters, in an implementation-
                    499:                         * defined manner.''
                    500:                         *      -- ANSI X3J11
                    501:                         */
                    502:                        ulval = (unsigned long)va_arg(ap, void *);
                    503:                        base = 16;
                    504:                        xdigs = "0123456789abcdef";
                    505:                        flags = (flags & ~QUADINT) | HEXPREFIX;
                    506:                        ch = 'x';
                    507:                        goto nosign;
                    508:                case 's':
                    509:                        if ((cp = va_arg(ap, char *)) == NULL)
                    510:                                cp = "(null)";
                    511:                        if (prec >= 0) {
                    512:                                /*
                    513:                                 * can't use strlen; can only look for the
                    514:                                 * NUL in the first `prec' characters, and
                    515:                                 * strlen() will go further.
                    516:                                 */
                    517:                                char *p = memchr(cp, 0, prec);
                    518: 
                    519:                                if (p != NULL) {
                    520:                                        size = p - cp;
                    521:                                        if (size > prec)
                    522:                                                size = prec;
                    523:                                } else
                    524:                                        size = prec;
                    525:                        } else
                    526:                                size = strlen(cp);
                    527:                        sign = '\0';
                    528:                        break;
                    529:                case 'U':
                    530:                        flags |= LONGINT;
                    531:                        /*FALLTHROUGH*/
                    532:                case 'u':
                    533: #ifdef HAVE_LONG_LONG_INT
                    534:                        if (flags & QUADINT)
                    535:                                uqval = va_arg(ap, unsigned long long);
                    536:                        else
                    537: #endif /* HAVE_LONG_LONG_INT */
                    538:                                ulval = UARG();
                    539:                        base = 10;
                    540:                        goto nosign;
                    541:                case 'X':
                    542:                        xdigs = "0123456789ABCDEF";
                    543:                        goto hex;
                    544:                case 'x':
                    545:                        xdigs = "0123456789abcdef";
                    546: hex:
                    547: #ifdef HAVE_LONG_LONG_INT
                    548:                        if (flags & QUADINT)
                    549:                                uqval = va_arg(ap, unsigned long long);
                    550:                        else
                    551: #endif /* HAVE_LONG_LONG_INT */
                    552:                                ulval = UARG();
                    553:                        base = 16;
                    554:                        /* leading 0x/X only if non-zero */
                    555:                        if (flags & ALT &&
                    556: #ifdef HAVE_LONG_LONG_INT
                    557:                            (flags & QUADINT ? uqval != 0 : ulval != 0))
                    558: #else
                    559:                            ulval != 0)
                    560: #endif /* HAVE_LONG_LONG_INT */
                    561:                                flags |= HEXPREFIX;
                    562: 
                    563:                        /* unsigned conversions */
                    564: nosign:                        sign = '\0';
                    565:                        /*
                    566:                         * ``... diouXx conversions ... if a precision is
                    567:                         * specified, the 0 flag will be ignored.''
                    568:                         *      -- ANSI X3J11
                    569:                         */
                    570: number:                        if ((dprec = prec) >= 0)
                    571:                                flags &= ~ZEROPAD;
                    572: 
                    573:                        /*
                    574:                         * ``The result of converting a zero value with an
                    575:                         * explicit precision of zero is no characters.''
                    576:                         *      -- ANSI X3J11
                    577:                         */
                    578:                        cp = buf + BUF;
                    579: #ifdef HAVE_LONG_LONG_INT
                    580:                        if (flags & QUADINT) {
                    581:                                if (uqval != 0 || prec != 0)
                    582:                                        cp = __uqtoa(uqval, cp, base,
                    583:                                            flags & ALT, xdigs);
                    584:                        }
                    585:                        else
                    586: #endif /* HAVE_LONG_LONG_INT */
                    587:                        {
                    588:                                if (ulval != 0 || prec != 0)
                    589:                                        cp = __ultoa(ulval, cp, base,
                    590:                                            flags & ALT, xdigs);
                    591:                        }
                    592:                        size = buf + BUF - cp;
                    593:                        break;
                    594:                default:        /* "%?" prints ?, unless ? is NUL */
                    595:                        if (ch == '\0')
                    596:                                goto done;
                    597:                        /* pretend it was %c with argument ch */
                    598:                        cp = buf;
                    599:                        *cp = ch;
                    600:                        size = 1;
                    601:                        sign = '\0';
                    602:                        break;
                    603:                }
                    604: 
                    605:                /*
                    606:                 * All reasonable formats wind up here.  At this point, `cp'
                    607:                 * points to a string which (if not flags&LADJUST) should be
                    608:                 * padded out to `width' places.  If flags&ZEROPAD, it should
                    609:                 * first be prefixed by any sign or other prefix; otherwise,
                    610:                 * it should be blank padded before the prefix is emitted.
                    611:                 * After any left-hand padding and prefixing, emit zeroes
                    612:                 * required by a decimal [diouxX] precision, then print the
                    613:                 * string proper, then emit zeroes required by any leftover
                    614:                 * floating precision; finally, if LADJUST, pad with blanks.
                    615:                 *
                    616:                 * Compute actual size, so we know how much to pad.
                    617:                 * fieldsz excludes decimal prec; realsz includes it.
                    618:                 */
                    619:                fieldsz = size;
                    620:                if (sign)
                    621:                        fieldsz++;
                    622:                else if (flags & HEXPREFIX)
                    623:                        fieldsz += 2;
                    624:                realsz = dprec > fieldsz ? dprec : fieldsz;
                    625: 
                    626:                /* right-adjusting blank padding */
                    627:                if ((flags & (LADJUST|ZEROPAD)) == 0)
                    628:                        PAD(width - realsz, blanks);
                    629: 
                    630:                /* prefix */
                    631:                if (sign) {
                    632:                        PRINT(&sign, 1);
                    633:                } else if (flags & HEXPREFIX) {
                    634:                        ox[0] = '0';
                    635:                        ox[1] = ch;
                    636:                        PRINT(ox, 2);
                    637:                }
                    638: 
                    639:                /* right-adjusting zero padding */
                    640:                if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
                    641:                        PAD(width - realsz, zeroes);
                    642: 
                    643:                /* leading zeroes from decimal precision */
                    644:                PAD(dprec - fieldsz, zeroes);
                    645: 
                    646:                /* the string or number proper */
                    647:                PRINT(cp, size);
                    648: 
                    649:                /* left-adjusting padding (always blank) */
                    650:                if (flags & LADJUST)
                    651:                        PAD(width - realsz, blanks);
                    652: 
                    653:                /* finally, adjust ret */
                    654:                ret += width > realsz ? width : realsz;
                    655:        }
                    656: done:
                    657:        if (strsize)
                    658:                *str = '\0';
                    659:        return ret;
                    660:        /* NOTREACHED */
                    661: }
                    662: 
                    663: #ifndef HAVE_VSNPRINTF
                    664: int
                    665: vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
                    666: {
                    667: 
                    668:        return xxxprintf(&str, n, 0, fmt, ap);
                    669: }
                    670: #endif /* HAVE_VSNPRINTF */
                    671: 
                    672: #ifndef HAVE_SNPRINTF
                    673: int
                    674: snprintf(char *str, size_t n, char const *fmt, ...)
                    675: {
                    676:        int ret;
                    677:        va_list ap;
                    678: 
                    679:        va_start(ap, fmt);
                    680:        ret = xxxprintf(&str, n, 0, fmt, ap);
                    681:        va_end(ap);
                    682:        return ret;
                    683: }
                    684: #endif /* HAVE_SNPRINTF */
                    685: 
                    686: #ifndef HAVE_VASPRINTF
                    687: int
                    688: vasprintf(char **str, const char *fmt, va_list ap)
                    689: {
                    690: 
                    691:        return xxxprintf(str, 0, 1, fmt, ap);
                    692: }
                    693: #endif /* HAVE_VASPRINTF */
                    694: 
                    695: #ifndef HAVE_ASPRINTF
                    696: int
                    697: asprintf(char **str, char const *fmt, ...)
                    698: {
                    699:        int ret;
                    700:        va_list ap;
                    701: 
                    702:        va_start(ap, fmt);
                    703:        ret = xxxprintf(str, 0, 1, fmt, ap);
                    704:        va_end(ap);
                    705:        return ret;
                    706: }
                    707: #endif /* HAVE_ASPRINTF */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>