/* Local functions: */
-static void info_registers_command (char *, int);
-
static void until_next_command (int);
-static void until_command (char *, int);
-
-static void path_info (char *, int);
-
-static void path_command (char *, int);
-
-static void unset_command (char *, int);
-
-static void info_float_command (char *, int);
-
-static void disconnect_command (char *, int);
-
-static void unset_environment_command (char *, int);
-
-static void set_environment_command (char *, int);
-
-static void environment_info (char *, int);
-
-static void info_program_command (char *, int);
-
-static void finish_command (char *, int);
-
-static void signal_command (char *, int);
-
-static void jump_command (char *, int);
-
-static void step_1 (int, int, char *);
-
-static void next_command (char *, int);
-
-static void step_command (char *, int);
-
-static void run_command (char *, int);
+static void step_1 (int, int, const char *);
#define ERROR_NO_INFERIOR \
if (!target_has_execution) error (_("The program is not being run."));
static char *inferior_args_scratch;
+/* Scratch area where the new cwd will be stored by 'set cwd'. */
+
+static char *inferior_cwd_scratch;
+
/* Scratch area where 'set inferior-tty' will store user-provided value.
We'll immediate copy it into per-inferior storage. */
}
static void
-set_inferior_tty_command (char *args, int from_tty,
+set_inferior_tty_command (const char *args, int from_tty,
struct cmd_list_element *c)
{
/* CLI has assigned the user-provided value to inferior_io_terminal_scratch.
NEWARGS is not transferred. */
void
-set_inferior_args (char *newargs)
+set_inferior_args (const char *newargs)
{
xfree (current_inferior ()->args);
current_inferior ()->args = newargs ? xstrdup (newargs) : NULL;
/* Notice when `set args' is run. */
static void
-set_args_command (char *args, int from_tty, struct cmd_list_element *c)
+set_args_command (const char *args, int from_tty, struct cmd_list_element *c)
{
/* CLI has assigned the user-provided value to inferior_args_scratch.
Now route it to current inferior. */
deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
}
+/* See common/common-inferior.h. */
+
+void
+set_inferior_cwd (const char *cwd)
+{
+ struct inferior *inf = current_inferior ();
+
+ gdb_assert (inf != NULL);
+
+ if (cwd == NULL)
+ inf->cwd.reset ();
+ else
+ inf->cwd.reset (xstrdup (cwd));
+}
+
+/* See common/common-inferior.h. */
+
+const char *
+get_inferior_cwd ()
+{
+ return current_inferior ()->cwd.get ();
+}
+
+/* Handle the 'set cwd' command. */
+
+static void
+set_cwd_command (const char *args, int from_tty, struct cmd_list_element *c)
+{
+ if (*inferior_cwd_scratch == '\0')
+ set_inferior_cwd (NULL);
+ else
+ set_inferior_cwd (inferior_cwd_scratch);
+}
+
+/* Handle the 'show cwd' command. */
+
+static void
+show_cwd_command (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ const char *cwd = get_inferior_cwd ();
+
+ if (cwd == NULL)
+ fprintf_filtered (gdb_stdout,
+ _("\
+You have not set the inferior's current working directory.\n\
+The inferior will inherit GDB's cwd if native debugging, or the remote\n\
+server's cwd if remote debugging.\n"));
+ else
+ fprintf_filtered (gdb_stdout,
+ _("Current working directory that will be used "
+ "when starting the inferior is \"%s\".\n"), cwd);
+}
+
\f
/* Compute command-line string given argument vector. This does the
same shell processing as fork_inferior. */
NULL is returned. *BG_CHAR_P is an output boolean that indicates
whether the '&' character was found. */
-static char *
+static gdb::unique_xmalloc_ptr<char>
strip_bg_char (const char *args, int *bg_char_p)
{
const char *p;
*bg_char_p = 1;
if (p != args)
- return savestring (args, p - args);
+ return gdb::unique_xmalloc_ptr<char>
+ (savestring (args, p - args));
else
- return NULL;
+ return gdb::unique_xmalloc_ptr<char> (nullptr);
}
*bg_char_p = 0;
- return xstrdup (args);
+ return gdb::unique_xmalloc_ptr<char> (xstrdup (args));
}
/* Common actions to take after creating any sort of inferior, by any
{
/* Be sure we own the terminal in case write operations are performed. */
- target_terminal_ours_for_output ();
+ target_terminal::ours_for_output ();
/* If the target hasn't taken care of this already, do it now.
Targets which need to access registers during to_open,
requested by RUN_HOW. */
static void
-run_command_1 (char *args, int from_tty, enum run_how run_how)
+run_command_1 (const char *args, int from_tty, enum run_how run_how)
{
const char *exec_file;
struct cleanup *old_chain;
struct ui_out *uiout = current_uiout;
struct target_ops *run_target;
int async_exec;
- struct cleanup *args_chain;
CORE_ADDR pc;
dont_repeat ();
reopen_exec_file ();
reread_symbols ();
- args = strip_bg_char (args, &async_exec);
- args_chain = make_cleanup (xfree, args);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec);
+ args = stripped.get ();
/* Do validation and preparation before possibly changing anything
in the inferior. */
uiout->flush ();
}
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
/* We call get_inferior_args() because we might need to compute
the value now. */
run_target->to_create_inferior (run_target, exec_file,
}
static void
-run_command (char *args, int from_tty)
+run_command (const char *args, int from_tty)
{
run_command_1 (args, from_tty, RUN_NORMAL);
}
program. */
static void
-start_command (char *args, int from_tty)
+start_command (const char *args, int from_tty)
{
/* Some languages such as Ada need to search inside the program
minimal symbols for the location where to put the temporary
instruction. */
static void
-starti_command (char *args, int from_tty)
+starti_command (const char *args, int from_tty)
{
run_command_1 (args, from_tty, RUN_STOP_AT_FIRST_INSN);
}
Continuing.
<no thread was resumed, but the inferior now owns the terminal>
*/
- target_terminal_inferior ();
+ target_terminal::inferior ();
}
}
else
/* continue [-a] [proceed-count] [&] */
static void
-continue_command (char *args, int from_tty)
+continue_command (const char *args, int from_tty)
{
int async_exec;
int all_threads = 0;
- struct cleanup *args_chain;
ERROR_NO_INFERIOR;
/* Find out whether we must run in the background. */
- args = strip_bg_char (args, &async_exec);
- args_chain = make_cleanup (xfree, args);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec);
+ args = stripped.get ();
if (args != NULL)
{
}
}
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
/* Step until outside of current statement. */
static void
-step_command (char *count_string, int from_tty)
+step_command (const char *count_string, int from_tty)
{
step_1 (0, 0, count_string);
}
/* Likewise, but skip over subroutine calls as if single instructions. */
static void
-next_command (char *count_string, int from_tty)
+next_command (const char *count_string, int from_tty)
{
step_1 (1, 0, count_string);
}
/* Likewise, but step only one instruction. */
static void
-stepi_command (char *count_string, int from_tty)
+stepi_command (const char *count_string, int from_tty)
{
step_1 (0, 1, count_string);
}
static void
-nexti_command (char *count_string, int from_tty)
+nexti_command (const char *count_string, int from_tty)
{
step_1 (1, 1, count_string);
}
static int prepare_one_step (struct step_command_fsm *sm);
static void
-step_1 (int skip_subroutines, int single_inst, char *count_string)
+step_1 (int skip_subroutines, int single_inst, const char *count_string)
{
int count;
int async_exec;
- struct cleanup *args_chain;
struct thread_info *thr;
struct step_command_fsm *step_sm;
ensure_valid_thread ();
ensure_not_running ();
- count_string = strip_bg_char (count_string, &async_exec);
- args_chain = make_cleanup (xfree, count_string);
+ gdb::unique_xmalloc_ptr<char> stripped
+ = strip_bg_char (count_string, &async_exec);
+ count_string = stripped.get ();
prepare_execution_command (¤t_target, async_exec);
count = count_string ? parse_and_eval_long (count_string) : 1;
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
clear_proceed_status (1);
/* Setup the execution command state machine to handle all the COUNT
&tp->control.step_range_end) == 0)
error (_("Cannot find bounds of current function"));
- target_terminal_ours_for_output ();
+ target_terminal::ours_for_output ();
printf_filtered (_("Single stepping until exit from function %s,"
"\nwhich has no line number information.\n"),
name);
/* Continue program at specified address. */
static void
-jump_command (char *arg, int from_tty)
+jump_command (const char *arg, int from_tty)
{
struct gdbarch *gdbarch = get_current_arch ();
CORE_ADDR addr;
struct symbol *fn;
struct symbol *sfn;
int async_exec;
- struct cleanup *args_chain;
ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
ensure_not_running ();
/* Find out whether we must run in the background. */
- arg = strip_bg_char (arg, &async_exec);
- args_chain = make_cleanup (xfree, arg);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
+ arg = stripped.get ();
prepare_execution_command (¤t_target, async_exec);
if (sals.size () != 1)
error (_("Unreasonable jump request"));
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
symtab_and_line &sal = sals[0];
if (sal.symtab == 0 && sal.pc == 0)
/* Continue program giving it specified signal. */
static void
-signal_command (char *signum_exp, int from_tty)
+signal_command (const char *signum_exp, int from_tty)
{
enum gdb_signal oursig;
int async_exec;
- struct cleanup *args_chain;
dont_repeat (); /* Too dangerous. */
ERROR_NO_INFERIOR;
ensure_not_running ();
/* Find out whether we must run in the background. */
- signum_exp = strip_bg_char (signum_exp, &async_exec);
- args_chain = make_cleanup (xfree, signum_exp);
+ gdb::unique_xmalloc_ptr<char> stripped
+ = strip_bg_char (signum_exp, &async_exec);
+ signum_exp = stripped.get ();
prepare_execution_command (¤t_target, async_exec);
oursig = gdb_signal_from_command (num);
}
- do_cleanups (args_chain);
-
/* Look for threads other than the current that this command ends up
resuming too (due to schedlock off), and warn if they'll get a
signal delivered. "signal 0" is used to suppress a previous
/* Queue a signal to be delivered to the current thread. */
static void
-queue_signal_command (char *signum_exp, int from_tty)
+queue_signal_command (const char *signum_exp, int from_tty)
{
enum gdb_signal oursig;
struct thread_info *tp;
}
static void
-until_command (char *arg, int from_tty)
+until_command (const char *arg, int from_tty)
{
int async_exec;
- struct cleanup *args_chain;
ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
ensure_not_running ();
/* Find out whether we must run in the background. */
- arg = strip_bg_char (arg, &async_exec);
- args_chain = make_cleanup (xfree, arg);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
+ arg = stripped.get ();
prepare_execution_command (¤t_target, async_exec);
until_break_command (arg, from_tty, 0);
else
until_next_command (from_tty);
-
- /* Done with ARGS. */
- do_cleanups (args_chain);
}
static void
-advance_command (char *arg, int from_tty)
+advance_command (const char *arg, int from_tty)
{
int async_exec;
- struct cleanup *args_chain;
ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
error_no_arg (_("a location"));
/* Find out whether we must run in the background. */
- arg = strip_bg_char (arg, &async_exec);
- args_chain = make_cleanup (xfree, arg);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
+ arg = stripped.get ();
prepare_execution_command (¤t_target, async_exec);
until_break_command (arg, from_tty, 1);
-
- /* Done with ARGS. */
- do_cleanups (args_chain);
}
\f
/* Return the value of the result of a function at the end of a 'finish'
sm->breakpoint = set_momentary_breakpoint (gdbarch, sal,
get_stack_frame_id (frame),
- bp_finish);
+ bp_finish).release ();
/* set_momentary_breakpoint invalidates FRAME. */
frame = NULL;
frame will return to, then continue. */
static void
-finish_command (char *arg, int from_tty)
+finish_command (const char *arg, int from_tty)
{
struct frame_info *frame;
int async_exec;
- struct cleanup *args_chain;
struct finish_command_fsm *sm;
struct thread_info *tp;
ensure_not_running ();
/* Find out whether we must run in the background. */
- arg = strip_bg_char (arg, &async_exec);
- args_chain = make_cleanup (xfree, arg);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
+ arg = stripped.get ();
prepare_execution_command (¤t_target, async_exec);
if (arg)
error (_("The \"finish\" command does not take any arguments."));
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
frame = get_prev_frame (get_selected_frame (_("No selected frame.")));
if (frame == 0)
error (_("\"finish\" not meaningful in the outermost frame."));
\f
static void
-info_program_command (char *args, int from_tty)
+info_program_command (const char *args, int from_tty)
{
bpstat bs;
int num, stat;
}
\f
static void
-environment_info (char *var, int from_tty)
+environment_info (const char *var, int from_tty)
{
if (var)
{
}
static void
-set_environment_command (char *arg, int from_tty)
+set_environment_command (const char *arg, int from_tty)
{
- char *p, *val, *var;
+ const char *p, *val;
int nullset = 0;
if (arg == 0)
while (p != arg && (p[-1] == ' ' || p[-1] == '\t'))
p--;
- var = savestring (arg, p - arg);
+ std::string var (arg, p - arg);
if (nullset)
{
printf_filtered (_("Setting environment variable "
"\"%s\" to null value.\n"),
- var);
- current_inferior ()->environment.set (var, "");
+ var.c_str ());
+ current_inferior ()->environment.set (var.c_str (), "");
}
else
- current_inferior ()->environment.set (var, val);
- xfree (var);
+ current_inferior ()->environment.set (var.c_str (), val);
}
static void
-unset_environment_command (char *var, int from_tty)
+unset_environment_command (const char *var, int from_tty)
{
if (var == 0)
{
static const char path_var_name[] = "PATH";
static void
-path_info (char *args, int from_tty)
+path_info (const char *args, int from_tty)
{
puts_filtered ("Executable and object file path: ");
puts_filtered (current_inferior ()->environment.get (path_var_name));
/* Add zero or more directories to the front of the execution path. */
static void
-path_command (char *dirname, int from_tty)
+path_command (const char *dirname, int from_tty)
{
char *exec_path;
const char *env;
}
void
-registers_info (char *addr_exp, int fpregs)
+registers_info (const char *addr_exp, int fpregs)
{
struct frame_info *frame;
struct gdbarch *gdbarch;
while (*addr_exp != '\0')
{
- char *start;
+ const char *start;
const char *end;
/* Skip leading white space. */
}
static void
-info_all_registers_command (char *addr_exp, int from_tty)
+info_all_registers_command (const char *addr_exp, int from_tty)
{
registers_info (addr_exp, 1);
}
static void
-info_registers_command (char *addr_exp, int from_tty)
+info_registers_command (const char *addr_exp, int from_tty)
{
registers_info (addr_exp, 0);
}
}
static void
-info_vector_command (char *args, int from_tty)
+info_vector_command (const char *args, int from_tty)
{
if (!target_has_registers)
error (_("The program has no registers now."));
/* Kill the inferior process. Make us have no inferior. */
static void
-kill_command (char *arg, int from_tty)
+kill_command (const char *arg, int from_tty)
{
/* FIXME: This should not really be inferior_ptid (or target_has_execution).
It should be a distinct flag that indicates that a target is active, cuz
and allows us to start debugging it. */
void
-attach_command (char *args, int from_tty)
+attach_command (const char *args, int from_tty)
{
int async_exec;
- struct cleanup *args_chain;
struct target_ops *attach_target;
struct inferior *inferior = current_inferior ();
enum attach_post_wait_mode mode;
this function should probably be moved into target_pre_inferior. */
target_pre_inferior (from_tty);
- args = strip_bg_char (args, &async_exec);
- args_chain = make_cleanup (xfree, args);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec);
+ args = stripped.get ();
attach_target = find_attach_target ();
/* Set up the "saved terminal modes" of the inferior
based on what modes we are starting it with. */
- target_terminal_init ();
+ target_terminal::init ();
/* Install inferior's terminal modes. This may look like a no-op,
as we've just saved them above, however, this does more than
while we're in the event loop waiting for that stop. That is,
before the attach continuation runs and the command is really
finished. */
- target_terminal_inferior ();
+ target_terminal::inferior ();
/* Set up execution context to know that we should return from
wait_for_inferior as soon as the target reports a stop. */
a->mode = mode;
add_inferior_continuation (attach_command_continuation, a,
attach_command_continuation_free_args);
- /* Done with ARGS. */
- do_cleanups (args_chain);
if (!target_is_async_p ())
mark_infrun_async_event_handler ();
return;
}
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
attach_post_wait (args, from_tty, mode);
}
*/
void
-detach_command (char *args, int from_tty)
+detach_command (const char *args, int from_tty)
{
dont_repeat (); /* Not for the faint of heart. */
stopped processes on some native platforms (e.g. GNU/Linux). */
static void
-disconnect_command (char *args, int from_tty)
+disconnect_command (const char *args, int from_tty)
{
dont_repeat (); /* Not for the faint of heart. */
query_if_trace_running (from_tty);
if the `-a' switch is used. */
static void
-interrupt_command (char *args, int from_tty)
+interrupt_command (const char *args, int from_tty)
{
if (target_can_async_p ())
{
}
static void
-info_float_command (char *args, int from_tty)
+info_float_command (const char *args, int from_tty)
{
struct frame_info *frame;
}
\f
static void
-unset_command (char *args, int from_tty)
+unset_command (const char *args, int from_tty)
{
printf_filtered (_("\"unset\" must be followed by the "
"name of an unset subcommand.\n"));
/* Implement `info proc' family of commands. */
static void
-info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty)
+info_proc_cmd_1 (const char *args, enum info_proc_what what, int from_tty)
{
struct gdbarch *gdbarch = get_current_arch ();
/* Implement `info proc' when given without any futher parameters. */
static void
-info_proc_cmd (char *args, int from_tty)
+info_proc_cmd (const char *args, int from_tty)
{
info_proc_cmd_1 (args, IP_MINIMAL, from_tty);
}
/* Implement `info proc mappings'. */
static void
-info_proc_cmd_mappings (char *args, int from_tty)
+info_proc_cmd_mappings (const char *args, int from_tty)
{
info_proc_cmd_1 (args, IP_MAPPINGS, from_tty);
}
/* Implement `info proc stat'. */
static void
-info_proc_cmd_stat (char *args, int from_tty)
+info_proc_cmd_stat (const char *args, int from_tty)
{
info_proc_cmd_1 (args, IP_STAT, from_tty);
}
/* Implement `info proc status'. */
static void
-info_proc_cmd_status (char *args, int from_tty)
+info_proc_cmd_status (const char *args, int from_tty)
{
info_proc_cmd_1 (args, IP_STATUS, from_tty);
}
/* Implement `info proc cwd'. */
static void
-info_proc_cmd_cwd (char *args, int from_tty)
+info_proc_cmd_cwd (const char *args, int from_tty)
{
info_proc_cmd_1 (args, IP_CWD, from_tty);
}
/* Implement `info proc cmdline'. */
static void
-info_proc_cmd_cmdline (char *args, int from_tty)
+info_proc_cmd_cmdline (const char *args, int from_tty)
{
info_proc_cmd_1 (args, IP_CMDLINE, from_tty);
}
/* Implement `info proc exe'. */
static void
-info_proc_cmd_exe (char *args, int from_tty)
+info_proc_cmd_exe (const char *args, int from_tty)
{
info_proc_cmd_1 (args, IP_EXE, from_tty);
}
/* Implement `info proc all'. */
static void
-info_proc_cmd_all (char *args, int from_tty)
+info_proc_cmd_all (const char *args, int from_tty)
{
info_proc_cmd_1 (args, IP_ALL, from_tty);
}
gdb_assert (c != NULL);
set_cmd_completer (c, filename_completer);
+ cmd_name = "cwd";
+ add_setshow_string_noescape_cmd (cmd_name, class_run,
+ &inferior_cwd_scratch, _("\
+Set the current working directory to be used when the inferior is started.\n\
+Changing this setting does not have any effect on inferiors that are\n\
+already running."),
+ _("\
+Show the current working directory that is used when the inferior is started."),
+ _("\
+Use this command to change the current working directory that will be used\n\
+when the inferior is started. This setting does not affect GDB's current\n\
+working directory."),
+ set_cwd_command,
+ show_cwd_command,
+ &setlist, &showlist);
+ c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+ gdb_assert (c != NULL);
+ set_cmd_completer (c, filename_completer);
+
c = add_cmd ("environment", no_class, environment_info, _("\
The environment to give the program, or one variable's value.\n\
With an argument VAR, prints the value of environment variable VAR to\n\