diff options
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/common/cmdline.c')
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/common/cmdline.c | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/common/cmdline.c b/board/MAI/bios_emulator/scitech/src/common/cmdline.c new file mode 100644 index 0000000..872fae9 --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/common/cmdline.c @@ -0,0 +1,428 @@ +/**************************************************************************** +* +* ======================================================================== +* +* 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); +} |