This source file includes following definitions.
- skip_atoi
- number
- vsprintf
1
2
3
4
5
6
7
8
9
10
11
12 #include <stdarg.h>
13 #include <string.h>
14
15
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
28 #define SIGN 2
29 #define PLUS 4
30 #define SPACE 8
31 #define LEFT 16
32 #define SPECIAL 32
33 #define SMALL 64
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;
101
102 int field_width;
103 int precision;
104
105 int qualifier;
106
107 for (str=buf ; *fmt ; ++fmt) {
108 if (*fmt != '%') {
109 *str++ = *fmt;
110 continue;
111 }
112
113
114 flags = 0;
115 repeat:
116 ++fmt;
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
126 field_width = -1;
127 if (is_digit(*fmt))
128 field_width = skip_atoi(&fmt);
129 else if (*fmt == '*') {
130
131 field_width = va_arg(args, int);
132 if (field_width < 0) {
133 field_width = -field_width;
134 flags |= LEFT;
135 }
136 }
137
138
139 precision = -1;
140 if (*fmt == '.') {
141 ++fmt;
142 if (is_digit(*fmt))
143 precision = skip_atoi(&fmt);
144 else if (*fmt == '*') {
145
146 precision = va_arg(args, int);
147 }
148 if (precision < 0)
149 precision = 0;
150 }
151
152
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 }