Commit | Line | Data |
---|---|---|
4ede3a83 DE |
1 | /* Simulator option handling. |
2 | Copyright (C) 1996, 1997 Free Software Foundation, Inc. | |
3 | Contributed by Cygnus Support. | |
4 | ||
5 | This file is part of GDB, the GNU debugger. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License along | |
18 | with this program; if not, write to the Free Software Foundation, Inc., | |
19 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | #include "sim-main.h" | |
22 | #ifdef HAVE_STRING_H | |
23 | #include <string.h> | |
24 | #else | |
25 | #ifdef HAVE_STRINGS_H | |
26 | #include <strings.h> | |
27 | #endif | |
28 | #endif | |
50a2a691 AC |
29 | #ifdef HAVE_STDLIB_H |
30 | #include <stdlib.h> | |
31 | #endif | |
32 | #include <ctype.h> | |
4ede3a83 DE |
33 | #include "libiberty.h" |
34 | #include "../libiberty/alloca-conf.h" | |
35 | #include "sim-options.h" | |
36 | #include "sim-io.h" | |
50a2a691 | 37 | #include "sim-assert.h" |
4ede3a83 | 38 | |
18c319ae AC |
39 | #include "bfd.h" |
40 | ||
4ede3a83 DE |
41 | /* Add a set of options to the simulator. |
42 | TABLE is an array of OPTIONS terminated by a NULL `opt.name' entry. | |
43 | This is intended to be called by modules in their `install' handler. */ | |
44 | ||
45 | SIM_RC | |
46 | sim_add_option_table (sd, table) | |
47 | SIM_DESC sd; | |
48 | const OPTION *table; | |
49 | { | |
50 | struct option_list *ol = ((struct option_list *) | |
51 | xmalloc (sizeof (struct option_list))); | |
52 | ||
53 | /* Note: The list is constructed in the reverse order we're called so | |
54 | later calls will override earlier ones (in case that ever happens). | |
55 | This is the intended behaviour. */ | |
56 | ol->next = STATE_OPTIONS (sd); | |
57 | ol->options = table; | |
58 | STATE_OPTIONS (sd) = ol; | |
59 | ||
60 | return SIM_RC_OK; | |
61 | } | |
62 | ||
63 | /* Standard option table. | |
64 | Modules may specify additional ones. | |
65 | The caller of sim_parse_args may also specify additional options | |
66 | by calling sim_add_option_table first. */ | |
67 | ||
68 | static DECLARE_OPTION_HANDLER (standard_option_handler); | |
69 | ||
70 | /* FIXME: We shouldn't print in --help output options that aren't usable. | |
71 | Some fine tuning will be necessary. One can either move less general | |
72 | options to another table or use a HAVE_FOO macro to ifdef out unavailable | |
73 | options. */ | |
74 | ||
e65bd1d8 DE |
75 | /* ??? One might want to conditionally compile out the entries that |
76 | aren't enabled. There's a distinction, however, between options a | |
77 | simulator can't support and options that haven't been configured in. | |
78 | Certainly options a simulator can't support shouldn't appear in the | |
79 | output of --help. Whether the same thing applies to options that haven't | |
80 | been configured in or not isn't something I can get worked up over. | |
81 | [Note that conditionally compiling them out might simply involve moving | |
82 | the option to another table.] | |
83 | If you decide to conditionally compile them out as well, delete this | |
84 | comment and add a comment saying that that is the rule. */ | |
85 | ||
4ede3a83 DE |
86 | #define OPTION_DEBUG_INSN (OPTION_START + 0) |
87 | #define OPTION_DEBUG_FILE (OPTION_START + 1) | |
43c53e07 | 88 | #define OPTION_DO_COMMAND (OPTION_START + 2) |
18c319ae AC |
89 | #define OPTION_ARCHITECTURE (OPTION_START + 3) |
90 | #define OPTION_TARGET (OPTION_START + 4) | |
4ede3a83 DE |
91 | |
92 | static const OPTION standard_options[] = | |
93 | { | |
94 | { {"verbose", no_argument, NULL, 'v'}, | |
95 | 'v', NULL, "Verbose output", | |
96 | standard_option_handler }, | |
97 | ||
e65bd1d8 DE |
98 | #if defined (SIM_HAVE_BIENDIAN) /* ??? && WITH_TARGET_BYTE_ORDER == 0 */ |
99 | { {"endian", required_argument, NULL, 'E'}, | |
100 | 'E', "big|little", "Set endianness", | |
101 | standard_option_handler }, | |
102 | #endif | |
103 | ||
4ede3a83 DE |
104 | { {"debug", no_argument, NULL, 'D'}, |
105 | 'D', NULL, "Print debugging messages", | |
106 | standard_option_handler }, | |
107 | { {"debug-insn", no_argument, NULL, OPTION_DEBUG_INSN}, | |
108 | '\0', NULL, "Print instruction debugging messages", | |
109 | standard_option_handler }, | |
110 | { {"debug-file", required_argument, NULL, OPTION_DEBUG_FILE}, | |
111 | '\0', "FILE NAME", "Specify debugging output file", | |
112 | standard_option_handler }, | |
113 | ||
4ede3a83 DE |
114 | #ifdef SIM_H8300 /* FIXME: Should be movable to h8300 dir. */ |
115 | { {"h8300h", no_argument, NULL, 'h'}, | |
116 | 'h', NULL, "Indicate the CPU is h8/300h or h8/300s", | |
117 | standard_option_handler }, | |
118 | #endif | |
119 | ||
4ede3a83 DE |
120 | #ifdef SIM_HAVE_FLATMEM |
121 | { {"mem-size", required_argument, NULL, 'm'}, | |
122 | 'm', "MEMORY SIZE", "Specify memory size", | |
123 | standard_option_handler }, | |
124 | #endif | |
125 | ||
43c53e07 | 126 | { {"do-command", required_argument, NULL, OPTION_DO_COMMAND}, |
50a2a691 | 127 | '\0', "COMMAND", ""/*undocumented*/, |
43c53e07 AC |
128 | standard_option_handler }, |
129 | ||
4ede3a83 DE |
130 | { {"help", no_argument, NULL, 'H'}, |
131 | 'H', NULL, "Print help information", | |
132 | standard_option_handler }, | |
133 | ||
18c319ae AC |
134 | { {"architecture", required_argument, NULL, OPTION_ARCHITECTURE}, |
135 | '\0', "MACHINE", "Specify the architecture to use", | |
136 | standard_option_handler }, | |
137 | ||
138 | { {"target", required_argument, NULL, OPTION_TARGET}, | |
139 | '\0', "BFDNAME", "Specify the object-code format for the object files", | |
140 | standard_option_handler }, | |
141 | ||
4ede3a83 DE |
142 | { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } |
143 | }; | |
144 | ||
145 | static SIM_RC | |
50a2a691 | 146 | standard_option_handler (sd, opt, arg, is_command) |
4ede3a83 DE |
147 | SIM_DESC sd; |
148 | int opt; | |
149 | char *arg; | |
50a2a691 | 150 | int is_command; |
4ede3a83 DE |
151 | { |
152 | int i,n; | |
4ede3a83 DE |
153 | |
154 | switch (opt) | |
155 | { | |
156 | case 'v' : | |
157 | STATE_VERBOSE_P (sd) = 1; | |
158 | break; | |
159 | ||
e65bd1d8 DE |
160 | #ifdef SIM_HAVE_BIENDIAN |
161 | case 'E' : | |
162 | if (strcmp (arg, "big") == 0) | |
163 | { | |
164 | if (WITH_TARGET_BYTE_ORDER == LITTLE_ENDIAN) | |
165 | { | |
166 | sim_io_eprintf (sd, "Simulator compiled for little endian only.\n"); | |
167 | return SIM_RC_FAIL; | |
168 | } | |
169 | /* FIXME:wip: Need to set something in STATE_CONFIG. */ | |
50a2a691 | 170 | current_target_byte_order = BIG_ENDIAN; |
e65bd1d8 DE |
171 | } |
172 | else if (strcmp (arg, "little") == 0) | |
173 | { | |
174 | if (WITH_TARGET_BYTE_ORDER == BIG_ENDIAN) | |
175 | { | |
176 | sim_io_eprintf (sd, "Simulator compiled for big endian only.\n"); | |
177 | return SIM_RC_FAIL; | |
178 | } | |
179 | /* FIXME:wip: Need to set something in STATE_CONFIG. */ | |
50a2a691 | 180 | current_target_byte_order = LITTLE_ENDIAN; |
e65bd1d8 DE |
181 | } |
182 | else | |
183 | { | |
184 | sim_io_eprintf (sd, "Invalid endian specification `%s'\n", arg); | |
185 | return SIM_RC_FAIL; | |
186 | } | |
187 | break; | |
188 | #endif | |
189 | ||
4ede3a83 DE |
190 | case 'D' : |
191 | if (! WITH_DEBUG) | |
192 | sim_io_eprintf (sd, "Debugging not compiled in, `-D' ignored\n"); | |
193 | else | |
194 | { | |
195 | for (n = 0; n < MAX_NR_PROCESSORS; ++n) | |
196 | for (i = 0; i < MAX_DEBUG_VALUES; ++i) | |
197 | CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[i] = 1; | |
198 | } | |
199 | break; | |
200 | ||
201 | case OPTION_DEBUG_INSN : | |
202 | if (! WITH_DEBUG) | |
203 | sim_io_eprintf (sd, "Debugging not compiled in, `--debug-insn' ignored\n"); | |
204 | else | |
205 | { | |
206 | for (n = 0; n < MAX_NR_PROCESSORS; ++n) | |
207 | CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[DEBUG_INSN_IDX] = 1; | |
208 | } | |
209 | break; | |
210 | ||
211 | case OPTION_DEBUG_FILE : | |
212 | if (! WITH_DEBUG) | |
213 | sim_io_eprintf (sd, "Debugging not compiled in, `--debug-file' ignored\n"); | |
214 | else | |
215 | { | |
216 | FILE *f = fopen (arg, "w"); | |
217 | ||
218 | if (f == NULL) | |
219 | { | |
220 | sim_io_eprintf (sd, "Unable to open debug output file `%s'\n", arg); | |
221 | return SIM_RC_FAIL; | |
222 | } | |
223 | for (n = 0; n < MAX_NR_PROCESSORS; ++n) | |
224 | CPU_DEBUG_FILE (STATE_CPU (sd, n)) = f; | |
225 | } | |
226 | break; | |
227 | ||
4ede3a83 DE |
228 | #ifdef SIM_H8300 /* FIXME: Can be moved to h8300 dir. */ |
229 | case 'h' : | |
230 | set_h8300h (1); | |
231 | break; | |
232 | #endif | |
233 | ||
4ede3a83 DE |
234 | #ifdef SIM_HAVE_FLATMEM |
235 | case 'm': | |
43c53e07 AC |
236 | { |
237 | unsigned long ul = strtol (arg, NULL, 0); | |
238 | /* 16384: some minimal amount */ | |
239 | if (! isdigit (arg[0]) || ul < 16384) | |
240 | { | |
241 | sim_io_eprintf (sd, "Invalid memory size `%s'", arg); | |
242 | return SIM_RC_FAIL; | |
243 | } | |
244 | STATE_MEM_SIZE (sd) = ul; | |
245 | } | |
4ede3a83 DE |
246 | break; |
247 | #endif | |
248 | ||
43c53e07 AC |
249 | case OPTION_DO_COMMAND: |
250 | sim_do_command (sd, arg); | |
251 | break; | |
252 | ||
18c319ae AC |
253 | case OPTION_ARCHITECTURE: |
254 | { | |
255 | const struct bfd_arch_info *ap = bfd_scan_arch (arg); | |
256 | if (ap == NULL) | |
257 | { | |
258 | sim_io_eprintf (sd, "Architecture `%s' unknown\n", arg); | |
259 | return SIM_RC_FAIL; | |
260 | } | |
261 | STATE_ARCHITECTURE (sd) = ap; | |
262 | break; | |
263 | } | |
264 | ||
265 | case OPTION_TARGET: | |
266 | { | |
36db8e64 | 267 | STATE_TARGET (sd) = xstrdup (arg); |
18c319ae AC |
268 | break; |
269 | } | |
270 | ||
4ede3a83 | 271 | case 'H': |
2f2e6c5d | 272 | sim_print_help (sd, is_command); |
4ede3a83 DE |
273 | if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) |
274 | exit (0); | |
275 | /* FIXME: 'twould be nice to do something similar if gdb. */ | |
276 | break; | |
277 | } | |
278 | ||
279 | return SIM_RC_OK; | |
280 | } | |
281 | ||
c967f187 | 282 | /* Add the standard option list to the simulator. */ |
4ede3a83 DE |
283 | |
284 | SIM_RC | |
c967f187 | 285 | standard_install (SIM_DESC sd) |
4ede3a83 | 286 | { |
50a2a691 | 287 | SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); |
4ede3a83 DE |
288 | if (sim_add_option_table (sd, standard_options) != SIM_RC_OK) |
289 | return SIM_RC_FAIL; | |
4ede3a83 DE |
290 | return SIM_RC_OK; |
291 | } | |
292 | ||
293 | /* Return non-zero if arg is a duplicate argument. | |
294 | If ARG is NULL, initialize. */ | |
295 | ||
296 | #define ARG_HASH_SIZE 97 | |
297 | #define ARG_HASH(a) ((256 * (unsigned char) a[0] + (unsigned char) a[1]) % ARG_HASH_SIZE) | |
298 | ||
299 | static int | |
300 | dup_arg_p (arg) | |
301 | char *arg; | |
302 | { | |
303 | int hash; | |
304 | static char **arg_table = NULL; | |
305 | ||
306 | if (arg == NULL) | |
307 | { | |
308 | if (arg_table == NULL) | |
309 | arg_table = (char **) xmalloc (ARG_HASH_SIZE * sizeof (char *)); | |
310 | memset (arg_table, 0, ARG_HASH_SIZE * sizeof (char *)); | |
311 | return 0; | |
312 | } | |
313 | ||
314 | hash = ARG_HASH (arg); | |
315 | while (arg_table[hash] != NULL) | |
316 | { | |
317 | if (strcmp (arg, arg_table[hash]) == 0) | |
318 | return 1; | |
319 | /* We assume there won't be more than ARG_HASH_SIZE arguments so we | |
320 | don't check if the table is full. */ | |
321 | if (++hash == ARG_HASH_SIZE) | |
322 | hash = 0; | |
323 | } | |
324 | arg_table[hash] = arg; | |
325 | return 0; | |
326 | } | |
327 | ||
328 | /* Called by sim_open to parse the arguments. */ | |
329 | ||
330 | SIM_RC | |
331 | sim_parse_args (sd, argv) | |
332 | SIM_DESC sd; | |
333 | char **argv; | |
334 | { | |
335 | int i, argc, num_opts; | |
336 | char *p, *short_options; | |
337 | /* The `val' option struct entry is dynamically assigned for options that | |
338 | only come in the long form. ORIG_VAL is used to get the original value | |
339 | back. */ | |
8786d426 | 340 | unsigned char *orig_val; |
4ede3a83 DE |
341 | struct option *lp, *long_options; |
342 | const struct option_list *ol; | |
343 | const OPTION *opt; | |
344 | OPTION_HANDLER **handlers; | |
345 | ||
346 | /* Count the number of arguments. */ | |
347 | for (argc = 0; argv[argc] != NULL; ++argc) | |
348 | continue; | |
349 | ||
350 | /* Count the number of options. */ | |
351 | num_opts = 0; | |
352 | for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) | |
353 | for (opt = ol->options; opt->opt.name != NULL; ++opt) | |
354 | ++num_opts; | |
355 | ||
356 | /* Initialize duplicate argument checker. */ | |
357 | (void) dup_arg_p (NULL); | |
358 | ||
359 | /* Build the option table for getopt. */ | |
360 | long_options = (struct option *) alloca ((num_opts + 1) * sizeof (struct option)); | |
361 | lp = long_options; | |
362 | short_options = (char *) alloca (num_opts * 3 + 1); | |
363 | p = short_options; | |
364 | #if 0 /* ??? necessary anymore? */ | |
365 | /* Set '+' as first char so argument permutation isn't done. This is done | |
366 | to workaround a problem with invoking getopt_long in run.c.: optind gets | |
367 | decremented when the program name is reached. */ | |
368 | *p++ = '+'; | |
369 | #endif | |
370 | handlers = (OPTION_HANDLER **) alloca (256 * sizeof (OPTION_HANDLER *)); | |
371 | memset (handlers, 0, 256 * sizeof (OPTION_HANDLER *)); | |
8786d426 | 372 | orig_val = (unsigned char *) alloca (256); |
4ede3a83 DE |
373 | for (i = OPTION_START, ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) |
374 | for (opt = ol->options; opt->opt.name != NULL; ++opt) | |
375 | { | |
376 | if (dup_arg_p (opt->opt.name)) | |
377 | continue; | |
378 | if (opt->shortopt != 0) | |
379 | { | |
380 | *p++ = opt->shortopt; | |
381 | if (opt->opt.has_arg == required_argument) | |
382 | *p++ = ':'; | |
383 | else if (opt->opt.has_arg == optional_argument) | |
384 | { *p++ = ':'; *p++ = ':'; } | |
385 | } | |
386 | *lp = opt->opt; | |
387 | /* Dynamically assign `val' numbers for long options that don't have | |
388 | a short option equivalent. */ | |
389 | if (OPTION_LONG_ONLY_P (opt->opt.val)) | |
390 | lp->val = i++; | |
391 | handlers[(unsigned char) lp->val] = opt->handler; | |
392 | orig_val[(unsigned char) lp->val] = opt->opt.val; | |
393 | ++lp; | |
394 | } | |
395 | *p = 0; | |
396 | lp->name = NULL; | |
397 | ||
398 | /* Ensure getopt is initialized. */ | |
399 | optind = 0; | |
400 | while (1) | |
401 | { | |
402 | int longind, optc; | |
403 | ||
404 | optc = getopt_long (argc, argv, short_options, long_options, &longind); | |
405 | if (optc == -1) | |
406 | { | |
407 | if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) | |
d07dddd2 | 408 | STATE_PROG_ARGV (sd) = sim_copy_argv (argv + optind); |
4ede3a83 DE |
409 | break; |
410 | } | |
411 | if (optc == '?') | |
412 | return SIM_RC_FAIL; | |
413 | ||
50a2a691 | 414 | if ((*handlers[optc]) (sd, orig_val[optc], optarg, 0/*!is_command*/) == SIM_RC_FAIL) |
4ede3a83 DE |
415 | return SIM_RC_FAIL; |
416 | } | |
417 | ||
418 | return SIM_RC_OK; | |
419 | } | |
420 | ||
421 | /* Print help messages for the options. */ | |
422 | ||
423 | void | |
2f2e6c5d | 424 | sim_print_help (sd, is_command) |
4ede3a83 | 425 | SIM_DESC sd; |
2f2e6c5d | 426 | int is_command; |
4ede3a83 DE |
427 | { |
428 | const struct option_list *ol; | |
429 | const OPTION *opt; | |
430 | ||
431 | if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) | |
432 | sim_io_printf (sd, "Usage: %s [options] program [program args]\n", | |
433 | STATE_MY_NAME (sd)); | |
434 | ||
435 | /* Initialize duplicate argument checker. */ | |
436 | (void) dup_arg_p (NULL); | |
437 | ||
d07dddd2 AC |
438 | if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) |
439 | sim_io_printf (sd, "Options:\n"); | |
440 | else | |
441 | sim_io_printf (sd, "Commands:\n"); | |
442 | ||
4ede3a83 DE |
443 | for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) |
444 | for (opt = ol->options; opt->opt.name != NULL; ++opt) | |
445 | { | |
446 | int comma, len; | |
447 | const OPTION *o; | |
448 | ||
449 | if (dup_arg_p (opt->opt.name)) | |
450 | continue; | |
451 | ||
452 | if (opt->doc == NULL) | |
453 | continue; | |
454 | ||
50a2a691 AC |
455 | if (opt->doc_name != NULL && opt->doc_name [0] == '\0') |
456 | continue; | |
457 | ||
4ede3a83 DE |
458 | sim_io_printf (sd, " "); |
459 | ||
460 | comma = 0; | |
461 | len = 2; | |
462 | ||
2f2e6c5d | 463 | if (!is_command) |
4ede3a83 | 464 | { |
2f2e6c5d AC |
465 | o = opt; |
466 | do | |
4ede3a83 | 467 | { |
2f2e6c5d | 468 | if (o->shortopt != '\0') |
4ede3a83 | 469 | { |
2f2e6c5d AC |
470 | sim_io_printf (sd, "%s-%c", comma ? ", " : "", o->shortopt); |
471 | len += (comma ? 2 : 0) + 2; | |
472 | if (o->arg != NULL) | |
43c53e07 | 473 | { |
2f2e6c5d AC |
474 | if (o->opt.has_arg == optional_argument) |
475 | { | |
476 | sim_io_printf (sd, "[%s]", o->arg); | |
477 | len += 1 + strlen (o->arg) + 1; | |
478 | } | |
479 | else | |
480 | { | |
481 | sim_io_printf (sd, " %s", o->arg); | |
482 | len += 1 + strlen (o->arg); | |
483 | } | |
4ede3a83 | 484 | } |
2f2e6c5d | 485 | comma = 1; |
4ede3a83 | 486 | } |
2f2e6c5d | 487 | ++o; |
4ede3a83 | 488 | } |
2f2e6c5d | 489 | while (o->opt.name != NULL && o->doc == NULL); |
4ede3a83 | 490 | } |
2f2e6c5d | 491 | |
4ede3a83 DE |
492 | o = opt; |
493 | do | |
494 | { | |
50a2a691 AC |
495 | const char *name; |
496 | if (o->doc_name != NULL) | |
497 | name = o->doc_name; | |
498 | else | |
499 | name = o->opt.name; | |
500 | if (name != NULL) | |
4ede3a83 | 501 | { |
2f2e6c5d | 502 | sim_io_printf (sd, "%s%s%s", |
4ede3a83 | 503 | comma ? ", " : "", |
2f2e6c5d | 504 | is_command ? "" : "--", |
50a2a691 | 505 | name); |
4ede3a83 | 506 | len += ((comma ? 2 : 0) |
2f2e6c5d | 507 | + (is_command ? 0 : 2) |
50a2a691 | 508 | + strlen (name)); |
4ede3a83 DE |
509 | if (o->arg != NULL) |
510 | { | |
43c53e07 AC |
511 | if (o->opt.has_arg == optional_argument) |
512 | { | |
513 | sim_io_printf (sd, " [%s]", o->arg); | |
514 | len += 2 + strlen (o->arg) + 1; | |
515 | } | |
516 | else | |
517 | { | |
518 | sim_io_printf (sd, " %s", o->arg); | |
519 | len += 1 + strlen (o->arg); | |
520 | } | |
4ede3a83 DE |
521 | } |
522 | comma = 1; | |
523 | } | |
524 | ++o; | |
525 | } | |
526 | while (o->opt.name != NULL && o->doc == NULL); | |
527 | ||
528 | if (len >= 30) | |
529 | { | |
530 | sim_io_printf (sd, "\n"); | |
531 | len = 0; | |
532 | } | |
533 | ||
534 | for (; len < 30; len++) | |
535 | sim_io_printf (sd, " "); | |
536 | ||
537 | sim_io_printf (sd, "%s\n", opt->doc); | |
538 | } | |
539 | ||
d07dddd2 AC |
540 | sim_io_printf (sd, "\n"); |
541 | sim_io_printf (sd, "Note: Depending on the simulator configuration some %ss\n", | |
542 | STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE ? "option" : "command"); | |
543 | sim_io_printf (sd, " may not be applicable\n"); | |
544 | ||
4ede3a83 DE |
545 | if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) |
546 | { | |
547 | sim_io_printf (sd, "\n"); | |
548 | sim_io_printf (sd, "program args Arguments to pass to simulated program.\n"); | |
549 | sim_io_printf (sd, " Note: Very few simulators support this.\n"); | |
550 | } | |
551 | } | |
43c53e07 AC |
552 | |
553 | ||
554 | ||
555 | ||
556 | SIM_RC | |
557 | sim_args_command (sd, cmd) | |
558 | SIM_DESC sd; | |
559 | char *cmd; | |
560 | { | |
561 | /* something to do? */ | |
562 | if (cmd == NULL) | |
563 | return SIM_RC_OK; /* FIXME - perhaphs help would be better */ | |
564 | ||
565 | if (cmd [0] == '-') | |
566 | { | |
567 | /* user specified -<opt> ... form? */ | |
568 | char **argv = buildargv (cmd); | |
569 | SIM_RC rc = sim_parse_args (sd, argv); | |
570 | freeargv (argv); | |
571 | return rc; | |
572 | } | |
573 | else | |
574 | { | |
575 | /* user specified <opt> form? */ | |
576 | const struct option_list *ol; | |
577 | const OPTION *opt; | |
578 | char **argv = buildargv (cmd); | |
50a2a691 AC |
579 | /* most recent option match */ |
580 | const OPTION *matching_opt = NULL; | |
581 | int matching_argi = -1; | |
582 | if (argv [0] != NULL) | |
583 | for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) | |
584 | for (opt = ol->options; opt->opt.name != NULL; ++opt) | |
585 | { | |
586 | int argi = 0; | |
587 | const char *name = opt->opt.name; | |
588 | while (strncmp (name, argv [argi], strlen (argv [argi])) == 0) | |
589 | { | |
590 | name = &name [strlen (argv[argi])]; | |
591 | if (name [0] == '-') | |
592 | { | |
593 | /* leading match ...<a-b-c>-d-e-f - continue search */ | |
594 | name ++; /* skip `-' */ | |
595 | argi ++; | |
596 | continue; | |
597 | } | |
598 | else if (name [0] == '\0') | |
599 | { | |
600 | /* exact match ...<a-b-c-d-e-f> - better than before? */ | |
601 | if (argi > matching_argi) | |
602 | { | |
603 | matching_argi = argi; | |
604 | matching_opt = opt; | |
605 | } | |
606 | break; | |
607 | } | |
608 | else | |
43c53e07 | 609 | break; |
50a2a691 AC |
610 | } |
611 | } | |
612 | if (matching_opt != NULL) | |
613 | { | |
614 | switch (matching_opt->opt.has_arg) | |
615 | { | |
616 | case no_argument: | |
617 | if (argv [matching_argi + 1] == NULL) | |
618 | matching_opt->handler (sd, matching_opt->opt.val, | |
619 | NULL, 1/*is_command*/); | |
620 | else | |
621 | sim_io_eprintf (sd, "Command `%s' takes no arguments\n", | |
622 | matching_opt->opt.name); | |
623 | break; | |
624 | case optional_argument: | |
625 | if (argv [matching_argi + 1] == NULL) | |
626 | matching_opt->handler (sd, matching_opt->opt.val, | |
627 | NULL, 1/*is_command*/); | |
628 | else if (argv [matching_argi + 2] == NULL) | |
629 | matching_opt->handler (sd, matching_opt->opt.val, | |
630 | argv [matching_argi + 1], 1/*is_command*/); | |
631 | else | |
632 | sim_io_eprintf (sd, "Command `%s' requires no more than one argument\n", | |
633 | matching_opt->opt.name); | |
634 | break; | |
635 | case required_argument: | |
636 | if (argv [matching_argi + 1] == NULL) | |
637 | sim_io_eprintf (sd, "Command `%s' requires an argument\n", | |
638 | matching_opt->opt.name); | |
639 | else if (argv [matching_argi + 2] == NULL) | |
640 | matching_opt->handler (sd, matching_opt->opt.val, | |
641 | argv [matching_argi + 1], 1/*is_command*/); | |
642 | else | |
643 | sim_io_eprintf (sd, "Command `%s' requires only one argument\n", | |
644 | matching_opt->opt.name); | |
645 | } | |
646 | return SIM_RC_OK; | |
647 | } | |
43c53e07 | 648 | } |
50a2a691 AC |
649 | |
650 | /* didn't find anything that remotly matched */ | |
43c53e07 AC |
651 | return SIM_RC_FAIL; |
652 | } |