Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!njin!princeton!notecnirp!sarantos From: sarantos@notecnirp.Princeton.EDU (Sarantos Kapidakis) Newsgroups: comp.lang.c Subject: Re: getopt Message-ID: <17697@princeton.Princeton.EDU> Date: 16 Jun 89 05:36:47 GMT References: <782@crdgw1.crd.ge.com> <13730@haddock.ima.isc.com> Sender: news@princeton.Princeton.EDU Reply-To: sarantos@notecnirp.UUCP (Sarantos Kapidakis) Organization: Princeton University CS Dept Lines: 187 Here is my version of getopt, which have much more flexibility than the standard one, and can parse the arguments more than one times. Examples and documentation can be produced by different preprocessor options: #if defined(DOC) The Getopt routine helps with finding the options from the command line. It takes 7 arguments: argc, argv: The argument counter and vector, as in the main program. The argv[0] is used as the program name, in case of error. pargc, pargv: Pointers to (so as their values can be updated) the argument index and position in the current argument. In the usual usage, in the first call to this routine, *pargc will be 1, indicating that the next argument to be processed is the first argument (after the program name), and **pargv=`\0`, indicating we finished processing the previous argument. In any case, if **pargv != '\0', the next letter **pargv is considered as the next option, while otherwise, a '-' is expected to be found as the first character of the next argument is processed. Normally, the client never has to change *pargv, and *pargc. par: If the option found has arguments, the first of these is stored in *par. If more arguments, say n were asked, argument i (1 Getopt(argc, argv, /*INOUT*/ pargc, /*INOUT*/ pargv, /*OUT*/ ppar, ostr1, ostr2) int argc; /* argument counter */ char **argv; /* argument vector */ int *pargc; /* the &possition to be read next on the argument vector */ char **pargv; /* the &possition to be read next on the current argument */ char **ppar; /* any returned &value (string) for the option found */ char *ostr1, *ostr2; /* the string of options */ { extern char *index(); char sop[2]; char *dummy; /* dummy parameter - ignored options */ register char **pstr; /* the real first parameter address */ register char *optr; /* option letter list index */ register int ochar; /* character checked for validity */ /* update scanning pointer */ for(;;){ if (**pargv == '\0' && (*pargc >= argc || (*pargv=argv[*pargc]) == NULL || **pargv != '-' || *++*pargv=='\0' || **pargv == '-' && (++*pargc))) { *pargv = ""; return(EOF); } if ((ochar = *(*pargv)++) == ':' || ochar == '*' || ochar == '?' || (ostr1==NULL || (pstr= ppar, optr=index(ostr1,ochar))==NULL) && (ostr2==NULL || (pstr= &dummy, optr=index(ostr2,ochar))==NULL)) { if (**pargv=='\0') ++*pargc ; sop[0]=ochar; sop[1]='\0'; wrong("illegal option: '%s'", sop); return('?'); } if (*++optr != ':' && *optr != '?') { /* don't need next argument */ if (*optr=='*' && *(*pstr = *pargv)!='\0') *pargv=""; if (**pargv=='\0') ++*pargc ; } else { /* need argument */ ++*pargc; if (*(*pstr = *pargv) != '\0') *pargv = ""; else *pstr = (*pargc < argc)? argv[(*pargc)++]: (--optr, (char *) NULL); while(*++optr == ':' || *optr == '?') if (++*pargc > argc && *optr == ':') { sop[0]=ochar; sop[1]='\0'; wrong("argument missing from option '%s'", sop); return('?'); } } if (pstr==ppar) return(ochar); /* dump back option letter */ } } /*FUNCTIONS*/ #endif #if defined(DOC) || defined(SHELL) a.out -vvargument -a argumenttoa -P -x 1 2 3 file1 file2 a.out -aargumenttoa -PargumenttoP -v varg -x 1 2 3 file1 file2 a.out -a argumenttoa -x1 2 3 file1 file2 a.out -P file1 file2 #endif #if defined(DOC) || defined(TEST) || defined(PROGRAM) #if !defined(DOC) #include #endif char *progname; char *opa="default aa", *opc=NULL, *opP=NULL; char *opx1=NULL, *opx2=NULL, *opx3=NULL; char *opy1=NULL, *opy2=NULL, *opy3=NULL; int opA=0; main(argc,argv) int argc ; char **argv ; { int optc=1; char *optr="", *par; int c, i; progname=argv[0]; while ((c=Getopt(argc, argv, &optc, &optr, &par, "Aa?P*c:x:::y:??", "v:"))!=EOF) switch (c) { /* 'v' will never be returned. It is just ignored */ case'a':opa=par ;break; /* may have 1 argument */ case'c':opc=par ;break; case'A':opA= !opA; break; /* needs no argument */ case'P':opP=par;break; /* may have an argument (if -Parg) or may not (if -P) */ case'x':opx1=par; opx2=argv[optc-2]; opx3=argv[optc-1]; break; /* needs 3 arguments */ case'y':opy1=par; if (optc-argc < 2) opy2=argv[optc-2]; if (optc-argc < 1) opy3=argv[optc-1]; break; /* needs 1 argument and may have up to 3 arguments */ default:exit(2); } for(i=0 ; i