Rev 8687 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 8687 | Rev 8718 | ||
---|---|---|---|
Line 11... | Line 11... | ||
11 | -%a |
11 | -%a |
12 | -can overflow unsigned as signed |
12 | -can overflow unsigned as signed |
13 | -radix point always '.', no LOCALEs |
13 | -radix point always '.', no LOCALEs |
14 | */ |
14 | */ |
Line -... | Line 15... | ||
- | 15 | ||
15 | 16 | ||
16 | #include |
17 | #include |
17 | #include |
18 | #include |
18 | #include |
19 | #include |
19 | #include |
- | |
Line -... | Line 20... | ||
- | 20 | #include |
|
- | 21 | ||
- | 22 | typedef int (*virtual_getc)(void *sp, const void *obj); |
|
- | 23 | typedef void (*virtual_ungetc)(void *sp, int c, const void *obj); |
|
- | 24 | ||
- | 25 | enum flags_t |
|
- | 26 | { |
|
- | 27 | flag_unsigned = 0x02, |
|
- | 28 | flag_register = 0x04, |
|
- | 29 | flag_plus = 0x08, |
|
- | 30 | flag_left_just = 0x10, |
|
- | 31 | flag_lead_zeros = 0x20, |
|
- | 32 | flag_space_plus = 0x40, |
|
- | 33 | flag_hash_sign = 0x80, |
|
- | 34 | flag_point = 0x100 |
|
20 | #include "format_scan.h" |
35 | }; |
21 | 36 | ||
22 | static int __try_parse_real(long double *real, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc) |
37 | int try_parse_real(long double *real, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc) |
23 | // returns 1 if OK, -1 == EOF, -2 parse broken |
38 | // returns 1 if OK, -1 == EOF, -2 parse broken |
24 | { |
39 | { |
Line 136... | Line 151... | ||
136 | *real *= pow(10,div); |
151 | *real *= pow(10, div); |
Line 137... | Line 152... | ||
137 | 152 | ||
138 | return 1; |
153 | return 1; |
Line 139... | Line 154... | ||
139 | } |
154 | } |
140 | 155 | ||
141 | static int __try_parse_int(long long *digit, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc) |
156 | int try_parse_int(long long *digit, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc) |
Line 142... | Line 157... | ||
142 | { |
157 | { |
143 | int sign = 1, base = 10, have_digits = 0; |
158 | int sign = 1, base = 10, have_digits = 0; |
Line 206... | Line 221... | ||
206 | return -2; |
221 | return -2; |
207 | } |
222 | } |
Line 208... | Line 223... | ||
208 | 223 | ||
209 | 224 | ||
210 | 225 | ||
211 | int _format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc) |
226 | int format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc) |
212 | { |
227 | { |
213 | int i; |
228 | int i; |
Line 361... | Line 376... | ||
361 | } |
376 | } |
362 | if (i < length) goto exit_me; // not enough chars |
377 | if (i < length) goto exit_me; // not enough chars |
363 | break; |
378 | break; |
364 | case 's': |
379 | case 's': |
365 | arg_str = va_arg(argp, char*); |
380 | arg_str = va_arg(argp, char*); |
366 | if (fmt1 == 0) length = STDIO_MAX_MEM; // max string scan 4096 |
381 | if (fmt1 == 0) length = 4095; // max string scan 4096 |
367 | else length = fmt1; |
382 | else length = fmt1; |
368 | for (i = 0; i < length; i++) |
383 | for (i = 0; i < length; i++) |
369 | { |
384 | { |
370 | *arg_str++ = ch; |
385 | *arg_str++ = ch; |
371 | ch = vgetc(&save, src); |
386 | ch = vgetc(&save, src); |
Line 373... | Line 388... | ||
373 | } |
388 | } |
374 | *arg_str++ = '\0'; |
389 | *arg_str++ = '\0'; |
375 | break; |
390 | break; |
376 | case 'd': case 'i': case 'u': |
391 | case 'd': case 'i': case 'u': |
377 | case 'o': case 'p': case 'x': |
392 | case 'o': case 'p': case 'x': |
378 | i = __try_parse_int(&digit, ch, src, &save, vgetc, vungetc); |
393 | i = try_parse_int(&digit, ch, src, &save, vgetc, vungetc); |
379 | if (i < 0) goto exit_me; |
394 | if (i < 0) goto exit_me; |
Line 380... | Line 395... | ||
380 | 395 | ||
381 | if (flag_long == 0) { arg_int = va_arg(argp, int*); *arg_int = (int)digit; } else |
396 | if (flag_long == 0) { arg_int = va_arg(argp, int*); *arg_int = (int)digit; } else |
382 | if (flag_long == 1) { arg_long = va_arg(argp, long*); *arg_long = (long)digit; } else |
397 | if (flag_long == 1) { arg_long = va_arg(argp, long*); *arg_long = (long)digit; } else |
383 | if (flag_long == 2) { arg_longlong = va_arg(argp, long long*); *arg_longlong = digit; } |
398 | if (flag_long == 2) { arg_longlong = va_arg(argp, long long*); *arg_longlong = digit; } |
384 | break; |
399 | break; |
385 | case 'a': case 'A': case 'f': case 'F': |
400 | case 'a': case 'A': case 'f': case 'F': |
386 | case 'e': case 'E': |
401 | case 'e': case 'E': |
387 | case 'g': case 'G': |
402 | case 'g': case 'G': |
388 | i = __try_parse_real(&real, ch, src, &save, vgetc, vungetc); |
403 | i = try_parse_real(&real, ch, src, &save, vgetc, vungetc); |
Line 389... | Line 404... | ||
389 | if (i < 0) goto exit_me; |
404 | if (i < 0) goto exit_me; |
390 | 405 | ||
391 | if (flag_long == 0) { arg_float = va_arg(argp, float*); *arg_float = (float)real; } else |
406 | if (flag_long == 0) { arg_float = va_arg(argp, float*); *arg_float = (float)real; } else |