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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [newlib/] [newlib/] [libc/] [stdio/] [vfscanf.c] - Blame information for rev 39

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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