OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libc/] [stdio/] [scanf.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/*  Copyright (C) 2002, 2003     Manuel Novoa III
2
 *
3
 *  This library is free software; you can redistribute it and/or
4
 *  modify it under the terms of the GNU Library General Public
5
 *  License as published by the Free Software Foundation; either
6
 *  version 2 of the License, or (at your option) any later version.
7
 *
8
 *  This library is distributed in the hope that it will be useful,
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
 *  Library General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU Library General Public
14
 *  License along with this library; if not, write to the Free
15
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
 */
17
 
18
/* Aug 1, 2003
19
 * New *scanf implementation with lots of bug fixes and *wscanf support.
20
 * Also now optionally supports hexadecimal float notation, positional
21
 * args, and glibc locale-specific digit grouping.  Should now be
22
 * standards compliant.
23
 *
24
 * Aug 18, 2003
25
 * Bug fix: scanf %lc,%ls,%l[ would always set mb_fail on eof or error,
26
 *   even when just starting a new mb char.
27
 * Bug fix: wscanf would incorrectly unget in certain situations.
28
 *
29
 * Sep 5, 2003
30
 * Bug fix: store flag wasn't respected if no positional args.
31
 * Implement vs{n}scanf for the non-buffered stdio no-wchar case.
32
 *
33
 * Sep 13, 2003
34
 * Bug fix: Fix a problem reported by Atsushi Nemoto <anemo@mba.ocn.ne.jp>
35
 * for environments where long and long long are the same.
36
 *
37
 * Sep 21, 2003
38
 * Ugh... EOF handling by scanf was completely broken.  :-(  Regretably,
39
 * I got my mind fixed in one mode and didn't comply with the standards.
40
 * Things should be fixed now, but comparision testing is difficult when
41
 * glibc's scanf is broken and they stubbornly refuse to even acknowledge
42
 * that it is... even when confronted by specific examples from the C99
43
 * standards and from an official C standard defect report.
44
 */
45
 
46
 
47
#define _ISOC99_SOURCE                  /* for LLONG_MAX primarily... */
48
#define _GNU_SOURCE
49
#define _STDIO_UTILITY
50
#include <features.h>
51
#include <stdio.h>
52
#include <stdlib.h>
53
#include <unistd.h>
54
#include <ctype.h>
55
#include <string.h>
56
#include <stdarg.h>
57
#include <stdint.h>
58
#include <errno.h>
59
#include <printf.h>
60
 
61
#ifdef __UCLIBC_HAS_WCHAR__
62
#include <bits/uClibc_uwchar.h>
63
#include <wchar.h>
64
#include <wctype.h>
65
#endif /* __UCLIBC_HAS_WCHAR__ */
66
 
67
#include <langinfo.h>
68
#include <locale.h>
69
 
70
#include <assert.h>
71
#include <limits.h>
72
 
73
#ifdef __STDIO_THREADSAFE
74
#include <stdio_ext.h>
75
#include <pthread.h>
76
#endif /* __STDIO_THREADSAFE */
77
 
78
#ifdef __UCLIBC_HAS_FLOATS__
79
#include <float.h>
80
#include <bits/uClibc_fpmax.h>
81
#endif /* __UCLIBC_HAS_FLOATS__ */
82
 
83
#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
84
#ifdef L_vfscanf
85
/* only emit this once */
86
#warning Forcing undef of __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ until implemented!
87
#endif
88
#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
89
#endif
90
 
91
#undef __STDIO_HAS_VSSCANF
92
#if defined(__STDIO_BUFFERS) || !defined(__UCLIBC_HAS_WCHAR__) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
93
#define __STDIO_HAS_VSSCANF 1
94
 
95
#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__)
96
typedef struct {
97
        FILE f;
98
        unsigned char *bufread;         /* pointer to 1 past end of buffer */
99
        unsigned char *bufpos;
100
} __FILE_vsscanf;
101
#endif
102
 
103
#endif
104
 
105
extern void _store_inttype(void *dest, int desttype, uintmax_t val);
106
 
107
#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
108
 
109
extern unsigned long long
110
_stdlib_strto_ll(register const char * __restrict str,
111
                                 char ** __restrict endptr, int base, int sflag);
112
#if (ULLONG_MAX == UINTMAX_MAX)
113
#define STRTOUIM(s,e,b,sf) _stdlib_strto_ll(s,e,b,sf)
114
#endif
115
 
116
#else  /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
117
 
118
extern unsigned long
119
_stdlib_strto_l(register const char * __restrict str,
120
                                char ** __restrict endptr, int base, int sflag);
121
 
122
#if (ULONG_MAX == UINTMAX_MAX)
123
#define STRTOUIM(s,e,b,sf) _stdlib_strto_l(s,e,b,sf)
124
#endif
125
 
126
#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
127
 
128
#ifndef STRTOUIM
129
#error STRTOUIM conversion function is undefined!
130
#endif
131
 
132
/**********************************************************************/
133
 
134
/* The standards require EOF < 0. */
135
#if EOF >= CHAR_MIN
136
#define __isdigit_char_or_EOF(C)   __isdigit_char((C))
137
#else
138
#define __isdigit_char_or_EOF(C)   __isdigit_int((C))
139
#endif
140
 
141
/**********************************************************************/
142
#ifdef L_fscanf
143
 
144
int fscanf(FILE * __restrict stream, const char * __restrict format, ...)
145
{
146
        va_list arg;
147
        int rv;
148
 
149
        va_start(arg, format);
150
        rv = vfscanf(stream, format, arg);
151
        va_end(arg);
152
 
153
        return rv;
154
}
155
 
156
#endif
157
/**********************************************************************/
158
#ifdef L_scanf
159
 
160
int scanf(const char * __restrict format, ...)
161
{
162
        va_list arg;
163
        int rv;
164
 
165
        va_start(arg, format);
166
        rv = vfscanf(stdin, format, arg);
167
        va_end(arg);
168
 
169
        return rv;
170
}
171
 
172
#endif
173
/**********************************************************************/
174
#ifdef L_sscanf
175
 
176
#ifdef __STDIO_HAS_VSSCANF
177
 
178
int sscanf(const char * __restrict str, const char * __restrict format, ...)
179
{
180
        va_list arg;
181
        int rv;
182
 
183
        va_start(arg, format);
184
        rv = vsscanf(str, format, arg);
185
        va_end(arg);
186
 
187
        return rv;
188
}
189
 
190
#else  /* __STDIO_HAS_VSSCANF */
191
#warning Skipping sscanf since no vsscanf!
192
#endif /* __STDIO_HAS_VSSCANF */
193
 
194
#endif
195
/**********************************************************************/
196
#ifdef L_vscanf
197
 
198
int vscanf(const char * __restrict format, va_list arg)
199
{
200
        return vfscanf(stdin, format, arg);
201
}
202
 
203
#endif
204
/**********************************************************************/
205
#ifdef L_vsscanf
206
 
207
#ifdef __UCLIBC_MJN3_ONLY__
208
#warning WISHLIST: Implement vsscanf for non-buffered and no custom stream case.
209
#endif /* __UCLIBC_MJN3_ONLY__ */
210
 
211
#ifdef __STDIO_BUFFERS
212
 
213
int vsscanf(__const char *sp, __const char *fmt, va_list ap)
214
{
215
        FILE string[1];
216
 
217
        string->filedes = -2;
218
        string->modeflags = (__FLAG_NARROW|__FLAG_READONLY);
219
        string->bufstart = string->bufpos = (unsigned char *) ((void *) sp);
220
#ifdef __STDIO_GETC_MACRO
221
        string->bufgetc =
222
#endif /* __STDIO_GETC_MACRO */
223
        string->bufread = string->bufstart + strlen(sp);
224
 
225
#ifdef __STDIO_MBSTATE
226
        __INIT_MBSTATE(&(string->state));
227
#endif /* __STDIO_MBSTATE */
228
 
229
#ifdef __STDIO_THREADSAFE
230
        string->user_locking = 0;
231
        __stdio_init_mutex(&string->lock);
232
#endif
233
 
234
        return vfscanf(string, fmt, ap);
235
}
236
 
237
#elif !defined(__UCLIBC_HAS_WCHAR__)
238
 
239
int vsscanf(__const char *sp, __const char *fmt, va_list ap)
240
{
241
        __FILE_vsscanf string[1];
242
 
243
        string->f.filedes = -2;
244
        string->f.modeflags = (__FLAG_NARROW|__FLAG_READONLY);
245
        string->bufpos = (unsigned char *) ((void *) sp);
246
        string->bufread = string->bufpos + strlen(sp);
247
 
248
#ifdef __STDIO_MBSTATE
249
#error __STDIO_MBSTATE is defined!
250
#endif /* __STDIO_MBSTATE */
251
 
252
#ifdef __STDIO_THREADSAFE
253
        string->user_locking = 0;
254
        __stdio_init_mutex(&string->f.lock);
255
#endif
256
 
257
        return vfscanf(&string->f, fmt, ap);
258
}
259
 
260
#elif defined(__STDIO_GLIBC_CUSTOM_STREAMS)
261
 
262
int vsscanf(__const char *sp, __const char *fmt, va_list ap)
263
{
264
        FILE *f;
265
        int rv;
266
 
267
        if ((f = fmemopen((char *)sp, strlen(sp), "r")) == NULL) {
268
                return -1;
269
        }
270
        rv = vfscanf(f, fmt, ap);
271
        fclose(f);
272
 
273
        return rv;
274
}
275
 
276
#else
277
#warning Skipping vsscanf since no buffering, no custom streams, and wchar enabled!
278
#ifdef __STDIO_HAS_VSSCANF
279
#error WHOA! __STDIO_HAS_VSSCANF is defined!
280
#endif
281
#endif
282
 
283
#endif
284
/**********************************************************************/
285
#ifdef L_fwscanf
286
 
287
int fwscanf(FILE * __restrict stream, const wchar_t * __restrict format, ...)
288
{
289
        va_list arg;
290
        int rv;
291
 
292
        va_start(arg, format);
293
        rv = vfwscanf(stream, format, arg);
294
        va_end(arg);
295
 
296
        return rv;
297
}
298
 
299
#endif
300
/**********************************************************************/
301
#ifdef L_wscanf
302
 
303
int wscanf(const wchar_t * __restrict format, ...)
304
{
305
        va_list arg;
306
        int rv;
307
 
308
        va_start(arg, format);
309
        rv = vfwscanf(stdin, format, arg);
310
        va_end(arg);
311
 
312
        return rv;
313
}
314
 
315
#endif
316
/**********************************************************************/
317
#ifdef L_swscanf
318
 
319
#ifdef __STDIO_BUFFERS
320
 
321
int swscanf(const wchar_t * __restrict str, const wchar_t * __restrict format,
322
                   ...)
323
{
324
        va_list arg;
325
        int rv;
326
 
327
        va_start(arg, format);
328
        rv = vswscanf(str, format, arg);
329
        va_end(arg);
330
 
331
        return rv;
332
}
333
#else  /* __STDIO_BUFFERS */
334
#warning Skipping swscanf since no buffering!
335
#endif /* __STDIO_BUFFERS */
336
 
337
#endif
338
/**********************************************************************/
339
#ifdef L_vwscanf
340
 
341
int vwscanf(const wchar_t * __restrict format, va_list arg)
342
{
343
        return vfwscanf(stdin, format, arg);
344
}
345
 
346
#endif
347
/**********************************************************************/
348
#ifdef L_vswscanf
349
 
350
#ifdef __STDIO_BUFFERS
351
 
352
int vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict format,
353
                        va_list arg)
