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