/************************************************************* * File: lib/scanf.c * Purpose: Part of C runtime library * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970304 Start of revision history */ #include "stdarg.h" #include "stdio.h" #include /* ** fscanf --\ sscanf --\ ** | | ** scanf --+-- vfscanf ----- vsscanf ** ** This not been very well tested.. it probably has bugs */ #define ISSPACE " \t\n\r\f\v" #ifdef TEST main(argc,argv) int argc; char *argv[]; { char buf[40],s[30]; int a,b,n,i; char fmt[80]; strcpy(fmt,"%d %d"); for (i=1;i 1) strcat(fmt," "); else *fmt = 0; strcat(fmt,argv[i]); } printf("fmt=[%s]\n",fmt); for (;;) { printf("> "); a = b = 0; n = scanf(fmt,&a,&b); printf("n=%d ",n); if (n == 0) break; if (n >= 1) printf("a=%d[%x] ",a,a); if (n >= 2) printf("b=%d[%x] ",b,b); printf("\n"); } printf("\n"); } #endif /************************************************************* * scanf(fmt,va_alist) */ scanf(const char *fmt,...) { va_list ap; int count; va_start(ap,fmt); count = vfscanf(stdin,fmt,ap); va_end(ap); return(count); } /************************************************************* * sscanf(buf,fmt,va_alist) */ sscanf(char *buf,const char *fmt,...) { va_list ap; int count; if (!buf) return(0); /* defensive programming */ va_start(ap,fmt); count = vsscanf(buf,fmt,ap); va_end(ap); return(count); } /************************************************************* * vfscanf(fp,fmt,ap) */ vfscanf(fp,s,ap) FILE *fp; char *s; va_list ap; { int count,noassign,width,base,lflag,c,i; char *t,tmp[MAXLN]; count = noassign = width = lflag = 0; c = getc(fp); while (*s) { while (isspace(*s)) s++; if (*s == '%') { s++; for (;*s;s++) { if (strchr("dibouxcsefg%",*s)) break; if (*s == '*') noassign = 1; else if (*s == 'l' || *s == 'L') lflag = 1; else if (*s >= '1' && *s <= '9') { for (t=s;isdigit(*s);s++) ; strncpy(tmp,t,s-t); atob(&width,tmp,10); s--; } } if (*s == 's') { while (isspace(c)) c = getc(fp); for (i=0,t=va_arg(ap,char *);;i++) { if (!width && isspace(c)) break; if (width && i >= width) break; if (!noassign) *t++ = c; c = getc(fp); } if (!noassign) count++, *t = 0; } else if (*s == 'c') { if (!width) width = 1; for (i=0,t=va_arg(ap,char *);i= width) break; if (!width) { if (isspace(*(s+1)) || *(s+1) == 0) { if (isspace(c)) break; } else if (c == *(s+1)) break; } *t++ = c; c = getc(fp); } *t = 0; if (!noassign) { if (atob(va_arg(ap,int *),tmp,base)) count++; } } width = noassign = lflag = 0; s++; } else { while (isspace(c)) c = getc(fp); if (*s != c) break; else s++,c=getc(fp); } } ungetc(c,fp); return(count); } /************************************************************* * vsscanf(buf,fmt,ap) */ vsscanf(buf,s,ap) char *buf,*s; va_list ap; { int count,noassign,width,base,lflag; char *t,tmp[MAXLN]; count = noassign = width = lflag = 0; while (*s && *buf) { while (isspace(*s)) s++; if (*s == '%') { s++; for (;*s;s++) { if (strchr("dibouxcsefg%",*s)) break; if (*s == '*') noassign = 1; else if (*s == 'l' || *s == 'L') lflag = 1; else if (*s >= '1' && *s <= '9') { for (t=s;isdigit(*s);s++) ; strncpy(tmp,t,s-t); atob(&width,tmp,10); s--; } } if (*s == 's') { while (isspace(*buf)) buf++; if (!width) width = strcspn(buf,ISSPACE); if (!noassign) { strncpy(va_arg(ap,char *),buf,width); count++; } buf += width; } else if (*s == 'c') { if (!width) width = 1; if (!noassign) { strncpy(va_arg(ap,char *),buf,width); count++; } buf += width; } else if (strchr("dobxu",*s)) { while (isspace(*buf)) buf++; if (*s == 'd' || *s == 'u') base = 10; else if (*s == 'x') base = 16; else if (*s == 'o') base = 8; else if (*s == 'b') base = 2; if (!width) { if (isspace(*(s+1)) || *(s+1) == 0) width = strcspn(buf,ISSPACE); else width = strchr(buf,*(s+1))-buf; } strncpy(tmp,buf,width); buf += width; if (!noassign) { if (atob(va_arg(ap,int *),tmp,base)) count++; } } width = noassign = lflag = 0; s++; } else { while (isspace(*buf)) buf++; if (*s != *buf) break; else s++,buf++; } } return(count); }