1 /*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * and/or other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18 /* Split from vfscanf.c */
19
20 #define _DEFAULT_SOURCE
21 #include <_ansi.h>
22 #include <newlib.h>
23 #include <stdio.h>
24 #include "local.h"
25
26 /*
27 * Fill in the given table from the scanset at the given format
28 * (just after `['). Return a pointer to the character past the
29 * closing `]'. The table has a 1 wherever characters should be
30 * considered part of the scanset.
31 */
32
33 u_char *
__sccl(register char * tab,register u_char * fmt)34 __sccl (register char *tab,
35 register u_char *fmt)
36 {
37 register int c, n, v;
38
39 /* first `clear' the whole table */
40 c = *fmt++; /* first char hat => negated scanset */
41 if (c == '^')
42 {
43 v = 1; /* default => accept */
44 c = *fmt++; /* get new first char */
45 }
46 else
47 v = 0; /* default => reject */
48 /* should probably use memset here */
49 for (n = 0; n < 256; n++)
50 tab[n] = v;
51 if (c == 0)
52 return fmt - 1; /* format ended before closing ] */
53
54 /*
55 * Now set the entries corresponding to the actual scanset to the
56 * opposite of the above.
57 *
58 * The first character may be ']' (or '-') without being special; the
59 * last character may be '-'.
60 */
61
62 v = 1 - v;
63 for (;;)
64 {
65 tab[c] = v; /* take character c */
66 doswitch:
67 n = *fmt++; /* and examine the next */
68 switch (n)
69 {
70
71 case 0: /* format ended too soon */
72 return fmt - 1;
73
74 case '-':
75 /*
76 * A scanset of the form [01+-] is defined as `the digit 0, the
77 * digit 1, the character +, the character -', but the effect of a
78 * scanset such as [a-zA-Z0-9] is implementation defined. The V7
79 * Unix scanf treats `a-z' as `the letters a through z', but treats
80 * `a-a' as `the letter a, the character -, and the letter a'.
81 *
82 * For compatibility, the `-' is not considerd to define a range if
83 * the character following it is either a close bracket (required by
84 * ANSI) or is not numerically greater than the character we just
85 * stored in the table (c).
86 */
87 n = *fmt;
88 if (n == ']' || n < c)
89 {
90 c = '-';
91 break; /* resume the for(;;) */
92 }
93 fmt++;
94 do
95 { /* fill in the range */
96 tab[++c] = v;
97 }
98 while (c < n);
99 #if 1 /* XXX another disgusting compatibility hack */
100 /*
101 * Alas, the V7 Unix scanf also treats formats such
102 * as [a-c-e] as `the letters a through e'. This too
103 * is permitted by the standard....
104 */
105 goto doswitch;
106 #else
107 c = *fmt++;
108 if (c == 0)
109 return fmt - 1;
110 if (c == ']')
111 return fmt;
112 #endif
113
114 break;
115
116
117 case ']': /* end of scanset */
118 return fmt;
119
120 default: /* just another character */
121 c = n;
122 break;
123 }
124 }
125 /* NOTREACHED */
126 }
127