/* Simulator option handling.
- Copyright (C) 1996, 1997, 2004, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1996-2019 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GDB, the GNU debugger.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#include "config.h"
#include "sim-main.h"
#ifdef HAVE_STRING_H
#include <string.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 "bfd.h"
OPTION_ENVIRONMENT,
OPTION_ALIGNMENT,
OPTION_VERBOSE,
-#if defined (SIM_HAVE_BIENDIAN)
OPTION_ENDIAN,
-#endif
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
{
{ {"verbose", no_argument, NULL, OPTION_VERBOSE},
'v', NULL, "Verbose output",
- standard_option_handler },
+ standard_option_handler, NULL },
-#if defined (SIM_HAVE_BIENDIAN) /* ??? && WITH_TARGET_BYTE_ORDER == 0 */
{ {"endian", required_argument, NULL, OPTION_ENDIAN},
'E', "big|little", "Set endianness",
- standard_option_handler },
-#endif
+ 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', "MEMORY SIZE", "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",
"Root for system calls with absolute file-names and cwd at start",
- standard_option_handler },
+ standard_option_handler, NULL },
- { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
+ { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
};
static SIM_RC
STATE_VERBOSE_P (sd) = 1;
break;
-#ifdef SIM_HAVE_BIENDIAN
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
{
return SIM_RC_FAIL;
}
break;
-#endif
case OPTION_ENVIRONMENT:
if (strcmp (arg, "user") == 0)
if (WITH_ENVIRONMENT != ALL_ENVIRONMENT
&& WITH_ENVIRONMENT != STATE_ENVIRONMENT (sd))
{
- char *type;
+ const char *type;
switch (WITH_ENVIRONMENT)
{
case USER_ENVIRONMENT: type = "user"; break;
}
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:
- {
- unsigned long ul = strtol (arg, NULL, 0);
- /* 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_io_printf (sd, "GNU simulator %s%s\n", PKGVERSION, version);
+ 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;
}
#define ARG_HASH(a) ((256 * (unsigned char) a[0] + (unsigned char) a[1]) % ARG_HASH_SIZE)
static int
-dup_arg_p (arg)
- char *arg;
+dup_arg_p (const char *arg)
{
int hash;
- static char **arg_table = NULL;
+ static const char **arg_table = NULL;
if (arg == NULL)
{
if (arg_table == NULL)
- arg_table = (char **) xmalloc (ARG_HASH_SIZE * sizeof (char *));
+ arg_table = (const char **) xmalloc (ARG_HASH_SIZE * sizeof (char *));
memset (arg_table, 0, ARG_HASH_SIZE * sizeof (char *));
return 0;
}
arg_table[hash] = arg;
return 0;
}
-
+
/* Called by sim_open to parse the arguments. */
SIM_RC
-sim_parse_args (sd, argv)
- 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;
char *name;
*lp = opt->opt;
/* Prepend --<cpuname>- to the option. */
- asprintf (&name, "%s-%s", CPU_NAME (cpu), lp->name);
+ if (asprintf (&name, "%s-%s", CPU_NAME (cpu), lp->name) < 0)
+ {
+ sim_io_eprintf (sd, "internal error, out of memory");
+ result = SIM_RC_FAIL;
+ break;
+ }
lp->name = name;
/* Dynamically assign `val' numbers for long options. */
lp->val = i++;
}
}
}
-
+
/* Terminate the short and long option lists. */
*p = 0;
lp->name = NULL;
/* 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;
}
}
}
- zfree (long_options);
- zfree (short_options);
- zfree (handlers);
- zfree (opt_cpu);
- zfree (orig_val);
+ opterr = save_opterr;
+
+ free (long_options);
+ free (short_options);
+ free (handlers);
+ free (opt_cpu);
+ free (orig_val);
return result;
}
}
while (OPTION_VALID_P (o) && o->doc == NULL);
}
-
+
/* list any long options (aliases) for the current OPT */
o = opt;
do
/* Print help messages for the options. */
void
-sim_print_help (sd, is_command)
- SIM_DESC sd;
- int is_command;
+sim_print_help (SIM_DESC sd, int is_command)
{
if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
sim_io_printf (sd, "Usage: %s [options] program [program args]\n",
return matching_opt;
}
+static char **
+complete_option_list (char **ret, size_t *cnt, const struct option_list *ol,
+ const char *text, const char *word)
+{
+ const OPTION *opt = NULL;
+ int argi;
+ size_t len = strlen (word);
+
+ for ( ; ol != NULL; ol = ol->next)
+ for (opt = ol->options; OPTION_VALID_P (opt); ++opt)
+ {
+ const char *name = opt->opt.name;
+
+ /* A long option to match against? */
+ if (!name)
+ continue;
+
+ /* Does this option actually match? */
+ if (strncmp (name, word, len))
+ continue;
+
+ ret = xrealloc (ret, ++*cnt * sizeof (ret[0]));
+ ret[*cnt - 2] = xstrdup (name);
+ }
+
+ return ret;
+}
+
+/* All leading text is stored in @text, while the current word being
+ completed is stored in @word. Trailing text of @word is not. */
+
+char **
+sim_complete_command (SIM_DESC sd, const char *text, const char *word)
+{
+ char **ret = NULL;
+ size_t cnt = 1;
+ sim_cpu *cpu;
+
+ /* Only complete first word for now. */
+ if (text != word)
+ return ret;
+
+ cpu = STATE_CPU (sd, 0);
+ if (cpu)
+ ret = complete_option_list (ret, &cnt, CPU_OPTIONS (cpu), text, word);
+ ret = complete_option_list (ret, &cnt, STATE_OPTIONS (sd), text, word);
+
+ if (ret)
+ ret[cnt - 1] = NULL;
+ return ret;
+}
+
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)
return SIM_RC_OK; /* FIXME - perhaps help would be better */
-
+
if (cmd [0] == '-')
{
/* user specified -<opt> ... form? */
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. */
{
freeargv (argv);
}
-
+
/* didn't find anything that remotly matched */
return SIM_RC_FAIL;
}