diff options
Diffstat (limited to 'arch/alpha/boot/stdio.c')
-rw-r--r-- | arch/alpha/boot/stdio.c | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/arch/alpha/boot/stdio.c b/arch/alpha/boot/stdio.c new file mode 100644 index 000000000000..f844dae8a54a --- /dev/null +++ b/arch/alpha/boot/stdio.c | |||
@@ -0,0 +1,306 @@ | |||
1 | /* | ||
2 | * Copyright (C) Paul Mackerras 1997. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | #include <stdarg.h> | ||
10 | #include <stddef.h> | ||
11 | |||
12 | size_t strnlen(const char * s, size_t count) | ||
13 | { | ||
14 | const char *sc; | ||
15 | |||
16 | for (sc = s; count-- && *sc != '\0'; ++sc) | ||
17 | /* nothing */; | ||
18 | return sc - s; | ||
19 | } | ||
20 | |||
21 | # define do_div(n, base) ({ \ | ||
22 | unsigned int __base = (base); \ | ||
23 | unsigned int __rem; \ | ||
24 | __rem = ((unsigned long long)(n)) % __base; \ | ||
25 | (n) = ((unsigned long long)(n)) / __base; \ | ||
26 | __rem; \ | ||
27 | }) | ||
28 | |||
29 | |||
30 | static int skip_atoi(const char **s) | ||
31 | { | ||
32 | int i, c; | ||
33 | |||
34 | for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s) | ||
35 | i = i*10 + c - '0'; | ||
36 | return i; | ||
37 | } | ||
38 | |||
39 | #define ZEROPAD 1 /* pad with zero */ | ||
40 | #define SIGN 2 /* unsigned/signed long */ | ||
41 | #define PLUS 4 /* show plus */ | ||
42 | #define SPACE 8 /* space if plus */ | ||
43 | #define LEFT 16 /* left justified */ | ||
44 | #define SPECIAL 32 /* 0x */ | ||
45 | #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ | ||
46 | |||
47 | static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) | ||
48 | { | ||
49 | char c,sign,tmp[66]; | ||
50 | const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; | ||
51 | int i; | ||
52 | |||
53 | if (type & LARGE) | ||
54 | digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||
55 | if (type & LEFT) | ||
56 | type &= ~ZEROPAD; | ||
57 | if (base < 2 || base > 36) | ||
58 | return 0; | ||
59 | c = (type & ZEROPAD) ? '0' : ' '; | ||
60 | sign = 0; | ||
61 | if (type & SIGN) { | ||
62 | if ((signed long long)num < 0) { | ||
63 | sign = '-'; | ||
64 | num = - (signed long long)num; | ||
65 | size--; | ||
66 | } else if (type & PLUS) { | ||
67 | sign = '+'; | ||
68 | size--; | ||
69 | } else if (type & SPACE) { | ||
70 | sign = ' '; | ||
71 | size--; | ||
72 | } | ||
73 | } | ||
74 | if (type & SPECIAL) { | ||
75 | if (base == 16) | ||
76 | size -= 2; | ||
77 | else if (base == 8) | ||
78 | size--; | ||
79 | } | ||
80 | i = 0; | ||
81 | if (num == 0) | ||
82 | tmp[i++]='0'; | ||
83 | else while (num != 0) { | ||
84 | tmp[i++] = digits[do_div(num, base)]; | ||
85 | } | ||
86 | if (i > precision) | ||
87 | precision = i; | ||
88 | size -= precision; | ||
89 | if (!(type&(ZEROPAD+LEFT))) | ||
90 | while(size-->0) | ||
91 | *str++ = ' '; | ||
92 | if (sign) | ||
93 | *str++ = sign; | ||
94 | if (type & SPECIAL) { | ||
95 | if (base==8) | ||
96 | *str++ = '0'; | ||
97 | else if (base==16) { | ||
98 | *str++ = '0'; | ||
99 | *str++ = digits[33]; | ||
100 | } | ||
101 | } | ||
102 | if (!(type & LEFT)) | ||
103 | while (size-- > 0) | ||
104 | *str++ = c; | ||
105 | while (i < precision--) | ||
106 | *str++ = '0'; | ||
107 | while (i-- > 0) | ||
108 | *str++ = tmp[i]; | ||
109 | while (size-- > 0) | ||
110 | *str++ = ' '; | ||
111 | return str; | ||
112 | } | ||
113 | |||
114 | int vsprintf(char *buf, const char *fmt, va_list args) | ||
115 | { | ||
116 | int len; | ||
117 | unsigned long long num; | ||
118 | int i, base; | ||
119 | char * str; | ||
120 | const char *s; | ||
121 | |||
122 | int flags; /* flags to number() */ | ||
123 | |||
124 | int field_width; /* width of output field */ | ||
125 | int precision; /* min. # of digits for integers; max | ||
126 | number of chars for from string */ | ||
127 | int qualifier; /* 'h', 'l', or 'L' for integer fields */ | ||
128 | /* 'z' support added 23/7/1999 S.H. */ | ||
129 | /* 'z' changed to 'Z' --davidm 1/25/99 */ | ||
130 | |||
131 | |||
132 | for (str=buf ; *fmt ; ++fmt) { | ||
133 | if (*fmt != '%') { | ||
134 | *str++ = *fmt; | ||
135 | continue; | ||
136 | } | ||
137 | |||
138 | /* process flags */ | ||
139 | flags = 0; | ||
140 | repeat: | ||
141 | ++fmt; /* this also skips first '%' */ | ||
142 | switch (*fmt) { | ||
143 | case '-': flags |= LEFT; goto repeat; | ||
144 | case '+': flags |= PLUS; goto repeat; | ||
145 | case ' ': flags |= SPACE; goto repeat; | ||
146 | case '#': flags |= SPECIAL; goto repeat; | ||
147 | case '0': flags |= ZEROPAD; goto repeat; | ||
148 | } | ||
149 | |||
150 | /* get field width */ | ||
151 | field_width = -1; | ||
152 | if ('0' <= *fmt && *fmt <= '9') | ||
153 | field_width = skip_atoi(&fmt); | ||
154 | else if (*fmt == '*') { | ||
155 | ++fmt; | ||
156 | /* it's the next argument */ | ||
157 | field_width = va_arg(args, int); | ||
158 | if (field_width < 0) { | ||
159 | field_width = -field_width; | ||
160 | flags |= LEFT; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | /* get the precision */ | ||
165 | precision = -1; | ||
166 | if (*fmt == '.') { | ||
167 | ++fmt; | ||
168 | if ('0' <= *fmt && *fmt <= '9') | ||
169 | precision = skip_atoi(&fmt); | ||
170 | else if (*fmt == '*') { | ||
171 | ++fmt; | ||
172 | /* it's the next argument */ | ||
173 | precision = va_arg(args, int); | ||
174 | } | ||
175 | if (precision < 0) | ||
176 | precision = 0; | ||
177 | } | ||
178 | |||
179 | /* get the conversion qualifier */ | ||
180 | qualifier = -1; | ||
181 | if (*fmt == 'l' && *(fmt + 1) == 'l') { | ||
182 | qualifier = 'q'; | ||
183 | fmt += 2; | ||
184 | } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' | ||
185 | || *fmt == 'Z') { | ||
186 | qualifier = *fmt; | ||
187 | ++fmt; | ||
188 | } | ||
189 | |||
190 | /* default base */ | ||
191 | base = 10; | ||
192 | |||
193 | switch (*fmt) { | ||
194 | case 'c': | ||
195 | if (!(flags & LEFT)) | ||
196 | while (--field_width > 0) | ||
197 | *str++ = ' '; | ||
198 | *str++ = (unsigned char) va_arg(args, int); | ||
199 | while (--field_width > 0) | ||
200 | *str++ = ' '; | ||
201 | continue; | ||
202 | |||
203 | case 's': | ||
204 | s = va_arg(args, char *); | ||
205 | if (!s) | ||
206 | s = "<NULL>"; | ||
207 | |||
208 | len = strnlen(s, precision); | ||
209 | |||
210 | if (!(flags & LEFT)) | ||
211 | while (len < field_width--) | ||
212 | *str++ = ' '; | ||
213 | for (i = 0; i < len; ++i) | ||
214 | *str++ = *s++; | ||
215 | while (len < field_width--) | ||
216 | *str++ = ' '; | ||
217 | continue; | ||
218 | |||
219 | case 'p': | ||
220 | if (field_width == -1) { | ||
221 | field_width = 2*sizeof(void *); | ||
222 | flags |= ZEROPAD; | ||
223 | } | ||
224 | str = number(str, | ||
225 | (unsigned long) va_arg(args, void *), 16, | ||
226 | field_width, precision, flags); | ||
227 | continue; | ||
228 | |||
229 | |||
230 | case 'n': | ||
231 | if (qualifier == 'l') { | ||
232 | long * ip = va_arg(args, long *); | ||
233 | *ip = (str - buf); | ||
234 | } else if (qualifier == 'Z') { | ||
235 | size_t * ip = va_arg(args, size_t *); | ||
236 | *ip = (str - buf); | ||
237 | } else { | ||
238 | int * ip = va_arg(args, int *); | ||
239 | *ip = (str - buf); | ||
240 | } | ||
241 | continue; | ||
242 | |||
243 | case '%': | ||
244 | *str++ = '%'; | ||
245 | continue; | ||
246 | |||
247 | /* integer number formats - set up the flags and "break" */ | ||
248 | case 'o': | ||
249 | base = 8; | ||
250 | break; | ||
251 | |||
252 | case 'X': | ||
253 | flags |= LARGE; | ||
254 | case 'x': | ||
255 | base = 16; | ||
256 | break; | ||
257 | |||
258 | case 'd': | ||
259 | case 'i': | ||
260 | flags |= SIGN; | ||
261 | case 'u': | ||
262 | break; | ||
263 | |||
264 | default: | ||
265 | *str++ = '%'; | ||
266 | if (*fmt) | ||
267 | *str++ = *fmt; | ||
268 | else | ||
269 | --fmt; | ||
270 | continue; | ||
271 | } | ||
272 | if (qualifier == 'l') { | ||
273 | num = va_arg(args, unsigned long); | ||
274 | if (flags & SIGN) | ||
275 | num = (signed long) num; | ||
276 | } else if (qualifier == 'q') { | ||
277 | num = va_arg(args, unsigned long long); | ||
278 | if (flags & SIGN) | ||
279 | num = (signed long long) num; | ||
280 | } else if (qualifier == 'Z') { | ||
281 | num = va_arg(args, size_t); | ||
282 | } else if (qualifier == 'h') { | ||
283 | num = (unsigned short) va_arg(args, int); | ||
284 | if (flags & SIGN) | ||
285 | num = (signed short) num; | ||
286 | } else { | ||
287 | num = va_arg(args, unsigned int); | ||
288 | if (flags & SIGN) | ||
289 | num = (signed int) num; | ||
290 | } | ||
291 | str = number(str, num, base, field_width, precision, flags); | ||
292 | } | ||
293 | *str = '\0'; | ||
294 | return str-buf; | ||
295 | } | ||
296 | |||
297 | int sprintf(char * buf, const char *fmt, ...) | ||
298 | { | ||
299 | va_list args; | ||
300 | int i; | ||
301 | |||
302 | va_start(args, fmt); | ||
303 | i=vsprintf(buf,fmt,args); | ||
304 | va_end(args); | ||
305 | return i; | ||
306 | } | ||