/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "rc.h"#include "getflags.h"#include "fns.h"char *flagset[] = {"<flag>"};char **flag[NFLAG];char *cmdname;static char *flagarg="";static void reverse(char**, char**);static int scanflag(int, char*);static void errn(char*, int);static void errs(char*);static void errc(int);static int reason;#define RESET 1#define FEWARGS 2#define FLAGSYN 3#define BADFLAG 4static int badflag; intgetflags(int argc, char *argv[], char *flags, int stop){ char *s; int i, j, c, count; flagarg = flags; if(cmdname==0) cmdname = argv[0]; i = 1; while(i!=argc){ if(argv[i][0] != '-' || argv[i][1] == '\0'){ if(stop) /* always true in rc */ return argc; i++; continue; } s = argv[i]+1; while(*s){ c=*s++; count = scanflag(c, flags); if(count==-1) return -1; if(flag[c]){ reason = RESET; badflag = c; return -1; } if(count==0){ flag[c] = flagset; if(*s=='\0'){ for(j = i+1;j<=argc;j++) argv[j-1] = argv[j]; --argc; } } else{ if(*s=='\0'){ for(j = i+1;j<=argc;j++) argv[j-1] = argv[j]; --argc; s = argv[i]; } if(argc-i<count){ reason = FEWARGS; badflag = c; return -1; } reverse(argv+i, argv+argc); reverse(argv+i, argv+argc-count); reverse(argv+argc-count+1, argv+argc); argc-=count; flag[c] = argv+argc+1; flag[c][0] = s; s=""; } } } return argc;} static voidreverse(char **p, char **q){ char *t; for(;p<q;p++,--q){ t=*p; *p=*q; *q = t; }} static intscanflag(int c, char *f){ int fc, count; if(0<=c && c<NFLAG) while(*f){ if(*f==' '){ f++; continue; } fc=*f++; if(*f==':'){ f++; if(*f<'0' || '9'<*f){ reason = FLAGSYN; return -1; } count = 0; while('0'<=*f && *f<='9') count = count*10+*f++-'0'; } else count = 0; if(*f=='['){ do{ f++; if(*f=='\0'){ reason = FLAGSYN; return -1; } }while(*f!=']'); f++; } if(c==fc) return count; } reason = BADFLAG; badflag = c; return -1;} voidusage(char *tail){ char *s, *t, c; int count, nflag = 0; switch(reason){ case RESET: errs("Flag -"); errc(badflag); errs(": set twice\n"); break; case FEWARGS: errs("Flag -"); errc(badflag); errs(": too few arguments\n"); break; case FLAGSYN: errs("Bad argument to getflags!\n"); break; case BADFLAG: errs("Illegal flag -"); errc(badflag); errc('\n'); break; } errs("Usage: "); errs(cmdname); for(s = flagarg;*s;){ c=*s; if(*s++==' ') continue; if(*s==':'){ s++; count = 0; while('0'<=*s && *s<='9') count = count*10+*s++-'0'; } else count = 0; if(count==0){ if(nflag==0) errs(" [-"); nflag++; errc(c); } if(*s=='['){ s++; while(*s!=']' && *s!='\0') s++; if(*s==']') s++; } } if(nflag) errs("]"); for(s = flagarg;*s;){ c=*s; if(*s++==' ') continue; if(*s==':'){ s++; count = 0; while('0'<=*s && *s<='9') count = count*10+*s++-'0'; } else count = 0; if(count!=0){ errs(" [-"); errc(c); if(*s=='['){ s++; t = s; while(*s!=']' && *s!='\0') s++; errs(" "); errn(t, s-t); if(*s==']') s++; } else while(count--) errs(" arg"); errs("]"); } else if(*s=='['){ s++; while(*s!=']' && *s!='\0') s++; if(*s==']') s++; } } if(tail){ errs(" "); errs(tail); } errs("\n"); Exit("bad flags");} static voiderrn(char *s, int count){ while(count){ errc(*s++); --count; }} static voiderrs(char *s){ while(*s) errc(*s++);}#define NBUF 80static char buf[NBUF], *bufp = buf; static voiderrc(int c){ *bufp++=c; if(bufp==&buf[NBUF] || c=='\n'){ Write(2, buf, bufp-buf); bufp = buf; }}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#include "rc.h"
#include "getflags.h"
#include "fns.h"
char *flagset[] = {"<flag>"};
char **flag[NFLAG];
char *cmdname;
static char *flagarg="";
static void reverse(char**, char**);
static int scanflag(int, char*);
static void errn(char*, int);
static void errs(char*);
static void errc(int);
static int reason;
#define RESET 1
#define FEWARGS 2
#define FLAGSYN 3
#define BADFLAG 4
static int badflag;
int
getflags(int argc, char *argv[], char *flags, int stop)
{
char *s;
int i, j, c, count;
flagarg = flags;
if(cmdname==0)
cmdname = argv[0];
i = 1;
while(i!=argc){
if(argv[i][0] != '-' || argv[i][1] == '\0'){
if(stop) /* always true in rc */
return argc;
i++;
continue;
}
s = argv[i]+1;
while(*s){
c=*s++;
count = scanflag(c, flags);
if(count==-1)
return -1;
if(flag[c]){ reason = RESET; badflag = c; return -1; }
if(count==0){
flag[c] = flagset;
if(*s=='\0'){
for(j = i+1;j<=argc;j++)
argv[j-1] = argv[j];
--argc;
}
}
else{
if(*s=='\0'){
for(j = i+1;j<=argc;j++)
argv[j-1] = argv[j];
--argc;
s = argv[i];
}
if(argc-i<count){
reason = FEWARGS;
badflag = c;
return -1;
}
reverse(argv+i, argv+argc);
reverse(argv+i, argv+argc-count);
reverse(argv+argc-count+1, argv+argc);
argc-=count;
flag[c] = argv+argc+1;
flag[c][0] = s;
s="";
}
}
}
return argc;
}
static void
reverse(char **p, char **q)
{
char *t;
for(;p<q;p++,--q){ t=*p; *p=*q; *q = t; }
}
static int
scanflag(int c, char *f)
{
int fc, count;
if(0<=c && c<NFLAG)
while(*f){
if(*f==' '){
f++;
continue;
}
fc=*f++;
if(*f==':'){
f++;
if(*f<'0' || '9'<*f){ reason = FLAGSYN; return -1; }
count = 0;
while('0'<=*f && *f<='9') count = count*10+*f++-'0';
}
else
count = 0;
if(*f=='['){
do{
f++;
if(*f=='\0'){ reason = FLAGSYN; return -1; }
}while(*f!=']');
f++;
}
if(c==fc)
return count;
}
reason = BADFLAG;
badflag = c;
return -1;
}
void
usage(char *tail)
{
char *s, *t, c;
int count, nflag = 0;
switch(reason){
case RESET:
errs("Flag -");
errc(badflag);
errs(": set twice\n");
break;
case FEWARGS:
errs("Flag -");
errc(badflag);
errs(": too few arguments\n");
break;
case FLAGSYN:
errs("Bad argument to getflags!\n");
break;
case BADFLAG:
errs("Illegal flag -");
errc(badflag);
errc('\n');
break;
}
errs("Usage: ");
errs(cmdname);
for(s = flagarg;*s;){
c=*s;
if(*s++==' ')
continue;
if(*s==':'){
s++;
count = 0;
while('0'<=*s && *s<='9') count = count*10+*s++-'0';
}
else count = 0;
if(count==0){
if(nflag==0)
errs(" [-");
nflag++;
errc(c);
}
if(*s=='['){
s++;
while(*s!=']' && *s!='\0') s++;
if(*s==']')
s++;
}
}
if(nflag)
errs("]");
for(s = flagarg;*s;){
c=*s;
if(*s++==' ')
continue;
if(*s==':'){
s++;
count = 0;
while('0'<=*s && *s<='9') count = count*10+*s++-'0';
}
else count = 0;
if(count!=0){
errs(" [-");
errc(c);
if(*s=='['){
s++;
t = s;
while(*s!=']' && *s!='\0') s++;
errs(" ");
errn(t, s-t);
if(*s==']')
s++;
}
else
while(count--) errs(" arg");
errs("]");
}
else if(*s=='['){
s++;
while(*s!=']' && *s!='\0') s++;
if(*s==']')
s++;
}
}
if(tail){
errs(" ");
errs(tail);
}
errs("\n");
Exit("bad flags");
}
static void
errn(char *s, int count)
{
while(count){ errc(*s++); --count; }
}
static void
errs(char *s)
{
while(*s) errc(*s++);
}
#define NBUF 80
static char buf[NBUF], *bufp = buf;
static void
errc(int c)
{
*bufp++=c;
if(bufp==&buf[NBUF] || c=='\n'){
Write(2, buf, bufp-buf);
bufp = buf;
}
}