00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00028 
00029 
00030 #include <stdarg.h>
00031 #include <sys/types.h>
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <errno.h>
00036 #include <limits.h>
00037 #include <ctype.h>
00038 #include <io.h>
00039 
00040 #define WANT_ERROR_PRINTF 1
00041 #define WANT_LONGLONG_PRINTF 1
00042 #define WANT_NULL_PRINTF 1
00043 #define WANT_FLOATING_POINT_IN_PRINTF 1
00044 
00045 #define WANT_FLOATING_POINT_IN_SCANF
00046 #define WANT_LONGLONG_SCANF
00047 #define WANT_CHARACTER_CLASSES_IN_SCANF
00048 
00049 struct str_data {
00050   unsigned char* str;
00051   size_t len;
00052   size_t size;
00053 };
00054 
00055 struct arg_printf {
00056   void *data;
00057   int (*put)(void*,size_t,void*);
00058 };
00059 
00060 static inline unsigned int skip_to(const unsigned char *format) {
00061   unsigned int nr;
00062   for (nr=0; format[nr] && (format[nr]!='%'); ++nr);
00063   return nr;
00064 }
00065 
00066 #define A_WRITE(fn,buf,sz)      ((fn)->put((void*)(buf),(sz),(fn)->data))
00067 
00068 static const char pad_line[2][16]= { "                ", "0000000000000000", };
00069 static inline int write_pad(struct arg_printf* fn, int len, int padwith) {
00070   int nr=0;
00071   for (;len>15;len-=16,nr+=16) {
00072     A_WRITE(fn,pad_line[(padwith=='0')?1:0],16);
00073   }
00074   if (len>0) {
00075     A_WRITE(fn,pad_line[(padwith=='0')?1:0],(unsigned int)len); nr+=len;
00076   }
00077   return nr;
00078 }
00079 
00080 int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase)
00081 {
00082   char *tmp;
00083   unsigned int j=0;
00084 
00085   s[--size]=0;
00086 
00087   tmp=s+size;
00088 
00089   if ((base==0)||(base>36)) base=10;
00090 
00091   j=0;
00092   if (!i)
00093   {
00094     *(--tmp)='0';
00095     j=1;
00096   }
00097 
00098   while((tmp>s)&&(i))
00099   {
00100     tmp--;
00101     if ((*tmp=i%base+'0')>'9') *tmp+=(UpCase?'A':'a')-'9'-1;
00102     i=i/base;
00103     j++;
00104   }
00105   memmove(s,tmp,j+1);
00106 
00107   return j;
00108 }
00109 
00110 int __ltostr(char *s, unsigned int size, unsigned long i, unsigned int base, int UpCase)
00111 {
00112   char *tmp;
00113   unsigned int j=0;
00114 
00115   s[--size]=0;
00116 
00117   tmp=s+size;
00118 
00119   if ((base==0)||(base>36)) base=10;
00120 
00121   j=0;
00122   if (!i)
00123   {
00124     *(--tmp)='0';
00125     j=1;
00126   }
00127 
00128   while((tmp>s)&&(i))
00129   {
00130     tmp--;
00131     if ((*tmp=i%base+'0')>'9') *tmp+=(UpCase?'A':'a')-'9'-1;
00132     i=i/base;
00133     j++;
00134   }
00135   memmove(s,tmp,j+1);
00136 
00137   return j;
00138 }
00139 
00140 static int copystring(char* buf,int maxlen, const char* s) {
00141   int i;
00142   for (i=0; i<3&&i<maxlen; ++i)
00143     buf[i]=s[i];
00144   if (i<maxlen) { buf[i]=0; ++i; }
00145   return i;
00146 }
00147 
00148 int isinf(double d) {
00149   union {
00150     unsigned long long l;
00151     double d;
00152   } u;
00153   u.d=d;
00154   return (u.l==0x7FF0000000000000ll?1:u.l==0xFFF0000000000000ll?-1:0);
00155 }
00156 
00157 int isnan(double d) {
00158   union {
00159     unsigned long long l;
00160     double d;
00161   } u;
00162   u.d=d;
00163   return (u.l==0x7FF8000000000000ll || u.l==0x7FF0000000000000ll || u.l==0xfff8000000000000ll);
00164 }
00165 
00166 int __dtostr(double d,char *buf,unsigned int maxlen,unsigned int prec,unsigned int prec2) {
00167 #if 1
00168   union {
00169     unsigned long long l;
00170     double d;
00171   } u = { .d=d };
00172   
00173   signed long e=((u.l>>52)&((1<<11)-1))-1023;
00174 #else
00175 #if __BYTE_ORDER == __LITTLE_ENDIAN
00176   signed long e=(((((unsigned long*)&d)[1])>>20)&((1<<11)-1))-1023;
00177 #else
00178   signed long e=(((*((unsigned long*)&d))>>20)&((1<<11)-1))-1023;
00179 #endif
00180 #endif
00181 
00182   
00183   signed long e10;
00184   
00185   unsigned int i;
00186   double backup=d;
00187   double tmp;
00188   char *oldbuf=buf;
00189 
00190   if ((i=isinf(d))) return copystring(buf,maxlen,i>0?"inf":"-inf");
00191   if (isnan(d)) return copystring(buf,maxlen,"nan");
00192   e10=1+(long)(e*0.30102999566398119802); 
00193   
00194 
00195 
00196 
00197 
00198 
00199   if (d==0.0) {
00200     prec2=prec2==0?1:prec2+2;
00201     prec2=prec2>maxlen?8:prec2;
00202     i=0;
00203     if (prec2 && (long long)u.l<0) { buf[0]='-'; ++i; }
00204     for (; i<prec2; ++i) buf[i]='0';
00205     buf[buf[0]=='0'?1:2]='.'; buf[i]=0;
00206     return i;
00207   }
00208 
00209   if (d < 0.0) { d=-d; *buf='-'; --maxlen; ++buf; }
00210 
00211    
00212 
00213 
00214 
00215 
00216   tmp = 0.5;
00217   for (i = 0; i < prec2; i++) { tmp *= 0.1; }
00218   d += tmp;
00219 
00220   if (d < 1.0) { *buf='0'; --maxlen; ++buf; }
00221 
00222   if (e10>0) {
00223     int first=1;        
00224     tmp = 10.0;
00225     i=e10;
00226     while (i>10) { tmp=tmp*1e10; i-=10; }
00227     while (i>1) { tmp=tmp*10; --i; }
00228     
00229 
00230 
00231     while (tmp>0.9) {
00232       char digit;
00233       double fraction=d/tmp;
00234         digit=(int)(fraction);          
00235       if (!first || digit) {
00236         first=0;
00237         *buf=digit+'0'; ++buf;
00238         if (!maxlen) {
00239           
00240           int len=__dtostr(backup/tmp,oldbuf,maxlen,prec,prec2);
00241           int initial=1;
00242           if (len==0) return 0;
00243           maxlen-=len; buf+=len;
00244           if (maxlen>0) {
00245             *buf='e';
00246             ++buf;
00247           }
00248           --maxlen;
00249           for (len=1000; len>0; len/=10) {
00250             if (e10>=len || !initial) {
00251               if (maxlen>0) {
00252                 *buf=(e10/len)+'0';
00253                 ++buf;
00254               }
00255               --maxlen;
00256               initial=0;
00257               e10=e10%len;
00258             }
00259           }
00260           if (maxlen>0) goto fini;
00261           return 0;
00262         }
00263         d-=digit*tmp;
00264         --maxlen;
00265       }
00266       tmp/=10.0;
00267     }
00268   }
00269   else
00270   {
00271      tmp = 0.1;
00272   }
00273 
00274   if (buf==oldbuf) {
00275     if (!maxlen) return 0; --maxlen;
00276     *buf='0'; ++buf;
00277   }
00278   if (prec2 || prec>(unsigned int)(buf-oldbuf)+1) {     
00279     if (!maxlen) return 0; --maxlen;
00280     *buf='.'; ++buf;
00281     prec-=buf-oldbuf-1;
00282     if (prec2) prec=prec2;
00283     if (prec>maxlen) return 0;
00284     while (prec>0) {
00285       char digit;
00286       double fraction=d/tmp;
00287       digit=(int)(fraction);            
00288       *buf=digit+'0'; ++buf;
00289       d-=digit*tmp;
00290       tmp/=10.0;
00291       --prec;
00292     }
00293   }
00294 fini:
00295   *buf=0;
00296   return buf-oldbuf;
00297 }
00298 
00299 int __v_printf(struct arg_printf* fn, const unsigned char *format, va_list arg_ptr)
00300 {
00301   int len=0;
00302 #ifdef WANT_ERROR_PRINTF
00303   int _my_errno = errno;
00304 #endif
00305 
00306   while (*format) {
00307     unsigned int sz = skip_to(format);
00308     if (sz) {
00309       A_WRITE(fn,format,sz); len+=sz;
00310       format+=sz;
00311     }
00312     if (*format=='%') {
00313       char buf[128];
00314       union { char*s; } u_str;
00315 #define s u_str.s
00316 
00317       int retval;
00318       unsigned char ch, padwith=' ';
00319 
00320       char flag_in_sign=0;
00321       char flag_upcase=0;
00322       char flag_hash=0;
00323       char flag_left=0;
00324       char flag_space=0;
00325       char flag_sign=0;
00326       char flag_dot=0;
00327       signed char flag_long=0;
00328 
00329       unsigned int base;
00330       unsigned int width=0, preci=0;
00331 
00332       long number=0;
00333 #ifdef WANT_LONGLONG_PRINTF
00334       long long llnumber=0;
00335 #endif
00336 
00337       ++format;
00338 inn_printf:
00339       switch(ch=*format++) {
00340       case 0:
00341         return -1;
00342         break;
00343 
00344       
00345       case '#':
00346         flag_hash=-1;
00347       case 'z':
00348         goto inn_printf;
00349 
00350       case 'h':
00351         --flag_long;
00352         goto inn_printf;
00353       case 'q':         
00354       case 'L':
00355         ++flag_long; 
00356       case 'l':
00357         ++flag_long;
00358         goto inn_printf;
00359 
00360       case '-':
00361         flag_left=1;
00362         goto inn_printf;
00363 
00364       case ' ':
00365         flag_space=1;
00366         goto inn_printf;
00367 
00368       case '+':
00369         flag_sign=1;
00370         goto inn_printf;
00371 
00372       case '0':
00373       case '1':
00374       case '2':
00375       case '3':
00376       case '4':
00377       case '5':
00378       case '6':
00379       case '7':
00380       case '8':
00381       case '9':
00382         if(flag_dot) return -1;
00383         width=strtoul(format-1,(char**)&s,10);
00384         if (ch=='0' && !flag_left) padwith='0';
00385         format=s;
00386         goto inn_printf;
00387 
00388       case '*':
00389         width=va_arg(arg_ptr,int);
00390         goto inn_printf;
00391 
00392       case '.':
00393         flag_dot=1;
00394         if (*format=='*') {
00395           int tmp=va_arg(arg_ptr,int);
00396           preci=tmp<0?0:tmp;
00397           ++format;
00398         } else {
00399           long int tmp=strtol(format,(char**)&s,10);
00400           preci=tmp<0?0:tmp;
00401           format=s;
00402         }
00403         goto inn_printf;
00404 
00405       
00406       case 'c':
00407         ch=(char)va_arg(arg_ptr,int);
00408       case '%':
00409         A_WRITE(fn,&ch,1); ++len;
00410         break;
00411 
00412 #ifdef WANT_ERROR_PRINTF
00413       
00414       case 'm':
00415         s=strerror(_my_errno);
00416         sz=strlen(s);
00417         A_WRITE(fn,s,sz); len+=sz;
00418         break;
00419 #endif
00420       
00421       case 's':
00422         s=va_arg(arg_ptr,char *);
00423 #ifdef WANT_NULL_PRINTF
00424         if (!s) s="(null)";
00425 #endif
00426         sz = strlen(s);
00427         if (flag_dot && sz>preci) sz=preci;
00428         preci=0;
00429         flag_dot^=flag_dot;
00430         padwith=' ';
00431 
00432 print_out:
00433       {
00434         char *sign=s;
00435         int todo=0;
00436         int vs;
00437         
00438         if (! (width||preci) ) {
00439           A_WRITE(fn,s,sz); len+=sz;
00440           break;
00441         }
00442         
00443         if (flag_in_sign) todo=1;
00444         if (flag_hash>0)  todo=flag_hash;
00445         if (todo) {
00446           s+=todo;
00447           sz-=todo;
00448           width-=todo;
00449         }
00450         
00451         if (!flag_left) {
00452           if (flag_dot) {
00453             vs=preci>sz?preci:sz;
00454             len+=write_pad(fn,(signed int)width-(signed int)vs,' ');
00455             if (todo) {
00456               A_WRITE(fn,sign,todo);
00457               len+=todo;
00458             }
00459             len+=write_pad(fn,(signed int)preci-(signed int)sz,'0');
00460           } else {
00461             if (todo && padwith=='0') {
00462               A_WRITE(fn,sign,todo);
00463               len+=todo; todo=0;
00464             }
00465             len+=write_pad(fn,(signed int)width-(signed int)sz, padwith);
00466             if (todo) {
00467               A_WRITE(fn,sign,todo);
00468               len+=todo;
00469             }
00470           }
00471           A_WRITE(fn,s,sz); len+=sz;
00472         } else if (flag_left) {
00473           if (todo) {
00474             A_WRITE(fn,sign,todo);
00475             len+=todo;
00476           }
00477           len+=write_pad(fn,(signed int)preci-(signed int)sz, '0');
00478           A_WRITE(fn,s,sz); len+=sz;
00479           vs=preci>sz?preci:sz;
00480           len+=write_pad(fn,(signed int)width-(signed int)vs, ' ');
00481         } else {
00482           A_WRITE(fn,s,sz); len+=sz;
00483         }
00484         break;
00485       }
00486 
00487       
00488       case 'b':
00489         base=2;
00490         sz=0;
00491         goto num_printf;
00492       case 'p':
00493         flag_hash=2;
00494         flag_long=1;
00495         ch='x';
00496       case 'X':
00497         flag_upcase=(ch=='X');
00498       case 'x':
00499         base=16;
00500         sz=0;
00501         if (flag_hash) {
00502           buf[1]='0';
00503           buf[2]=ch;
00504           flag_hash=2;
00505           sz=2;
00506         }
00507         if (preci>width) width=preci;
00508         goto num_printf;
00509       case 'd':
00510       case 'i':
00511         flag_in_sign=1;
00512       case 'u':
00513         base=10;
00514         sz=0;
00515         goto num_printf;
00516       case 'o':
00517         base=8;
00518         sz=0;
00519         if (flag_hash) {
00520           buf[1]='0';
00521           flag_hash=1;
00522           ++sz;
00523         }
00524 
00525 num_printf:
00526         s=buf+1;
00527 
00528         if (flag_long>0) {
00529 #ifdef WANT_LONGLONG_PRINTF
00530           if (flag_long>1)
00531             llnumber=va_arg(arg_ptr,long long);
00532           else
00533 #endif
00534             number=va_arg(arg_ptr,long);
00535         }
00536         else
00537           number=va_arg(arg_ptr,int);
00538 
00539         if (flag_in_sign) {
00540 #ifdef WANT_LONGLONG_PRINTF
00541           if ((flag_long>1)&&(llnumber<0)) {
00542             llnumber=-llnumber;
00543             flag_in_sign=2;
00544           } else
00545 #endif
00546             if (number<0) {
00547               number=-number;
00548               flag_in_sign=2;
00549             }
00550         }
00551         if (flag_long<0) number&=0xffff;
00552         if (flag_long<-1) number&=0xff;
00553 #ifdef WANT_LONGLONG_PRINTF
00554         if (flag_long>1)
00555           retval = __lltostr(s+sz,sizeof(buf)-5,(unsigned long long) llnumber,base,flag_upcase);
00556         else
00557 #endif
00558           retval = __ltostr(s+sz,sizeof(buf)-5,(unsigned long) number,base,flag_upcase);
00559 
00560         
00561         if (flag_dot && retval == 1 && s[sz] == '0') {
00562           if (preci == 0||flag_hash > 0) {
00563             sz = 0;
00564           }
00565           flag_hash = 0;
00566         } else sz += retval;
00567 
00568         if (flag_in_sign==2) {
00569           *(--s)='-';
00570           ++sz;
00571         } else if ((flag_in_sign)&&(flag_sign || flag_space)) {
00572           *(--s)=(flag_sign)?'+':' ';
00573           ++sz;
00574         } else flag_in_sign=0;
00575 
00576         goto print_out;
00577 
00578 #ifdef WANT_FLOATING_POINT_IN_PRINTF
00579       
00580       case 'f':
00581       case 'g':
00582         {
00583           int g=(ch=='g');
00584           double d=va_arg(arg_ptr,double);
00585           s=buf+1;
00586           if (width==0) width=1;
00587           if (!flag_dot) preci=6;
00588           if (flag_sign || d < +0.0) flag_in_sign=1;
00589         
00590           sz=__dtostr(d,s,sizeof(buf)-1,width,preci);
00591         
00592           if (flag_dot) {
00593             char *tmp;
00594             if ((tmp=strchr(s,'.'))) {
00595               if (preci || flag_hash) ++tmp;
00596               while (preci>0 && *++tmp) --preci;
00597               *tmp=0;
00598             } else if (flag_hash) {
00599               s[sz]='.';
00600               s[++sz]='\0';
00601             }
00602           }
00603 
00604           if (g) {
00605             char *tmp,*tmp1;    
00606             if ((tmp=strchr(s,'.'))) {
00607               tmp1=strchr(tmp,'e');
00608               while (*tmp) ++tmp;
00609               if (tmp1) tmp=tmp1;
00610               while (*--tmp=='0') ;
00611               if (*tmp!='.') ++tmp;
00612               *tmp=0;
00613               if (tmp1) strcpy(tmp,tmp1);
00614             }
00615           }
00616         
00617           if ((flag_sign || flag_space) && d>=0) {
00618             *(--s)=(flag_sign)?'+':' ';
00619             ++sz;
00620           }
00621         
00622           sz=strlen(s);
00623           flag_dot=0;
00624           flag_hash=0;
00625           goto print_out;
00626         }
00627 #endif
00628 
00629       default:
00630         break;
00631       }
00632     }
00633   }
00634   return len;
00635 }
00636 
00637 #undef s
00638 
00639 static int swrite(void*ptr, size_t nmemb, struct str_data* sd) {
00640   size_t tmp=sd->size-sd->len;
00641   if (tmp>0) {
00642     size_t len=nmemb;
00643     if (len>tmp) len=tmp;
00644     if (sd->str) {
00645       memcpy(sd->str+sd->len,ptr,len);
00646       sd->str[sd->len+len]=0;
00647     }
00648     sd->len+=len;
00649   }
00650   return nmemb;
00651 }
00652 
00653 int _win_vsnprintf(char* str, size_t size, const char *format, va_list arg_ptr)
00654 {
00655   long n;
00656   struct str_data sd = { str, 0, size?size-1:0 };
00657   struct arg_printf ap = { &sd, (int(*)(void*,size_t,void*)) swrite };
00658   n=__v_printf(&ap,format,arg_ptr);
00659   if (str && size && n>=0) {
00660     if (size!=(size_t)-1 && ((size_t)n>=size)) str[size-1]=0;
00661     else str[n]=0;
00662   }
00663   return n;
00664 }
00665 
00666 int _win_vsprintf(char *dest, const char *format, va_list arg_ptr)
00667 {
00668   return _win_vsnprintf(dest,(size_t)-1,format,arg_ptr);
00669 }
00670 
00671 static int __fwrite(void*ptr, size_t nmemb, int fd) {
00672   return fwrite(ptr, 1, nmemb, fd);
00673 }
00674 
00675 int _win_vfprintf(FILE *stream, const char *format, va_list arg_ptr)
00676 {
00677   struct arg_printf ap = { stream, (int(*)(void*,size_t,void*)) __fwrite };
00678   return __v_printf(&ap,format,arg_ptr);
00679 }
00680 
00681 int __stdio_outs(const char *s, size_t len) {
00682   return (fwrite(s, 1, len, stdout)==(int)len)?1:0;
00683 }
00684 
00685 int _win_vprintf(const char *format, va_list ap)
00686 {
00687   struct arg_printf _ap = { 0, (int(*)(void*,size_t,void*)) __stdio_outs };
00688   return __v_printf(&_ap,format,ap);
00689 }
00690 
00691 int _win_fprintf(FILE *f,const char *format, ...)
00692 {
00693   int n;
00694   va_list arg_ptr;
00695   va_start(arg_ptr,format);
00696   n=_win_vfprintf(f,format,arg_ptr);
00697   va_end(arg_ptr);
00698   return n;
00699 }
00700 
00701 int _win_printf(const char *format, ...)
00702 {
00703   int n;
00704   va_list arg_ptr;
00705   va_start(arg_ptr, format);
00706   n=_win_vprintf(format, arg_ptr);
00707   va_end(arg_ptr);
00708   return n;
00709 }
00710 
00711 int _win_snprintf(char *str, size_t size, const char *format, ...)
00712 {
00713   int n;
00714   va_list arg_ptr;
00715   va_start(arg_ptr, format);
00716   n=vsnprintf(str,size,format,arg_ptr);
00717   va_end (arg_ptr);
00718   return n;
00719 }
00720 
00721 int _win_sprintf(char *dest, const char *format, ...)
00722 {
00723   int n;
00724   va_list arg_ptr;
00725   va_start(arg_ptr, format);
00726   n=vsprintf(dest,format,arg_ptr);
00727   va_end (arg_ptr);
00728   return n;
00729 }
00730 
00731 #define A_GETC(fn)  (++consumed,(fn)->getch((fn)->data))
00732 #define A_PUTC(c,fn)  (--consumed,(fn)->putch((c),(fn)->data))
00733 
00734 struct arg_scanf {
00735   void *data;
00736   int (*getch)(void*);
00737   int (*putch)(int,void*);
00738 };
00739 
00740 int __v_scanf(struct arg_scanf* fn, const unsigned char *format, va_list arg_ptr)
00741 {
00742   unsigned int ch;  
00743   int n=0;
00744 
00745   
00746 #ifdef WANT_FLOATING_POINT_IN_SCANF
00747   double *pd;
00748   float  *pf;
00749 #endif
00750 #ifdef WANT_LONGLONG_SCANF
00751   long long *pll;
00752 #endif
00753   long   *pl;
00754   short  *ph;
00755   int    *pi;
00756   char    *s;
00757 
00758   unsigned int consumed=0;
00759 
00760   
00761   int tpch= A_GETC(fn);
00762 
00763   
00764   while (*format)
00765   {
00766     ch=*format++;
00767     switch (ch) {
00768     
00769     case 0: return 0;
00770 
00771     
00772     case ' ':
00773     case '\f':
00774     case '\t':
00775     case '\v':
00776     case '\n':
00777     case '\r':
00778       while((*format)&&(isspace(*format))) ++format;
00779       while(isspace(tpch)) tpch=A_GETC(fn);
00780       break;
00781 
00782     
00783     case '%':
00784       {
00785   unsigned int _div=0;
00786   int width=-1;
00787   char flag_width=0;
00788   char flag_discard=0;
00789   char flag_half=0;
00790   char flag_long=0;
00791   char flag_longlong=0;
00792 
00793 in_scan:
00794   ch=*format++;
00795   if(ch!='n' && tpch==-1) goto err_out;
00796   switch (ch) {
00797   
00798   case 0: return 0;
00799 
00800   
00801   case '%':
00802     if ((unsigned char)tpch != ch) goto err_out;
00803     tpch=A_GETC(fn);
00804     break;
00805 
00806   
00807   case '*':
00808     flag_discard=1;
00809     goto in_scan;
00810   case 'h':
00811     flag_half=1;
00812     goto in_scan;
00813   case 'l':
00814     if (flag_long) flag_longlong=1;
00815     flag_long=1;
00816     goto in_scan;
00817   case 'q':
00818   case 'L':
00819     flag_longlong=1;
00820     goto in_scan;
00821 
00822   
00823   case '0':
00824   case '1':
00825   case '2':
00826   case '3':
00827   case '4':
00828   case '5':
00829   case '6':
00830   case '7':
00831   case '8':
00832   case '9':
00833     width=strtol(format-1,&s,10);
00834     format=s;
00835     flag_width=1;
00836     goto in_scan;
00837 
00838   
00839   case 'p':
00840   case 'X':
00841   case 'x':
00842     _div+=6;
00843   case 'd':
00844     _div+=2;
00845   case 'o':
00846     _div+=8;
00847   case 'u':
00848   case 'i':
00849     {
00850 #ifdef WANT_LONGLONG_SCANF
00851       unsigned long long v=0;
00852 #else
00853       unsigned long v=0;
00854 #endif
00855       unsigned int consumedsofar;
00856       int neg=0;
00857       while(isspace(tpch)) tpch=A_GETC(fn);
00858       if (tpch=='-') {
00859         tpch=A_GETC(fn);
00860         neg=1;
00861       }
00862 
00863       if (tpch=='+') tpch=A_GETC(fn);
00864 
00865       if (tpch==-1) return n;
00866       consumedsofar=consumed;
00867 
00868       if (!flag_width) {
00869         if ((_div==16) && (tpch=='0')) goto scan_hex;
00870         if (!_div) {
00871     _div=10;
00872     if (tpch=='0') {
00873       _div=8;
00874 scan_hex:
00875       tpch=A_GETC(fn);
00876       if ((tpch|32)=='x') {
00877         tpch=A_GETC(fn);
00878         _div=16;
00879       }
00880     }
00881         }
00882       }
00883       while ((width)&&(tpch!=-1)) {
00884         register unsigned long c=tpch&0xff;
00885 #ifdef WANT_LONGLONG_SCANF
00886         register unsigned long long d=c|0x20;
00887 #else
00888         register unsigned long d=c|0x20;
00889 #endif
00890         c=(d>='a'?d-'a'+10:c<='9'?c-'0':0xff);
00891         if (c>=_div) break;
00892         d=v*_div;
00893 #ifdef WANT_LONGLONG_SCANF
00894         v=(d<v)?ULLONG_MAX:d+c;
00895 #else
00896         v=(d<v)?ULONG_MAX:d+c;
00897 #endif
00898         --width;
00899         tpch=A_GETC(fn);
00900       }
00901 
00902       if (consumedsofar==consumed) return n;
00903 
00904       if ((ch|0x20)<'p') {
00905 #ifdef WANT_LONGLONG_SCANF
00906         register long long l=v;
00907         if (v>=-((unsigned long long)LLONG_MIN)) {
00908     l=(neg)?LLONG_MIN:LLONG_MAX;
00909         }
00910         else {
00911     if (neg) v*=-1;
00912         }
00913 #else
00914         register long l=v;
00915         if (v>=-((unsigned long)LONG_MIN)) {
00916     l=(neg)?LONG_MIN:LONG_MAX;
00917         }
00918         else {
00919     if (neg) v*=-1;
00920         }
00921 #endif
00922       }
00923       if (!flag_discard) {
00924 #ifdef WANT_LONGLONG_SCANF
00925         if (flag_longlong) {
00926     pll=(long long *)va_arg(arg_ptr,long long*);
00927     *pll=v;
00928         } else
00929 #endif
00930         if (flag_long) {
00931     pl=(long *)va_arg(arg_ptr,long*);
00932     *pl=v;
00933         } else if (flag_half) {
00934     ph=(short*)va_arg(arg_ptr,short*);
00935     *ph=v;
00936         } else {
00937     pi=(int *)va_arg(arg_ptr,int*);
00938     *pi=v;
00939         }
00940         if(consumedsofar<consumed) ++n;
00941       }
00942     }
00943     break;
00944 
00945   
00946 #ifdef WANT_FLOATING_POINT_IN_SCANF
00947   
00948   case 'e':
00949   case 'E':
00950   case 'f':
00951   case 'g':
00952     {
00953       double d=0.0;
00954       int neg=0;
00955       unsigned int consumedsofar;
00956 
00957       while(isspace(tpch)) tpch=A_GETC(fn);
00958 
00959       if (tpch=='-') {
00960         tpch=A_GETC(fn);
00961         neg=1;
00962       }
00963       if (tpch=='+') tpch=A_GETC(fn);
00964 
00965       consumedsofar=consumed;
00966 
00967       while (isdigit(tpch)) {
00968         d=d*10+(tpch-'0');
00969         tpch=A_GETC(fn);
00970       }
00971       if (tpch=='.') {
00972         double factor=.1;
00973         consumedsofar++;
00974         tpch=A_GETC(fn);
00975         while (isdigit(tpch)) {
00976     d=d+(factor*(tpch-'0'));
00977     factor/=10;
00978     tpch=A_GETC(fn);
00979         }
00980       }
00981       if (consumedsofar==consumed) return n;  
00982       if ((tpch|0x20)=='e') {
00983         int exp=0, prec=tpch;
00984         double factor=10;
00985         tpch=A_GETC(fn);
00986         if (tpch=='-') {
00987     factor=0.1;
00988     tpch=A_GETC(fn);
00989         } else if (tpch=='+') {
00990     tpch=A_GETC(fn);
00991         } else {
00992     d=0;
00993     if (tpch!=-1) A_PUTC(tpch,fn);
00994     tpch=prec;
00995     goto exp_out;
00996         }
00997         consumedsofar=consumed;
00998         while (isdigit(tpch)) {
00999     exp=exp*10+(tpch-'0');
01000     tpch=A_GETC(fn);
01001         }
01002         if (consumedsofar==consumed) return n;  
01003         while (exp) { 
01004     d*=factor; --exp;
01005         }
01006       }
01007 exp_out:
01008       if (!flag_discard) {
01009         if (flag_long) {
01010     pd=(double *)va_arg(arg_ptr,double*);
01011     *pd=d;
01012         } else {
01013     pf=(float *)va_arg(arg_ptr,float*);
01014     *pf=d;
01015         }
01016         ++n;
01017       }
01018     }
01019     break;
01020 #endif
01021 
01022   
01023   case 'c':
01024     if (!flag_discard) {
01025       s=(char *)va_arg(arg_ptr,char*);
01026       ++n;
01027     }
01028     if (!flag_width) width=1;
01029     while (width && (tpch!=-1)) {
01030       if (!flag_discard) *(s++)=tpch;
01031       --width;
01032       tpch=A_GETC(fn);
01033     }
01034     break;
01035 
01036   
01037   case 's':
01038     if (!flag_discard) s=(char *)va_arg(arg_ptr,char*);
01039     while(isspace(tpch)) tpch=A_GETC(fn);
01040     if (tpch==-1) break;    
01041     while (width && (tpch!=-1) && (!isspace(tpch))) {
01042       if (!flag_discard) *s=tpch;
01043       if (tpch) ++s; else break;
01044       --width;
01045       tpch=A_GETC(fn);
01046     }
01047     if (!flag_discard) { *s=0; ++n; }
01048     break;
01049 
01050   
01051   case 'n':
01052     if (!flag_discard) {
01053       pi=(int *)va_arg(arg_ptr,int *);
01054 
01055             *pi=consumed-1;
01056     }
01057     break;
01058 
01059 #ifdef WANT_CHARACTER_CLASSES_IN_SCANF
01060   case '[':
01061     {
01062       char cset[256];
01063       int flag_not=0;
01064       int flag_dash=0;
01065       memset(cset,0,sizeof(cset));
01066       ch=*format++;
01067       
01068       if (ch=='^') {
01069         flag_not=1;
01070         ch=*format++;
01071       }
01072       if ((ch=='-')||(ch==']')) {
01073         cset[ch]=1;
01074         ch=*format++;
01075       }
01076       
01077       for (;(*format) && (*format!=']');++format) {
01078         if (flag_dash) {
01079     register unsigned char tmp=*format;
01080     for (;ch<=tmp;++ch) cset[ch]=1;
01081     flag_dash=0;
01082     ch=*format;
01083         }
01084         else if (*format=='-') flag_dash=1;
01085         else {
01086     cset[ch]=1;
01087     ch=*format;
01088         }
01089       }
01090       
01091       if (flag_dash) cset['-']=1;
01092       else cset[ch]=1;
01093 
01094       
01095       if (!flag_discard) {
01096         s=(char *)va_arg(arg_ptr,char*);
01097         ++n;
01098       }
01099       while (width && (tpch>=0) && (cset[tpch]^flag_not)) {
01100         if (!flag_discard) *s=tpch;
01101         if (tpch) ++s; else break;
01102         --width;
01103         tpch=A_GETC(fn);
01104       }
01105       if (!flag_discard) *s=0;
01106       ++format;
01107     }
01108     break;
01109 #endif
01110   default:
01111     goto err_out;
01112   }
01113       }
01114       break;
01115 
01116     
01117     default:
01118       if ((unsigned char)tpch != ch) goto err_out;
01119       tpch=A_GETC(fn);
01120       break;
01121     }
01122   }
01123 
01124   
01125   if(*format) {
01126     while(isspace(*format)) format++;
01127     if(format[0] == '%' && format[1] == 'n') {
01128       pi = (int *) va_arg(arg_ptr, int *);
01129       *pi = consumed - 1;
01130     }
01131   }
01132 
01133 err_out:
01134   if (tpch<0 && n==0) return EOF;
01135   A_PUTC(tpch,fn);
01136   return n;
01137 }
01138 
01139 struct scanf_str_data {
01140   unsigned char* str;
01141 };
01142 
01143 static int sgetc(struct scanf_str_data* sd) {
01144   register unsigned int ret = *(sd->str++);
01145   return (ret)?(int)ret:-1;
01146 }
01147 
01148 static int sputc(int c, struct scanf_str_data* sd) {
01149   return (*(--sd->str)==c)?c:-1;
01150 }
01151 
01152 int _win_vsscanf(const char* str, const char* format, va_list arg_ptr)
01153 {
01154   struct scanf_str_data  fdat = { (unsigned char*)str };
01155   struct arg_scanf farg = { (void*)&fdat, (int(*)(void*))sgetc, (int(*)(int,void*))sputc };
01156   return __v_scanf(&farg,format,arg_ptr);
01157 }
01158 
01159 int _win_sscanf(const char *str, const char *format, ...)
01160 {
01161   int n;
01162   va_list arg_ptr;
01163   va_start(arg_ptr, format);
01164   n = _win_vsscanf(str,format,arg_ptr);
01165   va_end (arg_ptr);
01166   return n;
01167 }
01168 
01169 int _win_vfscanf(FILE *stream, const char *format, va_list arg_ptr)
01170 {
01171   struct arg_scanf farg = { (void*)stream, (int(*)(void*))fgetc, (int(*)(int,void*))ungetc };
01172   return __v_scanf(&farg,format,arg_ptr);
01173 }
01174 
01175 int _win_vscanf(const char *format, va_list arg_ptr)
01176 {
01177   return _win_vfscanf(stdin,format,arg_ptr);
01178 }
01179 
01180 int _win_scanf(const char *format, ...)
01181 {
01182   int n;
01183   va_list arg_ptr;
01184   va_start(arg_ptr, format);
01185   n = _win_vfscanf(stdin,format,arg_ptr);
01186   va_end (arg_ptr);
01187   return n;
01188 }
01189 
01190 int _win_fscanf(FILE *stream, const char *format, ...)
01191 {
01192   int n;
01193   va_list arg_ptr;
01194   va_start(arg_ptr, format);
01195   n = _win_vfscanf(stream,format,arg_ptr);
01196   va_end (arg_ptr);
01197   return n;
01198 }
01199 
01200