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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [language/] [c/] [libc/] [stdio/] [v2_0/] [src/] [input/] [vfscanf.cxx] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//========================================================================
2
//
3
//      vfscanf.cxx
4
//
5
//      I/O routines for vfscanf() for use with ANSI C library
6
//
7
//========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):     jlarmour
44
// Contributors:  
45
// Date:          2000-04-20
46
// Purpose:     
47
// Description: 
48
// Usage:       
49
//
50
//####DESCRIPTIONEND####
51
//
52
//========================================================================
53
//
54
// This code is based on original code with the following copyright:
55
//
56
/*
57
 * Copyright (c) 1990 The Regents of the University of California.
58
 * All rights reserved.
59
 *
60
 * Redistribution and use in source and binary forms are permitted
61
 * provided that the above copyright notice and this paragraph are
62
 * duplicated in all such forms and that any documentation,
63
 * advertising materials, and other materials related to such
64
 * distribution and use acknowledge that the software was developed
65
 * by the University of California, Berkeley.  The name of the
66
 * University may not be used to endorse or promote products derived
67
 * from this software without specific prior written permission.
68
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
69
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
70
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
71
 */
72
 
73
 
74
// CONFIGURATION
75
 
76
#include <pkgconf/libc_stdio.h>   // Configuration header
77
#include <pkgconf/libc_i18n.h>    // Configuration header for mb support
78
 
79
// We have to have ungetc for this to work
80
#if defined(CYGFUN_LIBC_STDIO_ungetc) 
81
 
82
 
83
// INCLUDES
84
 
85
#include <cyg/infra/cyg_type.h>   // Common type definitions and support
86
#include <stdarg.h>               // Variable argument definitions
87
#include <stdio.h>                // Standard header for all stdio files
88
#include <ctype.h>                // isspace() and isupper()
89
#include <stdlib.h>               // standard utility functions e.g. strtol
90
#include <cyg/libc/stdio/stream.hxx>  // C library streams
91
 
92
#ifdef CYGSEM_LIBC_STDIO_SCANF_FLOATING_POINT
93
 
94
#include <float.h>
95
 
96
# define MAXFRACT   DBL_DIG
97
# define MAXEXP     DBL_MAX_10_EXP
98
 
99
# define BUF      (MAXEXP+MAXFRACT+3)  /* 3 = sign + decimal point + NUL */
100
 
101
#else // ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT
102
 
103
# define BUF            40
104
 
105
#endif // ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT
106
 
107
/*
108
 * Flags used during conversion.
109
 */
110
 
111
#define LONG            0x01    /* l: long or double */
112
#define LONGDBL         0x02    /* L: long double; unimplemented */
113
#define SHORT           0x04    /* h: short */
114
#define SUPPRESS        0x08    /* suppress assignment */
115
#define POINTER         0x10    /* weird %p pointer (`fake hex') */
116
#define NOSKIP          0x20    /* do not skip blanks */
117
 
118
/*
119
 * The following are used in numeric conversions only:
120
 * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
121
 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
122
 */
123
 
124
#define SIGNOK          0x40    /* +/- is (still) legal */
125
#define NDIGITS         0x80    /* no digits detected */
126
 
127
#define DPTOK           0x100   /* (float) decimal point is still legal */
128
#define EXPOK           0x200   /* (float) exponent (e+3, etc) still
129
                                   legal */
130
 
131
#define PFXOK           0x100   /* 0x prefix is (still) legal */
132
#define NZDIGITS        0x200   /* no zero digits detected */
133
 
134
/*
135
 * Conversion types.
136
 */
137
 
138
#define CT_CHAR         0       /* %c conversion */
139
#define CT_CCL          1       /* %[...] conversion */
140
#define CT_STRING       2       /* %s conversion */
141
#define CT_INT          3       /* integer, i.e., strtol or strtoul */
142
#define CT_FLOAT        4       /* floating, i.e., strtod */
143
 
144
#if 0
145
#define u_char unsigned char
146
#endif
147
#define u_char char
148
#define u_long unsigned long
149
 
150
typedef unsigned long (*strtoul_t)(const char *, char **endptr, int base);
151
 
152
static u_char *
153
__sccl (char *tab, u_char *fmt);
154
 
