Annotation of Gnu-Mach/linux/dev/lib/vsprintf.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  *  linux/lib/vsprintf.c
                      3:  *
                      4:  *  Copyright (C) 1991, 1992  Linus Torvalds
                      5:  */
                      6: 
                      7: /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
                      8: /*
                      9:  * Wirzenius wrote this portably, Torvalds fucked it up :-)
                     10:  */
                     11: 
                     12: #include <sys/types.h>
                     13: 
                     14: #define MACH_INCLUDE
                     15: #include <stdarg.h>
                     16: #include <linux/types.h>
                     17: #include <linux/string.h>
                     18: #include <linux/ctype.h>
                     19: 
                     20: unsigned long 
                     21: simple_strtoul (const char *cp, char **endp, unsigned int base)
                     22: {
                     23:   unsigned long result = 0, value;
                     24: 
                     25:   if (!base)
                     26:     {
                     27:       base = 10;
                     28:       if (*cp == '0')
                     29:        {
                     30:          base = 8;
                     31:          cp++;
                     32:          if ((*cp == 'x') && isxdigit (cp[1]))
                     33:            {
                     34:              cp++;
                     35:              base = 16;
                     36:            }
                     37:        }
                     38:     }
                     39:   while (isxdigit (*cp)
                     40:         && (value = isdigit (*cp) ? *cp - '0'
                     41:             : (islower (*cp) ? toupper (*cp) : *cp) - 'A' + 10) < base)
                     42:     {
                     43:       result = result * base + value;
                     44:       cp++;
                     45:     }
                     46:   if (endp)
                     47:     *endp = (char *) cp;
                     48:   return result;
                     49: }
                     50: 
                     51: /* we use this so that we can do without the ctype library */
                     52: #define is_digit(c)    ((c) >= '0' && (c) <= '9')
                     53: 
                     54: static int
                     55: skip_atoi (const char **s)
                     56: {
                     57:   int i = 0;
                     58: 
                     59:   while (is_digit (**s))
                     60:     i = i * 10 + *((*s)++) - '0';
                     61:   return i;
                     62: }
                     63: 
                     64: #define ZEROPAD        1               /* pad with zero */
                     65: #define SIGN   2               /* unsigned/signed long */
                     66: #define PLUS   4               /* show plus */
                     67: #define SPACE  8               /* space if plus */
                     68: #define LEFT   16              /* left justified */
                     69: #define SPECIAL        32              /* 0x */
                     70: #define LARGE  64              /* use 'ABCDEF' instead of 'abcdef' */
                     71: 
                     72: #define do_div(n,base) ({ \
                     73: int __res; \
                     74: __res = ((unsigned long) n) % (unsigned) base; \
                     75: n = ((unsigned long) n) / (unsigned) base; \
                     76: __res; })
                     77: 
                     78: static char *
                     79: number (char *str, long num, int base, int size, int precision, int type)
                     80: {
                     81:   char c, sign, tmp[66];
                     82:   const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
                     83:   int i;
                     84: 
                     85:   if (type & LARGE)
                     86:     digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                     87:   if (type & LEFT)
                     88:     type &= ~ZEROPAD;
                     89:   if (base < 2 || base > 36)
                     90:     return 0;
                     91:   c = (type & ZEROPAD) ? '0' : ' ';
                     92:   sign = 0;
                     93:   if (type & SIGN)
                     94:     {
                     95:       if (num < 0)
                     96:        {
                     97:          sign = '-';
                     98:          num = -num;
                     99:          size--;
                    100:        }
                    101:       else if (type & PLUS)
                    102:        {
                    103:          sign = '+';
                    104:          size--;
                    105:        }
                    106:       else if (type & SPACE)
                    107:        {
                    108:          sign = ' ';
                    109:          size--;
                    110:        }
                    111:     }
                    112:   if (type & SPECIAL)
                    113:     {
                    114:       if (base == 16)
                    115:        size -= 2;
                    116:       else if (base == 8)
                    117:        size--;
                    118:     }
                    119:   i = 0;
                    120:   if (num == 0)
                    121:     tmp[i++] = '0';
                    122:   else
                    123:     while (num != 0)
                    124:       tmp[i++] = digits[do_div (num, base)];
                    125:   if (i > precision)
                    126:     precision = i;
                    127:   size -= precision;
                    128:   if (!(type & (ZEROPAD + LEFT)))
                    129:     while (size-- > 0)
                    130:       *str++ = ' ';
                    131:   if (sign)
                    132:     *str++ = sign;
                    133:   if (type & SPECIAL)
1.1.1.2   root      134:     {
                    135:       if (base == 8)
                    136:        {
                    137:          *str++ = '0';
                    138:        }
                    139:       else if (base == 16)
                    140:        {
                    141:          *str++ = '0';
                    142:          *str++ = digits[33];
                    143:        }
                    144:     }
1.1       root      145:   if (!(type & LEFT))
                    146:     while (size-- > 0)
                    147:       *str++ = c;
                    148:   while (i < precision--)
                    149:     *str++ = '0';
                    150:   while (i-- > 0)
                    151:     *str++ = tmp[i];
                    152:   while (size-- > 0)
                    153:     *str++ = ' ';
                    154:   return str;
                    155: }
                    156: 
                    157: int
                    158: linux_vsprintf (char *buf, const char *fmt, va_list args)
                    159: {
                    160:   int len;
                    161:   unsigned long num;
                    162:   int i, base;
                    163:   char *str;
                    164:   const char *s;
                    165: 
                    166:   int flags;                   /* flags to number() */
                    167: 
                    168:   int field_width;             /* width of output field */
                    169:   int precision;               /* min. # of digits for integers; max
                    170:                                 * number of chars for from string
                    171:                                 */
                    172:   int qualifier;               /* 'h', 'l', or 'L' for integer fields */
                    173: 
                    174:   for (str = buf; *fmt; ++fmt)
                    175:     {
                    176:       if (*fmt != '%')
                    177:        {
                    178:          *str++ = *fmt;
                    179:          continue;
                    180:        }
                    181: 
                    182:       /* process flags */
                    183:       flags = 0;
                    184:     repeat:
                    185:       ++fmt;                   /* this also skips first '%' */
                    186:       switch (*fmt)
                    187:        {
                    188:        case '-':
                    189:          flags |= LEFT;
                    190:          goto repeat;
                    191:        case '+':
                    192:          flags |= PLUS;
                    193:          goto repeat;
                    194:        case ' ':
                    195:          flags |= SPACE;
                    196:          goto repeat;
                    197:        case '#':
                    198:          flags |= SPECIAL;
                    199:          goto repeat;
                    200:        case '0':
                    201:          flags |= ZEROPAD;
                    202:          goto repeat;
                    203:        }
                    204: 
                    205:       /* get field width */
                    206:       field_width = -1;
                    207:       if (is_digit (*fmt))
                    208:        field_width = skip_atoi (&fmt);
                    209:       else if (*fmt == '*')
                    210:        {
                    211:          ++fmt;
                    212:          /* it's the next argument */
                    213:          field_width = va_arg (args, int);
                    214:          if (field_width < 0)
                    215:            {
                    216:              field_width = -field_width;
                    217:              flags |= LEFT;
                    218:            }
                    219:        }
                    220: 
                    221:       /* get the precision */
                    222:       precision = -1;
                    223:       if (*fmt == '.')
                    224:        {
                    225:          ++fmt;
                    226:          if (is_digit (*fmt))
                    227:            precision = skip_atoi (&fmt);
                    228:          else if (*fmt == '*')
                    229:            {
                    230:              ++fmt;
                    231:              /* it's the next argument */
                    232:              precision = va_arg (args, int);
                    233:            }
                    234:          if (precision < 0)
                    235:            precision = 0;
                    236:        }
                    237: 
                    238:       /* get the conversion qualifier */
                    239:       qualifier = -1;
                    240:       if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
                    241:        {
                    242:          qualifier = *fmt;
                    243:          ++fmt;
                    244:        }
                    245: 
                    246:       /* default base */
                    247:       base = 10;
                    248: 
                    249:       switch (*fmt)
                    250:        {
                    251:        case 'c':
                    252:          if (!(flags & LEFT))
                    253:            while (--field_width > 0)
                    254:              *str++ = ' ';
                    255:          *str++ = (unsigned char) va_arg (args, int);
                    256:          while (--field_width > 0)
                    257:            *str++ = ' ';
                    258:          continue;
                    259: 
                    260:        case 's':
                    261:          s = va_arg (args, char *);
                    262:          if (!s)
                    263:            s = "<NULL>";
                    264: 
                    265:          len = strnlen (s, precision);
                    266: 
                    267:          if (!(flags & LEFT))
                    268:            while (len < field_width--)
                    269:              *str++ = ' ';
                    270:          for (i = 0; i < len; ++i)
                    271:            *str++ = *s++;
                    272:          while (len < field_width--)
                    273:            *str++ = ' ';
                    274:          continue;
                    275: 
                    276:        case 'p':
                    277:          if (field_width == -1)
                    278:            {
                    279:              field_width = 2 * sizeof (void *);
                    280:              flags |= ZEROPAD;
                    281:            }
                    282:          str = number (str,
                    283:                        (unsigned long) va_arg (args, void *), 16,
                    284:                        field_width, precision, flags);
                    285:          continue;
                    286: 
                    287: 
                    288:        case 'n':
                    289:          if (qualifier == 'l')
                    290:            {
                    291:              long *ip = va_arg (args, long *);
                    292:              *ip = (str - buf);
                    293:            }
                    294:          else
                    295:            {
                    296:              int *ip = va_arg (args, int *);
                    297:              *ip = (str - buf);
                    298:            }
                    299:          continue;
                    300: 
                    301:          /* integer number formats - set up the flags and "break" */
                    302:        case 'o':
                    303:          base = 8;
                    304:          break;
                    305: 
                    306:        case 'X':
                    307:          flags |= LARGE;
                    308:        case 'x':
                    309:          base = 16;
                    310:          break;
                    311: 
                    312:        case 'd':
                    313:        case 'i':
                    314:          flags |= SIGN;
                    315:        case 'u':
                    316:          break;
                    317: 
                    318:        default:
                    319:          if (*fmt != '%')
                    320:            *str++ = '%';
                    321:          if (*fmt)
                    322:            *str++ = *fmt;
                    323:          else
                    324:            --fmt;
                    325:          continue;
                    326:        }
                    327:       if (qualifier == 'l')
                    328:        num = va_arg (args, unsigned long);
                    329:       else if (qualifier == 'h')
                    330:        if (flags & SIGN)
1.1.1.3 ! root      331:          num = (short) va_arg (args, int);
1.1       root      332:        else
1.1.1.3 ! root      333:          num = (unsigned short) va_arg (args, unsigned int);
1.1       root      334:       else if (flags & SIGN)
                    335:        num = va_arg (args, int);
                    336:       else
                    337:        num = va_arg (args, unsigned int);
                    338:       str = number (str, num, base, field_width, precision, flags);
                    339:     }
                    340:   *str = '\0';
                    341:   return str - buf;
                    342: }
                    343: 
                    344: int
                    345: linux_sprintf (char *buf, const char *fmt,...)
                    346: {
                    347:   va_list args;
                    348:   int i;
                    349: 
                    350:   va_start (args, fmt);
                    351:   i = linux_vsprintf (buf, fmt, args);
                    352:   va_end (args);
                    353:   return i;
                    354: }

unix.superglobalmegacorp.com

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