home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
300-399
/
ff388.lzh
/
Free
/
getopt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-23
|
6KB
|
200 lines
/****************************************************************************
* getopt(): Return the next user option on each iteration.
* This is a clone of the usual UNIX getopt() function.
* If you have never used a getopt() before, you'll have to
* read about it on any UNIX machine or other C system that
* documents it.
*
* Author: Daniel Barrett, barrett@cs.jhu.edu.
* Date: April 12, 1990.
* Version: 1.0.
*
* License: This code is placed in the Public Domain.
* Give it away to anybody for free!
* Use it for any purpose you like!
*
* If you use this code in a program, please give me credit
* for my work. Thanks!
*
* Why I wrote it:
*
* Because every other getopt() function I have ever seen
* had source code that was difficult to understand.
* I wrote this code to be very modular and readable.
* I hope you find it instructive and/or helpful.
*
****************************************************************************/
#ifndef __STDIO_H /* If we haven't already included stdio.h, do it. */
#include <stdio.h> /* Maybe someday I'll eliminate this. */
#endif
/************************************************************************
* Some constants.
************************************************************************/
#define DASH '-' /* This preceeds an option. */
#define ARG_COMING ':' /* In the option string, this indicates that
* that the option requires an argument. */
#define UNKNOWN_OPT '?' /* The char returned for unknown option. */
/************************************************************************
* Internal error codes.
************************************************************************/
#define ERROR_BAD_OPTION 1
#define ERROR_MISSING_ARGUMENT 2
/************************************************************************
* ANSI function prototypes.
************************************************************************/
int getopt(int argc, char *argv[], char *optString);
static int g_NextOption(char *argv[], char *optString);
static int g_RealOption(char *argv[], char *str, int *skip, int *ind,
int opt);
static void g_HandleArgument(char *argv[], int *optind, int *skip);
static void g_Error(int err, int c);
static void g_Pass(char *argv[], int *optind, int *optsSkipped);
extern char *index();
/************************************************************************
* Global variables. You must declare these externs in your program
* if you want to see their values!
************************************************************************/
char *optarg = NULL; /* This will point to a required argument, if any. */
int optind = 1; /* The index of the next argument in argv. */
int opterr = 1; /* 1 == print internal error messages. 0 else. */
int optopt; /* The actual option letter that was found. */
int getopt(int argc, char *argv[], char *optString)
{
optarg = NULL;
if (optind < argc) /* More arguments to check. */
return(g_NextOption(argv, optString));
else /* We're done. */
return(EOF);
}
/* If the current argument does not begin with DASH, it is not an option.
* Return EOF.
* If we have ONLY a DASH, and nothing after it... return EOF as well.
* If we have a DASH followed immediately by another DASH, this is the
* special "--" option that means "no more options follow." Return EOF.
* Otherwise, we have an actual option or list of options. Process it. */
static int g_NextOption(char *argv[], char *optString)
{
static int optsSkipped = 0; /* In a single argv[i]. */
if ((argv[optind][0] == DASH)
&& ((optopt = argv[optind][1+optsSkipped]) != '\0'))
{
if (optopt == DASH)
{
optind++;
return(EOF);
}
else
return(g_RealOption(argv, optString, &optsSkipped,
&optind, optopt));
}
else
return(EOF);
}
/* At this point, we know that argv[optind] is an option or list of
* options. If this is a list of options, *optsSkipped tells us how
* many of those options have ALREADY been parsed on previous calls
* to getopt().
* If the option is not legal (not in optString), complain and return
* UNKNOWN_OPT.
* If the option requires no argument, just return the option letter.
* If the option requires an argument, call g_HandleArgument and return
* the option letter. */
static int g_RealOption(char *argv[], char *optString, int *optsSkipped,
int *optind, int optopt)
{
char *where;
(*optsSkipped)++;
if (where = index(optString, optopt))
{
if (*(where+1) == ARG_COMING)
g_HandleArgument(argv, optind, optsSkipped);
g_Pass(argv, optind, optsSkipped);
return(optopt);
}
else
{
g_Error(ERROR_BAD_OPTION, optopt);
g_Pass(argv, optind, optsSkipped);
return(UNKNOWN_OPT);
}
}
/* We have an option in argv[optind] that requires an argument. If there
* is no whitespace after the option letter itself, take the rest of
* argv[optind] to be the argument.
* If there IS whitespace after the option letter, take argv[optind+1] to
* be the argument.
* Otherwise, if there is NO argument, complain! */
static void g_HandleArgument(char *argv[], int *optind, int *optsSkipped)
{
if (argv[*optind][1+(*optsSkipped)])
optarg = argv[*optind] + 1 + (*optsSkipped);
else if (argv[(*optind)+1])
{
optarg = argv[(*optind)+1];
(*optind)++;
}
else
g_Error(ERROR_MISSING_ARGUMENT, optopt);
(*optsSkipped) = 0;
(*optind)++;
}
/* Print an appropriate error message. */
static void g_Error(int err, int c)
{
static char *optmsg = "Illegal option.\n";
static char *argmsg = "An argument is required, but missing.\n";
if (opterr)
{
if (err == ERROR_BAD_OPTION)
fprintf(stderr, "-%c: %s", c, optmsg);
else if (err == ERROR_MISSING_ARGUMENT)
fprintf(stderr, "-%c: %s", c, argmsg);
else /* Sanity check! */
fprintf(stderr, "-%c: an unknown error occurred\n",
c);
}
}
/* We have reached the end of argv[optind]... there are no more options
* in it to parse. Skip to the next item in argv. */
static void g_Pass(char *argv[], int *optind, int *optsSkipped)
{
if ( !(argv[*optind][1+(*optsSkipped)]) )
{
(*optind)++;
(*optsSkipped) = 0;
}
}