Annotation of researchv10no/libc/stdio/vfscanf.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * pANS stdio -- vfscanf
                      3:  */
                      4: #include "iolib.h"
                      5: #include <stdarg.h>
                      6: #include <math.h>
                      7: #include <stdlib.h>
                      8: #include <ctype.h>
                      9: #ifdef sgi
                     10: #undef getc
                     11: #define getc(p) (--(p)->_cnt>=0? (int)*(p)->_ptr++:xfilbuf(p))
                     12: 
                     13:  static int __cnt;
                     14:  static int xfilbuf(FILE*);
                     15: 
                     16:  static int
                     17: xfilbuf(FILE *p)
                     18: {
                     19:        int rv;
                     20:        if (p->_flag & _IOEOF)
                     21:                return EOF;
                     22:        if (_us_rsthread_stdio) {
                     23:                p->_cnt = __cnt;
                     24:                rv = _semgetc(p);
                     25:                __cnt = p->_cnt;
                     26:                p->_cnt = 0;
                     27:                }
                     28:        else {
                     29:                rv = _filbuf(p);
                     30:                if (p->_cnt == 1 && p->_ptr == p->_base)
                     31:                        p->_cnt = 0;
                     32:                }
                     33:        return rv;
                     34:        }
                     35: #endif
                     36: static int icvt_f(FILE *f, va_list *args, int store, int width, int type);
                     37: static int icvt_x(FILE *f, va_list *args, int store, int width, int type);
                     38: static int icvt_sq(FILE *f, va_list *args, int store, int width, int type);
                     39: static int icvt_c(FILE *f, va_list *args, int store, int width, int type);
                     40: static int icvt_d(FILE *f, va_list *args, int store, int width, int type);
                     41: static int icvt_i(FILE *f, va_list *args, int store, int width, int type);
                     42: static int icvt_n(FILE *f, va_list *args, int store, int width, int type);
                     43: static int icvt_o(FILE *f, va_list *args, int store, int width, int type);
                     44: static int icvt_p(FILE *f, va_list *args, int store, int width, int type);
                     45: static int icvt_s(FILE *f, va_list *args, int store, int width, int type);
                     46: static int icvt_u(FILE *f, va_list *args, int store, int width, int type);
                     47: static int (*icvt[])(FILE *, va_list *, int, int, int)={
                     48: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^@ ^A ^B ^C ^D ^E ^F ^G */
                     49: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^H ^I ^J ^K ^L ^M ^N ^O */
                     50: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^P ^Q ^R ^S ^T ^U ^V ^W */
                     51: 0,     0,      0,      0,      0,      0,      0,      0,      /* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
                     52: 0,     0,      0,      0,      0,      0,      0,      0,      /* sp  !  "  #  $  %  &  ' */
                     53: 0,     0,      0,      0,      0,      0,      0,      0,      /*  (  )  *  +  ,  -  .  / */
                     54: 0,     0,      0,      0,      0,      0,      0,      0,      /*  0  1  2  3  4  5  6  7 */
                     55: 0,     0,      0,      0,      0,      0,      0,      0,      /*  8  9  :  ;  <  =  >  ? */
                     56: 0,     0,      0,      0,      0,      icvt_f, 0,      icvt_f, /*  @  A  B  C  D  E  F  G */
                     57: 0,     0,      0,      0,      0,      0,      0,      0,      /*  H  I  J  K  L  M  N  O */
                     58: 0,     0,      0,      0,      0,      0,      0,      0,      /*  P  Q  R  S  T  U  V  W */
                     59: icvt_x,        0,      0,      icvt_sq,0,      0,      0,      0,      /*  X  Y  Z  [  \  ]  ^  _ */
                     60: 0,     0,      0,      icvt_c, icvt_d, icvt_f, icvt_f, icvt_f, /*  `  a  b  c  d  e  f  g */
                     61: 0,     icvt_i, 0,      0,      0,      0,      icvt_n, icvt_o, /*  h  i  j  k  l  m  n  o */
                     62: icvt_p,        0,      0,      icvt_s, 0,      icvt_u, 0,      0,      /*  p  q  r  s  t  u  v  w */
                     63: icvt_x,        0,      0,      0,      0,      0,      0,      0,      /*  x  y  z  {  |  }  ~ ^? */
                     64: 
                     65: 0,     0,      0,      0,      0,      0,      0,      0,
                     66: 0,     0,      0,      0,      0,      0,      0,      0,
                     67: 0,     0,      0,      0,      0,      0,      0,      0,
                     68: 0,     0,      0,      0,      0,      0,      0,      0,
                     69: 0,     0,      0,      0,      0,      0,      0,      0,
                     70: 0,     0,      0,      0,      0,      0,      0,      0,
                     71: 0,     0,      0,      0,      0,      0,      0,      0,
                     72: 0,     0,      0,      0,      0,      0,      0,      0,
                     73: 0,     0,      0,      0,      0,      0,      0,      0,
                     74: 0,     0,      0,      0,      0,      0,      0,      0,
                     75: 0,     0,      0,      0,      0,      0,      0,      0,
                     76: 0,     0,      0,      0,      0,      0,      0,      0,
                     77: 0,     0,      0,      0,      0,      0,      0,      0,
                     78: 0,     0,      0,      0,      0,      0,      0,      0,
                     79: 0,     0,      0,      0,      0,      0,      0,      0,
                     80: 0,     0,      0,      0,      0,      0,      0,      0,
                     81: 
                     82: };
                     83: #define        ngetc(f)                (nread++, getc(f))
                     84: #define        nungetc(c, f)           (--nread, ungetc((c), f))
                     85: #define        wgetc(c, f, out)        if(width--==0) goto out; (c)=ngetc(f)
                     86: #define        wungetc(c, f)           (++width, nungetc(c, f))
                     87: static int nread, ncvt;
                     88: static const char *fmtp;
                     89: 
                     90: int vfscanf(FILE *f, const char *s, va_list args){
                     91:        int c, width, type, store;
                     92: #ifdef sgi
                     93:        if (_us_rsthread_stdio) {
                     94:                __cnt = f->_cnt;
                     95:                f->_cnt = 0;
                     96:                }
                     97: #endif
                     98:        nread=0;
                     99:        ncvt=0;
                    100:        fmtp=s;
                    101:        for(;*fmtp;fmtp++) switch(*fmtp){
                    102:        default:
                    103:                if(isspace(*fmtp)){
                    104:                        do
                    105:                                c=ngetc(f);
                    106:                        while(isspace(c));
                    107:                        if(c==EOF) return ncvt?ncvt:EOF;
                    108:                        nungetc(c, f);
                    109:                        break;
                    110:                }
                    111:        NonSpecial:
                    112:                c=ngetc(f);
                    113:                if(c==EOF) return ncvt?ncvt:EOF;
                    114:                if(c!=*fmtp){
                    115:                        nungetc(c, f);
                    116:                        return ncvt;
                    117:                }
                    118:                break;
                    119:        case '%':
                    120:                fmtp++;
                    121:                if(*fmtp!='*') store=1;
                    122:                else{
                    123:                        store=0;
                    124:                        fmtp++;
                    125:                }
                    126:                if('0'<=*fmtp && *fmtp<='9'){
                    127:                        width=0;
                    128:                        while('0'<=*fmtp && *fmtp<='9') width=width*10 + *fmtp++ - '0';
                    129:                }
                    130:                else
                    131:                        width=-1;
                    132:                type=*fmtp=='h' || *fmtp=='l' || *fmtp=='L'?*fmtp++:'n';
                    133:                if(!icvt[*fmtp]) goto NonSpecial;
                    134:                if(!(*icvt[*fmtp])(f, &args, store, width, type))
                    135:                        return ncvt?ncvt:feof(f)?EOF:0;
                    136:                if(*fmtp=='\0') break;
                    137:                if(store) ncvt++;
                    138:        }
                    139:        return ncvt;
                    140: }
                    141: static int icvt_n(FILE *f, va_list *args, int store, int width, int type){
                    142: #pragma ref f
                    143: #pragma ref width
                    144:        if(store){
                    145:                --ncvt; /* this assignment doesn't count! */
                    146:                switch(type){
                    147:                case 'h': *va_arg(*args, short *)=nread; break;
                    148:                case 'n': *va_arg(*args, int *)=nread; break;
                    149:                case 'l':
                    150:                case 'L': *va_arg(*args, long *)=nread; break;
                    151:                }
                    152:        }
                    153:        return 1;
                    154: }
                    155: #define        SIGNED          1
                    156: #define        UNSIGNED        2
                    157: #define        POINTER         3
                    158: /*
                    159:  * Generic fixed-point conversion
                    160:  *     f is the input FILE *;
                    161:  *     args is the va_list * into which to store the number;
                    162:  *     store is a flag to enable storing;
                    163:  *     width is the maximum field width;
                    164:  *     type is 'h' 'l' or 'L', the scanf type modifier;
                    165:  *     unsgned is SIGNED, UNSIGNED or POINTER, giving part of the type to store in;
                    166:  *     base is the number base -- if 0, C number syntax is used.
                    167:  */
                    168: static int icvt_fixed(FILE *f, va_list *args,
                    169:                                int store, int width, int type, int unsgned, int base){
                    170:        unsigned long int num=0;
                    171:        int sign=1, ndig=0, dig;
                    172:        int c;
                    173:        do
                    174:                c=ngetc(f);
                    175:        while(isspace(c));
                    176:        if(width--==0){
                    177:                nungetc(c, f);
                    178:                goto Done;
                    179:        }
                    180:        if(c=='+'){
                    181:                wgetc(c, f, Done);
                    182:        }
                    183:        else if(c=='-'){
                    184:                sign=-1;
                    185:                wgetc(c, f, Done);
                    186:        }
                    187:        switch(base){
                    188:        case 0:
                    189:                if(c=='0'){
                    190:                        wgetc(c, f, Done);
                    191:                        if(c=='x' || c=='X'){
                    192:                                wgetc(c, f, Done);
                    193:                                base=16;
                    194:                        }
                    195:                        else{
                    196:                                ndig=1;
                    197:                                base=8;
                    198:                        }
                    199:                }
                    200:                else
                    201:                        base=10;
                    202:                break;
                    203:        case 16:
                    204:                if(c=='0'){
                    205:                        wgetc(c, f, Done);
                    206:                        if(c=='x' || c=='X'){
                    207:                                wgetc(c, f, Done);
                    208:                        }
                    209:                        else ndig=1;
                    210:                }
                    211:                break;
                    212:        }
                    213:        while('0'<=c && c<='9' || 'a'<=c && c<='f' || 'A'<=c && c<='F'){
                    214:                dig='0'<=c && c<='9'?c-'0':'a'<=c && c<='f'?c-'a'+10:c-'A'+10;
                    215:                if(dig>=base) break;
                    216:                ndig++;
                    217:                num=num*base+dig;
                    218:                wgetc(c, f, Done);
                    219:        }
                    220:        nungetc(c, f);
                    221: Done:
                    222:        if(ndig==0) return 0;
                    223:        if(store){
                    224:                switch(unsgned){
                    225:                case SIGNED:
                    226:                        switch(type){
                    227:                        case 'h': *va_arg(*args,  short *)=num*sign; break;
                    228:                        case 'n': *va_arg(*args,  int *)=num*sign; break;
                    229:                        case 'l':
                    230:                        case 'L': *va_arg(*args,  long *)=num*sign; break;
                    231:                        }
                    232:                        break;
                    233:                case UNSIGNED:
                    234:                        switch(type){
                    235:                        case 'h': *va_arg(*args, unsigned short *)=num*sign; break;
                    236:                        case 'n': *va_arg(*args, unsigned int *)=num*sign; break;
                    237:                        case 'l':
                    238:                        case 'L': *va_arg(*args, unsigned long *)=num*sign; break;
                    239:                        }
                    240:                        break;
                    241:                case POINTER:
                    242:                        *va_arg(*args, void **)=(void *)(num*sign); break;
                    243:                }
                    244:        }
                    245:        return 1;
                    246: }
                    247: static int icvt_d(FILE *f, va_list *args, int store, int width, int type){
                    248:        return icvt_fixed(f, args, store, width, type, SIGNED, 10);
                    249: }
                    250: static int icvt_x(FILE *f, va_list *args, int store, int width, int type){
                    251:        return icvt_fixed(f, args, store, width, type, UNSIGNED, 16);
                    252: }
                    253: static int icvt_o(FILE *f, va_list *args, int store, int width, int type){
                    254:        return icvt_fixed(f, args, store, width, type, UNSIGNED, 8);
                    255: }
                    256: static int icvt_i(FILE *f, va_list *args, int store, int width, int type){
                    257:        return icvt_fixed(f, args, store, width, type, SIGNED, 0);
                    258: }
                    259: static int icvt_u(FILE *f, va_list *args, int store, int width, int type){
                    260:        return icvt_fixed(f, args, store, width, type, UNSIGNED, 10);
                    261: }
                    262: static int icvt_p(FILE *f, va_list *args, int store, int width, int type){
                    263:        return icvt_fixed(f, args, store, width, type, POINTER, 16);
                    264: }
                    265: #define        NBUF    509
                    266: static int icvt_f(FILE *f, va_list *args, int store, int width, int type){
                    267:        char buf[NBUF+1];
                    268:        char *s=buf;
                    269:        int c, ndig=0, ndpt=0, nexp=1;
                    270:        if(width<0 || NBUF<width) width=NBUF;   /* bug -- no limit specified in ansi */
                    271:        do
                    272:                c=ngetc(f);
                    273:        while(isspace(c));
                    274:        if(width--==0){
                    275:                nungetc(c, f);
                    276:                goto Done;
                    277:        }
                    278:        if(c=='+' || c=='-'){
                    279:                *s++=c;
                    280:                wgetc(c, f, Done);
                    281:        }
                    282:        while('0'<=c && c<='9' || ndpt==0 && c=='.'){
                    283:                if(c=='.') ndpt++;
                    284:                else ndig++;
                    285:                *s++=c;
                    286:                wgetc(c, f, Done);
                    287:        }
                    288:        if(c=='e' || c=='E'){
                    289:                *s++=c;
                    290:                nexp=0;
                    291:                wgetc(c, f, Done);
                    292:                if(c=='+' || c=='-'){
                    293:                        *s++=c;
                    294:                        wgetc(c, f, Done);
                    295:                }
                    296:                while('0'<=c && c<='9'){
                    297:                        *s++=c;
                    298:                        nexp++;
                    299:                        wgetc(c, f, Done);
                    300:                }
                    301:        }
                    302:        nungetc(c, f);
                    303: Done:
                    304:        if(ndig==0 || nexp==0) return 0;
                    305:        *s='\0';
                    306:        if(store) switch(type){
                    307:        case 'h':
                    308:        case 'n': *va_arg(*args, float *)=atof(buf); break;
                    309:        case 'L': /* bug -- should store in a long double */
                    310:        case 'l': *va_arg(*args, double *)=atof(buf); break;
                    311:        }
                    312:        return 1;
                    313: }
                    314: static int icvt_s(FILE *f, va_list *args, int store, int width, int type){
                    315: #pragma ref type
                    316:        int c, nn;
                    317:        register char *s;
                    318:        if(store) s=va_arg(*args, char *);
                    319:        do
                    320:                c=ngetc(f);
                    321:        while(isspace(c));
                    322:        if(width--==0){
                    323:                nungetc(c, f);
                    324:                goto Done;
                    325:        }
                    326:        nn=0;
                    327:        while(!isspace(c)){
                    328:                if(c==EOF){
                    329:                        if(nn==0) return 0;
                    330:                        else goto Done;
                    331:                }
                    332:                nn++;
                    333:                if(store) *s++=c;
                    334:                wgetc(c, f, Done);
                    335:        }
                    336:        nungetc(c, f);
                    337: Done:
                    338:        if(store) *s='\0';
                    339:        return 1;
                    340: }
                    341: static int icvt_c(FILE *f, va_list *args, int store, int width, int type){
                    342: #pragma ref type
                    343:        int c;
                    344:        register char *s;
                    345:        if(store) s=va_arg(*args, char *);
                    346:        if(width<0) width=1;
                    347:        for(;;){
                    348:                wgetc(c, f, Done);
                    349:                if(c==EOF) return 0;
                    350:                if(store) *s++=c;
                    351:        }
                    352: Done:
                    353:        return 1;
                    354: }
                    355: static int match(int c, const char *pat){
                    356:        int ok=1;
                    357:        if(*pat=='^'){
                    358:                ok=!ok;
                    359:                pat++;
                    360:        }
                    361:        while(pat!=fmtp){
                    362:                if(pat+2<fmtp && pat[1]=='-'){
                    363:                        if(pat[0]<=c && c<=pat[2]
                    364:                        || pat[2]<=c && c<=pat[0])
                    365:                                return ok;
                    366:                        pat+=2;
                    367:                }
                    368:                else if(c==*pat) return ok;
                    369:                pat++;
                    370:        }
                    371:        return !ok;
                    372: }
                    373: static int icvt_sq(FILE *f, va_list *args, int store, int width, int type){
                    374: #pragma ref type
                    375:        int c, nn;
                    376:        register char *s;
                    377:        register const char *pat;
                    378:        pat=++fmtp;
                    379:        if(*fmtp=='^') fmtp++;
                    380:        if(*fmtp!='\0') fmtp++;
                    381:        while(*fmtp!='\0' && *fmtp!=']') fmtp++;
                    382:        if(store) s=va_arg(*args, char *);
                    383:        nn=0;
                    384:        for(;;){
                    385:                wgetc(c, f, Done);
                    386:                if(c==EOF){
                    387:                        if(nn==0) return 0;
                    388:                        else goto Done;
                    389:                }
                    390:                if(!match(c, pat)) break;
                    391:                if(store) *s++=c;
                    392:                nn++;
                    393:        }
                    394:        nungetc(c, f);
                    395: Done:
                    396:        if(store) *s='\0';
                    397:        return 1;
                    398: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.