From: David Edelsohn Date: Thu, 17 Apr 1997 12:39:29 +0000 (+0000) Subject: * sim-options.c, sim-options.h: New files. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4ede3a832bf3df431b42d153e70921b3bc81eabc;p=binutils-gdb.git * sim-options.c, sim-options.h: New files. --- diff --git a/sim/common/.Sanitize b/sim/common/.Sanitize index 740aaf6d803..efdd29c7f3d 100644 --- a/sim/common/.Sanitize +++ b/sim/common/.Sanitize @@ -57,6 +57,8 @@ sim-load.c sim-n-bits.h sim-n-core.h sim-n-endian.h +sim-options.c +sim-options.h sim-trace.h sim-types.h sim-utils.c diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index 2509f2b3854..27e29153993 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,5 +1,7 @@ Thu Apr 17 02:25:11 1997 Doug Evans + * sim-options.c, sim-options.h: New files. + * run.c (main): Check return value of sim_open. * Make-common.in (sim-options.o, sim-load.o): Add rules for. diff --git a/sim/common/sim-options.c b/sim/common/sim-options.c new file mode 100644 index 00000000000..16844a6ec79 --- /dev/null +++ b/sim/common/sim-options.c @@ -0,0 +1,724 @@ +/* Simulator option handling. + Copyright (C) 1996, 1997 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. + +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. */ + +#include "sim-main.h" +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#include "libiberty.h" +#include "../libiberty/alloca-conf.h" +#include "sim-options.h" +#include "sim-io.h" + +/* This is defined in sim-config.h. */ +#ifndef MAX_NR_PROCESSORS +#define MAX_NR_PROCESSORS 1 +#endif + +/* Add a set of options to the simulator. + TABLE is an array of OPTIONS terminated by a NULL `opt.name' entry. + This is intended to be called by modules in their `install' handler. */ + +SIM_RC +sim_add_option_table (sd, table) + SIM_DESC sd; + const OPTION *table; +{ + struct option_list *ol = ((struct option_list *) + xmalloc (sizeof (struct option_list))); + + /* Note: The list is constructed in the reverse order we're called so + later calls will override earlier ones (in case that ever happens). + This is the intended behaviour. */ + ol->next = STATE_OPTIONS (sd); + ol->options = table; + STATE_OPTIONS (sd) = ol; + + return SIM_RC_OK; +} + +/* Standard option table. + Modules may specify additional ones. + The caller of sim_parse_args may also specify additional options + by calling sim_add_option_table first. */ + +static DECLARE_OPTION_HANDLER (standard_option_handler); + +/* FIXME: We shouldn't print in --help output options that aren't usable. + Some fine tuning will be necessary. One can either move less general + options to another table or use a HAVE_FOO macro to ifdef out unavailable + options. */ + +#define OPTION_DEBUG_INSN (OPTION_START + 0) +#define OPTION_DEBUG_FILE (OPTION_START + 1) +#define OPTION_TRACE_INSN (OPTION_START + 2) +#define OPTION_TRACE_DECODE (OPTION_START + 3) +#define OPTION_TRACE_EXTRACT (OPTION_START + 4) +#define OPTION_TRACE_LINENUM (OPTION_START + 5) +#define OPTION_TRACE_MEMORY (OPTION_START + 6) +#define OPTION_TRACE_MODEL (OPTION_START + 7) +#define OPTION_TRACE_ALU (OPTION_START + 8) +#define OPTION_TRACE_FILE (OPTION_START + 9) +#define OPTION_PROFILE_INSN (OPTION_START + 10) +#define OPTION_PROFILE_MEMORY (OPTION_START + 11) +#define OPTION_PROFILE_MODEL (OPTION_START + 12) +#define OPTION_PROFILE_SIMCACHE (OPTION_START + 13) +#define OPTION_PROFILE_FILE (OPTION_START + 14) + +static const OPTION standard_options[] = +{ + { {"verbose", no_argument, NULL, 'v'}, + 'v', NULL, "Verbose output", + standard_option_handler }, + + { {"debug", no_argument, NULL, 'D'}, + 'D', NULL, "Print debugging messages", + standard_option_handler }, + { {"debug-insn", no_argument, NULL, OPTION_DEBUG_INSN}, + '\0', NULL, "Print instruction debugging messages", + standard_option_handler }, + { {"debug-file", required_argument, NULL, OPTION_DEBUG_FILE}, + '\0', "FILE NAME", "Specify debugging output file", + standard_option_handler }, + + { {"trace", no_argument, NULL, 't'}, + 't', NULL, "Perform tracing", + standard_option_handler }, + { {"trace-insn", no_argument, NULL, OPTION_TRACE_INSN}, + '\0', NULL, "Perform instruction tracing", + standard_option_handler }, + { {"trace-decode", no_argument, NULL, OPTION_TRACE_DECODE}, + '\0', NULL, "Perform instruction decoding tracing", + standard_option_handler }, + { {"trace-extract", no_argument, NULL, OPTION_TRACE_EXTRACT}, + '\0', NULL, "Perform instruction extraction tracing", + standard_option_handler }, + { {"trace-linenum", no_argument, NULL, OPTION_TRACE_LINENUM}, + '\0', NULL, "Perform line number tracing", + standard_option_handler }, + { {"trace-memory", no_argument, NULL, OPTION_TRACE_MEMORY}, + '\0', NULL, "Perform memory tracing", + standard_option_handler }, + { {"trace-model", no_argument, NULL, OPTION_TRACE_MODEL}, + '\0', NULL, "Perform model tracing", + standard_option_handler }, + { {"trace-alu", no_argument, NULL, OPTION_TRACE_ALU}, + '\0', NULL, "Perform ALU tracing", + standard_option_handler }, + { {"trace-file", required_argument, NULL, OPTION_TRACE_FILE}, + '\0', "FILE NAME", "Specify tracing output file", + standard_option_handler }, + +#ifdef SIM_H8300 /* FIXME: Should be movable to h8300 dir. */ + { {"h8300h", no_argument, NULL, 'h'}, + 'h', NULL, "Indicate the CPU is h8/300h or h8/300s", + standard_option_handler }, +#endif + +#ifdef SIM_HAVE_SIMCACHE + { {"simcache-size", required_argument, NULL, 'c'}, + 'c', "SIM CACHE SIZE", "Specify size of simulator instruction cache", + standard_option_handler }, +#endif + +#ifdef SIM_HAVE_FLATMEM + { {"mem-size", required_argument, NULL, 'm'}, + 'm', "MEMORY SIZE", "Specify memory size", + standard_option_handler }, +#endif + +#ifdef SIM_HAVE_MAX_INSNS + { {"max-insns", required_argument, NULL, 'M'}, + 'M', "MAX INSNS", "Specify maximum instructions to execute", + standard_option_handler }, +#endif + +#ifdef SIM_HAVE_PROFILE + { {"profile", no_argument, NULL, 'p'}, + 'p', NULL, "Perform profiling", + standard_option_handler }, + { {"profile-insn", no_argument, NULL, OPTION_PROFILE_INSN}, + '\0', NULL, "Perform instruction profiling", + standard_option_handler }, + { {"profile-memory", no_argument, NULL, OPTION_PROFILE_MEMORY}, + '\0', NULL, "Perform memory profiling", + standard_option_handler }, + { {"profile-model", no_argument, NULL, OPTION_PROFILE_MODEL}, + '\0', NULL, "Perform model profiling", + standard_option_handler }, + { {"profile-simcache", no_argument, NULL, OPTION_PROFILE_SIMCACHE}, + '\0', NULL, "Perform simulator execution cache profiling", + standard_option_handler }, + { {"profile-file", required_argument, NULL, OPTION_PROFILE_FILE}, + '\0', "FILE NAME", "Specify profile output file", + standard_option_handler }, +#ifdef SIM_HAVE_PROFILE_PC + { {"profile-pc-frequency", required_argument, NULL, 'F'}, + 'F', "PC PROFILE FREQUENCY", "Turn on PC profiling at specified frequency", + standard_option_handler }, + { {"profile-pc-size", required_argument, NULL, 'S'}, + 'S', "PC PROFILE SIZE", "Specify PC profiling size", + standard_option_handler }, +#endif +#endif /* SIM_HAVE_PROFILE */ + + { {"help", no_argument, NULL, 'H'}, + 'H', NULL, "Print help information", + standard_option_handler }, + + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + +static SIM_RC +standard_option_handler (sd, opt, arg) + SIM_DESC sd; + int opt; + char *arg; +{ + int i,n; + unsigned long ul; + + switch (opt) + { + case 'v' : + STATE_VERBOSE_P (sd) = 1; + break; + + case 'D' : + if (! WITH_DEBUG) + sim_io_eprintf (sd, "Debugging not compiled in, `-D' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + for (i = 0; i < MAX_DEBUG_VALUES; ++i) + CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[i] = 1; + } + break; + + case OPTION_DEBUG_INSN : + if (! WITH_DEBUG) + sim_io_eprintf (sd, "Debugging not compiled in, `--debug-insn' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[DEBUG_INSN_IDX] = 1; + } + break; + + case OPTION_DEBUG_FILE : + if (! WITH_DEBUG) + sim_io_eprintf (sd, "Debugging not compiled in, `--debug-file' ignored\n"); + else + { + FILE *f = fopen (arg, "w"); + + if (f == NULL) + { + sim_io_eprintf (sd, "Unable to open debug output file `%s'\n", arg); + return SIM_RC_FAIL; + } + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_DEBUG_FILE (STATE_CPU (sd, n)) = f; + } + break; + + case 't' : + if (! WITH_TRACE) + sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + for (i = 0; i < MAX_TRACE_VALUES; ++i) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[i] = 1; + } + break; + + case OPTION_TRACE_INSN : + if (! (WITH_TRACE & (1 << TRACE_INSN_IDX))) + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-insn' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_INSN_IDX] = 1; + } + break; + + case OPTION_TRACE_DECODE : + if (! (WITH_TRACE & (1 << TRACE_DECODE_IDX))) + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-decode' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_DECODE_IDX] = 1; + } + break; + + case OPTION_TRACE_EXTRACT : + if (! (WITH_TRACE & (1 << TRACE_EXTRACT_IDX))) + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-extract' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EXTRACT_IDX] = 1; + } + break; + + case OPTION_TRACE_LINENUM : + if (! (WITH_TRACE & (1 << TRACE_LINENUM_IDX))) + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-linenum' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_LINENUM_IDX] = 1; + } + break; + + case OPTION_TRACE_MEMORY : + if (! (WITH_TRACE & (1 << TRACE_MEMORY_IDX))) + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-memory' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MEMORY_IDX] = 1; + } + break; + + case OPTION_TRACE_MODEL : + if (! (WITH_TRACE & (1 << TRACE_MODEL_IDX))) + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-model' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MODEL_IDX] = 1; + } + break; + + case OPTION_TRACE_ALU : + if (! (WITH_TRACE & (1 << TRACE_ALU_IDX))) + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-alu' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_ALU_IDX] = 1; + } + break; + + case OPTION_TRACE_FILE : + if (! WITH_TRACE) + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n"); + else + { + FILE *f = fopen (arg, "w"); + + if (f == NULL) + { + sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg); + return SIM_RC_FAIL; + } + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FILE (STATE_CPU (sd, n)) = f; + } + break; + +#ifdef SIM_H8300 /* FIXME: Can be moved to h8300 dir. */ + case 'h' : + set_h8300h (1); + break; +#endif + +#ifdef SIM_HAVE_SIMCACHE + case 'c': + n = strtol (arg, NULL, 0); + if (n <= 0) + { + sim_io_eprintf (sd, "Invalid simulator cache size: %d", n); + return SIM_RC_FAIL; + } + STATE_SIMCACHE_SIZE (sd) = n; + break; +#endif + +#ifdef SIM_HAVE_FLATMEM + case 'm': + 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 + +#ifdef SIM_HAVE_MAX_INSNS + case 'M' : + ul = strtoul (arg, NULL, 0); + if (! isdigit (arg[0])) + { + sim_io_eprintf (sd, "Invalid maximum instruction count: `%s'", arg); + return SIM_RC_FAIL; + } + STATE_MAX_INSNS (sd) = ul; + break; +#endif + +#ifdef SIM_HAVE_PROFILE + case 'p' : + if (! WITH_PROFILE) + sim_io_eprintf (sd, "Profile not compiled in, -p option ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + for (i = 0; i < MAX_PROFILE_VALUES; ++i) + CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[i] = 1; + } + break; + + case OPTION_PROFILE_INSN : + if (! (WITH_PROFILE & (1 << PROFILE_INSN_IDX))) + sim_io_eprintf (sd, "Profiling not compiled in, `--profile-insn' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_INSN_IDX] = 1; + } + break; + + case OPTION_PROFILE_MEMORY : + if (! (WITH_PROFILE & (1 << PROFILE_MEMORY_IDX))) + sim_io_eprintf (sd, "Profiling not compiled in, `--profile-memory' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_MEMORY_IDX] = 1; + } + break; + + case OPTION_PROFILE_MODEL : + if (! (WITH_PROFILE & (1 << PROFILE_MODEL_IDX))) + sim_io_eprintf (sd, "Profiling not compiled in, `--profile-model' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_MODEL_IDX] = 1; + } + break; + + case OPTION_PROFILE_SIMCACHE : + if (! (WITH_PROFILE & (1 << PROFILE_SIMCACHE_IDX))) + sim_io_eprintf (sd, "Profiling not compiled in, `--profile-simcache' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_SIMCACHE_IDX] = 1; + } + break; + + case OPTION_PROFILE_FILE : + /* FIXME: Might want this to apply to pc profiling only, + or have two profile file options. */ + if (! WITH_PROFILE) + sim_io_eprintf (sd, "Profiling not compiled in, `--profile-file' ignored\n"); + else + { + FILE *f = fopen (arg, "w"); + + if (f == NULL) + { + sim_io_eprintf (sd, "Unable to open profile output file `%s'\n", arg); + return SIM_RC_FAIL; + } + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_PROFILE_FILE (STATE_CPU (sd, n)) = f; + } + break; + +#ifdef SIM_HAVE_PROFILE_PC + case 'F' : + STATE_PROFILE_PC_FREQUENCY (sd) = atoi (arg); + /* FIXME: Validate arg. */ + break; + case 'S' : + STATE_PROFILE_PC_SIZE (sd) = atoi (arg); + /* FIXME: Validate arg. */ + break; +#endif +#endif /* SIM_HAVE_PROFILE */ + + case 'H': + sim_print_help (sd); + if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) + exit (0); + /* FIXME: 'twould be nice to do something similar if gdb. */ + break; + } + + return SIM_RC_OK; +} + +/* Initialize common parts before argument processing. + Called by sim_open. */ + +SIM_RC +sim_pre_argv_init (sd, myname) + SIM_DESC sd; + const char *myname; +{ + STATE_MY_NAME (sd) = myname + strlen (myname); + while (STATE_MY_NAME (sd) > myname && STATE_MY_NAME (sd)[-1] != '/') + --STATE_MY_NAME (sd); + + if (sim_add_option_table (sd, standard_options) != SIM_RC_OK) + return SIM_RC_FAIL; + + 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 (arg) + char *arg; +{ + int hash; + static char **arg_table = NULL; + + if (arg == NULL) + { + if (arg_table == NULL) + arg_table = (char **) xmalloc (ARG_HASH_SIZE * sizeof (char *)); + memset (arg_table, 0, ARG_HASH_SIZE * sizeof (char *)); + 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; + return 0; +} + +/* Called by sim_open to parse the arguments. */ + +SIM_RC +sim_parse_args (sd, argv) + SIM_DESC sd; + char **argv; +{ + int i, argc, num_opts; + 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 + back. */ + char *orig_val; + struct option *lp, *long_options; + const struct option_list *ol; + const OPTION *opt; + OPTION_HANDLER **handlers; + + /* Count the number of arguments. */ + for (argc = 0; argv[argc] != NULL; ++argc) + continue; + + /* Count the number of options. */ + num_opts = 0; + for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) + for (opt = ol->options; opt->opt.name != NULL; ++opt) + ++num_opts; + + /* Initialize duplicate argument checker. */ + (void) dup_arg_p (NULL); + + /* Build the option table for getopt. */ + long_options = (struct option *) alloca ((num_opts + 1) * sizeof (struct option)); + lp = long_options; + short_options = (char *) alloca (num_opts * 3 + 1); + p = short_options; +#if 0 /* ??? necessary anymore? */ + /* Set '+' as first char so argument permutation isn't done. This is done + to workaround a problem with invoking getopt_long in run.c.: optind gets + decremented when the program name is reached. */ + *p++ = '+'; +#endif + handlers = (OPTION_HANDLER **) alloca (256 * sizeof (OPTION_HANDLER *)); + memset (handlers, 0, 256 * sizeof (OPTION_HANDLER *)); + orig_val = (char *) alloca (256); + for (i = OPTION_START, ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) + for (opt = ol->options; opt->opt.name != NULL; ++opt) + { + if (dup_arg_p (opt->opt.name)) + continue; + if (opt->shortopt != 0) + { + *p++ = opt->shortopt; + if (opt->opt.has_arg == required_argument) + *p++ = ':'; + else if (opt->opt.has_arg == optional_argument) + { *p++ = ':'; *p++ = ':'; } + } + *lp = opt->opt; + /* Dynamically assign `val' numbers for long options that don't have + a short option equivalent. */ + if (OPTION_LONG_ONLY_P (opt->opt.val)) + lp->val = i++; + handlers[(unsigned char) lp->val] = opt->handler; + orig_val[(unsigned char) lp->val] = opt->opt.val; + ++lp; + } + *p = 0; + lp->name = NULL; + + /* Ensure getopt is initialized. */ + optind = 0; + while (1) + { + int longind, optc; + + optc = getopt_long (argc, argv, short_options, long_options, &longind); + if (optc == -1) + { + if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) + STATE_PROG_ARGV (sd) = argv + optind; + break; + } + if (optc == '?') + return SIM_RC_FAIL; + + if ((*handlers[optc]) (sd, orig_val[optc], optarg) == SIM_RC_FAIL) + return SIM_RC_FAIL; + } + + return SIM_RC_OK; +} + +/* Print help messages for the options. */ + +void +sim_print_help (sd) + SIM_DESC sd; +{ + const struct option_list *ol; + const OPTION *opt; + + if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) + sim_io_printf (sd, "Usage: %s [options] program [program args]\n", + STATE_MY_NAME (sd)); + + /* Initialize duplicate argument checker. */ + (void) dup_arg_p (NULL); + + sim_io_printf (sd, "Options:\n"); + for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) + for (opt = ol->options; opt->opt.name != NULL; ++opt) + { + int comma, len; + const OPTION *o; + + if (dup_arg_p (opt->opt.name)) + continue; + + if (opt->doc == NULL) + continue; + + sim_io_printf (sd, " "); + + comma = 0; + len = 2; + + o = opt; + do + { + if (o->shortopt != '\0') + { + sim_io_printf (sd, "%s-%c", comma ? ", " : "", o->shortopt); + len += (comma ? 2 : 0) + 2; + if (o->arg != NULL) + { + if (o->opt.has_arg != optional_argument) + { + sim_io_printf (sd, " "); + ++len; + } + sim_io_printf (sd, "%s", o->arg); + len += strlen (o->arg); + } + comma = 1; + } + ++o; + } + while (o->opt.name != NULL && o->doc == NULL); + + o = opt; + do + { + if (o->opt.name != NULL) + { + sim_io_printf (sd, "%s--%s", + comma ? ", " : "", + o->opt.name); + len += ((comma ? 2 : 0) + + 2 + + strlen (o->opt.name)); + if (o->arg != NULL) + { + sim_io_printf (sd, " %s", o->arg); + len += 1 + strlen (o->arg); + } + comma = 1; + } + ++o; + } + while (o->opt.name != NULL && o->doc == NULL); + + if (len >= 30) + { + sim_io_printf (sd, "\n"); + len = 0; + } + + for (; len < 30; len++) + sim_io_printf (sd, " "); + + sim_io_printf (sd, "%s\n", opt->doc); + } + + if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) + { + sim_io_printf (sd, "\n"); + sim_io_printf (sd, "program args Arguments to pass to simulated program.\n"); + sim_io_printf (sd, " Note: Very few simulators support this.\n"); + } +} diff --git a/sim/common/sim-options.h b/sim/common/sim-options.h new file mode 100644 index 00000000000..ea0b21a6a47 --- /dev/null +++ b/sim/common/sim-options.h @@ -0,0 +1,81 @@ +/* Header file for simulator argument handling. + Copyright (C) 1997 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. + +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. */ + +#ifndef SIM_OPTIONS_H +#define SIM_OPTIONS_H + +#include "getopt.h" + +/* ARGV option support. + + Options for the standalone simulator are parsed by sim_open since + sim_open handles the large majority of them and it also parses the + options when invoked by gdb [or any external program]. */ + +typedef SIM_RC (OPTION_HANDLER) PARAMS ((SIM_DESC, int, char *)); + +/* Declare option handlers with a macro so it's usable on k&r systems. */ +#define DECLARE_OPTION_HANDLER(fn) SIM_RC fn PARAMS ((SIM_DESC, int, char *)) + +typedef struct { + /* The long option information. */ + struct option opt; + /* The short option with the same meaning ('\0' if none). */ + char shortopt; + /* The name of the argument (NULL if none). */ + const char *arg; + /* The documentation string. If this is NULL, this is a synonym for + the previous option. */ + const char *doc; + /* A function to process the option. */ + OPTION_HANDLER *handler; +} OPTION; + +/* All options that don't have a short form equivalent begin with this for + `val'. 130 isn't special, just some non-ASCII value to begin at. + Modules needn't worry about collisions here, the code dynamically assigned + the actual numbers used and then passes the original value to the option + handler. */ +#define OPTION_START 130 + +/* Non-zero if an option whose `val' entry is O is using OPTION_START. */ +#define OPTION_LONG_ONLY_P(o) ((unsigned char) (o) >= OPTION_START) + +/* List of options added by various modules. */ +typedef struct option_list { + struct option_list *next; + const OPTION *options; +} OPTION_LIST; + +/* Add a set of options to the simulator. + TABLE is an array of OPTIONS terminated by a NULL `opt.name' entry. */ +SIM_RC sim_add_option_table PARAMS ((SIM_DESC sd, const OPTION *table)); + +/* Initialize common parts before argument processing. + Called by sim_open. */ +SIM_RC sim_pre_argv_init PARAMS ((SIM_DESC sd, const char *myname)); + +/* Called by sim_open to parse the arguments. */ +SIM_RC sim_parse_args PARAMS ((SIM_DESC sd, char **argv)); + +/* Print help messages for the options. */ +void sim_print_help PARAMS ((SIM_DESC sd)); + +#endif /* SIM_OPTIONS_H */