|
|
1.1 ! root 1: /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ ! 2: /* ! 3: * Wirzenius wrote this portably, Torvalds fucked it up :-) ! 4: */ ! 5: ! 6: #include <stdarg.h> ! 7: #include <string.h> ! 8: ! 9: /* we use this so that we can do without the ctype library */ ! 10: #define is_digit(c) ((c) >= '0' && (c) <= '9') ! 11: ! 12: static int skip_atoi(const char **s) ! 13: { ! 14: int i=0; ! 15: ! 16: while (is_digit(**s)) ! 17: i = i*10 + *((*s)++) - '0'; ! 18: return i; ! 19: } ! 20: ! 21: #define ZEROPAD 1 /* pad with zero */ ! 22: #define SIGN 2 /* unsigned/signed long */ ! 23: #define PLUS 4 /* show plus */ ! 24: #define SPACE 8 /* space if plus */ ! 25: #define LEFT 16 /* left justified */ ! 26: #define SPECIAL 32 /* 0x */ ! 27: #define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */ ! 28: ! 29: #define do_div(n,base) ({ \ ! 30: int __res; \ ! 31: __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \ ! 32: __res; }) ! 33: ! 34: static char * number(char * str, int num, int base, int size, int precision ! 35: ,int type) ! 36: { ! 37: char c,sign,tmp[36]; ! 38: const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; ! 39: int i; ! 40: ! 41: if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz"; ! 42: if (type&LEFT) type &= ~ZEROPAD; ! 43: if (base<2 || base>36) ! 44: return 0; ! 45: c = (type & ZEROPAD) ? '0' : ' ' ; ! 46: if (type&SIGN && num<0) { ! 47: sign='-'; ! 48: num = -num; ! 49: } else ! 50: sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0); ! 51: if (sign) size--; ! 52: if (type&SPECIAL) ! 53: if (base==16) size -= 2; ! 54: else if (base==8) size--; ! 55: i=0; ! 56: if (num==0) ! 57: tmp[i++]='0'; ! 58: else while (num!=0) ! 59: tmp[i++]=digits[do_div(num,base)]; ! 60: if (i>precision) precision=i; ! 61: size -= precision; ! 62: if (!(type&(ZEROPAD+LEFT))) ! 63: while(size-->0) ! 64: *str++ = ' '; ! 65: if (sign) ! 66: *str++ = sign; ! 67: if (type&SPECIAL) ! 68: if (base==8) ! 69: *str++ = '0'; ! 70: else if (base==16) { ! 71: *str++ = '0'; ! 72: *str++ = digits[33]; ! 73: } ! 74: if (!(type&LEFT)) ! 75: while(size-->0) ! 76: *str++ = c; ! 77: while(i<precision--) ! 78: *str++ = '0'; ! 79: while(i-->0) ! 80: *str++ = tmp[i]; ! 81: while(size-->0) ! 82: *str++ = ' '; ! 83: return str; ! 84: } ! 85: ! 86: int vsprintf(char *buf, const char *fmt, va_list args) ! 87: { ! 88: int len; ! 89: int i; ! 90: char * str; ! 91: char *s; ! 92: int *ip; ! 93: ! 94: int flags; /* flags to number() */ ! 95: ! 96: int field_width; /* width of output field */ ! 97: int precision; /* min. # of digits for integers; max ! 98: number of chars for from string */ ! 99: int qualifier; /* 'h', 'l', or 'L' for integer fields */ ! 100: ! 101: for (str=buf ; *fmt ; ++fmt) { ! 102: if (*fmt != '%') { ! 103: *str++ = *fmt; ! 104: continue; ! 105: } ! 106: ! 107: /* process flags */ ! 108: flags = 0; ! 109: repeat: ! 110: ++fmt; /* this also skips first '%' */ ! 111: switch (*fmt) { ! 112: case '-': flags |= LEFT; goto repeat; ! 113: case '+': flags |= PLUS; goto repeat; ! 114: case ' ': flags |= SPACE; goto repeat; ! 115: case '#': flags |= SPECIAL; goto repeat; ! 116: case '0': flags |= ZEROPAD; goto repeat; ! 117: } ! 118: ! 119: /* get field width */ ! 120: field_width = -1; ! 121: if (is_digit(*fmt)) ! 122: field_width = skip_atoi(&fmt); ! 123: else if (*fmt == '*') { ! 124: /* it's the next argument */ ! 125: field_width = va_arg(args, int); ! 126: if (field_width < 0) { ! 127: field_width = -field_width; ! 128: flags |= LEFT; ! 129: } ! 130: } ! 131: ! 132: /* get the precision */ ! 133: precision = -1; ! 134: if (*fmt == '.') { ! 135: ++fmt; ! 136: if (is_digit(*fmt)) ! 137: precision = skip_atoi(&fmt); ! 138: else if (*fmt == '*') { ! 139: /* it's the next argument */ ! 140: precision = va_arg(args, int); ! 141: } ! 142: if (precision < 0) ! 143: precision = 0; ! 144: } ! 145: ! 146: /* get the conversion qualifier */ ! 147: qualifier = -1; ! 148: if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { ! 149: qualifier = *fmt; ! 150: ++fmt; ! 151: } ! 152: ! 153: switch (*fmt) { ! 154: case 'c': ! 155: if (!(flags & LEFT)) ! 156: while (--field_width > 0) ! 157: *str++ = ' '; ! 158: *str++ = (unsigned char) va_arg(args, int); ! 159: while (--field_width > 0) ! 160: *str++ = ' '; ! 161: break; ! 162: ! 163: case 's': ! 164: s = va_arg(args, char *); ! 165: len = strlen(s); ! 166: if (precision < 0) ! 167: precision = len; ! 168: else if (len > precision) ! 169: len = precision; ! 170: ! 171: if (!(flags & LEFT)) ! 172: while (len < field_width--) ! 173: *str++ = ' '; ! 174: for (i = 0; i < len; ++i) ! 175: *str++ = *s++; ! 176: while (len < field_width--) ! 177: *str++ = ' '; ! 178: break; ! 179: ! 180: case 'o': ! 181: str = number(str, va_arg(args, unsigned long), 8, ! 182: field_width, precision, flags); ! 183: break; ! 184: ! 185: case 'p': ! 186: if (field_width == -1) { ! 187: field_width = 8; ! 188: flags |= ZEROPAD; ! 189: } ! 190: str = number(str, ! 191: (unsigned long) va_arg(args, void *), 16, ! 192: field_width, precision, flags); ! 193: break; ! 194: ! 195: case 'x': ! 196: flags |= SMALL; ! 197: case 'X': ! 198: str = number(str, va_arg(args, unsigned long), 16, ! 199: field_width, precision, flags); ! 200: break; ! 201: ! 202: case 'd': ! 203: case 'i': ! 204: flags |= SIGN; ! 205: case 'u': ! 206: str = number(str, va_arg(args, unsigned long), 10, ! 207: field_width, precision, flags); ! 208: break; ! 209: ! 210: case 'n': ! 211: ip = va_arg(args, int *); ! 212: *ip = (str - buf); ! 213: break; ! 214: ! 215: default: ! 216: if (*fmt != '%') ! 217: *str++ = '%'; ! 218: if (*fmt) ! 219: *str++ = *fmt; ! 220: else ! 221: --fmt; ! 222: break; ! 223: } ! 224: } ! 225: *str = '\0'; ! 226: return str-buf; ! 227: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.