tnew - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit acd47706189b842db4894473168a4dded897e245
 (DIR) parent 92fd3a6469b82d5ed55b32049a9400852cd2cc0f
 (HTM) Author: rsc <devnull@localhost>
       Date:   Wed, 10 Aug 2005 18:00:38 +0000
       
       new
       
       Diffstat:
         A src/cmd/getflags/funcgetflags.c     |     267 +++++++++++++++++++++++++++++++
       
       1 file changed, 267 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/getflags/funcgetflags.c b/src/cmd/getflags/funcgetflags.c
       t@@ -0,0 +1,267 @@
       +#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(*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