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