]> Git Repo - binutils.git/blob - sim/common/sim-options.c
Automatic date update in version.in
[binutils.git] / sim / common / sim-options.c
1 /* Simulator option handling.
2    Copyright (C) 1996-2022 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 /* 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
44 SIM_RC
45 sim_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
75 static 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
93 typedef 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
117 static 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
206 static SIM_RC
207 env_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
250 static SIM_RC
251 standard_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 i, 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
540 SIM_RC
541 standard_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
553 static int
554 dup_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
578 SIM_RC
579 sim_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
801 static void
802 print_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
930 void
931 sim_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
981 void
982 sim_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) 2022 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, "\
994 License 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\
996 There 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 \
1011 online 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
1022 static const OPTION *
1023 find_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
1076 static char **
1077 complete_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   int argi;
1082   size_t len = strlen (word);
1083
1084   for ( ; ol != NULL; ol = ol->next)
1085     for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
1086       {
1087         const char *name = opt->opt.name;
1088
1089         /* A long option to match against?  */
1090         if (!name)
1091           continue;
1092
1093         /* Does this option actually match?  */
1094         if (strncmp (name, word, len))
1095           continue;
1096
1097         ret = xrealloc (ret, ++*cnt * sizeof (ret[0]));
1098         ret[*cnt - 2] = xstrdup (name);
1099       }
1100
1101   return ret;
1102 }
1103
1104 /* All leading text is stored in @text, while the current word being
1105    completed is stored in @word.  Trailing text of @word is not.  */
1106
1107 char **
1108 sim_complete_command (SIM_DESC sd, const char *text, const char *word)
1109 {
1110   char **ret = NULL;
1111   size_t cnt = 1;
1112   sim_cpu *cpu;
1113
1114   /* Only complete first word for now.  */
1115   if (text != word)
1116     return ret;
1117
1118   cpu = STATE_CPU (sd, 0);
1119   if (cpu)
1120     ret = complete_option_list (ret, &cnt, CPU_OPTIONS (cpu), text, word);
1121   ret = complete_option_list (ret, &cnt, STATE_OPTIONS (sd), text, word);
1122
1123   if (ret)
1124     ret[cnt - 1] = NULL;
1125   return ret;
1126 }
1127
1128 SIM_RC
1129 sim_args_command (SIM_DESC sd, const char *cmd)
1130 {
1131   /* something to do? */
1132   if (cmd == NULL)
1133     return SIM_RC_OK; /* FIXME - perhaps help would be better */
1134
1135   if (cmd [0] == '-')
1136     {
1137       /* user specified -<opt> ... form? */
1138       char **argv = buildargv (cmd);
1139       SIM_RC rc = sim_parse_args (sd, argv);
1140       freeargv (argv);
1141       return rc;
1142     }
1143   else
1144     {
1145       char **argv = buildargv (cmd);
1146       const OPTION *matching_opt = NULL;
1147       int matching_argi;
1148       sim_cpu *cpu;
1149
1150       if (argv [0] == NULL)
1151         {
1152           freeargv (argv);
1153           return SIM_RC_OK; /* FIXME - perhaps help would be better */
1154         }
1155
1156       /* First check for a cpu selector.  */
1157       {
1158         char *cpu_name = xstrdup (argv[0]);
1159         char *hyphen = strchr (cpu_name, '-');
1160         if (hyphen)
1161           *hyphen = 0;
1162         cpu = sim_cpu_lookup (sd, cpu_name);
1163         if (cpu)
1164           {
1165             /* If <cpuname>-<command>, point argv[0] at <command>.  */
1166             if (hyphen)
1167               {
1168                 matching_argi = 0;
1169                 argv[0] += hyphen - cpu_name + 1;
1170               }
1171             else
1172               matching_argi = 1;
1173             matching_opt = find_match (sd, cpu, argv, &matching_argi);
1174             /* If hyphen found restore argv[0].  */
1175             if (hyphen)
1176               argv[0] -= hyphen - cpu_name + 1;
1177           }
1178         free (cpu_name);
1179       }
1180
1181       /* If that failed, try the main table.  */
1182       if (matching_opt == NULL)
1183         {
1184           matching_argi = 0;
1185           matching_opt = find_match (sd, NULL, argv, &matching_argi);
1186         }
1187
1188       if (matching_opt != NULL)
1189         {
1190           switch (matching_opt->opt.has_arg)
1191             {
1192             case no_argument:
1193               if (argv [matching_argi + 1] == NULL)
1194                 matching_opt->handler (sd, cpu, matching_opt->opt.val,
1195                                        NULL, 1/*is_command*/);
1196               else
1197                 sim_io_eprintf (sd, "Command `%s' takes no arguments\n",
1198                                 matching_opt->opt.name);
1199               break;
1200             case optional_argument:
1201               if (argv [matching_argi + 1] == NULL)
1202                 matching_opt->handler (sd, cpu, matching_opt->opt.val,
1203                                        NULL, 1/*is_command*/);
1204               else if (argv [matching_argi + 2] == NULL)
1205                 matching_opt->handler (sd, cpu, matching_opt->opt.val,
1206                                        argv [matching_argi + 1], 1/*is_command*/);
1207               else
1208                 sim_io_eprintf (sd, "Command `%s' requires no more than one argument\n",
1209                                 matching_opt->opt.name);
1210               break;
1211             case required_argument:
1212               if (argv [matching_argi + 1] == NULL)
1213                 sim_io_eprintf (sd, "Command `%s' requires an argument\n",
1214                                 matching_opt->opt.name);
1215               else if (argv [matching_argi + 2] == NULL)
1216                 matching_opt->handler (sd, cpu, matching_opt->opt.val,
1217                                        argv [matching_argi + 1], 1/*is_command*/);
1218               else
1219                 sim_io_eprintf (sd, "Command `%s' requires only one argument\n",
1220                                 matching_opt->opt.name);
1221             }
1222           freeargv (argv);
1223           return SIM_RC_OK;
1224         }
1225
1226       freeargv (argv);
1227     }
1228
1229   /* didn't find anything that remotly matched */
1230   return SIM_RC_FAIL;
1231 }
This page took 0.095054 seconds and 4 git commands to generate.