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