|  | /*% cyntax -DTEST % && cc -DTEST -go # % | 
|  | */ | 
|  | #include "rc.h" | 
|  | #include "getflags.h" | 
|  | #include "fns.h" | 
|  | char *flagset[] = {"<flag>"}; | 
|  | char **flag[NFLAG]; | 
|  | char cmdline[NCMDLINE+1]; | 
|  | 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, *t; | 
|  | int i, j, c, count; | 
|  | flagarg = flags; | 
|  | if(cmdname==0) | 
|  | cmdname = argv[0]; | 
|  | s = cmdline; | 
|  | for(i = 0;i!=argc;i++){ | 
|  | for(t = argv[i];*t;t++) | 
|  | if(s!=&cmdline[NCMDLINE]) | 
|  | *s++=*t; | 
|  | if(i!=argc-1 && s!=&cmdline[NCMDLINE]) | 
|  | *s++=' '; | 
|  | } | 
|  | *s='\0'; | 
|  | i = 1; | 
|  | while(i!=argc){ | 
|  | if(argv[i][0]!='-' || argv[i][1]=='\0'){ | 
|  | if(stop) | 
|  | 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; | 
|  | } | 
|  | } |