Root/
Source at commit 1444 created 12 years 11 months ago. By jrcs, Print the multiboot_magic | |
---|---|
1 | /*␊ |
2 | * vsscanf.c␊ |
3 | *␊ |
4 | * vsscanf(), from which the rest of the scanf()␊ |
5 | * family is built␊ |
6 | */␊ |
7 | ␊ |
8 | //#include "libsaio.h"␊ |
9 | //Azi: "UCHAR_MAX" & "UINT_MAX" redefined error - limits.h is also present in i386/include.␊ |
10 | #include "libsa.h"␊ |
11 | #include "limits.h"␊ |
12 | ␊ |
13 | extern uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n);␊ |
14 | ␊ |
15 | #ifndef LONG_BIT␊ |
16 | #define LONG_BIT (CHAR_BIT*sizeof(long))␊ |
17 | #endif␊ |
18 | ␊ |
19 | enum flags {␊ |
20 | ␉FL_SPLAT = 0x01,␉/* Drop the value, do not assign */␊ |
21 | ␉FL_INV = 0x02,␉/* Character-set with inverse */␊ |
22 | ␉FL_WIDTH = 0x04,␉/* Field width specified */␊ |
23 | ␉FL_MINUS = 0x08,␉/* Negative number */␊ |
24 | };␊ |
25 | ␊ |
26 | enum ranks {␊ |
27 | ␉rank_char = -2,␊ |
28 | ␉rank_short = -1,␊ |
29 | ␉rank_int = 0,␊ |
30 | ␉rank_long = 1,␊ |
31 | ␉rank_longlong = 2,␊ |
32 | ␉rank_ptr = INT_MAX␉/* Special value used for pointers */␊ |
33 | };␊ |
34 | ␊ |
35 | #define MIN_RANK␉rank_char␊ |
36 | #define MAX_RANK␉rank_longlong␊ |
37 | ␊ |
38 | #define INTMAX_RANK␉rank_longlong␊ |
39 | #define SIZE_T_RANK␉rank_long␊ |
40 | #define PTRDIFF_T_RANK␉rank_long␊ |
41 | ␊ |
42 | enum bail {␊ |
43 | ␉bail_none = 0,␉␉/* No error condition */␊ |
44 | ␉bail_eof,␉␉/* Hit EOF */␊ |
45 | ␉bail_err␉␉/* Conversion mismatch */␊ |
46 | };␊ |
47 | ␊ |
48 | static inline const char *skipspace(const char *p)␊ |
49 | {␊ |
50 | ␉while (isspace((unsigned char)*p))␊ |
51 | ␉␉p++;␊ |
52 | ␉return p;␊ |
53 | }␊ |
54 | ␊ |
55 | #undef set_bit␊ |
56 | static inline void set_bit(unsigned long *bitmap, unsigned int bit)␊ |
57 | {␊ |
58 | ␉bitmap[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);␊ |
59 | }␊ |
60 | ␊ |
61 | #undef test_bit␊ |
62 | static inline int test_bit(unsigned long *bitmap, unsigned int bit)␊ |
63 | {␊ |
64 | ␉return (int)(bitmap[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1;␊ |
65 | }␊ |
66 | ␊ |
67 | int vsscanf(const char *buffer, const char *format, va_list ap)␊ |
68 | {␊ |
69 | ␉const char *p = format;␊ |
70 | ␉char ch;␊ |
71 | ␉unsigned char uc;␊ |
72 | ␉const char *q = buffer;␊ |
73 | ␉const char *qq;␊ |
74 | ␉uintmax_t val = 0;␊ |
75 | ␉int rank = rank_int;␉/* Default rank */␊ |
76 | ␉unsigned int width = UINT_MAX;␊ |
77 | ␉int base;␊ |
78 | ␉enum flags flags = 0;␊ |
79 | ␉enum {␊ |
80 | ␉␉st_normal,␉/* Ground state */␊ |
81 | ␉␉st_flags,␉/* Special flags */␊ |
82 | ␉␉st_width,␉/* Field width */␊ |
83 | ␉␉st_modifiers,␉/* Length or conversion modifiers */␊ |
84 | ␉␉st_match_init,␉/* Initial state of %[ sequence */␊ |
85 | ␉␉st_match,␉/* Main state of %[ sequence */␊ |
86 | ␉␉st_match_range,␉/* After - in a %[ sequence */␊ |
87 | ␉} state = st_normal;␊ |
88 | ␉char *sarg = NULL;␉/* %s %c or %[ string argument */␊ |
89 | ␉enum bail bail = bail_none;␊ |
90 | ␉int sign;␊ |
91 | ␉int converted = 0;␉/* Successful conversions */␊ |
92 | ␉unsigned long matchmap[((1 << CHAR_BIT) + (LONG_BIT - 1)) / LONG_BIT];␊ |
93 | ␉int matchinv = 0;␉/* Is match map inverted? */␊ |
94 | ␉unsigned char range_start = 0;␊ |
95 | ␊ |
96 | ␉while ((ch = *p++) && !bail) {␊ |
97 | ␉␉switch (state) {␊ |
98 | ␉␉case st_normal:␊ |
99 | ␉␉␉if (ch == '%') {␊ |
100 | ␉␉␉␉state = st_flags;␊ |
101 | ␉␉␉␉flags = 0;␊ |
102 | ␉␉␉␉rank = rank_int;␊ |
103 | ␉␉␉␉width = UINT_MAX;␊ |
104 | ␉␉␉} else if (isspace((unsigned char)ch)) {␊ |
105 | ␉␉␉␉q = skipspace(q);␊ |
106 | ␉␉␉} else {␊ |
107 | ␉␉␉␉if (*q == ch)␊ |
108 | ␉␉␉␉␉q++;␊ |
109 | ␉␉␉␉else␊ |
110 | ␉␉␉␉␉bail = bail_err; /* Match failure */␊ |
111 | ␉␉␉}␊ |
112 | ␉␉␉break;␊ |
113 | ␊ |
114 | ␉␉case st_flags:␊ |
115 | ␉␉␉switch (ch) {␊ |
116 | ␉␉␉case '*':␊ |
117 | ␉␉␉␉flags |= FL_SPLAT;␊ |
118 | ␉␉␉␉break;␊ |
119 | ␉␉␉case '0'...'9':␊ |
120 | ␉␉␉␉width = (ch - '0');␊ |
121 | ␉␉␉␉state = st_width;␊ |
122 | ␉␉␉␉flags |= FL_WIDTH;␊ |
123 | ␉␉␉␉break;␊ |
124 | ␉␉␉default:␊ |
125 | ␉␉␉␉state = st_modifiers;␊ |
126 | ␉␉␉␉p--;␉/* Process this character again */␊ |
127 | ␉␉␉␉break;␊ |
128 | ␉␉␉}␊ |
129 | ␉␉␉break;␊ |
130 | ␊ |
131 | ␉␉case st_width:␊ |
132 | ␉␉␉if (ch >= '0' && ch <= '9') {␊ |
133 | ␉␉␉␉width = width * 10 + (ch - '0');␊ |
134 | ␉␉␉} else {␊ |
135 | ␉␉␉␉state = st_modifiers;␊ |
136 | ␉␉␉␉p--;␉/* Process this character again */␊ |
137 | ␉␉␉}␊ |
138 | ␉␉␉break;␊ |
139 | ␊ |
140 | ␉␉case st_modifiers:␊ |
141 | ␉␉␉switch (ch) {␊ |
142 | ␉␉␉␉/* Length modifiers - nonterminal sequences */␊ |
143 | ␉␉␉case 'h':␊ |
144 | ␉␉␉␉rank--;␉/* Shorter rank */␊ |
145 | ␉␉␉␉break;␊ |
146 | ␉␉␉case 'l':␊ |
147 | ␉␉␉␉rank++;␉/* Longer rank */␊ |
148 | ␉␉␉␉break;␊ |
149 | ␉␉␉case 'j':␊ |
150 | ␉␉␉␉rank = INTMAX_RANK;␊ |
151 | ␉␉␉␉break;␊ |
152 | ␉␉␉case 'z':␊ |
153 | ␉␉␉␉rank = SIZE_T_RANK;␊ |
154 | ␉␉␉␉break;␊ |
155 | ␉␉␉case 't':␊ |
156 | ␉␉␉␉rank = PTRDIFF_T_RANK;␊ |
157 | ␉␉␉␉break;␊ |
158 | ␉␉␉case 'L':␊ |
159 | ␉␉␉case 'q':␊ |
160 | ␉␉␉␉rank = rank_longlong;␉/* long double/long long */␊ |
161 | ␉␉␉␉break;␊ |
162 | ␊ |
163 | ␉␉␉default:␊ |
164 | ␉␉␉␉/* Output modifiers - terminal sequences */␊ |
165 | ␉␉␉␉/* Next state will be normal */␊ |
166 | ␉␉␉␉state = st_normal;␊ |
167 | ␊ |
168 | ␉␉␉␉/* Canonicalize rank */␊ |
169 | ␉␉␉␉if (rank < MIN_RANK)␊ |
170 | ␉␉␉␉␉rank = MIN_RANK;␊ |
171 | ␉␉␉␉else if (rank > MAX_RANK)␊ |
172 | ␉␉␉␉␉rank = MAX_RANK;␊ |
173 | ␊ |
174 | ␉␉␉␉switch (ch) {␊ |
175 | ␉␉␉␉case 'P':␉/* Upper case pointer */␊ |
176 | ␉␉␉␉case 'p':␉/* Pointer */␊ |
177 | ␉␉␉␉␉rank = rank_ptr;␊ |
178 | ␉␉␉␉␉base = 0;␊ |
179 | ␉␉␉␉␉sign = 0;␊ |
180 | ␉␉␉␉␉goto scan_int;␊ |
181 | ␊ |
182 | ␉␉␉␉case 'i':␉/* Base-independent integer */␊ |
183 | ␉␉␉␉␉base = 0;␊ |
184 | ␉␉␉␉␉sign = 1;␊ |
185 | ␉␉␉␉␉goto scan_int;␊ |
186 | ␊ |
187 | ␉␉␉␉case 'd':␉/* Decimal integer */␊ |
188 | ␉␉␉␉␉base = 10;␊ |
189 | ␉␉␉␉␉sign = 1;␊ |
190 | ␉␉␉␉␉goto scan_int;␊ |
191 | ␊ |
192 | ␉␉␉␉case 'o':␉/* Octal integer */␊ |
193 | ␉␉␉␉␉base = 8;␊ |
194 | ␉␉␉␉␉sign = 0;␊ |
195 | ␉␉␉␉␉goto scan_int;␊ |
196 | ␊ |
197 | ␉␉␉␉case 'u':␉/* Unsigned decimal integer */␊ |
198 | ␉␉␉␉␉base = 10;␊ |
199 | ␉␉␉␉␉sign = 0;␊ |
200 | ␉␉␉␉␉goto scan_int;␊ |
201 | ␊ |
202 | ␉␉␉␉case 'x':␉/* Hexadecimal integer */␊ |
203 | ␉␉␉␉case 'X':␊ |
204 | ␉␉␉␉␉base = 16;␊ |
205 | ␉␉␉␉␉sign = 0;␊ |
206 | ␉␉␉␉␉goto scan_int;␊ |
207 | ␊ |
208 | ␉␉␉␉case 'n':␉/* # of characters consumed */␊ |
209 | ␉␉␉␉␉val = (q - buffer);␊ |
210 | ␉␉␉␉␉goto set_integer;␊ |
211 | ␊ |
212 | ␉␉␉␉ scan_int:␊ |
213 | ␉␉␉␉␉q = skipspace(q);␊ |
214 | ␉␉␉␉␉if (!*q) {␊ |
215 | ␉␉␉␉␉␉bail = bail_eof;␊ |
216 | ␉␉␉␉␉␉break;␊ |
217 | ␉␉␉␉␉}␊ |
218 | ␉␉␉␉␉val =␊ |
219 | ␉␉␉␉␉ strntoumax(q, (char **)&qq, base,␊ |
220 | ␉␉␉␉␉␉ width);␊ |
221 | ␉␉␉␉␉if (qq == q) {␊ |
222 | ␉␉␉␉␉␉bail = bail_err;␊ |
223 | ␉␉␉␉␉␉break;␊ |
224 | ␉␉␉␉␉}␊ |
225 | ␉␉␉␉␉q = qq;␊ |
226 | ␉␉␉␉␉if (!(flags & FL_SPLAT))␊ |
227 | ␉␉␉␉␉␉converted++;␊ |
228 | ␉␉␉␉␉/* fall through */␊ |
229 | ␊ |
230 | ␉␉␉␉ set_integer:␊ |
231 | ␉␉␉␉␉if (!(flags & FL_SPLAT)) {␊ |
232 | ␉␉␉␉␉␉switch (rank) {␊ |
233 | ␉␉␉␉␉␉case rank_char:␊ |
234 | ␉␉␉␉␉␉␉*va_arg(ap,␊ |
235 | ␉␉␉␉␉␉␉␉unsigned char *)␊ |
236 | ␉␉␉␉␉␉␉␉= val;␊ |
237 | ␉␉␉␉␉␉␉break;␊ |
238 | ␉␉␉␉␉␉case rank_short:␊ |
239 | ␉␉␉␉␉␉␉*va_arg(ap,␊ |
240 | ␉␉␉␉␉␉␉␉unsigned short␊ |
241 | ␉␉␉␉␉␉␉␉*) = val;␊ |
242 | ␉␉␉␉␉␉␉break;␊ |
243 | ␉␉␉␉␉␉case rank_int:␊ |
244 | ␉␉␉␉␉␉␉*va_arg(ap,␊ |
245 | ␉␉␉␉␉␉␉␉unsigned int *)␊ |
246 | ␉␉␉␉␉␉␉ = val;␊ |
247 | ␉␉␉␉␉␉␉break;␊ |
248 | ␉␉␉␉␉␉case rank_long:␊ |
249 | ␉␉␉␉␉␉␉*va_arg(ap,␊ |
250 | ␉␉␉␉␉␉␉␉unsigned long *)␊ |
251 | ␉␉␉␉␉␉␉␉= val;␊ |
252 | ␉␉␉␉␉␉␉break;␊ |
253 | ␉␉␉␉␉␉case rank_longlong:␊ |
254 | ␉␉␉␉␉␉␉*va_arg(ap,␊ |
255 | ␉␉␉␉␉␉␉␉unsigned long␊ |
256 | ␉␉␉␉␉␉␉␉long *) = val;␊ |
257 | ␉␉␉␉␉␉␉break;␊ |
258 | ␉␉␉␉␉␉case rank_ptr:␊ |
259 | ␉␉␉␉␉␉␉*va_arg(ap, void **) =␊ |
260 | ␉␉␉␉␉␉␉␉(void *)␊ |
261 | ␉␉␉␉␉␉␉␉(uintptr_t)val;␊ |
262 | ␉␉␉␉␉␉␉break;␊ |
263 | ␉␉␉␉␉␉}␊ |
264 | ␉␉␉␉␉}␊ |
265 | ␉␉␉␉␉break;␊ |
266 | ␊ |
267 | ␉␉␉␉case 'c':␉/* Character */␊ |
268 | ␉␉␉␉␉/* Default width == 1 */␊ |
269 | ␉␉␉␉␉width = (flags & FL_WIDTH) ? width : 1;␊ |
270 | ␉␉␉␉␉if (flags & FL_SPLAT) {␊ |
271 | ␉␉␉␉␉␉while (width--) {␊ |
272 | ␉␉␉␉␉␉␉if (!*q) {␊ |
273 | ␉␉␉␉␉␉␉␉bail = bail_eof;␊ |
274 | ␉␉␉␉␉␉␉␉break;␊ |
275 | ␉␉␉␉␉␉␉}␊ |
276 | ␉␉␉␉␉␉}␊ |
277 | ␉␉␉␉␉} else {␊ |
278 | ␉␉␉␉␉␉sarg = va_arg(ap, char *);␊ |
279 | ␉␉␉␉␉␉while (width--) {␊ |
280 | ␉␉␉␉␉␉␉if (!*q) {␊ |
281 | ␉␉␉␉␉␉␉␉bail = bail_eof;␊ |
282 | ␉␉␉␉␉␉␉␉break;␊ |
283 | ␉␉␉␉␉␉␉}␊ |
284 | ␉␉␉␉␉␉␉*sarg++ = *q++;␊ |
285 | ␉␉␉␉␉␉}␊ |
286 | ␉␉␉␉␉␉if (!bail)␊ |
287 | ␉␉␉␉␉␉␉converted++;␊ |
288 | ␉␉␉␉␉}␊ |
289 | ␉␉␉␉␉break;␊ |
290 | ␊ |
291 | ␉␉␉␉case 's':␉/* String */␊ |
292 | ␉␉␉␉␉uc = 1;␉/* Anything nonzero */␊ |
293 | ␉␉␉␉␉if (flags & FL_SPLAT) {␊ |
294 | ␉␉␉␉␉␉while (width-- && (uc = *q) &&␊ |
295 | ␉␉␉␉␉␉ !isspace(uc)) {␊ |
296 | ␉␉␉␉␉␉␉q++;␊ |
297 | ␉␉␉␉␉␉}␊ |
298 | ␉␉␉␉␉} else {␊ |
299 | ␉␉␉␉␉␉char *sp;␊ |
300 | ␉␉␉␉␉␉sp = sarg = va_arg(ap, char *);␊ |
301 | ␉␉␉␉␉␉while (width-- && (uc = *q) &&␊ |
302 | ␉␉␉␉␉␉ !isspace(uc)) {␊ |
303 | ␉␉␉␉␉␉␉*sp++ = uc;␊ |
304 | ␉␉␉␉␉␉␉q++;␊ |
305 | ␉␉␉␉␉␉}␊ |
306 | ␉␉␉␉␉␉if (sarg != sp) {␊ |
307 | ␉␉␉␉␉␉␉/* Terminate output */␊ |
308 | ␉␉␉␉␉␉␉*sp = '\0';␊ |
309 | ␉␉␉␉␉␉␉converted++;␊ |
310 | ␉␉␉␉␉␉}␊ |
311 | ␉␉␉␉␉}␊ |
312 | ␉␉␉␉␉if (!uc)␊ |
313 | ␉␉␉␉␉␉bail = bail_eof;␊ |
314 | ␉␉␉␉␉break;␊ |
315 | ␊ |
316 | ␉␉␉␉case '[':␉/* Character range */␊ |
317 | ␉␉␉␉␉sarg = (flags & FL_SPLAT) ? NULL␊ |
318 | ␉␉␉␉␉␉: va_arg(ap, char *);␊ |
319 | ␉␉␉␉␉state = st_match_init;␊ |
320 | ␉␉␉␉␉matchinv = 0;␊ |
321 | ␉␉␉␉␉memset(matchmap, 0, sizeof matchmap);␊ |
322 | ␉␉␉␉␉break;␊ |
323 | ␊ |
324 | ␉␉␉␉case '%':␉/* %% sequence */␊ |
325 | ␉␉␉␉␉if (*q == '%')␊ |
326 | ␉␉␉␉␉␉q++;␊ |
327 | ␉␉␉␉␉else␊ |
328 | ␉␉␉␉␉␉bail = bail_err;␊ |
329 | ␉␉␉␉␉break;␊ |
330 | ␊ |
331 | ␉␉␉␉default:␉/* Anything else */␊ |
332 | ␉␉␉␉␉/* Unknown sequence */␊ |
333 | ␉␉␉␉␉bail = bail_err;␊ |
334 | ␉␉␉␉␉break;␊ |
335 | ␉␉␉␉}␊ |
336 | ␉␉␉}␊ |
337 | ␉␉␉break;␊ |
338 | ␊ |
339 | ␉␉case st_match_init:␉/* Initial state for %[ match */␊ |
340 | ␉␉␉if (ch == '^' && !(flags & FL_INV)) {␊ |
341 | ␉␉␉␉matchinv = 1;␊ |
342 | ␉␉␉} else {␊ |
343 | ␉␉␉␉set_bit(matchmap, (unsigned char)ch);␊ |
344 | ␉␉␉␉state = st_match;␊ |
345 | ␉␉␉}␊ |
346 | ␉␉␉break;␊ |
347 | ␊ |
348 | ␉␉case st_match:␉/* Main state for %[ match */␊ |
349 | ␉␉␉if (ch == ']') {␊ |
350 | ␉␉␉␉goto match_run;␊ |
351 | ␉␉␉} else if (ch == '-') {␊ |
352 | ␉␉␉␉range_start = (unsigned char)ch;␊ |
353 | ␉␉␉␉state = st_match_range;␊ |
354 | ␉␉␉} else {␊ |
355 | ␉␉␉␉set_bit(matchmap, (unsigned char)ch);␊ |
356 | ␉␉␉}␊ |
357 | ␉␉␉break;␊ |
358 | ␊ |
359 | ␉␉case st_match_range:␉/* %[ match after - */␊ |
360 | ␉␉␉if (ch == ']') {␊ |
361 | ␉␉␉␉/* - was last character */␊ |
362 | ␉␉␉␉set_bit(matchmap, (unsigned char)'-');␊ |
363 | ␉␉␉␉goto match_run;␊ |
364 | ␉␉␉} else {␊ |
365 | ␉␉␉␉int i;␊ |
366 | ␉␉␉␉for (i = range_start; i < (unsigned char)ch;␊ |
367 | ␉␉␉␉ i++)␊ |
368 | ␉␉␉␉␉set_bit(matchmap, i);␊ |
369 | ␉␉␉␉state = st_match;␊ |
370 | ␉␉␉}␊ |
371 | ␉␉␉break;␊ |
372 | ␊ |
373 | ␉␉ match_run:␉/* Match expression finished */␊ |
374 | ␉␉␉qq = q;␊ |
375 | ␉␉␉uc = 1;␉/* Anything nonzero */␊ |
376 | ␉␉␉while (width && (uc = *q)␊ |
377 | ␉␉␉ && test_bit(matchmap, uc)^matchinv) {␊ |
378 | ␉␉␉␉if (sarg)␊ |
379 | ␉␉␉␉␉*sarg++ = uc;␊ |
380 | ␉␉␉␉q++;␊ |
381 | ␉␉␉}␊ |
382 | ␉␉␉if (q != qq && sarg) {␊ |
383 | ␉␉␉␉*sarg = '\0';␊ |
384 | ␉␉␉␉converted++;␊ |
385 | ␉␉␉} else {␊ |
386 | ␉␉␉␉bail = bail_err;␊ |
387 | ␉␉␉}␊ |
388 | ␉␉␉if (!uc)␊ |
389 | ␉␉␉␉bail = bail_eof;␊ |
390 | ␉␉␉break;␊ |
391 | ␉␉}␊ |
392 | ␉}␊ |
393 | ␊ |
394 | ␉if (bail == bail_eof && !converted)␊ |
395 | ␉␉converted = -1;␉/* Return EOF (-1) */␊ |
396 | ␊ |
397 | ␉return converted;␊ |
398 | }␊ |
399 |