354
{
355
        FILE f;
356
 
357
        f.filedes = -3;                         /* FAKE STREAM TO SUPPORT *wscanf! */
358
        f.modeflags = (__FLAG_WIDE|__FLAG_READONLY|__FLAG_READING);
359
        f.bufpos = (char *) str;
360
        f.bufend = (char *)(str + wcslen(str));
361
        f.ungot_width[0] = 0;
362
#ifdef __STDIO_THREADSAFE
363
        f.user_locking = 0;
364
        __stdio_init_mutex(&f.lock);
365
#endif
366
 
367
 
368
        return vfwscanf(&f, format, arg);
369
}
370
#else  /* __STDIO_BUFFERS */
371
#warning Skipping vswscanf since no buffering!
372
#endif /* __STDIO_BUFFERS */
373
 
374
#endif
375
/**********************************************************************/
376
/**********************************************************************/
377
 
378
 
379
 
380
/* float layout          0123456789012345678901  repeat n for "l[" */
381
#define SPEC_CHARS              "npxXoudifFeEgGaACSncs["
382
/*                       npxXoudif eEgG  CS cs[ */
383
 
384
/* NOTE: Ordering is important!  In particular, CONV_LEFTBRACKET
385
 * must immediately precede CONV_c. */
386
 
387
enum {
388
        CONV_n = 0,
389
        CONV_p,
390
        CONV_x, CONV_X, CONV_o, CONV_u, CONV_d, CONV_i,
391
        CONV_f, CONV_F, CONV_e, CONV_E, CONV_g, CONV_G, CONV_a, CONV_A,
392
        CONV_C, CONV_S, CONV_LEFTBRACKET, CONV_c, CONV_s, CONV_leftbracket,
393
        CONV_percent, CONV_whitespace /* not in SPEC_* and no flags */
394
};
395
 
396
#ifdef __UCLIBC_HAS_FLOATS__
397
#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
398
/*                         p   x   X  o   u   d   i   f   F   e   E   g   G   a   A */
399
#define SPEC_BASE               { 16, 16, 16, 8, 10, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0 }
400
#else
401
/*                         p   x   X  o   u   d   i   f   F   e   E   g   G   a   A */
402
#define SPEC_BASE               { 16, 16, 16, 8, 10, 10,  0, 10, 10, 10, 10, 10, 10, 10, 10 }
403
#endif
404
#else  /* __UCLIBC_HAS_FLOATS__ */
405
/*                         p   x   X  o   u   d   i   f   F   e   E   g   G   a   A */
406
#define SPEC_BASE               { 16, 16, 16, 8, 10, 10,  0 }
407
#endif /* __UCLIBC_HAS_FLOATS__ */
408
 
409
#ifdef __UCLIBC_MJN3_ONLY__
410
#ifdef L_vfscanf
411
/* emit once */
412
#warning CONSIDER: Add a '0' flag to eat 0 padding when grouping?
413
#endif
414
#endif /* __UCLIBC_MJN3_ONLY__ */
415
 
416
#define SPEC_FLAGS              "*'I"
417
 
418
enum {
419
        FLAG_SURPRESS   =   0x10,       /* MUST BE 1ST!!  See DO_FLAGS. */
420
        FLAG_THOUSANDS  =       0x20,
421
        FLAG_I18N               =       0x40,   /* only works for d, i, u */
422
        FLAG_MALLOC     =   0x80,       /* only works for s, S, and [ (and l[)*/
423
};
424
 
425
 
426
#define SPEC_RANGES             { CONV_n, CONV_p, CONV_i, CONV_A, \
427
                                                  CONV_C, CONV_LEFTBRACKET, \
428
                                                  CONV_c, CONV_leftbracket }
429
 
430
/* Note: We treat L and ll as synonymous... for ints and floats. */
431
 
432
#define SPEC_ALLOWED_FLAGS              { \
433
        /* n */                 (0x0f|FLAG_SURPRESS), \
434
        /* p */                 (   0|FLAG_SURPRESS), \
435
        /* oxXudi */    (0x0f|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \
436
        /* fFeEgGaA */  (0x0c|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \
437
        /* C */                 (   0|FLAG_SURPRESS), \
438
        /* S and l[ */  (   0|FLAG_SURPRESS|FLAG_MALLOC), \
439
        /* c */                 (0x04|FLAG_SURPRESS), \
440
        /* s and [ */   (0x04|FLAG_SURPRESS|FLAG_MALLOC), \
441
}
442
 
443
 
444
/**********************************************************************/
445
/*
446
 * In order to ease translation to what arginfo and _print_info._flags expect,
447
 * we map:  0:int  1:char  2:longlong 4:long  8:short
448
 * and then _flags |= (((q << 7) + q) & 0x701) and argtype |= (_flags & 0x701)
449
 */
450
 
451
/* TODO -- Fix the table below to take into account stdint.h. */
452
/*  #ifndef LLONG_MAX */
453
/*  #error fix QUAL_CHARS for no long long!  Affects 'L', 'j', 'q', 'll'. */
454
/*  #else */
455
/*  #if LLONG_MAX != INTMAX_MAX */
456
/*  #error fix QUAL_CHARS intmax_t entry 'j'! */
457
/*  #endif */
458
/*  #endif */
459
 
460
#ifdef PDS
461
#error PDS already defined!
462
#endif
463
#ifdef SS
464
#error SS already defined!
465
#endif
466
#ifdef IMS
467
#error IMS already defined!
468
#endif
469
 
470
#if PTRDIFF_MAX == INT_MAX
471
#define PDS             0
472
#elif PTRDIFF_MAX == LONG_MAX
473
#define PDS             4
474
#elif defined(LLONG_MAX) && (PTRDIFF_MAX == LLONG_MAX)
475
#define PDS             8
476
#else
477
#error fix QUAL_CHARS ptrdiff_t entry 't'!
478
#endif
479
 
480
#if SIZE_MAX == UINT_MAX
481
#define SS              0
482
#elif SIZE_MAX == ULONG_MAX
483
#define SS              4
484
#elif defined(LLONG_MAX) && (SIZE_MAX == ULLONG_MAX)
485
#define SS              8
486
#else
487
#error fix QUAL_CHARS size_t entries 'z', 'Z'!
488
#endif
489
 
490
#if INTMAX_MAX == INT_MAX
491
#define IMS             0
492
#elif INTMAX_MAX == LONG_MAX
493
#define IMS             4
494
#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX)
495
#define IMS             8
496
#else
497
#error fix QUAL_CHARS ptrdiff_t entry 't'!
498
#endif
499
 
500
#define QUAL_CHARS              { \
501
        /* j:(u)intmax_t z:(s)size_t  t:ptrdiff_t  \0:int  q:long_long */ \
502
        'h',   'l',  'L',  'j',  'z',  't',  'q', 0, \
503
         2,     4,    8,  IMS,   SS,  PDS,    8,  0, /* TODO -- fix!!! */\
504
     1,     8   }
505
 
506
 
507
/**********************************************************************/
508
 
509
#ifdef L_vfwscanf
510
#if WINT_MIN > EOF
511
#error Unfortunately, we currently need wint_t to be able to store EOF.  Sorry.
512
#endif
513
#define W_EOF WEOF
514
#define Wint wint_t
515
#define Wchar wchar_t
516
#define Wuchar __uwchar_t
517
#define ISSPACE(C) iswspace((C))
518
#define VFSCANF vfwscanf
519
#define GETC(SC) (SC)->sc_getc((SC))
520
#else
521
typedef unsigned char __uchar_t;
522
#define W_EOF EOF
523
#define Wint int
524
#define Wchar char
525
#define Wuchar __uchar_t
526
#define ISSPACE(C) isspace((C))
527
#define VFSCANF vfscanf
528
#ifdef __UCLIBC_HAS_WCHAR__
529
#define GETC(SC) (SC)->sc_getc((SC))
530
#else  /* __UCLIBC_HAS_WCHAR__ */
531
#define GETC(SC) getc_unlocked((SC)->fp)
532
#endif /* __UCLIBC_HAS_WCHAR__ */
533
#endif
534
 
535
struct scan_cookie {
536
        Wint cc;
537
        Wint ungot_char;
538
        FILE *fp;
539
        int nread;
540
        int width;
541
 
542
#ifdef __UCLIBC_HAS_WCHAR__
543
        wchar_t app_ungot;                      /* Match FILE struct member type. */
544
        unsigned char ungot_wchar_width;
545
#else  /* __UCLIBC_HAS_WCHAR__ */
546
        unsigned char app_ungot;        /* Match FILE struct member type. */
547
#endif /* __UCLIBC_HAS_WCHAR__ */
548
 
549
        char ungot_flag;
550
 
551
#ifdef __UCLIBC_HAS_WCHAR__
552
        char ungot_wflag;                       /* vfwscanf */
553
        char mb_fail;                           /* vfscanf */
554
        mbstate_t mbstate;                      /* vfscanf */
555
        wint_t wc;
556
        wint_t ungot_wchar;                     /* to support __scan_getc */
557
        int (*sc_getc)(struct scan_cookie *);
558
#endif /* __UCLIBC_HAS_WCHAR__ */
559
 
560
#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__
561
        const char *grouping;
562
        const unsigned char *thousands_sep;
563
        int tslen;
564
#ifdef __UCLIBC_HAS_WCHAR__
565
        wchar_t thousands_sep_wc;
566
#endif /* __UCLIBC_HAS_WCHAR__ */
567
#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */
568
 
569
#ifdef __UCLIBC_HAS_FLOATS__
570
        const unsigned char *decpt;
571
        int decpt_len;
572
#ifdef __UCLIBC_HAS_WCHAR__
573
        wchar_t decpt_wc;
574
#endif /* __UCLIBC_HAS_WCHAR__ */
575
        const unsigned char *fake_decpt;
576
#endif /* __UCLIBC_HAS_FLOATS__ */
577
 
578
};
579
 
