diff options
author | Gwenolé Beauchesne <gbeauchesne@mandriva.org> | 2003-06-04 18:44:09 +0000 |
---|---|---|
committer | Gwenolé Beauchesne <gbeauchesne@mandriva.org> | 2003-06-04 18:44:09 +0000 |
commit | 4cd6a4a5d7e49d54d53dcf4a6f3393d50bd88e8b (patch) | |
tree | acd4001a266a8713495af7f1b2102b61e67113b0 /mdk-stage1/dietlibc/lib/__v_scanf.c | |
parent | 71b111ec6c4671667a19c6fbe0023d33422535d7 (diff) | |
download | drakx-backup-do-not-use-4cd6a4a5d7e49d54d53dcf4a6f3393d50bd88e8b.tar drakx-backup-do-not-use-4cd6a4a5d7e49d54d53dcf4a6f3393d50bd88e8b.tar.gz drakx-backup-do-not-use-4cd6a4a5d7e49d54d53dcf4a6f3393d50bd88e8b.tar.bz2 drakx-backup-do-not-use-4cd6a4a5d7e49d54d53dcf4a6f3393d50bd88e8b.tar.xz drakx-backup-do-not-use-4cd6a4a5d7e49d54d53dcf4a6f3393d50bd88e8b.zip |
Import dietlibc 0.22 + other fixes for AMD64
Diffstat (limited to 'mdk-stage1/dietlibc/lib/__v_scanf.c')
-rw-r--r-- | mdk-stage1/dietlibc/lib/__v_scanf.c | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/mdk-stage1/dietlibc/lib/__v_scanf.c b/mdk-stage1/dietlibc/lib/__v_scanf.c new file mode 100644 index 000000000..6db51db59 --- /dev/null +++ b/mdk-stage1/dietlibc/lib/__v_scanf.c @@ -0,0 +1,391 @@ +#include "dietfeatures.h" +#include <stdarg.h> +#include <sys/types.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> + +#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<v)?ULLONG_MAX:d+c; +#else + v=(d<v)?ULONG_MAX:d+c; +#endif + --width; + tpch=A_GETC(fn); + } + if ((ch|0x20)<'p') { +#ifdef WANT_LONGLONG_SCANF + register long long l=v; + if (v>=-((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<consumed) + ++n; + } + } + break; + +#ifdef WANT_FLOATING_POINT_IN_SCANF + /* floating point numbers */ + case 'e': + case 'E': + case 'f': + case 'g': + { + double d=0.0; + int neg=0; + + while(isspace(tpch)) tpch=A_GETC(fn); + + if (tpch=='-') { + tpch=A_GETC(fn); + neg=1; + } + if (tpch=='+') tpch=A_GETC(fn); + + while (isdigit(tpch)) { + d=d*10+(tpch-'0'); + tpch=A_GETC(fn); + } + if (tpch=='.') { + double factor=.1; + tpch=A_GETC(fn); + while (isdigit(tpch)) { + d=d+(factor*(tpch-'0')); + factor/=10; + tpch=A_GETC(fn); + } + } + if ((tpch|0x20)=='e') { + int exp=0, prec=tpch; + double factor=10; + tpch=A_GETC(fn); + if (tpch=='-') { + factor=0.1; + tpch=A_GETC(fn); + } else if (tpch=='+') { + tpch=A_GETC(fn); + } else { + d=0; + if (tpch!=-1) A_PUTC(tpch,fn); + tpch=prec; + goto exp_out; + } + while (isdigit(tpch)) { + exp=exp*10+(tpch-'0'); + tpch=A_GETC(fn); + } + while (exp) { /* as in strtod: XXX: this introduces rounding errors */ + d*=factor; --exp; + } + } +exp_out: + if (!flag_discard) { + if (flag_long) { + pd=(double *)va_arg(arg_ptr,double*); + *pd=d; + } else { + pf=(float *)va_arg(arg_ptr,float*); + *pf=d; + } + } + ++n; + } + break; +#endif + + /* char-sequences */ + case 'c': + if (!flag_discard) { + s=(char *)va_arg(arg_ptr,char*); + ++n; + } + if (!flag_width) width=1; + while (width && (tpch!=-1)) { + if (!flag_discard) *(s++)=tpch; + --width; + tpch=A_GETC(fn); + } + break; + + /* c-string */ + case 's': + if (!flag_discard) s=(char *)va_arg(arg_ptr,char*); + while(isspace(tpch)) tpch=A_GETC(fn); + while (width && (tpch!=-1) && (!isspace(tpch))) { + if (!flag_discard) *s=tpch; + if (tpch) ++s; else break; + --width; + tpch=A_GETC(fn); + } + if (!flag_discard) { *s=0; n++; } + break; + + /* consumed-count */ + case 'n': + if (!flag_discard) { + s=(char *)va_arg(arg_ptr,char*); +// ++n; /* in accordance to ANSI C we don't count this conversion */ + } + if (!flag_discard) *(s++)=consumed-1; + break; + +#ifdef WANT_CHARACTER_CLASSES_IN_SCANF + case '[': + { + char cset[256]; + int flag_not=0; + int flag_dash=0; + memset(cset,0,sizeof(cset)); + ch=*format++; + /* first char specials */ + if (ch=='^') { + flag_not=1; + ch=*format++; + } + if ((ch=='-')||(ch==']')) { + cset[ch]=1; + ch=*format++; + } + /* almost all non special chars */ + for (;(*format) && (*format!=']');++format) { + if (flag_dash) { + register unsigned char tmp=*format; + for (;ch<=tmp;++ch) cset[ch]=1; + flag_dash=0; + ch=*format; + } + else if (*format=='-') flag_dash=1; + else { + cset[ch]=1; + ch=*format; + } + } + /* last char specials */ + if (flag_dash) cset['-']=1; + else cset[ch]=1; + + /* like %c or %s */ + if (!flag_discard) { + s=(char *)va_arg(arg_ptr,char*); + ++n; + } + while (width && (tpch>=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."); |