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

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

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