home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * 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;
- }
- }
-