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;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';101 }102 else103 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 else185 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 void errn(char *s, int count)202 {203 while(count){ errc(*s++); --count; }204 }205 static void errs(char *s)206 {207 while(*s) errc(*s++);208 }209 #define NBUF 80210 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;216 }217 }