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