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