| getflags.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
| git clone git://git.suckless.org/9base | |
| Log | |
| Files | |
| Refs | |
| README | |
| 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… | |
| 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; … | |
| 109 count = 0; | |
| 110 while('0'<=*f && *f<='9') count = count*… | |
| 111 } | |
| 112 else | |
| 113 count = 0; | |
| 114 if(*f=='['){ | |
| 115 do{ | |
| 116 f++; | |
| 117 if(*f=='\0'){ reason = FLAGSYN; … | |
| 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++-… | |
| 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++-… | |
| 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 } |