]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/MAI/bios_emulator/scitech/src/common/cmdline.c
* Patch by Thomas Frieden, 13 Nov 2002:
[karo-tx-uboot.git] / board / MAI / bios_emulator / scitech / src / common / cmdline.c
1 /****************************************************************************
2 *
3 *  ========================================================================
4 *
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
9 *
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.
14 *
15 *    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
16 *
17 *    The Initial Developer of the Original Code is SciTech Software, Inc.
18 *    All Rights Reserved.
19 *
20 *  ========================================================================
21 *
22 * Language:     ANSI C
23 * Environment:  any
24 *
25 * Description:  This module contains code to parse the command line,
26 *               extracting options and parameters in standard System V
27 *               style.
28 *
29 ****************************************************************************/
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include "cmdline.h"
35
36 /*------------------------- Global variables ------------------------------*/
37
38 int     nextargv    =   1;          /* Index into argv array            */
39 char    *nextchar   =   NULL;       /* Pointer to next character        */
40
41 /*-------------------------- Implementation -------------------------------*/
42
43 #define IS_SWITCH_CHAR(c)       ((c) == '-')
44 #define IS_NOT_SWITCH_CHAR(c)   ((c) != '-')
45
46 /****************************************************************************
47 DESCRIPTION:
48 Parse the command line for specific options
49
50 HEADER:
51 cmdline.h
52
53 PARAMETERS:
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
58
59 RETURNS:
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.
65
66 REMARKS:
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:
71
72     "abcd:e:f:"
73
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:
80
81     myprogram -adlines -b -f format infile outfile
82
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
85 argument format.
86
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
93 command line. eg:
94
95     myprogram -adlines infile -b outfile -f format
96
97 can be made to be a valid form of the above command line.
98 ****************************************************************************/
99 int getcmdopt(
100     int argc,
101     char **argv,
102     char *format,
103     char **argument)
104 {
105     char    ch;
106     char    *formatchar;
107
108     if (argc > nextargv) {
109         if (nextchar == NULL) {
110             nextchar = argv[nextargv];      /* Index next argument      */
111             if (nextchar == NULL) {
112                 nextargv++;
113                 return ALLDONE;             /* No more options          */
114                 }
115             if (IS_NOT_SWITCH_CHAR(*nextchar)) {
116                 nextchar = NULL;
117                 return PARAMETER;           /* We have a parameter      */
118                 }
119             nextchar++;                     /* Move past switch operator */
120             if (IS_SWITCH_CHAR(*nextchar)) {
121                 nextchar = NULL;
122                 return INVALID;             /* Ignore rest of line      */
123                 }
124             }
125         if ((ch = *(nextchar++)) == 0) {
126             nextchar = NULL;
127             return INVALID;                 /* No options on line       */
128             }
129
130         if (ch == ':' ||  (formatchar = strchr(format, ch)) == NULL)
131             return INVALID;
132
133         if (*(++formatchar) == ':') {   /* Expect an argument after option */
134             nextargv++;
135             if (*nextchar == 0) {
136                 if (argc <= nextargv)
137                     return INVALID;
138                 nextchar = argv[nextargv++];
139                 }
140             *argument = nextchar;
141             nextchar = NULL;
142             }
143         else {                      /* We have a switch style option    */
144             if (*nextchar == 0) {
145                 nextargv++;
146                 nextchar = NULL;
147                 }
148             *argument = NULL;
149             }
150         return ch;                  /* return the option specifier      */
151         }
152     nextchar = NULL;
153     nextargv++;
154     return ALLDONE;                 /* no arguments on command line     */
155 }
156
157 /****************************************************************************
158 PARAMETERS:
159 optarr      - Description for the option we are parsing
160 argument    - String to parse
161
162 RETURNS:
163 INVALID on error, ALLDONE on success.
164
165 REMARKS:
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(
171     Option *optarr,
172     char *argument)
173 {
174     int     num_read;
175
176     switch ((int)(optarr->type)) {
177         case OPT_INTEGER:
178             num_read = sscanf(argument,"%d",(int*)optarr->arg);
179             break;
180         case OPT_HEX:
181             num_read = sscanf(argument,"%x",(int*)optarr->arg);
182             break;
183         case OPT_OCTAL:
184             num_read = sscanf(argument,"%o",(int*)optarr->arg);
185             break;
186         case OPT_UNSIGNED:
187             num_read = sscanf(argument,"%u",(uint*)optarr->arg);
188             break;
189         case OPT_LINTEGER:
190             num_read = sscanf(argument,"%ld",(long*)optarr->arg);
191             break;
192         case OPT_LHEX:
193             num_read = sscanf(argument,"%lx",(long*)optarr->arg);
194             break;
195         case OPT_LOCTAL:
196             num_read = sscanf(argument,"%lo",(long*)optarr->arg);
197             break;
198         case OPT_LUNSIGNED:
199             num_read = sscanf(argument,"%lu",(ulong*)optarr->arg);
200             break;
201         case OPT_FLOAT:
202             num_read = sscanf(argument,"%f",(float*)optarr->arg);
203             break;
204         case OPT_DOUBLE:
205             num_read = sscanf(argument,"%lf",(double*)optarr->arg);
206             break;
207         case OPT_LDOUBLE:
208             num_read = sscanf(argument,"%Lf",(long double*)optarr->arg);
209             break;
210         case OPT_STRING:
211             num_read = 1;           /* This always works    */
212             *((char**)optarr->arg) = argument;
213             break;
214         default:
215             return INVALID;
216         }
217
218     if (num_read == 0)
219         return INVALID;
220     else
221         return ALLDONE;
222 }
223
224 /****************************************************************************
225 HEADER:
226 cmdline.h
227
228 PARAMETERS:
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
234
235 RETURNS:
236 ALLDONE, INVALID or HELP
237
238 REMARKS:
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
245 switch was parsed.
246
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.
253
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 ****************************************************************************/
258 int getargs(
259     int argc,
260     char *argv[],
261     int num_opt,
262     Option optarr[],
263     int (*do_param)(
264         char *param,
265         int num))
266 {
267     int     i,opt;
268     char    *argument;
269     int     param_num = 1;
270     char    cmdstr[MAXARG*2 + 4];
271
272     /* Build the command string from the array of options   */
273
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) {
278             cmdstr[++opt] = ':';
279             }
280         }
281     cmdstr[opt] = '\0';
282
283     for (;;) {
284         opt = getcmdopt(argc,argv,cmdstr,&argument);
285         switch (opt) {
286             case 'H':
287             case 'h':
288             case '?':
289                 return HELP;
290             case ALLDONE:
291                 return ALLDONE;
292             case INVALID:
293                 return INVALID;
294             case PARAMETER:
295                 if (do_param == NULL)
296                     return INVALID;
297                 if (do_param(argv[nextargv],param_num) == INVALID)
298                     return INVALID;
299                 nextargv++;
300                 param_num++;
301                 break;
302             default:
303
304                 /* Search for the option in the option array. We are
305                  * guaranteed to find it.
306                  */
307
308                 for (i = 0; i < num_opt; i++) {
309                     if (optarr[i].opt == opt)
310                         break;
311                     }
312                 if (optarr[i].type == OPT_SWITCH)
313                     *((ibool*)optarr[i].arg) = true;
314                 else {
315                     if (parse_option(&optarr[i],argument) == INVALID)
316                         return INVALID;
317                     }
318                 break;
319             }
320         }
321 }
322
323 /****************************************************************************
324 HEADER:
325 cmdline.h
326
327 PARAMETERS:
328 num_opt - Number of options in the table
329 optarr  - Table of option descriptions
330
331 REMARKS:
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
334 of options.
335 ****************************************************************************/
336 void print_desc(
337     int num_opt,
338     Option optarr[])
339 {
340     int     i;
341
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);
345         else
346             printf("  -%c<arg>  %s\n",optarr[i].opt,optarr[i].desc);
347         }
348 }
349
350 /****************************************************************************
351 HEADER:
352 cmdline.h
353
354 PARAMETERS:
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
360
361 REMARKS:
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(
367     char *moduleName,
368     char *cmdLine,
369     int *pargc,
370     char *argv[],
371     int maxArgv)
372 {
373     static char str[512];
374     static char filename[260];
375     char        *prevWord = NULL;
376     ibool        inQuote = FALSE;
377     ibool        noStrip = FALSE;
378     int         argc;
379
380     argc = 0;
381     strcpy(filename,moduleName);
382     argv[argc++] = filename;
383     cmdLine = strncpy(str, cmdLine, sizeof(str)-1);
384     while (*cmdLine) {
385         switch (*cmdLine) {
386             case '"' :
387                 if (prevWord != NULL) {
388                     if (inQuote) {
389                         if (!noStrip)
390                             *cmdLine = '\0';
391                         argv [argc++] = prevWord;
392                         prevWord = NULL;
393                         }
394                     else
395                         noStrip = TRUE;
396                     }
397                 inQuote = !inQuote;
398                 break;
399             case ' ' :
400             case '\t' :
401                 if (!inQuote) {
402                     if (prevWord != NULL) {
403                         *cmdLine = '\0';
404                         argv [argc++] = prevWord;
405                         prevWord = NULL;
406                         noStrip = FALSE;
407                         }
408                     }
409                 break;
410             default :
411                 if (prevWord == NULL)
412                     prevWord = cmdLine;
413                 break;
414                 }
415         if (argc >= maxArgv - 1)
416             break;
417         cmdLine++;
418         }
419
420     if ((prevWord != NULL || (inQuote && prevWord != NULL)) && argc < maxArgv - 1) {
421         *cmdLine = '\0';
422         argv [argc++] = prevWord;
423         }
424     argv[argc] = NULL;
425
426     /* Return updated parameters */
427     return (*pargc = argc);
428 }