The Independent JPEG Group's JPEG software v1
This commit is contained in:
276
egetopt.c
Normal file
276
egetopt.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* egetopt.c -- Extended 'getopt'.
|
||||
*
|
||||
* A while back, a public-domain version of getopt() was posted to the
|
||||
* net. A bit later, a gentleman by the name of Keith Bostic made some
|
||||
* enhancements and reposted it.
|
||||
*
|
||||
* In recent weeks (i.e., early-to-mid 1988) there's been some
|
||||
* heated discussion in comp.lang.c about the merits and drawbacks
|
||||
* of getopt(), especially with regard to its handling of '?'.
|
||||
*
|
||||
* In light of this, I have taken Mr. Bostic's public-domain getopt()
|
||||
* and have made some changes that I hope will be considered to be
|
||||
* improvements. I call this routine 'egetopt' ("Extended getopt").
|
||||
* The default behavior of this routine is the same as that of getopt(),
|
||||
* but it has some optional features that make it more useful. These
|
||||
* options are controlled by the settings of some global variables.
|
||||
* By not setting any of these extra global variables, you will have
|
||||
* the same functionality as getopt(), which should satisfy those
|
||||
* purists who believe getopt() is perfect and can never be improved.
|
||||
* If, on the other hand, you are someone who isn't satisfied with the
|
||||
* status quo, egetopt() may very well give you the added capabilities
|
||||
* you want.
|
||||
*
|
||||
* Look at the enclosed README file for a description of egetopt()'s
|
||||
* new features.
|
||||
*
|
||||
* The code was originally posted to the net as getopt.c by ...
|
||||
*
|
||||
* Keith Bostic
|
||||
* ARPA: keith@seismo
|
||||
* UUCP: seismo!keith
|
||||
*
|
||||
* Current version: added enhancements and comments, reformatted code.
|
||||
*
|
||||
* Lloyd Zusman
|
||||
* Master Byte Software
|
||||
* Los Gatos, California
|
||||
* Internet: ljz@fx.com
|
||||
* UUCP: ...!ames!fxgrp!ljz
|
||||
*
|
||||
* May, 1988
|
||||
*/
|
||||
|
||||
/*
|
||||
* If you want, include stdio.h or something where EOF and NULL are defined.
|
||||
* However, egetopt() is written so as not to need stdio.h, which should
|
||||
* make it significantly smaller on some systems.
|
||||
*/
|
||||
|
||||
#ifndef EOF
|
||||
# define EOF (-1)
|
||||
#endif /* ! EOF */
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL (char *)0
|
||||
#endif /* ! NULL */
|
||||
|
||||
/*
|
||||
* None of these constants are referenced in the executable portion of
|
||||
* the code ... their sole purpose is to initialize global variables.
|
||||
*/
|
||||
#define BADCH (int)'?'
|
||||
#define NEEDSEP (int)':'
|
||||
#define MAYBESEP (int)'\0'
|
||||
#define ERRFD 2
|
||||
#define EMSG ""
|
||||
#define START "-"
|
||||
|
||||
/*
|
||||
* Here are all the pertinent global variables.
|
||||
*/
|
||||
int opterr = 1; /* if true, output error message */
|
||||
int optind = 1; /* index into parent argv vector */
|
||||
int optopt; /* character checked for validity */
|
||||
int optbad = BADCH; /* character returned on error */
|
||||
int optchar = 0; /* character that begins returned option */
|
||||
int optneed = NEEDSEP; /* flag for mandatory argument */
|
||||
int optmaybe = MAYBESEP;/* flag for optional argument */
|
||||
int opterrfd = ERRFD; /* file descriptor for error text */
|
||||
char *optarg; /* argument associated with option */
|
||||
char *optstart = START; /* list of characters that start options */
|
||||
|
||||
|
||||
/*
|
||||
* Macros.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Conditionally print out an error message and return (depends on the
|
||||
* setting of 'opterr' and 'opterrfd'). Note that this version of
|
||||
* TELL() doesn't require the existence of stdio.h.
|
||||
*/
|
||||
#define TELL(S) { \
|
||||
if (opterr && opterrfd >= 0) { \
|
||||
char option = optopt; \
|
||||
write(opterrfd, *nargv, strlen(*nargv)); \
|
||||
write(opterrfd, (S), strlen(S)); \
|
||||
write(opterrfd, &option, 1); \
|
||||
write(opterrfd, "\n", 1); \
|
||||
} \
|
||||
return (optbad); \
|
||||
}
|
||||
|
||||
/*
|
||||
* This works similarly to index() and strchr(). I include it so that you
|
||||
* don't need to be concerned as to which one your system has.
|
||||
*/
|
||||
static char *
|
||||
_sindex(string, ch)
|
||||
char *string;
|
||||
int ch;
|
||||
{
|
||||
if (string != NULL) {
|
||||
for (; *string != '\0'; ++string) {
|
||||
if (*string == (char)ch) {
|
||||
return (string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here it is:
|
||||
*/
|
||||
int
|
||||
egetopt(nargc, nargv, ostr)
|
||||
int nargc;
|
||||
char **nargv;
|
||||
char *ostr;
|
||||
{
|
||||
static char *place = EMSG; /* option letter processing */
|
||||
register char *oli; /* option letter list index */
|
||||
register char *osi = NULL; /* option start list index */
|
||||
|
||||
if (nargv == (char **)NULL) {
|
||||
return (EOF);
|
||||
}
|
||||
|
||||
if (nargc <= optind || nargv[optind] == NULL) {
|
||||
return (EOF);
|
||||
}
|
||||
|
||||
if (place == NULL) {
|
||||
place = EMSG;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update scanning pointer.
|
||||
*/
|
||||
if (*place == '\0') {
|
||||
place = nargv[optind];
|
||||
if (place == NULL) {
|
||||
return (EOF);
|
||||
}
|
||||
osi = _sindex(optstart, *place);
|
||||
if (osi != NULL) {
|
||||
optchar = (int)*osi;
|
||||
}
|
||||
if (optind >= nargc || osi == NULL || *++place == '\0') {
|
||||
return (EOF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Two adjacent, identical flag characters were found.
|
||||
* This takes care of "--", for example.
|
||||
*/
|
||||
if (*place == place[-1]) {
|
||||
++optind;
|
||||
return (EOF);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the option is a separator or the option isn't in the list,
|
||||
* we've got an error.
|
||||
*/
|
||||
optopt = (int)*place++;
|
||||
oli = _sindex(ostr, optopt);
|
||||
if (optopt == optneed || optopt == optmaybe || oli == NULL) {
|
||||
/*
|
||||
* If we're at the end of the current argument, bump the
|
||||
* argument index.
|
||||
*/
|
||||
if (*place == '\0') {
|
||||
++optind;
|
||||
}
|
||||
TELL(": illegal option -- "); /* byebye */
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no argument indicator, then we don't even try to
|
||||
* return an argument.
|
||||
*/
|
||||
++oli;
|
||||
if (*oli == '\0' || (*oli != optneed && *oli != optmaybe)) {
|
||||
/*
|
||||
* If we're at the end of the current argument, bump the
|
||||
* argument index.
|
||||
*/
|
||||
if (*place == '\0') {
|
||||
++optind;
|
||||
}
|
||||
optarg = NULL;
|
||||
}
|
||||
/*
|
||||
* If we're here, there's an argument indicator. It's handled
|
||||
* differently depending on whether it's a mandatory or an
|
||||
* optional argument.
|
||||
*/
|
||||
else {
|
||||
/*
|
||||
* If there's no white space, use the rest of the
|
||||
* string as the argument. In this case, it doesn't
|
||||
* matter if the argument is mandatory or optional.
|
||||
*/
|
||||
if (*place != '\0') {
|
||||
optarg = place;
|
||||
}
|
||||
/*
|
||||
* If we're here, there's whitespace after the option.
|
||||
*
|
||||
* Is it a mandatory argument? If so, return the
|
||||
* next command-line argument if there is one.
|
||||
*/
|
||||
else if (*oli == optneed) {
|
||||
/*
|
||||
* If we're at the end of the argument list, there
|
||||
* isn't an argument and hence we have an error.
|
||||
* Otherwise, make 'optarg' point to the argument.
|
||||
*/
|
||||
if (nargc <= ++optind) {
|
||||
place = EMSG;
|
||||
TELL(": option requires an argument -- ");
|
||||
}
|
||||
else {
|
||||
optarg = nargv[optind];
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If we're here it must have been an optional argument.
|
||||
*/
|
||||
else {
|
||||
if (nargc <= ++optind) {
|
||||
place = EMSG;
|
||||
optarg = NULL;
|
||||
}
|
||||
else {
|
||||
optarg = nargv[optind];
|
||||
if (optarg == NULL) {
|
||||
place = EMSG;
|
||||
}
|
||||
/*
|
||||
* If the next item begins with a flag
|
||||
* character, we treat it like a new
|
||||
* argument. This is accomplished by
|
||||
* decrementing 'optind' and returning
|
||||
* a null argument.
|
||||
*/
|
||||
else if (_sindex(optstart, *optarg) != NULL) {
|
||||
--optind;
|
||||
optarg = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
place = EMSG;
|
||||
++optind;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return option letter.
|
||||
*/
|
||||
return (optopt);
|
||||
}
|
||||
Reference in New Issue
Block a user