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