1*26640Sdonn #if defined(LIBC_SCCS) && !defined(lint) 2*26640Sdonn static char sccsid[] = "@(#)vfscanf.c 5.2 (Berkeley) 03/09/86"; 3*26640Sdonn #endif LIBC_SCCS and not lint 49415Smckusick 59415Smckusick #include <stdio.h> 69415Smckusick #include <ctype.h> 79415Smckusick 89415Smckusick #define SPC 01 99415Smckusick #define STP 02 109415Smckusick 119415Smckusick #define SHORT 0 129415Smckusick #define REGULAR 1 139415Smckusick #define LONG 2 149415Smckusick #define INT 0 159415Smckusick #define FLOAT 1 169415Smckusick 1717951Sserge static char *_getccl(); 189415Smckusick 1917951Sserge static char _sctab[256] = { 209415Smckusick 0,0,0,0,0,0,0,0, 219415Smckusick 0,SPC,SPC,0,0,0,0,0, 229415Smckusick 0,0,0,0,0,0,0,0, 239415Smckusick 0,0,0,0,0,0,0,0, 249415Smckusick SPC,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 0,0,0,0,0,0,0,0, 289415Smckusick }; 299415Smckusick 309415Smckusick _doscan(iop, fmt, argp) 319415Smckusick FILE *iop; 329415Smckusick register char *fmt; 339415Smckusick register int **argp; 349415Smckusick { 359415Smckusick register int ch; 369415Smckusick int nmatch, len, ch1; 379415Smckusick int **ptr, fileended, size; 389415Smckusick 399415Smckusick nmatch = 0; 409415Smckusick fileended = 0; 419415Smckusick for (;;) switch (ch = *fmt++) { 429415Smckusick case '\0': 439415Smckusick return (nmatch); 449415Smckusick case '%': 459415Smckusick if ((ch = *fmt++) == '%') 469415Smckusick goto def; 479415Smckusick ptr = 0; 489415Smckusick if (ch != '*') 499415Smckusick ptr = argp++; 509415Smckusick else 519415Smckusick ch = *fmt++; 529415Smckusick len = 0; 539415Smckusick size = REGULAR; 549415Smckusick while (isdigit(ch)) { 559415Smckusick len = len*10 + ch - '0'; 569415Smckusick ch = *fmt++; 579415Smckusick } 589415Smckusick if (len == 0) 599415Smckusick len = 30000; 609415Smckusick if (ch=='l') { 619415Smckusick size = LONG; 629415Smckusick ch = *fmt++; 639415Smckusick } else if (ch=='h') { 649415Smckusick size = SHORT; 659415Smckusick ch = *fmt++; 669415Smckusick } else if (ch=='[') 679415Smckusick fmt = _getccl(fmt); 689415Smckusick if (isupper(ch)) { 699415Smckusick ch = tolower(ch); 709415Smckusick size = LONG; 719415Smckusick } 729415Smckusick if (ch == '\0') 739415Smckusick return(-1); 749415Smckusick if (_innum(ptr, ch, len, size, iop, &fileended) && ptr) 759415Smckusick nmatch++; 769415Smckusick if (fileended) 779415Smckusick return(nmatch? nmatch: -1); 789415Smckusick break; 799415Smckusick 809415Smckusick case ' ': 819415Smckusick case '\n': 829415Smckusick case '\t': 839415Smckusick while ((ch1 = getc(iop))==' ' || ch1=='\t' || ch1=='\n') 849415Smckusick ; 859415Smckusick if (ch1 != EOF) 869415Smckusick ungetc(ch1, iop); 879415Smckusick break; 889415Smckusick 899415Smckusick default: 909415Smckusick def: 919415Smckusick ch1 = getc(iop); 929415Smckusick if (ch1 != ch) { 939415Smckusick if (ch1==EOF) 949415Smckusick return(-1); 959415Smckusick ungetc(ch1, iop); 969415Smckusick return(nmatch); 979415Smckusick } 989415Smckusick } 999415Smckusick } 1009415Smckusick 10117951Sserge static 1029415Smckusick _innum(ptr, type, len, size, iop, eofptr) 1039415Smckusick int **ptr, *eofptr; 10417951Sserge FILE *iop; 1059415Smckusick { 1069415Smckusick extern double atof(); 1079415Smckusick register char *np; 1089415Smckusick char numbuf[64]; 1099415Smckusick register c, base; 1109415Smckusick int expseen, scale, negflg, c1, ndigit; 1119415Smckusick long lcval; 1129415Smckusick 1139415Smckusick if (type=='c' || type=='s' || type=='[') 1149415Smckusick return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len, iop, eofptr)); 1159415Smckusick lcval = 0; 1169415Smckusick ndigit = 0; 1179415Smckusick scale = INT; 1189415Smckusick if (type=='e'||type=='f') 1199415Smckusick scale = FLOAT; 1209415Smckusick base = 10; 1219415Smckusick if (type=='o') 1229415Smckusick base = 8; 1239415Smckusick else if (type=='x') 1249415Smckusick base = 16; 1259415Smckusick np = numbuf; 1269415Smckusick expseen = 0; 1279415Smckusick negflg = 0; 1289415Smckusick while ((c = getc(iop))==' ' || c=='\t' || c=='\n'); 1299415Smckusick if (c=='-') { 1309415Smckusick negflg++; 1319415Smckusick *np++ = c; 1329415Smckusick c = getc(iop); 1339415Smckusick len--; 1349415Smckusick } else if (c=='+') { 1359415Smckusick len--; 1369415Smckusick c = getc(iop); 1379415Smckusick } 1389415Smckusick for ( ; --len>=0; *np++ = c, c = getc(iop)) { 1399415Smckusick if (isdigit(c) 1409415Smckusick || base==16 && ('a'<=c && c<='f' || 'A'<=c && c<='F')) { 1419415Smckusick ndigit++; 1429415Smckusick if (base==8) 1439415Smckusick lcval <<=3; 1449415Smckusick else if (base==10) 1459415Smckusick lcval = ((lcval<<2) + lcval)<<1; 1469415Smckusick else 1479415Smckusick lcval <<= 4; 1489415Smckusick c1 = c; 1499415Smckusick if (isdigit(c)) 1509415Smckusick c -= '0'; 1519415Smckusick else if ('a'<=c && c<='f') 1529415Smckusick c -= 'a'-10; 1539415Smckusick else 1549415Smckusick c -= 'A'-10; 1559415Smckusick lcval += c; 1569415Smckusick c = c1; 1579415Smckusick continue; 1589415Smckusick } else if (c=='.') { 1599415Smckusick if (base!=10 || scale==INT) 1609415Smckusick break; 1619415Smckusick ndigit++; 1629415Smckusick continue; 1639415Smckusick } else if ((c=='e'||c=='E') && expseen==0) { 1649415Smckusick if (base!=10 || scale==INT || ndigit==0) 1659415Smckusick break; 1669415Smckusick expseen++; 1679415Smckusick *np++ = c; 1689415Smckusick c = getc(iop); 1699415Smckusick if (c!='+'&&c!='-'&&('0'>c||c>'9')) 1709415Smckusick break; 1719415Smckusick } else 1729415Smckusick break; 1739415Smckusick } 1749415Smckusick if (negflg) 1759415Smckusick lcval = -lcval; 1769415Smckusick if (c != EOF) { 1779415Smckusick ungetc(c, iop); 1789415Smckusick *eofptr = 0; 1799415Smckusick } else 1809415Smckusick *eofptr = 1; 1819416Smckusick if (ptr==NULL || np==numbuf || (negflg && np==numbuf+1) )/* gene dykes*/ 1829415Smckusick return(0); 1839415Smckusick *np++ = 0; 1849415Smckusick switch((scale<<4) | size) { 1859415Smckusick 1869415Smckusick case (FLOAT<<4) | SHORT: 1879415Smckusick case (FLOAT<<4) | REGULAR: 1889415Smckusick **(float **)ptr = atof(numbuf); 1899415Smckusick break; 1909415Smckusick 1919415Smckusick case (FLOAT<<4) | LONG: 1929415Smckusick **(double **)ptr = atof(numbuf); 1939415Smckusick break; 1949415Smckusick 1959415Smckusick case (INT<<4) | SHORT: 1969415Smckusick **(short **)ptr = lcval; 1979415Smckusick break; 1989415Smckusick 1999415Smckusick case (INT<<4) | REGULAR: 2009415Smckusick **(int **)ptr = lcval; 2019415Smckusick break; 2029415Smckusick 2039415Smckusick case (INT<<4) | LONG: 2049415Smckusick **(long **)ptr = lcval; 2059415Smckusick break; 2069415Smckusick } 2079415Smckusick return(1); 2089415Smckusick } 2099415Smckusick 21017951Sserge static 2119415Smckusick _instr(ptr, type, len, iop, eofptr) 2129415Smckusick register char *ptr; 21317951Sserge register FILE *iop; 2149415Smckusick int *eofptr; 2159415Smckusick { 2169415Smckusick register ch; 2179415Smckusick register char *optr; 2189415Smckusick int ignstp; 2199415Smckusick 2209415Smckusick *eofptr = 0; 2219415Smckusick optr = ptr; 2229415Smckusick if (type=='c' && len==30000) 2239415Smckusick len = 1; 2249415Smckusick ignstp = 0; 2259415Smckusick if (type=='s') 2269415Smckusick ignstp = SPC; 22717951Sserge while ((ch = getc(iop)) != EOF && _sctab[ch] & ignstp) 22817951Sserge ; 2299415Smckusick ignstp = SPC; 2309415Smckusick if (type=='c') 2319415Smckusick ignstp = 0; 2329415Smckusick else if (type=='[') 2339415Smckusick ignstp = STP; 2349415Smckusick while (ch!=EOF && (_sctab[ch]&ignstp)==0) { 2359415Smckusick if (ptr) 2369415Smckusick *ptr++ = ch; 2379415Smckusick if (--len <= 0) 2389415Smckusick break; 2399415Smckusick ch = getc(iop); 2409415Smckusick } 2419415Smckusick if (ch != EOF) { 2429415Smckusick if (len > 0) 2439415Smckusick ungetc(ch, iop); 2449415Smckusick *eofptr = 0; 2459415Smckusick } else 2469415Smckusick *eofptr = 1; 2479415Smckusick if (ptr && ptr!=optr) { 2489415Smckusick if (type!='c') 2499415Smckusick *ptr++ = '\0'; 2509415Smckusick return(1); 2519415Smckusick } 2529415Smckusick return(0); 2539415Smckusick } 2549415Smckusick 25517951Sserge static char * 2569415Smckusick _getccl(s) 25717951Sserge register unsigned char *s; 2589415Smckusick { 2599415Smckusick register c, t; 2609415Smckusick 2619415Smckusick t = 0; 2629415Smckusick if (*s == '^') { 2639415Smckusick t++; 2649415Smckusick s++; 2659415Smckusick } 26617951Sserge for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++) 2679415Smckusick if (t) 2689415Smckusick _sctab[c] &= ~STP; 2699415Smckusick else 2709415Smckusick _sctab[c] |= STP; 27117951Sserge if ((c = *s) == ']' || c == '-') { /* first char is special */ 2729415Smckusick if (t) 27317951Sserge _sctab[c] |= STP; 2749415Smckusick else 27517951Sserge _sctab[c] &= ~STP; 27617951Sserge s++; 27717951Sserge } 27817951Sserge while ((c = *s++) != ']') { 2799415Smckusick if (c==0) 28017951Sserge return((char *)--s); 28117951Sserge else if (c == '-' && *s != ']' && s[-2] < *s) { 28217951Sserge for (c = s[-2] + 1; c < *s; c++) 28317951Sserge if (t) 28417951Sserge _sctab[c] |= STP; 28517951Sserge else 28617951Sserge _sctab[c] &= ~STP; 28717951Sserge } else if (t) 28817951Sserge _sctab[c] |= STP; 28917951Sserge else 29017951Sserge _sctab[c] &= ~STP; 2919415Smckusick } 29217951Sserge return((char *)s); 2939415Smckusick } 294