aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/getflags.c82
-rw-r--r--cmd/usage.c72
-rw-r--r--man8/getflags.877
-rw-r--r--src/cmd/getflags/funcgetflags.c267
-rw-r--r--src/cmd/getflags/getflags.c199
-rw-r--r--src/cmd/getflags/getflags.h10
-rw-r--r--src/cmd/getflags/mkfile9
7 files changed, 231 insertions, 485 deletions
diff --git a/cmd/getflags.c b/cmd/getflags.c
new file mode 100644
index 00000000..bb0edf28
--- /dev/null
+++ b/cmd/getflags.c
@@ -0,0 +1,82 @@
+#include <u.h>
+#include <libc.h>
+
+void
+usage(void)
+{
+ print("status=usage\n");
+ exits(0);
+}
+
+char*
+findarg(char *flags, Rune r)
+{
+ char *p;
+ Rune rr;
+
+ for(p=flags; p!=(char*)1; p=strchr(p, ',')+1){
+ chartorune(&rr, p);
+ if(rr == r)
+ return p;
+ }
+ return nil;
+}
+
+int
+countargs(char *p)
+{
+ int n;
+
+ n = 1;
+ while(*p == ' ')
+ p++;
+ for(; *p && *p != ','; p++)
+ if(*p == ' ' && *(p-1) != ' ')
+ n++;
+ return n;
+}
+
+void
+main(int argc, char *argv[])
+{
+ char *flags, *p, buf[512];
+ int i, n;
+ Fmt fmt;
+
+ quotefmtinstall();
+ argv0 = argv[0]; /* for sysfatal */
+
+ flags = getenv("flagfmt");
+ if(flags == nil){
+ fprint(2, "$flagfmt not set\n");
+ print("exit 'missing flagfmt'");
+ exits(0);
+ }
+
+ fmtfdinit(&fmt, 1, buf, sizeof buf);
+ for(p=flags; p!=(char*)1; p=strchr(p, ',')+1)
+ fmtprint(&fmt, "flag%.1s=()\n", p);
+ ARGBEGIN{
+ default:
+ if((p = findarg(flags, ARGC())) == nil)
+ usage();
+ p += runelen(ARGC());
+ if(*p == ',' || *p == 0){
+ fmtprint(&fmt, "flag%C=1\n", ARGC());
+ break;
+ }
+ n = countargs(p);
+ fmtprint(&fmt, "flag%C=(", ARGC());
+ for(i=0; i<n; i++)
+ fmtprint(&fmt, "%s%q", i ? " " : "", EARGF(usage()));
+ fmtprint(&fmt, ")\n");
+ }ARGEND
+
+ fmtprint(&fmt, "*=(");
+ for(i=0; i<argc; i++)
+ fmtprint(&fmt, "%s%q", i ? " " : "", argv[i]);
+ fmtprint(&fmt, ")\n");
+ fmtprint(&fmt, "status=''\n");
+ fmtfdflush(&fmt);
+ exits(0);
+}
diff --git a/cmd/usage.c b/cmd/usage.c
new file mode 100644
index 00000000..b064feaf
--- /dev/null
+++ b/cmd/usage.c
@@ -0,0 +1,72 @@
+#include <u.h>
+#include <libc.h>
+
+void
+main(int argc, char **argv)
+{
+ Fmt fmt;
+ char buf[512];
+ char *argv0, *args, *flags, *p, *p0;
+ int single;
+ Rune r;
+
+ argv0 = getenv("0");
+ if(argv0 == nil) {
+ if(argc > 1)
+ argv0 = argv[1];
+ else
+ argv0 = "unknown-program-name";
+ }
+ if((p = strrchr(argv0, '/')) != nil)
+ argv0 = p+1;
+ flags = getenv("flagfmt");
+ args = getenv("args");
+
+ if(argv0 == nil){
+ fprint(2, "aux/usage: $0 not set\n");
+ exits("$0");
+ }
+ if(flags == nil)
+ flags = "";
+ if(args == nil)
+ args = "";
+
+ fmtfdinit(&fmt, 2, buf, sizeof buf);
+ fmtprint(&fmt, "usage: %s", argv0);
+ if(flags[0]){
+ single = 0;
+ for(p=flags; *p; ){
+ p += chartorune(&r, p);
+ if(*p == ',' || *p == 0){
+ if(!single){
+ fmtprint(&fmt, " [-");
+ single = 1;
+ }
+ fmtprint(&fmt, "%C", r);
+ if(*p == ',')
+ p++;
+ continue;
+ }
+ while(*p == ' ')
+ p++;
+ if(single){
+ fmtprint(&fmt, "]");
+ single = 0;
+ }
+ p0 = p;
+ p = strchr(p0, ',');
+ if(p == nil)
+ p = "";
+ else
+ *p++ = 0;
+ fmtprint(&fmt, " [-%C %s]", r, p0);
+ }
+ if(single)
+ fmtprint(&fmt, "]");
+ }
+ if(args)
+ fmtprint(&fmt, " %s", args);
+ fmtprint(&fmt, "\n");
+ fmtfdflush(&fmt);
+ exits("usage");
+}
diff --git a/man8/getflags.8 b/man8/getflags.8
new file mode 100644
index 00000000..50274d40
--- /dev/null
+++ b/man8/getflags.8
@@ -0,0 +1,77 @@
+.TH GETFLAGS 8
+.SH NAME
+getflags, usage \- command-line parsing for shell scripts
+.SH SYNOPSIS
+.B getflags $*
+.PP
+.B usage [ progname ]
+.SH DESCRIPTION
+.I Getflags
+parses the options in its command-line arguments
+according to the environment variable
+.BR $flagfmt .
+This variable should be a list of comma-separated options.
+Each option can be a single letter, indicating that it does
+not take arguments, or a letter followed by the space-separated
+names of its arguments.
+.I Getflags
+prints an
+.IR rc (1)
+script on standard output which initializes the
+environment variable
+.BI $flag x
+for every option mentioned in
+.BR $flagfmt .
+If the option is not present on the command-line, the script
+sets that option's flag variable to an empty list.
+Otherwise, the script sets that option's flag variable with
+a list containing the option's arguments or,
+if the option takes no arguments,
+with the string
+.BR 1 .
+The script also sets the variable
+.B $*
+to the list of arguments following the options.
+The final line in the script sets the
+.B $status
+variable, to the empty string on success
+and to the string
+.B usage
+when there is an error parsing the command line.
+.PP
+.I Usage
+prints a usage message to standard error.
+It creates the message using
+.BR $flagfmt ,
+as described above,
+.BR $args ,
+which should contain the string to be printed explaining
+non-option arguments,
+and
+.BR $0 ,
+the program name
+(see
+.IR rc (1)).
+If run under
+.IR sh (1),
+which does not set
+.BR $0 ,
+the program name must be given explicitly on the command line.
+.SH EXAMPLE
+Parse the arguments for
+.IR leak (1):
+.IP
+.EX
+flagfmt='b,s,f binary,r res,x width'
+args='name | pid list'
+if(! ifs=() eval `{getflags $*} || ~ $#* 0){
+ usage
+ exit usage
+}
+.EE
+.SH SOURCE
+.B \*9/src/cmd/getflags.c
+.br
+.B \*9/src/cmd/usage.c
+.SH SEE ALSO
+.IR arg (3)
diff --git a/src/cmd/getflags/funcgetflags.c b/src/cmd/getflags/funcgetflags.c
index d0686679..e69de29b 100644
--- a/src/cmd/getflags/funcgetflags.c
+++ b/src/cmd/getflags/funcgetflags.c
@@ -1,267 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <ctype.h>
-#include "getflags.h"
-
-char **flag[NFLAG];
-char cmdline[NCMDLINE+1];
-char *cmdname;
-char *flagset[];
-char *flagset[]={"<flag>"};
-static char *flagarg="";
-static void reverse(char **, char **);
-static int scanflag(int, char *);
-static int reason;
-#define RESET 1
-#define ARGCCOUNT 2
-#define FLAGSYN 3
-#define BADFLAG 4
-static int badflag;
-char *getflagsargv[NGETFLAGSARGV+2]; /* original argv stored here for people who need it */
-
-int
-getflags(int argc, char *argv[], char *flags)
-{
- char *s, *t;
- int i, j, c, count;
- flagarg=flags;
- if(cmdname==0){
- cmdname=argv[0];
- for(i=0;i!=argc && i!=NGETFLAGSARGV;i++) getflagsargv[i]=argv[i];
- if(argc>NGETFLAGSARGV) getflagsargv[i++]="...";
- getflagsargv[i]=0;
- }
- s=cmdline;
- for(i=0;i!=argc;i++){
- for(t=argv[i];*t;)
- if(s!=&cmdline[NCMDLINE])
- *s++=*t++;
- else
- break;
- if(i!=argc-1 && s!=&cmdline[NCMDLINE])
- *s++=' ';
- }
- *s='\0';
- i=1;
- while(i!=argc && argv[i][0]=='-'){
- s=argv[i]+1;
- if(*s=='\0'){ /* if argument is "-", stop scanning and delete it */
- for(j=i+1;j<=argc;j++)
- argv[j-1]=argv[j];
- return argc-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=ARGCCOUNT;
- 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;
-}
-
-void
-static reverse(char **p, char **q)
-{
- register 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(!isdigit((uchar)*f)){ reason=FLAGSYN; return -1; }
- count=strtol(f, &f, 10);
- }
- else
- count=0;
- if(*f=='['){
- int depth=1;
- do{
- f++;
- if(*f=='\0'){ reason=FLAGSYN; return -1; }
- if(*f=='[') depth++;
- if(*f==']') depth--;
- }while(depth>0);
- f++;
- }
- if(c==fc) return count;
- }
- reason=BADFLAG;
- badflag=c;
- return -1;
-}
-
-static void errn(char *, int), errs(char *), errc(int);
-
-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 ARGCCOUNT:
- 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=strtol(s, &s, 10);
- }
- else count=0;
- if(count==0){
- if(nflag==0) errs(" [-");
- nflag++;
- errc(c);
- }
- if(*s=='['){
- int depth=1;
- s++;
- for(;*s!='\0' && depth>0; s++)
- if (*s==']') depth--;
- else if (*s=='[') depth++;
- }
- }
- if(nflag) errs("]");
- for(s=flagarg;*s;){
- c=*s;
- if(*s++==' ') continue;
- if(*s==':'){
- s++;
- count=strtol(s, &s, 10);
- }
- else count=0;
- if(count!=0){
- errs(" [-");
- errc(c);
- if(*s=='['){
- int depth=1;
- s++;
- t=s;
- for(;*s!='\0' && depth>0; s++)
- if (*s==']') depth--;
- else if (*s=='[') depth++;
- errs(" ");
- errn(t, s-t);
- }
- else
- while(count--) errs(" arg");
- errs("]");
- }
- else if(*s=='['){
- int depth=1;
- s++;
- for(;*s!='\0' && depth>0; s++)
- if (*s==']') depth--;
- else if (*s=='[') depth++;
- }
- }
- if(tail){
- errs(" ");
- errs(tail);
- }
- errs("\n");
- exits("usage");
-}
-
-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;
- }
-}
-
-#ifdef TEST
-#include <stdio.h>
-main(int argc, char *argv[])
-{
- int c, i, n;
- if(argc<3){
- fprint(2, "Usage: %s flags cmd ...\n", argv[0]);
- exits("usage");
- }
- n=getflags(argc-2, argv+2, argv[1]);
- if(n<0) usage("...");
- putchar('\n');
- for(c=0;c!=128;c++) if(flag[c]){
- print("\t-.%c. ", c);
- n=scanflag(c, argv[1]);
- for(i=0;i!=n;i++) print(" <%s>", flag[c][i]);
- putchar('\n');
- }
-}
-#endif
diff --git a/src/cmd/getflags/getflags.c b/src/cmd/getflags/getflags.c
index 781da33c..e69de29b 100644
--- a/src/cmd/getflags/getflags.c
+++ b/src/cmd/getflags/getflags.c
@@ -1,199 +0,0 @@
-/*% cyntax % && cc -go # %
- * getflags: process flags for command files
- * Usage: ifs='' eval `{getflags [-s] flagfmt [arg ...]} # rc
- * Usage: IFS= eval `getflags -b [-s] flagfmt [arg...]` # Bourne shell
- * -b means give Bourne-shell compatible output
- */
-#include <u.h>
-#include <libc.h>
-#include "getflags.h"
-
-/* predefine functions */
-void bourneprint(int, char *[]);
-void bournearg(char *);
-void rcprint(int, char *[]);
-void usmsg(char *);
-int count(int, char *);
-void rcarg(char *);
-
-void
-main(int argc, char *argv[])
-{
- int bourne;
- argc=getflags(argc, argv, "b");
- if(argc<2) usage("flagfmt [arg ...]");
- bourne=flag['b']!=0;
- flag['b']=0;
- if((argc=getflags(argc-1, argv+1, argv[1]))<0){
- usmsg(argv[1]);
- exits(0);
- }
- if(bourne) bourneprint(argc, argv);
- else rcprint(argc, argv);
- exits(0);
-}
-void
-bourneprint(int argc, char *argv[])
-{
- register int c, i, n;
- for(c=0;c!=NFLAG;c++) if(flag[c]){
- print("FLAG%c=", c); /* bug -- c could be a bad char */
- n=count(c, argv[1]);
- if(n==0)
- print("1\n");
- else{
- print("'");
- bournearg(flag[c][0]);
- for(i=1;i!=n;i++){
- print(" ");
- bournearg(flag[c][i]);
- }
- print("'\n");
- }
- }
- print("set --");
- for(c=1;c!=argc;c++){
- print(" ");
- bournearg(argv[c+1]);
- }
- print("\n");
-}
-void
-bournearg(char *s)
-{
- for(;*s;s++)
- if(*s=='\'')
- print("'\\''");
- else
- print("%c", *s);
-}
-void
-rcprint(int argc, char *argv[])
-{
- int c, i, n;
- for(c=0;c!=NFLAG;c++) if(flag[c]){
- print("FLAG%c=", c); /* bug -- c could be a bad char */
- n=count(c, argv[1]);
- if(n==0)
- print("''");
- else if(n==1)
- rcarg(flag[c][0]);
- else{
- print("(");
- rcarg(flag[c][0]);
- for(i=1;i!=n;i++){
- print(" ");
- rcarg(flag[c][i]);
- }
- print(")");
- }
- print("\n");
- }
- print("*=");
- if(argc==1) print("()");
- else if(argc==2) rcarg(argv[2]);
- else{
- print("(");
- rcarg(argv[2]);
- for(c=2;c!=argc;c++){
- print(" ");
- rcarg(argv[c+1]);
- }
- print(")");
- }
- print("\n");
-}
-void
-usmsg(char *flagarg)
-{
- char *s, *t, c;
- int count, nflag=0;
- print("echo Usage: $0'");
- for(s=flagarg;*s;){
- c=*s;
- if(*s++==' ') continue;
- if(*s==':')
- count = strtol(s+1, &s, 10);
- else count=0;
- if(count==0){
- if(nflag==0) print(" [-");
- nflag++;
- print("%c", c);
- }
- if(*s=='['){
- int depth=1;
- s++;
- for(;*s!='\0' && depth>0; s++)
- if (*s==']') depth--;
- else if (*s=='[') depth++;
- }
- }
- if(nflag) print("]");
- for(s=flagarg;*s;){
- c=*s;
- if(*s++==' ') continue;
- if(*s==':')
- count = strtol(s+1, &s, 10);
- else count=0;
- if(count!=0){
- print(" [-");
- print("%c", c);
- if(*s=='['){
- int depth=1;
- s++;
- t=s;
- for(;*s!='\0' && depth>0; s++)
- if (*s==']') depth--;
- else if (*s=='[') depth++;
- print(" ");
- write(1, t, s - t);
- }
- else
- while(count--) print(" arg");
- print("]");
- }
- else if(*s=='['){
- int depth=1;
- s++;
- for(;*s!='\0' && depth>0; s++)
- if (*s==']') depth--;
- else if (*s=='[') depth++;
- }
- }
- print("' $usage;\n");
- print("exit 'usage'\n");
-}
-int
-count(int flag, char *flagarg)
-{
- char *s, c;
- int n;
- for(s=flagarg;*s;){
- c=*s;
- if(*s++==' ') continue;
- if(*s==':')
- n = strtol(s+1, &s, 10);
- else n=0;
- if(*s=='['){
- int depth=1;
- s++;
- for(;*s!='\0' && depth>0; s++)
- if (*s==']') depth--;
- else if (*s=='[') depth++;
- }
- if(c==flag) return n;
- }
- return -1; /* never happens */
-}
-void
-rcarg(char *s)
-{
- if(*s=='\0' || strpbrk(s, "\n \t#;&|^$=`'{}()<>?")){
- print("\'");
- for(;*s;s++)
- if(*s=='\'') print("''");
- else print("%c", *s);
- print("\'");
- }
- else print("%s", s);
-}
diff --git a/src/cmd/getflags/getflags.h b/src/cmd/getflags/getflags.h
index ca7167b2..e69de29b 100644
--- a/src/cmd/getflags/getflags.h
+++ b/src/cmd/getflags/getflags.h
@@ -1,10 +0,0 @@
-#define NFLAG 128
-#define NCMDLINE 512
-#define NGETFLAGSARGV 256
-extern char **flag[NFLAG];
-extern char cmdline[NCMDLINE+1];
-extern char *cmdname;
-extern char *flagset[];
-extern char *getflagsargv[NGETFLAGSARGV+2];
-int getflags(int, char *[], char *);
-void usage(char *);
diff --git a/src/cmd/getflags/mkfile b/src/cmd/getflags/mkfile
index fab59aa5..e69de29b 100644
--- a/src/cmd/getflags/mkfile
+++ b/src/cmd/getflags/mkfile
@@ -1,9 +0,0 @@
-<$PLAN9/src/mkhdr
-
-TARG=getflags
-OFILES=\
- getflags.$O\
- funcgetflags.$O\
-
-<$PLAN9/src/mkone
-