1 //==========================================================================
5 // RedBoot command line parsing routine
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: gthomas
49 // This code is part of RedBoot (tm).
51 //####DESCRIPTIONEND####
53 //==========================================================================
56 #include <cyg/hal/hal_arch.h>
57 #include <cyg/hal/hal_intr.h>
58 #include <cyg/hal/hal_cache.h>
59 #include CYGHWR_MEMORY_LAYOUT_H
60 #include <cyg/hal/hal_tables.h>
62 // Define table boundaries
63 extern struct cmd __RedBoot_CMD_TAB__[], __RedBoot_CMD_TAB_END__;
66 // Scan through an input line and break it into "arguments". These
67 // are space delimited strings. Return a structure which points to
68 // the strings, similar to a Unix program. Multiple commands in the line
69 // are separated by ; similar to sh. If we find a semi we stop processing the
70 // line, terminate the current command with a null and return the start
71 // of the next command in *line. parse() can then be called again to
72 // process the next command on the line.
73 // Note: original input is destroyed by replacing the delimiters with
74 // null ('\0') characters for ease of use.
77 parse(char **line, int *argc, char **argv)
85 // Skip leading spaces
86 while (*cp && *cp == ' ') cp++;
88 break; // Line ended with a string of spaces
95 if (indx < MAX_ARGV) {
98 diag_printf("Too many arguments - stopped at: '%s'\n", cp);
104 } else if (*cp == ';') {
106 } else if (*cp == '"') {
107 // Swallow quote, scan till following one
108 if (argv[indx-1] == cp) {
112 while (*cp && *cp != '"') {
114 // Skip over escape - allows for escaped '"'
117 // Move string to swallow escapes
121 diag_printf("Unbalanced string!\n");
123 if (pp != cp) *pp = '\0';
138 return cmd_search(__RedBoot_CMD_TAB__, &__RedBoot_CMD_TAB_END__, argv[0]);
142 // Search through a list of commands
145 cmd_search(struct cmd *tab, struct cmd *tabend, char *arg)
148 struct cmd *cmd, *cmd2;
149 // Search command table
150 cmd_len = strlen(arg);
152 while (cmd != tabend) {
153 if (strncasecmp(arg, cmd->str, cmd_len) == 0) {
154 if (strlen(cmd->str) > cmd_len) {
155 // Check for ambiguous commands here
156 // Note: If there are commands which are not length-unique
157 // then this check will be invalid. E.g. "du" and "dump"
160 while (cmd2 != tabend) {
162 (strncasecmp(arg, cmd2->str, cmd_len) == 0)) {
164 diag_printf("Ambiguous command '%s', choices are: %s",
168 diag_printf(" %s", cmd2->str);
173 // At least one ambiguity found - fail the lookup
175 return (struct cmd *)0;
182 return (struct cmd *)0;
186 cmd_usage(struct cmd *tab, struct cmd *tabend, char *prefix)
190 diag_printf("Usage:\n");
191 for (cmd = tab; cmd != tabend; cmd++) {
192 diag_printf(" %s%s %s\n", prefix, cmd->str, cmd->usage);
198 // Initialize option table entry (required because these entries
199 // may have dynamic contents, thus cannot be statically initialized)
202 init_opts(struct option_info *opts, char flag, bool takes_arg,
203 int arg_type, void *arg, bool *arg_set, char *name)
206 opts->takes_arg = takes_arg;
207 opts->arg_type = arg_type,
209 opts->arg_set = arg_set;
214 // Scan command line arguments (argc/argv), processing options, etc.
217 // argc+1 if no default argument was specified,
218 // (index of first non-option argument)+1 otherwise
221 scan_opts(int argc, char *argv[], int first,
222 struct option_info *opts, int num_opts,
223 void *def_arg, int def_arg_type, char *def_descr)
228 bool def_arg_set = false;
231 struct option_info *opt;
233 if (def_arg && (def_arg_type == OPTION_ARG_TYPE_STR)) {
234 *(char **)def_arg = (char *)0;
237 for (j = 0; j < num_opts; j++, opt++) {
239 *opt->arg_set = false;
241 if (!opt->takes_arg) {
242 switch (opt->arg_type) {
243 case OPTION_ARG_TYPE_NUM:
244 *(int *)opt->arg = 0;
246 case OPTION_ARG_TYPE_FLG:
247 *(bool *)opt->arg = false;
252 for (i = first; i < argc; i++) {
253 if (argv[i][0] == '-') {
257 for (j = 0; j < num_opts; j++, opt++) {
258 if (c == opt->flag) {
259 if (opt->arg_set && *opt->arg_set) {
260 diag_printf("** Error: %s already specified\n", opt->name);
263 if (opt->takes_arg) {
264 if (argv[i][2] == '=') {
271 diag_printf("** Error: option '%c' [%s] requires an argument\n",
278 switch (opt->arg_type) {
279 case OPTION_ARG_TYPE_NUM:
280 if (!parse_num(s, (unsigned long *)opt->arg, 0, 0)) {
281 diag_printf("** Error: invalid number '%s' for %s\n",
286 case OPTION_ARG_TYPE_STR:
287 *(char **)opt->arg = s;
290 *opt->arg_set = true;
292 switch (opt->arg_type) {
293 case OPTION_ARG_TYPE_NUM:
294 *(int *)opt->arg = *(int *)opt->arg + 1;
296 case OPTION_ARG_TYPE_FLG:
297 *(bool *)opt->arg = true;
306 diag_printf("** Error: invalid flag '%c'\n", c);
313 diag_printf("** Error: %s already specified\n", def_descr);
316 switch (def_arg_type) {
317 case OPTION_ARG_TYPE_NUM:
318 if (!parse_num(argv[i], (unsigned long *)def_arg, 0, 0)) {
319 diag_printf("** Error: invalid number '%s' for %s\n",
324 case OPTION_ARG_TYPE_STR:
325 *(char **)def_arg = argv[i];
330 diag_printf("** Error: no default/non-flag arguments supported\n");
339 // Parse (scan) a number
342 parse_num(char *s, unsigned long *val, char **es, char *delim)
347 unsigned long result = 0;
350 while (*s == ' ') s++;
352 if (first && (s[0] == '0') && (_tolower(s[1]) == 'x')) {
358 if (_is_hex(c) && ((digit = _from_hex(c)) < radix)) {
360 #ifdef CYGPKG_HAL_MIPS
361 // FIXME: tx49 compiler generates 0x2539018 for MUL which
364 result = result << 4;
366 result = 10 * result;
369 result = (result * radix) + digit;
372 if (delim != (char *)0) {
373 // See if this character is one of the delimiters
375 while (*dp && (c != *dp)) dp++;
376 if (*dp) break; // Found a good delimiter
378 return false; // Malformatted number
382 if (es != (char **)0) {
389 parse_bool(char *s, bool *val)
391 while (*s == ' ') s++;
392 if ((*s == 't') || (*s == 'T')) {
395 // check for (partial) rest of the word and no extra including the
396 // terminating zero. "tru" will match; "truef" will not.
398 if ( *p != *s && *P != *s ) return false;
403 if ((*s == 'f') || (*s == 'F')) {
407 if ( *p != *s && *P != *s ) return false;