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