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 <linux/types.h>
14 #include <linux/string.h>
15
16
17 #define is_digit(c) ((c) >= '0' && (c) <= '9')
18
19 static int skip_atoi(const char **s)
20 {
21 int i=0;
22
23 while (is_digit(**s))
24 i = i*10 + *((*s)++) - '0';
25 return i;
26 }
27
28 #define ZEROPAD 1
29 #define SIGN 2
30 #define PLUS 4
31 #define SPACE 8
32 #define LEFT 16
33 #define SPECIAL 32
34 #define SMALL 64
35
36 #define do_div(n,base) ({ \
37 int __res; \
38 __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \
39 __res; })
40
41 static char * number(char * str, int num, int base, int size, int precision
42 ,int type)
43 {
44 char c,sign,tmp[36];
45 const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
46 int i;
47
48 if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz";
49 if (type&LEFT) type &= ~ZEROPAD;
50 if (base<2 || base>36)
51 return 0;
52 c = (type & ZEROPAD) ? '0' : ' ' ;
53 if (type&SIGN && num<0) {
54 sign='-';
55 num = -num;
56 } else
57 sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0);
58 if (sign) size--;
59 if (type&SPECIAL)
60 if (base==16) size -= 2;
61 else if (base==8) size--;
62 i=0;
63 if (num==0)
64 tmp[i++]='0';
65 else while (num!=0)
66 tmp[i++]=digits[do_div(num,base)];
67 if (i>precision) precision=i;
68 size -= precision;
69 if (!(type&(ZEROPAD+LEFT)))
70 while(size-->0)
71 *str++ = ' ';
72 if (sign)
73 *str++ = sign;
74 if (type&SPECIAL)
75 if (base==8)
76 *str++ = '0';
77 else if (base==16) {
78 *str++ = '0';
79 *str++ = digits[33];
80 }
81 if (!(type&LEFT))
82 while(size-->0)
83 *str++ = c;
84 while(i<precision--)
85 *str++ = '0';
86 while(i-->0)
87 *str++ = tmp[i];
88 while(size-->0)
89 *str++ = ' ';
90 return str;
91 }
92
93 int vsprintf(char *buf, const char *fmt, va_list args)
94 {
95 int len;
96 int i;
97 char * str;
98 char *s;
99 int *ip;
100
101 int flags;
102
103 int field_width;
104 int precision;
105
106 int qualifier;
107
108 for (str=buf ; *fmt ; ++fmt) {
109 if (*fmt != '%') {
110 *str++ = *fmt;
111 continue;
112 }
113
114
115 flags = 0;
116 repeat:
117 ++fmt;
118 switch (*fmt) {
119 case '-': flags |= LEFT; goto repeat;
120 case '+': flags |= PLUS; goto repeat;
121 case ' ': flags |= SPACE; goto repeat;
122 case '#': flags |= SPECIAL; goto repeat;
123 case '0': flags |= ZEROPAD; goto repeat;
124 }
125
126
127 field_width = -1;
128 if (is_digit(*fmt))
129 field_width = skip_atoi(&fmt);
130 else if (*fmt == '*') {
131
132 field_width = va_arg(args, int);
133 if (field_width < 0) {
134 field_width = -field_width;
135 flags |= LEFT;
136 }
137 }
138
139
140 precision = -1;
141 if (*fmt == '.') {
142 ++fmt;
143 if (is_digit(*fmt))
144 precision = skip_atoi(&fmt);
145 else if (*fmt == '*') {
146
147 precision = va_arg(args, int);
148 }
149 if (precision < 0)
150 precision = 0;
151 }
152
153
154 qualifier = -1;
155 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
156 qualifier = *fmt;
157 ++fmt;
158 }
159
160 switch (*fmt) {
161 case 'c':
162 if (!(flags & LEFT))
163 while (--field_width > 0)
164 *str++ = ' ';
165 *str++ = (unsigned char) va_arg(args, int);
166 while (--field_width > 0)
167 *str++ = ' ';
168 break;
169
170 case 's':
171 s = va_arg(args, char *);
172 len = strlen(s);
173 if (precision < 0)
174 precision = len;
175 else if (len > precision)
176 len = precision;
177
178 if (!(flags & LEFT))
179 while (len < field_width--)
180 *str++ = ' ';
181 for (i = 0; i < len; ++i)
182 *str++ = *s++;
183 while (len < field_width--)
184 *str++ = ' ';
185 break;
186
187 case 'o':
188 str = number(str, va_arg(args, unsigned long), 8,
189 field_width, precision, flags);
190 break;
191
192 case 'p':
193 if (field_width == -1) {
194 field_width = 8;
195 flags |= ZEROPAD;
196 }
197 str = number(str,
198 (unsigned long) va_arg(args, void *), 16,
199 field_width, precision, flags);
200 break;
201
202 case 'x':
203 flags |= SMALL;
204 case 'X':
205 str = number(str, va_arg(args, unsigned long), 16,
206 field_width, precision, flags);
207 break;
208
209 case 'd':
210 case 'i':
211 flags |= SIGN;
212 case 'u':
213 str = number(str, va_arg(args, unsigned long), 10,
214 field_width, precision, flags);
215 break;
216
217 case 'n':
218 ip = va_arg(args, int *);
219 *ip = (str - buf);
220 break;
221
222 default:
223 if (*fmt != '%')
224 *str++ = '%';
225 if (*fmt)
226 *str++ = *fmt;
227 else
228 --fmt;
229 break;
230 }
231 }
232 *str = '\0';
233 return str-buf;
234 }