580
typedef struct {
581
#if defined(NL_ARGMAX) && (NL_ARGMAX > 0)
582
#if NL_ARGMAX > 10
583
#warning NL_ARGMAX > 10, and space is allocated on the stack for positional args.
584
#endif
585
        void *pos_args[NL_ARGMAX];
586
        int num_pos_args;               /* Must start at -1. */
587
        int cur_pos_arg;
588
#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */
589
        void *cur_ptr;
590
        const unsigned char *fmt;
591
        int cnt, dataargtype, conv_num, max_width;
592
        unsigned char store, flags;
593
} psfs_t;                                               /* parse scanf format state */
594
 
595
 
596
/**********************************************************************/
597
/**********************************************************************/
598
 
599
extern void __init_scan_cookie(register struct scan_cookie *sc,
600
                                                           register FILE *fp);
601
extern int __scan_getc(register struct scan_cookie *sc);
602
extern void __scan_ungetc(register struct scan_cookie *sc);
603
 
604
#ifdef __UCLIBC_HAS_FLOATS__
605
extern int __scan_strtold(long double *ld, struct scan_cookie *sc);
606
#endif /* __UCLIBC_HAS_FLOATS__ */
607
 
608
extern int __psfs_parse_spec(psfs_t *psfs);
609
extern int __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc);
610
 
611
/**********************************************************************/
612
#ifdef L___scan_cookie
613
 
614
#ifdef __UCLIBC_MJN3_ONLY__
615
#warning TODO: Remove dependence on decpt_str and fake_decpt in stub locale mode.
616
#endif
617
#ifndef __UCLIBC_HAS_LOCALE__
618
static const char decpt_str[] = ".";
619
#endif
620
 
621
void __init_scan_cookie(register struct scan_cookie *sc,
622
                                                register FILE *fp)
623
{
624
        sc->fp = fp;
625
        sc->nread = 0;
626
        sc->ungot_flag = 0;
627
        sc->app_ungot = ((fp->modeflags & __MASK_UNGOT) ? fp->ungot[1] : 0);
628
#ifdef __UCLIBC_HAS_WCHAR__
629
        sc->ungot_wflag = 0;             /* vfwscanf */
630
        sc->mb_fail = 0;
631
#endif /* __UCLIBC_HAS_WCHAR__ */
632
 
633
#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__
634
        if (*(sc->grouping = __UCLIBC_CURLOCALE_DATA.grouping)) {
635
                sc->thousands_sep = __UCLIBC_CURLOCALE_DATA.thousands_sep;
636
                sc->tslen = __UCLIBC_CURLOCALE_DATA.thousands_sep_len;
637
#ifdef __UCLIBC_HAS_WCHAR__
638
                sc->thousands_sep_wc = __UCLIBC_CURLOCALE_DATA.thousands_sep_wc;
639
#endif /* __UCLIBC_HAS_WCHAR__ */
640
        }
641
#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */
642
 
643
#ifdef __UCLIBC_HAS_FLOATS__
644
#ifdef __UCLIBC_HAS_LOCALE__
645
        sc->decpt = __UCLIBC_CURLOCALE_DATA.decimal_point;
646
        sc->decpt_len = __UCLIBC_CURLOCALE_DATA.decimal_point_len;
647
#else  /* __UCLIBC_HAS_LOCALE__ */
648
        sc->fake_decpt = sc->decpt = decpt_str;
649
        sc->decpt_len = 1;
650
#endif /* __UCLIBC_HAS_LOCALE__ */
651
#ifdef __UCLIBC_HAS_WCHAR__
652
#ifdef __UCLIBC_HAS_LOCALE__
653
        sc->decpt_wc = __UCLIBC_CURLOCALE_DATA.decimal_point_wc;
654
#else
655
        sc->decpt_wc = '.';
656
#endif
657
#endif /* __UCLIBC_HAS_WCHAR__ */
658
#endif /* __UCLIBC_HAS_FLOATS__ */
659
 
660
}
661
 
662
int __scan_getc(register struct scan_cookie *sc)
663
{
664
        int c;
665
 
666
#ifdef __UCLIBC_HAS_WCHAR__
667
        assert(!sc->mb_fail);
668
#endif /* __UCLIBC_HAS_WCHAR__ */
669
 
670
        sc->cc = EOF;
671
 
672
        if (--sc->width < 0) {
673
                sc->ungot_flag |= 2;
674
                return -1;
675
        }
676
 
677
        if (sc->ungot_flag == 0) {
678
#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__)
679
                if (sc->fp->filedes != -2) {
680
                        c = GETC(sc);
681
                } else {
682
                        __FILE_vsscanf *fv = (__FILE_vsscanf *)(sc->fp);
683
                        if (fv->bufpos < fv->bufread) {
684
                                c = *fv->bufpos++;
685
                        } else {
686
                                c = EOF;
687
                                sc->fp->modeflags |= __FLAG_EOF;
688
                        }
689
                }
690
                if (c == EOF) {
691
                        sc->ungot_flag |= 2;
692
                        return -1;
693
                }
694
#else
695
                if ((c = GETC(sc)) == EOF) {
696
                        sc->ungot_flag |= 2;
697
                        return -1;
698
                }
699
#endif
700
                sc->ungot_char = c;
701
        } else {
702
                assert(sc->ungot_flag == 1);
703
                sc->ungot_flag = 0;
704
        }
705
 
706
        ++sc->nread;
707
        return sc->cc = sc->ungot_char;
708
}
709
 
710
void __scan_ungetc(register struct scan_cookie *sc)
711
{
712
        ++sc->width;
713
        if (sc->ungot_flag == 2) {      /* last was EOF */
714
                sc->ungot_flag = 0;
715
                sc->cc = sc->ungot_char;
716
        } else if (sc->ungot_flag == 0) {
717
                sc->ungot_flag = 1;
718
                --sc->nread;
719
        } else {
720
                assert(0);
721
        }
722
}
723
 
724
#endif
725
/**********************************************************************/
726
#ifdef L___psfs_parse_spec
727
 
728
#ifdef SPEC_FLAGS
729
static const unsigned char spec_flags[] = SPEC_FLAGS;
730
#endif /* SPEC_FLAGS */
731
static const unsigned char spec_chars[] = SPEC_CHARS;
732
static const unsigned char qual_chars[] = QUAL_CHARS;
733
static const unsigned char spec_ranges[] = SPEC_RANGES;
734
static const unsigned short spec_allowed[] = SPEC_ALLOWED_FLAGS;
735
 
736
int __psfs_parse_spec(register psfs_t *psfs)
737
{
738
        const unsigned char *p;
739
        const unsigned char *fmt0 = psfs->fmt;
740
        int i;
741
#ifdef SPEC_FLAGS
742
        int j;
743
#endif
744
#if defined(NL_ARGMAX) && (NL_ARGMAX > 0)
745
        unsigned char fail = 0;
746
 
747
        i = 0;                                           /* Do this here to avoid a warning. */
748
 
749
        if (!__isdigit_char(*psfs->fmt)) { /* Not a positional arg. */
750
                fail = 1;
751
                goto DO_FLAGS;
752
        }
753
 
754
        /* parse the positional arg (or width) value */
755
        do {
756
                if (i <= ((INT_MAX - 9)/10)) {
757
                        i = (i * 10) + (*psfs->fmt++ - '0');
758
                }
759
        } while (__isdigit_char(*psfs->fmt));
760
 
761
        if (*psfs->fmt != '$') { /* This is a max field width. */
762
                if (psfs->num_pos_args >= 0) { /* Already saw a pos arg! */
763
                        goto ERROR_EINVAL;
764
                }
765
                psfs->max_width = i;
766
                psfs->num_pos_args = -2;
767
                goto DO_QUALIFIER;
768
        }
769
        ++psfs->fmt;                    /* Advance past '$'. */
770
#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */
771
 
772
#if defined(SPEC_FLAGS) || (defined(NL_ARGMAX) && (NL_ARGMAX > 0))
773
 DO_FLAGS:
774
#endif /* defined(SPEC_FLAGS) || (defined(NL_ARGMAX) && (NL_ARGMAX > 0)) */
775
#ifdef SPEC_FLAGS
776
        p = spec_flags;
777
        j = FLAG_SURPRESS;
778
        do {
779
                if (*p == *psfs->fmt) {
780
                        ++psfs->fmt;
781
                        psfs->flags |= j;
782
                        goto DO_FLAGS;
783
                }
784
                j += j;
785
        } while (*++p);
786
 
787
        if (psfs->flags & FLAG_SURPRESS) { /* Suppress assignment. */
788
                psfs->store = 0;
789
                goto DO_WIDTH;
790
        }
791
#else  /* SPEC_FLAGS */
792
        if (*psfs->fmt == '*') {        /* Suppress assignment. */
793
                ++psfs->fmt;
794
                psfs->store = 0;
795
                goto DO_WIDTH;
796
        }
797
#endif /* SPEC_FLAGS */
798
 
799
 
800
#if defined(NL_ARGMAX) && (NL_ARGMAX > 0)
801
        if (fail) {
802
                /* Must be a non-positional arg */
803
                if (psfs->num_pos_args >= 0) { /* Already saw a pos arg! */
804
                        goto ERROR_EINVAL;
805
                }
806
                psfs->num_pos_args = -2;
807
        } else {
808
                if ((psfs->num_pos_args == -2) || (((unsigned int)(--i)) >= NL_ARGMAX)) {
809
                        /* Already saw a non-pos arg or (0-based) num too large. */
810
                        goto ERROR_EINVAL;
811
                }
812
                psfs->cur_pos_arg = i;
813
        }
814
#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */
815
 
816
 DO_WIDTH:
817
        for (i = 0 ; __isdigit_char(*psfs->fmt) ; ) {
818
                if (i <= ((INT_MAX - 9)/10)) {
819
                        i = (i * 10) + (*psfs->fmt++ - '0');
820
                        psfs->max_width = i;
821
                }
822
        }
823
 
824
#if defined(NL_ARGMAX) && (NL_ARGMAX > 0)
825
 DO_QUALIFIER:
826
#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */
827
        p = qual_chars;
828
        do {
829
                if (*psfs->fmt == *p) {
830
                        ++psfs->fmt;
831
                        break;
832
                }
833
        } while (*++p);
834
        if ((p - qual_chars < 2) && (*psfs->fmt == *p)) {
835
                p += ((sizeof(qual_chars)-2) / 2);
836
                ++psfs->fmt;
837
        }
838
        psfs->dataargtype = ((int)(p[(sizeof(qual_chars)-2) / 2])) << 8;
839
 
840
#ifdef __UCLIBC_MJN3_ONLY__
841
#warning CONSIDER: Should we validate that psfs->max_width > 0 in __psfs_parse_spec()?  It would avoid whitespace consumption...
842
#warning CONSIDER: Should INT_MAX be a valid width (%c/%C)?  See __psfs_parse_spec().
843
#endif /* __UCLIBC_MJN3_ONLY__ */
844
 
845
        p = spec_chars;
846
        do {
847
                if (*psfs->fmt == *p) {
848
                        int p_m_spec_chars = p - spec_chars;
849
 
850
#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
851
#error implement gnu a flag
852
                        if ((*p == 'a')
853
                                && ((psfs->fmt[1] == '[') || ((psfs->fmt[1]|0x20) == 's'))
854
                                ) {             /* Assumes ascii for 's' and 'S' test. */
855
                                psfs->flags |= FLAG_MALLOC;
856
                                ++psfs->fmt;
857
                                ++p;
858
                                continue; /* The related conversions follow 'a'. */
859
                        }
860
#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */
861
 
862
                        for (p = spec_ranges; p_m_spec_chars > *p ; ++p) {}
863
                        if (((psfs->dataargtype >> 8) | psfs->flags)
864
                                & ~spec_allowed[(int)(p - spec_ranges)]
865
                                ) {
866
                                goto ERROR_EINVAL;
867
                        }
868
 
869
                        if ((p_m_spec_chars >= CONV_c)
870
                                && (psfs->dataargtype & PA_FLAG_LONG)) {
871
                                p_m_spec_chars -= 3; /* lc -> C, ls -> S, l[ -> ?? */
872
                        }
873
 
874
                        psfs->conv_num = p_m_spec_chars;
875
                        return psfs->fmt - fmt0;
876
                }
877
                if (!*++p) {
878
                ERROR_EINVAL:
879
                        __set_errno(EINVAL);
880
                        return -1;
881
                }
882
        } while(1);
883
 
884
        assert(0);
885
}
886
 
