/**************************************************************************** * Modified from the original version found in SciTech's library. Note that * this in fact may have been copied/derived from a much earlier work as I * remember seeing a version of it 10 years ago for use in CP/M and it wasn't * new then. I peeled a routine out of the end of this as it was an alternative * for Windows code. CH * * Copyright (C) 1991-1997 SciTech Software, Inc. * All rights reserved. * * ====================================================================== * This library is free software; you can use it and/or * modify it under the terms of the SciTech MGL Software License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * SciTech MGL Software License for more details. * ====================================================================== * * Filename: $Workfile: getopt.c $ * Version: $Revision$ * * Language: ANSI C * Environment: any * * Description: This module contains code to parse the command line, * extracting options and parameters in standard System V * style. * * $Date$ $Author$ * * $Id$ * (Log is kept at end of this file) * ****************************************************************************/ #include #include #include #include "fg_getopt.h" /*------------------------- Global variables ------------------------------*/ int nextargv = 1; /* Index into argv array */ char *nextchar = NULL; /* Pointer to next character */ /*-------------------------- Implementation -------------------------------*/ #ifdef __WIN32__ #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 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 */ } static 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",(int*)optarr->arg); break; case OPT_HEX: num_read = sscanf(argument,"%x",(int*)optarr->arg); break; case OPT_OCTAL: num_read = sscanf(argument,"%o",(int*)optarr->arg); break; case OPT_UNSIGNED: num_read = sscanf(argument,"%u",(uint*)optarr->arg); break; case OPT_LINTEGER: num_read = sscanf(argument,"%ld",(long*)optarr->arg); break; case OPT_LHEX: num_read = sscanf(argument,"%lx",(long*)optarr->arg); break; case OPT_LOCTAL: num_read = sscanf(argument,"%lo",(long*)optarr->arg); break; case OPT_LUNSIGNED: num_read = sscanf(argument,"%lu",(ulong*)optarr->arg); break; case OPT_FLOAT: num_read = sscanf(argument,"%f",(float*)optarr->arg); break; case OPT_DOUBLE: num_read = sscanf(argument,"%lf",(double*)optarr->arg); break; case OPT_LDOUBLE: num_read = sscanf(argument,"%Lf",(long double*)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 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 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 %s\n",optarr[i]->opt,optarr[i]->desc); } } // End of getopt.c /* $Log$ /* Revision 1.1 1998/02/13 00:23:40 curt /* Initial revision. /* */