Annotation of embedaddon/ntp/lib/isc/print.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
                      3:  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
                      4:  *
                      5:  * Permission to use, copy, modify, and/or distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
                     10:  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
                     11:  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
                     12:  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
                     13:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
                     14:  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
                     15:  * PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: 
                     18: /* $Id: print.c,v 1.35 2008/02/18 23:46:59 tbox Exp $ */
                     19: 
                     20: /*! \file */
                     21: 
                     22: #include <config.h>
                     23: 
                     24: #include <ctype.h>
                     25: #include <stdio.h>             /* for sprintf() */
                     26: #include <string.h>            /* for strlen() */
                     27: 
                     28: #define        ISC__PRINT_SOURCE       /* Used to get the isc_print_* prototypes. */
                     29: 
                     30: #include <isc/assertions.h>
                     31: #include <isc/int.h>
                     32: #include <isc/msgs.h>
                     33: #include <isc/print.h>
                     34: #include <isc/stdlib.h>
                     35: #include <isc/util.h>
                     36: 
                     37: int
                     38: isc_print_sprintf(char *str, const char *format, ...) {
                     39:        va_list ap;
                     40: 
                     41:        va_start(ap, format);
                     42:        vsprintf(str, format, ap);
                     43:        va_end(ap);
                     44:        return (strlen(str));
                     45: }
                     46: 
                     47: /*!
                     48:  * Return length of string that would have been written if not truncated.
                     49:  */
                     50: 
                     51: int
                     52: isc_print_snprintf(char *str, size_t size, const char *format, ...) {
                     53:        va_list ap;
                     54:        int ret;
                     55: 
                     56:        va_start(ap, format);
                     57:        ret = vsnprintf(str, size, format, ap);
                     58:        va_end(ap);
                     59:        return (ret);
                     60: 
                     61: }
                     62: 
                     63: /*!
                     64:  * Return length of string that would have been written if not truncated.
                     65:  */
                     66: 
                     67: int
                     68: isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
                     69:        int h;
                     70:        int l;
                     71:        int q;
                     72:        int alt;
                     73:        int zero;
                     74:        int left;
                     75:        int plus;
                     76:        int space;
                     77:        int neg;
                     78:        isc_int64_t tmpi;
                     79:        isc_uint64_t tmpui;
                     80:        unsigned long width;
                     81:        unsigned long precision;
                     82:        unsigned int length;
                     83:        char buf[1024];
                     84:        char c;
                     85:        void *v;
                     86:        char *save = str;
                     87:        const char *cp;
                     88:        const char *head;
                     89:        int count = 0;
                     90:        int pad;
                     91:        int zeropad;
                     92:        int dot;
                     93:        double dbl;
                     94: #ifdef HAVE_LONG_DOUBLE
                     95:        long double ldbl;
                     96: #endif
                     97:        char fmt[32];
                     98: 
                     99:        INSIST(str != NULL);
                    100:        INSIST(format != NULL);
                    101: 
                    102:        while (*format != '\0') {
                    103:                if (*format != '%') {
                    104:                        if (size > 1) {
                    105:                                *str++ = *format;
                    106:                                size--;
                    107:                        }
                    108:                        count++;
                    109:                        format++;
                    110:                        continue;
                    111:                }
                    112:                format++;
                    113: 
                    114:                /*
                    115:                 * Reset flags.
                    116:                 */
                    117:                dot = neg = space = plus = left = zero = alt = h = l = q = 0;
                    118:                width = precision = 0;
                    119:                head = "";
                    120:                length = pad = zeropad = 0;
                    121: 
                    122:                do {
                    123:                        if (*format == '#') {
                    124:                                alt = 1;
                    125:                                format++;
                    126:                        } else if (*format == '-') {
                    127:                                left = 1;
                    128:                                zero = 0;
                    129:                                format++;
                    130:                        } else if (*format == ' ') {
                    131:                                if (!plus)
                    132:                                        space = 1;
                    133:                                format++;
                    134:                        } else if (*format == '+') {
                    135:                                plus = 1;
                    136:                                space = 0;
                    137:                                format++;
                    138:                        } else if (*format == '0') {
                    139:                                if (!left)
                    140:                                        zero = 1;
                    141:                                format++;
                    142:                        } else
                    143:                                break;
                    144:                } while (1);
                    145: 
                    146:                /*
                    147:                 * Width.
                    148:                 */
                    149:                if (*format == '*') {
                    150:                        width = va_arg(ap, int);
                    151:                        format++;
                    152:                } else if (isdigit((unsigned char)*format)) {
                    153:                        char *e;
                    154:                        width = strtoul(format, &e, 10);
                    155:                        format = e;
                    156:                }
                    157: 
                    158:                /*
                    159:                 * Precision.
                    160:                 */
                    161:                if (*format == '.') {
                    162:                        format++;
                    163:                        dot = 1;
                    164:                        if (*format == '*') {
                    165:                                precision = va_arg(ap, int);
                    166:                                format++;
                    167:                        } else if (isdigit((unsigned char)*format)) {
                    168:                                char *e;
                    169:                                precision = strtoul(format, &e, 10);
                    170:                                format = e;
                    171:                        }
                    172:                }
                    173: 
                    174:                switch (*format) {
                    175:                case '\0':
                    176:                        continue;
                    177:                case '%':
                    178:                        if (size > 1) {
                    179:                                *str++ = *format;
                    180:                                size--;
                    181:                        }
                    182:                        count++;
                    183:                        break;
                    184:                case 'q':
                    185:                        q = 1;
                    186:                        format++;
                    187:                        goto doint;
                    188:                case 'h':
                    189:                        h = 1;
                    190:                        format++;
                    191:                        goto doint;
                    192:                case 'l':
                    193:                        l = 1;
                    194:                        format++;
                    195:                        if (*format == 'l') {
                    196:                                q = 1;
                    197:                                format++;
                    198:                        }
                    199:                        goto doint;
                    200:                case 'n':
                    201:                case 'i':
                    202:                case 'd':
                    203:                case 'o':
                    204:                case 'u':
                    205:                case 'x':
                    206:                case 'X':
                    207:                doint:
                    208:                        if (precision != 0)
                    209:                                zero = 0;
                    210:                        switch (*format) {
                    211:                        case 'n':
                    212:                                if (h) {
                    213:                                        short int *p;
                    214:                                        p = va_arg(ap, short *);
                    215:                                        REQUIRE(p != NULL);
                    216:                                        *p = str - save;
                    217:                                } else if (l) {
                    218:                                        long int *p;
                    219:                                        p = va_arg(ap, long *);
                    220:                                        REQUIRE(p != NULL);
                    221:                                        *p = str - save;
                    222:                                } else {
                    223:                                        int *p;
                    224:                                        p = va_arg(ap, int *);
                    225:                                        REQUIRE(p != NULL);
                    226:                                        *p = str - save;
                    227:                                }
                    228:                                break;
                    229:                        case 'i':
                    230:                        case 'd':
                    231:                                if (q)
                    232:                                        tmpi = va_arg(ap, isc_int64_t);
                    233:                                else if (l)
                    234:                                        tmpi = va_arg(ap, long int);
                    235:                                else
                    236:                                        tmpi = va_arg(ap, int);
                    237:                                if (tmpi < 0) {
                    238:                                        head = "-";
                    239:                                        tmpui = -tmpi;
                    240:                                } else {
                    241:                                        if (plus)
                    242:                                                head = "+";
                    243:                                        else if (space)
                    244:                                                head = " ";
                    245:                                        else
                    246:                                                head = "";
                    247:                                        tmpui = tmpi;
                    248:                                }
                    249:                                if (tmpui <= 0xffffffffU)
                    250:                                        sprintf(buf, "%lu",
                    251:                                                (unsigned long)tmpui);
                    252:                                else {
                    253:                                        unsigned long mid;
                    254:                                        unsigned long lo;
                    255:                                        unsigned long hi;
                    256:                                        lo = tmpui % 1000000000;
                    257:                                        tmpui /= 1000000000;
                    258:                                        mid = tmpui % 1000000000;
                    259:                                        hi = tmpui / 1000000000;
                    260:                                        if (hi != 0)
                    261:                                                sprintf(buf, "%lu", hi);
                    262:                                        else
                    263:                                                buf[0] = '\n';
                    264:                                        sprintf(buf + strlen(buf), "%lu", mid);
                    265:                                        sprintf(buf + strlen(buf), "%lu", lo);
                    266:                                }
                    267:                                goto printint;
                    268:                        case 'o':
                    269:                                if (q)
                    270:                                        tmpui = va_arg(ap, isc_uint64_t);
                    271:                                else if (l)
                    272:                                        tmpui = va_arg(ap, long int);
                    273:                                else
                    274:                                        tmpui = va_arg(ap, int);
                    275:                                if (tmpui <= 0xffffffffU)
                    276:                                        sprintf(buf, alt ?  "%#lo" : "%lo",
                    277:                                                (unsigned long)tmpui);
                    278:                                else {
                    279:                                        unsigned long mid;
                    280:                                        unsigned long lo;
                    281:                                        unsigned long hi;
                    282:                                        lo = tmpui % 010000000000;
                    283:                                        tmpui /= 010000000000;
                    284:                                        mid = tmpui % 010000000000;
                    285:                                        hi = tmpui / 010000000000;
                    286:                                        if (hi != 0) {
                    287:                                                sprintf(buf,
                    288:                                                        alt ?  "%#lo" : "%lo",
                    289:                                                        hi);
                    290:                                                sprintf(buf + strlen(buf),
                    291:                                                        "%lo", mid);
                    292:                                        } else
                    293:                                                sprintf(buf,
                    294:                                                        alt ?  "%#lo" : "%lo",
                    295:                                                        mid);
                    296:                                        sprintf(buf + strlen(buf), "%lo", lo);
                    297:                                }
                    298:                                goto printint;
                    299:                        case 'u':
                    300:                                if (q)
                    301:                                        tmpui = va_arg(ap, isc_uint64_t);
                    302:                                else if (l)
                    303:                                        tmpui = va_arg(ap, unsigned long int);
                    304:                                else
                    305:                                        tmpui = va_arg(ap, unsigned int);
                    306:                                if (tmpui <= 0xffffffffU)
                    307:                                        sprintf(buf, "%lu",
                    308:                                                (unsigned long)tmpui);
                    309:                                else {
                    310:                                        unsigned long mid;
                    311:                                        unsigned long lo;
                    312:                                        unsigned long hi;
                    313:                                        lo = tmpui % 1000000000;
                    314:                                        tmpui /= 1000000000;
                    315:                                        mid = tmpui % 1000000000;
                    316:                                        hi = tmpui / 1000000000;
                    317:                                        if (hi != 0)
                    318:                                                sprintf(buf, "%lu", hi);
                    319:                                        else
                    320:                                                buf[0] = '\n';
                    321:                                        sprintf(buf + strlen(buf), "%lu", mid);
                    322:                                        sprintf(buf + strlen(buf), "%lu", lo);
                    323:                                }
                    324:                                goto printint;
                    325:                        case 'x':
                    326:                                if (q)
                    327:                                        tmpui = va_arg(ap, isc_uint64_t);
                    328:                                else if (l)
                    329:                                        tmpui = va_arg(ap, unsigned long int);
                    330:                                else
                    331:                                        tmpui = va_arg(ap, unsigned int);
                    332:                                if (alt) {
                    333:                                        head = "0x";
                    334:                                        if (precision > 2)
                    335:                                                precision -= 2;
                    336:                                }
                    337:                                if (tmpui <= 0xffffffffU)
                    338:                                        sprintf(buf, "%lx",
                    339:                                                (unsigned long)tmpui);
                    340:                                else {
                    341:                                        unsigned long hi = tmpui>>32;
                    342:                                        unsigned long lo = tmpui & 0xffffffff;
                    343:                                        sprintf(buf, "%lx", hi);
                    344:                                        sprintf(buf + strlen(buf), "%lx", lo);
                    345:                                }
                    346:                                goto printint;
                    347:                        case 'X':
                    348:                                if (q)
                    349:                                        tmpui = va_arg(ap, isc_uint64_t);
                    350:                                else if (l)
                    351:                                        tmpui = va_arg(ap, unsigned long int);
                    352:                                else
                    353:                                        tmpui = va_arg(ap, unsigned int);
                    354:                                if (alt) {
                    355:                                        head = "0X";
                    356:                                        if (precision > 2)
                    357:                                                precision -= 2;
                    358:                                }
                    359:                                if (tmpui <= 0xffffffffU)
                    360:                                        sprintf(buf, "%lX",
                    361:                                                (unsigned long)tmpui);
                    362:                                else  {
                    363:                                        unsigned long hi = tmpui>>32;
                    364:                                        unsigned long lo = tmpui & 0xffffffff;
                    365:                                        sprintf(buf, "%lX", hi);
                    366:                                        sprintf(buf + strlen(buf), "%lX", lo);
                    367:                                }
                    368:                                goto printint;
                    369:                        printint:
                    370:                                if (precision != 0 || width != 0) {
                    371:                                        length = strlen(buf);
                    372:                                        if (length < precision)
                    373:                                                zeropad = precision - length;
                    374:                                        else if (length < width && zero)
                    375:                                                zeropad = width - length;
                    376:                                        if (width != 0) {
                    377:                                                pad = width - length -
                    378:                                                      zeropad - strlen(head);
                    379:                                                if (pad < 0)
                    380:                                                        pad = 0;
                    381:                                        }
                    382:                                }
                    383:                                count += strlen(head) + strlen(buf) + pad +
                    384:                                         zeropad;
                    385:                                if (!left) {
                    386:                                        while (pad > 0 && size > 1) {
                    387:                                                *str++ = ' ';
                    388:                                                size--;
                    389:                                                pad--;
                    390:                                        }
                    391:                                }
                    392:                                cp = head;
                    393:                                while (*cp != '\0' && size > 1) {
                    394:                                        *str++ = *cp++;
                    395:                                        size--;
                    396:                                }
                    397:                                while (zeropad > 0 && size > 1) {
                    398:                                        *str++ = '0';
                    399:                                        size--;
                    400:                                        zeropad--;
                    401:                                }
                    402:                                cp = buf;
                    403:                                while (*cp != '\0' && size > 1) {
                    404:                                        *str++ = *cp++;
                    405:                                        size--;
                    406:                                }
                    407:                                while (pad > 0 && size > 1) {
                    408:                                        *str++ = ' ';
                    409:                                        size--;
                    410:                                        pad--;
                    411:                                }
                    412:                                break;
                    413:                        default:
                    414:                                break;
                    415:                        }
                    416:                        break;
                    417:                case 's':
                    418:                        cp = va_arg(ap, char *);
                    419:                        REQUIRE(cp != NULL);
                    420: 
                    421:                        if (precision != 0) {
                    422:                                /*
                    423:                                 * cp need not be NULL terminated.
                    424:                                 */
                    425:                                const char *tp;
                    426:                                unsigned long n;
                    427: 
                    428:                                n = precision;
                    429:                                tp = cp;
                    430:                                while (n != 0 && *tp != '\0')
                    431:                                        n--, tp++;
                    432:                                length = precision - n;
                    433:                        } else {
                    434:                                length = strlen(cp);
                    435:                        }
                    436:                        if (width != 0) {
                    437:                                pad = width - length;
                    438:                                if (pad < 0)
                    439:                                        pad = 0;
                    440:                        }
                    441:                        count += pad + length;
                    442:                        if (!left)
                    443:                                while (pad > 0 && size > 1) {
                    444:                                        *str++ = ' ';
                    445:                                        size--;
                    446:                                        pad--;
                    447:                                }
                    448:                        if (precision != 0)
                    449:                                while (precision > 0 && *cp != '\0' &&
                    450:                                       size > 1) {
                    451:                                        *str++ = *cp++;
                    452:                                        size--;
                    453:                                        precision--;
                    454:                                }
                    455:                        else
                    456:                                while (*cp != '\0' && size > 1) {
                    457:                                        *str++ = *cp++;
                    458:                                        size--;
                    459:                                }
                    460:                        while (pad > 0 && size > 1) {
                    461:                                *str++ = ' ';
                    462:                                size--;
                    463:                                pad--;
                    464:                        }
                    465:                        break;
                    466:                case 'c':
                    467:                        c = va_arg(ap, int);
                    468:                        if (width > 0) {
                    469:                                count += width;
                    470:                                width--;
                    471:                                if (left) {
                    472:                                        *str++ = c;
                    473:                                        size--;
                    474:                                }
                    475:                                while (width-- > 0 && size > 1) {
                    476:                                        *str++ = ' ';
                    477:                                        size--;
                    478:                                }
                    479:                                if (!left && size > 1) {
                    480:                                        *str++ = c;
                    481:                                        size--;
                    482:                                }
                    483:                        } else {
                    484:                                count++;
                    485:                                if (size > 1) {
                    486:                                        *str++ = c;
                    487:                                        size--;
                    488:                                }
                    489:                        }
                    490:                        break;
                    491:                case 'p':
                    492:                        v = va_arg(ap, void *);
                    493:                        sprintf(buf, "%p", v);
                    494:                        length = strlen(buf);
                    495:                        if (precision > length)
                    496:                                zeropad = precision - length;
                    497:                        if (width > 0) {
                    498:                                pad = width - length - zeropad;
                    499:                                if (pad < 0)
                    500:                                        pad = 0;
                    501:                        }
                    502:                        count += length + pad + zeropad;
                    503:                        if (!left)
                    504:                                while (pad > 0 && size > 1) {
                    505:                                        *str++ = ' ';
                    506:                                        size--;
                    507:                                        pad--;
                    508:                                }
                    509:                        cp = buf;
                    510:                        if (zeropad > 0 && buf[0] == '0' &&
                    511:                            (buf[1] == 'x' || buf[1] == 'X')) {
                    512:                                if (size > 1) {
                    513:                                        *str++ = *cp++;
                    514:                                        size--;
                    515:                                }
                    516:                                if (size > 1) {
                    517:                                        *str++ = *cp++;
                    518:                                        size--;
                    519:                                }
                    520:                                while (zeropad > 0 && size > 1) {
                    521:                                        *str++ = '0';
                    522:                                        size--;
                    523:                                        zeropad--;
                    524:                                }
                    525:                        }
                    526:                        while (*cp != '\0' && size > 1) {
                    527:                                *str++ = *cp++;
                    528:                                size--;
                    529:                        }
                    530:                        while (pad > 0 && size > 1) {
                    531:                                *str++ = ' ';
                    532:                                size--;
                    533:                                pad--;
                    534:                        }
                    535:                        break;
                    536:                case 'D':       /*deprecated*/
                    537:                        INSIST("use %ld instead of %D" == NULL);
                    538:                case 'O':       /*deprecated*/
                    539:                        INSIST("use %lo instead of %O" == NULL);
                    540:                case 'U':       /*deprecated*/
                    541:                        INSIST("use %lu instead of %U" == NULL);
                    542: 
                    543:                case 'L':
                    544: #ifdef HAVE_LONG_DOUBLE
                    545:                        l = 1;
                    546: #else
                    547:                        INSIST("long doubles are not supported" == NULL);
                    548: #endif
                    549:                        /*FALLTHROUGH*/
                    550:                case 'e':
                    551:                case 'E':
                    552:                case 'f':
                    553:                case 'g':
                    554:                case 'G':
                    555:                        if (!dot)
                    556:                                precision = 6;
                    557:                        /*
                    558:                         * IEEE floating point.
                    559:                         * MIN 2.2250738585072014E-308
                    560:                         * MAX 1.7976931348623157E+308
                    561:                         * VAX floating point has a smaller range than IEEE.
                    562:                         *
                    563:                         * precisions > 324 don't make much sense.
                    564:                         * if we cap the precision at 512 we will not
                    565:                         * overflow buf.
                    566:                         */
                    567:                        if (precision > 512)
                    568:                                precision = 512;
                    569:                        sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
                    570:                                plus ? "+" : space ? " " : "",
                    571:                                precision, l ? "L" : "", *format);
                    572:                        switch (*format) {
                    573:                        case 'e':
                    574:                        case 'E':
                    575:                        case 'f':
                    576:                        case 'g':
                    577:                        case 'G':
                    578: #ifdef HAVE_LONG_DOUBLE
                    579:                                if (l) {
                    580:                                        ldbl = va_arg(ap, long double);
                    581:                                        sprintf(buf, fmt, ldbl);
                    582:                                } else
                    583: #endif
                    584:                                {
                    585:                                        dbl = va_arg(ap, double);
                    586:                                        sprintf(buf, fmt, dbl);
                    587:                                }
                    588:                                length = strlen(buf);
                    589:                                if (width > 0) {
                    590:                                        pad = width - length;
                    591:                                        if (pad < 0)
                    592:                                                pad = 0;
                    593:                                }
                    594:                                count += length + pad;
                    595:                                if (!left)
                    596:                                        while (pad > 0 && size > 1) {
                    597:                                                *str++ = ' ';
                    598:                                                size--;
                    599:                                                pad--;
                    600:                                        }
                    601:                                cp = buf;
                    602:                                while (*cp != ' ' && size > 1) {
                    603:                                        *str++ = *cp++;
                    604:                                        size--;
                    605:                                }
                    606:                                while (pad > 0 && size > 1) {
                    607:                                        *str++ = ' ';
                    608:                                        size--;
                    609:                                        pad--;
                    610:                                }
                    611:                                break;
                    612:                        default:
                    613:                                continue;
                    614:                        }
                    615:                        break;
                    616:                default:
                    617:                        continue;
                    618:                }
                    619:                format++;
                    620:        }
                    621:        if (size > 0)
                    622:                *str = '\0';
                    623:        return (count);
                    624: }

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