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) | |
d0b59aa5 | 91 | #define OPTION_ARCHITECTURE_INFO (OPTION_START + 5) |
4ede3a83 DE |
92 | |
93 | static const OPTION standard_options[] = | |
94 | { | |
95 | { {"verbose", no_argument, NULL, 'v'}, | |
96 | 'v', NULL, "Verbose output", | |
97 | standard_option_handler }, | |
98 | ||
e65bd1d8 DE |
99 | #if defined (SIM_HAVE_BIENDIAN) /* ??? && WITH_TARGET_BYTE_ORDER == 0 */ |
100 | { {"endian", required_argument, NULL, 'E'}, | |
101 | 'E', "big|little", "Set endianness", | |
102 | standard_option_handler }, | |
103 | #endif | |
104 | ||
4ede3a83 DE |
105 | { {"debug", no_argument, NULL, 'D'}, |
106 | 'D', NULL, "Print debugging messages", | |
107 | standard_option_handler }, | |
108 | { {"debug-insn", no_argument, NULL, OPTION_DEBUG_INSN}, | |
109 | '\0', NULL, "Print instruction debugging messages", | |
110 | standard_option_handler }, | |
111 | { {"debug-file", required_argument, NULL, OPTION_DEBUG_FILE}, | |
112 | '\0', "FILE NAME", "Specify debugging output file", | |
113 | standard_option_handler }, | |
114 | ||
4ede3a83 DE |
115 | #ifdef SIM_H8300 /* FIXME: Should be movable to h8300 dir. */ |
116 | { {"h8300h", no_argument, NULL, 'h'}, | |
117 | 'h', NULL, "Indicate the CPU is h8/300h or h8/300s", | |
118 | standard_option_handler }, | |
119 | #endif | |
120 | ||
4ede3a83 DE |
121 | #ifdef SIM_HAVE_FLATMEM |
122 | { {"mem-size", required_argument, NULL, 'm'}, | |
123 | 'm', "MEMORY SIZE", "Specify memory size", | |
124 | standard_option_handler }, | |
125 | #endif | |
126 | ||
43c53e07 | 127 | { {"do-command", required_argument, NULL, OPTION_DO_COMMAND}, |
50a2a691 | 128 | '\0', "COMMAND", ""/*undocumented*/, |
43c53e07 AC |
129 | standard_option_handler }, |
130 | ||
4ede3a83 DE |
131 | { {"help", no_argument, NULL, 'H'}, |
132 | 'H', NULL, "Print help information", | |
133 | standard_option_handler }, | |
134 | ||
18c319ae AC |
135 | { {"architecture", required_argument, NULL, OPTION_ARCHITECTURE}, |
136 | '\0', "MACHINE", "Specify the architecture to use", | |
137 | standard_option_handler }, | |
d0b59aa5 AC |
138 | { {"architecture-info", no_argument, NULL, OPTION_ARCHITECTURE_INFO}, |
139 | '\0', NULL, "List supported architectures", | |
140 | standard_option_handler }, | |
141 | { {"info-architecture", no_argument, NULL, OPTION_ARCHITECTURE_INFO}, | |
142 | '\0', NULL, NULL, | |
143 | standard_option_handler }, | |
18c319ae AC |
144 | |
145 | { {"target", required_argument, NULL, OPTION_TARGET}, | |
146 | '\0', "BFDNAME", "Specify the object-code format for the object files", | |
147 | standard_option_handler }, | |
148 | ||
4ede3a83 DE |
149 | { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } |
150 | }; | |
151 | ||
152 | static SIM_RC | |
50a2a691 | 153 | standard_option_handler (sd, opt, arg, is_command) |
4ede3a83 DE |
154 | SIM_DESC sd; |
155 | int opt; | |
156 | char *arg; | |
50a2a691 | 157 | int is_command; |
4ede3a83 DE |
158 | { |
159 | int i,n; | |
4ede3a83 DE |
160 | |
161 | switch (opt) | |
162 | { | |
163 | case 'v' : | |
164 | STATE_VERBOSE_P (sd) = 1; | |
165 | break; | |
166 | ||
e65bd1d8 DE |
167 | #ifdef SIM_HAVE_BIENDIAN |
168 | case 'E' : | |
169 | if (strcmp (arg, "big") == 0) | |
170 | { | |
171 | if (WITH_TARGET_BYTE_ORDER == LITTLE_ENDIAN) | |
172 | { | |
173 | sim_io_eprintf (sd, "Simulator compiled for little endian only.\n"); | |
174 | return SIM_RC_FAIL; | |
175 | } | |
176 | /* FIXME:wip: Need to set something in STATE_CONFIG. */ | |
50a2a691 | 177 | current_target_byte_order = BIG_ENDIAN; |
e65bd1d8 DE |
178 | } |
179 | else if (strcmp (arg, "little") == 0) | |
180 | { | |
181 | if (WITH_TARGET_BYTE_ORDER == BIG_ENDIAN) | |
182 | { | |
183 | sim_io_eprintf (sd, "Simulator compiled for big endian only.\n"); | |
184 | return SIM_RC_FAIL; | |
185 | } | |
186 | /* FIXME:wip: Need to set something in STATE_CONFIG. */ | |
50a2a691 | 187 | current_target_byte_order = LITTLE_ENDIAN; |
e65bd1d8 DE |
188 | } |
189 | else | |
190 | { | |
191 | sim_io_eprintf (sd, "Invalid endian specification `%s'\n", arg); | |
192 | return SIM_RC_FAIL; | |
193 | } | |
194 | break; | |
195 | #endif | |
196 | ||
4ede3a83 DE |
197 | case 'D' : |
198 | if (! WITH_DEBUG) | |
199 | sim_io_eprintf (sd, "Debugging not compiled in, `-D' ignored\n"); | |
200 | else | |
201 | { | |
202 | for (n = 0; n < MAX_NR_PROCESSORS; ++n) | |
203 | for (i = 0; i < MAX_DEBUG_VALUES; ++i) | |
204 | CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[i] = 1; | |
205 | } | |
206 | break; | |
207 | ||
208 | case OPTION_DEBUG_INSN : | |
209 | if (! WITH_DEBUG) | |
210 | sim_io_eprintf (sd, "Debugging not compiled in, `--debug-insn' ignored\n"); | |
211 | else | |
212 | { | |
213 | for (n = 0; n < MAX_NR_PROCESSORS; ++n) | |
214 | CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[DEBUG_INSN_IDX] = 1; | |
215 | } | |
216 | break; | |
217 | ||
218 | case OPTION_DEBUG_FILE : | |
219 | if (! WITH_DEBUG) | |
220 | sim_io_eprintf (sd, "Debugging not compiled in, `--debug-file' ignored\n"); | |
221 | else | |
222 | { | |
223 | FILE *f = fopen (arg, "w"); | |
224 | ||
225 | if (f == NULL) | |
226 | { | |
227 | sim_io_eprintf (sd, "Unable to open debug output file `%s'\n", arg); | |
228 | return SIM_RC_FAIL; | |
229 | } | |
230 | for (n = 0; n < MAX_NR_PROCESSORS; ++n) | |
231 | CPU_DEBUG_FILE (STATE_CPU (sd, n)) = f; | |
232 | } | |
233 | break; | |
234 | ||
4ede3a83 DE |
235 | #ifdef SIM_H8300 /* FIXME: Can be moved to h8300 dir. */ |
236 | case 'h' : | |
237 | set_h8300h (1); | |
238 | break; | |
239 | #endif | |
240 | ||
4ede3a83 DE |
241 | #ifdef SIM_HAVE_FLATMEM |
242 | case 'm': | |
43c53e07 AC |
243 | { |
244 | unsigned long ul = strtol (arg, NULL, 0); | |
245 | /* 16384: some minimal amount */ | |
246 | if (! isdigit (arg[0]) || ul < 16384) | |
247 | { | |
248 | sim_io_eprintf (sd, "Invalid memory size `%s'", arg); | |
249 | return SIM_RC_FAIL; | |
250 | } | |
251 | STATE_MEM_SIZE (sd) = ul; | |
252 | } | |
4ede3a83 DE |
253 | break; |
254 | #endif | |
255 | ||
43c53e07 AC |
256 | case OPTION_DO_COMMAND: |
257 | sim_do_command (sd, arg); | |
258 | break; | |
259 | ||
18c319ae AC |
260 | case OPTION_ARCHITECTURE: |
261 | { | |
262 | const struct bfd_arch_info *ap = bfd_scan_arch (arg); | |
263 | if (ap == NULL) | |
264 | { | |
265 | sim_io_eprintf (sd, "Architecture `%s' unknown\n", arg); | |
266 | return SIM_RC_FAIL; | |
267 | } | |
268 | STATE_ARCHITECTURE (sd) = ap; | |
269 | break; | |
270 | } | |
271 | ||
d0b59aa5 AC |
272 | case OPTION_ARCHITECTURE_INFO: |
273 | { | |
274 | const char **list = bfd_arch_list(); | |
275 | const char **lp; | |
276 | if (list == NULL) | |
277 | abort (); | |
278 | sim_io_printf (sd, "Valid architectures:"); | |
279 | for (lp = list; *lp != NULL; lp++) | |
280 | sim_io_printf (sd, " %s", *lp); | |
281 | sim_io_printf (sd, "\n"); | |
282 | free (list); | |
283 | break; | |
284 | } | |
285 | ||
18c319ae AC |
286 | case OPTION_TARGET: |
287 | { | |
36db8e64 | 288 | STATE_TARGET (sd) = xstrdup (arg); |
18c319ae AC |
289 | break; |
290 | } | |
291 | ||
4ede3a83 | 292 | case 'H': |
2f2e6c5d | 293 | sim_print_help (sd, is_command); |
4ede3a83 DE |
294 | if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) |
295 | exit (0); | |
296 | /* FIXME: 'twould be nice to do something similar if gdb. */ | |
297 | break; | |
298 | } | |
299 | ||
300 | return SIM_RC_OK; | |
301 | } | |
302 | ||
c967f187 | 303 | /* Add the standard option list to the simulator. */ |
4ede3a83 DE |
304 | |
305 | SIM_RC | |
c967f187 | 306 | standard_install (SIM_DESC sd) |
4ede3a83 | 307 | { |
50a2a691 | 308 | SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); |
4ede3a83 DE |
309 | if (sim_add_option_table (sd, standard_options) != SIM_RC_OK) |
310 | return SIM_RC_FAIL; | |
4ede3a83 DE |
311 | return SIM_RC_OK; |
312 | } | |
313 | ||
314 | /* Return non-zero if arg is a duplicate argument. | |
315 | If ARG is NULL, initialize. */ | |
316 | ||
317 | #define ARG_HASH_SIZE 97 | |
318 | #define ARG_HASH(a) ((256 * (unsigned char) a[0] + (unsigned char) a[1]) % ARG_HASH_SIZE) | |
319 | ||
320 | static int | |
321 | dup_arg_p (arg) | |
322 | char *arg; | |
323 | { | |
324 | int hash; | |
325 | static char **arg_table = NULL; | |
326 | ||
327 | if (arg == NULL) | |
328 | { | |
329 | if (arg_table == NULL) | |
330 | arg_table = (char **) xmalloc (ARG_HASH_SIZE * sizeof (char *)); | |
331 | memset (arg_table, 0, ARG_HASH_SIZE * sizeof (char *)); | |
332 | return 0; | |
333 | } | |
334 | ||
335 | hash = ARG_HASH (arg); | |
336 | while (arg_table[hash] != NULL) | |
337 | { | |
338 | if (strcmp (arg, arg_table[hash]) == 0) | |
339 | return 1; | |
340 | /* We assume there won't be more than ARG_HASH_SIZE arguments so we | |
341 | don't check if the table is full. */ | |
342 | if (++hash == ARG_HASH_SIZE) | |
343 | hash = 0; | |
344 | } | |
345 | arg_table[hash] = arg; | |
346 | return 0; | |
347 | } | |
348 | ||
349 | /* Called by sim_open to parse the arguments. */ | |
350 | ||
351 | SIM_RC | |
352 | sim_parse_args (sd, argv) | |
353 | SIM_DESC sd; | |
354 | char **argv; | |
355 | { | |
356 | int i, argc, num_opts; | |
357 | char *p, *short_options; | |
358 | /* The `val' option struct entry is dynamically assigned for options that | |
359 | only come in the long form. ORIG_VAL is used to get the original value | |
360 | back. */ | |
8786d426 | 361 | unsigned char *orig_val; |
4ede3a83 DE |
362 | struct option *lp, *long_options; |
363 | const struct option_list *ol; | |
364 | const OPTION *opt; | |
365 | OPTION_HANDLER **handlers; | |
366 | ||
367 | /* Count the number of arguments. */ | |
368 | for (argc = 0; argv[argc] != NULL; ++argc) | |
369 | continue; | |
370 | ||
371 | /* Count the number of options. */ | |
372 | num_opts = 0; | |
373 | for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) | |
374 | for (opt = ol->options; opt->opt.name != NULL; ++opt) | |
375 | ++num_opts; | |
376 | ||
377 | /* Initialize duplicate argument checker. */ | |
378 | (void) dup_arg_p (NULL); | |
379 | ||
380 | /* Build the option table for getopt. */ | |
381 | long_options = (struct option *) alloca ((num_opts + 1) * sizeof (struct option)); | |
382 | lp = long_options; | |
383 | short_options = (char *) alloca (num_opts * 3 + 1); | |
384 | p = short_options; | |
385 | #if 0 /* ??? necessary anymore? */ | |
386 | /* Set '+' as first char so argument permutation isn't done. This is done | |
387 | to workaround a problem with invoking getopt_long in run.c.: optind gets | |
388 | decremented when the program name is reached. */ | |
389 | *p++ = '+'; | |
390 | #endif | |
391 | handlers = (OPTION_HANDLER **) alloca (256 * sizeof (OPTION_HANDLER *)); | |
392 | memset (handlers, 0, 256 * sizeof (OPTION_HANDLER *)); | |
8786d426 | 393 | orig_val = (unsigned char *) alloca (256); |
4ede3a83 DE |
394 | for (i = OPTION_START, ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) |
395 | for (opt = ol->options; opt->opt.name != NULL; ++opt) | |
396 | { | |
397 | if (dup_arg_p (opt->opt.name)) | |
398 | continue; | |
399 | if (opt->shortopt != 0) | |
400 | { | |
401 | *p++ = opt->shortopt; | |
402 | if (opt->opt.has_arg == required_argument) | |
403 | *p++ = ':'; | |
404 | else if (opt->opt.has_arg == optional_argument) | |
405 | { *p++ = ':'; *p++ = ':'; } | |
406 | } | |
407 | *lp = opt->opt; | |
408 | /* Dynamically assign `val' numbers for long options that don't have | |
409 | a short option equivalent. */ | |
410 | if (OPTION_LONG_ONLY_P (opt->opt.val)) | |
411 | lp->val = i++; | |
412 | handlers[(unsigned char) lp->val] = opt->handler; | |
413 | orig_val[(unsigned char) lp->val] = opt->opt.val; | |
414 | ++lp; | |
415 | } | |
416 | *p = 0; | |
417 | lp->name = NULL; | |
418 | ||
419 | /* Ensure getopt is initialized. */ | |
420 | optind = 0; | |
421 | while (1) | |
422 | { | |
423 | int longind, optc; | |
424 | ||
425 | optc = getopt_long (argc, argv, short_options, long_options, &longind); | |
426 | if (optc == -1) | |
427 | { | |
428 | if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) | |
f90b720b | 429 | STATE_PROG_ARGV (sd) = dupargv (argv + optind); |
4ede3a83 DE |
430 | break; |
431 | } | |
432 | if (optc == '?') | |
433 | return SIM_RC_FAIL; | |
434 | ||
50a2a691 | 435 | if ((*handlers[optc]) (sd, orig_val[optc], optarg, 0/*!is_command*/) == SIM_RC_FAIL) |
4ede3a83 DE |
436 | return SIM_RC_FAIL; |
437 | } | |
438 | ||
439 | return SIM_RC_OK; | |
440 | } | |
441 | ||
442 | /* Print help messages for the options. */ | |
443 | ||
444 | void | |
2f2e6c5d | 445 | sim_print_help (sd, is_command) |
4ede3a83 | 446 | SIM_DESC sd; |
2f2e6c5d | 447 | int is_command; |
4ede3a83 DE |
448 | { |
449 | const struct option_list *ol; | |
450 | const OPTION *opt; | |
451 | ||
452 | if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) | |
453 | sim_io_printf (sd, "Usage: %s [options] program [program args]\n", | |
454 | STATE_MY_NAME (sd)); | |
455 | ||
456 | /* Initialize duplicate argument checker. */ | |
457 | (void) dup_arg_p (NULL); | |
458 | ||
d07dddd2 AC |
459 | if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) |
460 | sim_io_printf (sd, "Options:\n"); | |
461 | else | |
462 | sim_io_printf (sd, "Commands:\n"); | |
463 | ||
4ede3a83 DE |
464 | for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) |
465 | for (opt = ol->options; opt->opt.name != NULL; ++opt) | |
466 | { | |
467 | int comma, len; | |
468 | const OPTION *o; | |
469 | ||
470 | if (dup_arg_p (opt->opt.name)) | |
471 | continue; | |
472 | ||
473 | if (opt->doc == NULL) | |
474 | continue; | |
475 | ||
50a2a691 AC |
476 | if (opt->doc_name != NULL && opt->doc_name [0] == '\0') |
477 | continue; | |
478 | ||
4ede3a83 DE |
479 | sim_io_printf (sd, " "); |
480 | ||
481 | comma = 0; | |
482 | len = 2; | |
483 | ||
2f2e6c5d | 484 | if (!is_command) |
4ede3a83 | 485 | { |
2f2e6c5d AC |
486 | o = opt; |
487 | do | |
4ede3a83 | 488 | { |
2f2e6c5d | 489 | if (o->shortopt != '\0') |
4ede3a83 | 490 | { |
2f2e6c5d AC |
491 | sim_io_printf (sd, "%s-%c", comma ? ", " : "", o->shortopt); |
492 | len += (comma ? 2 : 0) + 2; | |
493 | if (o->arg != NULL) | |
43c53e07 | 494 | { |
2f2e6c5d AC |
495 | if (o->opt.has_arg == optional_argument) |
496 | { | |
497 | sim_io_printf (sd, "[%s]", o->arg); | |
498 | len += 1 + strlen (o->arg) + 1; | |
499 | } | |
500 | else | |
501 | { | |
502 | sim_io_printf (sd, " %s", o->arg); | |
503 | len += 1 + strlen (o->arg); | |
504 | } | |
4ede3a83 | 505 | } |
2f2e6c5d | 506 | comma = 1; |
4ede3a83 | 507 | } |
2f2e6c5d | 508 | ++o; |
4ede3a83 | 509 | } |
2f2e6c5d | 510 | while (o->opt.name != NULL && o->doc == NULL); |
4ede3a83 | 511 | } |
2f2e6c5d | 512 | |
4ede3a83 DE |
513 | o = opt; |
514 | do | |
515 | { | |
50a2a691 AC |
516 | const char *name; |
517 | if (o->doc_name != NULL) | |
518 | name = o->doc_name; | |
519 | else | |
520 | name = o->opt.name; | |
521 | if (name != NULL) | |
4ede3a83 | 522 | { |
2f2e6c5d | 523 | sim_io_printf (sd, "%s%s%s", |
4ede3a83 | 524 | comma ? ", " : "", |
2f2e6c5d | 525 | is_command ? "" : "--", |
50a2a691 | 526 | name); |
4ede3a83 | 527 | len += ((comma ? 2 : 0) |
2f2e6c5d | 528 | + (is_command ? 0 : 2) |
50a2a691 | 529 | + strlen (name)); |
4ede3a83 DE |
530 | if (o->arg != NULL) |
531 | { | |
43c53e07 AC |
532 | if (o->opt.has_arg == optional_argument) |
533 | { | |
534 | sim_io_printf (sd, " [%s]", o->arg); | |
535 | len += 2 + strlen (o->arg) + 1; | |
536 | } | |
537 | else | |
538 | { | |
539 | sim_io_printf (sd, " %s", o->arg); | |
540 | len += 1 + strlen (o->arg); | |
541 | } | |
4ede3a83 DE |
542 | } |
543 | comma = 1; | |
544 | } | |
545 | ++o; | |
546 | } | |
547 | while (o->opt.name != NULL && o->doc == NULL); | |
548 | ||
549 | if (len >= 30) | |
550 | { | |
551 | sim_io_printf (sd, "\n"); | |
552 | len = 0; | |
553 | } | |
554 | ||
555 | for (; len < 30; len++) | |
556 | sim_io_printf (sd, " "); | |
557 | ||
558 | sim_io_printf (sd, "%s\n", opt->doc); | |
559 | } | |
560 | ||
d07dddd2 AC |
561 | sim_io_printf (sd, "\n"); |
562 | sim_io_printf (sd, "Note: Depending on the simulator configuration some %ss\n", | |
563 | STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE ? "option" : "command"); | |
564 | sim_io_printf (sd, " may not be applicable\n"); | |
565 | ||
4ede3a83 DE |
566 | if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) |
567 | { | |
568 | sim_io_printf (sd, "\n"); | |
569 | sim_io_printf (sd, "program args Arguments to pass to simulated program.\n"); | |
570 | sim_io_printf (sd, " Note: Very few simulators support this.\n"); | |
571 | } | |
572 | } | |
43c53e07 AC |
573 | |
574 | ||
575 | ||
576 | ||
577 | SIM_RC | |
578 | sim_args_command (sd, cmd) | |
579 | SIM_DESC sd; | |
580 | char *cmd; | |
581 | { | |
582 | /* something to do? */ | |
583 | if (cmd == NULL) | |
584 | return SIM_RC_OK; /* FIXME - perhaphs help would be better */ | |
585 | ||
586 | if (cmd [0] == '-') | |
587 | { | |
588 | /* user specified -<opt> ... form? */ | |
589 | char **argv = buildargv (cmd); | |
590 | SIM_RC rc = sim_parse_args (sd, argv); | |
591 | freeargv (argv); | |
592 | return rc; | |
593 | } | |
594 | else | |
595 | { | |
596 | /* user specified <opt> form? */ | |
597 | const struct option_list *ol; | |
598 | const OPTION *opt; | |
599 | char **argv = buildargv (cmd); | |
50a2a691 AC |
600 | /* most recent option match */ |
601 | const OPTION *matching_opt = NULL; | |
602 | int matching_argi = -1; | |
603 | if (argv [0] != NULL) | |
604 | for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) | |
605 | for (opt = ol->options; opt->opt.name != NULL; ++opt) | |
606 | { | |
607 | int argi = 0; | |
608 | const char *name = opt->opt.name; | |
609 | while (strncmp (name, argv [argi], strlen (argv [argi])) == 0) | |
610 | { | |
611 | name = &name [strlen (argv[argi])]; | |
612 | if (name [0] == '-') | |
613 | { | |
614 | /* leading match ...<a-b-c>-d-e-f - continue search */ | |
615 | name ++; /* skip `-' */ | |
616 | argi ++; | |
617 | continue; | |
618 | } | |
619 | else if (name [0] == '\0') | |
620 | { | |
621 | /* exact match ...<a-b-c-d-e-f> - better than before? */ | |
622 | if (argi > matching_argi) | |
623 | { | |
624 | matching_argi = argi; | |
625 | matching_opt = opt; | |
626 | } | |
627 | break; | |
628 | } | |
629 | else | |
43c53e07 | 630 | break; |
50a2a691 AC |
631 | } |
632 | } | |
633 | if (matching_opt != NULL) | |
634 | { | |
635 | switch (matching_opt->opt.has_arg) | |
636 | { | |
637 | case no_argument: | |
638 | if (argv [matching_argi + 1] == NULL) | |
639 | matching_opt->handler (sd, matching_opt->opt.val, | |
640 | NULL, 1/*is_command*/); | |
641 | else | |
642 | sim_io_eprintf (sd, "Command `%s' takes no arguments\n", | |
643 | matching_opt->opt.name); | |
644 | break; | |
645 | case optional_argument: | |
646 | if (argv [matching_argi + 1] == NULL) | |
647 | matching_opt->handler (sd, matching_opt->opt.val, | |
648 | NULL, 1/*is_command*/); | |
649 | else if (argv [matching_argi + 2] == NULL) | |
650 | matching_opt->handler (sd, matching_opt->opt.val, | |
651 | argv [matching_argi + 1], 1/*is_command*/); | |
652 | else | |
653 | sim_io_eprintf (sd, "Command `%s' requires no more than one argument\n", | |
654 | matching_opt->opt.name); | |
655 | break; | |
656 | case required_argument: | |
657 | if (argv [matching_argi + 1] == NULL) | |
658 | sim_io_eprintf (sd, "Command `%s' requires an argument\n", | |
659 | matching_opt->opt.name); | |
660 | else if (argv [matching_argi + 2] == NULL) | |
661 | matching_opt->handler (sd, matching_opt->opt.val, | |
662 | argv [matching_argi + 1], 1/*is_command*/); | |
663 | else | |
664 | sim_io_eprintf (sd, "Command `%s' requires only one argument\n", | |
665 | matching_opt->opt.name); | |
666 | } | |
667 | return SIM_RC_OK; | |
668 | } | |
43c53e07 | 669 | } |
50a2a691 AC |
670 | |
671 | /* didn't find anything that remotly matched */ | |
43c53e07 AC |
672 | return SIM_RC_FAIL; |
673 | } |