diff options
Diffstat (limited to 'sys/cmd/rc/getflags.c')
-rw-r--r-- | sys/cmd/rc/getflags.c | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/sys/cmd/rc/getflags.c b/sys/cmd/rc/getflags.c new file mode 100644 index 0000000..09f6e3a --- /dev/null +++ b/sys/cmd/rc/getflags.c @@ -0,0 +1,244 @@ +/*% 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; + } +} |