155
 
156
/*
157
 * vfscanf
158
 */
159
 
160
#define _CAST_VOID
161
 
162
#define CURR_POS (file->peek_byte( (cyg_uint8 *)&curr_byte),&curr_byte )
163
 
164
#define INC_CURR_POS ( file->read_byte( (cyg_uint8 *)&curr_byte ) )
165
 
166
#define MOVE_CURR_POS(x) (file->set_position( (x), SEEK_CUR ))
167
 
168
#define SPACE_LEFT (file->bytes_available_to_read())
169
 
170
#define REFILL (file->refill_read_buffer())
171
 
172
#define BufferEmpty ( !SPACE_LEFT && \
173
                      (REFILL, (!SPACE_LEFT)) )
174
 
175
#ifdef CYGINT_LIBC_I18N_MB_REQUIRED
176
typedef int (*mbtowc_fn_type)(wchar_t *, const char *, size_t, int *);
177
externC mbtowc_fn_type __get_current_locale_mbtowc_fn();
178
#endif
179
 
180
externC int
181
vfscanf (FILE *fp, const char *fmt0, va_list ap)
182
{
183
    u_char *fmt = (u_char *) fmt0;
184
    int c;              /* character from format, or conversion */
185
    wchar_t wc;         /* wide character from format */
186
    size_t width;       /* field width, or 0 */
187
    char *p;            /* points into all kinds of strings */
188
    int n;              /* handy integer */
189
    int flags;          /* flags as defined above */
190
    char *p0;           /* saves original value of p when necessary */
191
    char *lptr;         /* literal pointer */
192
    int nassigned;      /* number of fields assigned */
193
    int nread;          /* number of characters consumed from fp */
194
    int base = 0;       /* base argument to strtol/strtoul */
195
    int nbytes = 1;     /* number of bytes processed */
196
 
197
#ifdef CYGINT_LIBC_I18N_MB_REQUIRED
198
    mbtowc_fn_type mbtowc_fn;
199
    int state = 0;      /* used for mbtowc_fn */
200
#endif
201
 
202
    strtoul_t ccfn = NULL;      /* conversion function (strtol/strtoul) */
203
    char ccltab[256];           /* character class table for %[...] */
204
    char buf[BUF];              /* buffer for numeric conversions */
205
 
206
    Cyg_StdioStream *file = (Cyg_StdioStream *)fp;
207
    char curr_byte;
208
 
209
    short *sp;
210
    int *ip;
211
    float *flp;
212
    long double *ldp;
213
    double *dp;
214
    long *lp;
215
 
216
    /* `basefix' is used to avoid `if' tests in the integer scanner */
217
    static const short basefix[17] =
218
    {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
219
 
220
#ifdef CYGINT_LIBC_I18N_MB_REQUIRED
221
    mbtowc_fn = __get_current_locale_mbtowc_fn();
222
#endif
223
 
224
    nassigned = 0;
225
    nread = 0;
226
    for (;;)
227
    {
228
#ifndef CYGINT_LIBC_I18N_MB_REQUIRED
229
        wc = *fmt;
230
#else
231
        nbytes = mbtowc_fn (&wc, fmt, MB_CUR_MAX, &state);
232
#endif
233
        fmt += nbytes;
234
 
235
        if (wc == 0)
236
           return nassigned;
237
        if (nbytes == 1 && isspace (wc))
238
        {
239
            for (;;)
240
            {
241
                if (BufferEmpty)
242
                    return nassigned;
243
                if (!isspace (*CURR_POS))
244
                    break;
245
                nread++, INC_CURR_POS;
246
            }
247
            continue;
248
        }
249
        if (wc != '%')
250
            goto literal;
251
        width = 0;
252
        flags = 0;
253
 
254
        /*
255
         * switch on the format.  continue if done; break once format
256
         * type is derived.
257
         */
258
 
259
again:
260
        c = *fmt++;
261
 
262
        switch (c)
263
        {
264
        case '%':
265
literal:
266
            lptr = fmt - nbytes;
267
            for (n = 0; n < nbytes; ++n)
268
              {
269
                if (BufferEmpty)
270
                  goto input_failure;
271
                if (*CURR_POS != *lptr)
272
                  goto match_failure;
273
                INC_CURR_POS;
274
                nread++;
275
                ++lptr;
276
              }
277
        continue;
278
 
279
        case '*':
280
            flags |= SUPPRESS;
281
            goto again;
282
        case 'l':
283
            flags |= LONG;
284
            goto again;
285
        case 'L':
286
            flags |= LONGDBL;
287
            goto again;
288
        case 'h':
289
            flags |= SHORT;
290
            goto again;
291
 
292
        case '0':
293
        case '1':
294
        case '2':
295
        case '3':
296
        case '4':
297
        case '5':
298
        case '6':
299
        case '7':
300
        case '8':
301
        case '9':
302
            width = width * 10 + c - '0';
303
            goto again;
304
 
305
            /*
306
             * Conversions. Those marked `compat' are for
307
             * 4.[123]BSD compatibility.
308
             *
309
             * (According to ANSI, E and X formats are supposed to
310
             * the same as e and x.  Sorry about that.)
311
             */
312
 
313
        case 'D':               /* compat */
314
            flags |= LONG;
315
            /* FALLTHROUGH */
316
        case 'd':
317
            c = CT_INT;
318
            ccfn = (strtoul_t)strtol;
319
            base = 10;
320
            break;
321
 
322
        case 'i':
323
            c = CT_INT;
324
            ccfn = (strtoul_t)strtol;
325
            base = 0;
326
            break;
327
 
328
        case 'O':               /* compat */
329
            flags |= LONG;
330
            /* FALLTHROUGH */
331
        case 'o':
332
            c = CT_INT;
333
            ccfn = strtoul;
334
            base = 8;
335
            break;
336
 
337
        case 'u':
338
            c = CT_INT;
339
            ccfn = strtoul;
340
            base = 10;
341
            break;
342
 
343
        case 'X':               /* compat   XXX */
344
        case 'x':
345
            flags |= PFXOK;     /* enable 0x prefixing */
346
            c = CT_INT;
347
            ccfn = strtoul;
348
            base = 16;
349
            break;
350
 
351
        case 'E':               /* compat   XXX */
352
        case 'G':               /* compat   XXX */
353
/* ANSI says that E,G and X behave the same way as e,g,x */
354
            /* FALLTHROUGH */
355
        case 'e':
356
        case 'f':
357
        case 'g':
358
            c = CT_FLOAT;
359
            break;
360
 
361
        case 's':
362
            c = CT_STRING;
363
            break;
364
 
365
        case '[':
366
            fmt = __sccl (ccltab, fmt);
367
            flags |= NOSKIP;
368
            c = CT_CCL;
369
            break;
370
 
371
        case 'c':
372
            flags |= NOSKIP;
373
            c = CT_CHAR;
374
            break;
375
 
376
        case 'p':               /* pointer format is like hex */
377
            flags |= POINTER | PFXOK;
378
            c = CT_INT;
379
            ccfn = strtoul;
380
            base = 16;
381
            break;
382
 
383
        case 'n':
384
            if (flags & SUPPRESS)       /* ??? */
385
                continue;
386
            if (flags & SHORT)
387
            {
388
                sp = va_arg (ap, short *);
389
                *sp = nread;
390
            }
391
            else if (flags & LONG)
392
            {
393
                lp = va_arg (ap, long *);
394
                *lp = nread;
395
            }
396
            else
397
            {
398
                ip = va_arg (ap, int *);
399
                *ip = nread;
400
            }
401
            continue;
402
 
403
            /*
404
             * Disgusting backwards compatibility hacks.        XXX
405
             */
406
        case '\0':              /* compat */
407
            return EOF;
408
 
409
        default:                /* compat */
410
            if (isupper (c))
411
                flags |= LONG;
412
            c = CT_INT;
413
            ccfn = (strtoul_t)strtol;
414
            base = 10;
415
            break;
416
        }
417
 
418
        /*
419
         * We have a conversion that requires input.
420
         */
421
        if (BufferEmpty)
422
            goto input_failure;
423
 
424
        /*
425
         * Consume leading white space, except for formats that
426
         * suppress this.
427
         */
428
        if ((flags & NOSKIP) == 0)
429
        {
430
            while (isspace (*CURR_POS))
431
            {
432
                nread++;
433
                INC_CURR_POS;
434
                if (SPACE_LEFT == 0)
435
#ifndef REDHAT_NEC
436
                    if (REFILL)
437
#endif
438
                        goto input_failure;
439
            }
440
            /*
441
             * Note that there is at least one character in the
442
             * buffer, so conversions that do not set NOSKIP ca
443
             * no longer result in an input failure.
444
             */
445
        }
446
 
447
        /*
448
         * Do the conversion.
449
         */
450
        switch (c)
451
        {
452
 
453
        case CT_CHAR:
454
            /* scan arbitrary characters (sets NOSKIP) */
455
            if (width == 0)
456
                width = 1;
457
            if (flags & SUPPRESS)
458
            {
459
                size_t sum = 0;
460
 
461
                for (;;)
462
                {
463
                    if ((n = SPACE_LEFT) < (signed)width)
464
                    {
465
                        sum += n;
466
                        width -= n;
467
                        MOVE_CURR_POS(n-1);
468
                        INC_CURR_POS;
469
#ifndef REDHAT_NEC
470
                        if (REFILL)
471
                        {
472
#endif
473
                            if (sum == 0)
474
                                goto input_failure;
475
                            break;
476
#ifndef REDHAT_NEC
477
                        }
478
#endif
479
                    }
480
                    else
481
                    {
482
                        sum += width;
483
                        MOVE_CURR_POS(width - 1);
484
                        INC_CURR_POS;
485
                        break;
486
                    }
487
                }
488
                nread += sum;
489
            }
490
            else
491
            {
492
                /* Kludge city for the moment */
493
                char *dest = va_arg (ap, char *);
494
                int n = width;
495
                if (SPACE_LEFT == 0)
496
#ifndef REDHAT_NEC
497
                    if (REFILL)
498
#endif
499
                        goto input_failure;
500
 
501
                while (n && !BufferEmpty)
502
                {
503
                    *dest++ = *CURR_POS;
504
                    INC_CURR_POS;
505
                    n--;
506
                    nread++;
507
                }
508
                nassigned++;
509
            }
510
            break;
511
 
512
        case CT_CCL:
513
            /* scan a (nonempty) character class (sets NOSKIP) */
514
            if (width == 0)
515
                width = ~0;             /* `infinity' */
516
            /* take only those things in the class */
517
            if (flags & SUPPRESS)
518
            {
519
                n = 0;
520
                while (ccltab[*CURR_POS])
521
                {
522
                    n++, INC_CURR_POS;
523
                    if (--width == 0)
524
                        break;
525
                    if (BufferEmpty)
526
                    {
527
                        if (n == 0)
528
                            goto input_failure;
529
                        break;
530
                    }
531
                }
532
                if (n == 0)
533
                    goto match_failure;
534
            }
535
            else
536
            {
537
                p0 = p = va_arg (ap, char *);
538
                while (ccltab[*CURR_POS])
539
                {
540
                    *p++ = *CURR_POS;
541
                    INC_CURR_POS;
542
                    if (--width == 0)
543
                        break;
544
                    if (BufferEmpty)
545
                    {
546
                        if (p == p0)
547
                            goto input_failure;
548
                        break;
549
                    }
550
                }
551
                n = p - p0;
552
                if (n == 0)
553
                    goto match_failure;
554
                *p = 0;
555
                nassigned++;
556
            }
557
            nread += n;
558
            break;
559
 
560
        case CT_STRING:
561
            /* like CCL, but zero-length string OK, & no NOSKIP */
562
            if (width == 0)
563
                width = ~0;
564
            if (flags & SUPPRESS)
565
            {
566
                n = 0;
567
                while (!isspace (*CURR_POS))
568
                {
569
                    n++, INC_CURR_POS;
570
                    if (--width == 0)
571
                        break;
572
                    if (BufferEmpty)
573
                        break;
574
                }
575
                nread += n;
576
            }
577
            else
578
            {
579
                p0 = p = va_arg (ap, char *);
580
                while (!isspace (*CURR_POS))
581
                {
582
                    *p++ = *CURR_POS;
583
                    INC_CURR_POS;
584
                    if (--width == 0)
585
                        break;
586
                    if (BufferEmpty)
587
                        break;
588
                }
589
                *p = 0;
590
                nread += p - p0;
591
                nassigned++;
592
            }
593
            continue;
594
 
595
        case CT_INT:
596
            /* scan an integer as if by strtol/strtoul */
597
#ifdef hardway
598
            if (width == 0 || width > sizeof (buf) - 1)
599
                width = sizeof (buf) - 1;
600
#else
601
            /* size_t is unsigned, hence this optimisation */
602
            if (--width > sizeof (buf) - 2)
603
                width = sizeof (buf) - 2;
604
            width++;
605
#endif
606
            flags |= SIGNOK | NDIGITS | NZDIGITS;
607
            for (p = buf; width; width--)
608
            {
609
                c = *CURR_POS;
610
                /*
611
                 * Switch on the character; `goto ok' if we
612
                 * accept it as a part of number.
613
                 */
614
                switch (c)
615
                {
616
                    /*
617
                     * The digit 0 is always legal, but is special.
618
                     * For %i conversions, if no digits (zero or nonzero)
619
                     * have been scanned (only signs), we will have base==0
620
                     * In that case, we should set it to 8 and enable 0x
621
                     * prefixing. Also, if we have not scanned zero digits
622
                     * before this, do not turn off prefixing (someone else
623
                     * will turn it off if we have scanned any nonzero
624
                     * digits).
625
                     */
626
                case '0':
627
                    if (base == 0)
628
                    {
629
                        base = 8;
630
                        flags |= PFXOK;
631
                    }
632
                    if (flags & NZDIGITS)
633
                        flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
634
                    else
635
                        flags &= ~(SIGNOK | PFXOK | NDIGITS);
636
                    goto ok;
637
 
638
                    /* 1 through 7 always legal */
639
                case '1':
640
                case '2':
641
                case '3':
642
                case '4':
643
                case '5':
644
                case '6':
645
                case '7':
646
                    base = basefix[base];
647
                    flags &= ~(SIGNOK | PFXOK | NDIGITS);
648
                    goto ok;
649
 
650
                    /* digits 8 and 9 ok iff decimal or hex */
651
                case '8':
652
                case '9':
653
                    base = basefix[base];
654
                    if (base <= 8)
655
                        break;  /* not legal here */
656
                    flags &= ~(SIGNOK | PFXOK | NDIGITS);
657
                    goto ok;
658
 
659
                    /* letters ok iff hex */
660
                case 'A':
661
                case 'B':
662
                case 'C':
663
                case 'D':
664
                case 'E':
665
                case 'F':
666
                case 'a':
667
                case 'b':
668
                case 'c':
669
                case 'd':
670
                case 'e':
671
                case 'f':
672
                    /* no need to fix base here */
673
                    if (base <= 10)
674
                        break;  /* not legal here */
675
                    flags &= ~(SIGNOK | PFXOK | NDIGITS);
676
                    goto ok;
677
 
678
                    /* sign ok only as first character */
679
                case '+':
680
                case '-':
681
                    if (flags & SIGNOK)
682
                    {
683
                        flags &= ~SIGNOK;
684
                        goto ok;
685
                    }
686
                    break;
687
 
688
                    /* x ok iff flag still set & 2nd char */
689
                case 'x':
690
                case 'X':
691
                    if (flags & PFXOK && p == buf + 1)
692
                    {
693
                        base = 16;/* if %i */
694
                        flags &= ~PFXOK;
695
                        goto ok;
696
                    }
697
                    break;
698
                }
699
 
700
                /*
701
                 * If we got here, c is not a legal character
702
                 * for a number.  Stop accumulating digits.
703
                 */
704
                break;
705
            ok:
706
                /*
707
                 * c is legal: store it and look at the next.
708
                 */
709
                *p++ = c;
710
                INC_CURR_POS;
711
                if (SPACE_LEFT == 0)
712
#ifndef REDHAT_NEC
713
                    if (REFILL)
714
#endif
715
                        break;          /* EOF */
716
            }
717
            /*
718
             * If we had only a sign, it is no good; push back the sign.
719
             * If the number ends in `x', it was [sign] '0' 'x', so push
720
             * back the x and treat it as [sign] '0'.
721
             */
722
            if (flags & NDIGITS)
723
            {
724
                if (p > buf)
725
                    _CAST_VOID ungetc (*(u_char *)-- p, fp);
726
                goto match_failure;
727
            }
728
            c = ((u_char *) p)[-1];
729
            if (c == 'x' || c == 'X')
730
            {
731
                --p;
732
                /*(void)*/ ungetc (c, fp);
733
            }
734
            if ((flags & SUPPRESS) == 0)
735
            {
736
                u_long res;
737
 
738
                *p = 0;
739
                res = (*ccfn) (buf, (char **) NULL, base);
740
                if (flags & POINTER)
741
                    *(va_arg (ap, char **)) = (char *) (CYG_ADDRESS) res;
742
                else if (flags & SHORT)
743
                {
744
                    sp = va_arg (ap, short *);
745
                    *sp = res;
746
                }
747
                else if (flags & LONG)
748
                {
749
                    lp = va_arg (ap, long *);
750
                    *lp = res;
751
                }
752
                else
753
                {
754
                    ip = va_arg (ap, int *);
755
                    *ip = res;
756
                }
757
                nassigned++;
758
            }
759
            nread += p - buf;
760
            break;
761
 
762
        case CT_FLOAT:
763
            /* scan a floating point number as if by strtod */
764
 
765
#ifdef hardway
766
            if (width == 0 || width > sizeof (buf) - 1)
767
                width = sizeof (buf) - 1;
768
#else
769
            /* size_t is unsigned, hence this optimisation */
770
            if (--width > sizeof (buf) - 2)
771
                width = sizeof (buf) - 2;
772
            width++;
773
#endif // ifdef hardway
774
 
775
            flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
776
            for (p = buf; width; width--)
777
            {
778
                c = *CURR_POS;
779
                /*
780
                 * This code mimicks the integer conversion
781
                 * code, but is much simpler.
782
                 */
783
                switch (c)
784
                {
785
 
786
                case '0':
787
                case '1':
788
                case '2':
789
                case '3':
790
                case '4':
791
                case '5':
792
                case '6':
793
                case '7':
794
                case '8':
795
                case '9':
796
                    flags &= ~(SIGNOK | NDIGITS);
797
                    goto fok;
798
 
799
                case '+':
800
                case '-':
801
                    if (flags & SIGNOK)
802
                    {
803
                        flags &= ~SIGNOK;
804
                        goto fok;
805
                    }
806
                    break;
807
                case '.':
808
                    if (flags & DPTOK)
809
                    {
810
                        flags &= ~(SIGNOK | DPTOK);
811
                        goto fok;
812
                    }
813
                    break;
814
                case 'e':
815
                case 'E':
816
                    /* no exponent without some digits */
817
                    if ((flags & (NDIGITS | EXPOK)) == EXPOK)
818
                    {
819
                        flags =
820
                            (flags & ~(EXPOK | DPTOK)) |
821
                            SIGNOK | NDIGITS;
822
                        goto fok;
823
                    }
824
                    break;
825
                }
826
                break;
827
            fok:
828
                *p++ = c;
829
                INC_CURR_POS;
830
                if (SPACE_LEFT == 0)
831
#ifndef REDHAT_NEC
832
                    if (REFILL)
833
#endif
834
                        break;          /* EOF */
835
            }
836
            /*
837
             * If no digits, might be missing exponent digits
838
             * (just give back the exponent) or might be missing
839
             * regular digits, but had sign and/or decimal point.
840
             */
841
            if (flags & NDIGITS)
842
            {
843
                if (flags & EXPOK)
844
                {
845
                    /* no digits at all */
846
                    while (p > buf)
847
                        ungetc (*(u_char *)-- p, fp);
848
                    goto match_failure;
849
                }
850
                /* just a bad exponent (e and maybe sign) */
851
                c = *(u_char *)-- p;
852
                if (c != 'e' && c != 'E')
853
                {
854
                    _CAST_VOID ungetc (c, fp); /* sign */
855
                    c = *(u_char *)-- p;
856
                }
857
                _CAST_VOID ungetc (c, fp);
858
            }
859
            if ((flags & SUPPRESS) == 0)
860
            {
861
                double res;
862
 
863
                *p = 0;
864
#ifdef CYGSEM_LIBC_STDIO_SCANF_FLOATING_POINT
865
                res = atof (buf);
866
#else
867
                res = 0.0;
868
#endif
869
                if (flags & LONG)
870
                {
871
                    dp = va_arg (ap, double *);
872
                    *dp = res;
873
                }
874
                else if (flags & LONGDBL)
875
                {
876
                    ldp = va_arg (ap, long double *);
877
                    *ldp = res;
878
                }
879
                else
880
                {
881
                    flp = va_arg (ap, float *);
882
                    *flp = res;
883
                }
884
                nassigned++;
885
            }
886
            nread += p - buf;
887
            break;
888
        }
889
    }
890
 
891
input_failure:
892
    return nassigned ? nassigned : -1;
893
match_failure:
894
    return nassigned;
895
} // vfscanf()
896
 
897
/*
898
 * Fill in the given table from the scanset at the given format
899
 * (just after `[').  Return a pointer to the character past the
900
 * closing `]'.  The table has a 1 wherever characters should be
901
 * considered part of the scanset.
902
 */
903
 
904
/*static*/
905
u_char *
906
__sccl (char *tab, u_char *fmt)
907
{
908
    int c, n, v;
909
 
910
    /* first `clear' the whole table */
911
    c = *fmt++;                 /* first char hat => negated scanset */
912
    if (c == '^')
913
    {
914
        v = 1;                  /* default => accept */
915
        c = *fmt++;             /* get new first char */
916
    }
917
    else
918
        v = 0;                  /* default => reject */
919
    /* should probably use memset here */
920
    for (n = 0; n < 256; n++)
921
        tab[n] = v;
922
    if (c == 0)
923
        return fmt - 1;         /* format ended before closing ] */
924
 
925
    /*
926
     * Now set the entries corresponding to the actual scanset to the
927
     * opposite of the above.
928
     *
929
     * The first character may be ']' (or '-') without being special; the
930
     * last character may be '-'.
931
     */
932
 
933
    v = 1 - v;
934
    for (;;)
935
    {
936
        tab[c] = v;             /* take character c */
937
    doswitch:
938
        n = *fmt++;             /* and examine the next */
939
        switch (n)
940
        {
941
 
942
        case 0:         /* format ended too soon */
943
            return fmt - 1;
944
 
945
        case '-':
946
            /*
947
             * A scanset of the form [01+-] is defined as `the digit 0, the
948
             * digit 1, the character +, the character -', but the effect
949
             * of a scanset such as [a-zA-Z0-9] is implementation defined.
950
             * The V7 Unix scanf treats `a-z' as `the letters a through z',
951
             * but treats `a-a' as `the letter a, the character -, and the
952
             * letter a'.
953
             *
954
             * For compatibility, the `-' is not considerd to define a
955
             * range if the character following it is either a close
956
             * bracket (required by ANSI) or is not numerically greater
957
             * than the character we just stored in the table (c).
958
             */
959
            n = *fmt;
960
            if (n == ']' || n < c)
961
            {
962
                c = '-';
963
                break;          /* resume the for(;;) */
964
            }
965
            fmt++;
966
            do
967
            {                   /* fill in the range */
968
                tab[++c] = v;
969
            }
970
            while (c < n);
971
#if 1                   /* XXX another disgusting compatibility hack */
972
            /*
973
             * Alas, the V7 Unix scanf also treats formats such
974
             * as [a-c-e] as `the letters a through e'. This too
975
             * is permitted by the standard....
976
             */
977
            goto doswitch;
978
#else
979
            c = *fmt++;
980
            if (c == 0)
981
                return fmt - 1;
982
            if (c == ']')
983
                return fmt;
984
#endif
985
 
986
            break;
987
 
988
 
989
        case ']':               /* end of scanset */
990
            return fmt;
991
 
992
        default:                /* just another character */
993
            c = n;
994
            break;
995
        }
996
    }
997
    /* NOTREACHED */
998
} // __sccl()
999
 
1000
#endif // if defined(CYGFUN_LIBC_STDIO_ungetc)
1001
 
1002
// EOF vfscanf.cxx

powered by: WebSVN 2.1.0

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