comparison packages/redboot/current/src/parse.c @ 130:eb9fd8c04db3 ecos-sw-2000-10-23

Merge from eCos master repository on 2000-10-23-17:01:37-BST
author jlarmour
date Mon, 23 Oct 2000 17:10:57 +0000
parents
children 6b5f480c6929
comparison
equal deleted inserted replaced
129:605a0fc6f385 130:eb9fd8c04db3
1 //==========================================================================
2 //
3 // parse.c
4 //
5 // RedBoot command line parsing routine
6 //
7 //==========================================================================
8 //####COPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 // The contents of this file are subject to the Red Hat eCos Public License
12 // Version 1.1 (the "License"); you may not use this file except in
13 // compliance with the License. You may obtain a copy of the License at
14 // http://www.redhat.com/
15 //
16 // Software distributed under the License is distributed on an "AS IS"
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
18 // License for the specific language governing rights and limitations under
19 // the License.
20 //
21 // The Original Code is eCos - Embedded Configurable Operating System,
22 // released September 30, 1998.
23 //
24 // The Initial Developer of the Original Code is Red Hat.
25 // Portions created by Red Hat are
26 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
27 // All Rights Reserved.
28 // -------------------------------------------
29 //
30 //####COPYRIGHTEND####
31 //==========================================================================
32 //#####DESCRIPTIONBEGIN####
33 //
34 // Author(s): gthomas
35 // Contributors: gthomas
36 // Date: 2000-07-14
37 // Purpose:
38 // Description:
39 //
40 // This code is part of RedBoot (tm).
41 //
42 //####DESCRIPTIONEND####
43 //
44 //==========================================================================
45
46 #include <redboot.h>
47 #include <cyg/hal/hal_arch.h>
48 #include <cyg/hal/hal_intr.h>
49 #include <cyg/hal/hal_cache.h>
50 #include CYGHWR_MEMORY_LAYOUT_H
51 #include <cyg/hal/hal_tables.h>
52
53 // Define table boundaries
54 extern struct cmd __RedBoot_CMD_TAB__[], __RedBoot_CMD_TAB_END__;
55
56 //
57 // Scan through an input line and break it into "arguments". These
58 // are space delimited strings. Return a structure which points to
59 // the strings, similar to a Unix program.
60 // Note: original input is destroyed by replacing the delimiters with
61 // null ('\0') characters for ease of use.
62 //
63 struct cmd *
64 parse(char *line, int *argc, char **argv)
65 {
66 char *cp = line;
67 int indx = 0;
68
69 while (*cp) {
70 // Skip leading spaces
71 while (*cp && *cp == ' ') cp++;
72 if (!*cp) {
73 break; // Line ended with a string of spaces
74 }
75 argv[indx++] = cp;
76 while (*cp) {
77 if (*cp == ' ') {
78 *cp++ = '\0';
79 break;
80 } else if (*cp == '"') {
81 // Swallow quote, scan till following one
82 if (argv[indx-1] == cp) {
83 argv[indx-1] = ++cp;
84 }
85 while (*cp && *cp != '"') cp++;
86 if (!*cp) {
87 printf("Unbalanced string!\n");
88 } else {
89 *cp++ = '\0';
90 break;
91 }
92 } else {
93 cp++;
94 }
95 }
96 }
97 *argc = indx;
98 return cmd_search(__RedBoot_CMD_TAB__, &__RedBoot_CMD_TAB_END__, argv[0]);
99 }
100
101 //
102 // Search through a list of commands
103 //
104 struct cmd *
105 cmd_search(struct cmd *tab, struct cmd *tabend, char *arg)
106 {
107 int cmd_len;
108 struct cmd *cmd, *cmd2;
109 // Search command table
110 cmd_len = strlen(arg);
111 cmd = tab;
112 while (cmd != tabend) {
113 if (strncmpci(arg, cmd->str, cmd_len) == 0) {
114 if (strlen(cmd->str) > cmd_len) {
115 // Check for ambiguous commands here
116 // Note: If there are commands which are not length-unique
117 // then this check will be invalid. E.g. "du" and "dump"
118 bool first = true;
119 cmd2 = tab;
120 while (cmd2 != tabend) {
121 if ((cmd != cmd2) &&
122 (strncmpci(arg, cmd2->str, cmd_len) == 0)) {
123 if (first) {
124 printf("Ambiguous command '%s', choices are: %s", arg, cmd->str);
125 first = false;
126 }
127 printf(" %s", cmd2->str);
128 }
129 cmd2++;
130 }
131 if (!first) {
132 // At least one ambiguity found - fail the lookup
133 printf("\n");
134 return (struct cmd *)0;
135 }
136 }
137 return cmd;
138 }
139 cmd++;
140 }
141 return (struct cmd *)0;
142 }
143
144 void
145 cmd_usage(struct cmd *tab, struct cmd *tabend, char *prefix)
146 {
147 struct cmd *cmd;
148 printf("Usage:\n"); for (cmd = tab; cmd != tabend; cmd++) {
149 printf(" %s%s %s\n", prefix, cmd->str, cmd->usage);
150 }
151 }
152
153 // Option processing
154
155 // Initialize option table entry (required because these entries
156 // may have dynamic contents, thus cannot be statically initialized)
157 //
158 void
159 init_opts(struct option_info *opts, char flag, bool takes_arg,
160 int arg_type, void **arg, bool *arg_set, char *name)
161 {
162 opts->flag = flag;
163 opts->takes_arg = takes_arg;
164 opts->arg_type = arg_type,
165 opts->arg = arg;
166 opts->arg_set = arg_set;
167 opts->name = name;
168 }
169
170 //
171 // Scan command line arguments (argc/argv), processing options, etc.
172 //
173 bool
174 scan_opts(int argc, char *argv[], int first,
175 struct option_info *opts, int num_opts,
176 void **def_arg, int def_arg_type, char *def_descr)
177 {
178 bool ret = true;
179 bool flag_ok;
180 bool def_arg_set = false;
181 int i, j;
182 char c, *s;
183 struct option_info *opt;
184
185 if (def_arg && (def_arg_type == OPTION_ARG_TYPE_STR)) {
186 *def_arg = (char *)0;
187 }
188 opt = opts;
189 for (j = 0; j < num_opts; j++, opt++) {
190 if (opt->arg_set) {
191 *opt->arg_set = false;
192 }
193 if (!opt->takes_arg) {
194 switch (opt->arg_type) {
195 case OPTION_ARG_TYPE_NUM:
196 *(int *)opt->arg = 0;
197 break;
198 case OPTION_ARG_TYPE_FLG:
199 *(bool *)opt->arg = false;
200 break;
201 }
202 }
203 }
204 for (i = first; i < argc; i++) {
205 if (argv[i][0] == '-') {
206 c = argv[i][1];
207 flag_ok = false;
208 opt = opts;
209 for (j = 0; j < num_opts; j++, opt++) {
210 if (c == opt->flag) {
211 if (opt->arg_set && *opt->arg_set) {
212 printf("** Error: %s already specified\n", opt->name);
213 ret = false;
214 }
215 if (opt->takes_arg) {
216 if (argv[i][2] == '=') {
217 s = &argv[i][3];
218 } else {
219 s = argv[i+1];
220 i++;
221 }
222 switch (opt->arg_type) {
223 case OPTION_ARG_TYPE_NUM:
224 if (!parse_num(s, (unsigned long *)opt->arg, 0, 0)) {
225 printf("** Error: invalid number '%s' for %s\n", s, opt->name);
226 ret = false;
227 }
228 break;
229 case OPTION_ARG_TYPE_STR:
230 *opt->arg = s;
231 break;
232 }
233 *opt->arg_set = true;
234 } else {
235 switch (opt->arg_type) {
236 case OPTION_ARG_TYPE_NUM:
237 *(int *)opt->arg = *(int *)opt->arg + 1;
238 break;
239 case OPTION_ARG_TYPE_FLG:
240 *(bool *)opt->arg = true;
241 break;
242 }
243 }
244 flag_ok = true;
245 break;
246 }
247 }
248 if (!flag_ok) {
249 printf("** Error: invalid flag '%c'\n", c);
250 ret = false;
251 }
252 } else {
253 if (def_arg) {
254 if (def_arg_set) {
255 printf("** Error: %s already specified\n", def_descr);
256 ret = false;
257 }
258 switch (def_arg_type) {
259 case OPTION_ARG_TYPE_NUM:
260 if (!parse_num(argv[i], (unsigned long *)def_arg, 0, 0)) {
261 printf("** Error: invalid number '%s' for %s\n", argv[i], def_descr);
262 ret = false;
263 }
264 break;
265 case OPTION_ARG_TYPE_STR:
266 *def_arg = argv[i];
267 break;
268 }
269 def_arg_set = true;
270 } else {
271 printf("** Error: no default/non-flag arguments supported\n");
272 ret = false;
273 }
274 }
275 }
276 return ret;
277 }
278
279 //
280 // Parse (scan) a number
281 //
282 bool
283 parse_num(char *s, unsigned long *val, char **es, char *delim)
284 {
285 bool first = true;
286 int radix = 10;
287 char c;
288 unsigned long result = 0;
289 int digit;
290
291 while (*s == ' ') s++;
292 while (*s) {
293 if (first && (s[0] == '0') && (tolower(s[1]) == 'x')) {
294 radix = 16;
295 s += 2;
296 }
297 first = false;
298 c = *s++;
299 if (_is_hex(c) && ((digit = _from_hex(c)) < radix)) {
300 // Valid digit
301 result = (result * radix) + digit;
302 } else {
303 if (delim != (char *)0) {
304 // See if this character is one of the delimiters
305 char *dp = delim;
306 while (*dp && (c != *dp)) dp++;
307 if (*dp) break; // Found a good delimiter
308 }
309 return false; // Malformatted number
310 }
311 }
312 *val = result;
313 if (es != (char **)0) {
314 *es = s;
315 }
316 return true;
317 }
318
319 bool
320 parse_bool(char *s, bool *val)
321 {
322 while (*s == ' ') s++;
323 if ((*s == 't') || (*s == 'T')) {
324 *val = true;
325 } else
326 if ((*s == 'f') || (*s == 'F')) {
327 *val = false;
328 } else {
329 return false;
330 }
331 return true;
332 }
333