|
|
1.1 root 1: /*
2: * pANS stdio -- vfscanf
3: */
4: #include "iolib.h"
5: #include <stdarg.h>
6: #include <math.h>
7: #include <stdlib.h>
8: #include <ctype.h>
9: #ifdef sgi
10: #undef getc
11: #define getc(p) (--(p)->_cnt>=0? (int)*(p)->_ptr++:xfilbuf(p))
12:
13: static int __cnt;
14: static int xfilbuf(FILE*);
15:
16: static int
17: xfilbuf(FILE *p)
18: {
19: int rv;
20: if (p->_flag & _IOEOF)
21: return EOF;
22: if (_us_rsthread_stdio) {
23: p->_cnt = __cnt;
24: rv = _semgetc(p);
25: __cnt = p->_cnt;
26: p->_cnt = 0;
27: }
28: else {
29: rv = _filbuf(p);
30: if (p->_cnt == 1 && p->_ptr == p->_base)
31: p->_cnt = 0;
32: }
33: return rv;
34: }
35: #endif
36: static int icvt_f(FILE *f, va_list *args, int store, int width, int type);
37: static int icvt_x(FILE *f, va_list *args, int store, int width, int type);
38: static int icvt_sq(FILE *f, va_list *args, int store, int width, int type);
39: static int icvt_c(FILE *f, va_list *args, int store, int width, int type);
40: static int icvt_d(FILE *f, va_list *args, int store, int width, int type);
41: static int icvt_i(FILE *f, va_list *args, int store, int width, int type);
42: static int icvt_n(FILE *f, va_list *args, int store, int width, int type);
43: static int icvt_o(FILE *f, va_list *args, int store, int width, int type);
44: static int icvt_p(FILE *f, va_list *args, int store, int width, int type);
45: static int icvt_s(FILE *f, va_list *args, int store, int width, int type);
46: static int icvt_u(FILE *f, va_list *args, int store, int width, int type);
47: static int (*icvt[])(FILE *, va_list *, int, int, int)={
48: 0, 0, 0, 0, 0, 0, 0, 0, /* ^@ ^A ^B ^C ^D ^E ^F ^G */
49: 0, 0, 0, 0, 0, 0, 0, 0, /* ^H ^I ^J ^K ^L ^M ^N ^O */
50: 0, 0, 0, 0, 0, 0, 0, 0, /* ^P ^Q ^R ^S ^T ^U ^V ^W */
51: 0, 0, 0, 0, 0, 0, 0, 0, /* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
52: 0, 0, 0, 0, 0, 0, 0, 0, /* sp ! " # $ % & ' */
53: 0, 0, 0, 0, 0, 0, 0, 0, /* ( ) * + , - . / */
54: 0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */
55: 0, 0, 0, 0, 0, 0, 0, 0, /* 8 9 : ; < = > ? */
56: 0, 0, 0, 0, 0, icvt_f, 0, icvt_f, /* @ A B C D E F G */
57: 0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */
58: 0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */
59: icvt_x, 0, 0, icvt_sq,0, 0, 0, 0, /* X Y Z [ \ ] ^ _ */
60: 0, 0, 0, icvt_c, icvt_d, icvt_f, icvt_f, icvt_f, /* ` a b c d e f g */
61: 0, icvt_i, 0, 0, 0, 0, icvt_n, icvt_o, /* h i j k l m n o */
62: icvt_p, 0, 0, icvt_s, 0, icvt_u, 0, 0, /* p q r s t u v w */
63: icvt_x, 0, 0, 0, 0, 0, 0, 0, /* x y z { | } ~ ^? */
64:
65: 0, 0, 0, 0, 0, 0, 0, 0,
66: 0, 0, 0, 0, 0, 0, 0, 0,
67: 0, 0, 0, 0, 0, 0, 0, 0,
68: 0, 0, 0, 0, 0, 0, 0, 0,
69: 0, 0, 0, 0, 0, 0, 0, 0,
70: 0, 0, 0, 0, 0, 0, 0, 0,
71: 0, 0, 0, 0, 0, 0, 0, 0,
72: 0, 0, 0, 0, 0, 0, 0, 0,
73: 0, 0, 0, 0, 0, 0, 0, 0,
74: 0, 0, 0, 0, 0, 0, 0, 0,
75: 0, 0, 0, 0, 0, 0, 0, 0,
76: 0, 0, 0, 0, 0, 0, 0, 0,
77: 0, 0, 0, 0, 0, 0, 0, 0,
78: 0, 0, 0, 0, 0, 0, 0, 0,
79: 0, 0, 0, 0, 0, 0, 0, 0,
80: 0, 0, 0, 0, 0, 0, 0, 0,
81:
82: };
83: #define ngetc(f) (nread++, getc(f))
84: #define nungetc(c, f) (--nread, ungetc((c), f))
85: #define wgetc(c, f, out) if(width--==0) goto out; (c)=ngetc(f)
86: #define wungetc(c, f) (++width, nungetc(c, f))
87: static int nread, ncvt;
88: static const char *fmtp;
89:
90: int vfscanf(FILE *f, const char *s, va_list args){
91: int c, width, type, store;
92: #ifdef sgi
93: if (_us_rsthread_stdio) {
94: __cnt = f->_cnt;
95: f->_cnt = 0;
96: }
97: #endif
98: nread=0;
99: ncvt=0;
100: fmtp=s;
101: for(;*fmtp;fmtp++) switch(*fmtp){
102: default:
103: if(isspace(*fmtp)){
104: do
105: c=ngetc(f);
106: while(isspace(c));
107: if(c==EOF) return ncvt?ncvt:EOF;
108: nungetc(c, f);
109: break;
110: }
111: NonSpecial:
112: c=ngetc(f);
113: if(c==EOF) return ncvt?ncvt:EOF;
114: if(c!=*fmtp){
115: nungetc(c, f);
116: return ncvt;
117: }
118: break;
119: case '%':
120: fmtp++;
121: if(*fmtp!='*') store=1;
122: else{
123: store=0;
124: fmtp++;
125: }
126: if('0'<=*fmtp && *fmtp<='9'){
127: width=0;
128: while('0'<=*fmtp && *fmtp<='9') width=width*10 + *fmtp++ - '0';
129: }
130: else
131: width=-1;
132: type=*fmtp=='h' || *fmtp=='l' || *fmtp=='L'?*fmtp++:'n';
133: if(!icvt[*fmtp]) goto NonSpecial;
134: if(!(*icvt[*fmtp])(f, &args, store, width, type))
135: return ncvt?ncvt:feof(f)?EOF:0;
136: if(*fmtp=='\0') break;
137: if(store) ncvt++;
138: }
139: return ncvt;
140: }
141: static int icvt_n(FILE *f, va_list *args, int store, int width, int type){
142: #pragma ref f
143: #pragma ref width
144: if(store){
145: --ncvt; /* this assignment doesn't count! */
146: switch(type){
147: case 'h': *va_arg(*args, short *)=nread; break;
148: case 'n': *va_arg(*args, int *)=nread; break;
149: case 'l':
150: case 'L': *va_arg(*args, long *)=nread; break;
151: }
152: }
153: return 1;
154: }
155: #define SIGNED 1
156: #define UNSIGNED 2
157: #define POINTER 3
158: /*
159: * Generic fixed-point conversion
160: * f is the input FILE *;
161: * args is the va_list * into which to store the number;
162: * store is a flag to enable storing;
163: * width is the maximum field width;
164: * type is 'h' 'l' or 'L', the scanf type modifier;
165: * unsgned is SIGNED, UNSIGNED or POINTER, giving part of the type to store in;
166: * base is the number base -- if 0, C number syntax is used.
167: */
168: static int icvt_fixed(FILE *f, va_list *args,
169: int store, int width, int type, int unsgned, int base){
170: unsigned long int num=0;
171: int sign=1, ndig=0, dig;
172: int c;
173: do
174: c=ngetc(f);
175: while(isspace(c));
176: if(width--==0){
177: nungetc(c, f);
178: goto Done;
179: }
180: if(c=='+'){
181: wgetc(c, f, Done);
182: }
183: else if(c=='-'){
184: sign=-1;
185: wgetc(c, f, Done);
186: }
187: switch(base){
188: case 0:
189: if(c=='0'){
190: wgetc(c, f, Done);
191: if(c=='x' || c=='X'){
192: wgetc(c, f, Done);
193: base=16;
194: }
195: else{
196: ndig=1;
197: base=8;
198: }
199: }
200: else
201: base=10;
202: break;
203: case 16:
204: if(c=='0'){
205: wgetc(c, f, Done);
206: if(c=='x' || c=='X'){
207: wgetc(c, f, Done);
208: }
209: else ndig=1;
210: }
211: break;
212: }
213: while('0'<=c && c<='9' || 'a'<=c && c<='f' || 'A'<=c && c<='F'){
214: dig='0'<=c && c<='9'?c-'0':'a'<=c && c<='f'?c-'a'+10:c-'A'+10;
215: if(dig>=base) break;
216: ndig++;
217: num=num*base+dig;
218: wgetc(c, f, Done);
219: }
220: nungetc(c, f);
221: Done:
222: if(ndig==0) return 0;
223: if(store){
224: switch(unsgned){
225: case SIGNED:
226: switch(type){
227: case 'h': *va_arg(*args, short *)=num*sign; break;
228: case 'n': *va_arg(*args, int *)=num*sign; break;
229: case 'l':
230: case 'L': *va_arg(*args, long *)=num*sign; break;
231: }
232: break;
233: case UNSIGNED:
234: switch(type){
235: case 'h': *va_arg(*args, unsigned short *)=num*sign; break;
236: case 'n': *va_arg(*args, unsigned int *)=num*sign; break;
237: case 'l':
238: case 'L': *va_arg(*args, unsigned long *)=num*sign; break;
239: }
240: break;
241: case POINTER:
242: *va_arg(*args, void **)=(void *)(num*sign); break;
243: }
244: }
245: return 1;
246: }
247: static int icvt_d(FILE *f, va_list *args, int store, int width, int type){
248: return icvt_fixed(f, args, store, width, type, SIGNED, 10);
249: }
250: static int icvt_x(FILE *f, va_list *args, int store, int width, int type){
251: return icvt_fixed(f, args, store, width, type, UNSIGNED, 16);
252: }
253: static int icvt_o(FILE *f, va_list *args, int store, int width, int type){
254: return icvt_fixed(f, args, store, width, type, UNSIGNED, 8);
255: }
256: static int icvt_i(FILE *f, va_list *args, int store, int width, int type){
257: return icvt_fixed(f, args, store, width, type, SIGNED, 0);
258: }
259: static int icvt_u(FILE *f, va_list *args, int store, int width, int type){
260: return icvt_fixed(f, args, store, width, type, UNSIGNED, 10);
261: }
262: static int icvt_p(FILE *f, va_list *args, int store, int width, int type){
263: return icvt_fixed(f, args, store, width, type, POINTER, 16);
264: }
265: #define NBUF 509
266: static int icvt_f(FILE *f, va_list *args, int store, int width, int type){
267: char buf[NBUF+1];
268: char *s=buf;
269: int c, ndig=0, ndpt=0, nexp=1;
270: if(width<0 || NBUF<width) width=NBUF; /* bug -- no limit specified in ansi */
271: do
272: c=ngetc(f);
273: while(isspace(c));
274: if(width--==0){
275: nungetc(c, f);
276: goto Done;
277: }
278: if(c=='+' || c=='-'){
279: *s++=c;
280: wgetc(c, f, Done);
281: }
282: while('0'<=c && c<='9' || ndpt==0 && c=='.'){
283: if(c=='.') ndpt++;
284: else ndig++;
285: *s++=c;
286: wgetc(c, f, Done);
287: }
288: if(c=='e' || c=='E'){
289: *s++=c;
290: nexp=0;
291: wgetc(c, f, Done);
292: if(c=='+' || c=='-'){
293: *s++=c;
294: wgetc(c, f, Done);
295: }
296: while('0'<=c && c<='9'){
297: *s++=c;
298: nexp++;
299: wgetc(c, f, Done);
300: }
301: }
302: nungetc(c, f);
303: Done:
304: if(ndig==0 || nexp==0) return 0;
305: *s='\0';
306: if(store) switch(type){
307: case 'h':
308: case 'n': *va_arg(*args, float *)=atof(buf); break;
309: case 'L': /* bug -- should store in a long double */
310: case 'l': *va_arg(*args, double *)=atof(buf); break;
311: }
312: return 1;
313: }
314: static int icvt_s(FILE *f, va_list *args, int store, int width, int type){
315: #pragma ref type
316: int c, nn;
317: register char *s;
318: if(store) s=va_arg(*args, char *);
319: do
320: c=ngetc(f);
321: while(isspace(c));
322: if(width--==0){
323: nungetc(c, f);
324: goto Done;
325: }
326: nn=0;
327: while(!isspace(c)){
328: if(c==EOF){
329: if(nn==0) return 0;
330: else goto Done;
331: }
332: nn++;
333: if(store) *s++=c;
334: wgetc(c, f, Done);
335: }
336: nungetc(c, f);
337: Done:
338: if(store) *s='\0';
339: return 1;
340: }
341: static int icvt_c(FILE *f, va_list *args, int store, int width, int type){
342: #pragma ref type
343: int c;
344: register char *s;
345: if(store) s=va_arg(*args, char *);
346: if(width<0) width=1;
347: for(;;){
348: wgetc(c, f, Done);
349: if(c==EOF) return 0;
350: if(store) *s++=c;
351: }
352: Done:
353: return 1;
354: }
355: static int match(int c, const char *pat){
356: int ok=1;
357: if(*pat=='^'){
358: ok=!ok;
359: pat++;
360: }
361: while(pat!=fmtp){
362: if(pat+2<fmtp && pat[1]=='-'){
363: if(pat[0]<=c && c<=pat[2]
364: || pat[2]<=c && c<=pat[0])
365: return ok;
366: pat+=2;
367: }
368: else if(c==*pat) return ok;
369: pat++;
370: }
371: return !ok;
372: }
373: static int icvt_sq(FILE *f, va_list *args, int store, int width, int type){
374: #pragma ref type
375: int c, nn;
376: register char *s;
377: register const char *pat;
378: pat=++fmtp;
379: if(*fmtp=='^') fmtp++;
380: if(*fmtp!='\0') fmtp++;
381: while(*fmtp!='\0' && *fmtp!=']') fmtp++;
382: if(store) s=va_arg(*args, char *);
383: nn=0;
384: for(;;){
385: wgetc(c, f, Done);
386: if(c==EOF){
387: if(nn==0) return 0;
388: else goto Done;
389: }
390: if(!match(c, pat)) break;
391: if(store) *s++=c;
392: nn++;
393: }
394: nungetc(c, f);
395: Done:
396: if(store) *s='\0';
397: return 1;
398: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.