1 static char sccsid[] = "@(#)vfscanf.c 4.3 (Berkeley) 85/02/13"; 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 static char *_getccl(); 17 18 static char _sctab[256] = { 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 static 101 _innum(ptr, type, len, size, iop, eofptr) 102 int **ptr, *eofptr; 103 FILE *iop; 104 { 105 extern double atof(); 106 register char *np; 107 char numbuf[64]; 108 register c, base; 109 int expseen, scale, negflg, c1, ndigit; 110 long lcval; 111 112 if (type=='c' || type=='s' || type=='[') 113 return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len, iop, eofptr)); 114 lcval = 0; 115 ndigit = 0; 116 scale = INT; 117 if (type=='e'||type=='f') 118 scale = FLOAT; 119 base = 10; 120 if (type=='o') 121 base = 8; 122 else if (type=='x') 123 base = 16; 124 np = numbuf; 125 expseen = 0; 126 negflg = 0; 127 while ((c = getc(iop))==' ' || c=='\t' || c=='\n'); 128 if (c=='-') { 129 negflg++; 130 *np++ = c; 131 c = getc(iop); 132 len--; 133 } else if (c=='+') { 134 len--; 135 c = getc(iop); 136 } 137 for ( ; --len>=0; *np++ = c, c = getc(iop)) { 138 if (isdigit(c) 139 || base==16 && ('a'<=c && c<='f' || 'A'<=c && c<='F')) { 140 ndigit++; 141 if (base==8) 142 lcval <<=3; 143 else if (base==10) 144 lcval = ((lcval<<2) + lcval)<<1; 145 else 146 lcval <<= 4; 147 c1 = c; 148 if (isdigit(c)) 149 c -= '0'; 150 else if ('a'<=c && c<='f') 151 c -= 'a'-10; 152 else 153 c -= 'A'-10; 154 lcval += c; 155 c = c1; 156 continue; 157 } else if (c=='.') { 158 if (base!=10 || scale==INT) 159 break; 160 ndigit++; 161 continue; 162 } else if ((c=='e'||c=='E') && expseen==0) { 163 if (base!=10 || scale==INT || ndigit==0) 164 break; 165 expseen++; 166 *np++ = c; 167 c = getc(iop); 168 if (c!='+'&&c!='-'&&('0'>c||c>'9')) 169 break; 170 } else 171 break; 172 } 173 if (negflg) 174 lcval = -lcval; 175 if (c != EOF) { 176 ungetc(c, iop); 177 *eofptr = 0; 178 } else 179 *eofptr = 1; 180 if (ptr==NULL || np==numbuf || (negflg && np==numbuf+1) )/* gene dykes*/ 181 return(0); 182 *np++ = 0; 183 switch((scale<<4) | size) { 184 185 case (FLOAT<<4) | SHORT: 186 case (FLOAT<<4) | REGULAR: 187 **(float **)ptr = atof(numbuf); 188 break; 189 190 case (FLOAT<<4) | LONG: 191 **(double **)ptr = atof(numbuf); 192 break; 193 194 case (INT<<4) | SHORT: 195 **(short **)ptr = lcval; 196 break; 197 198 case (INT<<4) | REGULAR: 199 **(int **)ptr = lcval; 200 break; 201 202 case (INT<<4) | LONG: 203 **(long **)ptr = lcval; 204 break; 205 } 206 return(1); 207 } 208 209 static 210 _instr(ptr, type, len, iop, eofptr) 211 register char *ptr; 212 register FILE *iop; 213 int *eofptr; 214 { 215 register ch; 216 register char *optr; 217 int ignstp; 218 219 *eofptr = 0; 220 optr = ptr; 221 if (type=='c' && len==30000) 222 len = 1; 223 ignstp = 0; 224 if (type=='s') 225 ignstp = SPC; 226 while ((ch = getc(iop)) != EOF && _sctab[ch] & ignstp) 227 ; 228 ignstp = SPC; 229 if (type=='c') 230 ignstp = 0; 231 else if (type=='[') 232 ignstp = STP; 233 while (ch!=EOF && (_sctab[ch]&ignstp)==0) { 234 if (ptr) 235 *ptr++ = ch; 236 if (--len <= 0) 237 break; 238 ch = getc(iop); 239 } 240 if (ch != EOF) { 241 if (len > 0) 242 ungetc(ch, iop); 243 *eofptr = 0; 244 } else 245 *eofptr = 1; 246 if (ptr && ptr!=optr) { 247 if (type!='c') 248 *ptr++ = '\0'; 249 return(1); 250 } 251 return(0); 252 } 253 254 static char * 255 _getccl(s) 256 register unsigned char *s; 257 { 258 register c, t; 259 260 t = 0; 261 if (*s == '^') { 262 t++; 263 s++; 264 } 265 for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++) 266 if (t) 267 _sctab[c] &= ~STP; 268 else 269 _sctab[c] |= STP; 270 if ((c = *s) == ']' || c == '-') { /* first char is special */ 271 if (t) 272 _sctab[c] |= STP; 273 else 274 _sctab[c] &= ~STP; 275 s++; 276 } 277 while ((c = *s++) != ']') { 278 if (c==0) 279 return((char *)--s); 280 else if (c == '-' && *s != ']' && s[-2] < *s) { 281 for (c = s[-2] + 1; c < *s; c++) 282 if (t) 283 _sctab[c] |= STP; 284 else 285 _sctab[c] &= ~STP; 286 } else if (t) 287 _sctab[c] |= STP; 288 else 289 _sctab[c] &= ~STP; 290 } 291 return((char *)s); 292 } 293