BSD 1 development
[unix-history] / portlib / scanf.c
CommitLineData
520d5775
EA
1# include "iodec.h"
2
3/*
4** formatted read routine
5**
6** based on scanf() in the portable C library
7*/
8
9
10int (*__getc)(), (*__ungc)();
11int __input;
12
13scanf(paramlist)
14char *paramlist;
15{
16 extern cgetc(), ungetc();
17 extern __gets(), __ungs();
18 register char **p;
19 extern int cin;
20 register int nmatch;
21 char *format;
22 register char ch;
23 char match_ch;
24
25 p = &paramlist;
26 __getc = cgetc;
27 __ungc = ungetc;
28 __input = cin;
29 if (paramlist == -1)
30 {
31 p++;
32 __getc = __gets;
33 __ungc = __ungs;
34 __input = p++;
35 }
36 else
37 if (paramlist >= 0 && paramlist < MAXFILES)
38 {
39 __input = *p++;
40 }
41 nmatch = 0;
42 format = *p++;
43 while (1)
44 {
45 switch (ch = *format++)
46 {
47
48 case '\0':
49 return (nmatch);
50
51 case '%':
52 if (*format != '%')
53 {
54 switch (__scan(&format, *p))
55 {
56
57 case 1: /* good return */
58 p++;
59 nmatch++;
60 case 0: /* no return */
61 break;
62
63 case -1: /* no match */
64 return (nmatch);
65
66 case -2: /* end of file */
67 return (nmatch ? nmatch : -1);
68
69 default: /* syntax error */
70 return (-1);
71
72 }
73 break;
74 }
75 format++;
76
77 default:
78 match_ch = __next(0);
79 if (ch != match_ch)
80 {
81 (*__ungc)(match_ch, __input);
82 return (nmatch ? nmatch : -2);
83 }
84 break;
85
86 }
87 }
88}
89
90
91__scan(spec, result)
92char **spec;
93char *result;
94{
95 register int longf, length;
96 register char ch;
97 extern int __strend(), __splend();
98
99 longf = length = 0;
100 while (1)
101 {
102 switch (ch = *(*spec)++)
103 {
104 case '*':
105 result = 0;
106 break;
107
108 case '0':
109 case '1':
110 case '2':
111 case '3':
112 case '4':
113 case '5':
114 case '6':
115 case '7':
116 case '8':
117 case '9':
118 length = length * 10 + ch - '0';
119 break;
120
121 case 'l':
122 if (longf)
123 return (-3);
124 longf = 1;
125 break;
126
127 case 'h': /* short */
128 if (longf)
129 return (-3);
130 longf = -1;
131 break;
132
133 case 'o':
134 case 'O':
135 return (__dec(result, length ? length : 100, 8, longf));
136
137 case 'd':
138 case 'D':
139 return (__dec(result, length ? length : 100, 10, longf));
140
141 case 'x':
142 case 'X':
143 return (__dec(result, length ? length : 100, 16, longf));
144
145 case 'c':
146 case 'C':
147 if (longf)
148 return (-3);
149 return (__char(result, length ? length : 1));
150
151 case 's':
152 case 'S':
153 if (longf)
154 return (-3);
155 return (__str(result, length ? length : 100, __strend));
156
157 case 'e':
158 case 'E':
159 case 'f':
160 case 'F':
161 if (longf < 0)
162 return (-3);
163 return (__float(result, length ? length : 100, longf));
164
165 case '[':
166 if (longf)
167 return (-3);
168 if (__inits(spec))
169 return (-3);
170 return (__str(result, length ? length : 100, __splend));
171
172 default:
173 return (-3);
174
175 }
176 }
177}
178
179
180__dec(result, length, base, longf)
181int *result;
182int length;
183int base;
184int longf;
185{
186 register char ch;
187 long n, *lresult;
188 register int val;
189 long lres;
190 int ires;
191 int minus, ok;
192 register int ndigit;
193
194 ires = 0;
195 lres = 0;
196 ndigit = minus = 0;
197 switch (ch = __next(1))
198 {
199
200 case '\0':
201 return (-2);
202
203 case '-':
204 minus = 1;
205 case '+':
206 ndigit++;
207 ch = __next(-1);
208 }
209 ok = 0;
210 while ((val = __digit(ch, base)) >= 0 && ndigit++ < length)
211 {
212 ok++;
213 if (longf)
214 lres = lres * base + val;
215 else
216 ires = ires * base + val;
217 ch = __next(0);
218 }
219 (*__ungc)(ch, __input);
220 if (!ok)
221 return (-1);
222 if (!result)
223 return (0);
224 if (minus)
225 if (longf)
226 lres = -lres;
227 else
228 ires = -ires;
229 if (longf)
230 {
231 lresult = result;
232 *lresult = lres;
233 }
234 else
235 *result = ires;
236 return (1);
237}
238
239
240__next(mode)
241int mode;
242{
243/*
244 * mode -1: get next non-space or non-tab
245 * mode 0: get next character
246 * mode 1: get next non-space, non-tab, or non-newline
247 */
248 register int ch;
249
250 ch = (*__getc)(__input);
251 if (mode == 0)
252 return (ch);
253 while (ch == ' ' || ch == '\t' || ch == '\n')
254 {
255 if (ch == '\n' && mode < 0)
256 break;
257 ch = (*__getc)(__input);
258 }
259 return (ch);
260}
261
262
263__digit(ch, base)
264char ch;
265int base;
266{
267 register int n;
268
269 if (ch < '0')
270 return (-1);
271 if (ch <= '7')
272 return (ch - '0');
273 if (base == 8)
274 return (-1);
275 if (ch <= '9')
276 return (ch - '0');
277 if (base == 10 || ch < 'A')
278 return (-1);
279 if (ch <= 'F')
280 return (ch - 'A' + 10);
281 if (ch < 'a' || ch > 'f')
282 return (-1);
283 return (ch - 'a' + 10);
284}
285
286
287__fltend(cha)
288char cha;
289{
290 register char ch;
291 static char gote, gotpt, gotsn;
292
293 ch = cha;
294 if (ch < 0)
295 return (gote = gotpt = gotsn = 0);
296 if (ch >= '0' && ch <= '9')
297 {
298 gotsn = -1;
299 return (0);
300 }
301 if (ch == '+' || ch == '-')
302 {
303 if (gotsn || gotpt)
304 return (1);
305 gotsn = 1;
306 return (0);
307 }
308 if (ch == '.')
309 {
310 if (gote || gotpt)
311 return (1);
312 gotpt++;
313 return (0);
314 }
315 if (ch != 'e' && ch != 'E')
316 return (1);
317 if (gote)
318 return (1);
319 gote++;
320 gotsn = 0;
321 return (0);
322}
323
324
325__strend(cha)
326char cha;
327{
328 register char ch;
329
330 ch = cha;
331 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\0')
332 return (1);
333 return (0);
334}
335
336
337char __splset[128];
338
339__splend(ch)
340char ch;
341{
342 return (__splset[ch]);
343}
344
345
346__inits(spec)
347char **spec;
348{
349 register char ch;
350 register int i;
351 register int val;
352
353 ch = *(*spec)++;
354 if (ch == '^')
355 {
356 val = 0;
357 ch = *(*spec)++;
358 }
359 else
360 val = 1;
361 for (i = 1; i < 128; i++)
362 __splset[i] = val;
363 val = 1 - val;
364 while (ch != ']')
365 {
366 if (ch == 0)
367 return (-1);
368 __splset[ch & 0177] = val;
369 ch = *(*spec)++;
370 }
371 __splset[0] = 1;
372 return (0);
373}
374
375
376__float(result, length, longf)
377double *result;
378int length;
379int longf;
380{
381 extern int __fltend();
382 char temp[101];
383 float *fres;
384 register int r;
385 double x;
386 extern double atof();
387
388 __fltend(-1);
389 r = __str(temp, length, __fltend);
390 if (r < 0)
391 return (r);
392 if (!result)
393 return (0);
394 x = atof(temp);
395 if (longf)
396 {
397 *result = x;
398 return (1);
399 }
400 fres = result;
401 *fres = x;
402 return (1);
403}
404
405
406__str(result, length, endfn)
407char *result;
408int length;
409int (*endfn)();
410{
411 register char ch;
412 extern int __splend();
413 register int imode, notok;
414
415 notok = 1;
416 imode = (endfn != __splend);
417 while (!(*endfn)(ch = __next(imode)) && length-- > 0)
418 {
419 if (result)
420 *result++ = ch;
421 imode = notok = 0;
422 }
423 (*__ungc)(ch, __input);
424 if (notok)
425 return (ch ? -1 : -2);
426 if (!result)
427 return (0);
428 *result = 0;
429 return (1);
430}
431
432
433__char(result, length)
434char *result;
435int length;
436{
437 register char *r, ch;
438 register int l;
439
440 r = result;
441 l = length;
442
443 while (l--)
444 {
445 if ((ch = __next(0)) <= 0)
446 if (l + 1 == length)
447 return (ch ? -1 : -2);
448 else
449 return (result != 0);
450 if (result)
451 *result++ = ch;
452 }
453 return (result != 0);
454}
455
456
457__gets(s)
458char **s;
459{
460 register char c;
461
462 c = **s;
463 if (c)
464 (*s)++;
465 return (c);
466}
467
468
469__ungs(c, s)
470char c;
471char **s;
472{
473 if (c)
474 (*s)--;
475}