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 -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 } 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; return -1; } 109 count = 0; 110 while('0'<=*f && *f<='9') count = count*10+*f++-'0'; 111 } 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++; 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++-'0'; 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++-'0'; 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 }