#include "dietfeatures.h" #include #include #include #include #include #include #include "dietstdio.h" #include "dietwarning.h" #define A_GETC(fn) (++consumed,(fn)->getch((fn)->data)) #define A_PUTC(c,fn) (--consumed,(fn)->putch((c),(fn)->data)) int __v_scanf(struct arg_scanf* fn, const unsigned char *format, va_list arg_ptr) { unsigned int ch; /* format act. char */ int n=0; /* arg_ptr tmps */ #ifdef WANT_FLOATING_POINT_IN_SCANF double *pd; float *pf; #endif #ifdef WANT_LONGLONG_SCANF long long *pll; #endif long *pl; short *ph; int *pi; char *s; unsigned int consumed=0; /* get one char */ int tpch= A_GETC(fn); //while ((tpch!=-1)&&(*format)) while (*format) { // const unsigned char *prev_fmt=format; ch=*format++; switch (ch) { /* end of format string ?!? */ case 0: return 0; /* skip spaces ... */ case ' ': case '\f': case '\t': case '\v': case '\n': case '\r': while((*format)&&(isspace(*format))) ++format; while(isspace(tpch)) tpch=A_GETC(fn); break; /* format string ... */ case '%': { unsigned int _div=0; int width=-1; char flag_width=0; char flag_discard=0; char flag_half=0; char flag_long=0; char flag_longlong=0; in_scan: ch=*format++; if(ch!='n' && tpch==-1) goto err_out; switch (ch) { /* end of format string ?!? */ case 0: return 0; /* check for % */ case '%': if ((unsigned char)tpch != ch) goto err_out; tpch=A_GETC(fn); break; /* FLAGS */ case '*': flag_discard=1; goto in_scan; case 'h': flag_half=1; goto in_scan; case 'l': if (flag_long) flag_longlong=1; flag_long=1; goto in_scan; case 'q': case 'L': flag_longlong=1; goto in_scan; /* WIDTH */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': width=strtol(format-1,&s,10); format=s; flag_width=1; goto in_scan; /* scan for integer / strtol reimplementation ... */ case 'p': case 'X': case 'x': _div+=6; case 'd': _div+=2; case 'o': _div+=8; case 'u': case 'i': { #ifdef WANT_LONGLONG_SCANF unsigned long long v=0; #else unsigned long v=0; #endif unsigned int consumedsofar=consumed; int neg=0; while(isspace(tpch)) tpch=A_GETC(fn); if (tpch=='-') { tpch=A_GETC(fn); neg=1; } if (tpch=='+') tpch=A_GETC(fn); if (!flag_width) { if ((_div==16) && (tpch=='0')) goto scan_hex; if (!_div) { _div=10; if (tpch=='0') { _div=8; scan_hex: tpch=A_GETC(fn); if ((tpch|32)=='x') { tpch=A_GETC(fn); _div=16; } } } } while ((width)&&(tpch!=-1)) { register unsigned long c=tpch&0xff; #ifdef WANT_LONGLONG_SCANF register unsigned long long d=c|0x20; #else register unsigned long d=c|0x20; #endif c=(d>='a'?d-'a'+10:c<='9'?c-'0':0xff); if (c>=_div) break; d=v*_div; #ifdef WANT_LONGLONG_SCANF v=(d=-((unsigned long long)LLONG_MIN)) { l=(neg)?LLONG_MIN:LLONG_MAX; } else { if (neg) v*=-1; } #else register long l=v; if (v>=-((unsigned long)LONG_MIN)) { l=(neg)?LONG_MIN:LONG_MAX; } else { if (neg) v*=-1; } #endif } if (!flag_discard) { #ifdef WANT_LONGLONG_SCANF if (flag_longlong) { pll=(long long *)va_arg(arg_ptr,long long*); *pll=v; } else #endif if (flag_long) { pl=(long *)va_arg(arg_ptr,long*); *pl=v; } else if (flag_half) { ph=(short*)va_arg(arg_ptr,short*); *ph=v; } else { pi=(int *)va_arg(arg_ptr,int*); *pi=v; } if(consumedsofar=0) && (cset[tpch]^flag_not)) { if (!flag_discard) *s=tpch; if (tpch) ++s; else break; --width; tpch=A_GETC(fn); } if (!flag_discard) *s=0; ++format; } break; #endif default: goto err_out; } } break; /* check if equal format string... */ default: if ((unsigned char)tpch != ch) goto err_out; tpch=A_GETC(fn); break; } } err_out: if (tpch<0 && n==0) return EOF; A_PUTC(tpch,fn); return n; } link_warning("__v_scanf","warning: the scanf functions add several kilobytes of bloat.");