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 reverse(char**, char**); 12 static scanflag(int, char*); 13 static errn(char*, int); 14 static errs(char*); 15 static 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 reverse(char **p, char **q) 83 { 84 char *t; 85 for(;p<q;p++,--q){ t=*p; *p=*q; *q=t; } 86 } 87 static 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'; 101 } 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++; 110 } 111 if(c==fc) return count; 112 } 113 reason=BADFLAG; 114 badflag=c; 115 return -1; 116 } 117 void usage(char *tail) 118 { 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; 140 } 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'; 150 } 151 else count=0; 152 if(count==0){ 153 if(nflag==0) errs(" [-"); 154 nflag++; 155 errc(c); 156 } 157 if(*s=='['){ 158 s++; 159 while(*s!=']' && *s!='\0') s++; 160 if(*s==']') s++; 161 } 162 } 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'; 171 } 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++; 183 } 184 else 185 while(count--) errs(" arg"); 186 errs("]"); 187 } 188 else if(*s=='['){ 189 s++; 190 while(*s!=']' && *s!='\0') s++; 191 if(*s==']') s++; 192 } 193 } 194 if(tail){ 195 errs(" "); 196 errs(tail); 197 } 198 errs("\n"); 199 Exit("bad flags"); 200 } 201 static errn(char *s, int count) 202 { 203 while(count){ errc(*s++); --count; } 204 } 205 static errs(char *s) 206 { 207 while(*s) errc(*s++); 208 } 209 #define NBUF 80 210 static char buf[NBUF], *bufp=buf; 211 static errc(int c){ 212 *bufp++=c; 213 if(bufp==&buf[NBUF] || c=='\n'){ 214 Write(2, buf, bufp-buf); 215 bufp=buf; 216 } 217 } 218