POSIX.2 requires special behavior if the first character of the optstring

argument is a colon.
Updated the manpage to reflect the above change, and expanded the example to
the one used by the POSIX.2 rationale, as it more clearly explains how
the new behavior is to be used.
The manpage should be rewritten --- it is much more confusing than it
should be.
This commit is contained in:
jtc 1993-10-12 21:52:45 +00:00
parent 247aa8acb6
commit c5ff256532
2 changed files with 109 additions and 51 deletions

View File

@ -30,7 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" from: @(#)getopt.3 6.16 (Berkeley) 4/19/91
.\" $Id: getopt.3,v 1.3 1993/09/14 22:37:24 jtc Exp $
.\" $Id: getopt.3,v 1.4 1993/10/12 21:52:47 jtc Exp $
.\"
.Dd April 19, 1991
.Dt GETOPT 3
@ -39,7 +39,7 @@
.Nm getopt
.Nd get option letter from argv
.Sh SYNOPSIS
.Fd #include <stdlib.h>
.Fd #include <unistd.h>
.Vt extern char *optarg
.Vt extern int optind
.Vt extern int opterr
@ -95,8 +95,7 @@ The
.Fn getopt
function
returns \-1
when the argument list is exhausted, or a non-recognized
option is encountered.
when the argument list is exhausted.
The interpretation of options in the argument list may be cancelled
by the option
.Ql --
@ -108,44 +107,100 @@ argument),
.Fn getopt
returns \-1.
.Sh DIAGNOSTICS
If the
If the
.Fn getopt
function encounters a character not found in the string
.Va optarg
or detects
a missing option argument
it writes error message
.Ql ?
to the
.Em stderr .
Setting
function encounters an option character that is not contained in
.Fa optstring ,
it returns a question mark
.Pq ?
character.
If it detects a missing option argument, it returns a colon
.Pq \:
character if the first character of
.Fa optstring
is a colon, otherwise it returns a question mark.
In either case, a diagnostic message is written to
.Em stderr
unless the application has set
.Va opterr
to a zero will disable these error messages.
to zero or the first character of
.Fa optstring
is a colon.
.Sh EXAMPLE
.\" The following example comes from section E.9.7 of the IEEE 1003.2-90
.\" standard (POSIX.2).
The following code fragment shows how one might process the arguments for
a utility that can take the mutually exclusive options
.Em a
and
.Em b
and the options
.Em f
and
.Em o ,
both of which require arguments:
.Pp
.Bd -literal -compact
extern char *optarg;
extern int optind;
int bflag, ch, fd;
#include <unistd.h>
bflag = 0;
while ((ch = getopt(argc, argv, "bf:")) != -1)
switch(ch) {
case 'b':
bflag = 1;
break;
case 'f':
if ((fd = open(optarg, O_RDONLY, 0)) < 0) {
(void)fprintf(stderr,
"myname: unable to read file %s.\en", optarg);
exit(1) ;
int
main (argc, argv)
int argc;
char *argv[];
{
int c, bflg, aflg, errflg = 0;
char *ifile, *ofile;
extern char *optarg;
extern int optind, optopt;
. . .
while ((c = getopt(argc, argv, ":abf:o:")) != -1) {
switch(ch) {
case 'a':
if (bflg)
errflg = 1;
else
aflg = 1;
break;
case 'b':
if (aflg)
errflg = 1;
else
bflg = 1;
break;
case 'f':
ifile = optarg;
break;
case 'o':
ofile = optarg;
break;
case ':': /* -f or -o without option-arg */
fprintf (stderr,
"Option -%c requires an option-argument\\n",
optopt);
errflg = 1;
break;
case '?':
fprintf (stderr,
"Unrecognized option: -%c\\n",
optopt);
errflg = 1;
break;
}
break;
case '?':
default:
usage();
}
if (errflg) {
fprintf (stderr, "usage: . . .\\n");
exit (2);
}
argc -= optind;
argv += optind;
. . .
}
argc -= optind;
argv += optind;
.Ed
.Sh STANDARDS
The

View File

@ -33,7 +33,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)getopt.c 4.13 (Berkeley) 2/23/91";*/
static char *rcsid = "$Id: getopt.c,v 1.4 1993/09/14 22:37:26 jtc Exp $";
static char *rcsid = "$Id: getopt.c,v 1.5 1993/10/12 21:52:45 jtc Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@ -43,11 +43,12 @@ static char *rcsid = "$Id: getopt.c,v 1.4 1993/09/14 22:37:26 jtc Exp $";
/*
* get option letter from argument vector
*/
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt; /* character checked for validity */
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt; /* character checked for validity */
char *optarg; /* argument associated with option */
#define NOOPT (int)':' /* No option */
#define BADCH (int)'?'
#define EMSG ""
@ -71,9 +72,10 @@ getopt(nargc, nargv, ostr)
place = EMSG;
return(-1);
}
} /* option letter okay? */
}
/* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = index(ostr, optopt))) {
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
@ -82,8 +84,8 @@ getopt(nargc, nargv, ostr)
return(-1);
if (!*place)
++optind;
if (opterr) {
if (!(p = rindex(*nargv, '/')))
if (opterr && *ostr != ':') {
if (!(p = strrchr(*nargv, '/')))
p = *nargv;
else
++p;
@ -92,25 +94,26 @@ getopt(nargc, nargv, ostr)
}
return(BADCH);
}
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else { /* need an argument */
} else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
if (!(p = rindex(*nargv, '/')))
p = *nargv;
else
++p;
if (opterr)
if (opterr && *ostr != ':') {
if (!(p = strrchr(*nargv, '/')))
p = *nargv;
else
++p;
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
p, optopt);
return(BADCH);
}
return((*ostr == ':') ? NOOPT : BADCH);
}
else /* white space */
optarg = nargv[optind];