Logo Search packages:      
Sourcecode: 9base version File versions  Download package

getflags.c

/*% cyntax -DTEST % && cc -DTEST -go # %
 */
#include "rc.h"
#include "getflags.h"
#include "fns.h"
char *flagset[]={"<flag>"};
char **flag[NFLAG];
char cmdline[NCMDLINE+1];
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, *t;
      int i, j, c, count;
      flagarg=flags;
      if(cmdname==0) cmdname=argv[0];
      s=cmdline;
      for(i=0;i!=argc;i++){
            for(t=argv[i];*t;t++)
                  if(s!=&cmdline[NCMDLINE])
                        *s++=*t;
            if(i!=argc-1 && s!=&cmdline[NCMDLINE])
                  *s++=' ';
      }
      *s='\0';
      i=1;
      while(i!=argc){
            if(argv[i][0]!='-' || argv[i][1]=='\0'){
                  if(stop) 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;
      }
}

Generated by  Doxygen 1.6.0   Back to index