887
#endif
888
/**********************************************************************/
889
#if defined(L_vfscanf) || defined(L_vfwscanf)
890
 
891
#ifdef __UCLIBC_HAS_WCHAR__
892
#ifdef L_vfscanf
893
static int sc_getc(register struct scan_cookie *sc)
894
{
895
        return (getc_unlocked)(sc->fp); /* Disable the macro. */
896
}
897
 
898
static int scan_getwc(register struct scan_cookie *sc)
899
{
900
        size_t r;
901
        int width;
902
        wchar_t wc[1];
903
        char b[1];
904
 
905
        if (--sc->width < 0) {
906
                sc->ungot_flag |= 2;
907
                return -1;
908
        }
909
 
910
        width = sc->width;                      /* Preserve width. */
911
        sc->width = INT_MAX;            /* MB_CUR_MAX can invoke a function. */
912
 
913
        assert(!sc->mb_fail);
914
 
915
        r = (size_t)(-3);
916
        while (__scan_getc(sc) >= 0) {
917
                *b = sc->cc;
918
 
919
                r = mbrtowc(wc, b, 1, &sc->mbstate);
920
                if (((ssize_t) r) >= 0) { /* Successful completion of a wc. */
921
                        sc->wc = *wc;
922
                        goto SUCCESS;
923
                } else if (r == ((size_t) -2)) {
924
                        /* Potentially valid but incomplete. */
925
                        continue;
926
                }
927
                break;
928
        }
929
 
930
        if (r == ((size_t)(-3))) {      /* EOF or ERROR on first read */
931
                sc->wc = WEOF;
932
                r = (size_t)(-1);
933
        } else {
934
                /* If we reach here, either r == ((size_t)-1) and
935
                 * mbrtowc set errno to EILSEQ, or r == ((size_t)-2)
936
                 * and stream is in an error state or at EOF with a
937
                 * partially complete wchar. */
938
                __set_errno(EILSEQ);            /* In case of incomplete conversion. */
939
                sc->mb_fail = 1;
940
        }
941
 
942
 SUCCESS:
943
        sc->width = width;                      /* Restore width. */
944
 
945
        return (int)((ssize_t) r);
946
}
947
 
948
#endif /* L_vfscanf */
949
 
950
#ifdef L_vfwscanf
951
 
952
/* This gets called by __scan_getc.  __scan_getc is called by vfwscanf
953
 * when the next wide char is expected to be valid ascii (digits).
954
 */
955
static int sc_getc(register struct scan_cookie *sc)
956
{
957
        wint_t wc;
958
 
959
        if (sc->fp->filedes == -3) {
960
                if (sc->fp->bufpos < sc->fp->bufend) {
961
                        wc = *((wchar_t *)(sc->fp->bufpos));
962
                        sc->fp->bufpos += sizeof(wchar_t);
963
                } else {
964
                        sc->fp->modeflags |= __FLAG_EOF;
965
                        return EOF;
966
                }
967
        } else if ((wc = fgetwc_unlocked(sc->fp)) == WEOF) {
968
                return EOF;
969
        }
970
 
971
        sc->ungot_wflag = 1;
972
        sc->ungot_wchar = wc;
973
        sc->ungot_wchar_width = sc->fp->ungot_width[0];
974
 
975
#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__
976
        if (wc == sc->thousands_sep_wc) {
977
                wc = ',';
978
        } else
979
#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */
980
#ifdef __UCLIBC_HAS_FLOATS__
981
        if (wc == sc->decpt_wc) {
982
                wc = '.';
983
        } else
984
#endif /* __UCLIBC_HAS_FLOATS__ */
985
        if (!__isascii(wc)) {
986
                wc = '?';
987
        }
988
        sc->wc = sc->ungot_char = wc;
989
 
990
        return (int) wc;
991
}
992
 
993
static int scan_getwc(register struct scan_cookie *sc)
994
{
995
        wint_t wc;
996
 
997
        sc->wc = WEOF;
998
 
999
        if (--sc->width < 0) {
1000
                sc->ungot_flag |= 2;
1001
                return -1;
1002
        }
1003
 
1004
        if (sc->ungot_flag == 0) {
1005
 
1006
                if (sc->fp->filedes == -3) {
1007
                        if (sc->fp->bufpos < sc->fp->bufend) {
1008
                                wc = *((wchar_t *)(sc->fp->bufpos));
1009
                                sc->fp->bufpos += sizeof(wchar_t);
1010
                        } else {
1011
                                sc->ungot_flag |= 2;
1012
                                return -1;
1013
                        }
1014
                } else if ((wc = fgetwc_unlocked(sc->fp)) == WEOF) {
1015
                        sc->ungot_flag |= 2;
1016
                        return -1;
1017
                }
1018
                sc->ungot_wflag = 1;
1019
                sc->ungot_char = wc;
1020
                sc->ungot_wchar_width = sc->fp->ungot_width[0];
1021
        } else {
1022
                assert(sc->ungot_flag == 1);
1023
                sc->ungot_flag = 0;
1024
        }
1025
 
1026
        ++sc->nread;
1027
        sc->wc = sc->ungot_char;
1028
 
1029
        return 0;
1030
}
1031
 
1032
 
1033
#endif /* L_vfwscanf */
1034
#endif /* __UCLIBC_HAS_WCHAR__ */
1035
 
1036
static __inline void kill_scan_cookie(register struct scan_cookie *sc)
1037
{
1038
#ifdef L_vfscanf
1039
 
1040
        if (sc->ungot_flag & 1) {
1041
#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__)
1042
                if (sc->fp->filedes != -2) {
1043
                        ungetc(sc->ungot_char, sc->fp);
1044
                }
1045
#else
1046
                ungetc(sc->ungot_char, sc->fp);
1047
#endif
1048
                /* Deal with distiction between user and scanf ungots. */
1049
                if (sc->nread == 0) {    /* Only one char was read... app ungot? */
1050
                        sc->fp->ungot[1] = sc->app_ungot; /* restore ungot state. */
1051
                } else {
1052
                        sc->fp->ungot[1] = 0;
1053
                }
1054
        }
1055
 
1056
#else
1057
 
1058
        if ((sc->ungot_flag & 1) && (sc->ungot_wflag & 1)
1059
                && (sc->fp->filedes != -3) && (sc->fp->state.mask == 0)
1060
                ) {
1061
                ungetwc(sc->ungot_char, sc->fp);
1062
                /* Deal with distiction between user and scanf ungots. */
1063
                if (sc->nread == 0) {    /* Only one char was read... app ungot? */
1064
                        sc->fp->ungot[1] = sc->app_ungot; /* restore ungot state. */
1065
                } else {
1066
                        sc->fp->ungot[1] = 0;
1067
                }
1068
                sc->fp->ungot_width[1] = sc->ungot_wchar_width;
1069
        }
1070
 
1071
#endif
1072
}
1073
 
1074
#ifdef L_vfwscanf
1075
#ifdef __UCLIBC_HAS_FLOATS__
1076
static const char fake_decpt_str[] = ".";
1077
#endif
1078
#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__
1079
static const char fake_thousands_sep_str[] = ",";
1080
#endif
1081
#endif /* L_vfwscanf */
1082
 
1083
 
