henesyinit from p9fd787fda5 years agoHistory
267 lines · 4.5 KB · C
RawDownload
#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	4static int badflag;char *getflagsargv[NGETFLAGSARGV+2];	/* original argv stored here for people who need it */ intgetflags(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;} voidstatic reverse(char **p, char **q){	register 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(!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); 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 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 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;	}} #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