13e12c5d1SDavid du Colombier /*% cyntax -DTEST % && cc -DTEST -go # % 23e12c5d1SDavid du Colombier */ 33e12c5d1SDavid du Colombier #include "rc.h" 43e12c5d1SDavid du Colombier #include "getflags.h" 53e12c5d1SDavid du Colombier #include "fns.h" 63e12c5d1SDavid du Colombier char *flagset[] = {"<flag>"}; 73e12c5d1SDavid du Colombier char **flag[NFLAG]; 83e12c5d1SDavid du Colombier char cmdline[NCMDLINE+1]; 93e12c5d1SDavid du Colombier char *cmdname; 103e12c5d1SDavid du Colombier static char *flagarg=""; 117dd7cddfSDavid du Colombier static void reverse(char**, char**); 12*d3907fe5SDavid du Colombier static int scanflag(int, char*); 137dd7cddfSDavid du Colombier static void errn(char*, int); 147dd7cddfSDavid du Colombier static void errs(char*); 157dd7cddfSDavid du Colombier static void errc(int); 163e12c5d1SDavid du Colombier static int reason; 173e12c5d1SDavid du Colombier #define RESET 1 183e12c5d1SDavid du Colombier #define FEWARGS 2 193e12c5d1SDavid du Colombier #define FLAGSYN 3 203e12c5d1SDavid du Colombier #define BADFLAG 4 213e12c5d1SDavid du Colombier static int badflag; 22dc5a79c1SDavid du Colombier 23dc5a79c1SDavid du Colombier int 24dc5a79c1SDavid du Colombier getflags(int argc, char *argv[], char *flags, int stop) 253e12c5d1SDavid du Colombier { 263e12c5d1SDavid du Colombier char *s, *t; 273e12c5d1SDavid du Colombier int i, j, c, count; 283e12c5d1SDavid du Colombier flagarg = flags; 29dc5a79c1SDavid du Colombier if(cmdname==0) 30dc5a79c1SDavid du Colombier cmdname = argv[0]; 313e12c5d1SDavid du Colombier s = cmdline; 323e12c5d1SDavid du Colombier for(i = 0;i!=argc;i++){ 333e12c5d1SDavid du Colombier for(t = argv[i];*t;t++) 343e12c5d1SDavid du Colombier if(s!=&cmdline[NCMDLINE]) 353e12c5d1SDavid du Colombier *s++=*t; 363e12c5d1SDavid du Colombier if(i!=argc-1 && s!=&cmdline[NCMDLINE]) 373e12c5d1SDavid du Colombier *s++=' '; 383e12c5d1SDavid du Colombier } 393e12c5d1SDavid du Colombier *s='\0'; 403e12c5d1SDavid du Colombier i = 1; 413e12c5d1SDavid du Colombier while(i!=argc){ 423e12c5d1SDavid du Colombier if(argv[i][0]!='-' || argv[i][1]=='\0'){ 43dc5a79c1SDavid du Colombier if(stop) 44dc5a79c1SDavid du Colombier return argc; 453e12c5d1SDavid du Colombier i++; 463e12c5d1SDavid du Colombier continue; 473e12c5d1SDavid du Colombier } 483e12c5d1SDavid du Colombier s = argv[i]+1; 493e12c5d1SDavid du Colombier while(*s){ 503e12c5d1SDavid du Colombier c=*s++; 513e12c5d1SDavid du Colombier count = scanflag(c, flags); 52dc5a79c1SDavid du Colombier if(count==-1) 53dc5a79c1SDavid du Colombier return -1; 543e12c5d1SDavid du Colombier if(flag[c]){ reason = RESET; badflag = c; return -1; } 553e12c5d1SDavid du Colombier if(count==0){ 563e12c5d1SDavid du Colombier flag[c] = flagset; 573e12c5d1SDavid du Colombier if(*s=='\0'){ 583e12c5d1SDavid du Colombier for(j = i+1;j<=argc;j++) 593e12c5d1SDavid du Colombier argv[j-1] = argv[j]; 603e12c5d1SDavid du Colombier --argc; 613e12c5d1SDavid du Colombier } 623e12c5d1SDavid du Colombier } 633e12c5d1SDavid du Colombier else{ 643e12c5d1SDavid du Colombier if(*s=='\0'){ 653e12c5d1SDavid du Colombier for(j = i+1;j<=argc;j++) 663e12c5d1SDavid du Colombier argv[j-1] = argv[j]; 673e12c5d1SDavid du Colombier --argc; 683e12c5d1SDavid du Colombier s = argv[i]; 693e12c5d1SDavid du Colombier } 703e12c5d1SDavid du Colombier if(argc-i<count){ 713e12c5d1SDavid du Colombier reason = FEWARGS; 723e12c5d1SDavid du Colombier badflag = c; 733e12c5d1SDavid du Colombier return -1; 743e12c5d1SDavid du Colombier } 753e12c5d1SDavid du Colombier reverse(argv+i, argv+argc); 763e12c5d1SDavid du Colombier reverse(argv+i, argv+argc-count); 773e12c5d1SDavid du Colombier reverse(argv+argc-count+1, argv+argc); 783e12c5d1SDavid du Colombier argc-=count; 793e12c5d1SDavid du Colombier flag[c] = argv+argc+1; 803e12c5d1SDavid du Colombier flag[c][0] = s; 813e12c5d1SDavid du Colombier s=""; 823e12c5d1SDavid du Colombier } 833e12c5d1SDavid du Colombier } 843e12c5d1SDavid du Colombier } 853e12c5d1SDavid du Colombier return argc; 863e12c5d1SDavid du Colombier } 87dc5a79c1SDavid du Colombier 88dc5a79c1SDavid du Colombier static void 89dc5a79c1SDavid du Colombier reverse(char **p, char **q) 903e12c5d1SDavid du Colombier { 913e12c5d1SDavid du Colombier char *t; 923e12c5d1SDavid du Colombier for(;p<q;p++,--q){ t=*p; *p=*q; *q = t; } 933e12c5d1SDavid du Colombier } 94dc5a79c1SDavid du Colombier 95*d3907fe5SDavid du Colombier static int 96dc5a79c1SDavid du Colombier scanflag(int c, char *f) 973e12c5d1SDavid du Colombier { 983e12c5d1SDavid du Colombier int fc, count; 99dc5a79c1SDavid du Colombier if(0<=c && c<NFLAG) 100dc5a79c1SDavid du Colombier while(*f){ 1013e12c5d1SDavid du Colombier if(*f==' '){ 1023e12c5d1SDavid du Colombier f++; 1033e12c5d1SDavid du Colombier continue; 1043e12c5d1SDavid du Colombier } 1053e12c5d1SDavid du Colombier fc=*f++; 1063e12c5d1SDavid du Colombier if(*f==':'){ 1073e12c5d1SDavid du Colombier f++; 1083e12c5d1SDavid du Colombier if(*f<'0' || '9'<*f){ reason = FLAGSYN; return -1; } 1093e12c5d1SDavid du Colombier count = 0; 1103e12c5d1SDavid du Colombier while('0'<=*f && *f<='9') count = count*10+*f++-'0'; 1113e12c5d1SDavid du Colombier } 1123e12c5d1SDavid du Colombier else 1133e12c5d1SDavid du Colombier count = 0; 1143e12c5d1SDavid du Colombier if(*f=='['){ 1153e12c5d1SDavid du Colombier do{ 1163e12c5d1SDavid du Colombier f++; 1173e12c5d1SDavid du Colombier if(*f=='\0'){ reason = FLAGSYN; return -1; } 1183e12c5d1SDavid du Colombier }while(*f!=']'); 1193e12c5d1SDavid du Colombier f++; 1203e12c5d1SDavid du Colombier } 121dc5a79c1SDavid du Colombier if(c==fc) 122dc5a79c1SDavid du Colombier return count; 1233e12c5d1SDavid du Colombier } 1243e12c5d1SDavid du Colombier reason = BADFLAG; 1253e12c5d1SDavid du Colombier badflag = c; 1263e12c5d1SDavid du Colombier return -1; 1273e12c5d1SDavid du Colombier } 128dc5a79c1SDavid du Colombier 129dc5a79c1SDavid du Colombier void 130dc5a79c1SDavid du Colombier usage(char *tail) 1313e12c5d1SDavid du Colombier { 1323e12c5d1SDavid du Colombier char *s, *t, c; 1333e12c5d1SDavid du Colombier int count, nflag = 0; 1343e12c5d1SDavid du Colombier switch(reason){ 1353e12c5d1SDavid du Colombier case RESET: 1363e12c5d1SDavid du Colombier errs("Flag -"); 1373e12c5d1SDavid du Colombier errc(badflag); 1383e12c5d1SDavid du Colombier errs(": set twice\n"); 1393e12c5d1SDavid du Colombier break; 1403e12c5d1SDavid du Colombier case FEWARGS: 1413e12c5d1SDavid du Colombier errs("Flag -"); 1423e12c5d1SDavid du Colombier errc(badflag); 1433e12c5d1SDavid du Colombier errs(": too few arguments\n"); 1443e12c5d1SDavid du Colombier break; 1453e12c5d1SDavid du Colombier case FLAGSYN: 1463e12c5d1SDavid du Colombier errs("Bad argument to getflags!\n"); 1473e12c5d1SDavid du Colombier break; 1483e12c5d1SDavid du Colombier case BADFLAG: 1493e12c5d1SDavid du Colombier errs("Illegal flag -"); 1503e12c5d1SDavid du Colombier errc(badflag); 1513e12c5d1SDavid du Colombier errc('\n'); 1523e12c5d1SDavid du Colombier break; 1533e12c5d1SDavid du Colombier } 1543e12c5d1SDavid du Colombier errs("Usage: "); 1553e12c5d1SDavid du Colombier errs(cmdname); 1563e12c5d1SDavid du Colombier for(s = flagarg;*s;){ 1573e12c5d1SDavid du Colombier c=*s; 158dc5a79c1SDavid du Colombier if(*s++==' ') 159dc5a79c1SDavid du Colombier continue; 1603e12c5d1SDavid du Colombier if(*s==':'){ 1613e12c5d1SDavid du Colombier s++; 1623e12c5d1SDavid du Colombier count = 0; 1633e12c5d1SDavid du Colombier while('0'<=*s && *s<='9') count = count*10+*s++-'0'; 1643e12c5d1SDavid du Colombier } 1653e12c5d1SDavid du Colombier else count = 0; 1663e12c5d1SDavid du Colombier if(count==0){ 167dc5a79c1SDavid du Colombier if(nflag==0) 168dc5a79c1SDavid du Colombier errs(" [-"); 1693e12c5d1SDavid du Colombier nflag++; 1703e12c5d1SDavid du Colombier errc(c); 1713e12c5d1SDavid du Colombier } 1723e12c5d1SDavid du Colombier if(*s=='['){ 1733e12c5d1SDavid du Colombier s++; 1743e12c5d1SDavid du Colombier while(*s!=']' && *s!='\0') s++; 175dc5a79c1SDavid du Colombier if(*s==']') 176dc5a79c1SDavid du Colombier s++; 1773e12c5d1SDavid du Colombier } 1783e12c5d1SDavid du Colombier } 179dc5a79c1SDavid du Colombier if(nflag) 180dc5a79c1SDavid du Colombier errs("]"); 1813e12c5d1SDavid du Colombier for(s = flagarg;*s;){ 1823e12c5d1SDavid du Colombier c=*s; 183dc5a79c1SDavid du Colombier if(*s++==' ') 184dc5a79c1SDavid du Colombier continue; 1853e12c5d1SDavid du Colombier if(*s==':'){ 1863e12c5d1SDavid du Colombier s++; 1873e12c5d1SDavid du Colombier count = 0; 1883e12c5d1SDavid du Colombier while('0'<=*s && *s<='9') count = count*10+*s++-'0'; 1893e12c5d1SDavid du Colombier } 1903e12c5d1SDavid du Colombier else count = 0; 1913e12c5d1SDavid du Colombier if(count!=0){ 1923e12c5d1SDavid du Colombier errs(" [-"); 1933e12c5d1SDavid du Colombier errc(c); 1943e12c5d1SDavid du Colombier if(*s=='['){ 1953e12c5d1SDavid du Colombier s++; 1963e12c5d1SDavid du Colombier t = s; 1973e12c5d1SDavid du Colombier while(*s!=']' && *s!='\0') s++; 1983e12c5d1SDavid du Colombier errs(" "); 1993e12c5d1SDavid du Colombier errn(t, s-t); 200dc5a79c1SDavid du Colombier if(*s==']') 201dc5a79c1SDavid du Colombier s++; 2023e12c5d1SDavid du Colombier } 2033e12c5d1SDavid du Colombier else 2043e12c5d1SDavid du Colombier while(count--) errs(" arg"); 2053e12c5d1SDavid du Colombier errs("]"); 2063e12c5d1SDavid du Colombier } 2073e12c5d1SDavid du Colombier else if(*s=='['){ 2083e12c5d1SDavid du Colombier s++; 2093e12c5d1SDavid du Colombier while(*s!=']' && *s!='\0') s++; 210dc5a79c1SDavid du Colombier if(*s==']') 211dc5a79c1SDavid du Colombier s++; 2123e12c5d1SDavid du Colombier } 2133e12c5d1SDavid du Colombier } 2143e12c5d1SDavid du Colombier if(tail){ 2153e12c5d1SDavid du Colombier errs(" "); 2163e12c5d1SDavid du Colombier errs(tail); 2173e12c5d1SDavid du Colombier } 2183e12c5d1SDavid du Colombier errs("\n"); 2193e12c5d1SDavid du Colombier Exit("bad flags"); 2203e12c5d1SDavid du Colombier } 221dc5a79c1SDavid du Colombier 222dc5a79c1SDavid du Colombier static void 223dc5a79c1SDavid du Colombier errn(char *s, int count) 2243e12c5d1SDavid du Colombier { 2253e12c5d1SDavid du Colombier while(count){ errc(*s++); --count; } 2263e12c5d1SDavid du Colombier } 227dc5a79c1SDavid du Colombier 228dc5a79c1SDavid du Colombier static void 229dc5a79c1SDavid du Colombier errs(char *s) 2303e12c5d1SDavid du Colombier { 2313e12c5d1SDavid du Colombier while(*s) errc(*s++); 2323e12c5d1SDavid du Colombier } 2333e12c5d1SDavid du Colombier #define NBUF 80 2343e12c5d1SDavid du Colombier static char buf[NBUF], *bufp = buf; 235dc5a79c1SDavid du Colombier 236dc5a79c1SDavid du Colombier static void 237dc5a79c1SDavid du Colombier errc(int c) 238dc5a79c1SDavid du Colombier { 2393e12c5d1SDavid du Colombier *bufp++=c; 2403e12c5d1SDavid du Colombier if(bufp==&buf[NBUF] || c=='\n'){ 2413e12c5d1SDavid du Colombier Write(2, buf, bufp-buf); 2423e12c5d1SDavid du Colombier bufp = buf; 2433e12c5d1SDavid du Colombier } 2443e12c5d1SDavid du Colombier } 245