xref: /csrg-svn/lib/libc/stdio/vfscanf.c (revision 9416)
1*9416Smckusick static char sccsid[] = "@(#)vfscanf.c	4.2	(Berkeley)	82/12/03";
29415Smckusick 
39415Smckusick /* @(#)doscan.c	4.1 (Berkeley) 12/21/80 */
49415Smckusick #include <stdio.h>
59415Smckusick #include	<ctype.h>
69415Smckusick 
79415Smckusick #define	SPC	01
89415Smckusick #define	STP	02
99415Smckusick 
109415Smckusick #define	SHORT	0
119415Smckusick #define	REGULAR	1
129415Smckusick #define	LONG	2
139415Smckusick #define	INT	0
149415Smckusick #define	FLOAT	1
159415Smckusick 
169415Smckusick char	*_getccl();
179415Smckusick 
189415Smckusick char	_sctab[128] = {
199415Smckusick 	0,0,0,0,0,0,0,0,
209415Smckusick 	0,SPC,SPC,0,0,0,0,0,
219415Smckusick 	0,0,0,0,0,0,0,0,
229415Smckusick 	0,0,0,0,0,0,0,0,
239415Smckusick 	SPC,0,0,0,0,0,0,0,
249415Smckusick 	0,0,0,0,0,0,0,0,
259415Smckusick 	0,0,0,0,0,0,0,0,
269415Smckusick 	0,0,0,0,0,0,0,0,
279415Smckusick };
289415Smckusick 
299415Smckusick _doscan(iop, fmt, argp)
309415Smckusick FILE *iop;
319415Smckusick register char *fmt;
329415Smckusick register int **argp;
339415Smckusick {
349415Smckusick 	register int ch;
359415Smckusick 	int nmatch, len, ch1;
369415Smckusick 	int **ptr, fileended, size;
379415Smckusick 
389415Smckusick 	nmatch = 0;
399415Smckusick 	fileended = 0;
409415Smckusick 	for (;;) switch (ch = *fmt++) {
419415Smckusick 	case '\0':
429415Smckusick 		return (nmatch);
439415Smckusick 	case '%':
449415Smckusick 		if ((ch = *fmt++) == '%')
459415Smckusick 			goto def;
469415Smckusick 		ptr = 0;
479415Smckusick 		if (ch != '*')
489415Smckusick 			ptr = argp++;
499415Smckusick 		else
509415Smckusick 			ch = *fmt++;
519415Smckusick 		len = 0;
529415Smckusick 		size = REGULAR;
539415Smckusick 		while (isdigit(ch)) {
549415Smckusick 			len = len*10 + ch - '0';
559415Smckusick 			ch = *fmt++;
569415Smckusick 		}
579415Smckusick 		if (len == 0)
589415Smckusick 			len = 30000;
599415Smckusick 		if (ch=='l') {
609415Smckusick 			size = LONG;
619415Smckusick 			ch = *fmt++;
629415Smckusick 		} else if (ch=='h') {
639415Smckusick 			size = SHORT;
649415Smckusick 			ch = *fmt++;
659415Smckusick 		} else if (ch=='[')
669415Smckusick 			fmt = _getccl(fmt);
679415Smckusick 		if (isupper(ch)) {
689415Smckusick 			ch = tolower(ch);
699415Smckusick 			size = LONG;
709415Smckusick 		}
719415Smckusick 		if (ch == '\0')
729415Smckusick 			return(-1);
739415Smckusick 		if (_innum(ptr, ch, len, size, iop, &fileended) && ptr)
749415Smckusick 			nmatch++;
759415Smckusick 		if (fileended)
769415Smckusick 			return(nmatch? nmatch: -1);
779415Smckusick 		break;
789415Smckusick 
799415Smckusick 	case ' ':
809415Smckusick 	case '\n':
819415Smckusick 	case '\t':
829415Smckusick 		while ((ch1 = getc(iop))==' ' || ch1=='\t' || ch1=='\n')
839415Smckusick 			;
849415Smckusick 		if (ch1 != EOF)
859415Smckusick 			ungetc(ch1, iop);
869415Smckusick 		break;
879415Smckusick 
889415Smckusick 	default:
899415Smckusick 	def:
909415Smckusick 		ch1 = getc(iop);
919415Smckusick 		if (ch1 != ch) {
929415Smckusick 			if (ch1==EOF)
939415Smckusick 				return(-1);
949415Smckusick 			ungetc(ch1, iop);
959415Smckusick 			return(nmatch);
969415Smckusick 		}
979415Smckusick 	}
989415Smckusick }
999415Smckusick 
1009415Smckusick _innum(ptr, type, len, size, iop, eofptr)
1019415Smckusick int **ptr, *eofptr;
1029415Smckusick struct _iobuf *iop;
1039415Smckusick {
1049415Smckusick 	extern double atof();
1059415Smckusick 	register char *np;
1069415Smckusick 	char numbuf[64];
1079415Smckusick 	register c, base;
1089415Smckusick 	int expseen, scale, negflg, c1, ndigit;
1099415Smckusick 	long lcval;
1109415Smckusick 
1119415Smckusick 	if (type=='c' || type=='s' || type=='[')
1129415Smckusick 		return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len, iop, eofptr));
1139415Smckusick 	lcval = 0;
1149415Smckusick 	ndigit = 0;
1159415Smckusick 	scale = INT;
1169415Smckusick 	if (type=='e'||type=='f')
1179415Smckusick 		scale = FLOAT;
1189415Smckusick 	base = 10;
1199415Smckusick 	if (type=='o')
1209415Smckusick 		base = 8;
1219415Smckusick 	else if (type=='x')
1229415Smckusick 		base = 16;
1239415Smckusick 	np = numbuf;
1249415Smckusick 	expseen = 0;
1259415Smckusick 	negflg = 0;
1269415Smckusick 	while ((c = getc(iop))==' ' || c=='\t' || c=='\n');
1279415Smckusick 	if (c=='-') {
1289415Smckusick 		negflg++;
1299415Smckusick 		*np++ = c;
1309415Smckusick 		c = getc(iop);
1319415Smckusick 		len--;
1329415Smckusick 	} else if (c=='+') {
1339415Smckusick 		len--;
1349415Smckusick 		c = getc(iop);
1359415Smckusick 	}
1369415Smckusick 	for ( ; --len>=0; *np++ = c, c = getc(iop)) {
1379415Smckusick 		if (isdigit(c)
1389415Smckusick 		 || base==16 && ('a'<=c && c<='f' || 'A'<=c && c<='F')) {
1399415Smckusick 			ndigit++;
1409415Smckusick 			if (base==8)
1419415Smckusick 				lcval <<=3;
1429415Smckusick 			else if (base==10)
1439415Smckusick 				lcval = ((lcval<<2) + lcval)<<1;
1449415Smckusick 			else
1459415Smckusick 				lcval <<= 4;
1469415Smckusick 			c1 = c;
1479415Smckusick 			if (isdigit(c))
1489415Smckusick 				c -= '0';
1499415Smckusick 			else if ('a'<=c && c<='f')
1509415Smckusick 				c -= 'a'-10;
1519415Smckusick 			else
1529415Smckusick 				c -= 'A'-10;
1539415Smckusick 			lcval += c;
1549415Smckusick 			c = c1;
1559415Smckusick 			continue;
1569415Smckusick 		} else if (c=='.') {
1579415Smckusick 			if (base!=10 || scale==INT)
1589415Smckusick 				break;
1599415Smckusick 			ndigit++;
1609415Smckusick 			continue;
1619415Smckusick 		} else if ((c=='e'||c=='E') && expseen==0) {
1629415Smckusick 			if (base!=10 || scale==INT || ndigit==0)
1639415Smckusick 				break;
1649415Smckusick 			expseen++;
1659415Smckusick 			*np++ = c;
1669415Smckusick 			c = getc(iop);
1679415Smckusick 			if (c!='+'&&c!='-'&&('0'>c||c>'9'))
1689415Smckusick 				break;
1699415Smckusick 		} else
1709415Smckusick 			break;
1719415Smckusick 	}
1729415Smckusick 	if (negflg)
1739415Smckusick 		lcval = -lcval;
1749415Smckusick 	if (c != EOF) {
1759415Smckusick 		ungetc(c, iop);
1769415Smckusick 		*eofptr = 0;
1779415Smckusick 	} else
1789415Smckusick 		*eofptr = 1;
179*9416Smckusick  	if (ptr==NULL || np==numbuf || (negflg && np==numbuf+1) )/* gene dykes*/
1809415Smckusick 		return(0);
1819415Smckusick 	*np++ = 0;
1829415Smckusick 	switch((scale<<4) | size) {
1839415Smckusick 
1849415Smckusick 	case (FLOAT<<4) | SHORT:
1859415Smckusick 	case (FLOAT<<4) | REGULAR:
1869415Smckusick 		**(float **)ptr = atof(numbuf);
1879415Smckusick 		break;
1889415Smckusick 
1899415Smckusick 	case (FLOAT<<4) | LONG:
1909415Smckusick 		**(double **)ptr = atof(numbuf);
1919415Smckusick 		break;
1929415Smckusick 
1939415Smckusick 	case (INT<<4) | SHORT:
1949415Smckusick 		**(short **)ptr = lcval;
1959415Smckusick 		break;
1969415Smckusick 
1979415Smckusick 	case (INT<<4) | REGULAR:
1989415Smckusick 		**(int **)ptr = lcval;
1999415Smckusick 		break;
2009415Smckusick 
2019415Smckusick 	case (INT<<4) | LONG:
2029415Smckusick 		**(long **)ptr = lcval;
2039415Smckusick 		break;
2049415Smckusick 	}
2059415Smckusick 	return(1);
2069415Smckusick }
2079415Smckusick 
2089415Smckusick _instr(ptr, type, len, iop, eofptr)
2099415Smckusick register char *ptr;
2109415Smckusick register struct _iobuf *iop;
2119415Smckusick int *eofptr;
2129415Smckusick {
2139415Smckusick 	register ch;
2149415Smckusick 	register char *optr;
2159415Smckusick 	int ignstp;
2169415Smckusick 
2179415Smckusick 	*eofptr = 0;
2189415Smckusick 	optr = ptr;
2199415Smckusick 	if (type=='c' && len==30000)
2209415Smckusick 		len = 1;
2219415Smckusick 	ignstp = 0;
2229415Smckusick 	if (type=='s')
2239415Smckusick 		ignstp = SPC;
2249415Smckusick 	while (_sctab[ch = getc(iop)] & ignstp)
2259415Smckusick 		if (ch==EOF)
2269415Smckusick 			break;
2279415Smckusick 	ignstp = SPC;
2289415Smckusick 	if (type=='c')
2299415Smckusick 		ignstp = 0;
2309415Smckusick 	else if (type=='[')
2319415Smckusick 		ignstp = STP;
2329415Smckusick 	while (ch!=EOF && (_sctab[ch]&ignstp)==0) {
2339415Smckusick 		if (ptr)
2349415Smckusick 			*ptr++ = ch;
2359415Smckusick 		if (--len <= 0)
2369415Smckusick 			break;
2379415Smckusick 		ch = getc(iop);
2389415Smckusick 	}
2399415Smckusick 	if (ch != EOF) {
2409415Smckusick 		if (len > 0)
2419415Smckusick 			ungetc(ch, iop);
2429415Smckusick 		*eofptr = 0;
2439415Smckusick 	} else
2449415Smckusick 		*eofptr = 1;
2459415Smckusick 	if (ptr && ptr!=optr) {
2469415Smckusick 		if (type!='c')
2479415Smckusick 			*ptr++ = '\0';
2489415Smckusick 		return(1);
2499415Smckusick 	}
2509415Smckusick 	return(0);
2519415Smckusick }
2529415Smckusick 
2539415Smckusick char *
2549415Smckusick _getccl(s)
2559415Smckusick register char *s;
2569415Smckusick {
2579415Smckusick 	register c, t;
2589415Smckusick 
2599415Smckusick 	t = 0;
2609415Smckusick 	if (*s == '^') {
2619415Smckusick 		t++;
2629415Smckusick 		s++;
2639415Smckusick 	}
2649415Smckusick 	for (c = 0; c < 128; c++)
2659415Smckusick 		if (t)
2669415Smckusick 			_sctab[c] &= ~STP;
2679415Smckusick 		else
2689415Smckusick 			_sctab[c] |= STP;
2699415Smckusick 	while (((c = *s++)&0177) != ']') {
2709415Smckusick 		if (t)
2719415Smckusick 			_sctab[c++] |= STP;
2729415Smckusick 		else
2739415Smckusick 			_sctab[c++] &= ~STP;
2749415Smckusick 		if (c==0)
2759415Smckusick 			return(--s);
2769415Smckusick 	}
2779415Smckusick 	return(s);
2789415Smckusick }
279