everson@CompSci.Bristol.AC.UK (Phill Everson ) (06/13/89)
Following the getopt()/egetopt() discussions here in early 1988 ... 2 questions about getopt()/egetopt() ... 1) Is there any way of allowing getopt() to parse the following: foo -Wt name -x a ... 2) Or foo -x a b -y a ... Obviously, I want to be able to combine the above. I suspect 2) is possible with getopt() somehow, but for 1) it may be necessary to modify egetopt(). Has anyone done this before or has anyone any ideas about how it could be done? I'd prefer email ... Thanks in advance, Phill Everson Medical Imaging Dept Comp Sci University of Bristol, UK
davidsen@sungod.crd.ge.com (William Davidsen) (06/15/89)
I have a program which needs an option which may have either a default
value or a specific value. ie. "-c" or "-c4" would be typical. I would
like to use getopt to read the values.
The question: is there a tricky way to use the existing getopt, or
do I have to make an extended version? I would like to use the existing
interface if possible.
In the meantime, I took a P.D. version and added another option
qualifier, #, indicating an optional numeric argument. The logic
requires that the numeric value follow the option inducer without a
space, as "-c2" but not "-c 2". I set optarg to NULL if no value is
specified. I renamed the procedure, obviously, to prevent calling the
common version if the software is ported. Since the character # could be
an option in some software, my new version is not a superset.
I have seen references to "eoptarg" in this group, but can't find a
man entry for it on SunOS or Ultrix, so I assume it's either proprietary
or P.D. we don't have it.
bill davidsen (davidsen@crdos1.crd.GE.COM)
{uunet | philabs}!crdgw1!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -mekarl@haddock.ima.isc.com (Karl Heuer) (06/16/89)
In article <782@crdgw1.crd.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes: >I have a program which needs an option which may have either a default >value or a specific value. ie. "-c" or "-c4" would be typical. I would >like to use getopt to read the values. This doesn't fit the Official Arg Passing Style, so even if you use a hook a kludge into getopt(), it isn't guaranteed to always work. > In the meantime, I took a P.D. version and added another option >qualifier, #, indicating an optional numeric argument. Why restrict it to numeric? I use optional non-numeric arguments all the time. If you're going to add the optional-argument hack, you might as well let it return (in optarg) whatever string immediately followed the keyletter, including the empty string in the case of "-c". (No reason for it ever to return NULL; that would make an unnecessary special case.) >Since the character # could be an option in some software, my new version is >not a superset. "-#" is a not uncommon debugging option. I think ";" is a better choice, since it does half of what ":" does%, and because I don't know of any code that uses "-;" as an option. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint ________ % This pun works only if you pronounce them as "semicolon" and "colon".
sarantos@notecnirp.Princeton.EDU (Sarantos Kapidakis) (06/16/89)
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<i<=n) is accessed
as agrv[(*pargc)-n-1+i]. This is easily understand from the fact that
argv[*pargc] is always the next argument to be processed, so the last
argument found was argv[(*pargc)-1], and so on.
The first argument has a special treatment, because it may start from
the middle of the real argument, while the others start always in the
beginning.
This variable is not changed if the option found has no arguments.
ostr1: The string containing the option letters, and possibly some of
the control characters ':', '?' and '*'.
The option-letters, followed by a '*' means that this
option may have an argument adjacent to it. If no such
argument exists, the routine consider the empty string
as its argument (and never the next argument in the list).
The option-letters, followed by a number of ':' or '?' means that
this option needs so many arguments. The first argument may
be adjacent to the option letter, or a separate argument if
if the option was the last character in that argument.
*ppar is assigned the address of the first argument, or NULL
if there are no arguments at all.
The rest of the required arguments (if any), are the next
arguments in the argv list, upto argv[(*pargc)-1].
An error occurs if not enough arguments were found, when the
':' was used (but not when the '*' was used).
In any case, *pargc is always increased one for each expected
argument, so that its difference from argc expresses the number
of arguments still availiable (or missing for negative value).
After returning from any of these cases(an option found followed
by a ':', '?' or '*'), **pargv is always '\0', since the last
argument was consumed entirelly.
ostr2: The string containing some additional option letters, in the same
format as ostr1, and which are just going to be ignored and passed by,
by the procedure. In most cases this string is the empty string.
The routine returns the option found, or '?' for error
and EOF for no option found. Then the arguments to the
program are from argv[*pargc] up to argv[argc-1].
example:
we can call the following program as follows,
or in many other combinations:
#endif
#if !(defined(DOC) || defined(DEFS) || defined(SHELL) ||\
defined(PROGRAM) || defined(DATA))
/*FUNCTIONS*/
/* got this off net.sources, and improve it */
#include <stdio.h>
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 <stdio.h>
#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<argc ; i++) printf("%s%c", argv[i], (i==argc-1)?'\n':' ');
printf("%c: %s\n", 'A', opA? "true": "false");
if (opP != NULL)printf("%c: %s\n", 'P', opP);
if (opc != NULL)printf("%c: %s\n", 'c', opc);
if (opa != NULL)printf("%c: %s\n", 'a', opa);
if (opx1 != NULL)printf("%c: %s %s %s\n", 'x', opx1, opx2, opx3);
if (opy1 != NULL)printf("%c: %s", 'y', opy1);
if (opy2 != NULL)printf(" %s", opy2);
if (opy3 != NULL)printf(" %s", opy3);
if (opy1 != NULL)printf("\n");
printf("optc=%d, argc=%d\n file arguments:", optc, argc);
while(optc < argc) printf("%s ", argv[optc++]);
printf("\noptc=%d, argc=%d\n", optc, argc);
exit(0);
}
#include "error.c"
#endifdavidsen@sungod.crd.ge.com (William Davidsen) (06/16/89)
I would like to thank all the people who posted or mailed comments
about my getopt question. I am incorporating some of those ideas and
will be posting a source and man page for the result. I am using the
character ? for the optional argument character. Since getopt returns ?
to indicate an unknown option, there won't be any existing programs
using it, and the extended getopt will work with existing programs.
I guess anything with a man page should be posted to sources.misc
rather than alt.sources, so look for it soon.
bill davidsen (davidsen@crdos1.crd.GE.COM)
{uunet | philabs}!crdgw1!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -mejmm@eci386.uucp (John Macdonald) (06/19/89)
In article <13730@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: }In article <782@crdgw1.crd.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes: }>I have a program which needs an option which may have either a default }>value or a specific value. ie. "-c" or "-c4" would be typical. I would }>like to use getopt to read the values. } }This doesn't fit the Official Arg Passing Style, so even if you use a hook a }kludge into getopt(), it isn't guaranteed to always work. } } [...] } }"-#" is a not uncommon debugging option. I think ";" is a better choice, }since it does half of what ":" does%, and because I don't know of any code }that uses "-;" as an option. } }Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint }________ }% This pun works only if you pronounce them as "semicolon" and "colon". Surely it would be better (except for punning purposes) to use -? to indicate an optional argument. Getopt precludes having a useful ? option since the return of ? indicates an error occurred. The ? is also suggests that the option is "conditionally present".
bobmon@iuvax.cs.indiana.edu (RAMontante) (06/21/89)
jmm@eci386.UUCP (John Macdonald) <1989Jun19.153426.21238@eci386.uucp> : -} -}"-#" is a not uncommon debugging option. I think ";" is a better choice, -}since it does half of what ":" does%, and because I don't know of any code -}that uses "-;" as an option. -} -}Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint -}________ -}% This pun works only if you pronounce them as "semicolon" and "colon". - -Surely it would be better (except for punning purposes) to use -? to indicate -an optional argument. Getopt precludes having a useful ? option since the -return of ? indicates an error occurred. The ? is also suggests that the -option is "conditionally present". I believe that some command-line interpreters (viz., csh?) will attempt to expand `?' as a wildcard unless it's escaped, at which point using it becomes a nuisance. I'm not too comfortable with `;' and `:', either, as some CLI, somewhere, may treat these as statement delimiters or something. Letters seem like the safest bet to me....