Chameleon

Chameleon Svn Source Tree

Root/tags/2.0/i386/modules/klibc/vsscanf.c

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

Archive Download this file

Revision: 1808