1084
int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg)
1085
{
1086
        const Wuchar *fmt;
1087
        unsigned char *b;
1088
 
1089
 
1090
#ifdef L_vfwscanf
1091
        wchar_t wbuf[1];
1092
        wchar_t *wb;
1093
#endif /* L_vfwscanf */
1094
 
1095
#ifdef __UCLIBC_HAS_WCHAR__
1096
        mbstate_t mbstate;
1097
#endif /* __UCLIBC_HAS_WCHAR__ */
1098
 
1099
        struct scan_cookie sc;
1100
        psfs_t psfs;
1101
 
1102
        int i;
1103
 
1104
#warning fix MAX_DIGITS.  we do not do binary, so...!
1105
#define MAX_DIGITS 65                   /* Allow one leading 0. */
1106
        unsigned char buf[MAX_DIGITS+2];
1107
#ifdef L_vfscanf
1108
        unsigned char scanset[UCHAR_MAX + 1];
1109
        unsigned char invert;           /* Careful!  Meaning changes. */
1110
#endif /* L_vfscanf */
1111
        unsigned char fail;
1112
        unsigned char zero_conversions = 1;
1113
 
1114
#ifdef __UCLIBC_MJN3_ONLY__
1115
#warning TODO: Make checking of the format string in C locale an option.
1116
#endif
1117
        /* To support old programs, don't check mb validity if in C locale. */
1118
#if defined(__UCLIBC_HAS_LOCALE__) && !defined(L_vfwscanf)
1119
        /* ANSI/ISO C99 requires format string to be a valid multibyte string
1120
         * beginning and ending in its initial shift state. */
1121
        if (((__UCLIBC_CURLOCALE_DATA).encoding) != __ctype_encoding_7_bit) {
1122
                const char *p = format;
1123
                mbstate.mask = 0;                /* Initialize the mbstate. */
1124
                if (mbsrtowcs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) {
1125
                        __set_errno(EINVAL); /* Format string is invalid. */
1126
                        return 0;
1127
                }
1128
        }
1129
#endif /* defined(__UCLIBC_HAS_LOCALE__) && !defined(L_vfwscanf) */
1130
 
1131
#if defined(NL_ARGMAX) && (NL_ARGMAX > 0)
1132
        psfs.num_pos_args = -1;         /* Must start at -1. */
1133
        /* Initialize positional arg ptrs to NULL. */
1134
        memset(psfs.pos_args, 0, sizeof(psfs.pos_args));
1135
#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */
1136
 
1137
        __STDIO_THREADLOCK(fp);
1138
 
1139
        __init_scan_cookie(&sc,fp);
1140
#ifdef __UCLIBC_HAS_WCHAR__
1141
        sc.sc_getc = sc_getc;
1142
        sc.ungot_wchar_width = sc.fp->ungot_width[1];
1143
 
1144
#ifdef L_vfwscanf
1145
 
1146
#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__
1147
        if (*sc.grouping) {
1148
                sc.thousands_sep = fake_thousands_sep_str;
1149
                sc.tslen = 1;
1150
        }
1151
#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */
1152
 
1153
#ifdef __UCLIBC_HAS_FLOATS__
1154
        sc.fake_decpt = fake_decpt_str;
1155
#endif /* __UCLIBC_HAS_FLOATS__ */
1156
 
1157
#else  /* L_vfwscanf */
1158
 
1159
#ifdef __UCLIBC_HAS_FLOATS__
1160
        sc.fake_decpt = sc.decpt;
1161
#endif /* __UCLIBC_HAS_FLOATS__ */
1162
 
1163
#endif /* L_vfwscanf */
1164
 
1165
#endif /* __UCLIBC_HAS_WCHAR__ */
1166
        psfs.cnt = 0;
1167
 
1168
        /* Note: If we ever wanted to support non-nice codesets, we
1169
         * would really need to do a mb->wc conversion here in the
1170
         * vfscanf case.  Related changes would have to be made in
1171
         * the code that follows... basicly wherever fmt appears. */
1172
        for (fmt = (const Wuchar *) format ; *fmt ; /* ++fmt */) {
1173
 
1174
                psfs.store = 1;
1175
                psfs.flags = 0;
1176
#ifndef NDEBUG
1177
                psfs.cur_ptr = NULL;    /* Debugging aid. */
1178
#endif /* NDEBUG */
1179
 
1180
 
1181
                sc.ungot_flag &= 1;             /* Clear (possible fake) EOF. */
1182
                sc.width = psfs.max_width = INT_MAX;
1183
 
1184
                /* Note: According to the standards, vfscanf does use isspace
1185
                 * here. So, if we did a mb->wc conversion, we would have to do
1186
                 * something like
1187
                 *      ((((__uwchar_t)wc) < UCHAR_MAX) && isspace(wc))
1188
                 * because wc might not be in the allowed domain. */
1189
                if (ISSPACE(*fmt)) {
1190
                        do {
1191
                                ++fmt;
1192
                        } while (ISSPACE(*fmt));
1193
                        --fmt;
1194
                        psfs.conv_num = CONV_whitespace;
1195
                        goto DO_WHITESPACE;
1196
                }
1197
 
1198
                if (*fmt == '%') {              /* Conversion specification. */
1199
                        if (*++fmt == '%') { /* Remember, '%' eats whitespace too. */
1200
                                /* Note: The standard says no conversion occurs.
1201
                                 * So do not reset zero_conversions flag. */
1202
                                psfs.conv_num = CONV_percent;
1203
                                goto DO_CONVERSION;
1204
                        }
1205
 
1206
 
1207
#ifdef L_vfscanf
1208
                        psfs.fmt = fmt;
1209
#else  /* L_vfscanf */
1210
                        {
1211
                                const __uwchar_t *wf = fmt;
1212
                                psfs.fmt = b = buf;
1213
 
1214
                                while (*wf && __isascii(*wf) && (b < buf + sizeof(buf) - 1)) {
1215
                                        *b++ = *wf++;
1216
                                }
1217
#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
1218
#error this is wrong... we need to ched in __psfs_parse_spec instead since this checks last char in buffer and conversion my have stopped before it.
1219
                                if ((*b == 'a') && ((*wf == '[') || ((*wf|0x20) == 's'))) {
1220
                                        goto DONE;      /* Spec was excessively long. */
1221
                                }
1222
#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */
1223
                                *b = 0;
1224
                                if (b == buf) { /* Bad conversion specifier! */
1225
                                        goto DONE;
1226
                                }
1227
                        }
1228
#endif /* L_vfscanf */
1229
                        if ((i = __psfs_parse_spec(&psfs)) < 0) { /* Bad conversion specifier! */
1230
                                goto DONE;
1231
                        }
1232
                        fmt += i;
1233
 
1234
                        if (psfs.store) {
1235
#if defined(NL_ARGMAX) && (NL_ARGMAX > 0)
1236
                                if (psfs.num_pos_args == -2) {
1237
                                        psfs.cur_ptr = va_arg(arg, void *);
1238
                                } else {
1239
                                        while (psfs.cur_pos_arg > psfs.num_pos_args) {
1240
                                                psfs.pos_args[++psfs.num_pos_args] = va_arg(arg, void *);
1241
                                        }
1242
                                        psfs.cur_ptr = psfs.pos_args[psfs.cur_pos_arg];
1243
                                }
1244
#else  /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */
1245
                                psfs.cur_ptr = va_arg(arg, void *);
1246
#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */
1247
                        }
1248
 
1249
                DO_CONVERSION:
1250
                        /* First, consume white-space if not n, c, [, C, or l[. */
1251
                        if ((((1L << CONV_n)|(1L << CONV_C)|(1L << CONV_c)
1252
                                 |(1L << CONV_LEFTBRACKET)|(1L << CONV_leftbracket))
1253
                                 & (1L << psfs.conv_num)) == 0
1254
                                ) {
1255
                        DO_WHITESPACE:
1256
                                while ((__scan_getc(&sc) >= 0)
1257
#ifdef L_vfscanf
1258
                                           && isspace(sc.cc)
1259
#else  /* L_vfscanf */
1260
                                           && iswspace(sc.wc)
1261
#endif /* L_vfscanf */
1262
                                           ) {}
1263
                                __scan_ungetc(&sc);
1264
                                if (psfs.conv_num == CONV_whitespace) {
1265
                                        goto NEXT_FMT;
1266
                                }
1267
                        }
1268
 
1269
                        sc.width = psfs.max_width; /* Now limit the max width. */
1270
 
1271
                        if (sc.width == 0) { /* 0 width is forbidden. */
1272
                                goto DONE;
1273
                        }
1274
 
1275
 
1276
                        if (psfs.conv_num == CONV_percent) {
1277
                                goto MATCH_CHAR;
1278
                        }
1279
 
1280
                        if (psfs.conv_num == CONV_n) {
1281
#ifdef __UCLIBC_MJN3_ONLY__
1282
#warning Should %n count as a conversion as far as EOF return value?
1283
#endif
1284
/*                              zero_conversions = 0; */
1285
                                if (psfs.store) {
1286
                                        _store_inttype(psfs.cur_ptr, psfs.dataargtype,
1287
                                                                   (uintmax_t) sc.nread);
1288
                                }
1289
                                goto NEXT_FMT;
1290
                        }
1291
 
1292
                        if (psfs.conv_num <= CONV_A) { /* pointer, integer, or float spec */
1293
                                int r = __psfs_do_numeric(&psfs, &sc);
1294
#ifndef L_vfscanf
1295
                                if (sc.ungot_wflag == 1) {      /* fix up  '?', '.', and ',' hacks */
1296
                                        sc.cc = sc.ungot_char = sc.ungot_wchar;
1297
                                }
1298
#endif
1299
                                if (r != -1) {  /* Either success or a matching failure. */
1300
                                        zero_conversions = 0;
1301
                                }
1302
                                if (r < 0) {
1303
                                        goto DONE;
1304
                                }
1305
                                goto NEXT_FMT;
1306
                        }
1307
 
1308
                        /* Do string conversions here since they are not common code. */
1309
 
1310
 
1311
#ifdef L_vfscanf
1312
 
1313
                        if
1314
#ifdef __UCLIBC_HAS_WCHAR__
1315
                                (psfs.conv_num >= CONV_LEFTBRACKET)
1316
#else  /* __UCLIBC_HAS_WCHAR__ */
1317
                                (psfs.conv_num >= CONV_c)
1318
#endif /* __UCLIBC_HAS_WCHAR__ */
1319
                        {
1320
                                b = (psfs.store ? ((unsigned char *) psfs.cur_ptr) : buf);
1321
                                fail = 1;
1322
 
1323
 
1324
                                if (psfs.conv_num == CONV_c) {
1325
                                        if (sc.width == INT_MAX) {
1326
                                                sc.width = 1;
1327
                                        }
1328
 
1329
                                        while (__scan_getc(&sc) >= 0) {
1330
                                                zero_conversions = 0;
1331
                                                *b = sc.cc;
1332
                                                b += psfs.store;
1333
                                        }
1334
                                        __scan_ungetc(&sc);
1335
                                        if (sc.width > 0) {      /* Failed to read all required. */
1336
                                                goto DONE;
1337
                                        }
1338
                                        psfs.cnt += psfs.store;
1339
                                        goto NEXT_FMT;
1340
                                }
1341
 
1342
                                if (psfs.conv_num == CONV_s) {
1343
                                        /* Yes, believe it or not, a %s conversion can store nuls. */
1344
                                        while ((__scan_getc(&sc) >= 0) && !isspace(sc.cc)) {
1345
                                                zero_conversions = 0;
1346
                                                *b = sc.cc;
1347
                                                b += psfs.store;
1348
                                                fail = 0;
1349
                                        }
1350
                                } else {
1351
#ifdef __UCLIBC_HAS_WCHAR__
1352
                                        assert((psfs.conv_num == CONV_LEFTBRACKET) || \
1353
                                                   (psfs.conv_num == CONV_leftbracket));
1354
#else /* __UCLIBC_HAS_WCHAR__ */
1355
                                        assert((psfs.conv_num == CONV_leftbracket));
1356
#endif /* __UCLIBC_HAS_WCHAR__ */
1357
 
1358
                                        invert = 0;
1359
 
1360
                                        if (*++fmt == '^') {
1361
                                                ++fmt;
1362
                                                invert = 1;
1363
                                        }
1364
                                        memset(scanset, invert, sizeof(scanset));
1365
                                        invert = 1-invert;
1366
 
1367
                                        if (*fmt == ']') {
1368
                                                scanset[(int)(']')] = invert;
1369
                                                ++fmt;
1370
                                        }
1371
 
1372
                                        while (*fmt != ']') {
1373
                                                if (!*fmt) { /* No closing ']'. */
1374
                                                        goto DONE;
1375
                                                }
1376
                                                if ((*fmt == '-') && (fmt[1] != ']')
1377
                                                        && (fmt[-1] < fmt[1]) /* sorted? */
1378
                                                        ) {     /* range */
1379
                                                        ++fmt;
1380
                                                        i = fmt[-2];
1381
                                                        /* Note: scanset[i] should already have been done
1382
                                                         * in the previous iteration. */
1383
                                                        do {
1384
                                                                scanset[++i] = invert;
1385
                                                        } while (i < *fmt);
1386
                                                        /* Safe to fall through, and a bit smaller. */
1387
                                                }
1388
                                                /* literal char */
1389
                                                scanset[(int) *fmt] = invert;
1390
                                                ++fmt;
1391
                                        }
1392
 
1393
#ifdef __UCLIBC_HAS_WCHAR__
1394
                                        if (psfs.conv_num == CONV_LEFTBRACKET) {
1395
                                                goto DO_LEFTBRACKET;
1396
                                        }
1397
#endif /* __UCLIBC_HAS_WCHAR__ */
1398
 
1399
 
1400
                                        while (__scan_getc(&sc) >= 0) {
1401
                                                zero_conversions = 0;
1402
                                                if (!scanset[sc.cc]) {
1403
                                                        break;
1404
                                                }
1405
                                                *b = sc.cc;
1406
                                                b += psfs.store;
1407
                                                fail = 0;
1408
                                        }
1409
                                }
1410
                                /* Common tail for processing of %s and %[. */
1411
 
1412
                                __scan_ungetc(&sc);
1413
                                if (fail) {     /* nothing stored! */
1414
                                        goto DONE;
1415
                                }
1416
                                *b = 0;          /* Nul-terminate string. */
1417
                                psfs.cnt += psfs.store;
1418
                                goto NEXT_FMT;
1419
                        }
1420
 
1421
#ifdef __UCLIBC_HAS_WCHAR__
1422
                DO_LEFTBRACKET:                 /* Need to do common wide init. */
1423
                        if (psfs.conv_num >= CONV_C) {
1424
                                wchar_t wbuf[1];
1425
                                wchar_t *wb;
1426
 
1427
                                sc.mbstate.mask = 0;
1428
 
1429
                                wb = (psfs.store ? ((wchar_t *) psfs.cur_ptr) : wbuf);
1430
                                fail = 1;
1431
 
1432
                                if (psfs.conv_num == CONV_C) {
1433
                                        if (sc.width == INT_MAX) {
1434
                                                sc.width = 1;
1435
                                        }
1436
 
1437
                                        while (scan_getwc(&sc) >= 0) {
1438
                                                zero_conversions = 0;
1439
                                                assert(sc.width >= 0);
1440
                                                *wb = sc.wc;
1441
                                                wb += psfs.store;
1442
                                        }
1443
 
1444
                                        __scan_ungetc(&sc);
1445
                                        if (sc.width > 0) {      /* Failed to read all required. */
1446
                                                goto DONE;
1447
                                        }
1448
                                        psfs.cnt += psfs.store;
1449
                                        goto NEXT_FMT;
1450
                                }
1451
 
1452
 
1453
                                if (psfs.conv_num == CONV_S) {
1454
                                        /* Yes, believe it or not, a %s conversion can store nuls. */
1455
                                        while (scan_getwc(&sc) >= 0) {
1456
                                                zero_conversions = 0;
1457
                                                if ((((__uwchar_t)(sc.wc)) <= UCHAR_MAX) && isspace(sc.wc)) {
1458
                                                        break;
1459
                                                }
1460
                                                *wb = sc.wc;
1461
                                                wb += psfs.store;
1462
                                                fail = 0;
1463
                                        }
1464
                                } else {
1465
                                        assert(psfs.conv_num == CONV_LEFTBRACKET);
1466
 
1467
                                        while (scan_getwc(&sc) >= 0) {
1468
                                                zero_conversions = 0;
1469
                                                if (((__uwchar_t) sc.wc) <= UCHAR_MAX) {
1470
                                                        if (!scanset[sc.wc]) {
1471
                                                                break;
1472
                                                        }
1473
                                                } else if (invert) {
1474
                                                        break;
1475
                                                }
1476
                                                *wb = sc.wc;
1477
                                                wb += psfs.store;
1478
                                                fail = 0;
1479
                                        }
1480
                                }
1481
                                /* Common tail for processing of %ls and %l[. */
1482
 
1483
                                __scan_ungetc(&sc);
1484
                                if (fail || sc.mb_fail) { /* Nothing stored or mb error. */
1485
                                        goto DONE;
1486
                                }
1487
                                *wb = 0;         /* Nul-terminate string. */
1488
                                psfs.cnt += psfs.store;
1489
                                goto NEXT_FMT;
1490
 
1491
                        }
1492
 
1493
#endif /* __UCLIBC_HAS_WCHAR__ */
1494
#else  /* L_vfscanf */
1495
 
1496
                        if (psfs.conv_num >= CONV_C) {
1497
                                b = buf;
1498
                                wb = wbuf;
1499
                                if (psfs.conv_num >= CONV_c) {
1500
                                        mbstate.mask = 0;                /* Initialize the mbstate. */
1501
                                        if (psfs.store) {
1502
                                                b = (unsigned char *) psfs.cur_ptr;
1503
                                        }
1504
                                } else {
1505
                                        if (psfs.store) {
1506
                                                wb = (wchar_t *) psfs.cur_ptr;
1507
                                        }
1508
                                }
1509
                                fail = 1;
1510
 
1511
 
1512
                                if ((psfs.conv_num == CONV_C) || (psfs.conv_num == CONV_c)) {
1513
                                        if (sc.width == INT_MAX) {
1514
                                                sc.width = 1;
1515
                                        }
1516
 
1517
                                        while (scan_getwc(&sc) >= 0) {
1518
                                                zero_conversions = 0;
1519
                                                if (psfs.conv_num == CONV_C) {
1520
                                                        *wb = sc.wc;
1521
                                                        wb += psfs.store;
1522
                                                } else {
1523
                                                        i = wcrtomb(b, sc.wc, &mbstate);
1524
                                                        if (i < 0) { /* Conversion failure. */
1525
                                                                goto DONE_DO_UNGET;
1526
                                                        }
1527
                                                        if (psfs.store) {
1528
                                                                b += i;
1529
                                                        }
1530
                                                }
1531
                                        }
1532
                                        __scan_ungetc(&sc);
1533
                                        if (sc.width > 0) {      /* Failed to read all required. */
1534
                                                goto DONE;
1535
                                        }
1536
                                        psfs.cnt += psfs.store;
1537
                                        goto NEXT_FMT;
1538
                                }
1539
 
1540
                                if ((psfs.conv_num == CONV_S) || (psfs.conv_num == CONV_s)) {
1541
                                        /* Yes, believe it or not, a %s conversion can store nuls. */
1542
                                        while (scan_getwc(&sc) >= 0) {
1543
                                                zero_conversions = 0;
1544
                                                if  (iswspace(sc.wc)) {
1545
                                                        break;
1546
                                                }
1547
                                                if (psfs.conv_num == CONV_S) {
1548
                                                        *wb = sc.wc;
1549
                                                        wb += psfs.store;
1550
                                                } else {
1551
                                                        i = wcrtomb(b, sc.wc, &mbstate);
1552
                                                        if (i < 0) { /* Conversion failure. */
1553
                                                                goto DONE_DO_UNGET;
1554
                                                        }
1555
                                                        if (psfs.store) {
1556
                                                                b += i;
1557
                                                        }
1558
                                                }
1559
                                                fail = 0;
1560
                                        }
1561
                                } else {
1562
                                        const wchar_t *sss;
1563
                                        const wchar_t *ssp;
1564
                                        unsigned char invert = 0;
1565
 
1566
                                        assert((psfs.conv_num == CONV_LEFTBRACKET)
1567
                                                   || (psfs.conv_num == CONV_leftbracket));
1568
 
1569
                                        if (*++fmt == '^') {
1570
                                                ++fmt;
1571
                                                invert = 1;
1572
                                        }
1573
                                        sss = (const wchar_t *) fmt;
1574
                                        if (*fmt == ']') {
1575
                                                ++fmt;
1576
                                        }
1577
                                        while (*fmt != ']') {
1578
                                                if (!*fmt) { /* No closing ']'. */
1579
                                                        goto DONE;
1580
                                                }
1581
                                                if ((*fmt == '-') && (fmt[1] != ']')
1582
                                                        && (fmt[-1] < fmt[1]) /* sorted? */
1583
                                                        ) {     /* range */
1584
                                                        ++fmt;
1585
                                                }
1586
                                                ++fmt;
1587
                                        }
1588
                                        /* Ok... a valid scanset spec. */
1589
 
1590
                                        while (scan_getwc(&sc) >= 0) {
1591
                                                zero_conversions = 0;
1592
                                                ssp = sss;
1593
                                                do {    /* We know sss < fmt. */
1594
                                                        if (*ssp == '-') { /* possible range... */
1595
                                                                /* Note: We accept a-c-e (ordered) as
1596
                                                                 * equivalent to a-e. */
1597
                                                                if (ssp > sss) {
1598
                                                                        if ((++ssp < (const wchar_t *) fmt)
1599
                                                                                && (ssp[-2] < *ssp)     /* sorted? */
1600
                                                                                ) { /* yes */
1601
                                                                                if ((sc.wc >= ssp[-2])
1602
                                                                                        && (sc.wc <= *ssp)) {
1603
                                                                                        break;
1604
                                                                                }
1605
                                                                                continue; /* not in range */
1606
                                                                        }
1607
                                                                        --ssp; /* oops... '-' at end, so back up */
1608
                                                                }
1609
                                                                /* false alarm... a literal '-' */
1610
                                                        }
1611
                                                        if (sc.wc == *ssp) { /* Matched literal char. */
1612
                                                                break;
1613
                                                        }
1614
                                                } while (++ssp < (const wchar_t *) fmt);
1615
 
1616
                                                if ((ssp == (const wchar_t *) fmt) ^ invert) {
1617
                                                        /* no match and not inverting
1618
                                                         * or match and inverting */
1619
                                                        break;
1620
                                                }
1621
                                                if (psfs.conv_num == CONV_LEFTBRACKET) {
1622
                                                        *wb = sc.wc;
1623
                                                        wb += psfs.store;
1624
                                                } else {
1625
                                                        i = wcrtomb(b, sc.wc, &mbstate);
1626
                                                        if (i < 0) { /* Conversion failure. */
1627
                                                                goto DONE_DO_UNGET;
1628
                                                        }
1629
                                                        if (psfs.store) {
1630
                                                                b += i;
1631
                                                        }
1632
                                                }
1633
                                                fail = 0;
1634
                                        }
1635
                                }
1636
                                /* Common tail for processing of %s and %[. */
1637
 
1638
                                __scan_ungetc(&sc);
1639
                                if (fail) {     /* nothing stored! */
1640
                                        goto DONE;
1641
                                }
1642
                                *wb = 0;         /* Nul-terminate string. */
1643
                                *b = 0;
1644
                                psfs.cnt += psfs.store;
1645
                                goto NEXT_FMT;
1646
                        }
1647
 
1648
#endif /* L_vfscanf */
1649
 
1650
                        assert(0);
1651
                        goto DONE;
1652
                } /* conversion specification */
1653
 
1654
        MATCH_CHAR:
1655
                if (__scan_getc(&sc) != *fmt) {
1656
#ifdef L_vfwscanf
1657
                DONE_DO_UNGET:
1658
#endif /* L_vfwscanf */
1659
                        __scan_ungetc(&sc);
1660
                        goto DONE;
1661
                }
1662
 
1663
        NEXT_FMT:
1664
                ++fmt;
1665
                if (__FERROR(fp)) {
1666
                        break;
1667
                }
1668
        }
1669
 
1670
 DONE:
1671
        if (__FERROR(fp) || (*fmt && zero_conversions && __FEOF(fp))) {
1672
                psfs.cnt = EOF;                 /* Yes, vfwscanf also returns EOF. */
1673
        }
1674
 
1675
        kill_scan_cookie(&sc);
1676
 
1677
        __STDIO_THREADUNLOCK(fp);
1678
 
1679
        return psfs.cnt;
1680
}
1681
#endif
1682
/**********************************************************************/
1683
#ifdef L___psfs_do_numeric
1684
 
