]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/common/sim-options.c
ld: pru: Increase the default memory region sizes
[thirdparty/binutils-gdb.git] / sim / common / sim-options.c
CommitLineData
c906108c 1/* Simulator option handling.
1d506c26 2 Copyright (C) 1996-2024 Free Software Foundation, Inc.
c906108c
SS
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
4744ac1b
JB
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
c906108c
SS
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
4744ac1b
JB
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c 19
6df01ab8
MF
20/* This must come before any other includes. */
21#include "defs.h"
22
c906108c 23#include <ctype.h>
b6061d4d 24#include <stdio.h>
20a8e078
MF
25#include <stdlib.h>
26#include <string.h>
35818ade 27#include <unistd.h>
20a8e078
MF
28
29#include "bfd.h"
30#include "environ.h"
31#include "hashtab.h"
c906108c 32#include "libiberty.h"
20a8e078
MF
33
34#include "sim-main.h"
c906108c
SS
35#include "sim-options.h"
36#include "sim-io.h"
37#include "sim-assert.h"
a542beff 38#include "version.h"
c906108c
SS
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,
adc82fdb 99 OPTION_TARGET_INFO,
c906108c
SS
100 OPTION_ARCHITECTURE_INFO,
101 OPTION_ENVIRONMENT,
102 OPTION_ALIGNMENT,
103 OPTION_VERBOSE,
c906108c 104 OPTION_ENDIAN,
c906108c 105 OPTION_DEBUG,
c906108c 106 OPTION_HELP,
a542beff 107 OPTION_VERSION,
43e526b9
JM
108 OPTION_LOAD_LMA,
109 OPTION_LOAD_VMA,
852016f9
MF
110 OPTION_SYSROOT,
111 OPTION_ARGV0,
35818ade
MF
112 OPTION_ENV_SET,
113 OPTION_ENV_UNSET,
114 OPTION_ENV_CLEAR,
c906108c
SS
115} STANDARD_OPTIONS;
116
117static const OPTION standard_options[] =
118{
119 { {"verbose", no_argument, NULL, OPTION_VERBOSE},
120 'v', NULL, "Verbose output",
21cf617c 121 standard_option_handler, NULL },
c906108c 122
c906108c 123 { {"endian", required_argument, NULL, OPTION_ENDIAN},
21b9b99c 124 'E', "B|big|L|little", "Set endianness",
21cf617c 125 standard_option_handler, NULL },
c906108c 126
c906108c
SS
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 },
c906108c
SS
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
c906108c
SS
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},
bf9f8f41 153 'h', NULL, "Print help information",
c906108c 154 standard_option_handler },
a542beff
MF
155 { {"version", no_argument, NULL, OPTION_VERSION},
156 '\0', NULL, "Print version information",
157 standard_option_handler },
c906108c
SS
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 },
adc82fdb
MF
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 },
c906108c 176
43e526b9
JM
177 { {"load-lma", no_argument, NULL, OPTION_LOAD_LMA},
178 '\0', NULL,
43e526b9 179 "Use VMA or LMA addresses when loading image (default LMA)",
43e526b9
JM
180 standard_option_handler, "load-{lma,vma}" },
181 { {"load-vma", no_argument, NULL, OPTION_LOAD_VMA},
182 '\0', NULL, "", standard_option_handler, "" },
43e526b9 183
027e2a04
HPN
184 { {"sysroot", required_argument, NULL, OPTION_SYSROOT},
185 '\0', "SYSROOT",
186 "Root for system calls with absolute file-names and cwd at start",
21cf617c 187 standard_option_handler, NULL },
027e2a04 188
852016f9
MF
189 { {"argv0", required_argument, NULL, OPTION_ARGV0},
190 '\0', "ARGV0", "Set argv[0] to the specified string",
191 standard_option_handler, NULL },
192
35818ade
MF
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
21cf617c 203 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
c906108c
SS
204};
205
35818ade
MF
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
c906108c
SS
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
c906108c 262 case OPTION_ENDIAN:
21b9b99c 263 if (strcmp (arg, "big") == 0 || strcmp (arg, "B") == 0)
c906108c 264 {
1ac72f06 265 if (WITH_TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
c906108c
SS
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. */
1ac72f06 271 current_target_byte_order = BFD_ENDIAN_BIG;
c906108c 272 }
21b9b99c 273 else if (strcmp (arg, "little") == 0 || strcmp (arg, "L") == 0)
c906108c 274 {
1ac72f06 275 if (WITH_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
c906108c
SS
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. */
1ac72f06 281 current_target_byte_order = BFD_ENDIAN_LITTLE;
c906108c
SS
282 }
283 else
284 {
285 sim_io_eprintf (sd, "Invalid endian specification `%s'\n", arg);
286 return SIM_RC_FAIL;
287 }
288 break;
c906108c
SS
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 {
3dd68605 305 const char *type;
c906108c
SS
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;
72042732 311 default: abort ();
c906108c
SS
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;
72042732 360 default: abort ();
c906108c
SS
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
c906108c
SS
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 {
34b47c38 420 const char **list = bfd_arch_list ();
c906108c
SS
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
adc82fdb
MF
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
43e526b9
JM
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
c906108c
SS
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;
027e2a04 470
a542beff 471 case OPTION_VERSION:
19b1c385 472 sim_print_version (sd, is_command);
a542beff
MF
473 if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
474 exit (0);
475 break;
476
027e2a04
HPN
477 case OPTION_SYSROOT:
478 /* Don't leak memory in the odd event that there's lots of
440db575
MF
479 --sysroot=... options. We treat "" specially since this
480 is the statically initialized value and cannot free it. */
481 if (simulator_sysroot[0] != '\0')
027e2a04 482 free (simulator_sysroot);
440db575
MF
483 if (arg[0] != '\0')
484 simulator_sysroot = xstrdup (arg);
485 else
486 simulator_sysroot = "";
027e2a04 487 break;
852016f9
MF
488
489 case OPTION_ARGV0:
490 free (STATE_PROG_ARGV0 (sd));
491 STATE_PROG_ARGV0 (sd) = xstrdup (arg);
492 break;
35818ade
MF
493
494 case OPTION_ENV_SET:
495 return env_set (sd, arg);
496
497 case OPTION_ENV_UNSET:
498 {
ef382e84 499 int varlen;
35818ade
MF
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;
c906108c
SS
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;
26936211 546 STATE_LOAD_AT_LMA_P (sd) = 1;
c906108c
SS
547 return SIM_RC_OK;
548}
549
550/* Return non-zero if arg is a duplicate argument.
551 If ARG is NULL, initialize. */
552
c906108c 553static int
e377ca52 554dup_arg_p (const char *arg)
c906108c 555{
4478c331
TT
556 static htab_t arg_table = NULL;
557 void **slot;
c906108c
SS
558
559 if (arg == NULL)
560 {
561 if (arg_table == NULL)
4478c331 562 arg_table = htab_create_alloc (10, htab_hash_string,
65a9835b 563 htab_eq_string, NULL,
4478c331 564 xcalloc, free);
e4821e2f 565 htab_empty (arg_table);
c906108c
SS
566 return 0;
567 }
568
4478c331
TT
569 slot = htab_find_slot (arg_table, arg, INSERT);
570 if (*slot != NULL)
571 return 1;
572 *slot = (void *) arg;
c906108c
SS
573 return 0;
574}
028f6515 575
c906108c
SS
576/* Called by sim_open to parse the arguments. */
577
578SIM_RC
2e3d4f4d 579sim_parse_args (SIM_DESC sd, char * const *argv)
c906108c 580{
77cf2ef5 581 int c, i, argc, num_opts, save_opterr;
c906108c
SS
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;
7c070881 592 SIM_RC result = SIM_RC_OK;
c906108c
SS
593
594 /* Count the number of arguments. */
34fed699 595 argc = countargv (argv);
c906108c
SS
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");
7c070881
SC
672 result = SIM_RC_FAIL;
673 break;
c906108c
SS
674 }
675 if (opt->opt.name != NULL)
676 {
677 char *name;
678 *lp = opt->opt;
679 /* Prepend --<cpuname>- to the option. */
39a3ae0a
MF
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 }
c906108c
SS
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 }
028f6515 696
c906108c
SS
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
77cf2ef5
MF
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
c906108c
SS
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)
e8f20a28 717 {
7770da97 718 char **new_argv;
852016f9 719
7770da97
MF
720 free (STATE_PROG_FILE (sd));
721 STATE_PROG_FILE (sd) = NULL;
722
3b293485
MF
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
7770da97 739 new_argv = dupargv (argv + optind);
852016f9
MF
740 freeargv (STATE_PROG_ARGV (sd));
741 STATE_PROG_ARGV (sd) = new_argv;
7770da97
MF
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 }
e8f20a28 754 }
c906108c
SS
755 break;
756 }
757 if (optc == '?')
7c070881 758 {
77cf2ef5
MF
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,
8d7d784e 774 "%s: unrecognized option '%s'\n"
77cf2ef5
MF
775 "Use --help for a complete list of options.\n",
776 STATE_MY_NAME (sd), badopt);
777
7c070881
SC
778 result = SIM_RC_FAIL;
779 break;
780 }
c906108c
SS
781
782 if ((*handlers[optc]) (sd, opt_cpu[optc], orig_val[optc], optarg, 0/*!is_command*/) == SIM_RC_FAIL)
7c070881
SC
783 {
784 result = SIM_RC_FAIL;
785 break;
786 }
c906108c
SS
787 }
788
77cf2ef5
MF
789 opterr = save_opterr;
790
d79fe0d6
MF
791 free (long_options);
792 free (short_options);
793 free (handlers);
794 free (opt_cpu);
795 free (orig_val);
7c070881 796 return result;
c906108c
SS
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 }
028f6515 856
c906108c
SS
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 {
c4093a6a 882 sim_io_printf (sd, "[=%s]", o->arg);
c906108c
SS
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;
e158f0a0
AC
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 "");
c906108c
SS
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
dc416615 931sim_print_help (SIM_DESC sd, int is_command)
c906108c
SS
932{
933 if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
3b293485
MF
934 sim_io_printf (sd,
935 "Usage: %s [options] [VAR=VAL|--] program [program args]\n",
c906108c
SS
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");
3b293485
MF
971 sim_io_printf (sd,
972 "VAR=VAL Environment variables to set. "
973 "Ignored if -- is used.\n");
c906108c
SS
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
19b1c385
MF
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
1d506c26 986 sim_io_printf (sd, "Copyright (C) 2024 Free Software Foundation, Inc.\n");
19b1c385
MF
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");
babd2ee1
MF
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");
19b1c385
MF
1012}
1013
c906108c
SS
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
56a9aa1d
MF
1076static char **
1077complete_option_list (char **ret, size_t *cnt, const struct option_list *ol,
f06dccb0 1078 const char *text, const char *word)
56a9aa1d
MF
1079{
1080 const OPTION *opt = NULL;
56a9aa1d
MF
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. */
5592f70e 1105
56a9aa1d 1106char **
3cb2ab1a 1107sim_complete_command (SIM_DESC sd, const char *text, const char *word)
56a9aa1d
MF
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
c906108c 1127SIM_RC
60d847df 1128sim_args_command (SIM_DESC sd, const char *cmd)
c906108c
SS
1129{
1130 /* something to do? */
1131 if (cmd == NULL)
109d3db3 1132 return SIM_RC_OK; /* FIXME - perhaps help would be better */
028f6515 1133
c906108c
SS
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)
c9ba137e
CG
1150 {
1151 freeargv (argv);
1152 return SIM_RC_OK; /* FIXME - perhaps help would be better */
1153 }
c906108c
SS
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 }
028f6515 1227
c906108c
SS
1228 /* didn't find anything that remotly matched */
1229 return SIM_RC_FAIL;
1230}