Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#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;
        }
}