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