xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/sim-options.c (revision 0d3e0572e40d81edb4fdbff937458d47b685c34c)
14e98e3e1Schristos /* Simulator option handling.
2*0d3e0572Schristos    Copyright (C) 1996-2024 Free Software Foundation, Inc.
34e98e3e1Schristos    Contributed by Cygnus Support.
44e98e3e1Schristos 
54e98e3e1Schristos This file is part of GDB, the GNU debugger.
64e98e3e1Schristos 
74e98e3e1Schristos This program is free software; you can redistribute it and/or modify
84e98e3e1Schristos it under the terms of the GNU General Public License as published by
94e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or
104e98e3e1Schristos (at your option) any later version.
114e98e3e1Schristos 
124e98e3e1Schristos This program is distributed in the hope that it will be useful,
134e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
144e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
154e98e3e1Schristos GNU General Public License for more details.
164e98e3e1Schristos 
174e98e3e1Schristos You should have received a copy of the GNU General Public License
184e98e3e1Schristos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
194e98e3e1Schristos 
204b169a6bSchristos /* This must come before any other includes.  */
214b169a6bSchristos #include "defs.h"
224b169a6bSchristos 
234e98e3e1Schristos #include <ctype.h>
248dffb485Schristos #include <stdio.h>
254b169a6bSchristos #include <stdlib.h>
264b169a6bSchristos #include <string.h>
274b169a6bSchristos #include <unistd.h>
284b169a6bSchristos 
294b169a6bSchristos #include "bfd.h"
304b169a6bSchristos #include "environ.h"
314b169a6bSchristos #include "hashtab.h"
324e98e3e1Schristos #include "libiberty.h"
334b169a6bSchristos 
344b169a6bSchristos #include "sim-main.h"
354e98e3e1Schristos #include "sim-options.h"
364e98e3e1Schristos #include "sim-io.h"
374e98e3e1Schristos #include "sim-assert.h"
38212397c6Schristos #include "version.h"
394e98e3e1Schristos 
404e98e3e1Schristos /* Add a set of options to the simulator.
414e98e3e1Schristos    TABLE is an array of OPTIONS terminated by a NULL `opt.name' entry.
424e98e3e1Schristos    This is intended to be called by modules in their `install' handler.  */
434e98e3e1Schristos 
444e98e3e1Schristos SIM_RC
454e98e3e1Schristos sim_add_option_table (SIM_DESC sd, sim_cpu *cpu, const OPTION *table)
464e98e3e1Schristos {
474e98e3e1Schristos   struct option_list *ol = ((struct option_list *)
484e98e3e1Schristos 			    xmalloc (sizeof (struct option_list)));
494e98e3e1Schristos 
504e98e3e1Schristos   /* Note: The list is constructed in the reverse order we're called so
514e98e3e1Schristos      later calls will override earlier ones (in case that ever happens).
524e98e3e1Schristos      This is the intended behaviour.  */
534e98e3e1Schristos 
544e98e3e1Schristos   if (cpu)
554e98e3e1Schristos     {
564e98e3e1Schristos       ol->next = CPU_OPTIONS (cpu);
574e98e3e1Schristos       ol->options = table;
584e98e3e1Schristos       CPU_OPTIONS (cpu) = ol;
594e98e3e1Schristos     }
604e98e3e1Schristos   else
614e98e3e1Schristos     {
624e98e3e1Schristos       ol->next = STATE_OPTIONS (sd);
634e98e3e1Schristos       ol->options = table;
644e98e3e1Schristos       STATE_OPTIONS (sd) = ol;
654e98e3e1Schristos     }
664e98e3e1Schristos 
674e98e3e1Schristos   return SIM_RC_OK;
684e98e3e1Schristos }
694e98e3e1Schristos 
704e98e3e1Schristos /* Standard option table.
714e98e3e1Schristos    Modules may specify additional ones.
724e98e3e1Schristos    The caller of sim_parse_args may also specify additional options
734e98e3e1Schristos    by calling sim_add_option_table first.  */
744e98e3e1Schristos 
754e98e3e1Schristos static DECLARE_OPTION_HANDLER (standard_option_handler);
764e98e3e1Schristos 
774e98e3e1Schristos /* FIXME: We shouldn't print in --help output options that aren't usable.
784e98e3e1Schristos    Some fine tuning will be necessary.  One can either move less general
794e98e3e1Schristos    options to another table or use a HAVE_FOO macro to ifdef out unavailable
804e98e3e1Schristos    options.  */
814e98e3e1Schristos 
824e98e3e1Schristos /* ??? One might want to conditionally compile out the entries that
834e98e3e1Schristos    aren't enabled.  There's a distinction, however, between options a
844e98e3e1Schristos    simulator can't support and options that haven't been configured in.
854e98e3e1Schristos    Certainly options a simulator can't support shouldn't appear in the
864e98e3e1Schristos    output of --help.  Whether the same thing applies to options that haven't
874e98e3e1Schristos    been configured in or not isn't something I can get worked up over.
884e98e3e1Schristos    [Note that conditionally compiling them out might simply involve moving
894e98e3e1Schristos    the option to another table.]
904e98e3e1Schristos    If you decide to conditionally compile them out as well, delete this
914e98e3e1Schristos    comment and add a comment saying that that is the rule.  */
924e98e3e1Schristos 
934e98e3e1Schristos typedef enum {
944e98e3e1Schristos   OPTION_DEBUG_INSN = OPTION_START,
954e98e3e1Schristos   OPTION_DEBUG_FILE,
964e98e3e1Schristos   OPTION_DO_COMMAND,
974e98e3e1Schristos   OPTION_ARCHITECTURE,
984e98e3e1Schristos   OPTION_TARGET,
994b169a6bSchristos   OPTION_TARGET_INFO,
1004e98e3e1Schristos   OPTION_ARCHITECTURE_INFO,
1014e98e3e1Schristos   OPTION_ENVIRONMENT,
1024e98e3e1Schristos   OPTION_ALIGNMENT,
1034e98e3e1Schristos   OPTION_VERBOSE,
1044e98e3e1Schristos   OPTION_ENDIAN,
1054e98e3e1Schristos   OPTION_DEBUG,
1064e98e3e1Schristos   OPTION_HELP,
107212397c6Schristos   OPTION_VERSION,
1084e98e3e1Schristos   OPTION_LOAD_LMA,
1094e98e3e1Schristos   OPTION_LOAD_VMA,
1104b169a6bSchristos   OPTION_SYSROOT,
1114b169a6bSchristos   OPTION_ARGV0,
1124b169a6bSchristos   OPTION_ENV_SET,
1134b169a6bSchristos   OPTION_ENV_UNSET,
1144b169a6bSchristos   OPTION_ENV_CLEAR,
1154e98e3e1Schristos } STANDARD_OPTIONS;
1164e98e3e1Schristos 
1174e98e3e1Schristos static const OPTION standard_options[] =
1184e98e3e1Schristos {
1194e98e3e1Schristos   { {"verbose", no_argument, NULL, OPTION_VERBOSE},
1204e98e3e1Schristos       'v', NULL, "Verbose output",
1214e98e3e1Schristos       standard_option_handler, NULL },
1224e98e3e1Schristos 
1234e98e3e1Schristos   { {"endian", required_argument, NULL, OPTION_ENDIAN},
1244b169a6bSchristos       'E', "B|big|L|little", "Set endianness",
1254e98e3e1Schristos       standard_option_handler, NULL },
1264e98e3e1Schristos 
1274e98e3e1Schristos   /* This option isn't supported unless all choices are supported in keeping
1284e98e3e1Schristos      with the goal of not printing in --help output things the simulator can't
1294e98e3e1Schristos      do [as opposed to things that just haven't been configured in].  */
1304e98e3e1Schristos   { {"environment", required_argument, NULL, OPTION_ENVIRONMENT},
1314e98e3e1Schristos       '\0', "user|virtual|operating", "Set running environment",
1324e98e3e1Schristos       standard_option_handler },
1334e98e3e1Schristos 
1344e98e3e1Schristos   { {"alignment", required_argument, NULL, OPTION_ALIGNMENT},
1354e98e3e1Schristos       '\0', "strict|nonstrict|forced", "Set memory access alignment",
1364e98e3e1Schristos       standard_option_handler },
1374e98e3e1Schristos 
1384e98e3e1Schristos   { {"debug", no_argument, NULL, OPTION_DEBUG},
1394e98e3e1Schristos       'D', NULL, "Print debugging messages",
1404e98e3e1Schristos       standard_option_handler },
1414e98e3e1Schristos   { {"debug-insn", no_argument, NULL, OPTION_DEBUG_INSN},
1424e98e3e1Schristos       '\0', NULL, "Print instruction debugging messages",
1434e98e3e1Schristos       standard_option_handler },
1444e98e3e1Schristos   { {"debug-file", required_argument, NULL, OPTION_DEBUG_FILE},
1454e98e3e1Schristos       '\0', "FILE NAME", "Specify debugging output file",
1464e98e3e1Schristos       standard_option_handler },
1474e98e3e1Schristos 
1484e98e3e1Schristos   { {"do-command", required_argument, NULL, OPTION_DO_COMMAND},
1494e98e3e1Schristos       '\0', "COMMAND", ""/*undocumented*/,
1504e98e3e1Schristos       standard_option_handler },
1514e98e3e1Schristos 
1524e98e3e1Schristos   { {"help", no_argument, NULL, OPTION_HELP},
1534b169a6bSchristos       'h', NULL, "Print help information",
1544e98e3e1Schristos       standard_option_handler },
155212397c6Schristos   { {"version", no_argument, NULL, OPTION_VERSION},
156212397c6Schristos       '\0', NULL, "Print version information",
157212397c6Schristos       standard_option_handler },
1584e98e3e1Schristos 
1594e98e3e1Schristos   { {"architecture", required_argument, NULL, OPTION_ARCHITECTURE},
1604e98e3e1Schristos       '\0', "MACHINE", "Specify the architecture to use",
1614e98e3e1Schristos       standard_option_handler },
1624e98e3e1Schristos   { {"architecture-info", no_argument, NULL, OPTION_ARCHITECTURE_INFO},
1634e98e3e1Schristos       '\0', NULL, "List supported architectures",
1644e98e3e1Schristos       standard_option_handler },
1654e98e3e1Schristos   { {"info-architecture", no_argument, NULL, OPTION_ARCHITECTURE_INFO},
1664e98e3e1Schristos       '\0', NULL, NULL,
1674e98e3e1Schristos       standard_option_handler },
1684e98e3e1Schristos 
1694e98e3e1Schristos   { {"target", required_argument, NULL, OPTION_TARGET},
1704e98e3e1Schristos       '\0', "BFDNAME", "Specify the object-code format for the object files",
1714e98e3e1Schristos       standard_option_handler },
1724b169a6bSchristos   { {"target-info", no_argument, NULL, OPTION_TARGET_INFO},
1734b169a6bSchristos       '\0', NULL, "List supported targets", standard_option_handler },
1744b169a6bSchristos   { {"info-target", no_argument, NULL, OPTION_TARGET_INFO},
1754b169a6bSchristos       '\0', NULL, NULL, standard_option_handler },
1764e98e3e1Schristos 
1774e98e3e1Schristos   { {"load-lma", no_argument, NULL, OPTION_LOAD_LMA},
1784e98e3e1Schristos       '\0', NULL,
1794e98e3e1Schristos     "Use VMA or LMA addresses when loading image (default LMA)",
1804e98e3e1Schristos       standard_option_handler, "load-{lma,vma}" },
1814e98e3e1Schristos   { {"load-vma", no_argument, NULL, OPTION_LOAD_VMA},
1824e98e3e1Schristos       '\0', NULL, "", standard_option_handler,  "" },
1834e98e3e1Schristos 
1844e98e3e1Schristos   { {"sysroot", required_argument, NULL, OPTION_SYSROOT},
1854e98e3e1Schristos       '\0', "SYSROOT",
1864e98e3e1Schristos     "Root for system calls with absolute file-names and cwd at start",
1874e98e3e1Schristos       standard_option_handler, NULL },
1884e98e3e1Schristos 
1894b169a6bSchristos   { {"argv0", required_argument, NULL, OPTION_ARGV0},
1904b169a6bSchristos       '\0', "ARGV0", "Set argv[0] to the specified string",
1914b169a6bSchristos       standard_option_handler, NULL },
1924b169a6bSchristos 
1934b169a6bSchristos   { {"env-set", required_argument, NULL, OPTION_ENV_SET},
1944b169a6bSchristos       '\0', "VAR=VAL", "Set the variable in the program's environment",
1954b169a6bSchristos       standard_option_handler, NULL },
1964b169a6bSchristos   { {"env-unset", required_argument, NULL, OPTION_ENV_UNSET},
1974b169a6bSchristos       '\0', "VAR", "Unset the variable in the program's environment",
1984b169a6bSchristos       standard_option_handler, NULL },
1994b169a6bSchristos   { {"env-clear", no_argument, NULL, OPTION_ENV_CLEAR},
2004b169a6bSchristos       '\0', NULL, "Clear the program's environment",
2014b169a6bSchristos       standard_option_handler, NULL },
2024b169a6bSchristos 
2034e98e3e1Schristos   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
2044e98e3e1Schristos };
2054e98e3e1Schristos 
2064e98e3e1Schristos static SIM_RC
2074b169a6bSchristos env_set (SIM_DESC sd, const char *arg)
2084b169a6bSchristos {
2094b169a6bSchristos   int i, varlen;
2104b169a6bSchristos   char *eq;
2114b169a6bSchristos   char **envp;
2124b169a6bSchristos 
2134b169a6bSchristos   if (STATE_PROG_ENVP (sd) == NULL)
2144b169a6bSchristos     STATE_PROG_ENVP (sd) = dupargv (environ);
2154b169a6bSchristos 
2164b169a6bSchristos   eq = strchr (arg, '=');
2174b169a6bSchristos   if (eq == NULL)
2184b169a6bSchristos     {
2194b169a6bSchristos       sim_io_eprintf (sd, "invalid syntax when setting env var `%s'"
2204b169a6bSchristos 		      ": missing value", arg);
2214b169a6bSchristos       return SIM_RC_FAIL;
2224b169a6bSchristos     }
2234b169a6bSchristos   /* Include the = in the comparison below.  */
2244b169a6bSchristos   varlen = eq - arg + 1;
2254b169a6bSchristos 
2264b169a6bSchristos   /* If we can find an existing variable, replace it.  */
2274b169a6bSchristos   envp = STATE_PROG_ENVP (sd);
2284b169a6bSchristos   for (i = 0; envp[i]; ++i)
2294b169a6bSchristos     {
2304b169a6bSchristos       if (strncmp (envp[i], arg, varlen) == 0)
2314b169a6bSchristos 	{
2324b169a6bSchristos 	  free (envp[i]);
2334b169a6bSchristos 	  envp[i] = xstrdup (arg);
2344b169a6bSchristos 	  break;
2354b169a6bSchristos 	}
2364b169a6bSchristos     }
2374b169a6bSchristos 
2384b169a6bSchristos   /* If we didn't find the var, add it.  */
2394b169a6bSchristos   if (envp[i] == NULL)
2404b169a6bSchristos     {
2414b169a6bSchristos       envp = xrealloc (envp, (i + 2) * sizeof (char *));
2424b169a6bSchristos       envp[i] = xstrdup (arg);
2434b169a6bSchristos       envp[i + 1] = NULL;
2444b169a6bSchristos       STATE_PROG_ENVP (sd) = envp;
2454b169a6bSchristos   }
2464b169a6bSchristos 
2474b169a6bSchristos   return SIM_RC_OK;
2484b169a6bSchristos }
2494b169a6bSchristos 
2504b169a6bSchristos static SIM_RC
2514e98e3e1Schristos standard_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
2524e98e3e1Schristos 			 char *arg, int is_command)
2534e98e3e1Schristos {
2544e98e3e1Schristos   int i,n;
2554e98e3e1Schristos 
2564e98e3e1Schristos   switch ((STANDARD_OPTIONS) opt)
2574e98e3e1Schristos     {
2584e98e3e1Schristos     case OPTION_VERBOSE:
2594e98e3e1Schristos       STATE_VERBOSE_P (sd) = 1;
2604e98e3e1Schristos       break;
2614e98e3e1Schristos 
2624e98e3e1Schristos     case OPTION_ENDIAN:
2634b169a6bSchristos       if (strcmp (arg, "big") == 0 || strcmp (arg, "B") == 0)
2644e98e3e1Schristos 	{
265ba340e45Schristos 	  if (WITH_TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
2664e98e3e1Schristos 	    {
2674e98e3e1Schristos 	      sim_io_eprintf (sd, "Simulator compiled for little endian only.\n");
2684e98e3e1Schristos 	      return SIM_RC_FAIL;
2694e98e3e1Schristos 	    }
2704e98e3e1Schristos 	  /* FIXME:wip: Need to set something in STATE_CONFIG.  */
271ba340e45Schristos 	  current_target_byte_order = BFD_ENDIAN_BIG;
2724e98e3e1Schristos 	}
2734b169a6bSchristos       else if (strcmp (arg, "little") == 0 || strcmp (arg, "L") == 0)
2744e98e3e1Schristos 	{
275ba340e45Schristos 	  if (WITH_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
2764e98e3e1Schristos 	    {
2774e98e3e1Schristos 	      sim_io_eprintf (sd, "Simulator compiled for big endian only.\n");
2784e98e3e1Schristos 	      return SIM_RC_FAIL;
2794e98e3e1Schristos 	    }
2804e98e3e1Schristos 	  /* FIXME:wip: Need to set something in STATE_CONFIG.  */
281ba340e45Schristos 	  current_target_byte_order = BFD_ENDIAN_LITTLE;
2824e98e3e1Schristos 	}
2834e98e3e1Schristos       else
2844e98e3e1Schristos 	{
2854e98e3e1Schristos 	  sim_io_eprintf (sd, "Invalid endian specification `%s'\n", arg);
2864e98e3e1Schristos 	  return SIM_RC_FAIL;
2874e98e3e1Schristos 	}
2884e98e3e1Schristos       break;
2894e98e3e1Schristos 
2904e98e3e1Schristos     case OPTION_ENVIRONMENT:
2914e98e3e1Schristos       if (strcmp (arg, "user") == 0)
2924e98e3e1Schristos 	STATE_ENVIRONMENT (sd) = USER_ENVIRONMENT;
2934e98e3e1Schristos       else if (strcmp (arg, "virtual") == 0)
2944e98e3e1Schristos 	STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT;
2954e98e3e1Schristos       else if (strcmp (arg, "operating") == 0)
2964e98e3e1Schristos 	STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
2974e98e3e1Schristos       else
2984e98e3e1Schristos 	{
2994e98e3e1Schristos 	  sim_io_eprintf (sd, "Invalid environment specification `%s'\n", arg);
3004e98e3e1Schristos 	  return SIM_RC_FAIL;
3014e98e3e1Schristos 	}
3024e98e3e1Schristos       if (WITH_ENVIRONMENT != ALL_ENVIRONMENT
3034e98e3e1Schristos 	  && WITH_ENVIRONMENT != STATE_ENVIRONMENT (sd))
3044e98e3e1Schristos 	{
3054e98e3e1Schristos 	  const char *type;
3064e98e3e1Schristos 	  switch (WITH_ENVIRONMENT)
3074e98e3e1Schristos 	    {
3084e98e3e1Schristos 	    case USER_ENVIRONMENT: type = "user"; break;
3094e98e3e1Schristos 	    case VIRTUAL_ENVIRONMENT: type = "virtual"; break;
3104e98e3e1Schristos 	    case OPERATING_ENVIRONMENT: type = "operating"; break;
3114b169a6bSchristos 	    default: abort ();
3124e98e3e1Schristos 	    }
3134e98e3e1Schristos 	  sim_io_eprintf (sd, "Simulator compiled for the %s environment only.\n",
3144e98e3e1Schristos 			  type);
3154e98e3e1Schristos 	  return SIM_RC_FAIL;
3164e98e3e1Schristos 	}
3174e98e3e1Schristos       break;
3184e98e3e1Schristos 
3194e98e3e1Schristos     case OPTION_ALIGNMENT:
3204e98e3e1Schristos       if (strcmp (arg, "strict") == 0)
3214e98e3e1Schristos 	{
3224e98e3e1Schristos 	  if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == STRICT_ALIGNMENT)
3234e98e3e1Schristos 	    {
3244e98e3e1Schristos 	      current_alignment = STRICT_ALIGNMENT;
3254e98e3e1Schristos 	      break;
3264e98e3e1Schristos 	    }
3274e98e3e1Schristos 	}
3284e98e3e1Schristos       else if (strcmp (arg, "nonstrict") == 0)
3294e98e3e1Schristos 	{
3304e98e3e1Schristos 	  if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == NONSTRICT_ALIGNMENT)
3314e98e3e1Schristos 	    {
3324e98e3e1Schristos 	      current_alignment = NONSTRICT_ALIGNMENT;
3334e98e3e1Schristos 	      break;
3344e98e3e1Schristos 	    }
3354e98e3e1Schristos 	}
3364e98e3e1Schristos       else if (strcmp (arg, "forced") == 0)
3374e98e3e1Schristos 	{
3384e98e3e1Schristos 	  if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == FORCED_ALIGNMENT)
3394e98e3e1Schristos 	    {
3404e98e3e1Schristos 	      current_alignment = FORCED_ALIGNMENT;
3414e98e3e1Schristos 	      break;
3424e98e3e1Schristos 	    }
3434e98e3e1Schristos 	}
3444e98e3e1Schristos       else
3454e98e3e1Schristos 	{
3464e98e3e1Schristos 	  sim_io_eprintf (sd, "Invalid alignment specification `%s'\n", arg);
3474e98e3e1Schristos 	  return SIM_RC_FAIL;
3484e98e3e1Schristos 	}
3494e98e3e1Schristos       switch (WITH_ALIGNMENT)
3504e98e3e1Schristos 	{
3514e98e3e1Schristos 	case STRICT_ALIGNMENT:
3524e98e3e1Schristos 	  sim_io_eprintf (sd, "Simulator compiled for strict alignment only.\n");
3534e98e3e1Schristos 	  break;
3544e98e3e1Schristos 	case NONSTRICT_ALIGNMENT:
3554e98e3e1Schristos 	  sim_io_eprintf (sd, "Simulator compiled for nonstrict alignment only.\n");
3564e98e3e1Schristos 	  break;
3574e98e3e1Schristos 	case FORCED_ALIGNMENT:
3584e98e3e1Schristos 	  sim_io_eprintf (sd, "Simulator compiled for forced alignment only.\n");
3594e98e3e1Schristos 	  break;
3604b169a6bSchristos 	default: abort ();
3614e98e3e1Schristos 	}
3624e98e3e1Schristos       return SIM_RC_FAIL;
3634e98e3e1Schristos 
3644e98e3e1Schristos     case OPTION_DEBUG:
3654e98e3e1Schristos       if (! WITH_DEBUG)
3664e98e3e1Schristos 	sim_io_eprintf (sd, "Debugging not compiled in, `-D' ignored\n");
3674e98e3e1Schristos       else
3684e98e3e1Schristos 	{
3694e98e3e1Schristos 	  for (n = 0; n < MAX_NR_PROCESSORS; ++n)
3704e98e3e1Schristos 	    for (i = 0; i < MAX_DEBUG_VALUES; ++i)
3714e98e3e1Schristos 	      CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[i] = 1;
3724e98e3e1Schristos 	}
3734e98e3e1Schristos       break;
3744e98e3e1Schristos 
3754e98e3e1Schristos     case OPTION_DEBUG_INSN :
3764e98e3e1Schristos       if (! WITH_DEBUG)
3774e98e3e1Schristos 	sim_io_eprintf (sd, "Debugging not compiled in, `--debug-insn' ignored\n");
3784e98e3e1Schristos       else
3794e98e3e1Schristos 	{
3804e98e3e1Schristos 	  for (n = 0; n < MAX_NR_PROCESSORS; ++n)
3814e98e3e1Schristos 	    CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[DEBUG_INSN_IDX] = 1;
3824e98e3e1Schristos 	}
3834e98e3e1Schristos       break;
3844e98e3e1Schristos 
3854e98e3e1Schristos     case OPTION_DEBUG_FILE :
3864e98e3e1Schristos       if (! WITH_DEBUG)
3874e98e3e1Schristos 	sim_io_eprintf (sd, "Debugging not compiled in, `--debug-file' ignored\n");
3884e98e3e1Schristos       else
3894e98e3e1Schristos 	{
3904e98e3e1Schristos 	  FILE *f = fopen (arg, "w");
3914e98e3e1Schristos 
3924e98e3e1Schristos 	  if (f == NULL)
3934e98e3e1Schristos 	    {
3944e98e3e1Schristos 	      sim_io_eprintf (sd, "Unable to open debug output file `%s'\n", arg);
3954e98e3e1Schristos 	      return SIM_RC_FAIL;
3964e98e3e1Schristos 	    }
3974e98e3e1Schristos 	  for (n = 0; n < MAX_NR_PROCESSORS; ++n)
3984e98e3e1Schristos 	    CPU_DEBUG_FILE (STATE_CPU (sd, n)) = f;
3994e98e3e1Schristos 	}
4004e98e3e1Schristos       break;
4014e98e3e1Schristos 
4024e98e3e1Schristos     case OPTION_DO_COMMAND:
4034e98e3e1Schristos       sim_do_command (sd, arg);
4044e98e3e1Schristos       break;
4054e98e3e1Schristos 
4064e98e3e1Schristos     case OPTION_ARCHITECTURE:
4074e98e3e1Schristos       {
4084e98e3e1Schristos 	const struct bfd_arch_info *ap = bfd_scan_arch (arg);
4094e98e3e1Schristos 	if (ap == NULL)
4104e98e3e1Schristos 	  {
4114e98e3e1Schristos 	    sim_io_eprintf (sd, "Architecture `%s' unknown\n", arg);
4124e98e3e1Schristos 	    return SIM_RC_FAIL;
4134e98e3e1Schristos 	  }
4144e98e3e1Schristos 	STATE_ARCHITECTURE (sd) = ap;
4154e98e3e1Schristos 	break;
4164e98e3e1Schristos       }
4174e98e3e1Schristos 
4184e98e3e1Schristos     case OPTION_ARCHITECTURE_INFO:
4194e98e3e1Schristos       {
4204e98e3e1Schristos 	const char **list = bfd_arch_list ();
4214e98e3e1Schristos 	const char **lp;
4224e98e3e1Schristos 	if (list == NULL)
4234e98e3e1Schristos 	  abort ();
4244e98e3e1Schristos 	sim_io_printf (sd, "Possible architectures:");
4254e98e3e1Schristos 	for (lp = list; *lp != NULL; lp++)
4264e98e3e1Schristos 	  sim_io_printf (sd, " %s", *lp);
4274e98e3e1Schristos 	sim_io_printf (sd, "\n");
4284e98e3e1Schristos 	free (list);
4294e98e3e1Schristos 	break;
4304e98e3e1Schristos       }
4314e98e3e1Schristos 
4324e98e3e1Schristos     case OPTION_TARGET:
4334e98e3e1Schristos       {
4344e98e3e1Schristos 	STATE_TARGET (sd) = xstrdup (arg);
4354e98e3e1Schristos 	break;
4364e98e3e1Schristos       }
4374e98e3e1Schristos 
4384b169a6bSchristos     case OPTION_TARGET_INFO:
4394b169a6bSchristos       {
4404b169a6bSchristos 	const char **list = bfd_target_list ();
4414b169a6bSchristos 	const char **lp;
4424b169a6bSchristos 	if (list == NULL)
4434b169a6bSchristos 	  abort ();
4444b169a6bSchristos 	sim_io_printf (sd, "Possible targets:");
4454b169a6bSchristos 	for (lp = list; *lp != NULL; lp++)
4464b169a6bSchristos 	  sim_io_printf (sd, " %s", *lp);
4474b169a6bSchristos 	sim_io_printf (sd, "\n");
4484b169a6bSchristos 	free (list);
4494b169a6bSchristos 	break;
4504b169a6bSchristos       }
4514b169a6bSchristos 
4524e98e3e1Schristos     case OPTION_LOAD_LMA:
4534e98e3e1Schristos       {
4544e98e3e1Schristos 	STATE_LOAD_AT_LMA_P (sd) = 1;
4554e98e3e1Schristos 	break;
4564e98e3e1Schristos       }
4574e98e3e1Schristos 
4584e98e3e1Schristos     case OPTION_LOAD_VMA:
4594e98e3e1Schristos       {
4604e98e3e1Schristos 	STATE_LOAD_AT_LMA_P (sd) = 0;
4614e98e3e1Schristos 	break;
4624e98e3e1Schristos       }
4634e98e3e1Schristos 
4644e98e3e1Schristos     case OPTION_HELP:
4654e98e3e1Schristos       sim_print_help (sd, is_command);
4664e98e3e1Schristos       if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
4674e98e3e1Schristos 	exit (0);
4684e98e3e1Schristos       /* FIXME: 'twould be nice to do something similar if gdb.  */
4694e98e3e1Schristos       break;
4704e98e3e1Schristos 
471212397c6Schristos     case OPTION_VERSION:
4724b169a6bSchristos       sim_print_version (sd, is_command);
473212397c6Schristos       if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
474212397c6Schristos 	exit (0);
475212397c6Schristos       break;
476212397c6Schristos 
4774e98e3e1Schristos     case OPTION_SYSROOT:
4784e98e3e1Schristos       /* Don't leak memory in the odd event that there's lots of
479a2e2270fSchristos 	 --sysroot=... options.  We treat "" specially since this
480a2e2270fSchristos 	 is the statically initialized value and cannot free it.  */
481a2e2270fSchristos       if (simulator_sysroot[0] != '\0')
4824e98e3e1Schristos 	free (simulator_sysroot);
483a2e2270fSchristos       if (arg[0] != '\0')
4844e98e3e1Schristos 	simulator_sysroot = xstrdup (arg);
485a2e2270fSchristos       else
486a2e2270fSchristos 	simulator_sysroot = "";
4874e98e3e1Schristos       break;
4884b169a6bSchristos 
4894b169a6bSchristos     case OPTION_ARGV0:
4904b169a6bSchristos       free (STATE_PROG_ARGV0 (sd));
4914b169a6bSchristos       STATE_PROG_ARGV0 (sd) = xstrdup (arg);
4924b169a6bSchristos       break;
4934b169a6bSchristos 
4944b169a6bSchristos     case OPTION_ENV_SET:
4954b169a6bSchristos       return env_set (sd, arg);
4964b169a6bSchristos 
4974b169a6bSchristos     case OPTION_ENV_UNSET:
4984b169a6bSchristos       {
499*0d3e0572Schristos 	int varlen;
5004b169a6bSchristos 	char **envp;
5014b169a6bSchristos 
5024b169a6bSchristos 	if (STATE_PROG_ENVP (sd) == NULL)
5034b169a6bSchristos 	  STATE_PROG_ENVP (sd) = dupargv (environ);
5044b169a6bSchristos 
5054b169a6bSchristos 	varlen = strlen (arg);
5064b169a6bSchristos 
5074b169a6bSchristos 	/* If we can find an existing variable, replace it.  */
5084b169a6bSchristos 	envp = STATE_PROG_ENVP (sd);
5094b169a6bSchristos 	for (i = 0; envp[i]; ++i)
5104b169a6bSchristos 	  {
5114b169a6bSchristos 	    char *env = envp[i];
5124b169a6bSchristos 
5134b169a6bSchristos 	    if (strncmp (env, arg, varlen) == 0
5144b169a6bSchristos 		&& (env[varlen] == '\0' || env[varlen] == '='))
5154b169a6bSchristos 	      {
5164b169a6bSchristos 		free (envp[i]);
5174b169a6bSchristos 		break;
5184b169a6bSchristos 	      }
5194b169a6bSchristos 	  }
5204b169a6bSchristos 
5214b169a6bSchristos 	/* If we clear the var, shift the array down.  */
5224b169a6bSchristos 	for (; envp[i]; ++i)
5234b169a6bSchristos 	  envp[i] = envp[i + 1];
5244b169a6bSchristos 
5254b169a6bSchristos 	break;
5264b169a6bSchristos       }
5274b169a6bSchristos 
5284b169a6bSchristos     case OPTION_ENV_CLEAR:
5294b169a6bSchristos       freeargv (STATE_PROG_ENVP (sd));
5304b169a6bSchristos       STATE_PROG_ENVP (sd) = xmalloc (sizeof (char *));
5314b169a6bSchristos       STATE_PROG_ENVP (sd)[0] = NULL;
5324b169a6bSchristos       break;
5334e98e3e1Schristos     }
5344e98e3e1Schristos 
5354e98e3e1Schristos   return SIM_RC_OK;
5364e98e3e1Schristos }
5374e98e3e1Schristos 
5384e98e3e1Schristos /* Add the standard option list to the simulator.  */
5394e98e3e1Schristos 
5404e98e3e1Schristos SIM_RC
5414e98e3e1Schristos standard_install (SIM_DESC sd)
5424e98e3e1Schristos {
5434e98e3e1Schristos   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
5444e98e3e1Schristos   if (sim_add_option_table (sd, NULL, standard_options) != SIM_RC_OK)
5454e98e3e1Schristos     return SIM_RC_FAIL;
546ba340e45Schristos   STATE_LOAD_AT_LMA_P (sd) = 1;
5474e98e3e1Schristos   return SIM_RC_OK;
5484e98e3e1Schristos }
5494e98e3e1Schristos 
5504e98e3e1Schristos /* Return non-zero if arg is a duplicate argument.
5514e98e3e1Schristos    If ARG is NULL, initialize.  */
5524e98e3e1Schristos 
5534e98e3e1Schristos static int
5544e98e3e1Schristos dup_arg_p (const char *arg)
5554e98e3e1Schristos {
5564b169a6bSchristos   static htab_t arg_table = NULL;
5574b169a6bSchristos   void **slot;
5584e98e3e1Schristos 
5594e98e3e1Schristos   if (arg == NULL)
5604e98e3e1Schristos     {
5614e98e3e1Schristos       if (arg_table == NULL)
5624b169a6bSchristos 	arg_table = htab_create_alloc (10, htab_hash_string,
5634b169a6bSchristos 				       htab_eq_string, NULL,
5644b169a6bSchristos 				       xcalloc, free);
5654b169a6bSchristos       htab_empty (arg_table);
5664e98e3e1Schristos       return 0;
5674e98e3e1Schristos     }
5684e98e3e1Schristos 
5694b169a6bSchristos   slot = htab_find_slot (arg_table, arg, INSERT);
5704b169a6bSchristos   if (*slot != NULL)
5714e98e3e1Schristos     return 1;
5724b169a6bSchristos   *slot = (void *) arg;
5734e98e3e1Schristos   return 0;
5744e98e3e1Schristos }
5754e98e3e1Schristos 
5764e98e3e1Schristos /* Called by sim_open to parse the arguments.  */
5774e98e3e1Schristos 
5784e98e3e1Schristos SIM_RC
579ba340e45Schristos sim_parse_args (SIM_DESC sd, char * const *argv)
5804e98e3e1Schristos {
581ba340e45Schristos   int c, i, argc, num_opts, save_opterr;
5824e98e3e1Schristos   char *p, *short_options;
5834e98e3e1Schristos   /* The `val' option struct entry is dynamically assigned for options that
5844e98e3e1Schristos      only come in the long form.  ORIG_VAL is used to get the original value
5854e98e3e1Schristos      back.  */
5864e98e3e1Schristos   int *orig_val;
5874e98e3e1Schristos   struct option *lp, *long_options;
5884e98e3e1Schristos   const struct option_list *ol;
5894e98e3e1Schristos   const OPTION *opt;
5904e98e3e1Schristos   OPTION_HANDLER **handlers;
5914e98e3e1Schristos   sim_cpu **opt_cpu;
5924e98e3e1Schristos   SIM_RC result = SIM_RC_OK;
5934e98e3e1Schristos 
5944e98e3e1Schristos   /* Count the number of arguments.  */
595ba340e45Schristos   argc = countargv (argv);
5964e98e3e1Schristos 
5974e98e3e1Schristos   /* Count the number of options.  */
5984e98e3e1Schristos   num_opts = 0;
5994e98e3e1Schristos   for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next)
6004e98e3e1Schristos     for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
6014e98e3e1Schristos       ++num_opts;
6024e98e3e1Schristos   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
6034e98e3e1Schristos     for (ol = CPU_OPTIONS (STATE_CPU (sd, i)); ol != NULL; ol = ol->next)
6044e98e3e1Schristos       for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
6054e98e3e1Schristos 	++num_opts;
6064e98e3e1Schristos 
6074e98e3e1Schristos   /* Initialize duplicate argument checker.  */
6084e98e3e1Schristos   (void) dup_arg_p (NULL);
6094e98e3e1Schristos 
6104e98e3e1Schristos   /* Build the option table for getopt.  */
6114e98e3e1Schristos 
6124e98e3e1Schristos   long_options = NZALLOC (struct option, num_opts + 1);
6134e98e3e1Schristos   lp = long_options;
6144e98e3e1Schristos   short_options = NZALLOC (char, num_opts * 3 + 1);
6154e98e3e1Schristos   p = short_options;
6164e98e3e1Schristos   handlers = NZALLOC (OPTION_HANDLER *, OPTION_START + num_opts);
6174e98e3e1Schristos   orig_val = NZALLOC (int, OPTION_START + num_opts);
6184e98e3e1Schristos   opt_cpu = NZALLOC (sim_cpu *, OPTION_START + num_opts);
6194e98e3e1Schristos 
6204e98e3e1Schristos   /* Set '+' as first char so argument permutation isn't done.  This
6214e98e3e1Schristos      is done to stop getopt_long returning options that appear after
6224e98e3e1Schristos      the target program.  Such options should be passed unchanged into
6234e98e3e1Schristos      the program image. */
6244e98e3e1Schristos   *p++ = '+';
6254e98e3e1Schristos 
6264e98e3e1Schristos   for (i = OPTION_START, ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next)
6274e98e3e1Schristos     for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
6284e98e3e1Schristos       {
6294e98e3e1Schristos 	if (dup_arg_p (opt->opt.name))
6304e98e3e1Schristos 	  continue;
6314e98e3e1Schristos 	if (opt->shortopt != 0)
6324e98e3e1Schristos 	  {
6334e98e3e1Schristos 	    *p++ = opt->shortopt;
6344e98e3e1Schristos 	    if (opt->opt.has_arg == required_argument)
6354e98e3e1Schristos 	      *p++ = ':';
6364e98e3e1Schristos 	    else if (opt->opt.has_arg == optional_argument)
6374e98e3e1Schristos 	      { *p++ = ':'; *p++ = ':'; }
6384e98e3e1Schristos 	    handlers[(unsigned char) opt->shortopt] = opt->handler;
6394e98e3e1Schristos 	    if (opt->opt.val != 0)
6404e98e3e1Schristos 	      orig_val[(unsigned char) opt->shortopt] = opt->opt.val;
6414e98e3e1Schristos 	    else
6424e98e3e1Schristos 	      orig_val[(unsigned char) opt->shortopt] = opt->shortopt;
6434e98e3e1Schristos 	  }
6444e98e3e1Schristos 	if (opt->opt.name != NULL)
6454e98e3e1Schristos 	  {
6464e98e3e1Schristos 	    *lp = opt->opt;
6474e98e3e1Schristos 	    /* Dynamically assign `val' numbers for long options. */
6484e98e3e1Schristos 	    lp->val = i++;
6494e98e3e1Schristos 	    handlers[lp->val] = opt->handler;
6504e98e3e1Schristos 	    orig_val[lp->val] = opt->opt.val;
6514e98e3e1Schristos 	    opt_cpu[lp->val] = NULL;
6524e98e3e1Schristos 	    ++lp;
6534e98e3e1Schristos 	  }
6544e98e3e1Schristos       }
6554e98e3e1Schristos 
6564e98e3e1Schristos   for (c = 0; c < MAX_NR_PROCESSORS; ++c)
6574e98e3e1Schristos     {
6584e98e3e1Schristos       sim_cpu *cpu = STATE_CPU (sd, c);
6594e98e3e1Schristos       for (ol = CPU_OPTIONS (cpu); ol != NULL; ol = ol->next)
6604e98e3e1Schristos 	for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
6614e98e3e1Schristos 	  {
6624e98e3e1Schristos #if 0 /* Each option is prepended with --<cpuname>- so this greatly cuts down
6634e98e3e1Schristos 	 on the need for dup_arg_p checking.  Maybe in the future it'll be
6644e98e3e1Schristos 	 needed so this is just commented out, and not deleted.  */
6654e98e3e1Schristos 	    if (dup_arg_p (opt->opt.name))
6664e98e3e1Schristos 	      continue;
6674e98e3e1Schristos #endif
6684e98e3e1Schristos 	    /* Don't allow short versions of cpu specific options for now.  */
6694e98e3e1Schristos 	    if (opt->shortopt != 0)
6704e98e3e1Schristos 	      {
6714e98e3e1Schristos 		sim_io_eprintf (sd, "internal error, short cpu specific option");
6724e98e3e1Schristos 		result = SIM_RC_FAIL;
6734e98e3e1Schristos 		break;
6744e98e3e1Schristos 	      }
6754e98e3e1Schristos 	    if (opt->opt.name != NULL)
6764e98e3e1Schristos 	      {
6774e98e3e1Schristos 		char *name;
6784e98e3e1Schristos 		*lp = opt->opt;
6794e98e3e1Schristos 		/* Prepend --<cpuname>- to the option.  */
6804e98e3e1Schristos 		if (asprintf (&name, "%s-%s", CPU_NAME (cpu), lp->name) < 0)
6814e98e3e1Schristos 		  {
6824e98e3e1Schristos 		    sim_io_eprintf (sd, "internal error, out of memory");
6834e98e3e1Schristos 		    result = SIM_RC_FAIL;
6844e98e3e1Schristos 		    break;
6854e98e3e1Schristos 		  }
6864e98e3e1Schristos 		lp->name = name;
6874e98e3e1Schristos 		/* Dynamically assign `val' numbers for long options. */
6884e98e3e1Schristos 		lp->val = i++;
6894e98e3e1Schristos 		handlers[lp->val] = opt->handler;
6904e98e3e1Schristos 		orig_val[lp->val] = opt->opt.val;
6914e98e3e1Schristos 		opt_cpu[lp->val] = cpu;
6924e98e3e1Schristos 		++lp;
6934e98e3e1Schristos 	      }
6944e98e3e1Schristos 	  }
6954e98e3e1Schristos     }
6964e98e3e1Schristos 
6974e98e3e1Schristos   /* Terminate the short and long option lists.  */
6984e98e3e1Schristos   *p = 0;
6994e98e3e1Schristos   lp->name = NULL;
7004e98e3e1Schristos 
7014e98e3e1Schristos   /* Ensure getopt is initialized.  */
7024e98e3e1Schristos   optind = 0;
7034e98e3e1Schristos 
704ba340e45Schristos   /* Do not lot getopt throw errors for us.  But don't mess with the state for
705ba340e45Schristos      any callers higher up by saving/restoring it.  */
706ba340e45Schristos   save_opterr = opterr;
707ba340e45Schristos   opterr = 0;
708ba340e45Schristos 
7094e98e3e1Schristos   while (1)
7104e98e3e1Schristos     {
7114e98e3e1Schristos       int longind, optc;
7124e98e3e1Schristos 
7134e98e3e1Schristos       optc = getopt_long (argc, argv, short_options, long_options, &longind);
7144e98e3e1Schristos       if (optc == -1)
7154e98e3e1Schristos 	{
7164e98e3e1Schristos 	  if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
7174b169a6bSchristos 	    {
7184b169a6bSchristos 	      char **new_argv;
7194b169a6bSchristos 
7204b169a6bSchristos 	      free (STATE_PROG_FILE (sd));
7214b169a6bSchristos 	      STATE_PROG_FILE (sd) = NULL;
7224b169a6bSchristos 
7234b169a6bSchristos 	      /* Handle any inline variables if -- wasn't used.  */
7244b169a6bSchristos 	      if (argv[optind] != NULL && optind > 0
7254b169a6bSchristos 		  && strcmp (argv[optind - 1], "--") != 0)
7264b169a6bSchristos 		{
7274b169a6bSchristos 		  while (1)
7284b169a6bSchristos 		    {
7294b169a6bSchristos 		      const char *arg = argv[optind];
7304b169a6bSchristos 
7314b169a6bSchristos 		      if (strchr (arg, '=') == NULL)
7324b169a6bSchristos 			break;
7334b169a6bSchristos 
7344b169a6bSchristos 		      env_set (sd, arg);
7354b169a6bSchristos 		      ++optind;
7364b169a6bSchristos 		    }
7374b169a6bSchristos 		}
7384b169a6bSchristos 
7394b169a6bSchristos 	      new_argv = dupargv (argv + optind);
7404b169a6bSchristos 	      freeargv (STATE_PROG_ARGV (sd));
7414b169a6bSchristos 	      STATE_PROG_ARGV (sd) = new_argv;
7424b169a6bSchristos 
7434b169a6bSchristos 	      /* Skip steps when argc == 0.  */
7444b169a6bSchristos 	      if (argv[optind] != NULL)
7454b169a6bSchristos 		{
7464b169a6bSchristos 		  STATE_PROG_FILE (sd) = xstrdup (argv[optind]);
7474b169a6bSchristos 
7484b169a6bSchristos 		  if (STATE_PROG_ARGV0 (sd) != NULL)
7494b169a6bSchristos 		    {
7504b169a6bSchristos 		      free (new_argv[0]);
7514b169a6bSchristos 		      new_argv[0] = xstrdup (STATE_PROG_ARGV0 (sd));
7524b169a6bSchristos 		    }
7534b169a6bSchristos 		}
7544b169a6bSchristos 	    }
7554e98e3e1Schristos 	  break;
7564e98e3e1Schristos 	}
7574e98e3e1Schristos       if (optc == '?')
7584e98e3e1Schristos 	{
759ba340e45Schristos 	  /* If getopt rejects a short option, optopt is set to the bad char.
760ba340e45Schristos 	     If it rejects a long option, we have to look at optind.  In the
761ba340e45Schristos 	     short option case, argv could be multiple short options.  */
762ba340e45Schristos 	  const char *badopt;
763ba340e45Schristos 	  char optbuf[3];
764ba340e45Schristos 
765ba340e45Schristos 	  if (optopt)
766ba340e45Schristos 	    {
767ba340e45Schristos 	      sprintf (optbuf, "-%c", optopt);
768ba340e45Schristos 	      badopt = optbuf;
769ba340e45Schristos 	    }
770ba340e45Schristos 	  else
771ba340e45Schristos 	    badopt = argv[optind - 1];
772ba340e45Schristos 
773ba340e45Schristos 	  sim_io_eprintf (sd,
774ba340e45Schristos 			  "%s: unrecognized option '%s'\n"
775ba340e45Schristos 			  "Use --help for a complete list of options.\n",
776ba340e45Schristos 			  STATE_MY_NAME (sd), badopt);
777ba340e45Schristos 
7784e98e3e1Schristos 	  result = SIM_RC_FAIL;
7794e98e3e1Schristos 	  break;
7804e98e3e1Schristos 	}
7814e98e3e1Schristos 
7824e98e3e1Schristos       if ((*handlers[optc]) (sd, opt_cpu[optc], orig_val[optc], optarg, 0/*!is_command*/) == SIM_RC_FAIL)
7834e98e3e1Schristos 	{
7844e98e3e1Schristos 	  result = SIM_RC_FAIL;
7854e98e3e1Schristos 	  break;
7864e98e3e1Schristos 	}
7874e98e3e1Schristos     }
7884e98e3e1Schristos 
789ba340e45Schristos   opterr = save_opterr;
790ba340e45Schristos 
7914e98e3e1Schristos   free (long_options);
7924e98e3e1Schristos   free (short_options);
7934e98e3e1Schristos   free (handlers);
7944e98e3e1Schristos   free (opt_cpu);
7954e98e3e1Schristos   free (orig_val);
7964e98e3e1Schristos   return result;
7974e98e3e1Schristos }
7984e98e3e1Schristos 
7994e98e3e1Schristos /* Utility of sim_print_help to print a list of option tables.  */
8004e98e3e1Schristos 
8014e98e3e1Schristos static void
8024e98e3e1Schristos print_help (SIM_DESC sd, sim_cpu *cpu, const struct option_list *ol, int is_command)
8034e98e3e1Schristos {
8044e98e3e1Schristos   const OPTION *opt;
8054e98e3e1Schristos 
8064e98e3e1Schristos   for ( ; ol != NULL; ol = ol->next)
8074e98e3e1Schristos     for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
8084e98e3e1Schristos       {
8094e98e3e1Schristos 	const int indent = 30;
8104e98e3e1Schristos 	int comma, len;
8114e98e3e1Schristos 	const OPTION *o;
8124e98e3e1Schristos 
8134e98e3e1Schristos 	if (dup_arg_p (opt->opt.name))
8144e98e3e1Schristos 	  continue;
8154e98e3e1Schristos 
8164e98e3e1Schristos 	if (opt->doc == NULL)
8174e98e3e1Schristos 	  continue;
8184e98e3e1Schristos 
8194e98e3e1Schristos 	if (opt->doc_name != NULL && opt->doc_name [0] == '\0')
8204e98e3e1Schristos 	  continue;
8214e98e3e1Schristos 
8224e98e3e1Schristos 	sim_io_printf (sd, "  ");
8234e98e3e1Schristos 
8244e98e3e1Schristos 	comma = 0;
8254e98e3e1Schristos 	len = 2;
8264e98e3e1Schristos 
8274e98e3e1Schristos 	/* list any short options (aliases) for the current OPT */
8284e98e3e1Schristos 	if (!is_command)
8294e98e3e1Schristos 	  {
8304e98e3e1Schristos 	    o = opt;
8314e98e3e1Schristos 	    do
8324e98e3e1Schristos 	      {
8334e98e3e1Schristos 		if (o->shortopt != '\0')
8344e98e3e1Schristos 		  {
8354e98e3e1Schristos 		    sim_io_printf (sd, "%s-%c", comma ? ", " : "", o->shortopt);
8364e98e3e1Schristos 		    len += (comma ? 2 : 0) + 2;
8374e98e3e1Schristos 		    if (o->arg != NULL)
8384e98e3e1Schristos 		      {
8394e98e3e1Schristos 			if (o->opt.has_arg == optional_argument)
8404e98e3e1Schristos 			  {
8414e98e3e1Schristos 			    sim_io_printf (sd, "[%s]", o->arg);
8424e98e3e1Schristos 			    len += 1 + strlen (o->arg) + 1;
8434e98e3e1Schristos 			  }
8444e98e3e1Schristos 			else
8454e98e3e1Schristos 			  {
8464e98e3e1Schristos 			    sim_io_printf (sd, " %s", o->arg);
8474e98e3e1Schristos 			    len += 1 + strlen (o->arg);
8484e98e3e1Schristos 			  }
8494e98e3e1Schristos 		      }
8504e98e3e1Schristos 		    comma = 1;
8514e98e3e1Schristos 		  }
8524e98e3e1Schristos 		++o;
8534e98e3e1Schristos 	      }
8544e98e3e1Schristos 	    while (OPTION_VALID_P (o) && o->doc == NULL);
8554e98e3e1Schristos 	  }
8564e98e3e1Schristos 
8574e98e3e1Schristos 	/* list any long options (aliases) for the current OPT */
8584e98e3e1Schristos 	o = opt;
8594e98e3e1Schristos 	do
8604e98e3e1Schristos 	  {
8614e98e3e1Schristos 	    const char *name;
8624e98e3e1Schristos 	    const char *cpu_prefix = cpu ? CPU_NAME (cpu) : NULL;
8634e98e3e1Schristos 	    if (o->doc_name != NULL)
8644e98e3e1Schristos 	      name = o->doc_name;
8654e98e3e1Schristos 	    else
8664e98e3e1Schristos 	      name = o->opt.name;
8674e98e3e1Schristos 	    if (name != NULL)
8684e98e3e1Schristos 	      {
8694e98e3e1Schristos 		sim_io_printf (sd, "%s%s%s%s%s",
8704e98e3e1Schristos 			       comma ? ", " : "",
8714e98e3e1Schristos 			       is_command ? "" : "--",
8724e98e3e1Schristos 			       cpu ? cpu_prefix : "",
8734e98e3e1Schristos 			       cpu ? "-" : "",
8744e98e3e1Schristos 			       name);
8754e98e3e1Schristos 		len += ((comma ? 2 : 0)
8764e98e3e1Schristos 			+ (is_command ? 0 : 2)
8774e98e3e1Schristos 			+ strlen (name));
8784e98e3e1Schristos 		if (o->arg != NULL)
8794e98e3e1Schristos 		  {
8804e98e3e1Schristos 		    if (o->opt.has_arg == optional_argument)
8814e98e3e1Schristos 		      {
8824e98e3e1Schristos 			sim_io_printf (sd, "[=%s]", o->arg);
8834e98e3e1Schristos 			len += 2 + strlen (o->arg) + 1;
8844e98e3e1Schristos 		      }
8854e98e3e1Schristos 		    else
8864e98e3e1Schristos 		      {
8874e98e3e1Schristos 			sim_io_printf (sd, " %s", o->arg);
8884e98e3e1Schristos 			len += 1 + strlen (o->arg);
8894e98e3e1Schristos 		      }
8904e98e3e1Schristos 		  }
8914e98e3e1Schristos 		comma = 1;
8924e98e3e1Schristos 	      }
8934e98e3e1Schristos 	    ++o;
8944e98e3e1Schristos 	  }
8954e98e3e1Schristos 	while (OPTION_VALID_P (o) && o->doc == NULL);
8964e98e3e1Schristos 
8974e98e3e1Schristos 	if (len >= indent)
8984e98e3e1Schristos 	  {
8994e98e3e1Schristos 	    sim_io_printf (sd, "\n%*s", indent, "");
9004e98e3e1Schristos 	  }
9014e98e3e1Schristos 	else
9024e98e3e1Schristos 	  sim_io_printf (sd, "%*s", indent - len, "");
9034e98e3e1Schristos 
9044e98e3e1Schristos 	/* print the description, word wrap long lines */
9054e98e3e1Schristos 	{
9064e98e3e1Schristos 	  const char *chp = opt->doc;
9074e98e3e1Schristos 	  unsigned doc_width = 80 - indent;
9084e98e3e1Schristos 	  while (strlen (chp) >= doc_width) /* some slack */
9094e98e3e1Schristos 	    {
9104e98e3e1Schristos 	      const char *end = chp + doc_width - 1;
9114e98e3e1Schristos 	      while (end > chp && !isspace (*end))
9124e98e3e1Schristos 		end --;
9134e98e3e1Schristos 	      if (end == chp)
9144e98e3e1Schristos 		end = chp + doc_width - 1;
9154e98e3e1Schristos 	      /* The cast should be ok - its distances between to
9164e98e3e1Schristos                  points in a string.  */
9174e98e3e1Schristos 	      sim_io_printf (sd, "%.*s\n%*s", (int) (end - chp), chp, indent,
9184e98e3e1Schristos 			     "");
9194e98e3e1Schristos 	      chp = end;
9204e98e3e1Schristos 	      while (isspace (*chp) && *chp != '\0')
9214e98e3e1Schristos 		chp++;
9224e98e3e1Schristos 	    }
9234e98e3e1Schristos 	  sim_io_printf (sd, "%s\n", chp);
9244e98e3e1Schristos 	}
9254e98e3e1Schristos       }
9264e98e3e1Schristos }
9274e98e3e1Schristos 
9284e98e3e1Schristos /* Print help messages for the options.  */
9294e98e3e1Schristos 
9304e98e3e1Schristos void
9314e98e3e1Schristos sim_print_help (SIM_DESC sd, int is_command)
9324e98e3e1Schristos {
9334e98e3e1Schristos   if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
9344b169a6bSchristos     sim_io_printf (sd,
9354b169a6bSchristos 		   "Usage: %s [options] [VAR=VAL|--] program [program args]\n",
9364e98e3e1Schristos 		   STATE_MY_NAME (sd));
9374e98e3e1Schristos 
9384e98e3e1Schristos   /* Initialize duplicate argument checker.  */
9394e98e3e1Schristos   (void) dup_arg_p (NULL);
9404e98e3e1Schristos 
9414e98e3e1Schristos   if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
9424e98e3e1Schristos     sim_io_printf (sd, "Options:\n");
9434e98e3e1Schristos   else
9444e98e3e1Schristos     sim_io_printf (sd, "Commands:\n");
9454e98e3e1Schristos 
9464e98e3e1Schristos   print_help (sd, NULL, STATE_OPTIONS (sd), is_command);
9474e98e3e1Schristos   sim_io_printf (sd, "\n");
9484e98e3e1Schristos 
9494e98e3e1Schristos   /* Print cpu-specific options.  */
9504e98e3e1Schristos   {
9514e98e3e1Schristos     int i;
9524e98e3e1Schristos 
9534e98e3e1Schristos     for (i = 0; i < MAX_NR_PROCESSORS; ++i)
9544e98e3e1Schristos       {
9554e98e3e1Schristos 	sim_cpu *cpu = STATE_CPU (sd, i);
9564e98e3e1Schristos 	if (CPU_OPTIONS (cpu) == NULL)
9574e98e3e1Schristos 	  continue;
9584e98e3e1Schristos 	sim_io_printf (sd, "CPU %s specific options:\n", CPU_NAME (cpu));
9594e98e3e1Schristos 	print_help (sd, cpu, CPU_OPTIONS (cpu), is_command);
9604e98e3e1Schristos 	sim_io_printf (sd, "\n");
9614e98e3e1Schristos       }
9624e98e3e1Schristos   }
9634e98e3e1Schristos 
9644e98e3e1Schristos   sim_io_printf (sd, "Note: Depending on the simulator configuration some %ss\n",
9654e98e3e1Schristos 		 STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE ? "option" : "command");
9664e98e3e1Schristos   sim_io_printf (sd, "      may not be applicable\n");
9674e98e3e1Schristos 
9684e98e3e1Schristos   if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
9694e98e3e1Schristos     {
9704e98e3e1Schristos       sim_io_printf (sd, "\n");
9714b169a6bSchristos       sim_io_printf (sd,
9724b169a6bSchristos 		     "VAR=VAL         Environment variables to set.  "
9734b169a6bSchristos 		     "Ignored if -- is used.\n");
9744e98e3e1Schristos       sim_io_printf (sd, "program args    Arguments to pass to simulated program.\n");
9754e98e3e1Schristos       sim_io_printf (sd, "                Note: Very few simulators support this.\n");
9764e98e3e1Schristos     }
9774e98e3e1Schristos }
9784e98e3e1Schristos 
9794b169a6bSchristos /* Print version information.  */
9804b169a6bSchristos 
9814b169a6bSchristos void
9824b169a6bSchristos sim_print_version (SIM_DESC sd, int is_command)
9834b169a6bSchristos {
9844b169a6bSchristos   sim_io_printf (sd, "GNU simulator %s%s\n", PKGVERSION, version);
9854b169a6bSchristos 
986*0d3e0572Schristos   sim_io_printf (sd, "Copyright (C) 2024 Free Software Foundation, Inc.\n");
9874b169a6bSchristos 
9884b169a6bSchristos   /* Following the copyright is a brief statement that the program is
9894b169a6bSchristos      free software, that users are free to copy and change it on
9904b169a6bSchristos      certain conditions, that it is covered by the GNU GPL, and that
9914b169a6bSchristos      there is no warranty.  */
9924b169a6bSchristos 
9934b169a6bSchristos   sim_io_printf (sd, "\
9944b169a6bSchristos License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>\
9954b169a6bSchristos \nThis is free software: you are free to change and redistribute it.\n\
9964b169a6bSchristos There is NO WARRANTY, to the extent permitted by law.\n");
9974b169a6bSchristos 
9984b169a6bSchristos   if (!is_command)
9994b169a6bSchristos     return;
10004b169a6bSchristos 
10014b169a6bSchristos   sim_io_printf (sd, "This SIM was configured as:\n");
10024b169a6bSchristos   sim_config_print (sd);
10034b169a6bSchristos 
10044b169a6bSchristos   if (REPORT_BUGS_TO[0])
10054b169a6bSchristos     {
10064b169a6bSchristos       sim_io_printf (sd, "For bug reporting instructions, please see:\n\
10074b169a6bSchristos     %s.\n",
10084b169a6bSchristos 		     REPORT_BUGS_TO);
10094b169a6bSchristos     }
10104b169a6bSchristos   sim_io_printf (sd, "Find the SIM homepage & other documentation resources \
10114b169a6bSchristos online at:\n    <https://sourceware.org/gdb/wiki/Sim/>.\n");
10124b169a6bSchristos }
10134b169a6bSchristos 
10144e98e3e1Schristos /* Utility of sim_args_command to find the closest match for a command.
10154e98e3e1Schristos    Commands that have "-" in them can be specified as separate words.
10164e98e3e1Schristos    e.g. sim memory-region 0x800000,0x4000
10174e98e3e1Schristos    or   sim memory region 0x800000,0x4000
10184e98e3e1Schristos    If CPU is non-null, use its option table list, otherwise use the main one.
10194e98e3e1Schristos    *PARGI is where to start looking in ARGV.  It is updated to point past
10204e98e3e1Schristos    the found option.  */
10214e98e3e1Schristos 
10224e98e3e1Schristos static const OPTION *
10234e98e3e1Schristos find_match (SIM_DESC sd, sim_cpu *cpu, char *argv[], int *pargi)
10244e98e3e1Schristos {
10254e98e3e1Schristos   const struct option_list *ol;
10264e98e3e1Schristos   const OPTION *opt;
10274e98e3e1Schristos   /* most recent option match */
10284e98e3e1Schristos   const OPTION *matching_opt = NULL;
10294e98e3e1Schristos   int matching_argi = -1;
10304e98e3e1Schristos 
10314e98e3e1Schristos   if (cpu)
10324e98e3e1Schristos     ol = CPU_OPTIONS (cpu);
10334e98e3e1Schristos   else
10344e98e3e1Schristos     ol = STATE_OPTIONS (sd);
10354e98e3e1Schristos 
10364e98e3e1Schristos   /* Skip passed elements specified by *PARGI.  */
10374e98e3e1Schristos   argv += *pargi;
10384e98e3e1Schristos 
10394e98e3e1Schristos   for ( ; ol != NULL; ol = ol->next)
10404e98e3e1Schristos     for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
10414e98e3e1Schristos       {
10424e98e3e1Schristos 	int argi = 0;
10434e98e3e1Schristos 	const char *name = opt->opt.name;
10444e98e3e1Schristos 	if (name == NULL)
10454e98e3e1Schristos 	  continue;
10464e98e3e1Schristos 	while (argv [argi] != NULL
10474e98e3e1Schristos 	       && strncmp (name, argv [argi], strlen (argv [argi])) == 0)
10484e98e3e1Schristos 	  {
10494e98e3e1Schristos 	    name = &name [strlen (argv[argi])];
10504e98e3e1Schristos 	    if (name [0] == '-')
10514e98e3e1Schristos 	      {
10524e98e3e1Schristos 		/* leading match ...<a-b-c>-d-e-f - continue search */
10534e98e3e1Schristos 		name ++; /* skip `-' */
10544e98e3e1Schristos 		argi ++;
10554e98e3e1Schristos 		continue;
10564e98e3e1Schristos 	      }
10574e98e3e1Schristos 	    else if (name [0] == '\0')
10584e98e3e1Schristos 	      {
10594e98e3e1Schristos 		/* exact match ...<a-b-c-d-e-f> - better than before? */
10604e98e3e1Schristos 		if (argi > matching_argi)
10614e98e3e1Schristos 		  {
10624e98e3e1Schristos 		    matching_argi = argi;
10634e98e3e1Schristos 		    matching_opt = opt;
10644e98e3e1Schristos 		  }
10654e98e3e1Schristos 		break;
10664e98e3e1Schristos 	      }
10674e98e3e1Schristos 	    else
10684e98e3e1Schristos 	      break;
10694e98e3e1Schristos 	  }
10704e98e3e1Schristos       }
10714e98e3e1Schristos 
10724e98e3e1Schristos   *pargi = matching_argi;
10734e98e3e1Schristos   return matching_opt;
10744e98e3e1Schristos }
10754e98e3e1Schristos 
1076a2e2270fSchristos static char **
1077a2e2270fSchristos complete_option_list (char **ret, size_t *cnt, const struct option_list *ol,
107803467a24Schristos 		      const char *text, const char *word)
1079a2e2270fSchristos {
1080a2e2270fSchristos   const OPTION *opt = NULL;
1081a2e2270fSchristos   size_t len = strlen (word);
1082a2e2270fSchristos 
1083a2e2270fSchristos   for ( ; ol != NULL; ol = ol->next)
1084a2e2270fSchristos     for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
1085a2e2270fSchristos       {
1086a2e2270fSchristos 	const char *name = opt->opt.name;
1087a2e2270fSchristos 
1088a2e2270fSchristos 	/* A long option to match against?  */
1089a2e2270fSchristos 	if (!name)
1090a2e2270fSchristos 	  continue;
1091a2e2270fSchristos 
1092a2e2270fSchristos 	/* Does this option actually match?  */
1093a2e2270fSchristos 	if (strncmp (name, word, len))
1094a2e2270fSchristos 	  continue;
1095a2e2270fSchristos 
1096a2e2270fSchristos 	ret = xrealloc (ret, ++*cnt * sizeof (ret[0]));
1097a2e2270fSchristos 	ret[*cnt - 2] = xstrdup (name);
1098a2e2270fSchristos       }
1099a2e2270fSchristos 
1100a2e2270fSchristos   return ret;
1101a2e2270fSchristos }
1102a2e2270fSchristos 
1103a2e2270fSchristos /* All leading text is stored in @text, while the current word being
1104a2e2270fSchristos    completed is stored in @word.  Trailing text of @word is not.  */
1105a2e2270fSchristos 
1106a2e2270fSchristos char **
110703467a24Schristos sim_complete_command (SIM_DESC sd, const char *text, const char *word)
1108a2e2270fSchristos {
1109a2e2270fSchristos   char **ret = NULL;
1110a2e2270fSchristos   size_t cnt = 1;
1111a2e2270fSchristos   sim_cpu *cpu;
1112a2e2270fSchristos 
1113a2e2270fSchristos   /* Only complete first word for now.  */
1114a2e2270fSchristos   if (text != word)
1115a2e2270fSchristos     return ret;
1116a2e2270fSchristos 
1117a2e2270fSchristos   cpu = STATE_CPU (sd, 0);
1118a2e2270fSchristos   if (cpu)
1119a2e2270fSchristos     ret = complete_option_list (ret, &cnt, CPU_OPTIONS (cpu), text, word);
1120a2e2270fSchristos   ret = complete_option_list (ret, &cnt, STATE_OPTIONS (sd), text, word);
1121a2e2270fSchristos 
1122a2e2270fSchristos   if (ret)
1123a2e2270fSchristos     ret[cnt - 1] = NULL;
1124a2e2270fSchristos   return ret;
1125a2e2270fSchristos }
1126a2e2270fSchristos 
11274e98e3e1Schristos SIM_RC
1128837edd6bSchristos sim_args_command (SIM_DESC sd, const char *cmd)
11294e98e3e1Schristos {
11304e98e3e1Schristos   /* something to do? */
11314e98e3e1Schristos   if (cmd == NULL)
11324e98e3e1Schristos     return SIM_RC_OK; /* FIXME - perhaps help would be better */
11334e98e3e1Schristos 
11344e98e3e1Schristos   if (cmd [0] == '-')
11354e98e3e1Schristos     {
11364e98e3e1Schristos       /* user specified -<opt> ... form? */
11374e98e3e1Schristos       char **argv = buildargv (cmd);
11384e98e3e1Schristos       SIM_RC rc = sim_parse_args (sd, argv);
11394e98e3e1Schristos       freeargv (argv);
11404e98e3e1Schristos       return rc;
11414e98e3e1Schristos     }
11424e98e3e1Schristos   else
11434e98e3e1Schristos     {
11444e98e3e1Schristos       char **argv = buildargv (cmd);
11454e98e3e1Schristos       const OPTION *matching_opt = NULL;
11464e98e3e1Schristos       int matching_argi;
11474e98e3e1Schristos       sim_cpu *cpu;
11484e98e3e1Schristos 
11494e98e3e1Schristos       if (argv [0] == NULL)
1150212397c6Schristos 	{
1151212397c6Schristos 	  freeargv (argv);
11524e98e3e1Schristos 	  return SIM_RC_OK; /* FIXME - perhaps help would be better */
1153212397c6Schristos 	}
11544e98e3e1Schristos 
11554e98e3e1Schristos       /* First check for a cpu selector.  */
11564e98e3e1Schristos       {
11574e98e3e1Schristos 	char *cpu_name = xstrdup (argv[0]);
11584e98e3e1Schristos 	char *hyphen = strchr (cpu_name, '-');
11594e98e3e1Schristos 	if (hyphen)
11604e98e3e1Schristos 	  *hyphen = 0;
11614e98e3e1Schristos 	cpu = sim_cpu_lookup (sd, cpu_name);
11624e98e3e1Schristos 	if (cpu)
11634e98e3e1Schristos 	  {
11644e98e3e1Schristos 	    /* If <cpuname>-<command>, point argv[0] at <command>.  */
11654e98e3e1Schristos 	    if (hyphen)
11664e98e3e1Schristos 	      {
11674e98e3e1Schristos 		matching_argi = 0;
11684e98e3e1Schristos 		argv[0] += hyphen - cpu_name + 1;
11694e98e3e1Schristos 	      }
11704e98e3e1Schristos 	    else
11714e98e3e1Schristos 	      matching_argi = 1;
11724e98e3e1Schristos 	    matching_opt = find_match (sd, cpu, argv, &matching_argi);
11734e98e3e1Schristos 	    /* If hyphen found restore argv[0].  */
11744e98e3e1Schristos 	    if (hyphen)
11754e98e3e1Schristos 	      argv[0] -= hyphen - cpu_name + 1;
11764e98e3e1Schristos 	  }
11774e98e3e1Schristos 	free (cpu_name);
11784e98e3e1Schristos       }
11794e98e3e1Schristos 
11804e98e3e1Schristos       /* If that failed, try the main table.  */
11814e98e3e1Schristos       if (matching_opt == NULL)
11824e98e3e1Schristos 	{
11834e98e3e1Schristos 	  matching_argi = 0;
11844e98e3e1Schristos 	  matching_opt = find_match (sd, NULL, argv, &matching_argi);
11854e98e3e1Schristos 	}
11864e98e3e1Schristos 
11874e98e3e1Schristos       if (matching_opt != NULL)
11884e98e3e1Schristos 	{
11894e98e3e1Schristos 	  switch (matching_opt->opt.has_arg)
11904e98e3e1Schristos 	    {
11914e98e3e1Schristos 	    case no_argument:
11924e98e3e1Schristos 	      if (argv [matching_argi + 1] == NULL)
11934e98e3e1Schristos 		matching_opt->handler (sd, cpu, matching_opt->opt.val,
11944e98e3e1Schristos 				       NULL, 1/*is_command*/);
11954e98e3e1Schristos 	      else
11964e98e3e1Schristos 		sim_io_eprintf (sd, "Command `%s' takes no arguments\n",
11974e98e3e1Schristos 				matching_opt->opt.name);
11984e98e3e1Schristos 	      break;
11994e98e3e1Schristos 	    case optional_argument:
12004e98e3e1Schristos 	      if (argv [matching_argi + 1] == NULL)
12014e98e3e1Schristos 		matching_opt->handler (sd, cpu, matching_opt->opt.val,
12024e98e3e1Schristos 				       NULL, 1/*is_command*/);
12034e98e3e1Schristos 	      else if (argv [matching_argi + 2] == NULL)
12044e98e3e1Schristos 		matching_opt->handler (sd, cpu, matching_opt->opt.val,
12054e98e3e1Schristos 				       argv [matching_argi + 1], 1/*is_command*/);
12064e98e3e1Schristos 	      else
12074e98e3e1Schristos 		sim_io_eprintf (sd, "Command `%s' requires no more than one argument\n",
12084e98e3e1Schristos 				matching_opt->opt.name);
12094e98e3e1Schristos 	      break;
12104e98e3e1Schristos 	    case required_argument:
12114e98e3e1Schristos 	      if (argv [matching_argi + 1] == NULL)
12124e98e3e1Schristos 		sim_io_eprintf (sd, "Command `%s' requires an argument\n",
12134e98e3e1Schristos 				matching_opt->opt.name);
12144e98e3e1Schristos 	      else if (argv [matching_argi + 2] == NULL)
12154e98e3e1Schristos 		matching_opt->handler (sd, cpu, matching_opt->opt.val,
12164e98e3e1Schristos 				       argv [matching_argi + 1], 1/*is_command*/);
12174e98e3e1Schristos 	      else
12184e98e3e1Schristos 		sim_io_eprintf (sd, "Command `%s' requires only one argument\n",
12194e98e3e1Schristos 				matching_opt->opt.name);
12204e98e3e1Schristos 	    }
12214e98e3e1Schristos 	  freeargv (argv);
12224e98e3e1Schristos 	  return SIM_RC_OK;
12234e98e3e1Schristos 	}
12244e98e3e1Schristos 
12254e98e3e1Schristos       freeargv (argv);
12264e98e3e1Schristos     }
12274e98e3e1Schristos 
12284e98e3e1Schristos   /* didn't find anything that remotly matched */
12294e98e3e1Schristos   return SIM_RC_FAIL;
12304e98e3e1Schristos }
1231