Annotation of Gnu-Mach/linux/dev/lib/vsprintf.c, revision 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.