xref: /plan9/sys/src/cmd/rc/getflags.c (revision 99eb86a7eded05d02373a1dc66f01c7d211105e0)
1 #include "rc.h"
2 #include "getflags.h"
3 #include "fns.h"
4 char *flagset[] = {"<flag>"};
5 char **flag[NFLAG];
6 char *cmdname;
7 static char *flagarg="";
8 static void reverse(char**, char**);
9 static int scanflag(int, char*);
10 static void errn(char*, int);
11 static void errs(char*);
12 static void errc(int);
13 static int reason;
14 #define	RESET	1
15 #define	FEWARGS	2
16 #define	FLAGSYN	3
17 #define	BADFLAG	4
18 static int badflag;
19 
20 int
getflags(int argc,char * argv[],char * flags,int stop)21 getflags(int argc, char *argv[], char *flags, int stop)
22 {
23 	char *s;
24 	int i, j, c, count;
25 	flagarg = flags;
26 	if(cmdname==0)
27 		cmdname = argv[0];
28 
29 	i = 1;
30 	while(i!=argc){
31 		if(argv[i][0] != '-' || argv[i][1] == '\0'){
32 			if(stop)		/* always true in rc */
33 				return argc;
34 			i++;
35 			continue;
36 		}
37 		s = argv[i]+1;
38 		while(*s){
39 			c=*s++;
40 			count = scanflag(c, flags);
41 			if(count==-1)
42 				return -1;
43 			if(flag[c]){ reason = RESET; badflag = c; return -1; }
44 			if(count==0){
45 				flag[c] = flagset;
46 				if(*s=='\0'){
47 					for(j = i+1;j<=argc;j++)
48 						argv[j-1] = argv[j];
49 					--argc;
50 				}
51 			}
52 			else{
53 				if(*s=='\0'){
54 					for(j = i+1;j<=argc;j++)
55 						argv[j-1] = argv[j];
56 					--argc;
57 					s = argv[i];
58 				}
59 				if(argc-i<count){
60 					reason = FEWARGS;
61 					badflag = c;
62 					return -1;
63 				}
64 				reverse(argv+i, argv+argc);
65 				reverse(argv+i, argv+argc-count);
66 				reverse(argv+argc-count+1, argv+argc);
67 				argc-=count;
68 				flag[c] = argv+argc+1;
69 				flag[c][0] = s;
70 				s="";
71 			}
72 		}
73 	}
74 	return argc;
75 }
76 
77 static void
reverse(char ** p,char ** q)78 reverse(char **p, char **q)
79 {
80 	char *t;
81 	for(;p<q;p++,--q){ t=*p; *p=*q; *q = t; }
82 }
83 
84 static int
scanflag(int c,char * f)85 scanflag(int c, char *f)
86 {
87 	int fc, count;
88 	if(0<=c && c<NFLAG)
89 		while(*f){
90 			if(*f==' '){
91 				f++;
92 				continue;
93 			}
94 			fc=*f++;
95 			if(*f==':'){
96 				f++;
97 				if(*f<'0' || '9'<*f){ reason = FLAGSYN; return -1; }
98 				count = 0;
99 				while('0'<=*f && *f<='9') count = count*10+*f++-'0';
100 			}
101 			else
102 				count = 0;
103 			if(*f=='['){
104 				do{
105 					f++;
106 					if(*f=='\0'){ reason = FLAGSYN; return -1; }
107 				}while(*f!=']');
108 				f++;
109 			}
110 			if(c==fc)
111 				return count;
112 		}
113 	reason = BADFLAG;
114 	badflag = c;
115 	return -1;
116 }
117 
118 void
usage(char * tail)119 usage(char *tail)
120 {
121 	char *s, *t, c;
122 	int count, nflag = 0;
123 	switch(reason){
124 	case RESET:
125 		errs("Flag -");
126 		errc(badflag);
127 		errs(": set twice\n");
128 		break;
129 	case FEWARGS:
130 		errs("Flag -");
131 		errc(badflag);
132 		errs(": too few arguments\n");
133 		break;
134 	case FLAGSYN:
135 		errs("Bad argument to getflags!\n");
136 		break;
137 	case BADFLAG:
138 		errs("Illegal flag -");
139 		errc(badflag);
140 		errc('\n');
141 		break;
142 	}
143 	errs("Usage: ");
144 	errs(cmdname);
145 	for(s = flagarg;*s;){
146 		c=*s;
147 		if(*s++==' ')
148 			continue;
149 		if(*s==':'){
150 			s++;
151 			count = 0;
152 			while('0'<=*s && *s<='9') count = count*10+*s++-'0';
153 		}
154 		else count = 0;
155 		if(count==0){
156 			if(nflag==0)
157 				errs(" [-");
158 			nflag++;
159 			errc(c);
160 		}
161 		if(*s=='['){
162 			s++;
163 			while(*s!=']' && *s!='\0') s++;
164 			if(*s==']')
165 				s++;
166 		}
167 	}
168 	if(nflag)
169 		errs("]");
170 	for(s = flagarg;*s;){
171 		c=*s;
172 		if(*s++==' ')
173 			continue;
174 		if(*s==':'){
175 			s++;
176 			count = 0;
177 			while('0'<=*s && *s<='9') count = count*10+*s++-'0';
178 		}
179 		else count = 0;
180 		if(count!=0){
181 			errs(" [-");
182 			errc(c);
183 			if(*s=='['){
184 				s++;
185 				t = s;
186 				while(*s!=']' && *s!='\0') s++;
187 				errs(" ");
188 				errn(t, s-t);
189 				if(*s==']')
190 					s++;
191 			}
192 			else
193 				while(count--) errs(" arg");
194 			errs("]");
195 		}
196 		else if(*s=='['){
197 			s++;
198 			while(*s!=']' && *s!='\0') s++;
199 			if(*s==']')
200 				s++;
201 		}
202 	}
203 	if(tail){
204 		errs(" ");
205 		errs(tail);
206 	}
207 	errs("\n");
208 	Exit("bad flags");
209 }
210 
211 static void
errn(char * s,int count)212 errn(char *s, int count)
213 {
214 	while(count){ errc(*s++); --count; }
215 }
216 
217 static void
errs(char * s)218 errs(char *s)
219 {
220 	while(*s) errc(*s++);
221 }
222 #define	NBUF	80
223 static char buf[NBUF], *bufp = buf;
224 
225 static void
errc(int c)226 errc(int c)
227 {
228 	*bufp++=c;
229 	if(bufp==&buf[NBUF] || c=='\n'){
230 		Write(2, buf, bufp-buf);
231 		bufp = buf;
232 	}
233 }
234