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;
22 int getflags(int argc, char *argv[], char *flags, int stop)
23 {
24 char *s, *t;
25 int i, j, c, count;
26 flagarg=flags;
27 if(cmdname==0) cmdname=argv[0];
28 s=cmdline;
29 for(i=0;i!=argc;i++){
30 for(t=argv[i];*t;t++)
31 if(s!=&cmdline[NCMDLINE])
32 *s++=*t;
33 if(i!=argc-1 && s!=&cmdline[NCMDLINE])
34 *s++=' ';
35 }
36 *s='\0';
37 i=1;
38 while(i!=argc){
39 if(argv[i][0]!='-' || argv[i][1]=='\0'){
40 if(stop) return argc;
41 i++;
42 continue;
43 }
44 s=argv[i]+1;
45 while(*s){
46 c=*s++;
47 count=scanflag(c, flags);
48 if(count==-1) return -1;
49 if(flag[c]){ reason=RESET; badflag=c; return -1; }
50 if(count==0){
51 flag[c]=flagset;
52 if(*s=='\0'){
53 for(j=i+1;j<=argc;j++)
54 argv[j-1]=argv[j];
55 --argc;
56 }
57 }
58 else{
59 if(*s=='\0'){
60 for(j=i+1;j<=argc;j++)
61 argv[j-1]=argv[j];
62 --argc;
63 s=argv[i];
64 }
65 if(argc-i<count){
66 reason=FEWARGS;
67 badflag=c;
68 return -1;
69 }
70 reverse(argv+i, argv+argc);
71 reverse(argv+i, argv+argc-count);
72 reverse(argv+argc-count+1, argv+argc);
73 argc-=count;
74 flag[c]=argv+argc+1;
75 flag[c][0]=s;
76 s="";
77 }
78 }
79 }
80 return argc;
81 }
82 static void reverse(char **p, char **q)
83 {
84 char *t;
85 for(;p<q;p++,--q){ t=*p; *p=*q; *q=t; }
86 }
87 static int scanflag(int c, char *f)
88 {
89 int fc, count;
90 if(0<=c && c<NFLAG) while(*f){
91 if(*f==' '){
92 f++;
93 continue;
94 }
95 fc=*f++;
96 if(*f==':'){
97 f++;
98 if(*f<'0' || '9'<*f){ reason=FLAGSYN; return -1; }
99 count=0;
100 while('0'<=*f && *f<='9') count=count*10+*f++-'0';
102 else
103 count=0;
104 if(*f=='['){
105 do{
106 f++;
107 if(*f=='\0'){ reason=FLAGSYN; return -1; }
108 }while(*f!=']');
109 f++;
111 if(c==fc) return count;
113 reason=BADFLAG;
114 badflag=c;
115 return -1;
117 void usage(char *tail)
119 char *s, *t, c;
120 int count, nflag=0;
121 switch(reason){
122 case RESET:
123 errs("Flag -");
124 errc(badflag);
125 errs(": set twice\n");
126 break;
127 case FEWARGS:
128 errs("Flag -");
129 errc(badflag);
130 errs(": too few arguments\n");
131 break;
132 case FLAGSYN:
133 errs("Bad argument to getflags!\n");
134 break;
135 case BADFLAG:
136 errs("Illegal flag -");
137 errc(badflag);
138 errc('\n');
139 break;
141 errs("Usage: ");
142 errs(cmdname);
143 for(s=flagarg;*s;){
144 c=*s;
145 if(*s++==' ') continue;
146 if(*s==':'){
147 s++;
148 count=0;
149 while('0'<=*s && *s<='9') count=count*10+*s++-'0';
151 else count=0;
152 if(count==0){
153 if(nflag==0) errs(" [-");
154 nflag++;
155 errc(c);
157 if(*s=='['){
158 s++;
159 while(*s!=']' && *s!='\0') s++;
160 if(*s==']') s++;
163 if(nflag) errs("]");
164 for(s=flagarg;*s;){
165 c=*s;
166 if(*s++==' ') continue;
167 if(*s==':'){
168 s++;
169 count=0;
170 while('0'<=*s && *s<='9') count=count*10+*s++-'0';
172 else count=0;
173 if(count!=0){
174 errs(" [-");
175 errc(c);
176 if(*s=='['){
177 s++;
178 t=s;
179 while(*s!=']' && *s!='\0') s++;
180 errs(" ");
181 errn(t, s-t);
182 if(*s==']') s++;
184 else
185 while(count--) errs(" arg");
186 errs("]");
188 else if(*s=='['){
189 s++;
190 while(*s!=']' && *s!='\0') s++;
191 if(*s==']') s++;
194 if(tail){
195 errs(" ");
196 errs(tail);
198 errs("\n");
199 Exit("bad flags");
201 static void errn(char *s, int count)
203 while(count){ errc(*s++); --count; }
205 static void errs(char *s)
207 while(*s) errc(*s++);
209 #define NBUF 80
210 static char buf[NBUF], *bufp=buf;
211 static void errc(int c){
212 *bufp++=c;
213 if(bufp==&buf[NBUF] || c=='\n'){
214 Write(2, buf, bufp-buf);
215 bufp=buf;