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