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