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