Annotation of researchv10no/libc/stdio/vfscanf.c, revision 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.