]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame_incremental - sim/common/sim-options.c
binutils: drop unused note_size, contents, old variables
[thirdparty/binutils-gdb.git] / sim / common / sim-options.c
... / ...
CommitLineData
1/* Simulator option handling.
2 Copyright (C) 1996-2025 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20/* This must come before any other includes. */
21#include "defs.h"
22
23#include <ctype.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28
29#include "bfd.h"
30#include "environ.h"
31#include "hashtab.h"
32#include "libiberty.h"
33
34#include "sim-main.h"
35#include "sim-options.h"
36#include "sim-io.h"
37#include "sim-assert.h"
38#include "version.h"
39
40/* Add a set of options to the simulator.
41 TABLE is an array of OPTIONS terminated by a NULL `opt.name' entry.
42 This is intended to be called by modules in their `install' handler. */
43
44SIM_RC
45sim_add_option_table (SIM_DESC sd, sim_cpu *cpu, const OPTION *table)
46{
47 struct option_list *ol = ((struct option_list *)
48 xmalloc (sizeof (struct option_list)));
49
50 /* Note: The list is constructed in the reverse order we're called so
51 later calls will override earlier ones (in case that ever happens).
52 This is the intended behaviour. */
53
54 if (cpu)
55 {
56 ol->next = CPU_OPTIONS (cpu);
57 ol->options = table;
58 CPU_OPTIONS (cpu) = ol;
59 }
60 else
61 {
62 ol->next = STATE_OPTIONS (sd);
63 ol->options = table;
64 STATE_OPTIONS (sd) = ol;
65 }
66
67 return SIM_RC_OK;
68}
69
70/* Standard option table.
71 Modules may specify additional ones.
72 The caller of sim_parse_args may also specify additional options
73 by calling sim_add_option_table first. */
74
75static DECLARE_OPTION_HANDLER (standard_option_handler);
76
77/* FIXME: We shouldn't print in --help output options that aren't usable.
78 Some fine tuning will be necessary. One can either move less general
79 options to another table or use a HAVE_FOO macro to ifdef out unavailable
80 options. */
81
82/* ??? One might want to conditionally compile out the entries that
83 aren't enabled. There's a distinction, however, between options a
84 simulator can't support and options that haven't been configured in.
85 Certainly options a simulator can't support shouldn't appear in the
86 output of --help. Whether the same thing applies to options that haven't
87 been configured in or not isn't something I can get worked up over.
88 [Note that conditionally compiling them out might simply involve moving
89 the option to another table.]
90 If you decide to conditionally compile them out as well, delete this
91 comment and add a comment saying that that is the rule. */
92
93typedef enum {
94 OPTION_DEBUG_INSN = OPTION_START,
95 OPTION_DEBUG_FILE,
96 OPTION_DO_COMMAND,
97 OPTION_ARCHITECTURE,
98 OPTION_TARGET,
99 OPTION_TARGET_INFO,
100 OPTION_ARCHITECTURE_INFO,
101 OPTION_ENVIRONMENT,
102 OPTION_ALIGNMENT,
103 OPTION_VERBOSE,
104 OPTION_ENDIAN,
105 OPTION_DEBUG,
106 OPTION_HELP,
107 OPTION_VERSION,
108 OPTION_LOAD_LMA,
109 OPTION_LOAD_VMA,
110 OPTION_SYSROOT,
111 OPTION_ARGV0,
112 OPTION_ENV_SET,
113 OPTION_ENV_UNSET,
114 OPTION_ENV_CLEAR,
115} STANDARD_OPTIONS;
116
117static const OPTION standard_options[] =
118{
119 { {"verbose", no_argument, NULL, OPTION_VERBOSE},
120 'v', NULL, "Verbose output",
121 standard_option_handler, NULL },
122
123 { {"endian", required_argument, NULL, OPTION_ENDIAN},
124 'E', "B|big|L|little", "Set endianness",
125 standard_option_handler, NULL },
126
127 /* This option isn't supported unless all choices are supported in keeping
128 with the goal of not printing in --help output things the simulator can't
129 do [as opposed to things that just haven't been configured in]. */
130 { {"environment", required_argument, NULL, OPTION_ENVIRONMENT},
131 '\0', "user|virtual|operating", "Set running environment",
132 standard_option_handler },
133
134 { {"alignment", required_argument, NULL, OPTION_ALIGNMENT},
135 '\0', "strict|nonstrict|forced", "Set memory access alignment",
136 standard_option_handler },
137
138 { {"debug", no_argument, NULL, OPTION_DEBUG},
139 'D', NULL, "Print debugging messages",
140 standard_option_handler },
141 { {"debug-insn", no_argument, NULL, OPTION_DEBUG_INSN},
142 '\0', NULL, "Print instruction debugging messages",
143 standard_option_handler },
144 { {"debug-file", required_argument, NULL, OPTION_DEBUG_FILE},
145 '\0', "FILE NAME", "Specify debugging output file",
146 standard_option_handler },
147
148 { {"do-command", required_argument, NULL, OPTION_DO_COMMAND},
149 '\0', "COMMAND", ""/*undocumented*/,
150 standard_option_handler },
151
152 { {"help", no_argument, NULL, OPTION_HELP},
153 'h', NULL, "Print help information",
154 standard_option_handler },
155 { {"version", no_argument, NULL, OPTION_VERSION},
156 '\0', NULL, "Print version information",
157 standard_option_handler },
158
159 { {"architecture", required_argument, NULL, OPTION_ARCHITECTURE},
160 '\0', "MACHINE", "Specify the architecture to use",
161 standard_option_handler },
162 { {"architecture-info", no_argument, NULL, OPTION_ARCHITECTURE_INFO},
163 '\0', NULL, "List supported architectures",
164 standard_option_handler },
165 { {"info-architecture", no_argument, NULL, OPTION_ARCHITECTURE_INFO},
166 '\0', NULL, NULL,
167 standard_option_handler },
168
169 { {"target", required_argument, NULL, OPTION_TARGET},
170 '\0', "BFDNAME", "Specify the object-code format for the object files",
171 standard_option_handler },
172 { {"target-info", no_argument, NULL, OPTION_TARGET_INFO},
173 '\0', NULL, "List supported targets", standard_option_handler },
174 { {"info-target", no_argument, NULL, OPTION_TARGET_INFO},
175 '\0', NULL, NULL, standard_option_handler },
176
177 { {"load-lma", no_argument, NULL, OPTION_LOAD_LMA},
178 '\0', NULL,
179 "Use VMA or LMA addresses when loading image (default LMA)",
180 standard_option_handler, "load-{lma,vma}" },
181 { {"load-vma", no_argument, NULL, OPTION_LOAD_VMA},
182 '\0', NULL, "", standard_option_handler, "" },
183
184 { {"sysroot", required_argument, NULL, OPTION_SYSROOT},
185 '\0', "SYSROOT",
186 "Root for system calls with absolute file-names and cwd at start",
187 standard_option_handler, NULL },
188
189 { {"argv0", required_argument, NULL, OPTION_ARGV0},
190 '\0', "ARGV0", "Set argv[0] to the specified string",
191 standard_option_handler, NULL },
192
193 { {"env-set", required_argument, NULL, OPTION_ENV_SET},
194 '\0', "VAR=VAL", "Set the variable in the program's environment",
195 standard_option_handler, NULL },
196 { {"env-unset", required_argument, NULL, OPTION_ENV_UNSET},
197 '\0', "VAR", "Unset the variable in the program's environment",
198 standard_option_handler, NULL },
199 { {"env-clear", no_argument, NULL, OPTION_ENV_CLEAR},
200 '\0', NULL, "Clear the program's environment",
201 standard_option_handler, NULL },
202
203 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
204};
205
206static SIM_RC
207env_set (SIM_DESC sd, const char *arg)
208{
209 int i, varlen;
210 char *eq;
211 char **envp;
212
213 if (STATE_PROG_ENVP (sd) == NULL)
214 STATE_PROG_ENVP (sd) = dupargv (environ);
215
216 eq = strchr (arg, '=');
217 if (eq == NULL)
218 {
219 sim_io_eprintf (sd, "invalid syntax when setting env var `%s'"
220 ": missing value", arg);
221 return SIM_RC_FAIL;
222 }
223 /* Include the = in the comparison below. */
224 varlen = eq - arg + 1;
225
226 /* If we can find an existing variable, replace it. */
227 envp = STATE_PROG_ENVP (sd);
228 for (i = 0; envp[i]; ++i)
229 {
230 if (strncmp (envp[i], arg, varlen) == 0)
231 {
232 free (envp[i]);
233 envp[i] = xstrdup (arg);
234 break;
235 }
236 }
237
238 /* If we didn't find the var, add it. */
239 if (envp[i] == NULL)
240 {
241 envp = xrealloc (envp, (i + 2) * sizeof (char *));
242 envp[i] = xstrdup (arg);
243 envp[i + 1] = NULL;
244 STATE_PROG_ENVP (sd) = envp;
245 }
246
247 return SIM_RC_OK;
248}
249
250static SIM_RC
251standard_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
252 char *arg, int is_command)
253{
254 int i,n;
255
256 switch ((STANDARD_OPTIONS) opt)
257 {
258 case OPTION_VERBOSE:
259 STATE_VERBOSE_P (sd) = 1;
260 break;
261
262 case OPTION_ENDIAN:
263 if (strcmp (arg, "big") == 0 || strcmp (arg, "B") == 0)
264 {
265 if (WITH_TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
266 {
267 sim_io_eprintf (sd, "Simulator compiled for little endian only.\n");
268 return SIM_RC_FAIL;
269 }
270 /* FIXME:wip: Need to set something in STATE_CONFIG. */
271 current_target_byte_order = BFD_ENDIAN_BIG;
272 }
273 else if (strcmp (arg, "little") == 0 || strcmp (arg, "L") == 0)
274 {
275 if (WITH_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
276 {
277 sim_io_eprintf (sd, "Simulator compiled for big endian only.\n");
278 return SIM_RC_FAIL;
279 }
280 /* FIXME:wip: Need to set something in STATE_CONFIG. */
281 current_target_byte_order = BFD_ENDIAN_LITTLE;
282 }
283 else
284 {
285 sim_io_eprintf (sd, "Invalid endian specification `%s'\n", arg);
286 return SIM_RC_FAIL;
287 }
288 break;
289
290 case OPTION_ENVIRONMENT:
291 if (strcmp (arg, "user") == 0)
292 STATE_ENVIRONMENT (sd) = USER_ENVIRONMENT;
293 else if (strcmp (arg, "virtual") == 0)
294 STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT;
295 else if (strcmp (arg, "operating") == 0)
296 STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
297 else
298 {
299 sim_io_eprintf (sd, "Invalid environment specification `%s'\n", arg);
300 return SIM_RC_FAIL;
301 }
302 if (WITH_ENVIRONMENT != ALL_ENVIRONMENT
303 && WITH_ENVIRONMENT != STATE_ENVIRONMENT (sd))
304 {
305 const char *type;
306 switch (WITH_ENVIRONMENT)
307 {
308 case USER_ENVIRONMENT: type = "user"; break;
309 case VIRTUAL_ENVIRONMENT: type = "virtual"; break;
310 case OPERATING_ENVIRONMENT: type = "operating"; break;
311 default: abort ();
312 }
313 sim_io_eprintf (sd, "Simulator compiled for the %s environment only.\n",
314 type);
315 return SIM_RC_FAIL;
316 }
317 break;
318
319 case OPTION_ALIGNMENT:
320 if (strcmp (arg, "strict") == 0)
321 {
322 if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == STRICT_ALIGNMENT)
323 {
324 current_alignment = STRICT_ALIGNMENT;
325 break;
326 }
327 }
328 else if (strcmp (arg, "nonstrict") == 0)
329 {
330 if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == NONSTRICT_ALIGNMENT)
331 {
332 current_alignment = NONSTRICT_ALIGNMENT;
333 break;
334 }
335 }
336 else if (strcmp (arg, "forced") == 0)
337 {
338 if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == FORCED_ALIGNMENT)
339 {
340 current_alignment = FORCED_ALIGNMENT;
341 break;
342 }
343 }
344 else
345 {
346 sim_io_eprintf (sd, "Invalid alignment specification `%s'\n", arg);
347 return SIM_RC_FAIL;
348 }
349 switch (WITH_ALIGNMENT)
350 {
351 case STRICT_ALIGNMENT:
352 sim_io_eprintf (sd, "Simulator compiled for strict alignment only.\n");
353 break;
354 case NONSTRICT_ALIGNMENT:
355 sim_io_eprintf (sd, "Simulator compiled for nonstrict alignment only.\n");
356 break;
357 case FORCED_ALIGNMENT:
358 sim_io_eprintf (sd, "Simulator compiled for forced alignment only.\n");
359 break;
360 default: abort ();
361 }
362 return SIM_RC_FAIL;
363
364 case OPTION_DEBUG:
365 if (! WITH_DEBUG)
366 sim_io_eprintf (sd, "Debugging not compiled in, `-D' ignored\n");
367 else
368 {
369 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
370 for (i = 0; i < MAX_DEBUG_VALUES; ++i)
371 CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[i] = 1;
372 }
373 break;
374
375 case OPTION_DEBUG_INSN :
376 if (! WITH_DEBUG)
377 sim_io_eprintf (sd, "Debugging not compiled in, `--debug-insn' ignored\n");
378 else
379 {
380 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
381 CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[DEBUG_INSN_IDX] = 1;
382 }
383 break;
384
385 case OPTION_DEBUG_FILE :
386 if (! WITH_DEBUG)
387 sim_io_eprintf (sd, "Debugging not compiled in, `--debug-file' ignored\n");
388 else
389 {
390 FILE *f = fopen (arg, "w");
391
392 if (f == NULL)
393 {
394 sim_io_eprintf (sd, "Unable to open debug output file `%s'\n", arg);
395 return SIM_RC_FAIL;
396 }
397 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
398 CPU_DEBUG_FILE (STATE_CPU (sd, n)) = f;
399 }
400 break;
401
402 case OPTION_DO_COMMAND:
403 sim_do_command (sd, arg);
404 break;
405
406 case OPTION_ARCHITECTURE:
407 {
408 const struct bfd_arch_info *ap = bfd_scan_arch (arg);
409 if (ap == NULL)
410 {
411 sim_io_eprintf (sd, "Architecture `%s' unknown\n", arg);
412 return SIM_RC_FAIL;
413 }
414 STATE_ARCHITECTURE (sd) = ap;
415 break;
416 }
417
418 case OPTION_ARCHITECTURE_INFO:
419 {
420 const char **list = bfd_arch_list ();
421 const char **lp;
422 if (list == NULL)
423 abort ();
424 sim_io_printf (sd, "Possible architectures:");
425 for (lp = list; *lp != NULL; lp++)
426 sim_io_printf (sd, " %s", *lp);
427 sim_io_printf (sd, "\n");
428 free (list);
429 break;
430 }
431
432 case OPTION_TARGET:
433 {
434 STATE_TARGET (sd) = xstrdup (arg);
435 break;
436 }
437
438 case OPTION_TARGET_INFO:
439 {
440 const char **list = bfd_target_list ();
441 const char **lp;
442 if (list == NULL)
443 abort ();
444 sim_io_printf (sd, "Possible targets:");
445 for (lp = list; *lp != NULL; lp++)
446 sim_io_printf (sd, " %s", *lp);
447 sim_io_printf (sd, "\n");
448 free (list);
449 break;
450 }
451
452 case OPTION_LOAD_LMA:
453 {
454 STATE_LOAD_AT_LMA_P (sd) = 1;
455 break;
456 }
457
458 case OPTION_LOAD_VMA:
459 {
460 STATE_LOAD_AT_LMA_P (sd) = 0;
461 break;
462 }
463
464 case OPTION_HELP:
465 sim_print_help (sd, is_command);
466 if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
467 exit (0);
468 /* FIXME: 'twould be nice to do something similar if gdb. */
469 break;
470
471 case OPTION_VERSION:
472 sim_print_version (sd, is_command);
473 if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
474 exit (0);
475 break;
476
477 case OPTION_SYSROOT:
478 /* Don't leak memory in the odd event that there's lots of
479 --sysroot=... options. We treat "" specially since this
480 is the statically initialized value and cannot free it. */
481 if (simulator_sysroot[0] != '\0')
482 free (simulator_sysroot);
483 if (arg[0] != '\0')
484 simulator_sysroot = xstrdup (arg);
485 else
486 simulator_sysroot = "";
487 break;
488
489 case OPTION_ARGV0:
490 free (STATE_PROG_ARGV0 (sd));
491 STATE_PROG_ARGV0 (sd) = xstrdup (arg);
492 break;
493
494 case OPTION_ENV_SET:
495 return env_set (sd, arg);
496
497 case OPTION_ENV_UNSET:
498 {
499 int varlen;
500 char **envp;
501
502 if (STATE_PROG_ENVP (sd) == NULL)
503 STATE_PROG_ENVP (sd) = dupargv (environ);
504
505 varlen = strlen (arg);
506
507 /* If we can find an existing variable, replace it. */
508 envp = STATE_PROG_ENVP (sd);
509 for (i = 0; envp[i]; ++i)
510 {
511 char *env = envp[i];
512
513 if (strncmp (env, arg, varlen) == 0
514 && (env[varlen] == '\0' || env[varlen] == '='))
515 {
516 free (envp[i]);
517 break;
518 }
519 }
520
521 /* If we clear the var, shift the array down. */
522 for (; envp[i]; ++i)
523 envp[i] = envp[i + 1];
524
525 break;
526 }
527
528 case OPTION_ENV_CLEAR:
529 freeargv (STATE_PROG_ENVP (sd));
530 STATE_PROG_ENVP (sd) = xmalloc (sizeof (char *));
531 STATE_PROG_ENVP (sd)[0] = NULL;
532 break;
533 }
534
535 return SIM_RC_OK;
536}
537
538/* Add the standard option list to the simulator. */
539
540SIM_RC
541standard_install (SIM_DESC sd)
542{
543 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
544 if (sim_add_option_table (sd, NULL, standard_options) != SIM_RC_OK)
545 return SIM_RC_FAIL;
546 STATE_LOAD_AT_LMA_P (sd) = 1;
547 return SIM_RC_OK;
548}
549
550/* Return non-zero if arg is a duplicate argument.
551 If ARG is NULL, initialize. */
552
553static int
554dup_arg_p (const char *arg)
555{
556 static htab_t arg_table = NULL;
557 void **slot;
558
559 if (arg == NULL)
560 {
561 if (arg_table == NULL)
562 arg_table = htab_create_alloc (10, htab_hash_string,
563 htab_eq_string, NULL,
564 xcalloc, free);
565 htab_empty (arg_table);
566 return 0;
567 }
568
569 slot = htab_find_slot (arg_table, arg, INSERT);
570 if (*slot != NULL)
571 return 1;
572 *slot = (void *) arg;
573 return 0;
574}
575
576/* Called by sim_open to parse the arguments. */
577
578SIM_RC
579sim_parse_args (SIM_DESC sd, char * const *argv)
580{
581 int c, i, argc, num_opts, save_opterr;
582 char *p, *short_options;
583 /* The `val' option struct entry is dynamically assigned for options that
584 only come in the long form. ORIG_VAL is used to get the original value
585 back. */
586 int *orig_val;
587 struct option *lp, *long_options;
588 const struct option_list *ol;
589 const OPTION *opt;
590 OPTION_HANDLER **handlers;
591 sim_cpu **opt_cpu;
592 SIM_RC result = SIM_RC_OK;
593
594 /* Count the number of arguments. */
595 argc = countargv (argv);
596
597 /* Count the number of options. */
598 num_opts = 0;
599 for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next)
600 for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
601 ++num_opts;
602 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
603 for (ol = CPU_OPTIONS (STATE_CPU (sd, i)); ol != NULL; ol = ol->next)
604 for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
605 ++num_opts;
606
607 /* Initialize duplicate argument checker. */
608 (void) dup_arg_p (NULL);
609
610 /* Build the option table for getopt. */
611
612 long_options = NZALLOC (struct option, num_opts + 1);
613 lp = long_options;
614 short_options = NZALLOC (char, num_opts * 3 + 1);
615 p = short_options;
616 handlers = NZALLOC (OPTION_HANDLER *, OPTION_START + num_opts);
617 orig_val = NZALLOC (int, OPTION_START + num_opts);
618 opt_cpu = NZALLOC (sim_cpu *, OPTION_START + num_opts);
619
620 /* Set '+' as first char so argument permutation isn't done. This
621 is done to stop getopt_long returning options that appear after
622 the target program. Such options should be passed unchanged into
623 the program image. */
624 *p++ = '+';
625
626 for (i = OPTION_START, ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next)
627 for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
628 {
629 if (dup_arg_p (opt->opt.name))
630 continue;
631 if (opt->shortopt != 0)
632 {
633 *p++ = opt->shortopt;
634 if (opt->opt.has_arg == required_argument)
635 *p++ = ':';
636 else if (opt->opt.has_arg == optional_argument)
637 { *p++ = ':'; *p++ = ':'; }
638 handlers[(unsigned char) opt->shortopt] = opt->handler;
639 if (opt->opt.val != 0)
640 orig_val[(unsigned char) opt->shortopt] = opt->opt.val;
641 else
642 orig_val[(unsigned char) opt->shortopt] = opt->shortopt;
643 }
644 if (opt->opt.name != NULL)
645 {
646 *lp = opt->opt;
647 /* Dynamically assign `val' numbers for long options. */
648 lp->val = i++;
649 handlers[lp->val] = opt->handler;
650 orig_val[lp->val] = opt->opt.val;
651 opt_cpu[lp->val] = NULL;
652 ++lp;
653 }
654 }
655
656 for (c = 0; c < MAX_NR_PROCESSORS; ++c)
657 {
658 sim_cpu *cpu = STATE_CPU (sd, c);
659 for (ol = CPU_OPTIONS (cpu); ol != NULL; ol = ol->next)
660 for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
661 {
662#if 0 /* Each option is prepended with --<cpuname>- so this greatly cuts down
663 on the need for dup_arg_p checking. Maybe in the future it'll be
664 needed so this is just commented out, and not deleted. */
665 if (dup_arg_p (opt->opt.name))
666 continue;
667#endif
668 /* Don't allow short versions of cpu specific options for now. */
669 if (opt->shortopt != 0)
670 {
671 sim_io_eprintf (sd, "internal error, short cpu specific option");
672 result = SIM_RC_FAIL;
673 break;
674 }
675 if (opt->opt.name != NULL)
676 {
677 char *name;
678 *lp = opt->opt;
679 /* Prepend --<cpuname>- to the option. */
680 if (asprintf (&name, "%s-%s", CPU_NAME (cpu), lp->name) < 0)
681 {
682 sim_io_eprintf (sd, "internal error, out of memory");
683 result = SIM_RC_FAIL;
684 break;
685 }
686 lp->name = name;
687 /* Dynamically assign `val' numbers for long options. */
688 lp->val = i++;
689 handlers[lp->val] = opt->handler;
690 orig_val[lp->val] = opt->opt.val;
691 opt_cpu[lp->val] = cpu;
692 ++lp;
693 }
694 }
695 }
696
697 /* Terminate the short and long option lists. */
698 *p = 0;
699 lp->name = NULL;
700
701 /* Ensure getopt is initialized. */
702 optind = 0;
703
704 /* Do not lot getopt throw errors for us. But don't mess with the state for
705 any callers higher up by saving/restoring it. */
706 save_opterr = opterr;
707 opterr = 0;
708
709 while (1)
710 {
711 int longind, optc;
712
713 optc = getopt_long (argc, argv, short_options, long_options, &longind);
714 if (optc == -1)
715 {
716 if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
717 {
718 char **new_argv;
719
720 free (STATE_PROG_FILE (sd));
721 STATE_PROG_FILE (sd) = NULL;
722
723 /* Handle any inline variables if -- wasn't used. */
724 if (argv[optind] != NULL && optind > 0
725 && strcmp (argv[optind - 1], "--") != 0)
726 {
727 while (1)
728 {
729 const char *arg = argv[optind];
730
731 if (strchr (arg, '=') == NULL)
732 break;
733
734 env_set (sd, arg);
735 ++optind;
736 }
737 }
738
739 new_argv = dupargv (argv + optind);
740 freeargv (STATE_PROG_ARGV (sd));
741 STATE_PROG_ARGV (sd) = new_argv;
742
743 /* Skip steps when argc == 0. */
744 if (argv[optind] != NULL)
745 {
746 STATE_PROG_FILE (sd) = xstrdup (argv[optind]);
747
748 if (STATE_PROG_ARGV0 (sd) != NULL)
749 {
750 free (new_argv[0]);
751 new_argv[0] = xstrdup (STATE_PROG_ARGV0 (sd));
752 }
753 }
754 }
755 break;
756 }
757 if (optc == '?')
758 {
759 /* If getopt rejects a short option, optopt is set to the bad char.
760 If it rejects a long option, we have to look at optind. In the
761 short option case, argv could be multiple short options. */
762 const char *badopt;
763 char optbuf[3];
764
765 if (optopt)
766 {
767 sprintf (optbuf, "-%c", optopt);
768 badopt = optbuf;
769 }
770 else
771 badopt = argv[optind - 1];
772
773 sim_io_eprintf (sd,
774 "%s: unrecognized option '%s'\n"
775 "Use --help for a complete list of options.\n",
776 STATE_MY_NAME (sd), badopt);
777
778 result = SIM_RC_FAIL;
779 break;
780 }
781
782 if ((*handlers[optc]) (sd, opt_cpu[optc], orig_val[optc], optarg, 0/*!is_command*/) == SIM_RC_FAIL)
783 {
784 result = SIM_RC_FAIL;
785 break;
786 }
787 }
788
789 opterr = save_opterr;
790
791 free (long_options);
792 free (short_options);
793 free (handlers);
794 free (opt_cpu);
795 free (orig_val);
796 return result;
797}
798
799/* Utility of sim_print_help to print a list of option tables. */
800
801static void
802print_help (SIM_DESC sd, sim_cpu *cpu, const struct option_list *ol, int is_command)
803{
804 const OPTION *opt;
805
806 for ( ; ol != NULL; ol = ol->next)
807 for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
808 {
809 const int indent = 30;
810 int comma, len;
811 const OPTION *o;
812
813 if (dup_arg_p (opt->opt.name))
814 continue;
815
816 if (opt->doc == NULL)
817 continue;
818
819 if (opt->doc_name != NULL && opt->doc_name [0] == '\0')
820 continue;
821
822 sim_io_printf (sd, " ");
823
824 comma = 0;
825 len = 2;
826
827 /* list any short options (aliases) for the current OPT */
828 if (!is_command)
829 {
830 o = opt;
831 do
832 {
833 if (o->shortopt != '\0')
834 {
835 sim_io_printf (sd, "%s-%c", comma ? ", " : "", o->shortopt);
836 len += (comma ? 2 : 0) + 2;
837 if (o->arg != NULL)
838 {
839 if (o->opt.has_arg == optional_argument)
840 {
841 sim_io_printf (sd, "[%s]", o->arg);
842 len += 1 + strlen (o->arg) + 1;
843 }
844 else
845 {
846 sim_io_printf (sd, " %s", o->arg);
847 len += 1 + strlen (o->arg);
848 }
849 }
850 comma = 1;
851 }
852 ++o;
853 }
854 while (OPTION_VALID_P (o) && o->doc == NULL);
855 }
856
857 /* list any long options (aliases) for the current OPT */
858 o = opt;
859 do
860 {
861 const char *name;
862 const char *cpu_prefix = cpu ? CPU_NAME (cpu) : NULL;
863 if (o->doc_name != NULL)
864 name = o->doc_name;
865 else
866 name = o->opt.name;
867 if (name != NULL)
868 {
869 sim_io_printf (sd, "%s%s%s%s%s",
870 comma ? ", " : "",
871 is_command ? "" : "--",
872 cpu ? cpu_prefix : "",
873 cpu ? "-" : "",
874 name);
875 len += ((comma ? 2 : 0)
876 + (is_command ? 0 : 2)
877 + strlen (name));
878 if (o->arg != NULL)
879 {
880 if (o->opt.has_arg == optional_argument)
881 {
882 sim_io_printf (sd, "[=%s]", o->arg);
883 len += 2 + strlen (o->arg) + 1;
884 }
885 else
886 {
887 sim_io_printf (sd, " %s", o->arg);
888 len += 1 + strlen (o->arg);
889 }
890 }
891 comma = 1;
892 }
893 ++o;
894 }
895 while (OPTION_VALID_P (o) && o->doc == NULL);
896
897 if (len >= indent)
898 {
899 sim_io_printf (sd, "\n%*s", indent, "");
900 }
901 else
902 sim_io_printf (sd, "%*s", indent - len, "");
903
904 /* print the description, word wrap long lines */
905 {
906 const char *chp = opt->doc;
907 unsigned doc_width = 80 - indent;
908 while (strlen (chp) >= doc_width) /* some slack */
909 {
910 const char *end = chp + doc_width - 1;
911 while (end > chp && !isspace (*end))
912 end --;
913 if (end == chp)
914 end = chp + doc_width - 1;
915 /* The cast should be ok - its distances between to
916 points in a string. */
917 sim_io_printf (sd, "%.*s\n%*s", (int) (end - chp), chp, indent,
918 "");
919 chp = end;
920 while (isspace (*chp) && *chp != '\0')
921 chp++;
922 }
923 sim_io_printf (sd, "%s\n", chp);
924 }
925 }
926}
927
928/* Print help messages for the options. */
929
930void
931sim_print_help (SIM_DESC sd, int is_command)
932{
933 if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
934 sim_io_printf (sd,
935 "Usage: %s [options] [VAR=VAL|--] program [program args]\n",
936 STATE_MY_NAME (sd));
937
938 /* Initialize duplicate argument checker. */
939 (void) dup_arg_p (NULL);
940
941 if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
942 sim_io_printf (sd, "Options:\n");
943 else
944 sim_io_printf (sd, "Commands:\n");
945
946 print_help (sd, NULL, STATE_OPTIONS (sd), is_command);
947 sim_io_printf (sd, "\n");
948
949 /* Print cpu-specific options. */
950 {
951 int i;
952
953 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
954 {
955 sim_cpu *cpu = STATE_CPU (sd, i);
956 if (CPU_OPTIONS (cpu) == NULL)
957 continue;
958 sim_io_printf (sd, "CPU %s specific options:\n", CPU_NAME (cpu));
959 print_help (sd, cpu, CPU_OPTIONS (cpu), is_command);
960 sim_io_printf (sd, "\n");
961 }
962 }
963
964 sim_io_printf (sd, "Note: Depending on the simulator configuration some %ss\n",
965 STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE ? "option" : "command");
966 sim_io_printf (sd, " may not be applicable\n");
967
968 if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
969 {
970 sim_io_printf (sd, "\n");
971 sim_io_printf (sd,
972 "VAR=VAL Environment variables to set. "
973 "Ignored if -- is used.\n");
974 sim_io_printf (sd, "program args Arguments to pass to simulated program.\n");
975 sim_io_printf (sd, " Note: Very few simulators support this.\n");
976 }
977}
978
979/* Print version information. */
980
981void
982sim_print_version (SIM_DESC sd, int is_command)
983{
984 sim_io_printf (sd, "GNU simulator %s%s\n", PKGVERSION, version);
985
986 sim_io_printf (sd, "Copyright (C) 2024 Free Software Foundation, Inc.\n");
987
988 /* Following the copyright is a brief statement that the program is
989 free software, that users are free to copy and change it on
990 certain conditions, that it is covered by the GNU GPL, and that
991 there is no warranty. */
992
993 sim_io_printf (sd, "\
994License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>\
995\nThis is free software: you are free to change and redistribute it.\n\
996There is NO WARRANTY, to the extent permitted by law.\n");
997
998 if (!is_command)
999 return;
1000
1001 sim_io_printf (sd, "This SIM was configured as:\n");
1002 sim_config_print (sd);
1003
1004 if (REPORT_BUGS_TO[0])
1005 {
1006 sim_io_printf (sd, "For bug reporting instructions, please see:\n\
1007 %s.\n",
1008 REPORT_BUGS_TO);
1009 }
1010 sim_io_printf (sd, "Find the SIM homepage & other documentation resources \
1011online at:\n <https://sourceware.org/gdb/wiki/Sim/>.\n");
1012}
1013
1014/* Utility of sim_args_command to find the closest match for a command.
1015 Commands that have "-" in them can be specified as separate words.
1016 e.g. sim memory-region 0x800000,0x4000
1017 or sim memory region 0x800000,0x4000
1018 If CPU is non-null, use its option table list, otherwise use the main one.
1019 *PARGI is where to start looking in ARGV. It is updated to point past
1020 the found option. */
1021
1022static const OPTION *
1023find_match (SIM_DESC sd, sim_cpu *cpu, char *argv[], int *pargi)
1024{
1025 const struct option_list *ol;
1026 const OPTION *opt;
1027 /* most recent option match */
1028 const OPTION *matching_opt = NULL;
1029 int matching_argi = -1;
1030
1031 if (cpu)
1032 ol = CPU_OPTIONS (cpu);
1033 else
1034 ol = STATE_OPTIONS (sd);
1035
1036 /* Skip passed elements specified by *PARGI. */
1037 argv += *pargi;
1038
1039 for ( ; ol != NULL; ol = ol->next)
1040 for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
1041 {
1042 int argi = 0;
1043 const char *name = opt->opt.name;
1044 if (name == NULL)
1045 continue;
1046 while (argv [argi] != NULL
1047 && strncmp (name, argv [argi], strlen (argv [argi])) == 0)
1048 {
1049 name = &name [strlen (argv[argi])];
1050 if (name [0] == '-')
1051 {
1052 /* leading match ...<a-b-c>-d-e-f - continue search */
1053 name ++; /* skip `-' */
1054 argi ++;
1055 continue;
1056 }
1057 else if (name [0] == '\0')
1058 {
1059 /* exact match ...<a-b-c-d-e-f> - better than before? */
1060 if (argi > matching_argi)
1061 {
1062 matching_argi = argi;
1063 matching_opt = opt;
1064 }
1065 break;
1066 }
1067 else
1068 break;
1069 }
1070 }
1071
1072 *pargi = matching_argi;
1073 return matching_opt;
1074}
1075
1076static char **
1077complete_option_list (char **ret, size_t *cnt, const struct option_list *ol,
1078 const char *text, const char *word)
1079{
1080 const OPTION *opt = NULL;
1081 size_t len = strlen (word);
1082
1083 for ( ; ol != NULL; ol = ol->next)
1084 for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
1085 {
1086 const char *name = opt->opt.name;
1087
1088 /* A long option to match against? */
1089 if (!name)
1090 continue;
1091
1092 /* Does this option actually match? */
1093 if (strncmp (name, word, len))
1094 continue;
1095
1096 ret = xrealloc (ret, ++*cnt * sizeof (ret[0]));
1097 ret[*cnt - 2] = xstrdup (name);
1098 }
1099
1100 return ret;
1101}
1102
1103/* All leading text is stored in @text, while the current word being
1104 completed is stored in @word. Trailing text of @word is not. */
1105
1106char **
1107sim_complete_command (SIM_DESC sd, const char *text, const char *word)
1108{
1109 char **ret = NULL;
1110 size_t cnt = 1;
1111 sim_cpu *cpu;
1112
1113 /* Only complete first word for now. */
1114 if (text != word)
1115 return ret;
1116
1117 cpu = STATE_CPU (sd, 0);
1118 if (cpu)
1119 ret = complete_option_list (ret, &cnt, CPU_OPTIONS (cpu), text, word);
1120 ret = complete_option_list (ret, &cnt, STATE_OPTIONS (sd), text, word);
1121
1122 if (ret)
1123 ret[cnt - 1] = NULL;
1124 return ret;
1125}
1126
1127SIM_RC
1128sim_args_command (SIM_DESC sd, const char *cmd)
1129{
1130 /* something to do? */
1131 if (cmd == NULL)
1132 return SIM_RC_OK; /* FIXME - perhaps help would be better */
1133
1134 if (cmd [0] == '-')
1135 {
1136 /* user specified -<opt> ... form? */
1137 char **argv = buildargv (cmd);
1138 SIM_RC rc = sim_parse_args (sd, argv);
1139 freeargv (argv);
1140 return rc;
1141 }
1142 else
1143 {
1144 char **argv = buildargv (cmd);
1145 const OPTION *matching_opt = NULL;
1146 int matching_argi;
1147 sim_cpu *cpu;
1148
1149 if (argv [0] == NULL)
1150 {
1151 freeargv (argv);
1152 return SIM_RC_OK; /* FIXME - perhaps help would be better */
1153 }
1154
1155 /* First check for a cpu selector. */
1156 {
1157 char *cpu_name = xstrdup (argv[0]);
1158 char *hyphen = strchr (cpu_name, '-');
1159 if (hyphen)
1160 *hyphen = 0;
1161 cpu = sim_cpu_lookup (sd, cpu_name);
1162 if (cpu)
1163 {
1164 /* If <cpuname>-<command>, point argv[0] at <command>. */
1165 if (hyphen)
1166 {
1167 matching_argi = 0;
1168 argv[0] += hyphen - cpu_name + 1;
1169 }
1170 else
1171 matching_argi = 1;
1172 matching_opt = find_match (sd, cpu, argv, &matching_argi);
1173 /* If hyphen found restore argv[0]. */
1174 if (hyphen)
1175 argv[0] -= hyphen - cpu_name + 1;
1176 }
1177 free (cpu_name);
1178 }
1179
1180 /* If that failed, try the main table. */
1181 if (matching_opt == NULL)
1182 {
1183 matching_argi = 0;
1184 matching_opt = find_match (sd, NULL, argv, &matching_argi);
1185 }
1186
1187 if (matching_opt != NULL)
1188 {
1189 switch (matching_opt->opt.has_arg)
1190 {
1191 case no_argument:
1192 if (argv [matching_argi + 1] == NULL)
1193 matching_opt->handler (sd, cpu, matching_opt->opt.val,
1194 NULL, 1/*is_command*/);
1195 else
1196 sim_io_eprintf (sd, "Command `%s' takes no arguments\n",
1197 matching_opt->opt.name);
1198 break;
1199 case optional_argument:
1200 if (argv [matching_argi + 1] == NULL)
1201 matching_opt->handler (sd, cpu, matching_opt->opt.val,
1202 NULL, 1/*is_command*/);
1203 else if (argv [matching_argi + 2] == NULL)
1204 matching_opt->handler (sd, cpu, matching_opt->opt.val,
1205 argv [matching_argi + 1], 1/*is_command*/);
1206 else
1207 sim_io_eprintf (sd, "Command `%s' requires no more than one argument\n",
1208 matching_opt->opt.name);
1209 break;
1210 case required_argument:
1211 if (argv [matching_argi + 1] == NULL)
1212 sim_io_eprintf (sd, "Command `%s' requires an argument\n",
1213 matching_opt->opt.name);
1214 else if (argv [matching_argi + 2] == NULL)
1215 matching_opt->handler (sd, cpu, matching_opt->opt.val,
1216 argv [matching_argi + 1], 1/*is_command*/);
1217 else
1218 sim_io_eprintf (sd, "Command `%s' requires only one argument\n",
1219 matching_opt->opt.name);
1220 }
1221 freeargv (argv);
1222 return SIM_RC_OK;
1223 }
1224
1225 freeargv (argv);
1226 }
1227
1228 /* didn't find anything that remotly matched */
1229 return SIM_RC_FAIL;
1230}