Annotation of qemu/roms/openbios/libc/vsprintf.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * String functions for logger.
                      3:  */
                      4: 
                      5: /*
                      6:  *  linux/lib/vsprintf.c
                      7:  *
                      8:  *  Copyright (C) 1991, 1992  Linus Torvalds
                      9:  */
                     10: 
                     11: /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
                     12: /*
                     13:  * Wirzenius wrote this portably, Torvalds fucked it up :-)
                     14:  */
                     15: 
                     16: /*
                     17:  * Fri Jul 13 2001 Crutcher Dunnavant <[email protected]>
                     18:  * - changed to provide snprintf and vsnprintf functions
                     19:  */
                     20: 
                     21: #include "config.h"
                     22: #include "libc/string.h"
                     23: #include "libc/vsprintf.h"
                     24: 
                     25: static int skip_atoi(const char **s)
                     26: {
                     27:        int i=0;
                     28: 
                     29:        while (isdigit(**s))
                     30:                i = i*10 + *((*s)++) - '0';
                     31:        return i;
                     32: }
                     33: 
                     34: #define ZEROPAD        1               /* pad with zero */
                     35: #define SIGN   2               /* unsigned/signed long */
                     36: #define PLUS   4               /* show plus */
                     37: #define SPACE  8               /* space if plus */
                     38: #define LEFT   16              /* left justified */
                     39: #define SPECIAL        32              /* 0x */
                     40: #define LARGE  64              /* use 'ABCDEF' instead of 'abcdef' */
                     41: 
                     42: #define do_div(n,base) ({ \
                     43: int __res; \
                     44: __res = ((unsigned long long) n) % (unsigned) base; \
                     45: n = ((unsigned long long) n) / (unsigned) base; \
                     46: __res; })
                     47: 
                     48: static int mstrlen( const char *str );
                     49: 
                     50: #ifndef PAGE_SIZE
                     51: #define PAGE_SIZE 4096
                     52: #endif
                     53: 
                     54: static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
                     55: {
                     56:        char c,sign,tmp[66];
                     57:        const char *digits;
                     58:        static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
                     59:        static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                     60:        int i;
                     61: 
                     62:        digits = (type & LARGE) ? large_digits : small_digits;
                     63:        if (type & LEFT)
                     64:                type &= ~ZEROPAD;
                     65:        if (base < 2 || base > 36)
                     66:                 return NULL;
                     67:        c = (type & ZEROPAD) ? '0' : ' ';
                     68:        sign = 0;
                     69:        if (type & SIGN) {
                     70:                if (num < 0) {
                     71:                        sign = '-';
                     72:                        num = -num;
                     73:                        size--;
                     74:                } else if (type & PLUS) {
                     75:                        sign = '+';
                     76:                        size--;
                     77:                } else if (type & SPACE) {
                     78:                        sign = ' ';
                     79:                        size--;
                     80:                }
                     81:        }
                     82:        if (type & SPECIAL) {
                     83:                if (base == 16)
                     84:                        size -= 2;
                     85:                else if (base == 8)
                     86:                        size--;
                     87:        }
                     88:        i = 0;
                     89:        if (num == 0)
                     90:                tmp[i++]='0';
                     91:        else while (num != 0)
                     92:                tmp[i++] = digits[do_div(num,base)];
                     93:        if (i > precision)
                     94:                precision = i;
                     95:        size -= precision;
                     96:        if (!(type&(ZEROPAD+LEFT))) {
                     97:                while(size-->0) {
                     98:                        if (buf <= end)
                     99:                                *buf = ' ';
                    100:                        ++buf;
                    101:                }
                    102:        }
                    103:        if (sign) {
                    104:                if (buf <= end)
                    105:                        *buf = sign;
                    106:                ++buf;
                    107:        }
                    108:        if (type & SPECIAL) {
                    109:                if (base==8) {
                    110:                        if (buf <= end)
                    111:                                *buf = '0';
                    112:                        ++buf;
                    113:                } else if (base==16) {
                    114:                        if (buf <= end)
                    115:                                *buf = '0';
                    116:                        ++buf;
                    117:                        if (buf <= end)
                    118:                                *buf = digits[33];
                    119:                        ++buf;
                    120:                }
                    121:        }
                    122:        if (!(type & LEFT)) {
                    123:                while (size-- > 0) {
                    124:                        if (buf <= end)
                    125:                                *buf = c;
                    126:                        ++buf;
                    127:                }
                    128:        }
                    129:        while (i < precision--) {
                    130:                if (buf <= end)
                    131:                        *buf = '0';
                    132:                ++buf;
                    133:        }
                    134:        while (i-- > 0) {
                    135:                if (buf <= end)
                    136:                        *buf = tmp[i];
                    137:                ++buf;
                    138:        }
                    139:        while (size-- > 0) {
                    140:                if (buf <= end)
                    141:                        *buf = ' ';
                    142:                ++buf;
                    143:        }
                    144:        return buf;
                    145: }
                    146: 
                    147: /**
                    148: * vsnprintf - Format a string and place it in a buffer
                    149: * @buf: The buffer to place the result into
                    150: * @size: The size of the buffer, including the trailing null space
                    151: * @fmt: The format string to use
                    152: * @args: Arguments for the format string
                    153: *
                    154: * Call this function if you are already dealing with a va_list.
                    155: * You probably want snprintf instead.
                    156:  */
                    157: int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
                    158: {
                    159:        int len;
                    160:        unsigned long long num;
                    161:        int i, base;
                    162:        char *str, *end, c;
                    163:        const char *s;
                    164: 
                    165:        int flags;              /* flags to number() */
                    166: 
                    167:        int field_width;        /* width of output field */
                    168:        int precision;          /* min. # of digits for integers; max
                    169:                                   number of chars for from string */
                    170:        int qualifier;          /* 'h', 'l', or 'L' for integer fields */
                    171:                                /* 'z' support added 23/7/1999 S.H.    */
                    172:                                /* 'z' changed to 'Z' --davidm 1/25/99 */
                    173: 
                    174:        str = buf;
                    175:        end = buf + size - 1;
                    176: 
                    177:        if (end < buf - 1) {
                    178:                end = ((void *) -1);
                    179:                size = end - buf + 1;
                    180:        }
                    181: 
                    182:        for (; *fmt ; ++fmt) {
                    183:                if (*fmt != '%') {
                    184:                        if (str <= end)
                    185:                                *str = *fmt;
                    186:                        ++str;
                    187:                        continue;
                    188:                }
                    189: 
                    190:                /* process flags */
                    191:                flags = 0;
                    192:                repeat:
                    193:                        ++fmt;          /* this also skips first '%' */
                    194:                        switch (*fmt) {
                    195:                                case '-': flags |= LEFT; goto repeat;
                    196:                                case '+': flags |= PLUS; goto repeat;
                    197:                                case ' ': flags |= SPACE; goto repeat;
                    198:                                case '#': flags |= SPECIAL; goto repeat;
                    199:                                case '0': flags |= ZEROPAD; goto repeat;
                    200:                        }
                    201: 
                    202:                /* get field width */
                    203:                field_width = -1;
                    204:                if (isdigit(*fmt))
                    205:                        field_width = skip_atoi(&fmt);
                    206:                else if (*fmt == '*') {
                    207:                        ++fmt;
                    208:                        /* it's the next argument */
                    209:                        field_width = va_arg(args, int);
                    210:                        if (field_width < 0) {
                    211:                                field_width = -field_width;
                    212:                                flags |= LEFT;
                    213:                        }
                    214:                }
                    215: 
                    216:                /* get the precision */
                    217:                precision = -1;
                    218:                if (*fmt == '.') {
                    219:                        ++fmt;
                    220:                        if (isdigit(*fmt))
                    221:                                precision = skip_atoi(&fmt);
                    222:                        else if (*fmt == '*') {
                    223:                                ++fmt;
                    224:                                /* it's the next argument */
                    225:                                precision = va_arg(args, int);
                    226:                        }
                    227:                        if (precision < 0)
                    228:                                precision = 0;
                    229:                }
                    230: 
                    231:                /* get the conversion qualifier */
                    232:                qualifier = -1;
                    233:                if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
                    234:                    *fmt =='Z' || *fmt == 'z') {
                    235:                        qualifier = *fmt;
                    236:                        ++fmt;
                    237:                        if (qualifier == 'l' && *fmt == 'l') {
                    238:                                qualifier = 'L';
                    239:                                ++fmt;
                    240:                        }
                    241:                }
                    242: 
                    243:                /* default base */
                    244:                base = 10;
                    245: 
                    246:                switch (*fmt) {
                    247:                        case 'c':
                    248:                                if (!(flags & LEFT)) {
                    249:                                        while (--field_width > 0) {
                    250:                                                if (str <= end)
                    251:                                                        *str = ' ';
                    252:                                                ++str;
                    253:                                        }
                    254:                                }
                    255:                                c = (unsigned char) va_arg(args, int);
                    256:                                if (str <= end)
                    257:                                        *str = c;
                    258:                                ++str;
                    259:                                while (--field_width > 0) {
                    260:                                        if (str <= end)
                    261:                                                *str = ' ';
                    262:                                        ++str;
                    263:                                }
                    264:                                continue;
                    265: 
                    266:                        case 's':
                    267:                                s = va_arg(args, char *);
                    268:                                if ((unsigned long)s < PAGE_SIZE)
                    269:                                        s = "<NULL>";
                    270: 
                    271: #if 0
                    272:                                 len = strnlen(s, precision);
                    273: #else
                    274:                                 len = mstrlen(s);
                    275:                                 if( precision > len )
                    276:                                     len = precision;
                    277: #endif
                    278:                                if (!(flags & LEFT)) {
                    279:                                        while (len < field_width--) {
                    280:                                                if (str <= end)
                    281:                                                        *str = ' ';
                    282:                                                ++str;
                    283:                                        }
                    284:                                }
                    285:                                for (i = 0; i < len; ++i) {
                    286:                                        if (str <= end)
                    287:                                                *str = *s;
                    288:                                        ++str; ++s;
                    289:                                }
                    290:                                while (len < field_width--) {
                    291:                                        if (str <= end)
                    292:                                                *str = ' ';
                    293:                                        ++str;
                    294:                                }
                    295:                                continue;
                    296: 
                    297:                        case 'p':
                    298:                                if (field_width == -1) {
                    299:                                        field_width = 2*sizeof(void *);
                    300:                                        flags |= ZEROPAD;
                    301:                                }
                    302:                                str = number(str, end,
                    303:                                                (unsigned long) va_arg(args, void *),
                    304:                                                16, field_width, precision, flags);
                    305:                                continue;
                    306: 
                    307: 
                    308:                        case 'n':
                    309:                                /* FIXME:
                    310:                                * What does C99 say about the overflow case here? */
                    311:                                if (qualifier == 'l') {
                    312:                                        long * ip = va_arg(args, long *);
                    313:                                        *ip = (str - buf);
                    314:                                } else if (qualifier == 'Z' || qualifier == 'z') {
                    315:                                        size_t * ip = va_arg(args, size_t *);
                    316:                                        *ip = (str - buf);
                    317:                                } else {
                    318:                                        int * ip = va_arg(args, int *);
                    319:                                        *ip = (str - buf);
                    320:                                }
                    321:                                continue;
                    322: 
                    323:                        case '%':
                    324:                                if (str <= end)
                    325:                                        *str = '%';
                    326:                                ++str;
                    327:                                continue;
                    328: 
                    329:                                /* integer number formats - set up the flags and "break" */
                    330:                        case 'o':
                    331:                                base = 8;
                    332:                                break;
                    333: 
                    334:                        case 'X':
                    335:                                flags |= LARGE;
                    336:                        case 'x':
                    337:                                base = 16;
                    338:                                break;
                    339: 
                    340:                        case 'd':
                    341:                        case 'i':
                    342:                                flags |= SIGN;
                    343:                        case 'u':
                    344:                                break;
                    345: 
                    346:                        default:
                    347:                                if (str <= end)
                    348:                                        *str = '%';
                    349:                                ++str;
                    350:                                if (*fmt) {
                    351:                                        if (str <= end)
                    352:                                                *str = *fmt;
                    353:                                        ++str;
                    354:                                } else {
                    355:                                        --fmt;
                    356:                                }
                    357:                                continue;
                    358:                }
                    359:                if (qualifier == 'L')
                    360:                        num = va_arg(args, long long);
                    361:                else if (qualifier == 'l') {
                    362:                        num = va_arg(args, unsigned long);
                    363:                        if (flags & SIGN)
                    364:                                num = (signed long) num;
                    365:                } else if (qualifier == 'Z' || qualifier == 'z') {
                    366:                        num = va_arg(args, size_t);
                    367:                } else if (qualifier == 'h') {
                    368:                        num = (unsigned short) va_arg(args, int);
                    369:                        if (flags & SIGN)
                    370:                                num = (signed short) num;
                    371:                } else {
                    372:                        num = va_arg(args, unsigned int);
                    373:                        if (flags & SIGN)
                    374:                                num = (signed int) num;
                    375:                }
                    376:                str = number(str, end, num, base,
                    377:                                field_width, precision, flags);
                    378:        }
                    379:        if (str <= end)
                    380:                *str = '\0';
                    381:        else if (size > 0)
                    382:                /* don't write out a null byte if the buf size is zero */
                    383:                *end = '\0';
                    384:        /* the trailing null byte doesn't count towards the total
                    385:        * ++str;
                    386:        */
                    387:        return str-buf;
                    388: }
                    389: 
                    390: /**
                    391:  * snprintf - Format a string and place it in a buffer
                    392:  * @buf: The buffer to place the result into
                    393:  * @size: The size of the buffer, including the trailing null space
                    394:  * @fmt: The format string to use
                    395:  * @...: Arguments for the format string
                    396:  */
                    397: int snprintf(char * buf, size_t size, const char *fmt, ...)
                    398: {
                    399:        va_list args;
                    400:        int i;
                    401: 
                    402:        va_start(args, fmt);
                    403:        i=vsnprintf(buf,size,fmt,args);
                    404:        va_end(args);
                    405:        return i;
                    406: }
                    407: 
                    408: /**
                    409:  * vsprintf - Format a string and place it in a buffer
                    410:  * @buf: The buffer to place the result into
                    411:  * @fmt: The format string to use
                    412:  * @args: Arguments for the format string
                    413:  *
                    414:  * Call this function if you are already dealing with a va_list.
                    415:  * You probably want sprintf instead.
                    416:  */
                    417: int vsprintf(char *buf, const char *fmt, va_list args)
                    418: {
                    419:        return vsnprintf(buf, (~0U)>>1, fmt, args);
                    420: }
                    421: 
                    422: 
                    423: /**
                    424:  * sprintf - Format a string and place it in a buffer
                    425:  * @buf: The buffer to place the result into
                    426:  * @fmt: The format string to use
                    427:  * @...: Arguments for the format string
                    428:  */
                    429: int sprintf(char * buf, const char *fmt, ...)
                    430: {
                    431:        va_list args;
                    432:        int i;
                    433: 
                    434:        va_start(args, fmt);
                    435:        i=vsprintf(buf,fmt,args);
                    436:        va_end(args);
                    437:        return i;
                    438: }
                    439: 
                    440: static int mstrlen( const char *str )
                    441: {
                    442:        int i=0;
                    443:        if( str == NULL )
                    444:                return 0;
                    445:        while( *str++ )
                    446:                i++;
                    447:        return i;
                    448: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.