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

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)
                    134:     if (base == 8)
                    135:       *str++ = '0';
                    136:     else if (base == 16)
                    137:       {
                    138:        *str++ = '0';
                    139:        *str++ = digits[33];
                    140:       }
                    141:   if (!(type & LEFT))
                    142:     while (size-- > 0)
                    143:       *str++ = c;
                    144:   while (i < precision--)
                    145:     *str++ = '0';
                    146:   while (i-- > 0)
                    147:     *str++ = tmp[i];
                    148:   while (size-- > 0)
                    149:     *str++ = ' ';
                    150:   return str;
                    151: }
                    152: 
                    153: int
                    154: linux_vsprintf (char *buf, const char *fmt, va_list args)
                    155: {
                    156:   int len;
                    157:   unsigned long num;
                    158:   int i, base;
                    159:   char *str;
                    160:   const char *s;
                    161: 
                    162:   int flags;                   /* flags to number() */
                    163: 
                    164:   int field_width;             /* width of output field */
                    165:   int precision;               /* min. # of digits for integers; max
                    166:                                 * number of chars for from string
                    167:                                 */
                    168:   int qualifier;               /* 'h', 'l', or 'L' for integer fields */
                    169: 
                    170:   for (str = buf; *fmt; ++fmt)
                    171:     {
                    172:       if (*fmt != '%')
                    173:        {
                    174:          *str++ = *fmt;
                    175:          continue;
                    176:        }
                    177: 
                    178:       /* process flags */
                    179:       flags = 0;
                    180:     repeat:
                    181:       ++fmt;                   /* this also skips first '%' */
                    182:       switch (*fmt)
                    183:        {
                    184:        case '-':
                    185:          flags |= LEFT;
                    186:          goto repeat;
                    187:        case '+':
                    188:          flags |= PLUS;
                    189:          goto repeat;
                    190:        case ' ':
                    191:          flags |= SPACE;
                    192:          goto repeat;
                    193:        case '#':
                    194:          flags |= SPECIAL;
                    195:          goto repeat;
                    196:        case '0':
                    197:          flags |= ZEROPAD;
                    198:          goto repeat;
                    199:        }
                    200: 
                    201:       /* get field width */
                    202:       field_width = -1;
                    203:       if (is_digit (*fmt))
                    204:        field_width = skip_atoi (&fmt);
                    205:       else if (*fmt == '*')
                    206:        {
                    207:          ++fmt;
                    208:          /* it's the next argument */
                    209:          field_width = va_arg (args, int);
                    210:          if (field_width < 0)
                    211:            {
                    212:              field_width = -field_width;
                    213:              flags |= LEFT;
                    214:            }
                    215:        }
                    216: 
                    217:       /* get the precision */
                    218:       precision = -1;
                    219:       if (*fmt == '.')
                    220:        {
                    221:          ++fmt;
                    222:          if (is_digit (*fmt))
                    223:            precision = skip_atoi (&fmt);
                    224:          else if (*fmt == '*')
                    225:            {
                    226:              ++fmt;
                    227:              /* it's the next argument */
                    228:              precision = va_arg (args, int);
                    229:            }
                    230:          if (precision < 0)
                    231:            precision = 0;
                    232:        }
                    233: 
                    234:       /* get the conversion qualifier */
                    235:       qualifier = -1;
                    236:       if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
                    237:        {
                    238:          qualifier = *fmt;
                    239:          ++fmt;
                    240:        }
                    241: 
                    242:       /* default base */
                    243:       base = 10;
                    244: 
                    245:       switch (*fmt)
                    246:        {
                    247:        case 'c':
                    248:          if (!(flags & LEFT))
                    249:            while (--field_width > 0)
                    250:              *str++ = ' ';
                    251:          *str++ = (unsigned char) va_arg (args, int);
                    252:          while (--field_width > 0)
                    253:            *str++ = ' ';
                    254:          continue;
                    255: 
                    256:        case 's':
                    257:          s = va_arg (args, char *);
                    258:          if (!s)
                    259:            s = "<NULL>";
                    260: 
                    261:          len = strnlen (s, precision);
                    262: 
                    263:          if (!(flags & LEFT))
                    264:            while (len < field_width--)
                    265:              *str++ = ' ';
                    266:          for (i = 0; i < len; ++i)
                    267:            *str++ = *s++;
                    268:          while (len < field_width--)
                    269:            *str++ = ' ';
                    270:          continue;
                    271: 
                    272:        case 'p':
                    273:          if (field_width == -1)
                    274:            {
                    275:              field_width = 2 * sizeof (void *);
                    276:              flags |= ZEROPAD;
                    277:            }
                    278:          str = number (str,
                    279:                        (unsigned long) va_arg (args, void *), 16,
                    280:                        field_width, precision, flags);
                    281:          continue;
                    282: 
                    283: 
                    284:        case 'n':
                    285:          if (qualifier == 'l')
                    286:            {
                    287:              long *ip = va_arg (args, long *);
                    288:              *ip = (str - buf);
                    289:            }
                    290:          else
                    291:            {
                    292:              int *ip = va_arg (args, int *);
                    293:              *ip = (str - buf);
                    294:            }
                    295:          continue;
                    296: 
                    297:          /* integer number formats - set up the flags and "break" */
                    298:        case 'o':
                    299:          base = 8;
                    300:          break;
                    301: 
                    302:        case 'X':
                    303:          flags |= LARGE;
                    304:        case 'x':
                    305:          base = 16;
                    306:          break;
                    307: 
                    308:        case 'd':
                    309:        case 'i':
                    310:          flags |= SIGN;
                    311:        case 'u':
                    312:          break;
                    313: 
                    314:        default:
                    315:          if (*fmt != '%')
                    316:            *str++ = '%';
                    317:          if (*fmt)
                    318:            *str++ = *fmt;
                    319:          else
                    320:            --fmt;
                    321:          continue;
                    322:        }
                    323:       if (qualifier == 'l')
                    324:        num = va_arg (args, unsigned long);
                    325:       else if (qualifier == 'h')
                    326:        if (flags & SIGN)
                    327:          num = va_arg (args, short);
                    328:        else
                    329:          num = va_arg (args, unsigned short);
                    330:       else if (flags & SIGN)
                    331:        num = va_arg (args, int);
                    332:       else
                    333:        num = va_arg (args, unsigned int);
                    334:       str = number (str, num, base, field_width, precision, flags);
                    335:     }
                    336:   *str = '\0';
                    337:   return str - buf;
                    338: }
                    339: 
                    340: int
                    341: linux_sprintf (char *buf, const char *fmt,...)
                    342: {
                    343:   va_list args;
                    344:   int i;
                    345: 
                    346:   va_start (args, fmt);
                    347:   i = linux_vsprintf (buf, fmt, args);
                    348:   va_end (args);
                    349:   return i;
                    350: }

unix.superglobalmegacorp.com

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