home *** CD-ROM | disk | FTP | other *** search
- /* getargs - command line argument processor for C programs
-
- (C) Copyright 1985, Allen I. Holub. All rights reserved.
- This program may be copied for personal, non-profit use only
-
- history...
-
- May 1985 published in Dr. Dobb's Journal #103.
- 19 May 85 Transcribed by James R. Van Zandt */
-
- #include <stdio.h>
- #include <getargs.h>
-
- typedef int (*PFI)();
-
- static char *setarg(argp,linep) ARG *argp; char *linep;
-
- { /* set an argument. argp points at the argument table entry
- corresponding to *linep. Returns linep, updated to point
- past the argument being set */
- ++linep;
- switch(argp->type)
- {case INTEGER: *argp->variable=stoi(&linep); break;
- case BOOLEAN: *argp->variable=1; break;
- case CHARACTER: *argp->variable=*linep++; break;
- case STRING: *(char **)argp->variable=linep; linep=""; break;
- case PROC: (*(PFI)(argp->variable))(linep); linep=""; break;
- default:
- fprintf(stderr,"INTERNAL ERROR: BAD ARGUMENT TYPE\n"); break;
- }
- return (linep);
- }
-
- static ARG *findarg(c,tabp,tabsize) int c,tabsize; ARG *tabp;
-
- { /* return pointer to argument table entry corresponding to
- c (or 0 if c isn't in table). */
-
- for( ; --tabsize>=0; tabp++) {if(tabp->arg==c) return tabp;}
- return 0;
- }
-
- static pr_usage(tabp,tabsize) ARG *tabp; int tabsize;
-
- { /* print the argtab in the form:
- -<arg> <errmsg> (value is <*variable>) */
-
- for(; --tabsize>=0; tabp++)
- {switch(tabp->type)
- {case INTEGER:
- fprintf(stderr,"-%c<num> %-40s (value is ",
- tabp->arg, tabp->errmsg);
- fprintf(stderr,"%-5d)\n",*(tabp->variable));
- break;
- case BOOLEAN:
- fprintf(stderr,"-%c %-40s (value is ",
- tabp->arg, tabp->errmsg);
- fprintf(stderr,"%-5s)\n",*(tabp->variable)
- ?"TRUE":"FALSE");
- break;
- case CHARACTER:
- fprintf(stderr,"-%c<c> %-40s (value is ",
- tabp->arg,tabp->errmsg);
- fprintf(stderr,"%-5c)\n",*(tabp->variable));
- break;
- case STRING:
- fprintf(stderr,"-%c<str> %-40s (value is ",
- tabp->arg, tabp->errmsg);
- fprintf(stderr,"\"%s\")\n", *(char **)tabp->variable);
- break;
- case PROC:
- fprintf(stderr,"-%c<str> %-40s\n",
- tabp->arg,tabp->errmsg);
- break;
- }
- }
- }
-
- #define ERRMSG "Illegal argument \'%c\'. Legal arguments are:\n\n"
-
- int getargs(argc,argv,tabp,tabsize)
- int argc,tabsize;
- char **argv;
- ARG *tabp;
- { /* Process command line arguments, stripping all command line
- switches out of argv. Return a new argc. If an error is found
- exit(1) is called (getargs won't return) and a usage message
- is printed showing all arguments in the table. */
-
- register int nargc;
- register char **nargv, *p;
- register ARG *argp;
-
- nargc=1;
- for (nargv=++argv; --argc>0; argv++)
- {if(**argv!='-') {*nargv++=*argv; nargc++;}
- else
- {p=(*argv)+1;
- while(*p)
- {if(argp=findarg(*p,tabp, tabsize)) {p=setarg(argp,p);}
- else
- {fprintf(stderr,ERRMSG,*p);
- pr_usage(tabp,tabsize);
- exit(1);
- }
- }
- }
- }
- return nargc;
- }
-
- #define islower(c) ('a'<=(c)&&(c)<='z')
- #define toupper(c) (islower(c)?(c)-('a'-'A'):(c))
-
- int stoi(instr) register char **instr;
- { /* Convert string to integer. If string starts with 0x it is
- interpreted as a hex number, else if it starts with a 0 it
- is octal, else it is decimal. Conversion stops on encountering
- the first character which is not a digit in the indicated
- radix. *instr is updated to point past the end of the number. */
-
- register int num=0;
- register char *str;
- int sign=1;
-
- str=*instr;
- while(*str==' ' || *str=='\t' || *str=='\n') {str++;}
- if(*str=='-') {sign=-1; str++;}
- if(*str=='0')
- {++str;
- if(*str=='x' || *str=='X')
- {str++;
- while( ('0'<=*str && *str<='9') ||
- ('a'<=*str && *str<='f') ||
- ('A'<=*str && *str<='F') )
- {num=num*16+
- (('0'<=*str && *str<='9') ?
- *str-'0' :
- toupper(*str)-'A'+10);
- str++;
- }
- }
- else {while('0'<=*str && *str<='7') {num = num*8+ *str++ - '0';}}
- }
- else {while('0'<=*str && *str<='9') {num=num*10+ *str++-'0';}}
- *instr=str;
- return (num*sign);
- }
-