1685
static const unsigned char spec_base[] = SPEC_BASE;
1686
static const unsigned char nil_string[] = "(nil)";
1687
 
1688
int __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc)
1689
{
1690
        unsigned char *b;
1691
        const unsigned char *p;
1692
 
1693
#ifdef __UCLIBC_HAS_FLOATS__
1694
        int exp_adjust = 0;
1695
#endif
1696
#warning fix MAX_DIGITS.  we do not do binary, so...!
1697
#define MAX_DIGITS 65                   /* Allow one leading 0. */
1698
#warning fix buf!
1699
        unsigned char buf[MAX_DIGITS+2+ 100];
1700
        unsigned char usflag, base;
1701
        unsigned char nonzero = 0;
1702
        unsigned char seendigit = 0;
1703
 
1704
 
1705
#warning what should be returned for an invalid conversion specifier?
1706
#ifndef __UCLIBC_HAS_FLOATS__
1707
        if (psfs->conv_num > CONV_i) { /* floating point */
1708
                goto DONE;
1709
        }
1710
#endif
1711
 
1712
        base = spec_base[psfs->conv_num - CONV_p];
1713
        usflag = (psfs->conv_num <= CONV_u); /* (1)0 if (un)signed */
1714
        b = buf;
1715
 
1716
 
1717
        if (psfs->conv_num == CONV_p) { /* Pointer */
1718
                p = nil_string;
1719
                do {
1720
                        if ((__scan_getc(sc) < 0) || (*p != sc->cc)) {
1721
                                __scan_ungetc(sc);
1722
                                if (p > nil_string) {
1723
                                        /* We matched at least the '(' so even if we
1724
                                         * are at eof,  we can not match a pointer. */
1725
                                        return -2;      /* Matching failure */
1726
                                }
1727
                                break;
1728
                        }
1729
                        if (!*++p) {   /* Matched (nil), so no unget necessary. */
1730
                                if (psfs->store) {
1731
                                        ++psfs->cnt;
1732
                                        _store_inttype(psfs->cur_ptr, psfs->dataargtype,
1733
                                                                   (uintmax_t) NULL);
1734
                                }
1735
                                return 0;
1736
                        }
1737
                } while (1);
1738
 
1739
#ifdef __UCLIBC_MJN3_ONLY__
1740
#warning CONSIDER: Should we require a 0x prefix and disallow +/- for pointer %p?
1741
#endif /*  __UCLIBC_MJN3_ONLY__ */
1742
        }
1743
 
1744
        __scan_getc(sc);
1745
        if (sc->cc < 0) {
1746
                return -1;                              /* Input failure (nothing read yet). */
1747
        }
1748
 
1749
        if ((sc->cc == '+') || (sc->cc == '-')) { /* Handle leading sign.*/
1750
                *b++ = sc->cc;
1751
                __scan_getc(sc);
1752
        }
1753
 
1754
        if ((base & 0xef) == 0) { /* 0xef is ~16, so 16 or 0. */
1755
                if (sc->cc == '0') {    /* Possibly set base and handle prefix. */
1756
                        __scan_getc(sc);
1757
                        if ((sc->cc|0x20) == 'x') { /* Assumes ascii.. x or X. */
1758
                                if (__scan_getc(sc) < 0) {
1759
                                        /* Either EOF or error (including wc outside char range).
1760
                                         * If EOF or error, this is a matching failure (we read 0x).
1761
                                         * If wc outside char range, this is also a matching failure.
1762
                                         * Hence, we do an unget (although not really necessary here
1763
                                         * and fail. */
1764
                                        goto DONE_DO_UNGET;     /* matching failure */
1765
                                }
1766
                                base = 16; /* Base 16 for sure now. */
1767
#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
1768
                                /* The prefix is required for hexadecimal floats. */
1769
                                *b++ = '0';
1770
                                *b++ = 'x';
1771
#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */
1772
                        } else { /* oops... back up */
1773
                                __scan_ungetc(sc);
1774
                                sc->cc = '0';   /* NASTY HACK! */
1775
 
1776
                                base = (base >> 1) + 8; /* 0->8, 16->16.  no 'if' */
1777
#ifdef __UCLIBC_HAS_FLOATS__
1778
                                if (psfs->conv_num > CONV_i) { /* floating point */
1779
                                        base = 10;
1780
                                }
1781
#endif
1782
                        }
1783
                } else if (!base) {
1784
                        base = 10;
1785
                }
1786
        }
1787
 
1788
        /***************** digit grouping **********************/
1789
#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__
1790
 
1791
        if ((psfs->flags & FLAG_THOUSANDS) && (base == 10)
1792
                && *(p = sc->grouping)
1793
                ) {
1794
 
1795
                int nblk1, nblk2, nbmax, lastblock, pass, i;
1796
 
1797
 
1798
#ifdef __UCLIBC_MJN3_ONLY__
1799
#warning CONSIDER: Should we initalize the grouping blocks in __init_scan_cookie()?
1800
#endif /*  __UCLIBC_MJN3_ONLY__ */
1801
                nbmax = nblk2 = nblk1 = *p;
1802
                if (*++p) {
1803
                        nblk2 = *p;
1804
                        if (nbmax < nblk2) {
1805
                                nbmax = nblk2;
1806
                        }
1807
                        assert(!p[1]);
1808
                }
1809
 
1810
                /* Note: for printf, if 0 and \' flags appear then
1811
                 * grouping is done before 0-padding.  Should we
1812
                 * strip leading 0's first?  Or add a 0 flag? */
1813
 
1814
                /* For vfwscanf, sc_getc translates, so the value of sc->cc is
1815
                 * either EOF or a char. */
1816
 
1817
                if (!__isdigit_char_or_EOF(sc->cc)) { /* No starting digit! */
1818
#ifdef __UCLIBC_HAS_FLOATS__
1819
                        if (psfs->conv_num > CONV_i) { /* floating point */
1820
                                goto NO_STARTING_DIGIT;
1821
                        }
1822
#endif
1823
                        goto DONE_DO_UNGET;
1824
                }
1825
 
1826
                if (sc->cc == '0') {
1827
                        seendigit = 1;
1828
                        *b++ = '0';                     /* Store the first 0. */
1829
#ifdef __UCLIBC_MJN3_ONLY__
1830
#warning CONSIDER: Should leading 0s be skipped before digit grouping? (printf 0 pad)
1831
#endif /*  __UCLIBC_MJN3_ONLY__ */
1832
#if 0
1833
                        do {                            /* But ignore all subsequent 0s. */
1834
                                __scan_getc(sc);
1835
                        } while (sc->cc == '0');
1836
#endif
1837
                }
1838
                pass = 0;
1839
                lastblock = 0;
1840
                do {
1841
                        i = 0;
1842
                        while (__isdigit_char_or_EOF(sc->cc)) {
1843
                                seendigit = 1;
1844
                                if (i == nbmax) { /* too many digits for a block */
1845
#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__
1846
                                        if (!pass) { /* treat as nongrouped */
1847
                                                if (nonzero) {
1848
                                                        goto DO_NO_GROUP;
1849
                                                }
1850
                                                goto DO_TRIM_LEADING_ZEROS;
1851
                                        }
1852
#endif
1853
                                        if (nbmax > nblk1) {
1854
                                                goto DONE_DO_UNGET;     /* matching failure */
1855
                                        }
1856
                                        goto DONE_GROUPING_DO_UNGET; /* nbmax == nblk1 */
1857
                                }
1858
                                ++i;
1859
 
1860
                                if (nonzero || (sc->cc != '0')) {
1861
                                        if (b < buf + MAX_DIGITS) {
1862
                                                *b++ = sc->cc;
1863
                                                nonzero = 1;
1864
#ifdef __UCLIBC_HAS_FLOATS__
1865
                                        } else {
1866
                                                ++exp_adjust;
1867
#endif
1868
                                        }
1869
                                }
1870
 
1871
                                __scan_getc(sc);
1872
                        }
1873
 
1874
                        if (i) {                        /* we saw digits digits */
1875
                                if ((i == nblk2) || ((i < nblk2) && !pass)) {
1876
                                        /* (possible) outer grp */
1877
                                        p = sc->thousands_sep;
1878
                                        if (*p == sc->cc) {     /* first byte matches... */
1879
                                                /* so check if grouping mb char */
1880
                                                /* Since 1st matched, either match or fail now
1881
                                                 * unless EOF (yuk) */
1882
                                                __scan_getc(sc);
1883
                                        MBG_LOOP:
1884
                                                if (!*++p) { /* is a grouping mb char */
1885
                                                        lastblock = i;
1886
                                                        ++pass;
1887
                                                        continue;
1888
                                                }
1889
                                                if (*p == sc->cc) {
1890
                                                        __scan_getc(sc);
1891
                                                        goto MBG_LOOP;
1892
                                                }
1893
                                                /* bad grouping mb char! */
1894
                                                __scan_ungetc(sc);
1895
                                                if ((sc->cc >= 0) || (p > sc->thousands_sep + 1)) {
1896
#ifdef __UCLIBC_HAS_FLOATS__
1897
                                                        /* We failed to match a thousep mb char, and
1898
                                                         * we've read too much to recover.  But if
1899
                                                         * this is a floating point conversion and
1900
                                                         * the initial portion of the decpt mb char
1901
                                                         * matches, then we may still be able to
1902
                                                         * recover. */
1903
                                                        int k = p - sc->thousands_sep - 1;
1904
 
1905
                                                        if ((psfs->conv_num > CONV_i) /* float conversion */
1906
                                                                && (!pass || (i == nblk1)) /* possible last */
1907
                                                                && !memcmp(sc->thousands_sep, sc->fake_decpt, k)
1908
                                                                /* and prefix matched, so could be decpt */
1909
                                                                ) {
1910
                                                                __scan_getc(sc);
1911
                                                                p = sc->fake_decpt + k;
1912
                                                                do {
1913
                                                                        if (!*++p) {
1914
                                                                                strcpy(b, sc->decpt);
1915
                                                                                b += sc->decpt_len;
1916
                                                                                goto GOT_DECPT;
1917
                                                                        }
1918
                                                                        if (*p != sc->cc) {
1919
                                                                                __scan_ungetc(sc);
1920
                                                                                break; /* failed */
1921
                                                                        }
1922
                                                                        __scan_getc(sc);
1923
                                                                } while (1);
1924
                                                        }
1925
#endif /* __UCLIBC_HAS_FLOATS__ */
1926
                                                        goto DONE;
1927
                                                }
1928
                                                /* was EOF and 1st, so recoverable. */
1929
                                        }
1930
                                }
1931
                                if ((i == nblk1) || ((i < nblk1) && !pass)) {
1932
                                        /* got an inner group */
1933
                                        goto DONE_GROUPING_DO_UNGET;
1934
                                }
1935
                                goto DONE_DO_UNGET;     /* Matching failure. */
1936
                        } /* i != 0 */
1937
 
1938
                        assert(pass);
1939
 
1940
                        goto DONE_DO_UNGET;
1941
                } while (1);
1942
 
1943
                assert(0);                               /* Should never get here. */
1944
        }
1945
 
1946
#endif /***************** digit grouping **********************/
1947
 
1948
        /* Not grouping so first trim all but one leading 0. */
1949
#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__
1950
        DO_TRIM_LEADING_ZEROS:
1951
#endif /* __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ */
1952
        if (sc->cc == '0') {
1953
                seendigit = 1;
1954
                *b++ = '0';                             /* Store the first 0. */
1955
                do {                                    /* But ignore all subsequent 0s. */
1956
                        __scan_getc(sc);
1957
                } while (sc->cc == '0');
1958
        }
1959
 
1960
#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__
1961
 DO_NO_GROUP:
1962
#endif /* __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ */
1963
        /* At this point, we're ready to start reading digits. */
1964
 
1965
#define valid_digit(cc,base) (isxdigit(cc) && ((base == 16) || (cc - '0' < base)))
1966
 
1967
        while (valid_digit(sc->cc,base)) { /* Now for significant digits.*/
1968
                if (b - buf < MAX_DIGITS) {
1969
                        nonzero = seendigit = 1; /* Set nonzero too 0s trimmed above. */
1970
                        *b++ = sc->cc;
1971
#ifdef __UCLIBC_HAS_FLOATS__
1972
                } else {
1973
                        ++exp_adjust;
1974
#endif
1975
                }
1976
                __scan_getc(sc);
1977
        }
1978
 
1979
#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__
1980
 DONE_GROUPING_DO_UNGET:
1981
#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */
1982
        if (psfs->conv_num <= CONV_i) { /* integer conversion */
1983
                __scan_ungetc(sc);
1984
                *b = 0;                                          /* null-terminate */
1985
                if (!seendigit) {
1986
                        goto DONE;                              /* No digits! */
1987
                }
1988
                if (psfs->store) {
1989
                        if (*buf == '-') {
1990
                                usflag = 0;
1991
                        }
1992
                        ++psfs->cnt;
1993
                        _store_inttype(psfs->cur_ptr, psfs->dataargtype,
1994
                                                   (uintmax_t) STRTOUIM(buf, NULL, base, 1-usflag));
1995
                }
1996
                return 0;
1997
        }
1998
 
1999
#ifdef __UCLIBC_HAS_FLOATS__
2000
 
2001
        /* At this point, we have everything left of the decimal point or exponent. */
2002
#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__
2003
 NO_STARTING_DIGIT:
2004
#endif
2005
        p = sc->fake_decpt;
2006
        do {
2007
                if (!*p) {
2008
                        strcpy(b, sc->decpt);
2009
                        b += sc->decpt_len;
2010
                        break;
2011
                }
2012
                if (*p != sc->cc) {
2013
                        if (p > sc->fake_decpt) {
2014
                                goto DONE_DO_UNGET;     /* matching failure (read some of decpt) */
2015
                        }
2016
                        goto DO_DIGIT_CHECK;
2017
                }
2018
                ++p;
2019
                __scan_getc(sc);
2020
        } while (1);
2021
 
2022
#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__
2023
 GOT_DECPT:
2024
#endif
2025
        if (!nonzero) {
2026
                if (sc->cc == '0') {
2027
                        assert(exp_adjust == 0);
2028
                        *b++ = '0';
2029
                        ++exp_adjust;
2030
                        seendigit = 1;
2031
                        do {
2032
                                --exp_adjust;
2033
                                __scan_getc(sc);
2034
                        } while (sc->cc == '0');
2035
                }
2036
        }
2037
 
2038
        while (valid_digit(sc->cc,base)) { /* Process fractional digits.*/
2039
                if (b - buf < MAX_DIGITS) {
2040
                        seendigit = 1;
2041
                        *b++ = sc->cc;
2042
                }
2043
                __scan_getc(sc);
2044
        }
2045
 
2046
 DO_DIGIT_CHECK:
2047
        /* Hmm... no decimal point.   */
2048
        if (!seendigit) {
2049
                static const unsigned char nan_inf_str[] = "an\0nfinity";
2050
 
2051
                if (base == 16) {               /* We had a prefix, but no digits! */
2052
                        goto DONE_DO_UNGET;     /* matching failure */
2053
                }
2054
 
2055
                /* Avoid tolower problems for INFINITY in the tr_TR locale. (yuk)*/
2056
#undef TOLOWER
2057
#define TOLOWER(C)     ((C)|0x20)
2058
 
2059
                switch (TOLOWER(sc->cc)) {
2060
                        case 'i':
2061
                                p = nan_inf_str + 3;
2062
                                break;
2063
                        case 'n':
2064
                                p = nan_inf_str;
2065
                                break;
2066
                        default:
2067
                                /* No digits and not inf or nan. */
2068
                                goto DONE_DO_UNGET;
2069
                }
2070
 
2071
                *b++ = sc->cc;
2072
 
2073
                do {
2074
                        __scan_getc(sc);
2075
                        if (TOLOWER(sc->cc) == *p) {
2076
                                *b++ = sc->cc;
2077
                                ++p;
2078
                                continue;
2079
                        }
2080
                        if (!*p || (p == nan_inf_str + 5)) { /* match nan/infinity or inf */
2081
                                goto GOT_FLOAT;
2082
                        }
2083
                        /* Unrecoverable.  Even if on 1st char, we had no digits. */
2084
                        goto DONE_DO_UNGET;
2085
                } while (1);
2086
        }
2087
 
2088
        /* If we get here, we had some digits. */
2089
 
2090
        if (
2091
#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
2092
                ((base == 16) && (((sc->cc)|0x20) == 'p')) ||
2093
#endif
2094
                (((sc->cc)|0x20) == 'e')
2095
                ) {                                             /* Process an exponent. */
2096
                *b++ = sc->cc;
2097
 
2098
                __scan_getc(sc);
2099
                if (sc->cc < 0) {
2100
                        goto DONE_DO_UNGET;     /* matching failure.. no exponent digits */
2101
                }
2102
 
2103
                if ((sc->cc == '+') || (sc->cc == '-')) { /* Signed exponent? */
2104
                        *b++ = sc->cc;
2105
                        __scan_getc(sc);
2106
                }
2107
 
2108
#warning fix MAX_EXP_DIGITS!
2109
#define MAX_EXP_DIGITS 20
2110
                assert(seendigit);
2111
                seendigit = 0;
2112
                nonzero = 0;
2113
 
2114
                if (sc->cc == '0') {
2115
                        seendigit = 1;
2116
                        *b++ = '0';
2117
                        do {
2118
                                __scan_getc(sc);
2119
                        } while (sc->cc == '0');
2120
                }
2121
 
2122
                while (__isdigit_char_or_EOF(sc->cc)) { /* Exponent digits (base 10).*/
2123
                        if (seendigit < MAX_EXP_DIGITS) {
2124
                                ++seendigit;
2125
                                *b++ = sc->cc;
2126
                        }
2127
                        __scan_getc(sc);
2128
                }
2129
 
2130
                if (!seendigit) {               /* No digits.  Unrecoverable. */
2131
                        goto DONE_DO_UNGET;
2132
                }
2133
        }
2134
 
2135
 
2136
 GOT_FLOAT:
2137
        *b = 0;
2138
        {
2139
                __fpmax_t x;
2140
                char *e;
2141
                x = __strtofpmax(buf, &e, exp_adjust);
2142
                assert(!*e);
2143
                if (psfs->store) {
2144
                        if (psfs->dataargtype & PA_FLAG_LONG_LONG) {
2145
                                *((long double *)psfs->cur_ptr) = (long double) x;
2146
                        } else if (psfs->dataargtype & PA_FLAG_LONG) {
2147
                                *((double *)psfs->cur_ptr) = (double) x;
2148
                        } else {
2149
                                *((float *)psfs->cur_ptr) = (float) x;
2150
                        }
2151
                        ++psfs->cnt;
2152
                }
2153
                __scan_ungetc(sc);
2154
                return 0;
2155
        }
2156
#endif /* __UCLIBC_HAS_FLOATS__ */
2157
 
2158
 DONE_DO_UNGET:
2159
        __scan_ungetc(sc);
2160
 DONE:
2161
        return -2;                                      /* Matching failure. */
2162
 
2163
}
2164
#endif
2165
/**********************************************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.