ref: 3b7e03a30ed29ee0666c00568bf67b8179c28d12
dir: /sys/src/cmd/rc/getflags.c/
#include "rc.h" #include "getflags.h" #include "fns.h" char *flagset[] = {"<flag>"}; char **flag[NFLAG]; char *cmdname; static char *flagarg=""; static void reverse(char**, char**); static int scanflag(int, char*); static void errn(char*, int); static void errs(char*); static void errc(int); static int reason; #define RESET 1 #define FEWARGS 2 #define FLAGSYN 3 #define BADFLAG 4 static int badflag; int getflags(int argc, char *argv[], char *flags, int stop) { char *s; int i, j, c, count; flagarg = flags; if(cmdname==0) cmdname = argv[0]; i = 1; while(i!=argc){ if(argv[i][0] != '-' || argv[i][1] == '\0'){ if(stop) /* always true in rc */ return argc; i++; continue; } s = argv[i]+1; while(*s){ c=*s++; count = scanflag(c, flags); if(count==-1) return -1; if(flag[c]){ reason = RESET; badflag = c; return -1; } if(count==0){ flag[c] = flagset; if(*s=='\0'){ for(j = i+1;j<=argc;j++) argv[j-1] = argv[j]; --argc; } } else{ if(*s=='\0'){ for(j = i+1;j<=argc;j++) argv[j-1] = argv[j]; --argc; s = argv[i]; } if(argc-i<count){ reason = FEWARGS; badflag = c; return -1; } reverse(argv+i, argv+argc); reverse(argv+i, argv+argc-count); reverse(argv+argc-count+1, argv+argc); argc-=count; flag[c] = argv+argc+1; flag[c][0] = s; s=""; } } } return argc; } static void reverse(char **p, char **q) { char *t; for(;p<q;p++,--q){ t=*p; *p=*q; *q = t; } } static int scanflag(int c, char *f) { int fc, count; if(0<=c && c<NFLAG) while(*f){ if(*f==' '){ f++; continue; } fc=*f++; if(*f==':'){ f++; if(*f<'0' || '9'<*f){ reason = FLAGSYN; return -1; } count = 0; while('0'<=*f && *f<='9') count = count*10+*f++-'0'; } else count = 0; if(*f=='['){ do{ f++; if(*f=='\0'){ reason = FLAGSYN; return -1; } }while(*f!=']'); f++; } if(c==fc) return count; } reason = BADFLAG; badflag = c; return -1; } void usage(char *tail) { char *s, *t, c; int count, nflag = 0; switch(reason){ case RESET: errs("Flag -"); errc(badflag); errs(": set twice\n"); break; case FEWARGS: errs("Flag -"); errc(badflag); errs(": too few arguments\n"); break; case FLAGSYN: errs("Bad argument to getflags!\n"); break; case BADFLAG: errs("Illegal flag -"); errc(badflag); errc('\n'); break; } errs("Usage: "); errs(cmdname); for(s = flagarg;*s;){ c=*s; if(*s++==' ') continue; if(*s==':'){ s++; count = 0; while('0'<=*s && *s<='9') count = count*10+*s++-'0'; } else count = 0; if(count==0){ if(nflag==0) errs(" [-"); nflag++; errc(c); } if(*s=='['){ s++; while(*s!=']' && *s!='\0') s++; if(*s==']') s++; } } if(nflag) errs("]"); for(s = flagarg;*s;){ c=*s; if(*s++==' ') continue; if(*s==':'){ s++; count = 0; while('0'<=*s && *s<='9') count = count*10+*s++-'0'; } else count = 0; if(count!=0){ errs(" [-"); errc(c); if(*s=='['){ s++; t = s; while(*s!=']' && *s!='\0') s++; errs(" "); errn(t, s-t); if(*s==']') s++; } else while(count--) errs(" arg"); errs("]"); } else if(*s=='['){ s++; while(*s!=']' && *s!='\0') s++; if(*s==']') s++; } } if(tail){ errs(" "); errs(tail); } errs("\n"); Exit("bad flags"); } static void errn(char *s, int count) { while(count){ errc(*s++); --count; } } static void errs(char *s) { while(*s) errc(*s++); } #define NBUF 80 static char buf[NBUF], *bufp = buf; static void errc(int c) { *bufp++=c; if(bufp==&buf[NBUF] || c=='\n'){ Write(2, buf, bufp-buf); bufp = buf; } }