getflags.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       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 }