1 /****************************************************************************
3 * ========================================================================
5 * The contents of this file are subject to the SciTech MGL Public
6 * License Version 1.0 (the "License"); you may not use this file
7 * except in compliance with the License. You may obtain a copy of
8 * the License at http://www.scitechsoft.com/mgl-license.txt
10 * Software distributed under the License is distributed on an
11 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12 * implied. See the License for the specific language governing
13 * rights and limitations under the License.
15 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
17 * The Initial Developer of the Original Code is SciTech Software, Inc.
18 * All Rights Reserved.
20 * ========================================================================
25 * Description: This module contains code to parse the command line,
26 * extracting options and parameters in standard System V
29 ****************************************************************************/
36 /*------------------------- Global variables ------------------------------*/
38 int nextargv = 1; /* Index into argv array */
39 char *nextchar = NULL; /* Pointer to next character */
41 /*-------------------------- Implementation -------------------------------*/
43 #define IS_SWITCH_CHAR(c) ((c) == '-')
44 #define IS_NOT_SWITCH_CHAR(c) ((c) != '-')
46 /****************************************************************************
48 Parse the command line for specific options
54 argc - Value passed to program through argc variable
55 argv - Pointer to the argv array passed to the program
56 format - A string representing the expected format of the command line
57 argument - Pointer to optional argument on command line
60 Character code representing the next option parsed from the command line by
61 getcmdopt. Returns ALLDONE (-1) when there are no more parameters to be parsed
62 on the command line, PARAMETER (-2) when the argument being parsed is a
63 parameter and not an option switch and lastly INVALID (-3) if an error
64 occured while parsing the command line.
67 Function to parse the command line option switches in UNIX System V style.
68 When getcmdopt is called, it returns the character code of the next valid
69 option that is parsed from the command line as specified by the Format
70 string. The format string should be in the following form:
74 where a,b and c represent single switch style options and the character
75 code returned by getcmdopt is the only value returned. Also d, e and f
76 represent options that expect arguments immediately after them on the
77 command line. The argument that follows the option on the command line is
78 returned via a reference in the pointer argument. Thus a valid command line
79 for this format string might be:
81 myprogram -adlines -b -f format infile outfile
83 where a and b will be returned as single character options with no argument,
84 while d is returned with the argument lines and f is returned with the
87 When getcmdopt returns with PARAMETER (we attempted to parse a paramter, not
88 an option), the global variable NextArgv will hold an index in the argv
89 array to the argument on the command line AFTER the options, ie in the
90 above example the string 'infile'. If the parameter is successfully used,
91 NextArgv should be incremented and getcmdopt can be called again to parse any
92 more options. Thus you can also have options interspersed throught the
95 myprogram -adlines infile -b outfile -f format
97 can be made to be a valid form of the above command line.
98 ****************************************************************************/
108 if (argc > nextargv) {
109 if (nextchar == NULL) {
110 nextchar = argv[nextargv]; /* Index next argument */
111 if (nextchar == NULL) {
113 return ALLDONE; /* No more options */
115 if (IS_NOT_SWITCH_CHAR(*nextchar)) {
117 return PARAMETER; /* We have a parameter */
119 nextchar++; /* Move past switch operator */
120 if (IS_SWITCH_CHAR(*nextchar)) {
122 return INVALID; /* Ignore rest of line */
125 if ((ch = *(nextchar++)) == 0) {
127 return INVALID; /* No options on line */
130 if (ch == ':' || (formatchar = strchr(format, ch)) == NULL)
133 if (*(++formatchar) == ':') { /* Expect an argument after option */
135 if (*nextchar == 0) {
136 if (argc <= nextargv)
138 nextchar = argv[nextargv++];
140 *argument = nextchar;
143 else { /* We have a switch style option */
144 if (*nextchar == 0) {
150 return ch; /* return the option specifier */
154 return ALLDONE; /* no arguments on command line */
157 /****************************************************************************
159 optarr - Description for the option we are parsing
160 argument - String to parse
163 INVALID on error, ALLDONE on success.
166 Parses the argument string depending on the type of argument that is
167 expected, filling in the argument for that option. Note that to parse a
168 string, we simply return a pointer to argument.
169 ****************************************************************************/
170 static int parse_option(
176 switch ((int)(optarr->type)) {
178 num_read = sscanf(argument,"%d",(int*)optarr->arg);
181 num_read = sscanf(argument,"%x",(int*)optarr->arg);
184 num_read = sscanf(argument,"%o",(int*)optarr->arg);
187 num_read = sscanf(argument,"%u",(uint*)optarr->arg);
190 num_read = sscanf(argument,"%ld",(long*)optarr->arg);
193 num_read = sscanf(argument,"%lx",(long*)optarr->arg);
196 num_read = sscanf(argument,"%lo",(long*)optarr->arg);
199 num_read = sscanf(argument,"%lu",(ulong*)optarr->arg);
202 num_read = sscanf(argument,"%f",(float*)optarr->arg);
205 num_read = sscanf(argument,"%lf",(double*)optarr->arg);
208 num_read = sscanf(argument,"%Lf",(long double*)optarr->arg);
211 num_read = 1; /* This always works */
212 *((char**)optarr->arg) = argument;
224 /****************************************************************************
229 argc - Number of arguments on command line
230 argv - Array of command line arguments
231 num_opt - Number of options in option array
232 optarr - Array to specify how to parse the command line
233 do_param - Routine to handle a command line parameter
236 ALLDONE, INVALID or HELP
239 Function to parse the command line according to a table of options. This
240 routine calls getcmdopt above to parse each individual option and attempts
241 to parse each option into a variable of the specified type. The routine
242 can parse integers and long integers in either decimal, octal, hexadecimal
243 notation, unsigned integers and unsigned longs, strings and option switches.
244 Option switches are simply boolean variables that get turned on if the
247 Parameters are extracted from the command line by calling a user supplied
248 routine do_param() to handle each parameter as it is encountered. The
249 routine do_param() should accept a pointer to the parameter on the command
250 line and an integer representing how many parameters have been encountered
251 (ie: 1 if this is the first parameter, 10 if it is the 10th etc), and return
252 ALLDONE upon successfully parsing it or INVALID if the parameter was invalid.
254 We return either ALLDONE if all the options were successfully parsed,
255 INVALID if an invalid option was encountered or HELP if any of -h, -H or
256 -? were present on the command line.
257 ****************************************************************************/
270 char cmdstr[MAXARG*2 + 4];
272 /* Build the command string from the array of options */
274 strcpy(cmdstr,"hH?");
275 for (i = 0,opt = 3; i < num_opt; i++,opt++) {
276 cmdstr[opt] = optarr[i].opt;
277 if (optarr[i].type != OPT_SWITCH) {
284 opt = getcmdopt(argc,argv,cmdstr,&argument);
295 if (do_param == NULL)
297 if (do_param(argv[nextargv],param_num) == INVALID)
304 /* Search for the option in the option array. We are
305 * guaranteed to find it.
308 for (i = 0; i < num_opt; i++) {
309 if (optarr[i].opt == opt)
312 if (optarr[i].type == OPT_SWITCH)
313 *((ibool*)optarr[i].arg) = true;
315 if (parse_option(&optarr[i],argument) == INVALID)
323 /****************************************************************************
328 num_opt - Number of options in the table
329 optarr - Table of option descriptions
332 Prints the description of each option in a standard format to the standard
333 output device. The description for each option is obtained from the table
335 ****************************************************************************/
342 for (i = 0; i < num_opt; i++) {
343 if (optarr[i].type == OPT_SWITCH)
344 printf(" -%c %s\n",optarr[i].opt,optarr[i].desc);
346 printf(" -%c<arg> %s\n",optarr[i].opt,optarr[i].desc);
350 /****************************************************************************
355 moduleName - Module name for program
356 cmdLine - Command line to parse
357 pargc - Pointer to 'argc' parameter
358 pargv - Pointer to 'argv' parameter
359 maxArgc - Maximum argv array index
362 Parses a command line from a single string into the C style 'argc' and
363 'argv' format. Most useful for Windows programs where the command line
364 is passed in verbatim.
365 ****************************************************************************/
366 int parse_commandline(
373 static char str[512];
374 static char filename[260];
375 char *prevWord = NULL;
376 ibool inQuote = FALSE;
377 ibool noStrip = FALSE;
381 strcpy(filename,moduleName);
382 argv[argc++] = filename;
383 cmdLine = strncpy(str, cmdLine, sizeof(str)-1);
387 if (prevWord != NULL) {
391 argv [argc++] = prevWord;
402 if (prevWord != NULL) {
404 argv [argc++] = prevWord;
411 if (prevWord == NULL)
415 if (argc >= maxArgv - 1)
420 if ((prevWord != NULL || (inQuote && prevWord != NULL)) && argc < maxArgv - 1) {
422 argv [argc++] = prevWord;
426 /* Return updated parameters */
427 return (*pargc = argc);