#define NOCCARGC /* ** Yes, it's right. These function do not call ones which need arg counts. */ #include stdio.h /* ** fscanf(fd, ctlstring, arg, arg, ....) - Formatted read. ** Operates as described by Kernighan and Ritchie. ** b, c, d, o, s, u, and x specifications are supported. ** Note: b (binary) is a non-standard extension. */ fscanf(argc) int argc; { int *nxtarg; nxtarg = CCARGC() + &argc; return (_scan(*(--nxtarg), --nxtarg)); } /* ** scanf(ctlstring, arg, arg, ....) - Formatted read. ** Operates as described by Kernighan and Ritchie. ** b, c, d, o, s, u, and x specifications are supported. ** Note: b (binary) is a non-standard extension. */ scanf(argc) int argc; { return (_scan(stdin, CCARGC() + &argc -1)); } /* ** _scan(fd, ctlstring, arg, arg, ....) - Formatted read. ** Called by fscanf() and scanf()l */ _scan(fd,nxtarg) int fd, *nxtarg; { char *carg, *ctl, *unsigned; int *narg, wast, ac, width, ch, cnv, base, ovfl, sign; ac = 0; ctl = *nxtarg--; while(*ctl) { if(isspace(*ctl)) {++ctl; continue;} if(*ctl++ != '%') continue; if(*ctl == '*') {narg = carg = &wast; ++ctl;} else narg = carg = *nxtarg--; ctl += utoi(ctl, &width); if(!width) width = 32767; if(!(cnv = *ctl++)) break; while(isspace(ch = fgetc(fd))); if(ch == EOF) {if(ac) break; else return (EOF);} ungetc(ch,fd); switch(cnv) { case 'c': *carg = fgetc(fd); break; case 's': while(width--) { if((*carg = fgetc(fd)) == EOF) break; if(isspace(*carg)) break; if(carg != &wast) ++carg; } *carg = 0; break; default: switch(cnv) { case 'b': base = 2; sign = 1; ovfl = 32767; break; case 'd': base = 10; sign = 0; ovfl = 3276; break; case 'o': base = 8; sign = 1; ovfl = 8191; break; case 'u': base = 10; sign = 1; ovfl = 6553; break; case 'x': base = 16; sign = 1; ovfl = 4095; break; default: return (ac); } *narg = unsigned = 0; while(width-- && !isspace(ch=fgetc(fd)) && ch!=EOF) { if(!sign) if(ch == '-') {sign = -1; continue;} else sign = 1; if(ch < '0') return (ac); if(ch > 'a') ch -= 87; else if(ch >= 'A') ch -= 55; else ch -= '0'; if(ch >= base || unsigned > ovfl) return (ac); unsigned = unsigned * base + ch; } *narg = sign * unsigned; } ++ac; } return (ac); }