home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * Copyright (C) 1991 Kendall Bennett.
- * All rights reserved.
- *
- * Filename: $RCSfile: getopt.c $
- * Version: $Revision: 1.5 $
- *
- * Language: ANSI C
- * Environment: any
- *
- * Description: This module contains code to parse the command line,
- * extracting options and parameters in standard System V
- * style.
- *
- * $Id: getopt.c 1.5 1991/12/31 19:39:55 kjb Exp $
- *
- * Revision History:
- * -----------------
- *
- * $Log: getopt.c $
- * Revision 1.5 1991/12/31 19:39:55 kjb
- * Modified include file directories.
- *
- * Revision 1.4 91/10/28 03:17:02 kjb
- * Ported to the Iris.
- *
- * Revision 1.3 91/09/24 19:48:05 kjb
- * Added getargs() to parse the entire command line and converting the
- * parameters to the types specified in a table of options.
- * Added routine print_desc() to print the option description from the
- * table to the standard output device.
- *
- * Revision 1.2 91/09/03 18:27:52 ROOT_DOS
- * Ported to UNIX.
- *
- * Revision 1.1 91/08/16 10:45:36 ROOT_DOS
- * Initial revision
- *
- ****************************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include "debug.h"
- #include "getopt.h"
-
- /*------------------------- Global variables ------------------------------*/
-
- int nextargv = 1; /* Index into argv array */
- char *nextchar = NULL; /* Pointer to next character */
-
- /*-------------------------- Implementation -------------------------------*/
-
- #ifdef __MSDOS__
- #define IS_SWITCH_CHAR(c) (c == '-') || (c == '/')
- #define IS_NOT_SWITCH_CHAR(c) (c != '-') && (c != '/')
- #else
- #define IS_SWITCH_CHAR(c) (c == '-')
- #define IS_NOT_SWITCH_CHAR(c) (c != '-')
- #endif
-
- int PUBAPI getopt(int argc,char **argv,char *format,char **argument)
- /****************************************************************************
- *
- * Function: getopt
- * Parameters: argc - Value passed to program through argc
- * variable in the function main.
- * argv - Pointer to the argv array that is passed to
- * the program in function main.
- * format - A string representing the expected format
- * of the command line options that need to be
- * parsed.
- * argument - Pointer to optional argument on command
- * line.
- *
- * Returns: Character code representing the next option parsed from the
- * command line by getopt. Returns ALLDONE (-1) when there are
- * no more parameters to be parsed on the command line,
- * PARAMETER (-2) when the argument being parsed is a
- * parameter and not an option switch and lastly INVALID (-3)
- * if an error occured while parsing the command line.
- *
- * Description: Function to parse the command line option switches in
- * UNIX System V style. When getopt is called, it returns the
- * character code of the next valid option that is parsed from
- * the command line as specified by the Format string. The
- * format string should be in the following form:
- *
- * "abcd:e:f:"
- *
- * where a,b and c represent single switch style options and
- * the character code returned by getopt is the only value
- * returned. Also d, e and f represent options that expect
- * arguments immediately after them on the command line. The
- * argument that follows the option on the command line is
- * returned via a reference in the pointer argument. Thus
- * a valid command line for this format string might be:
- *
- * myprogram -adlines /b /f format infile outfile
- *
- * where a and b will be returned as single character options
- * with no argument, while d is returned with the argument
- * lines and f is returned with the argument format. Note that
- * either UNIX style or MS-DOS command switches may be used
- * interchangeably under MSDOS, but under UNIX only the UNIX
- * style switches are supported.
- *
- * When getopt returns with PARAMETER (we attempted to parse
- * a paramter, not an option), the global variable NextArgv
- * will hold an index in the argv array to the argument on the
- * command line AFTER the options, ie in the above example the
- * string 'infile'. If the parameter is successfully used,
- * NextArgv should be incremented and getopt can be called
- * again to parse any more options. Thus you can also have
- * options interspersed throught the command line. eg:
- *
- * myprogram -adlines infile /b outfile /f format
- *
- * can be made to be a valid form of the above command line.
- *
- ****************************************************************************/
- {
- char ch;
- char *formatchar;
-
- if (argc > nextargv) {
- if (nextchar == NULL) {
- nextchar = argv[nextargv]; /* Index next argument */
- if(nextchar == NULL) {
- nextargv++;
- return ALLDONE; /* No more options */
- }
- if(IS_NOT_SWITCH_CHAR(*nextchar)) {
- nextchar = NULL;
- return PARAMETER; /* We have a parameter */
- }
- nextchar++; /* Move past switch operator */
- if(IS_SWITCH_CHAR(*nextchar)) {
- nextchar = NULL;
- return INVALID; /* Ignore rest of line */
- }
- }
-
- if ((ch = *(nextchar++)) == 0) {
- nextchar = NULL;
- return INVALID; /* No options on line */
- }
-
- if (ch == ':' || (formatchar = strchr(format, ch)) == NULL)
- return INVALID;
-
- if (*(++formatchar) == ':') { /* Expect an argument after option */
- nextargv++;
- if (*nextchar == 0) {
- if (argc <= nextargv)
- return INVALID;
- nextchar = argv[nextargv++];
- }
- *argument = nextchar;
- nextchar = NULL;
- }
- else { /* We have a switch style option */
- if (*nextchar == 0) {
- nextargv++;
- nextchar = NULL;
- }
- *argument = NULL;
- }
- return ch; /* return the option specifier */
- }
- nextchar = NULL;
- nextargv++;
- return ALLDONE; /* no arguments on command line */
- }
-
- PRIVATE int parse_option(Option *optarr,char *argument)
- /****************************************************************************
- *
- * Function: parse_option
- * Parameters: optarr - Description for the option we are parsing
- * argument - String to parse
- * Returns: INVALID on error, ALLDONE on success.
- *
- * Description: Parses the argument string depending on the type of argument
- * that is expected, filling in the argument for that option.
- * Note that to parse a string, we simply return a pointer
- * to argument.
- *
- ****************************************************************************/
- {
- int num_read = 0;
-
- switch ((int)(optarr->type)) {
- case OPT_INTEGER:
- num_read = sscanf(argument,"%d",optarr->arg);
- break;
- case OPT_HEX:
- num_read = sscanf(argument,"%x",optarr->arg);
- break;
- case OPT_OCTAL:
- num_read = sscanf(argument,"%o",optarr->arg);
- break;
- case OPT_UNSIGNED:
- num_read = sscanf(argument,"%u",optarr->arg);
- break;
- case OPT_LINTEGER:
- num_read = sscanf(argument,"%ld",optarr->arg);
- break;
- case OPT_LHEX:
- num_read = sscanf(argument,"%lx",optarr->arg);
- break;
- case OPT_LOCTAL:
- num_read = sscanf(argument,"%lo",optarr->arg);
- break;
- case OPT_LUNSIGNED:
- num_read = sscanf(argument,"%lu",optarr->arg);
- break;
- case OPT_FLOAT:
- num_read = sscanf(argument,"%f",optarr->arg);
- break;
- case OPT_DOUBLE:
- num_read = sscanf(argument,"%lf",optarr->arg);
- break;
- case OPT_LDOUBLE:
- num_read = sscanf(argument,"%Lf",optarr->arg);
- break;
- case OPT_STRING:
- num_read = 1; /* This always works */
- *((char**)optarr->arg) = argument;
- break;
- default:
- return INVALID;
- }
-
- if (num_read == 0)
- return INVALID;
- else
- return ALLDONE;
- }
-
- int PUBAPI getargs(int argc,char *argv[],int num_opt,Option optarr[],
- int (*do_param)(char *param,int num))
- /****************************************************************************
- *
- * Function: getargs
- * Parameters: argc - Number of arguments on command line
- * argv - Array of command line arguments
- * num_opt - Number of options in option array
- * optarr - Array to specify how to parse the command line
- * do_param - Routine to handle a command line parameter
- * Returns: ALLDONE, INVALID or HELP
- *
- * Description: Function to parse the command line according to a table of
- * options. This routine calls getopt above to parse each
- * individual option and attempts to parse each option into
- * a variable of the specified type. The routine can parse
- * integers and long integers in either decimal, octal,
- * hexadecimal notation, unsigned integers and unsigned longs,
- * strings and option switches. Option switches are simply
- * boolean variables that get turned on if the switch was
- * parsed.
- *
- * Parameters are extracted from the command line by calling
- * a user supplied routine do_param() to handle each parameter
- * as it is encountered. The routine do_param() should accept
- * a pointer to the parameter on the command line and an
- * integer representing how many parameters have been
- * encountered (ie: 1 if this is the first parameter, 10 if
- * it is the 10th etc), and return ALLDONE upon successfully
- * parsing it or INVALID if the parameter was invalid.
- *
- * We return either ALLDONE if all the options were
- * successfully parsed, INVALID if an invalid option was
- * encountered or HELP if any of -h, -H or -? were present
- * on the command line.
- *
- ****************************************************************************/
- {
- int i,opt;
- char *argument;
- int param_num = 1;
- char cmdstr[MAXARG*2 + 4];
-
- /* Build the command string from the array of options */
-
- strcpy(cmdstr,"hH?");
- for (i = 0,opt = 3; i < num_opt; i++,opt++) {
- cmdstr[opt] = optarr[i].opt;
- if (optarr[i].type != OPT_SWITCH) {
- cmdstr[++opt] = ':';
- }
- }
- cmdstr[opt] = '\0';
-
- while (true) {
- opt = getopt(argc,argv,cmdstr,&argument);
- switch (opt) {
- case 'H':
- case 'h':
- case '?':
- return HELP;
- case ALLDONE:
- return ALLDONE;
- case INVALID:
- return INVALID;
- case PARAMETER:
- if (do_param == NULL)
- return INVALID;
- if (do_param(argv[nextargv],param_num) == INVALID)
- return INVALID;
- nextargv++;
- param_num++;
- break;
- default:
-
- /* Search for the option in the option array. We are
- * guaranteed to find it.
- */
-
- for (i = 0; i < num_opt; i++) {
- if (optarr[i].opt == opt)
- break;
- }
- if (optarr[i].type == OPT_SWITCH)
- *((bool*)optarr[i].arg) = true;
- else {
- if (parse_option(&optarr[i],argument) == INVALID)
- return INVALID;
- }
- break;
- }
- }
- }
-
- void PUBAPI print_desc(int num_opt,Option optarr[])
- /****************************************************************************
- *
- * Function: print_desc
- * Parameters: num_opt - Number of options in the table
- * optarr - Table of option descriptions
- *
- * Description: Prints the description of each option in a standard format
- * to the standard output device. The description for each
- * option is obtained from the table of options.
- *
- ****************************************************************************/
- {
- int i;
-
- for (i = 0; i < num_opt; i++) {
- if (optarr[i].type == OPT_SWITCH)
- printf(" -%c %s\n",optarr[i].opt,optarr[i].desc);
- else
- printf(" -%c<arg> %s\n",optarr[i].opt,optarr[i].desc);
- }
- }
-