|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.