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