Blame


1 acd47706 2005-08-10 devnull #include <u.h>
2 acd47706 2005-08-10 devnull #include <libc.h>
3 acd47706 2005-08-10 devnull #include <ctype.h>
4 acd47706 2005-08-10 devnull #include "getflags.h"
5 acd47706 2005-08-10 devnull
6 acd47706 2005-08-10 devnull char **flag[NFLAG];
7 acd47706 2005-08-10 devnull char cmdline[NCMDLINE+1];
8 acd47706 2005-08-10 devnull char *cmdname;
9 acd47706 2005-08-10 devnull char *flagset[];
10 acd47706 2005-08-10 devnull char *flagset[]={"<flag>"};
11 acd47706 2005-08-10 devnull static char *flagarg="";
12 acd47706 2005-08-10 devnull static void reverse(char **, char **);
13 acd47706 2005-08-10 devnull static int scanflag(int, char *);
14 acd47706 2005-08-10 devnull static int reason;
15 acd47706 2005-08-10 devnull #define RESET 1
16 acd47706 2005-08-10 devnull #define ARGCCOUNT 2
17 acd47706 2005-08-10 devnull #define FLAGSYN 3
18 acd47706 2005-08-10 devnull #define BADFLAG 4
19 acd47706 2005-08-10 devnull static int badflag;
20 acd47706 2005-08-10 devnull char *getflagsargv[NGETFLAGSARGV+2]; /* original argv stored here for people who need it */
21 acd47706 2005-08-10 devnull
22 acd47706 2005-08-10 devnull int
23 acd47706 2005-08-10 devnull getflags(int argc, char *argv[], char *flags)
24 acd47706 2005-08-10 devnull {
25 acd47706 2005-08-10 devnull char *s, *t;
26 acd47706 2005-08-10 devnull int i, j, c, count;
27 acd47706 2005-08-10 devnull flagarg=flags;
28 acd47706 2005-08-10 devnull if(cmdname==0){
29 acd47706 2005-08-10 devnull cmdname=argv[0];
30 acd47706 2005-08-10 devnull for(i=0;i!=argc && i!=NGETFLAGSARGV;i++) getflagsargv[i]=argv[i];
31 acd47706 2005-08-10 devnull if(argc>NGETFLAGSARGV) getflagsargv[i++]="...";
32 acd47706 2005-08-10 devnull getflagsargv[i]=0;
33 acd47706 2005-08-10 devnull }
34 acd47706 2005-08-10 devnull s=cmdline;
35 acd47706 2005-08-10 devnull for(i=0;i!=argc;i++){
36 acd47706 2005-08-10 devnull for(t=argv[i];*t;)
37 acd47706 2005-08-10 devnull if(s!=&cmdline[NCMDLINE])
38 acd47706 2005-08-10 devnull *s++=*t++;
39 acd47706 2005-08-10 devnull else
40 acd47706 2005-08-10 devnull break;
41 acd47706 2005-08-10 devnull if(i!=argc-1 && s!=&cmdline[NCMDLINE])
42 acd47706 2005-08-10 devnull *s++=' ';
43 acd47706 2005-08-10 devnull }
44 acd47706 2005-08-10 devnull *s='\0';
45 acd47706 2005-08-10 devnull i=1;
46 acd47706 2005-08-10 devnull while(i!=argc && argv[i][0]=='-'){
47 acd47706 2005-08-10 devnull s=argv[i]+1;
48 acd47706 2005-08-10 devnull if(*s=='\0'){ /* if argument is "-", stop scanning and delete it */
49 acd47706 2005-08-10 devnull for(j=i+1;j<=argc;j++)
50 acd47706 2005-08-10 devnull argv[j-1]=argv[j];
51 acd47706 2005-08-10 devnull return argc-1;
52 acd47706 2005-08-10 devnull }
53 acd47706 2005-08-10 devnull while(*s){
54 acd47706 2005-08-10 devnull c=*s++;
55 acd47706 2005-08-10 devnull count=scanflag(c, flags);
56 acd47706 2005-08-10 devnull if(count==-1) return -1;
57 acd47706 2005-08-10 devnull if(flag[c]){ reason=RESET; badflag=c; return -1; }
58 acd47706 2005-08-10 devnull if(count==0){
59 acd47706 2005-08-10 devnull flag[c]=flagset;
60 acd47706 2005-08-10 devnull if(*s=='\0'){
61 acd47706 2005-08-10 devnull for(j=i+1;j<=argc;j++)
62 acd47706 2005-08-10 devnull argv[j-1]=argv[j];
63 acd47706 2005-08-10 devnull --argc;
64 acd47706 2005-08-10 devnull }
65 acd47706 2005-08-10 devnull }
66 acd47706 2005-08-10 devnull else{
67 acd47706 2005-08-10 devnull if(*s=='\0'){
68 acd47706 2005-08-10 devnull for(j=i+1;j<=argc;j++)
69 acd47706 2005-08-10 devnull argv[j-1]=argv[j];
70 acd47706 2005-08-10 devnull --argc;
71 acd47706 2005-08-10 devnull s=argv[i];
72 acd47706 2005-08-10 devnull }
73 acd47706 2005-08-10 devnull if(argc-i<count){
74 acd47706 2005-08-10 devnull reason=ARGCCOUNT;
75 acd47706 2005-08-10 devnull badflag=c;
76 acd47706 2005-08-10 devnull return -1;
77 acd47706 2005-08-10 devnull }
78 acd47706 2005-08-10 devnull reverse(argv+i, argv+argc);
79 acd47706 2005-08-10 devnull reverse(argv+i, argv+argc-count);
80 acd47706 2005-08-10 devnull reverse(argv+argc-count+1, argv+argc);
81 acd47706 2005-08-10 devnull argc-=count;
82 acd47706 2005-08-10 devnull flag[c]=argv+argc+1;
83 acd47706 2005-08-10 devnull flag[c][0]=s;
84 acd47706 2005-08-10 devnull s="";
85 acd47706 2005-08-10 devnull }
86 acd47706 2005-08-10 devnull }
87 acd47706 2005-08-10 devnull }
88 acd47706 2005-08-10 devnull return argc;
89 acd47706 2005-08-10 devnull }
90 acd47706 2005-08-10 devnull
91 acd47706 2005-08-10 devnull void
92 acd47706 2005-08-10 devnull static reverse(char **p, char **q)
93 acd47706 2005-08-10 devnull {
94 acd47706 2005-08-10 devnull register char *t;
95 acd47706 2005-08-10 devnull for(;p<q;p++,--q){ t=*p; *p=*q; *q=t; }
96 acd47706 2005-08-10 devnull }
97 acd47706 2005-08-10 devnull
98 acd47706 2005-08-10 devnull static int
99 acd47706 2005-08-10 devnull scanflag(int c, char *f)
100 acd47706 2005-08-10 devnull {
101 acd47706 2005-08-10 devnull int fc, count;
102 acd47706 2005-08-10 devnull if(0<=c && c<NFLAG) while(*f){
103 acd47706 2005-08-10 devnull if(*f==' '){
104 acd47706 2005-08-10 devnull f++;
105 acd47706 2005-08-10 devnull continue;
106 acd47706 2005-08-10 devnull }
107 acd47706 2005-08-10 devnull fc=*f++;
108 acd47706 2005-08-10 devnull if(*f==':'){
109 acd47706 2005-08-10 devnull f++;
110 3bd56b04 2005-09-09 devnull if(!isdigit((uchar)*f)){ reason=FLAGSYN; return -1; }
111 acd47706 2005-08-10 devnull count=strtol(f, &f, 10);
112 acd47706 2005-08-10 devnull }
113 acd47706 2005-08-10 devnull else
114 acd47706 2005-08-10 devnull count=0;
115 acd47706 2005-08-10 devnull if(*f=='['){
116 acd47706 2005-08-10 devnull int depth=1;
117 acd47706 2005-08-10 devnull do{
118 acd47706 2005-08-10 devnull f++;
119 acd47706 2005-08-10 devnull if(*f=='\0'){ reason=FLAGSYN; return -1; }
120 acd47706 2005-08-10 devnull if(*f=='[') depth++;
121 acd47706 2005-08-10 devnull if(*f==']') depth--;
122 acd47706 2005-08-10 devnull }while(depth>0);
123 acd47706 2005-08-10 devnull f++;
124 acd47706 2005-08-10 devnull }
125 acd47706 2005-08-10 devnull if(c==fc) return count;
126 acd47706 2005-08-10 devnull }
127 acd47706 2005-08-10 devnull reason=BADFLAG;
128 acd47706 2005-08-10 devnull badflag=c;
129 acd47706 2005-08-10 devnull return -1;
130 acd47706 2005-08-10 devnull }
131 acd47706 2005-08-10 devnull
132 acd47706 2005-08-10 devnull static void errn(char *, int), errs(char *), errc(int);
133 acd47706 2005-08-10 devnull
134 acd47706 2005-08-10 devnull void
135 acd47706 2005-08-10 devnull usage(char *tail)
136 acd47706 2005-08-10 devnull {
137 acd47706 2005-08-10 devnull char *s, *t, c;
138 acd47706 2005-08-10 devnull int count, nflag=0;
139 acd47706 2005-08-10 devnull switch(reason){
140 acd47706 2005-08-10 devnull case RESET:
141 acd47706 2005-08-10 devnull errs("Flag -");
142 acd47706 2005-08-10 devnull errc(badflag);
143 acd47706 2005-08-10 devnull errs(": set twice\n");
144 acd47706 2005-08-10 devnull break;
145 acd47706 2005-08-10 devnull case ARGCCOUNT:
146 acd47706 2005-08-10 devnull errs("Flag -");
147 acd47706 2005-08-10 devnull errc(badflag);
148 acd47706 2005-08-10 devnull errs(": too few arguments\n");
149 acd47706 2005-08-10 devnull break;
150 acd47706 2005-08-10 devnull case FLAGSYN:
151 acd47706 2005-08-10 devnull errs("Bad argument to getflags!\n");
152 acd47706 2005-08-10 devnull break;
153 acd47706 2005-08-10 devnull case BADFLAG:
154 acd47706 2005-08-10 devnull errs("Illegal flag -");
155 acd47706 2005-08-10 devnull errc(badflag);
156 acd47706 2005-08-10 devnull errc('\n');
157 acd47706 2005-08-10 devnull break;
158 acd47706 2005-08-10 devnull }
159 acd47706 2005-08-10 devnull errs("Usage: ");
160 acd47706 2005-08-10 devnull errs(cmdname);
161 acd47706 2005-08-10 devnull for(s=flagarg;*s;){
162 acd47706 2005-08-10 devnull c=*s;
163 acd47706 2005-08-10 devnull if(*s++==' ') continue;
164 acd47706 2005-08-10 devnull if(*s==':'){
165 acd47706 2005-08-10 devnull s++;
166 acd47706 2005-08-10 devnull count=strtol(s, &s, 10);
167 acd47706 2005-08-10 devnull }
168 acd47706 2005-08-10 devnull else count=0;
169 acd47706 2005-08-10 devnull if(count==0){
170 acd47706 2005-08-10 devnull if(nflag==0) errs(" [-");
171 acd47706 2005-08-10 devnull nflag++;
172 acd47706 2005-08-10 devnull errc(c);
173 acd47706 2005-08-10 devnull }
174 acd47706 2005-08-10 devnull if(*s=='['){
175 acd47706 2005-08-10 devnull int depth=1;
176 acd47706 2005-08-10 devnull s++;
177 acd47706 2005-08-10 devnull for(;*s!='\0' && depth>0; s++)
178 acd47706 2005-08-10 devnull if (*s==']') depth--;
179 acd47706 2005-08-10 devnull else if (*s=='[') depth++;
180 acd47706 2005-08-10 devnull }
181 acd47706 2005-08-10 devnull }
182 acd47706 2005-08-10 devnull if(nflag) errs("]");
183 acd47706 2005-08-10 devnull for(s=flagarg;*s;){
184 acd47706 2005-08-10 devnull c=*s;
185 acd47706 2005-08-10 devnull if(*s++==' ') continue;
186 acd47706 2005-08-10 devnull if(*s==':'){
187 acd47706 2005-08-10 devnull s++;
188 acd47706 2005-08-10 devnull count=strtol(s, &s, 10);
189 acd47706 2005-08-10 devnull }
190 acd47706 2005-08-10 devnull else count=0;
191 acd47706 2005-08-10 devnull if(count!=0){
192 acd47706 2005-08-10 devnull errs(" [-");
193 acd47706 2005-08-10 devnull errc(c);
194 acd47706 2005-08-10 devnull if(*s=='['){
195 acd47706 2005-08-10 devnull int depth=1;
196 acd47706 2005-08-10 devnull s++;
197 acd47706 2005-08-10 devnull t=s;
198 acd47706 2005-08-10 devnull for(;*s!='\0' && depth>0; s++)
199 acd47706 2005-08-10 devnull if (*s==']') depth--;
200 acd47706 2005-08-10 devnull else if (*s=='[') depth++;
201 acd47706 2005-08-10 devnull errs(" ");
202 acd47706 2005-08-10 devnull errn(t, s-t);
203 acd47706 2005-08-10 devnull }
204 acd47706 2005-08-10 devnull else
205 acd47706 2005-08-10 devnull while(count--) errs(" arg");
206 acd47706 2005-08-10 devnull errs("]");
207 acd47706 2005-08-10 devnull }
208 acd47706 2005-08-10 devnull else if(*s=='['){
209 acd47706 2005-08-10 devnull int depth=1;
210 acd47706 2005-08-10 devnull s++;
211 acd47706 2005-08-10 devnull for(;*s!='\0' && depth>0; s++)
212 acd47706 2005-08-10 devnull if (*s==']') depth--;
213 acd47706 2005-08-10 devnull else if (*s=='[') depth++;
214 acd47706 2005-08-10 devnull }
215 acd47706 2005-08-10 devnull }
216 acd47706 2005-08-10 devnull if(tail){
217 acd47706 2005-08-10 devnull errs(" ");
218 acd47706 2005-08-10 devnull errs(tail);
219 acd47706 2005-08-10 devnull }
220 acd47706 2005-08-10 devnull errs("\n");
221 acd47706 2005-08-10 devnull exits("usage");
222 acd47706 2005-08-10 devnull }
223 acd47706 2005-08-10 devnull
224 acd47706 2005-08-10 devnull static void
225 acd47706 2005-08-10 devnull errn(char *s, int count)
226 acd47706 2005-08-10 devnull {
227 acd47706 2005-08-10 devnull while(count){ errc(*s++); --count; }
228 acd47706 2005-08-10 devnull }
229 acd47706 2005-08-10 devnull
230 acd47706 2005-08-10 devnull static void
231 acd47706 2005-08-10 devnull errs(char *s)
232 acd47706 2005-08-10 devnull {
233 acd47706 2005-08-10 devnull while(*s) errc(*s++);
234 acd47706 2005-08-10 devnull }
235 acd47706 2005-08-10 devnull
236 acd47706 2005-08-10 devnull #define NBUF 80
237 acd47706 2005-08-10 devnull static char buf[NBUF], *bufp=buf;
238 acd47706 2005-08-10 devnull
239 acd47706 2005-08-10 devnull static void
240 acd47706 2005-08-10 devnull errc(int c){
241 acd47706 2005-08-10 devnull *bufp++=c;
242 acd47706 2005-08-10 devnull if(bufp==&buf[NBUF] || c=='\n'){
243 acd47706 2005-08-10 devnull write(2, buf, bufp-buf);
244 acd47706 2005-08-10 devnull bufp=buf;
245 acd47706 2005-08-10 devnull }
246 acd47706 2005-08-10 devnull }
247 acd47706 2005-08-10 devnull
248 acd47706 2005-08-10 devnull #ifdef TEST
249 acd47706 2005-08-10 devnull #include <stdio.h>
250 acd47706 2005-08-10 devnull main(int argc, char *argv[])
251 acd47706 2005-08-10 devnull {
252 acd47706 2005-08-10 devnull int c, i, n;
253 acd47706 2005-08-10 devnull if(argc<3){
254 acd47706 2005-08-10 devnull fprint(2, "Usage: %s flags cmd ...\n", argv[0]);
255 acd47706 2005-08-10 devnull exits("usage");
256 acd47706 2005-08-10 devnull }
257 acd47706 2005-08-10 devnull n=getflags(argc-2, argv+2, argv[1]);
258 acd47706 2005-08-10 devnull if(n<0) usage("...");
259 acd47706 2005-08-10 devnull putchar('\n');
260 acd47706 2005-08-10 devnull for(c=0;c!=128;c++) if(flag[c]){
261 acd47706 2005-08-10 devnull print("\t-.%c. ", c);
262 acd47706 2005-08-10 devnull n=scanflag(c, argv[1]);
263 acd47706 2005-08-10 devnull for(i=0;i!=n;i++) print(" <%s>", flag[c][i]);
264 acd47706 2005-08-10 devnull putchar('\n');
265 acd47706 2005-08-10 devnull }
266 acd47706 2005-08-10 devnull }
267 acd47706 2005-08-10 devnull #endif