Blob


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;
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 -1; }
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 }
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 }
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;
105 fc=*f++;
106 if(*f==':'){
107 f++;
108 if(*f<'0' || '9'<*f){ reason = FLAGSYN; return -1; }
109 count = 0;
110 while('0'<=*f && *f<='9') count = count*10+*f++-'0';
112 else
113 count = 0;
114 if(*f=='['){
115 do{
116 f++;
117 if(*f=='\0'){ reason = FLAGSYN; return -1; }
118 }while(*f!=']');
119 f++;
121 if(c==fc)
122 return count;
124 reason = BADFLAG;
125 badflag = c;
126 return -1;
129 void
130 usage(char *tail)
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;
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++-'0';
165 else count = 0;
166 if(count==0){
167 if(nflag==0)
168 errs(" [-");
169 nflag++;
170 errc(c);
172 if(*s=='['){
173 s++;
174 while(*s!=']' && *s!='\0') s++;
175 if(*s==']')
176 s++;
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++-'0';
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++;
203 else
204 while(count--) errs(" arg");
205 errs("]");
207 else if(*s=='['){
208 s++;
209 while(*s!=']' && *s!='\0') s++;
210 if(*s==']')
211 s++;
214 if(tail){
215 errs(" ");
216 errs(tail);
218 errs("\n");
219 Exit("bad flags");
222 static void
223 errn(char *s, int count)
225 while(count){ errc(*s++); --count; }
228 static void
229 errs(char *s)
231 while(*s) errc(*s++);
233 #define NBUF 80
234 static char buf[NBUF], *bufp = buf;
236 static void
237 errc(int c)
239 *bufp++=c;
240 if(bufp==&buf[NBUF] || c=='\n'){
241 Write(2, buf, bufp-buf);
242 bufp = buf;