xref: /plan9/sys/src/cmd/rc/getflags.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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="";
11*7dd7cddfSDavid du Colombier static void reverse(char**, char**);
123e12c5d1SDavid du Colombier static scanflag(int, char*);
13*7dd7cddfSDavid du Colombier static void errn(char*, int);
14*7dd7cddfSDavid du Colombier static void errs(char*);
15*7dd7cddfSDavid 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;
223e12c5d1SDavid du Colombier int getflags(int argc, char *argv[], char *flags, int stop)
233e12c5d1SDavid du Colombier {
243e12c5d1SDavid du Colombier 	char *s, *t;
253e12c5d1SDavid du Colombier 	int i, j, c, count;
263e12c5d1SDavid du Colombier 	flagarg=flags;
273e12c5d1SDavid du Colombier 	if(cmdname==0) cmdname=argv[0];
283e12c5d1SDavid du Colombier 	s=cmdline;
293e12c5d1SDavid du Colombier 	for(i=0;i!=argc;i++){
303e12c5d1SDavid du Colombier 		for(t=argv[i];*t;t++)
313e12c5d1SDavid du Colombier 			if(s!=&cmdline[NCMDLINE])
323e12c5d1SDavid du Colombier 				*s++=*t;
333e12c5d1SDavid du Colombier 		if(i!=argc-1 && s!=&cmdline[NCMDLINE])
343e12c5d1SDavid du Colombier 			*s++=' ';
353e12c5d1SDavid du Colombier 	}
363e12c5d1SDavid du Colombier 	*s='\0';
373e12c5d1SDavid du Colombier 	i=1;
383e12c5d1SDavid du Colombier 	while(i!=argc){
393e12c5d1SDavid du Colombier 		if(argv[i][0]!='-' || argv[i][1]=='\0'){
403e12c5d1SDavid du Colombier 			if(stop) return argc;
413e12c5d1SDavid du Colombier 			i++;
423e12c5d1SDavid du Colombier 			continue;
433e12c5d1SDavid du Colombier 		}
443e12c5d1SDavid du Colombier 		s=argv[i]+1;
453e12c5d1SDavid du Colombier 		while(*s){
463e12c5d1SDavid du Colombier 			c=*s++;
473e12c5d1SDavid du Colombier 			count=scanflag(c, flags);
483e12c5d1SDavid du Colombier 			if(count==-1) return -1;
493e12c5d1SDavid du Colombier 			if(flag[c]){ reason=RESET; badflag=c; return -1; }
503e12c5d1SDavid du Colombier 			if(count==0){
513e12c5d1SDavid du Colombier 				flag[c]=flagset;
523e12c5d1SDavid du Colombier 				if(*s=='\0'){
533e12c5d1SDavid du Colombier 					for(j=i+1;j<=argc;j++)
543e12c5d1SDavid du Colombier 						argv[j-1]=argv[j];
553e12c5d1SDavid du Colombier 					--argc;
563e12c5d1SDavid du Colombier 				}
573e12c5d1SDavid du Colombier 			}
583e12c5d1SDavid du Colombier 			else{
593e12c5d1SDavid du Colombier 				if(*s=='\0'){
603e12c5d1SDavid du Colombier 					for(j=i+1;j<=argc;j++)
613e12c5d1SDavid du Colombier 						argv[j-1]=argv[j];
623e12c5d1SDavid du Colombier 					--argc;
633e12c5d1SDavid du Colombier 					s=argv[i];
643e12c5d1SDavid du Colombier 				}
653e12c5d1SDavid du Colombier 				if(argc-i<count){
663e12c5d1SDavid du Colombier 					reason=FEWARGS;
673e12c5d1SDavid du Colombier 					badflag=c;
683e12c5d1SDavid du Colombier 					return -1;
693e12c5d1SDavid du Colombier 				}
703e12c5d1SDavid du Colombier 				reverse(argv+i, argv+argc);
713e12c5d1SDavid du Colombier 				reverse(argv+i, argv+argc-count);
723e12c5d1SDavid du Colombier 				reverse(argv+argc-count+1, argv+argc);
733e12c5d1SDavid du Colombier 				argc-=count;
743e12c5d1SDavid du Colombier 				flag[c]=argv+argc+1;
753e12c5d1SDavid du Colombier 				flag[c][0]=s;
763e12c5d1SDavid du Colombier 				s="";
773e12c5d1SDavid du Colombier 			}
783e12c5d1SDavid du Colombier 		}
793e12c5d1SDavid du Colombier 	}
803e12c5d1SDavid du Colombier 	return argc;
813e12c5d1SDavid du Colombier }
82*7dd7cddfSDavid du Colombier static void reverse(char **p, char **q)
833e12c5d1SDavid du Colombier {
843e12c5d1SDavid du Colombier 	char *t;
853e12c5d1SDavid du Colombier 	for(;p<q;p++,--q){ t=*p; *p=*q; *q=t; }
863e12c5d1SDavid du Colombier }
873e12c5d1SDavid du Colombier static scanflag(int c, char *f)
883e12c5d1SDavid du Colombier {
893e12c5d1SDavid du Colombier 	int fc, count;
903e12c5d1SDavid du Colombier 	if(0<=c && c<NFLAG) while(*f){
913e12c5d1SDavid du Colombier 		if(*f==' '){
923e12c5d1SDavid du Colombier 			f++;
933e12c5d1SDavid du Colombier 			continue;
943e12c5d1SDavid du Colombier 		}
953e12c5d1SDavid du Colombier 		fc=*f++;
963e12c5d1SDavid du Colombier 		if(*f==':'){
973e12c5d1SDavid du Colombier 			f++;
983e12c5d1SDavid du Colombier 			if(*f<'0' || '9'<*f){ reason=FLAGSYN; return -1; }
993e12c5d1SDavid du Colombier 			count=0;
1003e12c5d1SDavid du Colombier 			while('0'<=*f && *f<='9') count=count*10+*f++-'0';
1013e12c5d1SDavid du Colombier 		}
1023e12c5d1SDavid du Colombier 		else
1033e12c5d1SDavid du Colombier 			count=0;
1043e12c5d1SDavid du Colombier 		if(*f=='['){
1053e12c5d1SDavid du Colombier 			do{
1063e12c5d1SDavid du Colombier 				f++;
1073e12c5d1SDavid du Colombier 				if(*f=='\0'){ reason=FLAGSYN; return -1; }
1083e12c5d1SDavid du Colombier 			}while(*f!=']');
1093e12c5d1SDavid du Colombier 			f++;
1103e12c5d1SDavid du Colombier 		}
1113e12c5d1SDavid du Colombier 		if(c==fc) return count;
1123e12c5d1SDavid du Colombier 	}
1133e12c5d1SDavid du Colombier 	reason=BADFLAG;
1143e12c5d1SDavid du Colombier 	badflag=c;
1153e12c5d1SDavid du Colombier 	return -1;
1163e12c5d1SDavid du Colombier }
1173e12c5d1SDavid du Colombier void usage(char *tail)
1183e12c5d1SDavid du Colombier {
1193e12c5d1SDavid du Colombier 	char *s, *t, c;
1203e12c5d1SDavid du Colombier 	int count, nflag=0;
1213e12c5d1SDavid du Colombier 	switch(reason){
1223e12c5d1SDavid du Colombier 	case RESET:
1233e12c5d1SDavid du Colombier 		errs("Flag -");
1243e12c5d1SDavid du Colombier 		errc(badflag);
1253e12c5d1SDavid du Colombier 		errs(": set twice\n");
1263e12c5d1SDavid du Colombier 		break;
1273e12c5d1SDavid du Colombier 	case FEWARGS:
1283e12c5d1SDavid du Colombier 		errs("Flag -");
1293e12c5d1SDavid du Colombier 		errc(badflag);
1303e12c5d1SDavid du Colombier 		errs(": too few arguments\n");
1313e12c5d1SDavid du Colombier 		break;
1323e12c5d1SDavid du Colombier 	case FLAGSYN:
1333e12c5d1SDavid du Colombier 		errs("Bad argument to getflags!\n");
1343e12c5d1SDavid du Colombier 		break;
1353e12c5d1SDavid du Colombier 	case BADFLAG:
1363e12c5d1SDavid du Colombier 		errs("Illegal flag -");
1373e12c5d1SDavid du Colombier 		errc(badflag);
1383e12c5d1SDavid du Colombier 		errc('\n');
1393e12c5d1SDavid du Colombier 		break;
1403e12c5d1SDavid du Colombier 	}
1413e12c5d1SDavid du Colombier 	errs("Usage: ");
1423e12c5d1SDavid du Colombier 	errs(cmdname);
1433e12c5d1SDavid du Colombier 	for(s=flagarg;*s;){
1443e12c5d1SDavid du Colombier 		c=*s;
1453e12c5d1SDavid du Colombier 		if(*s++==' ') continue;
1463e12c5d1SDavid du Colombier 		if(*s==':'){
1473e12c5d1SDavid du Colombier 			s++;
1483e12c5d1SDavid du Colombier 			count=0;
1493e12c5d1SDavid du Colombier 			while('0'<=*s && *s<='9') count=count*10+*s++-'0';
1503e12c5d1SDavid du Colombier 		}
1513e12c5d1SDavid du Colombier 		else count=0;
1523e12c5d1SDavid du Colombier 		if(count==0){
1533e12c5d1SDavid du Colombier 			if(nflag==0) errs(" [-");
1543e12c5d1SDavid du Colombier 			nflag++;
1553e12c5d1SDavid du Colombier 			errc(c);
1563e12c5d1SDavid du Colombier 		}
1573e12c5d1SDavid du Colombier 		if(*s=='['){
1583e12c5d1SDavid du Colombier 			s++;
1593e12c5d1SDavid du Colombier 			while(*s!=']' && *s!='\0') s++;
1603e12c5d1SDavid du Colombier 			if(*s==']') s++;
1613e12c5d1SDavid du Colombier 		}
1623e12c5d1SDavid du Colombier 	}
1633e12c5d1SDavid du Colombier 	if(nflag) errs("]");
1643e12c5d1SDavid du Colombier 	for(s=flagarg;*s;){
1653e12c5d1SDavid du Colombier 		c=*s;
1663e12c5d1SDavid du Colombier 		if(*s++==' ') continue;
1673e12c5d1SDavid du Colombier 		if(*s==':'){
1683e12c5d1SDavid du Colombier 			s++;
1693e12c5d1SDavid du Colombier 			count=0;
1703e12c5d1SDavid du Colombier 			while('0'<=*s && *s<='9') count=count*10+*s++-'0';
1713e12c5d1SDavid du Colombier 		}
1723e12c5d1SDavid du Colombier 		else count=0;
1733e12c5d1SDavid du Colombier 		if(count!=0){
1743e12c5d1SDavid du Colombier 			errs(" [-");
1753e12c5d1SDavid du Colombier 			errc(c);
1763e12c5d1SDavid du Colombier 			if(*s=='['){
1773e12c5d1SDavid du Colombier 				s++;
1783e12c5d1SDavid du Colombier 				t=s;
1793e12c5d1SDavid du Colombier 				while(*s!=']' && *s!='\0') s++;
1803e12c5d1SDavid du Colombier 				errs(" ");
1813e12c5d1SDavid du Colombier 				errn(t, s-t);
1823e12c5d1SDavid du Colombier 				if(*s==']') s++;
1833e12c5d1SDavid du Colombier 			}
1843e12c5d1SDavid du Colombier 			else
1853e12c5d1SDavid du Colombier 				while(count--) errs(" arg");
1863e12c5d1SDavid du Colombier 			errs("]");
1873e12c5d1SDavid du Colombier 		}
1883e12c5d1SDavid du Colombier 		else if(*s=='['){
1893e12c5d1SDavid du Colombier 			s++;
1903e12c5d1SDavid du Colombier 			while(*s!=']' && *s!='\0') s++;
1913e12c5d1SDavid du Colombier 			if(*s==']') s++;
1923e12c5d1SDavid du Colombier 		}
1933e12c5d1SDavid du Colombier 	}
1943e12c5d1SDavid du Colombier 	if(tail){
1953e12c5d1SDavid du Colombier 		errs(" ");
1963e12c5d1SDavid du Colombier 		errs(tail);
1973e12c5d1SDavid du Colombier 	}
1983e12c5d1SDavid du Colombier 	errs("\n");
1993e12c5d1SDavid du Colombier 	Exit("bad flags");
2003e12c5d1SDavid du Colombier }
201*7dd7cddfSDavid du Colombier static void errn(char *s, int count)
2023e12c5d1SDavid du Colombier {
2033e12c5d1SDavid du Colombier 	while(count){ errc(*s++); --count; }
2043e12c5d1SDavid du Colombier }
205*7dd7cddfSDavid du Colombier static void errs(char *s)
2063e12c5d1SDavid du Colombier {
2073e12c5d1SDavid du Colombier 	while(*s) errc(*s++);
2083e12c5d1SDavid du Colombier }
2093e12c5d1SDavid du Colombier #define	NBUF	80
2103e12c5d1SDavid du Colombier static char buf[NBUF], *bufp=buf;
211*7dd7cddfSDavid du Colombier static void errc(int c){
2123e12c5d1SDavid du Colombier 	*bufp++=c;
2133e12c5d1SDavid du Colombier 	if(bufp==&buf[NBUF] || c=='\n'){
2143e12c5d1SDavid du Colombier 		Write(2, buf, bufp-buf);
2153e12c5d1SDavid du Colombier 		bufp=buf;
2163e12c5d1SDavid du Colombier 	}
2173e12c5d1SDavid du Colombier }
218