Blob
1 #include <u.h>2 #include <libc.h>3 #include <ctype.h>4 #include "getflags.h"6 char **flag[NFLAG];7 char cmdline[NCMDLINE+1];8 char *cmdname;9 char *flagset[];10 char *flagset[]={"<flag>"};11 static char *flagarg="";12 static void reverse(char **, char **);13 static int scanflag(int, char *);14 static int reason;15 #define RESET 116 #define ARGCCOUNT 217 #define FLAGSYN 318 #define BADFLAG 419 static int badflag;20 char *getflagsargv[NGETFLAGSARGV+2]; /* original argv stored here for people who need it */22 int23 getflags(int argc, char *argv[], char *flags)24 {25 char *s, *t;26 int i, j, c, count;27 flagarg=flags;28 if(cmdname==0){29 cmdname=argv[0];30 for(i=0;i!=argc && i!=NGETFLAGSARGV;i++) getflagsargv[i]=argv[i];31 if(argc>NGETFLAGSARGV) getflagsargv[i++]="...";32 getflagsargv[i]=0;33 }34 s=cmdline;35 for(i=0;i!=argc;i++){36 for(t=argv[i];*t;)37 if(s!=&cmdline[NCMDLINE])38 *s++=*t++;39 else40 break;41 if(i!=argc-1 && s!=&cmdline[NCMDLINE])42 *s++=' ';43 }44 *s='\0';45 i=1;46 while(i!=argc && argv[i][0]=='-'){47 s=argv[i]+1;48 if(*s=='\0'){ /* if argument is "-", stop scanning and delete it */49 for(j=i+1;j<=argc;j++)50 argv[j-1]=argv[j];51 return argc-1;52 }53 while(*s){54 c=*s++;55 count=scanflag(c, flags);56 if(count==-1) return -1;57 if(flag[c]){ reason=RESET; badflag=c; return -1; }58 if(count==0){59 flag[c]=flagset;60 if(*s=='\0'){61 for(j=i+1;j<=argc;j++)62 argv[j-1]=argv[j];63 --argc;64 }65 }66 else{67 if(*s=='\0'){68 for(j=i+1;j<=argc;j++)69 argv[j-1]=argv[j];70 --argc;71 s=argv[i];72 }73 if(argc-i<count){74 reason=ARGCCOUNT;75 badflag=c;76 return -1;77 }78 reverse(argv+i, argv+argc);79 reverse(argv+i, argv+argc-count);80 reverse(argv+argc-count+1, argv+argc);81 argc-=count;82 flag[c]=argv+argc+1;83 flag[c][0]=s;84 s="";85 }86 }87 }88 return argc;89 }91 void92 static reverse(char **p, char **q)93 {94 register char *t;95 for(;p<q;p++,--q){ t=*p; *p=*q; *q=t; }96 }98 static int99 scanflag(int c, char *f)100 {101 int fc, count;102 if(0<=c && c<NFLAG) while(*f){103 if(*f==' '){104 f++;105 continue;106 }107 fc=*f++;108 if(*f==':'){109 f++;110 if(!isdigit((uchar)*f)){ reason=FLAGSYN; return -1; }111 count=strtol(f, &f, 10);112 }113 else114 count=0;115 if(*f=='['){116 int depth=1;117 do{118 f++;119 if(*f=='\0'){ reason=FLAGSYN; return -1; }120 if(*f=='[') depth++;121 if(*f==']') depth--;122 }while(depth>0);123 f++;124 }125 if(c==fc) return count;126 }127 reason=BADFLAG;128 badflag=c;129 return -1;130 }132 static void errn(char *, int), errs(char *), errc(int);134 void135 usage(char *tail)136 {137 char *s, *t, c;138 int count, nflag=0;139 switch(reason){140 case RESET:141 errs("Flag -");142 errc(badflag);143 errs(": set twice\n");144 break;145 case ARGCCOUNT:146 errs("Flag -");147 errc(badflag);148 errs(": too few arguments\n");149 break;150 case FLAGSYN:151 errs("Bad argument to getflags!\n");152 break;153 case BADFLAG:154 errs("Illegal flag -");155 errc(badflag);156 errc('\n');157 break;158 }159 errs("Usage: ");160 errs(cmdname);161 for(s=flagarg;*s;){162 c=*s;163 if(*s++==' ') continue;164 if(*s==':'){165 s++;166 count=strtol(s, &s, 10);167 }168 else count=0;169 if(count==0){170 if(nflag==0) errs(" [-");171 nflag++;172 errc(c);173 }174 if(*s=='['){175 int depth=1;176 s++;177 for(;*s!='\0' && depth>0; s++)178 if (*s==']') depth--;179 else if (*s=='[') depth++;180 }181 }182 if(nflag) errs("]");183 for(s=flagarg;*s;){184 c=*s;185 if(*s++==' ') continue;186 if(*s==':'){187 s++;188 count=strtol(s, &s, 10);189 }190 else count=0;191 if(count!=0){192 errs(" [-");193 errc(c);194 if(*s=='['){195 int depth=1;196 s++;197 t=s;198 for(;*s!='\0' && depth>0; s++)199 if (*s==']') depth--;200 else if (*s=='[') depth++;201 errs(" ");202 errn(t, s-t);203 }204 else205 while(count--) errs(" arg");206 errs("]");207 }208 else if(*s=='['){209 int depth=1;210 s++;211 for(;*s!='\0' && depth>0; s++)212 if (*s==']') depth--;213 else if (*s=='[') depth++;214 }215 }216 if(tail){217 errs(" ");218 errs(tail);219 }220 errs("\n");221 exits("usage");222 }224 static void225 errn(char *s, int count)226 {227 while(count){ errc(*s++); --count; }228 }230 static void231 errs(char *s)232 {233 while(*s) errc(*s++);234 }236 #define NBUF 80237 static char buf[NBUF], *bufp=buf;239 static void240 errc(int c){241 *bufp++=c;242 if(bufp==&buf[NBUF] || c=='\n'){243 write(2, buf, bufp-buf);244 bufp=buf;245 }246 }248 #ifdef TEST249 #include <stdio.h>250 main(int argc, char *argv[])251 {252 int c, i, n;253 if(argc<3){254 fprint(2, "Usage: %s flags cmd ...\n", argv[0]);255 exits("usage");256 }257 n=getflags(argc-2, argv+2, argv[1]);258 if(n<0) usage("...");259 putchar('\n');260 for(c=0;c!=128;c++) if(flag[c]){261 print("\t-.%c. ", c);262 n=scanflag(c, argv[1]);263 for(i=0;i!=n;i++) print(" <%s>", flag[c][i]);264 putchar('\n');265 }266 }267 #endif