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 118 #define FEWARGS 219 #define FLAGSYN 320 #define BADFLAG 421 static int badflag;23 int24 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 void89 reverse(char **p, char **q)90 {91 char *t;92 for(;p<q;p++,--q){ t=*p; *p=*q; *q = t; }93 }95 static int96 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 else113 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 }129 void130 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 else204 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 }222 static void223 errn(char *s, int count)224 {225 while(count){ errc(*s++); --count; }226 }228 static void229 errs(char *s)230 {231 while(*s) errc(*s++);232 }233 #define NBUF 80234 static char buf[NBUF], *bufp = buf;236 static void237 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 }