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

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

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