2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Function to scan a string like scanf().
8 #define __vcscan __vcscan
13 #ifndef AROS_NO_LIMITS_H
16 # define ULONG_MAX 4294967295UL
21 /* some macros to cut this short
22 * NEXT(c); read next character
23 * PREV(c); ungetc a character
24 * VAL(a) leads to 1 if a is true and valid
27 # define FULL_SPECIFIERS
30 #define NEXT(c) ((c)=(*getc)(data),size++,incount++)
31 #define PREV(c) do{if((c)!=EOF)(*ungetc)((c),data);size--;incount--;}while(0)
32 #define VAL(a) ((a)&&size<=width)
34 extern unsigned char *__decimalpoint
;
36 #ifdef FULL_SPECIFIERS
37 const static unsigned char undef
[3][sizeof(double)]= /* Undefined numeric values, IEEE */
38 { { 0x7f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00 }, /* +inf */
39 { 0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00 }, /* -inf */
40 { 0x7f,0xf1,0x00,0x00,0x00,0x00,0x00,0x00 } /* NaN */
47 /*****************************************************************************
56 int (* ungetc
)(int,void *),
61 Scan an input stream as specified in format. The result of
62 the scan will be placed in args.
65 data - This is passed to the usercallback getc and ungetc
66 getc - This function gets called when the routine wants to
67 read the next character. It whould return EOF when
68 no more characters are available.
69 ungetc - This function gets called when the routine wants to
70 put a read character back into the stream. The next
71 call to getc should return this character. It is possible
72 that this function is called more than once before the
74 format - A scanf() format string.
75 args - A list of arguments in which the result of the scan should
79 The number of arguments converted.
91 ******************************************************************************/
93 size_t blocks
=0,incount
=0;
102 size_t width
=ULONG_MAX
;
103 char type
,subtype
='i',ignore
=0;
104 const unsigned char *ptr
=format
+1;
110 width
=width
*10+(*ptr
++-'0'); }
112 while(*ptr
=='h'||*ptr
=='l'||*ptr
=='L'||*ptr
=='*')
122 if(type
&&type
!='%'&&type
!='c'&&type
!='n'&&type
!='[')
123 { do /* ignore leading whitespace characters */
126 size
=1; } /* The first non-whitespace character is already read */
132 if(width
==ULONG_MAX
) /* Default */
136 bp
=va_arg(args
,char *);
138 bp
=NULL
; /* Just to get the compiler happy */
140 NEXT(c
); /* 'c' did not skip whitespace */
154 unsigned char tab
[32],a
,b
;
160 for(i
=0;i
<sizeof(tab
);i
++)
161 tab
[i
]=circflag
?255:0;
166 if(*ptr
=='-'&&ptr
[1]&&ptr
[1]!=']')
171 tab
[i
/8]&=~(1<<(i
&7));
180 bp
=va_arg(args
,char *);
182 bp
=NULL
; /* Just to get the compiler happy */
185 while(VAL(c
!=EOF
&&tab
[c
/8]&(1<<(c
&7))))
201 bp
=va_arg(args
,char *);
203 bp
=NULL
; /* Just to get the compiler happy */
205 while(VAL(c
!=EOF
&&!isspace(c
)))
217 #ifdef FULL_SPECIFIERS
223 int min
=0,mine
=0; /* This is a workaround for gcc 2.3.3: should be char */
225 do /* This is there just to be able to break out */
227 if(VAL(c
=='-'||c
=='+'))
231 if(VAL(tolower(c
)=='i')) /* +- inf */
234 if(VAL(tolower(d
)=='n'))
237 if(VAL(tolower(e
)=='f'))
238 { v
=*(double *)&undef
[min
=='-'];
239 break; } /* break out */
244 else if(VAL(toupper(c
)=='N')) /* NaN */
247 if(VAL(tolower(d
)=='a'))
250 if(VAL(toupper(e
)=='N'))
251 { v
=*(double *)&undef
[2];
259 while(VAL(isdigit(c
)))
264 if(VAL(c
==__decimalpoint
[0]))
267 while(VAL(isdigit(c
)))
271 if(size
==2+(min
!=0)) /* No number read till now -> malformatted */
273 c
=__decimalpoint
[0]; }
276 if(min
&&size
==2) /* No number read till now -> malformatted */
282 if(VAL(tolower(c
)=='e'))
285 if(VAL(d
=='-'||d
=='+'))
293 }while(VAL(isdigit(d
)&&ex
<100));
317 *va_arg(args
,double *)=v
;
320 *va_arg(args
,float *)=v
;
331 PREV(c
); /* unget non-'%' character */
335 *va_arg(args
,int *)=incount
;
336 size
=1; /* fake a valid argument */
345 ptr
--; /* unparse NUL character */
348 { subtype
='l'; /* This is the same as %lx */
351 if(VAL((c
=='-'&&type
!='u')||c
=='+'))
355 if(type
=='i') /* which one to use ? */
356 { if(VAL(c
=='0')) /* Could be octal or sedecimal */
358 NEXT(d
); /* Get a look at next character */
359 if(VAL(tolower(d
)=='x'))
361 NEXT(e
); /* And the next */
363 type
='x'; /* Is a valid x number with '0x?' */
368 }else if(VAL(!isdigit(c
)&&isxdigit(c
)))
369 type
='x'; /* Is a valid x number without '0x' */
372 while(type
=='x'&&VAL(c
=='0')) /* sedecimal */
375 if(VAL(tolower(d
)=='x'))
380 break; } /* Used while just to do this ;-) */
384 break; /* Need no loop */
387 base
=type
=='x'||type
=='X'?16:(type
=='o'?8:10);
388 while(VAL(isxdigit(c
)&&(base
!=10||isdigit(c
))&&(base
!=8||c
<='7')))
389 { v
=v
*base
+(isdigit(c
)?c
-'0':0)+(isupper(c
)?c
-'A'+10:0)+(islower(c
)?c
-'a'+10:0);
393 if(min
&&size
==2) /* If there is no valid character after sign, unget last */
406 *va_arg(args
,unsigned long *)=v
;
409 *va_arg(args
,unsigned int *)=v
;
412 *va_arg(args
,unsigned short *)=v
;
424 *va_arg(args
,signed long *)=v2
;
427 *va_arg(args
,signed int *)=v2
;
430 *va_arg(args
,signed short *)=v2
;
440 { if(isspace(*format
))