/* Simulator option handling.
- Copyright (C) 1996, 1997, 2004, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1996-2021 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GDB, the GNU debugger.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
+/* This must come before any other includes. */
+#include "defs.h"
+
#include "sim-main.h"
-#ifdef HAVE_STRING_H
#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
#include <ctype.h>
+#include <stdio.h>
#include "libiberty.h"
#include "sim-options.h"
#include "sim-io.h"
#include "sim-assert.h"
+#include "version.h"
+#include "hashtab.h"
#include "bfd.h"
OPTION_VERBOSE,
OPTION_ENDIAN,
OPTION_DEBUG,
-#ifdef SIM_HAVE_FLATMEM
- OPTION_MEM_SIZE,
-#endif
OPTION_HELP,
-#ifdef SIM_H8300 /* FIXME: Should be movable to h8300 dir. */
- OPTION_H8300H,
- OPTION_H8300S,
- OPTION_H8300SX,
-#endif
+ OPTION_VERSION,
OPTION_LOAD_LMA,
OPTION_LOAD_VMA,
OPTION_SYSROOT
'E', "big|little", "Set endianness",
standard_option_handler, NULL },
-#ifdef SIM_HAVE_ENVIRONMENT
/* This option isn't supported unless all choices are supported in keeping
with the goal of not printing in --help output things the simulator can't
do [as opposed to things that just haven't been configured in]. */
{ {"environment", required_argument, NULL, OPTION_ENVIRONMENT},
'\0', "user|virtual|operating", "Set running environment",
standard_option_handler },
-#endif
{ {"alignment", required_argument, NULL, OPTION_ALIGNMENT},
'\0', "strict|nonstrict|forced", "Set memory access alignment",
'\0', "FILE NAME", "Specify debugging output file",
standard_option_handler },
-#ifdef SIM_H8300 /* FIXME: Should be movable to h8300 dir. */
- { {"h8300h", no_argument, NULL, OPTION_H8300H},
- 'h', NULL, "Indicate the CPU is H8/300H",
- standard_option_handler },
- { {"h8300s", no_argument, NULL, OPTION_H8300S},
- 'S', NULL, "Indicate the CPU is H8S",
- standard_option_handler },
- { {"h8300sx", no_argument, NULL, OPTION_H8300SX},
- 'x', NULL, "Indicate the CPU is H8SX",
- standard_option_handler },
-#endif
-
-#ifdef SIM_HAVE_FLATMEM
- { {"mem-size", required_argument, NULL, OPTION_MEM_SIZE},
- 'm', "<size>[in bytes, Kb (k suffix), Mb (m suffix) or Gb (g suffix)]",
- "Specify memory size", standard_option_handler },
-#endif
-
{ {"do-command", required_argument, NULL, OPTION_DO_COMMAND},
'\0', "COMMAND", ""/*undocumented*/,
standard_option_handler },
{ {"help", no_argument, NULL, OPTION_HELP},
'H', NULL, "Print help information",
standard_option_handler },
+ { {"version", no_argument, NULL, OPTION_VERSION},
+ '\0', NULL, "Print version information",
+ standard_option_handler },
{ {"architecture", required_argument, NULL, OPTION_ARCHITECTURE},
'\0', "MACHINE", "Specify the architecture to use",
'\0', "BFDNAME", "Specify the object-code format for the object files",
standard_option_handler },
-#ifdef SIM_HANDLES_LMA
{ {"load-lma", no_argument, NULL, OPTION_LOAD_LMA},
'\0', NULL,
-#if SIM_HANDLES_LMA
"Use VMA or LMA addresses when loading image (default LMA)",
-#else
- "Use VMA or LMA addresses when loading image (default VMA)",
-#endif
standard_option_handler, "load-{lma,vma}" },
{ {"load-vma", no_argument, NULL, OPTION_LOAD_VMA},
'\0', NULL, "", standard_option_handler, "" },
-#endif
{ {"sysroot", required_argument, NULL, OPTION_SYSROOT},
'\0', "SYSROOT",
case OPTION_ENDIAN:
if (strcmp (arg, "big") == 0)
{
- if (WITH_TARGET_BYTE_ORDER == LITTLE_ENDIAN)
+ if (WITH_TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
{
sim_io_eprintf (sd, "Simulator compiled for little endian only.\n");
return SIM_RC_FAIL;
}
/* FIXME:wip: Need to set something in STATE_CONFIG. */
- current_target_byte_order = BIG_ENDIAN;
+ current_target_byte_order = BFD_ENDIAN_BIG;
}
else if (strcmp (arg, "little") == 0)
{
- if (WITH_TARGET_BYTE_ORDER == BIG_ENDIAN)
+ if (WITH_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
{
sim_io_eprintf (sd, "Simulator compiled for big endian only.\n");
return SIM_RC_FAIL;
}
/* FIXME:wip: Need to set something in STATE_CONFIG. */
- current_target_byte_order = LITTLE_ENDIAN;
+ current_target_byte_order = BFD_ENDIAN_LITTLE;
}
else
{
case USER_ENVIRONMENT: type = "user"; break;
case VIRTUAL_ENVIRONMENT: type = "virtual"; break;
case OPERATING_ENVIRONMENT: type = "operating"; break;
+ default: abort ();
}
sim_io_eprintf (sd, "Simulator compiled for the %s environment only.\n",
type);
case FORCED_ALIGNMENT:
sim_io_eprintf (sd, "Simulator compiled for forced alignment only.\n");
break;
+ default: abort ();
}
return SIM_RC_FAIL;
}
break;
-#ifdef SIM_H8300 /* FIXME: Can be moved to h8300 dir. */
- case OPTION_H8300H:
- set_h8300h (bfd_mach_h8300h);
- break;
- case OPTION_H8300S:
- set_h8300h (bfd_mach_h8300s);
- break;
- case OPTION_H8300SX:
- set_h8300h (bfd_mach_h8300sx);
- break;
-#endif
-
-#ifdef SIM_HAVE_FLATMEM
- case OPTION_MEM_SIZE:
- {
- char * endp;
- unsigned long ul = strtol (arg, &endp, 0);
-
- switch (* endp)
- {
- case 'k': case 'K': size <<= 10; break;
- case 'm': case 'M': size <<= 20; break;
- case 'g': case 'G': size <<= 30; break;
- case ' ': case '\0': case '\t': break;
- default:
- if (ul > 0)
- sim_io_eprintf (sd, "Ignoring strange character at end of memory size: %c\n", * endp);
- break;
- }
-
- /* 16384: some minimal amount */
- if (! isdigit (arg[0]) || ul < 16384)
- {
- sim_io_eprintf (sd, "Invalid memory size `%s'", arg);
- return SIM_RC_FAIL;
- }
- STATE_MEM_SIZE (sd) = ul;
- }
- break;
-#endif
-
case OPTION_DO_COMMAND:
sim_do_command (sd, arg);
break;
case OPTION_ARCHITECTURE_INFO:
{
- const char **list = bfd_arch_list();
+ const char **list = bfd_arch_list ();
const char **lp;
if (list == NULL)
abort ();
/* FIXME: 'twould be nice to do something similar if gdb. */
break;
+ case OPTION_VERSION:
+ sim_print_version (sd, is_command);
+ if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
+ exit (0);
+ break;
+
case OPTION_SYSROOT:
/* Don't leak memory in the odd event that there's lots of
- --sysroot=... options. */
- if (simulator_sysroot[0] != '\0' && arg[0] != '\0')
+ --sysroot=... options. We treat "" specially since this
+ is the statically initialized value and cannot free it. */
+ if (simulator_sysroot[0] != '\0')
free (simulator_sysroot);
- simulator_sysroot = xstrdup (arg);
+ if (arg[0] != '\0')
+ simulator_sysroot = xstrdup (arg);
+ else
+ simulator_sysroot = "";
break;
}
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
if (sim_add_option_table (sd, NULL, standard_options) != SIM_RC_OK)
return SIM_RC_FAIL;
-#ifdef SIM_HANDLES_LMA
- STATE_LOAD_AT_LMA_P (sd) = SIM_HANDLES_LMA;
-#endif
+ STATE_LOAD_AT_LMA_P (sd) = 1;
return SIM_RC_OK;
}
/* Return non-zero if arg is a duplicate argument.
If ARG is NULL, initialize. */
-#define ARG_HASH_SIZE 97
-#define ARG_HASH(a) ((256 * (unsigned char) a[0] + (unsigned char) a[1]) % ARG_HASH_SIZE)
-
static int
dup_arg_p (const char *arg)
{
- int hash;
- static const char **arg_table = NULL;
+ static htab_t arg_table = NULL;
+ void **slot;
if (arg == NULL)
{
if (arg_table == NULL)
- arg_table = (const char **) xmalloc (ARG_HASH_SIZE * sizeof (char *));
- memset (arg_table, 0, ARG_HASH_SIZE * sizeof (char *));
+ arg_table = htab_create_alloc (10, htab_hash_string,
+ htab_eq_string, NULL,
+ xcalloc, free);
+ htab_empty (arg_table);
return 0;
}
- hash = ARG_HASH (arg);
- while (arg_table[hash] != NULL)
- {
- if (strcmp (arg, arg_table[hash]) == 0)
- return 1;
- /* We assume there won't be more than ARG_HASH_SIZE arguments so we
- don't check if the table is full. */
- if (++hash == ARG_HASH_SIZE)
- hash = 0;
- }
- arg_table[hash] = arg;
+ slot = htab_find_slot (arg_table, arg, INSERT);
+ if (*slot != NULL)
+ return 1;
+ *slot = (void *) arg;
return 0;
}
/* Called by sim_open to parse the arguments. */
SIM_RC
-sim_parse_args (SIM_DESC sd, char **argv)
+sim_parse_args (SIM_DESC sd, char * const *argv)
{
- int c, i, argc, num_opts;
+ int c, i, argc, num_opts, save_opterr;
char *p, *short_options;
/* The `val' option struct entry is dynamically assigned for options that
only come in the long form. ORIG_VAL is used to get the original value
SIM_RC result = SIM_RC_OK;
/* Count the number of arguments. */
- for (argc = 0; argv[argc] != NULL; ++argc)
- continue;
+ argc = countargv (argv);
/* Count the number of options. */
num_opts = 0;
/* Ensure getopt is initialized. */
optind = 0;
+ /* Do not lot getopt throw errors for us. But don't mess with the state for
+ any callers higher up by saving/restoring it. */
+ save_opterr = opterr;
+ opterr = 0;
+
while (1)
{
int longind, optc;
}
if (optc == '?')
{
+ /* If getopt rejects a short option, optopt is set to the bad char.
+ If it rejects a long option, we have to look at optind. In the
+ short option case, argv could be multiple short options. */
+ const char *badopt;
+ char optbuf[3];
+
+ if (optopt)
+ {
+ sprintf (optbuf, "-%c", optopt);
+ badopt = optbuf;
+ }
+ else
+ badopt = argv[optind - 1];
+
+ sim_io_eprintf (sd,
+ "%s: unrecognized option '%s'\n"
+ "Use --help for a complete list of options.\n",
+ STATE_MY_NAME (sd), badopt);
+
result = SIM_RC_FAIL;
break;
}
}
}
+ opterr = save_opterr;
+
free (long_options);
free (short_options);
free (handlers);
}
}
+/* Print version information. */
+
+void
+sim_print_version (SIM_DESC sd, int is_command)
+{
+ sim_io_printf (sd, "GNU simulator %s%s\n", PKGVERSION, version);
+
+ sim_io_printf (sd, "Copyright (C) 2021 Free Software Foundation, Inc.\n");
+
+ /* Following the copyright is a brief statement that the program is
+ free software, that users are free to copy and change it on
+ certain conditions, that it is covered by the GNU GPL, and that
+ there is no warranty. */
+
+ sim_io_printf (sd, "\
+License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>\
+\nThis is free software: you are free to change and redistribute it.\n\
+There is NO WARRANTY, to the extent permitted by law.\n");
+
+ if (!is_command)
+ return;
+
+ sim_io_printf (sd, "This SIM was configured as:\n");
+ sim_config_print (sd);
+
+ if (REPORT_BUGS_TO[0])
+ {
+ sim_io_printf (sd, "For bug reporting instructions, please see:\n\
+ %s.\n",
+ REPORT_BUGS_TO);
+ }
+ sim_io_printf (sd, "Find the SIM homepage & other documentation resources \
+online at:\n <https://sourceware.org/gdb/wiki/Sim/>.\n");
+}
+
/* Utility of sim_args_command to find the closest match for a command.
Commands that have "-" in them can be specified as separate words.
e.g. sim memory-region 0x800000,0x4000
static char **
complete_option_list (char **ret, size_t *cnt, const struct option_list *ol,
- char *text, char *word)
+ const char *text, const char *word)
{
const OPTION *opt = NULL;
int argi;
completed is stored in @word. Trailing text of @word is not. */
char **
-sim_complete_command (SIM_DESC sd, char *text, char *word)
+sim_complete_command (SIM_DESC sd, const char *text, const char *word)
{
char **ret = NULL;
size_t cnt = 1;
}
SIM_RC
-sim_args_command (SIM_DESC sd, char *cmd)
+sim_args_command (SIM_DESC sd, const char *cmd)
{
/* something to do? */
if (cmd == NULL)
sim_cpu *cpu;
if (argv [0] == NULL)
- return SIM_RC_OK; /* FIXME - perhaps help would be better */
+ {
+ freeargv (argv);
+ return SIM_RC_OK; /* FIXME - perhaps help would be better */
+ }
/* First check for a cpu selector. */
{