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