xref: /plan9/sys/src/cmd/rc/getflags.c (revision 99eb86a7eded05d02373a1dc66f01c7d211105e0)
13e12c5d1SDavid du Colombier #include "rc.h"
23e12c5d1SDavid du Colombier #include "getflags.h"
33e12c5d1SDavid du Colombier #include "fns.h"
43e12c5d1SDavid du Colombier char *flagset[] = {"<flag>"};
53e12c5d1SDavid du Colombier char **flag[NFLAG];
63e12c5d1SDavid du Colombier char *cmdname;
73e12c5d1SDavid du Colombier static char *flagarg="";
87dd7cddfSDavid du Colombier static void reverse(char**, char**);
9d3907fe5SDavid du Colombier static int scanflag(int, char*);
107dd7cddfSDavid du Colombier static void errn(char*, int);
117dd7cddfSDavid du Colombier static void errs(char*);
127dd7cddfSDavid du Colombier static void errc(int);
13*99eb86a7SDavid du Colombier static int reason;
14*99eb86a7SDavid du Colombier #define	RESET	1
15*99eb86a7SDavid du Colombier #define	FEWARGS	2
16*99eb86a7SDavid du Colombier #define	FLAGSYN	3
17*99eb86a7SDavid du Colombier #define	BADFLAG	4
18*99eb86a7SDavid du Colombier static int badflag;
19dc5a79c1SDavid du Colombier 
20dc5a79c1SDavid du Colombier int
getflags(int argc,char * argv[],char * flags,int stop)21dc5a79c1SDavid du Colombier getflags(int argc, char *argv[], char *flags, int stop)
223e12c5d1SDavid du Colombier {
23276e7d6dSDavid du Colombier 	char *s;
243e12c5d1SDavid du Colombier 	int i, j, c, count;
253e12c5d1SDavid du Colombier 	flagarg = flags;
26dc5a79c1SDavid du Colombier 	if(cmdname==0)
27dc5a79c1SDavid du Colombier 		cmdname = argv[0];
28276e7d6dSDavid du Colombier 
293e12c5d1SDavid du Colombier 	i = 1;
303e12c5d1SDavid du Colombier 	while(i!=argc){
313e12c5d1SDavid du Colombier 		if(argv[i][0] != '-' || argv[i][1] == '\0'){
32276e7d6dSDavid du Colombier 			if(stop)		/* always true in rc */
33dc5a79c1SDavid du Colombier 				return argc;
343e12c5d1SDavid du Colombier 			i++;
353e12c5d1SDavid du Colombier 			continue;
363e12c5d1SDavid du Colombier 		}
373e12c5d1SDavid du Colombier 		s = argv[i]+1;
383e12c5d1SDavid du Colombier 		while(*s){
393e12c5d1SDavid du Colombier 			c=*s++;
403e12c5d1SDavid du Colombier 			count = scanflag(c, flags);
41dc5a79c1SDavid du Colombier 			if(count==-1)
42dc5a79c1SDavid du Colombier 				return -1;
43*99eb86a7SDavid du Colombier 			if(flag[c]){ reason = RESET; badflag = c; return -1; }
443e12c5d1SDavid du Colombier 			if(count==0){
453e12c5d1SDavid du Colombier 				flag[c] = flagset;
463e12c5d1SDavid du Colombier 				if(*s=='\0'){
473e12c5d1SDavid du Colombier 					for(j = i+1;j<=argc;j++)
483e12c5d1SDavid du Colombier 						argv[j-1] = argv[j];
493e12c5d1SDavid du Colombier 					--argc;
503e12c5d1SDavid du Colombier 				}
513e12c5d1SDavid du Colombier 			}
523e12c5d1SDavid du Colombier 			else{
533e12c5d1SDavid du Colombier 				if(*s=='\0'){
543e12c5d1SDavid du Colombier 					for(j = i+1;j<=argc;j++)
553e12c5d1SDavid du Colombier 						argv[j-1] = argv[j];
563e12c5d1SDavid du Colombier 					--argc;
573e12c5d1SDavid du Colombier 					s = argv[i];
583e12c5d1SDavid du Colombier 				}
593e12c5d1SDavid du Colombier 				if(argc-i<count){
603e12c5d1SDavid du Colombier 					reason = FEWARGS;
613e12c5d1SDavid du Colombier 					badflag = c;
623e12c5d1SDavid du Colombier 					return -1;
633e12c5d1SDavid du Colombier 				}
643e12c5d1SDavid du Colombier 				reverse(argv+i, argv+argc);
653e12c5d1SDavid du Colombier 				reverse(argv+i, argv+argc-count);
663e12c5d1SDavid du Colombier 				reverse(argv+argc-count+1, argv+argc);
673e12c5d1SDavid du Colombier 				argc-=count;
683e12c5d1SDavid du Colombier 				flag[c] = argv+argc+1;
693e12c5d1SDavid du Colombier 				flag[c][0] = s;
703e12c5d1SDavid du Colombier 				s="";
713e12c5d1SDavid du Colombier 			}
723e12c5d1SDavid du Colombier 		}
733e12c5d1SDavid du Colombier 	}
743e12c5d1SDavid du Colombier 	return argc;
753e12c5d1SDavid du Colombier }
76dc5a79c1SDavid du Colombier 
77dc5a79c1SDavid du Colombier static void
reverse(char ** p,char ** q)78dc5a79c1SDavid du Colombier reverse(char **p, char **q)
793e12c5d1SDavid du Colombier {
803e12c5d1SDavid du Colombier 	char *t;
81*99eb86a7SDavid du Colombier 	for(;p<q;p++,--q){ t=*p; *p=*q; *q = t; }
823e12c5d1SDavid du Colombier }
83dc5a79c1SDavid du Colombier 
84d3907fe5SDavid du Colombier static int
scanflag(int c,char * f)85dc5a79c1SDavid du Colombier scanflag(int c, char *f)
863e12c5d1SDavid du Colombier {
873e12c5d1SDavid du Colombier 	int fc, count;
88dc5a79c1SDavid du Colombier 	if(0<=c && c<NFLAG)
89dc5a79c1SDavid du Colombier 		while(*f){
903e12c5d1SDavid du Colombier 			if(*f==' '){
913e12c5d1SDavid du Colombier 				f++;
923e12c5d1SDavid du Colombier 				continue;
933e12c5d1SDavid du Colombier 			}
943e12c5d1SDavid du Colombier 			fc=*f++;
953e12c5d1SDavid du Colombier 			if(*f==':'){
963e12c5d1SDavid du Colombier 				f++;
97*99eb86a7SDavid du Colombier 				if(*f<'0' || '9'<*f){ reason = FLAGSYN; return -1; }
983e12c5d1SDavid du Colombier 				count = 0;
99*99eb86a7SDavid du Colombier 				while('0'<=*f && *f<='9') count = count*10+*f++-'0';
1003e12c5d1SDavid du Colombier 			}
1013e12c5d1SDavid du Colombier 			else
1023e12c5d1SDavid du Colombier 				count = 0;
1033e12c5d1SDavid du Colombier 			if(*f=='['){
1043e12c5d1SDavid du Colombier 				do{
1053e12c5d1SDavid du Colombier 					f++;
106*99eb86a7SDavid du Colombier 					if(*f=='\0'){ reason = FLAGSYN; return -1; }
1073e12c5d1SDavid du Colombier 				}while(*f!=']');
1083e12c5d1SDavid du Colombier 				f++;
1093e12c5d1SDavid du Colombier 			}
110dc5a79c1SDavid du Colombier 			if(c==fc)
111dc5a79c1SDavid du Colombier 				return count;
1123e12c5d1SDavid du Colombier 		}
1133e12c5d1SDavid du Colombier 	reason = BADFLAG;
1143e12c5d1SDavid du Colombier 	badflag = c;
1153e12c5d1SDavid du Colombier 	return -1;
1163e12c5d1SDavid du Colombier }
117dc5a79c1SDavid du Colombier 
118dc5a79c1SDavid du Colombier void
usage(char * tail)119dc5a79c1SDavid du Colombier usage(char *tail)
1203e12c5d1SDavid du Colombier {
1213e12c5d1SDavid du Colombier 	char *s, *t, c;
1223e12c5d1SDavid du Colombier 	int count, nflag = 0;
1233e12c5d1SDavid du Colombier 	switch(reason){
1243e12c5d1SDavid du Colombier 	case RESET:
1253e12c5d1SDavid du Colombier 		errs("Flag -");
1263e12c5d1SDavid du Colombier 		errc(badflag);
1273e12c5d1SDavid du Colombier 		errs(": set twice\n");
1283e12c5d1SDavid du Colombier 		break;
1293e12c5d1SDavid du Colombier 	case FEWARGS:
1303e12c5d1SDavid du Colombier 		errs("Flag -");
1313e12c5d1SDavid du Colombier 		errc(badflag);
1323e12c5d1SDavid du Colombier 		errs(": too few arguments\n");
1333e12c5d1SDavid du Colombier 		break;
1343e12c5d1SDavid du Colombier 	case FLAGSYN:
1353e12c5d1SDavid du Colombier 		errs("Bad argument to getflags!\n");
1363e12c5d1SDavid du Colombier 		break;
1373e12c5d1SDavid du Colombier 	case BADFLAG:
1383e12c5d1SDavid du Colombier 		errs("Illegal flag -");
1393e12c5d1SDavid du Colombier 		errc(badflag);
1403e12c5d1SDavid du Colombier 		errc('\n');
1413e12c5d1SDavid du Colombier 		break;
1423e12c5d1SDavid du Colombier 	}
1433e12c5d1SDavid du Colombier 	errs("Usage: ");
1443e12c5d1SDavid du Colombier 	errs(cmdname);
1453e12c5d1SDavid du Colombier 	for(s = flagarg;*s;){
1463e12c5d1SDavid du Colombier 		c=*s;
147dc5a79c1SDavid du Colombier 		if(*s++==' ')
148dc5a79c1SDavid du Colombier 			continue;
1493e12c5d1SDavid du Colombier 		if(*s==':'){
1503e12c5d1SDavid du Colombier 			s++;
1513e12c5d1SDavid du Colombier 			count = 0;
1523e12c5d1SDavid du Colombier 			while('0'<=*s && *s<='9') count = count*10+*s++-'0';
1533e12c5d1SDavid du Colombier 		}
1543e12c5d1SDavid du Colombier 		else count = 0;
1553e12c5d1SDavid du Colombier 		if(count==0){
156dc5a79c1SDavid du Colombier 			if(nflag==0)
157dc5a79c1SDavid du Colombier 				errs(" [-");
1583e12c5d1SDavid du Colombier 			nflag++;
1593e12c5d1SDavid du Colombier 			errc(c);
1603e12c5d1SDavid du Colombier 		}
1613e12c5d1SDavid du Colombier 		if(*s=='['){
1623e12c5d1SDavid du Colombier 			s++;
1633e12c5d1SDavid du Colombier 			while(*s!=']' && *s!='\0') s++;
164dc5a79c1SDavid du Colombier 			if(*s==']')
165dc5a79c1SDavid du Colombier 				s++;
1663e12c5d1SDavid du Colombier 		}
1673e12c5d1SDavid du Colombier 	}
168dc5a79c1SDavid du Colombier 	if(nflag)
169dc5a79c1SDavid du Colombier 		errs("]");
1703e12c5d1SDavid du Colombier 	for(s = flagarg;*s;){
1713e12c5d1SDavid du Colombier 		c=*s;
172dc5a79c1SDavid du Colombier 		if(*s++==' ')
173dc5a79c1SDavid du Colombier 			continue;
1743e12c5d1SDavid du Colombier 		if(*s==':'){
1753e12c5d1SDavid du Colombier 			s++;
1763e12c5d1SDavid du Colombier 			count = 0;
1773e12c5d1SDavid du Colombier 			while('0'<=*s && *s<='9') count = count*10+*s++-'0';
1783e12c5d1SDavid du Colombier 		}
1793e12c5d1SDavid du Colombier 		else count = 0;
1803e12c5d1SDavid du Colombier 		if(count!=0){
1813e12c5d1SDavid du Colombier 			errs(" [-");
1823e12c5d1SDavid du Colombier 			errc(c);
1833e12c5d1SDavid du Colombier 			if(*s=='['){
1843e12c5d1SDavid du Colombier 				s++;
1853e12c5d1SDavid du Colombier 				t = s;
1863e12c5d1SDavid du Colombier 				while(*s!=']' && *s!='\0') s++;
1873e12c5d1SDavid du Colombier 				errs(" ");
1883e12c5d1SDavid du Colombier 				errn(t, s-t);
189dc5a79c1SDavid du Colombier 				if(*s==']')
190dc5a79c1SDavid du Colombier 					s++;
1913e12c5d1SDavid du Colombier 			}
1923e12c5d1SDavid du Colombier 			else
1933e12c5d1SDavid du Colombier 				while(count--) errs(" arg");
1943e12c5d1SDavid du Colombier 			errs("]");
1953e12c5d1SDavid du Colombier 		}
1963e12c5d1SDavid du Colombier 		else if(*s=='['){
1973e12c5d1SDavid du Colombier 			s++;
1983e12c5d1SDavid du Colombier 			while(*s!=']' && *s!='\0') s++;
199dc5a79c1SDavid du Colombier 			if(*s==']')
200dc5a79c1SDavid du Colombier 				s++;
2013e12c5d1SDavid du Colombier 		}
2023e12c5d1SDavid du Colombier 	}
2033e12c5d1SDavid du Colombier 	if(tail){
2043e12c5d1SDavid du Colombier 		errs(" ");
2053e12c5d1SDavid du Colombier 		errs(tail);
2063e12c5d1SDavid du Colombier 	}
2073e12c5d1SDavid du Colombier 	errs("\n");
2083e12c5d1SDavid du Colombier 	Exit("bad flags");
2093e12c5d1SDavid du Colombier }
210dc5a79c1SDavid du Colombier 
211dc5a79c1SDavid du Colombier static void
errn(char * s,int count)212dc5a79c1SDavid du Colombier errn(char *s, int count)
2133e12c5d1SDavid du Colombier {
214*99eb86a7SDavid du Colombier 	while(count){ errc(*s++); --count; }
2153e12c5d1SDavid du Colombier }
216dc5a79c1SDavid du Colombier 
217dc5a79c1SDavid du Colombier static void
errs(char * s)218dc5a79c1SDavid du Colombier errs(char *s)
2193e12c5d1SDavid du Colombier {
220*99eb86a7SDavid du Colombier 	while(*s) errc(*s++);
2213e12c5d1SDavid du Colombier }
2223e12c5d1SDavid du Colombier #define	NBUF	80
2233e12c5d1SDavid du Colombier static char buf[NBUF], *bufp = buf;
224dc5a79c1SDavid du Colombier 
225dc5a79c1SDavid du Colombier static void
errc(int c)226dc5a79c1SDavid du Colombier errc(int c)
227dc5a79c1SDavid du Colombier {
2283e12c5d1SDavid du Colombier 	*bufp++=c;
2293e12c5d1SDavid du Colombier 	if(bufp==&buf[NBUF] || c=='\n'){
2303e12c5d1SDavid du Colombier 		Write(2, buf, bufp-buf);
2313e12c5d1SDavid du Colombier 		bufp = buf;
2323e12c5d1SDavid du Colombier 	}
2333e12c5d1SDavid du Colombier }
234