]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/rc/getflags.c
ip/ipconfig: use ewrite() to enable routing command for sendra
[plan9front.git] / sys / src / cmd / rc / getflags.c
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
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
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
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
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
212 errn(char *s, int count)
213 {
214         while(count){ errc(*s++); --count; }
215 }
216
217 static void
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
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 }