Commit | Line | Data |
---|---|---|
2ce81398 DS |
1 | #if defined(LIBC_SCCS) && !defined(lint) |
2 | static char sccsid[] = "@(#)vfscanf.c 5.2 (Berkeley) %G%"; | |
3 | #endif LIBC_SCCS and not lint | |
87bdee5f | 4 | |
87bdee5f KM |
5 | #include <stdio.h> |
6 | #include <ctype.h> | |
7 | ||
8 | #define SPC 01 | |
9 | #define STP 02 | |
10 | ||
11 | #define SHORT 0 | |
12 | #define REGULAR 1 | |
13 | #define LONG 2 | |
14 | #define INT 0 | |
15 | #define FLOAT 1 | |
16 | ||
41e01b3e | 17 | static char *_getccl(); |
87bdee5f | 18 | |
41e01b3e | 19 | static char _sctab[256] = { |
87bdee5f KM |
20 | 0,0,0,0,0,0,0,0, |
21 | 0,SPC,SPC,0,0,0,0,0, | |
22 | 0,0,0,0,0,0,0,0, | |
23 | 0,0,0,0,0,0,0,0, | |
24 | SPC,0,0,0,0,0,0,0, | |
25 | 0,0,0,0,0,0,0,0, | |
26 | 0,0,0,0,0,0,0,0, | |
27 | 0,0,0,0,0,0,0,0, | |
28 | }; | |
29 | ||
30 | _doscan(iop, fmt, argp) | |
31 | FILE *iop; | |
32 | register char *fmt; | |
33 | register int **argp; | |
34 | { | |
35 | register int ch; | |
36 | int nmatch, len, ch1; | |
37 | int **ptr, fileended, size; | |
38 | ||
39 | nmatch = 0; | |
40 | fileended = 0; | |
41 | for (;;) switch (ch = *fmt++) { | |
42 | case '\0': | |
43 | return (nmatch); | |
44 | case '%': | |
45 | if ((ch = *fmt++) == '%') | |
46 | goto def; | |
47 | ptr = 0; | |
48 | if (ch != '*') | |
49 | ptr = argp++; | |
50 | else | |
51 | ch = *fmt++; | |
52 | len = 0; | |
53 | size = REGULAR; | |
54 | while (isdigit(ch)) { | |
55 | len = len*10 + ch - '0'; | |
56 | ch = *fmt++; | |
57 | } | |
58 | if (len == 0) | |
59 | len = 30000; | |
60 | if (ch=='l') { | |
61 | size = LONG; | |
62 | ch = *fmt++; | |
63 | } else if (ch=='h') { | |
64 | size = SHORT; | |
65 | ch = *fmt++; | |
66 | } else if (ch=='[') | |
67 | fmt = _getccl(fmt); | |
68 | if (isupper(ch)) { | |
69 | ch = tolower(ch); | |
70 | size = LONG; | |
71 | } | |
72 | if (ch == '\0') | |
73 | return(-1); | |
74 | if (_innum(ptr, ch, len, size, iop, &fileended) && ptr) | |
75 | nmatch++; | |
76 | if (fileended) | |
77 | return(nmatch? nmatch: -1); | |
78 | break; | |
79 | ||
80 | case ' ': | |
81 | case '\n': | |
82 | case '\t': | |
83 | while ((ch1 = getc(iop))==' ' || ch1=='\t' || ch1=='\n') | |
84 | ; | |
85 | if (ch1 != EOF) | |
86 | ungetc(ch1, iop); | |
87 | break; | |
88 | ||
89 | default: | |
90 | def: | |
91 | ch1 = getc(iop); | |
92 | if (ch1 != ch) { | |
93 | if (ch1==EOF) | |
94 | return(-1); | |
95 | ungetc(ch1, iop); | |
96 | return(nmatch); | |
97 | } | |
98 | } | |
99 | } | |
100 | ||
41e01b3e | 101 | static |
87bdee5f KM |
102 | _innum(ptr, type, len, size, iop, eofptr) |
103 | int **ptr, *eofptr; | |
41e01b3e | 104 | FILE *iop; |
87bdee5f KM |
105 | { |
106 | extern double atof(); | |
107 | register char *np; | |
108 | char numbuf[64]; | |
109 | register c, base; | |
110 | int expseen, scale, negflg, c1, ndigit; | |
111 | long lcval; | |
112 | ||
113 | if (type=='c' || type=='s' || type=='[') | |
114 | return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len, iop, eofptr)); | |
115 | lcval = 0; | |
116 | ndigit = 0; | |
117 | scale = INT; | |
118 | if (type=='e'||type=='f') | |
119 | scale = FLOAT; | |
120 | base = 10; | |
121 | if (type=='o') | |
122 | base = 8; | |
123 | else if (type=='x') | |
124 | base = 16; | |
125 | np = numbuf; | |
126 | expseen = 0; | |
127 | negflg = 0; | |
128 | while ((c = getc(iop))==' ' || c=='\t' || c=='\n'); | |
129 | if (c=='-') { | |
130 | negflg++; | |
131 | *np++ = c; | |
132 | c = getc(iop); | |
133 | len--; | |
134 | } else if (c=='+') { | |
135 | len--; | |
136 | c = getc(iop); | |
137 | } | |
138 | for ( ; --len>=0; *np++ = c, c = getc(iop)) { | |
139 | if (isdigit(c) | |
140 | || base==16 && ('a'<=c && c<='f' || 'A'<=c && c<='F')) { | |
141 | ndigit++; | |
142 | if (base==8) | |
143 | lcval <<=3; | |
144 | else if (base==10) | |
145 | lcval = ((lcval<<2) + lcval)<<1; | |
146 | else | |
147 | lcval <<= 4; | |
148 | c1 = c; | |
149 | if (isdigit(c)) | |
150 | c -= '0'; | |
151 | else if ('a'<=c && c<='f') | |
152 | c -= 'a'-10; | |
153 | else | |
154 | c -= 'A'-10; | |
155 | lcval += c; | |
156 | c = c1; | |
157 | continue; | |
158 | } else if (c=='.') { | |
159 | if (base!=10 || scale==INT) | |
160 | break; | |
161 | ndigit++; | |
162 | continue; | |
163 | } else if ((c=='e'||c=='E') && expseen==0) { | |
164 | if (base!=10 || scale==INT || ndigit==0) | |
165 | break; | |
166 | expseen++; | |
167 | *np++ = c; | |
168 | c = getc(iop); | |
169 | if (c!='+'&&c!='-'&&('0'>c||c>'9')) | |
170 | break; | |
171 | } else | |
172 | break; | |
173 | } | |
174 | if (negflg) | |
175 | lcval = -lcval; | |
176 | if (c != EOF) { | |
177 | ungetc(c, iop); | |
178 | *eofptr = 0; | |
179 | } else | |
180 | *eofptr = 1; | |
8ed00122 | 181 | if (ptr==NULL || np==numbuf || (negflg && np==numbuf+1) )/* gene dykes*/ |
87bdee5f KM |
182 | return(0); |
183 | *np++ = 0; | |
184 | switch((scale<<4) | size) { | |
185 | ||
186 | case (FLOAT<<4) | SHORT: | |
187 | case (FLOAT<<4) | REGULAR: | |
188 | **(float **)ptr = atof(numbuf); | |
189 | break; | |
190 | ||
191 | case (FLOAT<<4) | LONG: | |
192 | **(double **)ptr = atof(numbuf); | |
193 | break; | |
194 | ||
195 | case (INT<<4) | SHORT: | |
196 | **(short **)ptr = lcval; | |
197 | break; | |
198 | ||
199 | case (INT<<4) | REGULAR: | |
200 | **(int **)ptr = lcval; | |
201 | break; | |
202 | ||
203 | case (INT<<4) | LONG: | |
204 | **(long **)ptr = lcval; | |
205 | break; | |
206 | } | |
207 | return(1); | |
208 | } | |
209 | ||
41e01b3e | 210 | static |
87bdee5f KM |
211 | _instr(ptr, type, len, iop, eofptr) |
212 | register char *ptr; | |
41e01b3e | 213 | register FILE *iop; |
87bdee5f KM |
214 | int *eofptr; |
215 | { | |
216 | register ch; | |
217 | register char *optr; | |
218 | int ignstp; | |
219 | ||
220 | *eofptr = 0; | |
221 | optr = ptr; | |
222 | if (type=='c' && len==30000) | |
223 | len = 1; | |
224 | ignstp = 0; | |
225 | if (type=='s') | |
226 | ignstp = SPC; | |
41e01b3e S |
227 | while ((ch = getc(iop)) != EOF && _sctab[ch] & ignstp) |
228 | ; | |
87bdee5f KM |
229 | ignstp = SPC; |
230 | if (type=='c') | |
231 | ignstp = 0; | |
232 | else if (type=='[') | |
233 | ignstp = STP; | |
234 | while (ch!=EOF && (_sctab[ch]&ignstp)==0) { | |
235 | if (ptr) | |
236 | *ptr++ = ch; | |
237 | if (--len <= 0) | |
238 | break; | |
239 | ch = getc(iop); | |
240 | } | |
241 | if (ch != EOF) { | |
242 | if (len > 0) | |
243 | ungetc(ch, iop); | |
244 | *eofptr = 0; | |
245 | } else | |
246 | *eofptr = 1; | |
247 | if (ptr && ptr!=optr) { | |
248 | if (type!='c') | |
249 | *ptr++ = '\0'; | |
250 | return(1); | |
251 | } | |
252 | return(0); | |
253 | } | |
254 | ||
41e01b3e | 255 | static char * |
87bdee5f | 256 | _getccl(s) |
41e01b3e | 257 | register unsigned char *s; |
87bdee5f KM |
258 | { |
259 | register c, t; | |
260 | ||
261 | t = 0; | |
262 | if (*s == '^') { | |
263 | t++; | |
264 | s++; | |
265 | } | |
41e01b3e | 266 | for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++) |
87bdee5f KM |
267 | if (t) |
268 | _sctab[c] &= ~STP; | |
269 | else | |
270 | _sctab[c] |= STP; | |
41e01b3e | 271 | if ((c = *s) == ']' || c == '-') { /* first char is special */ |
87bdee5f | 272 | if (t) |
41e01b3e | 273 | _sctab[c] |= STP; |
87bdee5f | 274 | else |
41e01b3e S |
275 | _sctab[c] &= ~STP; |
276 | s++; | |
277 | } | |
278 | while ((c = *s++) != ']') { | |
87bdee5f | 279 | if (c==0) |
41e01b3e S |
280 | return((char *)--s); |
281 | else if (c == '-' && *s != ']' && s[-2] < *s) { | |
282 | for (c = s[-2] + 1; c < *s; c++) | |
283 | if (t) | |
284 | _sctab[c] |= STP; | |
285 | else | |
286 | _sctab[c] &= ~STP; | |
287 | } else if (t) | |
288 | _sctab[c] |= STP; | |
289 | else | |
290 | _sctab[c] &= ~STP; | |
87bdee5f | 291 | } |
41e01b3e | 292 | return((char *)s); |
87bdee5f | 293 | } |