123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428 |
- /****************************************************************************
- *
- * ========================================================================
- *
- * The contents of this file are subject to the SciTech MGL Public
- * License Version 1.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.scitechsoft.com/mgl-license.txt
- *
- * Software distributed under the License is distributed on an
- * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
- *
- * The Initial Developer of the Original Code is SciTech Software, Inc.
- * All Rights Reserved.
- *
- * ========================================================================
- *
- * Language: ANSI C
- * Environment: any
- *
- * Description: This module contains code to parse the command line,
- * extracting options and parameters in standard System V
- * style.
- *
- ****************************************************************************/
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include "cmdline.h"
- /*------------------------- Global variables ------------------------------*/
- int nextargv = 1; /* Index into argv array */
- char *nextchar = NULL; /* Pointer to next character */
- /*-------------------------- Implementation -------------------------------*/
- #define IS_SWITCH_CHAR(c) ((c) == '-')
- #define IS_NOT_SWITCH_CHAR(c) ((c) != '-')
- /****************************************************************************
- DESCRIPTION:
- Parse the command line for specific options
- HEADER:
- cmdline.h
- PARAMETERS:
- argc - Value passed to program through argc variable
- argv - Pointer to the argv array passed to the program
- format - A string representing the expected format of the command line
- argument - Pointer to optional argument on command line
- RETURNS:
- Character code representing the next option parsed from the command line by
- getcmdopt. 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.
- REMARKS:
- Function to parse the command line option switches in UNIX System V style.
- When getcmdopt 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 getcmdopt 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.
- When getcmdopt 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 getcmdopt 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.
- ****************************************************************************/
- int getcmdopt(
- int argc,
- char **argv,
- char *format,
- char **argument)
- {
- 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 */
- }
- /****************************************************************************
- PARAMETERS:
- optarr - Description for the option we are parsing
- argument - String to parse
- RETURNS:
- INVALID on error, ALLDONE on success.
- REMARKS:
- 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.
- ****************************************************************************/
- static int parse_option(
- Option *optarr,
- char *argument)
- {
- int num_read;
- 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;
- }
- /****************************************************************************
- HEADER:
- cmdline.h
- 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
- REMARKS:
- Function to parse the command line according to a table of options. This
- routine calls getcmdopt 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 getargs(
- int argc,
- char *argv[],
- int num_opt,
- Option optarr[],
- int (*do_param)(
- char *param,
- int num))
- {
- 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';
- for (;;) {
- opt = getcmdopt(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)
- *((ibool*)optarr[i].arg) = true;
- else {
- if (parse_option(&optarr[i],argument) == INVALID)
- return INVALID;
- }
- break;
- }
- }
- }
- /****************************************************************************
- HEADER:
- cmdline.h
- PARAMETERS:
- num_opt - Number of options in the table
- optarr - Table of option descriptions
- REMARKS:
- 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.
- ****************************************************************************/
- void print_desc(
- int num_opt,
- Option optarr[])
- {
- 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);
- }
- }
- /****************************************************************************
- HEADER:
- cmdline.h
- PARAMETERS:
- moduleName - Module name for program
- cmdLine - Command line to parse
- pargc - Pointer to 'argc' parameter
- pargv - Pointer to 'argv' parameter
- maxArgc - Maximum argv array index
- REMARKS:
- Parses a command line from a single string into the C style 'argc' and
- 'argv' format. Most useful for Windows programs where the command line
- is passed in verbatim.
- ****************************************************************************/
- int parse_commandline(
- char *moduleName,
- char *cmdLine,
- int *pargc,
- char *argv[],
- int maxArgv)
- {
- static char str[512];
- static char filename[260];
- char *prevWord = NULL;
- ibool inQuote = FALSE;
- ibool noStrip = FALSE;
- int argc;
- argc = 0;
- strcpy(filename,moduleName);
- argv[argc++] = filename;
- cmdLine = strncpy(str, cmdLine, sizeof(str)-1);
- while (*cmdLine) {
- switch (*cmdLine) {
- case '"' :
- if (prevWord != NULL) {
- if (inQuote) {
- if (!noStrip)
- *cmdLine = '\0';
- argv [argc++] = prevWord;
- prevWord = NULL;
- }
- else
- noStrip = TRUE;
- }
- inQuote = !inQuote;
- break;
- case ' ' :
- case '\t' :
- if (!inQuote) {
- if (prevWord != NULL) {
- *cmdLine = '\0';
- argv [argc++] = prevWord;
- prevWord = NULL;
- noStrip = FALSE;
- }
- }
- break;
- default :
- if (prevWord == NULL)
- prevWord = cmdLine;
- break;
- }
- if (argc >= maxArgv - 1)
- break;
- cmdLine++;
- }
- if ((prevWord != NULL || (inQuote && prevWord != NULL)) && argc < maxArgv - 1) {
- *cmdLine = '\0';
- argv [argc++] = prevWord;
- }
- argv[argc] = NULL;
- /* Return updated parameters */
- return (*pargc = argc);
- }
|