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