/* Memory-access and commands for "inferior" process, for GDB.
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
This file is part of GDB.
#include "symfile.h"
#include "objfiles.h"
#include "completer.h"
-#ifdef UI_OUT
#include "ui-out.h"
-#endif
#include "event-top.h"
#include "parser-defs.h"
static char *inferior_args;
+/* The inferior arguments as a vector. If INFERIOR_ARGC is nonzero,
+ then we must compute INFERIOR_ARGS from this (via the target). */
+
+static int inferior_argc;
+static char **inferior_argv;
+
/* File name for default use for standard in/out in the inferior. */
char *inferior_io_terminal;
char *
get_inferior_args (void)
{
+ if (inferior_argc != 0)
+ {
+ char *n, *old;
+
+ n = gdbarch_construct_inferior_arguments (current_gdbarch,
+ inferior_argc, inferior_argv);
+ old = set_inferior_args (n);
+ xfree (old);
+ }
+
+ if (inferior_args == NULL)
+ inferior_args = xstrdup ("");
+
return inferior_args;
}
char *saved_args = inferior_args;
inferior_args = newargs;
+ inferior_argc = 0;
+ inferior_argv = 0;
return saved_args;
}
+void
+set_inferior_args_vector (int argc, char **argv)
+{
+ inferior_argc = argc;
+ inferior_argv = argv;
+}
+
+/* Notice when `set args' is run. */
+static void
+notice_args_set (char *args, int from_tty, struct cmd_list_element *c)
+{
+ inferior_argc = 0;
+ inferior_argv = 0;
+}
+
+/* Notice when `show args' is run. */
+static void
+notice_args_read (char *args, int from_tty, struct cmd_list_element *c)
+{
+ /* Might compute the value. */
+ get_inferior_args ();
+}
+
+\f
+/* Compute command-line string given argument vector. This does the
+ same shell processing as fork_inferior. */
+/* ARGSUSED */
+char *
+construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv)
+{
+ char *result;
+
+ if (STARTUP_WITH_SHELL)
+ {
+ /* This holds all the characters considered special to the
+ typical Unix shells. We include `^' because the SunOS
+ /bin/sh treats it as a synonym for `|'. */
+ char *special = "\"!#$&*()\\|[]{}<>?'\"`~^; \t\n";
+ int i;
+ int length = 0;
+ char *out, *cp;
+
+ /* We over-compute the size. It shouldn't matter. */
+ for (i = 0; i < argc; ++i)
+ length += 2 * strlen (argv[i]) + 1;
+
+ result = (char *) xmalloc (length);
+ out = result;
+
+ for (i = 0; i < argc; ++i)
+ {
+ if (i > 0)
+ *out++ = ' ';
+
+ for (cp = argv[i]; *cp; ++cp)
+ {
+ if (strchr (special, *cp) != NULL)
+ *out++ = '\\';
+ *out++ = *cp;
+ }
+ }
+ *out = '\0';
+ }
+ else
+ {
+ /* In this case we can't handle arguments that contain spaces,
+ tabs, or newlines -- see breakup_args(). */
+ int i;
+ int length = 0;
+
+ for (i = 0; i < argc; ++i)
+ {
+ char *cp = strchr (argv[i], ' ');
+ if (cp == NULL)
+ cp = strchr (argv[i], '\t');
+ if (cp == NULL)
+ cp = strchr (argv[i], '\n');
+ if (cp != NULL)
+ error ("can't handle command-line argument containing whitespace");
+ length += strlen (argv[i]) + 1;
+ }
+
+ result = (char *) xmalloc (length);
+ result[0] = '\0';
+ for (i = 0; i < argc; ++i)
+ {
+ if (i > 0)
+ strcat (result, " ");
+ strcat (result, argv[i]);
+ }
+ }
+
+ return result;
+}
+\f
+
/* This function detects whether or not a '&' character (indicating
background execution) has been added as *the last* of the arguments ARGS
of a command. If it has, it removes it and returns 1. Otherwise it
clear_breakpoint_hit_counts ();
- exec_file = (char *) get_exec_file (0);
-
/* Purge old solib objfiles. */
objfile_purge_solibs ();
do_run_cleanups (NULL);
- /* The exec file is re-read every time we do a generic_mourn_inferior, so
- we just have to worry about the symbol file. */
+ /* The comment here used to read, "The exec file is re-read every
+ time we do a generic_mourn_inferior, so we just have to worry
+ about the symbol file." The `generic_mourn_inferior' function
+ gets called whenever the program exits. However, suppose the
+ program exits, and *then* the executable file changes? We need
+ to check again here. Since reopen_exec_file doesn't do anything
+ if the timestamp hasn't changed, I don't see the harm. */
+ reopen_exec_file ();
reread_symbols ();
+ exec_file = (char *) get_exec_file (0);
+
/* We keep symbols from add-symbol-file, on the grounds that the
user might want to add some symbols before running the program
(right?). But sometimes (dynamic loading where the user manually
if (from_tty)
{
-#ifdef UI_OUT
ui_out_field_string (uiout, NULL, "Starting program");
ui_out_text (uiout, ": ");
if (exec_file)
ui_out_field_string (uiout, "execfile", exec_file);
ui_out_spaces (uiout, 1);
- ui_out_field_string (uiout, "infargs", inferior_args);
+ /* We call get_inferior_args() because we might need to compute
+ the value now. */
+ ui_out_field_string (uiout, "infargs", get_inferior_args ());
ui_out_text (uiout, "\n");
ui_out_flush (uiout);
-#else
- puts_filtered ("Starting program: ");
- if (exec_file)
- puts_filtered (exec_file);
- puts_filtered (" ");
- puts_filtered (inferior_args);
- puts_filtered ("\n");
- gdb_flush (gdb_stdout);
-#endif
}
- target_create_inferior (exec_file, inferior_args,
+ /* We call get_inferior_args() because we might need to compute
+ the value now. */
+ target_create_inferior (exec_file, get_inferior_args (),
environ_vector (inferior_environ));
}
static void
print_return_value (int structure_return, struct type *value_type)
{
- register value_ptr value;
-#ifdef UI_OUT
+ struct value *value;
static struct ui_stream *stb = NULL;
-#endif /* UI_OUT */
if (!structure_return)
{
value = value_being_returned (value_type, stop_registers, structure_return);
-#ifdef UI_OUT
stb = ui_out_stream_new (uiout);
ui_out_text (uiout, "Value returned is ");
ui_out_field_fmt (uiout, "gdb-result-var", "$%d", record_latest_value (value));
value_print (value, stb->stream, 0, Val_no_prettyprint);
ui_out_field_stream (uiout, "return-value", stb);
ui_out_text (uiout, "\n");
-#else /* UI_OUT */
- printf_filtered ("Value returned is $%d = ", record_latest_value (value));
- value_print (value, gdb_stdout, 0, Val_no_prettyprint);
- printf_filtered ("\n");
-#endif /* UI_OUT */
}
else
{
initiate the call, as opposed to the call_function_by_hand case */
#ifdef VALUE_RETURNED_FROM_STACK
value = 0;
-#ifdef UI_OUT
ui_out_text (uiout, "Value returned has type: ");
ui_out_field_string (uiout, "return-type", TYPE_NAME (value_type));
ui_out_text (uiout, ".");
ui_out_text (uiout, " Cannot determine contents\n");
-#else /* UI_OUT */
- printf_filtered ("Value returned has type: %s.", TYPE_NAME (value_type));
- printf_filtered (" Cannot determine contents\n");
-#endif /* UI_OUT */
#else
value = value_being_returned (value_type, stop_registers, structure_return);
-#ifdef UI_OUT
stb = ui_out_stream_new (uiout);
ui_out_text (uiout, "Value returned is ");
ui_out_field_fmt (uiout, "gdb-result-var", "$%d", record_latest_value (value));
value_print (value, stb->stream, 0, Val_no_prettyprint);
ui_out_field_stream (uiout, "return-value", stb);
ui_out_text (uiout, "\n");
-#else
- printf_filtered ("Value returned is $%d = ", record_latest_value (value));
- value_print (value, gdb_stdout, 0, Val_no_prettyprint);
- printf_filtered ("\n");
-#endif
#endif
}
}
if (from_tty)
{
printf_filtered ("Run till exit from ");
- print_stack_frame (selected_frame, selected_frame_level, 0);
+ print_stack_frame (selected_frame,
+ frame_relative_level (selected_frame), 0);
}
/* If running asynchronously and the target support asynchronous
print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), gdb_stdout);
/* Get the data in raw format. */
- if (read_relative_register_raw_bytes (i, raw_buffer))
+ if (! frame_register_read (selected_frame, i, raw_buffer))
{
printf_filtered ("*value not available*\n");
continue;
{
register int j;
-#ifdef INVALID_FLOAT
- if (INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
- printf_filtered ("<invalid float>");
- else
-#endif
- val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
- gdb_stdout, 0, 1, 0, Val_pretty_default);
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
printf_filtered ("\t(raw 0x");
for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
{
- register int idx = TARGET_BYTE_ORDER == BIG_ENDIAN ? j
+ register int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j
: REGISTER_RAW_SIZE (i) - 1 - j;
printf_filtered ("%02x", (unsigned char) raw_buffer[idx]);
}
if (*addr_exp >= '0' && *addr_exp <= '9')
regnum = atoi (addr_exp); /* Take a number */
if (regnum >= numregs) /* Bad name, or bad number */
- error ("%.*s: invalid register", end - addr_exp, addr_exp);
+ error ("%.*s: invalid register", (int) (end - addr_exp), addr_exp);
found:
DO_REGISTERS_INFO (regnum, fpregs);
/* Stop the execution of the target while running in async mode, in
the backgound. */
-#ifdef UI_OUT
+
void
interrupt_target_command_wrapper (char *args, int from_tty)
{
interrupt_target_command (args, from_tty);
}
-#endif
+
static void
interrupt_target_command (char *args, int from_tty)
{
static void
float_info (char *addr_exp, int from_tty)
{
-#ifdef FLOAT_INFO
- FLOAT_INFO;
-#else
- printf_filtered ("No floating point info available for this processor.\n");
-#endif
+ PRINT_FLOAT_INFO ();
}
\f
/* ARGSUSED */
c = add_com ("tty", class_run, tty_command,
"Set terminal for future runs of program being debugged.");
- c->completer = filename_completer;
+ set_cmd_completer (c, filename_completer);
c = add_set_cmd ("args", class_run, var_string_noescape,
(char *) &inferior_args,
"Set argument list to give program being debugged when it is started.\n\
Follow this command with any number of args, to be passed to the program.",
&setlist);
- add_show_from_set (c, &showlist);
- c->completer = filename_completer;
+ set_cmd_completer (c, filename_completer);
+ set_cmd_sfunc (c, notice_args_set);
+ c = add_show_from_set (c, &showlist);
+ set_cmd_sfunc (c, notice_args_read);
c = add_cmd
("environment", no_class, environment_info,
With an argument VAR, prints the value of environment variable VAR to\n\
give the program being debugged. With no arguments, prints the entire\n\
environment to be given to the program.", &showlist);
- c->completer = noop_completer;
+ set_cmd_completer (c, noop_completer);
add_prefix_cmd ("unset", no_class, unset_command,
- "Complement to certain \"set\" commands",
+ "Complement to certain \"set\" commands.",
&unsetlist, "unset ", 0, &cmdlist);
c = add_cmd ("environment", class_run, unset_environment_command,
"Cancel environment variable VAR for the program.\n\
This does not affect the program until the next \"run\" command.",
&unsetlist);
- c->completer = noop_completer;
+ set_cmd_completer (c, noop_completer);
c = add_cmd ("environment", class_run, set_environment_command,
"Set environment variable value to give the program.\n\
VALUES of environment variables are uninterpreted strings.\n\
This does not affect the program until the next \"run\" command.",
&setlist);
- c->completer = noop_completer;
+ set_cmd_completer (c, noop_completer);
c = add_com ("path", class_files, path_command,
"Add directory DIR(s) to beginning of search path for object files.\n\
This path is equivalent to the $PATH shell variable. It is a list of\n\
directories, separated by colons. These directories are searched to find\n\
fully linked executable files and separately compiled object files as needed.");
- c->completer = filename_completer;
+ set_cmd_completer (c, filename_completer);
c = add_cmd ("paths", no_class, path_info,
"Current search path for finding object files.\n\
directories, separated by colons. These directories are searched to find\n\
fully linked executable files and separately compiled object files as needed.",
&showlist);
- c->completer = noop_completer;
+ set_cmd_completer (c, noop_completer);
add_com ("attach", class_run, attach_command,
"Attach to a process or file outside of GDB.\n\
"Execute until the program reaches a source line greater than the current\n\
or a specified line or address or function (same args as break command).\n\
Execution will also stop upon exit from the current stack frame.");
- c->completer = location_completer;
+ set_cmd_completer (c, location_completer);
add_com_alias ("u", "until", class_run, 1);
c = add_com ("jump", class_run, jump_command,
"Continue program being debugged at specified line or address.\n\
Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\
for an address to start at.");
- c->completer = location_completer;
+ set_cmd_completer (c, location_completer);
if (xdb_commands)
{
Give as argument either LINENUM or *ADDR, where ADDR is an \n\
expression for an address to start at.\n\
This command is a combination of tbreak and jump.");
- c->completer = location_completer;
+ set_cmd_completer (c, location_completer);
}
if (xdb_commands)
With no arguments, uses arguments last specified (with \"run\" or \"set args\").\n\
To cancel previous arguments and run with no arguments,\n\
use \"set args\" without arguments.");
- c->completer = filename_completer;
+ set_cmd_completer (c, filename_completer);
add_com_alias ("r", "run", class_run, 1);
if (xdb_commands)
add_com ("R", class_run, run_no_args_command,
add_info ("float", float_info,
"Print the status of the floating point unit\n");
- set_inferior_args (xstrdup ("")); /* Initially no args */
inferior_environ = make_environ ();
init_environ (inferior_environ);
}