Annotation of qemu/roms/openbios/libc/vsprintf.c, revision 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.