Chameleon

Chameleon Svn Source Tree

Root/branches/meklortOld/i386/modules/klibc/vsscanf.c

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

Archive Download this file

Revision: 1146