/* Top level stuff for GDB, the GNU debugger.
- Copyright (C) 1986-2015 Free Software Foundation, Inc.
+ Copyright (C) 1986-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "value.h"
#include "language.h"
#include "terminal.h" /* For job_control. */
+#include "job-control.h"
#include "annotate.h"
#include "completer.h"
#include "top.h"
#include "version.h"
#include "serial.h"
-#include "doublest.h"
#include "main.h"
#include "event-loop.h"
#include "gdbthread.h"
#include "extension.h"
#include "interps.h"
-#include "observer.h"
+#include "observable.h"
#include "maint.h"
#include "filenames.h"
+#include "frame.h"
+#include "buffer.h"
+#include "gdb_select.h"
/* readline include files. */
#include "readline/readline.h"
#include "tracepoint.h"
#include "inf-loop.h"
+#if defined(TUI)
+# include "tui/tui.h"
+#endif
+
+#ifndef O_NOCTTY
+# define O_NOCTTY 0
+#endif
+
extern void initialize_all_files (void);
#define PROMPT(X) the_prompts.prompt_stack[the_prompts.top + X].prompt
#define DEFAULT_PROMPT "(gdb) "
#endif
+/* Generate a function that exports a pointer to a field of the
+ current UI. */
+
+#define gen_ret_current_ui_field_ptr(type, name) \
+type * \
+current_ui_## name ## _ptr (void) \
+{ \
+ return ¤t_ui->m_ ## name; \
+}
+
+gen_ret_current_ui_field_ptr (struct ui_file *, gdb_stdout)
+gen_ret_current_ui_field_ptr (struct ui_file *, gdb_stdin)
+gen_ret_current_ui_field_ptr (struct ui_file *, gdb_stderr)
+gen_ret_current_ui_field_ptr (struct ui_file *, gdb_stdlog)
+gen_ret_current_ui_field_ptr (struct ui_out *, current_uiout)
+
/* Initialization file name for gdb. This is host-dependent. */
const char gdbinit[] = GDBINIT;
value);
}
-/* stdio stream that command input is being read from. Set to stdin
- normally. Set by source_command to the file we are sourcing. Set
- to NULL if we are executing a user-defined command or interacting
- via a GUI. */
-
-FILE *instream;
-
-/* Flag to indicate whether a user defined command is currently running. */
-
-int in_user_command;
-
/* Current working directory. */
char *current_directory;
-/* The directory name is actually stored here (usually). */
-char gdb_dirbuf[1024];
-
-/* Function to call before reading a command, if nonzero.
- The function receives two args: an input stream,
- and a prompt string. */
-
-void (*window_hook) (FILE *, char *);
-
-/* Buffer used for reading command lines, and the size
- allocated for it so far. */
-
+/* The last command line executed on the console. Used for command
+ repetitions. */
char *saved_command_line;
-int saved_command_line_size = 100;
/* Nonzero if the current command is modified by "server ". This
affects things like recording into the command history, commands
/* Hooks for alternate command interfaces. */
-/* Called after most modules have been initialized, but before taking
- users command file.
-
- If the UI fails to initialize and it wants GDB to continue using
- the default UI, then it should clear this hook before returning. */
-
-void (*deprecated_init_ui_hook) (char *argv0);
-
/* This hook is called from within gdb's many mini-event loops which
could steal control from a real user interface's event loop. It
returns non-zero if the user is requesting a detach, zero
called to notify the GUI that we are done with the interaction
window and it can close it. */
-void (*deprecated_readline_begin_hook) (char *, ...);
+void (*deprecated_readline_begin_hook) (const char *, ...);
char *(*deprecated_readline_hook) (const char *);
void (*deprecated_readline_end_hook) (void);
void (*deprecated_interactive_hook) (void);
-/* Tell the GUI someone changed the register REGNO. -1 means
- that the caller does not know which register changed or
- that several registers have changed (see value_assign). */
-void (*deprecated_register_changed_hook) (int regno);
-
/* Called when going to wait for the target. Usually allows the GUI
to run while waiting for target events. */
things like enabling/disabling buttons, etc... */
void (*deprecated_call_command_hook) (struct cmd_list_element * c,
- char *cmd, int from_tty);
+ const char *cmd, int from_tty);
/* Called when the current thread changes. Argument is thread id. */
void (*deprecated_context_hook) (int id);
+/* The highest UI number ever assigned. */
+static int highest_ui_num;
+
+/* See top.h. */
+
+ui::ui (FILE *instream_, FILE *outstream_, FILE *errstream_)
+ : next (nullptr),
+ num (++highest_ui_num),
+ call_readline (nullptr),
+ input_handler (nullptr),
+ command_editing (0),
+ interp_info (nullptr),
+ async (0),
+ secondary_prompt_depth (0),
+ stdin_stream (instream_),
+ instream (instream_),
+ outstream (outstream_),
+ errstream (errstream_),
+ input_fd (fileno (instream)),
+ input_interactive_p (ISATTY (instream)),
+ prompt_state (PROMPT_NEEDED),
+ m_gdb_stdout (new stdio_file (outstream)),
+ m_gdb_stdin (new stdio_file (instream)),
+ m_gdb_stderr (new stderr_file (errstream)),
+ m_gdb_stdlog (m_gdb_stderr),
+ m_current_uiout (nullptr)
+{
+ buffer_init (&line_buffer);
+
+ if (ui_list == NULL)
+ ui_list = this;
+ else
+ {
+ struct ui *last;
+
+ for (last = ui_list; last->next != NULL; last = last->next)
+ ;
+ last->next = this;
+ }
+}
+
+ui::~ui ()
+{
+ struct ui *ui, *uiprev;
+
+ uiprev = NULL;
+
+ for (ui = ui_list; ui != NULL; uiprev = ui, ui = ui->next)
+ if (ui == this)
+ break;
+
+ gdb_assert (ui != NULL);
+
+ if (uiprev != NULL)
+ uiprev->next = next;
+ else
+ ui_list = next;
+
+ delete m_gdb_stdin;
+ delete m_gdb_stdout;
+ delete m_gdb_stderr;
+}
+
+/* Open file named NAME for read/write, making sure not to make it the
+ controlling terminal. */
+
+static gdb_file_up
+open_terminal_stream (const char *name)
+{
+ int fd;
+
+ fd = gdb_open_cloexec (name, O_RDWR | O_NOCTTY, 0);
+ if (fd < 0)
+ perror_with_name (_("opening terminal failed"));
+
+ return gdb_file_up (fdopen (fd, "w+"));
+}
+
+/* Implementation of the "new-ui" command. */
+
+static void
+new_ui_command (const char *args, int from_tty)
+{
+ gdb_file_up stream[3];
+ int i;
+ int argc;
+ const char *interpreter_name;
+ const char *tty_name;
+
+ dont_repeat ();
+
+ gdb_argv argv (args);
+ argc = argv.count ();
+
+ if (argc < 2)
+ error (_("usage: new-ui <interpreter> <tty>"));
+
+ interpreter_name = argv[0];
+ tty_name = argv[1];
+
+ {
+ scoped_restore save_ui = make_scoped_restore (¤t_ui);
+
+ /* Open specified terminal, once for each of
+ stdin/stdout/stderr. */
+ for (i = 0; i < 3; i++)
+ stream[i] = open_terminal_stream (tty_name);
+
+ std::unique_ptr<ui> ui
+ (new struct ui (stream[0].get (), stream[1].get (), stream[2].get ()));
+
+ ui->async = 1;
+
+ current_ui = ui.get ();
+
+ set_top_level_interpreter (interpreter_name);
+
+ interp_pre_command_loop (top_level_interpreter ());
+
+ /* Make sure the files are not closed. */
+ stream[0].release ();
+ stream[1].release ();
+ stream[2].release ();
+
+ ui.release ();
+ }
+
+ printf_unfiltered ("New UI allocated\n");
+}
+
/* Handler for SIGHUP. */
#ifdef SIGHUP
event-top.c into this file, top.c. */
/* static */ const char *source_file_name;
-/* Clean up on error during a "source" command (or execution of a
- user-defined command). */
-
-void
-do_restore_instream_cleanup (void *stream)
-{
- /* Restore the previous input stream. */
- instream = stream;
-}
-
/* Read commands from STREAM. */
void
read_command_file (FILE *stream)
{
- struct cleanup *cleanups;
+ struct ui *ui = current_ui;
- cleanups = make_cleanup (do_restore_instream_cleanup, instream);
- instream = stream;
- command_loop ();
- do_cleanups (cleanups);
+ scoped_restore save_instream
+ = make_scoped_restore (&ui->instream, stream);
+
+ /* Read commands from `instream' and execute them until end of file
+ or error reading instream. */
+
+ while (ui->instream != NULL && !feof (ui->instream))
+ {
+ char *command;
+
+ /* Get a command-line. This calls the readline package. */
+ command = command_line_input (NULL, 0, NULL);
+ if (command == NULL)
+ break;
+ command_handler (command);
+ }
}
\f
void (*pre_init_ui_hook) (void);
static void
do_chdir_cleanup (void *old_dir)
{
- chdir (old_dir);
+ chdir ((const char *) old_dir);
xfree (old_dir);
}
#endif
-struct cleanup *
-prepare_execute_command (void)
+scoped_value_mark
+prepare_execute_command ()
{
- struct value *mark;
- struct cleanup *cleanup;
-
- mark = value_mark ();
- cleanup = make_cleanup_value_free_to_mark (mark);
-
/* With multiple threads running while the one we're examining is
stopped, the dcache can get stale without us being able to detect
it. For the duration of the command, though, use the dcache to
if (non_stop)
target_dcache_invalidate ();
- return cleanup;
+ return scoped_value_mark ();
}
/* Tell the user if the language has changed (except first time) after
check_frame_language_change (void)
{
static int warned = 0;
+ struct frame_info *frame;
/* First make sure that a new frame has been selected, in case the
command or the hooks changed the program state. */
- deprecated_safe_get_selected_frame ();
+ frame = deprecated_safe_get_selected_frame ();
if (current_language != expected_language)
{
if (language_mode == language_mode_auto && info_verbose)
{
enum language flang;
- flang = get_frame_language ();
+ flang = get_frame_language (frame);
if (!warned
&& flang != language_unknown
&& flang != current_language->la_language)
/* See top.h. */
+void
+wait_sync_command_done (void)
+{
+ /* Processing events may change the current UI. */
+ scoped_restore save_ui = make_scoped_restore (¤t_ui);
+ struct ui *ui = current_ui;
+
+ while (gdb_do_one_event () >= 0)
+ if (ui->prompt_state != PROMPT_BLOCKED)
+ break;
+}
+
+/* See top.h. */
+
void
maybe_wait_sync_command_done (int was_sync)
{
command's list, running command hooks or similars), and we
just ran a synchronous command that started the target, wait
for that command to end. */
- if (!interpreter_async && !was_sync && sync_execution)
- {
- while (gdb_do_one_event () >= 0)
- if (!sync_execution)
- break;
- }
+ if (!current_ui->async
+ && !was_sync
+ && current_ui->prompt_state == PROMPT_BLOCKED)
+ wait_sync_command_done ();
+}
+
+/* If not NULL, the arguments that should be passed if the current
+ command is repeated. */
+
+static const char *repeat_arguments;
+
+/* See command.h. */
+
+void
+set_repeat_arguments (const char *args)
+{
+ repeat_arguments = args;
}
/* Execute the line P as a command, in the current user context.
Pass FROM_TTY as second argument to the defining function. */
void
-execute_command (char *p, int from_tty)
+execute_command (const char *p, int from_tty)
{
- struct cleanup *cleanup_if_error, *cleanup;
+ struct cleanup *cleanup_if_error;
struct cmd_list_element *c;
- char *line;
+ const char *line;
+ const char *cmd_start = p;
cleanup_if_error = make_bpstat_clear_actions_cleanup ();
- cleanup = prepare_execute_command ();
+ scoped_value_mark cleanup = prepare_execute_command ();
/* Force cleanup of any alloca areas if using C alloca instead of
a builtin alloca. */
/* This can happen when command_line_input hits end of file. */
if (p == NULL)
{
- do_cleanups (cleanup);
discard_cleanups (cleanup_if_error);
return;
}
if (*p)
{
const char *cmd = p;
- char *arg;
- int was_sync = sync_execution;
+ const char *arg;
+ int was_sync = current_ui->prompt_state == PROMPT_BLOCKED;
line = p;
print_command_trace (p);
c = lookup_cmd (&cmd, cmdlist, "", 0, 1);
- p = (char *) cmd;
+ p = cmd;
+
+ scoped_restore save_repeat_args
+ = make_scoped_restore (&repeat_arguments, nullptr);
+ const char *args_pointer = p;
/* Pass null arg rather than an empty one. */
arg = *p ? p : 0;
is_complete_command hack is testing for. */
/* Clear off trailing whitespace, except for set and complete
command. */
+ std::string without_whitespace;
if (arg
&& c->type != set_cmd
&& !is_complete_command (c))
{
- p = arg + strlen (arg) - 1;
+ const char *old_end = arg + strlen (arg) - 1;
+ p = old_end;
while (p >= arg && (*p == ' ' || *p == '\t'))
p--;
- *(p + 1) = '\0';
+ if (p != old_end)
+ {
+ without_whitespace = std::string (arg, p + 1);
+ arg = without_whitespace.c_str ();
+ }
}
/* If this command has been pre-hooked, run the hook first. */
/* If this command has been post-hooked, run the hook last. */
execute_cmd_post_hook (c);
+ if (repeat_arguments != NULL && cmd_start == saved_command_line)
+ {
+ gdb_assert (strlen (args_pointer) >= strlen (repeat_arguments));
+ strcpy (saved_command_line + (args_pointer - cmd_start),
+ repeat_arguments);
+ }
}
check_frame_language_change ();
- do_cleanups (cleanup);
discard_cleanups (cleanup_if_error);
}
returned string, do not display it to the screen. BATCH_FLAG will be
temporarily set to true. */
-char *
-execute_command_to_string (char *p, int from_tty)
+std::string
+execute_command_to_string (const char *p, int from_tty)
{
- struct ui_file *str_file;
- struct cleanup *cleanup;
- char *retval;
-
/* GDB_STDOUT should be better already restored during these
restoration callbacks. */
- cleanup = set_batch_flag_and_make_cleanup_restore_page_info ();
-
- make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
-
- str_file = mem_fileopen ();
-
- make_cleanup_ui_file_delete (str_file);
- make_cleanup_restore_ui_file (&gdb_stdout);
- make_cleanup_restore_ui_file (&gdb_stderr);
- make_cleanup_restore_ui_file (&gdb_stdlog);
- make_cleanup_restore_ui_file (&gdb_stdtarg);
- make_cleanup_restore_ui_file (&gdb_stdtargerr);
-
- if (ui_out_redirect (current_uiout, str_file) < 0)
- warning (_("Current output protocol does not support redirection"));
- else
- make_cleanup_ui_out_redirect_pop (current_uiout);
-
- gdb_stdout = str_file;
- gdb_stderr = str_file;
- gdb_stdlog = str_file;
- gdb_stdtarg = str_file;
- gdb_stdtargerr = str_file;
+ set_batch_flag_and_restore_page_info save_page_info;
- execute_command (p, from_tty);
+ scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0);
- retval = ui_file_xstrdup (str_file, NULL);
+ string_file str_file;
- do_cleanups (cleanup);
-
- return retval;
+ {
+ current_uiout->redirect (&str_file);
+ ui_out_redirect_pop redirect_popper (current_uiout);
+
+ scoped_restore save_stdout
+ = make_scoped_restore (&gdb_stdout, &str_file);
+ scoped_restore save_stderr
+ = make_scoped_restore (&gdb_stderr, &str_file);
+ scoped_restore save_stdlog
+ = make_scoped_restore (&gdb_stdlog, &str_file);
+ scoped_restore save_stdtarg
+ = make_scoped_restore (&gdb_stdtarg, &str_file);
+ scoped_restore save_stdtargerr
+ = make_scoped_restore (&gdb_stdtargerr, &str_file);
+
+ execute_command (p, from_tty);
+ }
+
+ return std::move (str_file.string ());
}
-/* Read commands from `instream' and execute them
- until end of file or error reading instream. */
-
-void
-command_loop (void)
-{
- struct cleanup *old_chain;
- char *command;
- int stdin_is_tty = ISATTY (stdin);
-
- while (instream && !feof (instream))
- {
- if (window_hook && instream == stdin)
- (*window_hook) (instream, get_prompt ());
-
- clear_quit_flag ();
- if (instream == stdin && stdin_is_tty)
- reinitialize_more_filter ();
- old_chain = make_cleanup (null_cleanup, 0);
-
- /* Get a command-line. This calls the readline package. */
- command = command_line_input (instream == stdin ?
- get_prompt () : (char *) NULL,
- instream == stdin, "prompt");
- if (command == 0)
- {
- do_cleanups (old_chain);
- return;
- }
-
- make_command_stats_cleanup (1);
-
- /* Do not execute commented lines. */
- if (command[0] != '#')
- {
- execute_command (command, instream == stdin);
-
- /* Do any commands attached to breakpoint we are stopped at. */
- bpstat_do_actions ();
- }
- do_cleanups (old_chain);
- }
-}
\f
/* When nonzero, cause dont_repeat to do nothing. This should only be
set via prevent_dont_repeat. */
void
dont_repeat (void)
{
+ struct ui *ui = current_ui;
+
if (suppress_dont_repeat || server_command)
return;
/* If we aren't reading from standard input, we are saving the last
thing read from stdin in line and don't want to delete it. Null
lines won't repeat here in any case. */
- if (instream == stdin)
+ if (ui->instream == ui->stdin_stream)
*saved_command_line = 0;
}
/* Prevent dont_repeat from working, and return a cleanup that
restores the previous state. */
-struct cleanup *
+scoped_restore_tmpl<int>
prevent_dont_repeat (void)
{
- struct cleanup *result = make_cleanup_restore_integer (&suppress_dont_repeat);
-
- suppress_dont_repeat = 1;
- return result;
+ return make_scoped_restore (&suppress_dont_repeat, 1);
}
\f
/* Read a line from the stream "instream" without command line editing.
- It prints PROMPT_ARG once at the start.
+ It prints PROMPT once at the start.
Action is compatible with "readline", e.g. space for the result is
malloc'd and should be freed by the caller.
A NULL return means end of file. */
-char *
-gdb_readline (const char *prompt_arg)
+
+static char *
+gdb_readline_no_editing (const char *prompt)
{
- int c;
- char *result;
- int input_index = 0;
- int result_size = 80;
+ struct buffer line_buffer;
+ struct ui *ui = current_ui;
+ /* Read from stdin if we are executing a user defined command. This
+ is the right thing for prompt_for_continue, at least. */
+ FILE *stream = ui->instream != NULL ? ui->instream : stdin;
+ int fd = fileno (stream);
+
+ buffer_init (&line_buffer);
- if (prompt_arg)
+ if (prompt != NULL)
{
/* Don't use a _filtered function here. It causes the assumed
character position to be off, since the newline we read from
the user is not accounted for. */
- fputs_unfiltered (prompt_arg, gdb_stdout);
+ fputs_unfiltered (prompt, gdb_stdout);
gdb_flush (gdb_stdout);
}
- result = (char *) xmalloc (result_size);
-
while (1)
{
- /* Read from stdin if we are executing a user defined command.
- This is the right thing for prompt_for_continue, at least. */
- c = fgetc (instream ? instream : stdin);
+ int c;
+ fd_set readfds;
+
+ QUIT;
+
+ /* Wait until at least one byte of data is available. Control-C
+ can interrupt interruptible_select, but not fgetc. */
+ FD_ZERO (&readfds);
+ FD_SET (fd, &readfds);
+ if (interruptible_select (fd + 1, &readfds, NULL, NULL, NULL) == -1)
+ {
+ if (errno == EINTR)
+ {
+ /* If this was ctrl-c, the QUIT above handles it. */
+ continue;
+ }
+ perror_with_name (("select"));
+ }
+
+ c = fgetc (stream);
if (c == EOF)
{
- if (input_index > 0)
+ if (line_buffer.used_size > 0)
/* The last line does not end with a newline. Return it, and
if we are called again fgetc will still return EOF and
we'll return NULL then. */
break;
- xfree (result);
+ xfree (buffer_finish (&line_buffer));
return NULL;
}
if (c == '\n')
{
- if (input_index > 0 && result[input_index - 1] == '\r')
- input_index--;
+ if (line_buffer.used_size > 0
+ && line_buffer.buffer[line_buffer.used_size - 1] == '\r')
+ line_buffer.used_size--;
break;
}
- result[input_index++] = c;
- while (input_index >= result_size)
- {
- result_size *= 2;
- result = (char *) xrealloc (result, result_size);
- }
+ buffer_grow_char (&line_buffer, c);
}
- result[input_index++] = '\0';
- return result;
+ buffer_grow_char (&line_buffer, '\0');
+ return buffer_finish (&line_buffer);
}
/* Variables which control command line editing and history
}
/* The variable associated with the "set/show history size"
- command. */
-static unsigned int history_size_setshow_var;
+ command. The value -1 means unlimited, and -2 means undefined. */
+static int history_size_setshow_var = -2;
static void
show_history_size (struct ui_file *file, int from_tty,
value);
}
+/* Variable associated with the "history remove-duplicates" option.
+ The value -1 means unlimited. */
+static int history_remove_duplicates = 0;
+
+static void
+show_history_remove_duplicates (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file,
+ _("The number of history entries to look back at for "
+ "duplicates is %s.\n"),
+ value);
+}
+
static char *history_filename;
static void
show_history_filename (struct ui_file *file, int from_tty,
return. */
static void (*saved_after_char_processing_hook) (void);
+
+/* See top.h. */
+
+int
+gdb_in_secondary_prompt_p (struct ui *ui)
+{
+ return ui->secondary_prompt_depth > 0;
+}
+
+
/* This function is called when readline has seen a complete line of
text. */
we're handling an asynchronous target event and running in the
background, just before returning to the event loop to process
further input (or more target events). */
- if (async_command_editing_p)
+ if (current_ui->command_editing)
gdb_rl_callback_handler_remove ();
}
-struct gdb_readline_wrapper_cleanup
+class gdb_readline_wrapper_cleanup
+{
+public:
+ gdb_readline_wrapper_cleanup ()
+ : m_handler_orig (current_ui->input_handler),
+ m_already_prompted_orig (current_ui->command_editing
+ ? rl_already_prompted : 0),
+ m_target_is_async_orig (target_is_async_p ()),
+ m_save_ui (¤t_ui)
{
- void (*handler_orig) (char *);
- int already_prompted_orig;
+ current_ui->input_handler = gdb_readline_wrapper_line;
+ current_ui->secondary_prompt_depth++;
- /* Whether the target was async. */
- int target_is_async_orig;
- };
+ if (m_target_is_async_orig)
+ target_async (0);
+ }
-static void
-gdb_readline_wrapper_cleanup (void *arg)
-{
- struct gdb_readline_wrapper_cleanup *cleanup = arg;
+ ~gdb_readline_wrapper_cleanup ()
+ {
+ struct ui *ui = current_ui;
- rl_already_prompted = cleanup->already_prompted_orig;
+ if (ui->command_editing)
+ rl_already_prompted = m_already_prompted_orig;
- gdb_assert (input_handler == gdb_readline_wrapper_line);
- input_handler = cleanup->handler_orig;
+ gdb_assert (ui->input_handler == gdb_readline_wrapper_line);
+ ui->input_handler = m_handler_orig;
- /* Don't restore our input handler in readline yet. That would make
- readline prep the terminal (putting it in raw mode), while the
- line we just read may trigger execution of a command that expects
- the terminal in the default cooked/canonical mode, such as e.g.,
- running Python's interactive online help utility. See
- gdb_readline_wrapper_line for when we'll reinstall it. */
+ /* Don't restore our input handler in readline yet. That would make
+ readline prep the terminal (putting it in raw mode), while the
+ line we just read may trigger execution of a command that expects
+ the terminal in the default cooked/canonical mode, such as e.g.,
+ running Python's interactive online help utility. See
+ gdb_readline_wrapper_line for when we'll reinstall it. */
- gdb_readline_wrapper_result = NULL;
- gdb_readline_wrapper_done = 0;
+ gdb_readline_wrapper_result = NULL;
+ gdb_readline_wrapper_done = 0;
+ ui->secondary_prompt_depth--;
+ gdb_assert (ui->secondary_prompt_depth >= 0);
- after_char_processing_hook = saved_after_char_processing_hook;
- saved_after_char_processing_hook = NULL;
+ after_char_processing_hook = saved_after_char_processing_hook;
+ saved_after_char_processing_hook = NULL;
- if (cleanup->target_is_async_orig)
- target_async (1);
+ if (m_target_is_async_orig)
+ target_async (1);
+ }
- xfree (cleanup);
-}
+ DISABLE_COPY_AND_ASSIGN (gdb_readline_wrapper_cleanup);
-char *
-gdb_readline_wrapper (const char *prompt)
-{
- struct cleanup *back_to;
- struct gdb_readline_wrapper_cleanup *cleanup;
- char *retval;
+private:
- cleanup = xmalloc (sizeof (*cleanup));
- cleanup->handler_orig = input_handler;
- input_handler = gdb_readline_wrapper_line;
+ void (*m_handler_orig) (char *);
+ int m_already_prompted_orig;
- cleanup->already_prompted_orig = rl_already_prompted;
+ /* Whether the target was async. */
+ int m_target_is_async_orig;
- cleanup->target_is_async_orig = target_is_async_p ();
+ /* Processing events may change the current UI. */
+ scoped_restore_tmpl<struct ui *> m_save_ui;
+};
- back_to = make_cleanup (gdb_readline_wrapper_cleanup, cleanup);
+char *
+gdb_readline_wrapper (const char *prompt)
+{
+ struct ui *ui = current_ui;
- if (cleanup->target_is_async_orig)
- target_async (0);
+ gdb_readline_wrapper_cleanup cleanup;
- /* Display our prompt and prevent double prompt display. */
- display_gdb_prompt (prompt);
- rl_already_prompted = 1;
+ /* Display our prompt and prevent double prompt display. Don't pass
+ down a NULL prompt, since that has special meaning for
+ display_gdb_prompt -- it indicates a request to print the primary
+ prompt, while we want a secondary prompt here. */
+ display_gdb_prompt (prompt != NULL ? prompt : "");
+ if (ui->command_editing)
+ rl_already_prompted = 1;
if (after_char_processing_hook)
(*after_char_processing_hook) ();
if (gdb_readline_wrapper_done)
break;
- retval = gdb_readline_wrapper_result;
- do_cleanups (back_to);
- return retval;
+ return gdb_readline_wrapper_result;
}
\f
void
gdb_add_history (const char *command)
{
- add_history (command);
command_count++;
+
+ if (history_remove_duplicates != 0)
+ {
+ int lookbehind;
+ int lookbehind_threshold;
+
+ /* The lookbehind threshold for finding a duplicate history entry is
+ bounded by command_count because we can't meaningfully delete
+ history entries that are already stored in the history file since
+ the history file is appended to. */
+ if (history_remove_duplicates == -1
+ || history_remove_duplicates > command_count)
+ lookbehind_threshold = command_count;
+ else
+ lookbehind_threshold = history_remove_duplicates;
+
+ using_history ();
+ for (lookbehind = 0; lookbehind < lookbehind_threshold; lookbehind++)
+ {
+ HIST_ENTRY *temp = previous_history ();
+
+ if (temp == NULL)
+ break;
+
+ if (strcmp (temp->line, command) == 0)
+ {
+ HIST_ENTRY *prev = remove_history (where_history ());
+ command_count--;
+ free_history_entry (prev);
+ break;
+ }
+ }
+ using_history ();
+ }
+
+ add_history (command);
}
/* Safely append new history entries to the history file in a corruption-free
gdb_safe_append_history (void)
{
int ret, saved_errno;
- char *local_history_filename;
- struct cleanup *old_chain;
- local_history_filename
- = xstrprintf ("%s-gdb%d~", history_filename, getpid ());
- old_chain = make_cleanup (xfree, local_history_filename);
+ std::string local_history_filename
+ = string_printf ("%s-gdb%ld~", history_filename, (long) getpid ());
- ret = rename (history_filename, local_history_filename);
+ ret = rename (history_filename, local_history_filename.c_str ());
saved_errno = errno;
if (ret < 0 && saved_errno != ENOENT)
{
warning (_("Could not rename %s to %s: %s"),
- history_filename, local_history_filename,
+ history_filename, local_history_filename.c_str (),
safe_strerror (saved_errno));
}
else
to move it back anyway. Otherwise a global history file would
never get created! */
gdb_assert (saved_errno == ENOENT);
- write_history (local_history_filename);
+ write_history (local_history_filename.c_str ());
}
else
{
- append_history (command_count, local_history_filename);
- history_truncate_file (local_history_filename, history_max_entries);
+ append_history (command_count, local_history_filename.c_str ());
+ if (history_is_stifled ())
+ history_truncate_file (local_history_filename.c_str (),
+ history_max_entries);
}
- ret = rename (local_history_filename, history_filename);
+ ret = rename (local_history_filename.c_str (), history_filename);
saved_errno = errno;
if (ret < 0 && saved_errno != EEXIST)
warning (_("Could not rename %s to %s: %s"),
- local_history_filename, history_filename,
+ local_history_filename.c_str (), history_filename,
safe_strerror (saved_errno));
}
-
- do_cleanups (old_chain);
}
-/* Read one line from the command input stream `instream'
- into the local static buffer `linebuffer' (whose current length
- is `linelength').
- The buffer is made bigger as necessary.
- Returns the address of the start of the line.
+/* Read one line from the command input stream `instream' into a local
+ static buffer. The buffer is made bigger as necessary. Returns
+ the address of the start of the line.
NULL is returned for end of file.
- *If* the instream == stdin & stdin is a terminal, the line read
- is copied into the file line saver (global var char *line,
- length linesize) so that it can be duplicated.
+ *If* input is from an interactive stream (stdin), the line read is
+ copied into the global 'saved_command_line' so that it can be
+ repeated.
- This routine either uses fancy command line editing or
- simple input as the user has requested. */
+ This routine either uses fancy command line editing or simple input
+ as the user has requested. */
char *
-command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
+command_line_input (const char *prompt_arg, int repeat,
+ const char *annotation_suffix)
{
- static char *linebuffer = 0;
- static unsigned linelength = 0;
+ static struct buffer cmd_line_buffer;
+ static int cmd_line_buffer_initialized;
+ struct ui *ui = current_ui;
const char *prompt = prompt_arg;
- char *p;
- char *p1;
- char *rl;
- char *nline;
- char got_eof = 0;
+ char *cmd;
+ int from_tty = ui->instream == ui->stdin_stream;
/* The annotation suffix must be non-NULL. */
if (annotation_suffix == NULL)
annotation_suffix = "";
- if (annotation_level > 1 && instream == stdin)
+ if (from_tty && annotation_level > 1)
{
char *local_prompt;
- local_prompt = alloca ((prompt == NULL ? 0 : strlen (prompt))
- + strlen (annotation_suffix) + 40);
+ local_prompt
+ = (char *) alloca ((prompt == NULL ? 0 : strlen (prompt))
+ + strlen (annotation_suffix) + 40);
if (prompt == NULL)
local_prompt[0] = '\0';
else
prompt = local_prompt;
}
- if (linebuffer == 0)
+ if (!cmd_line_buffer_initialized)
{
- linelength = 80;
- linebuffer = (char *) xmalloc (linelength);
+ buffer_init (&cmd_line_buffer);
+ cmd_line_buffer_initialized = 1;
}
- p = linebuffer;
+ /* Starting a new command line. */
+ cmd_line_buffer.used_size = 0;
- /* Control-C quits instantly if typed while in this loop
- since it should not wait until the user types a newline. */
- immediate_quit++;
- QUIT;
-#ifdef STOP_SIGNAL
+#ifdef SIGTSTP
if (job_control)
- signal (STOP_SIGNAL, handle_stop_sig);
+ signal (SIGTSTP, handle_sigtstp);
#endif
while (1)
{
+ char *rl;
+
/* Make sure that all output has been output. Some machines may
let you get away with leaving out some of the gdb_flush, but
not all. */
if (source_file_name != NULL)
++source_line_number;
- if (annotation_level > 1 && instream == stdin)
+ if (from_tty && annotation_level > 1)
{
puts_unfiltered ("\n\032\032pre-");
puts_unfiltered (annotation_suffix);
}
/* Don't use fancy stuff if not talking to stdin. */
- if (deprecated_readline_hook && input_from_terminal_p ())
+ if (deprecated_readline_hook
+ && from_tty
+ && input_interactive_p (current_ui))
{
rl = (*deprecated_readline_hook) (prompt);
}
- else if (command_editing_p && input_from_terminal_p ())
+ else if (command_editing_p
+ && from_tty
+ && input_interactive_p (current_ui))
{
rl = gdb_readline_wrapper (prompt);
}
else
{
- rl = gdb_readline (prompt);
- }
-
- if (annotation_level > 1 && instream == stdin)
- {
- puts_unfiltered ("\n\032\032post-");
- puts_unfiltered (annotation_suffix);
- puts_unfiltered ("\n");
+ rl = gdb_readline_no_editing (prompt);
}
- if (!rl || rl == (char *) EOF)
+ cmd = handle_line_of_input (&cmd_line_buffer, rl,
+ repeat, annotation_suffix);
+ if (cmd == (char *) EOF)
{
- got_eof = 1;
+ cmd = NULL;
break;
}
- if (strlen (rl) + 1 + (p - linebuffer) > linelength)
- {
- linelength = strlen (rl) + 1 + (p - linebuffer);
- nline = (char *) xrealloc (linebuffer, linelength);
- p += nline - linebuffer;
- linebuffer = nline;
- }
- p1 = rl;
- /* Copy line. Don't copy null at end. (Leaves line alone
- if this was just a newline). */
- while (*p1)
- *p++ = *p1++;
-
- xfree (rl); /* Allocated in readline. */
-
- if (p == linebuffer || *(p - 1) != '\\')
+ if (cmd != NULL)
break;
- p--; /* Put on top of '\'. */
+ /* Got partial input. I.e., got a line that ends with a
+ continuation character (backslash). Suppress printing the
+ prompt again. */
prompt = NULL;
}
-#ifdef STOP_SIGNAL
+#ifdef SIGTSTP
if (job_control)
- signal (STOP_SIGNAL, SIG_DFL);
+ signal (SIGTSTP, SIG_DFL);
#endif
- immediate_quit--;
-
- if (got_eof)
- return NULL;
-
-#define SERVER_COMMAND_LENGTH 7
- server_command =
- (p - linebuffer > SERVER_COMMAND_LENGTH)
- && strncmp (linebuffer, "server ", SERVER_COMMAND_LENGTH) == 0;
- if (server_command)
- {
- /* Note that we don't set `line'. Between this and the check in
- dont_repeat, this insures that repeating will still do the
- right thing. */
- *p = '\0';
- return linebuffer + SERVER_COMMAND_LENGTH;
- }
-
- /* Do history expansion if that is wished. */
- if (history_expansion_p && instream == stdin
- && ISATTY (instream))
- {
- char *history_value;
- int expanded;
- *p = '\0'; /* Insert null now. */
- expanded = history_expand (linebuffer, &history_value);
- if (expanded)
- {
- /* Print the changes. */
- printf_unfiltered ("%s\n", history_value);
-
- /* If there was an error, call this function again. */
- if (expanded < 0)
- {
- xfree (history_value);
- return command_line_input (prompt, repeat,
- annotation_suffix);
- }
- if (strlen (history_value) > linelength)
- {
- linelength = strlen (history_value) + 1;
- linebuffer = (char *) xrealloc (linebuffer, linelength);
- }
- strcpy (linebuffer, history_value);
- p = linebuffer + strlen (linebuffer);
- }
- xfree (history_value);
- }
-
- /* If we just got an empty line, and that is supposed to repeat the
- previous command, return the value in the global buffer. */
- if (repeat && p == linebuffer)
- return saved_command_line;
- for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++);
- if (repeat && !*p1)
- return saved_command_line;
-
- *p = 0;
-
- /* Add line to history if appropriate. */
- if (*linebuffer && input_from_terminal_p ())
- gdb_add_history (linebuffer);
-
- /* Save into global buffer if appropriate. */
- if (repeat)
- {
- if (linelength > saved_command_line_size)
- {
- saved_command_line = xrealloc (saved_command_line, linelength);
- saved_command_line_size = linelength;
- }
- strcpy (saved_command_line, linebuffer);
- return saved_command_line;
- }
-
- return linebuffer;
+ return cmd;
}
\f
/* Print the GDB banner. */
/* Second line is a copyright notice. */
fprintf_filtered (stream,
- "Copyright (C) 2015 Free Software Foundation, Inc.\n");
+ "Copyright (C) 2018 Free Software Foundation, Inc.\n");
/* Following the copyright is a brief statement that the program is
free software, that users are free to copy and change it on
--without-lzma\n\
"));
#endif
+#if HAVE_LIBBABELTRACE
+ fprintf_filtered (stream, _("\
+ --with-babeltrace\n\
+"));
+#else
+ fprintf_filtered (stream, _("\
+ --without-babeltrace\n\
+"));
+#endif
+#if HAVE_LIBIPT
+ fprintf_filtered (stream, _("\
+ --with-intel-pt\n\
+"));
+#else
+ fprintf_filtered (stream, _("\
+ --without-intel-pt\n\
+"));
+#endif
+#if HAVE_LIBMCHECK
+ fprintf_filtered (stream, _("\
+ --enable-libmcheck\n\
+"));
+#else
+ fprintf_filtered (stream, _("\
+ --disable-libmcheck\n\
+"));
+#endif
+#if HAVE_LIBMPFR
+ fprintf_filtered (stream, _("\
+ --with-mpfr\n\
+"));
+#else
+ fprintf_filtered (stream, _("\
+ --without-mpfr\n\
+"));
+#endif
#ifdef WITH_PYTHON_PATH
fprintf_filtered (stream, _("\
--with-python=%s%s\n\
fprintf_filtered (stream, _("\
--with-system-gdbinit=%s%s\n\
"), SYSTEM_GDBINIT, SYSTEM_GDBINIT_RELOCATABLE ? " (relocatable)" : "");
-#if HAVE_LIBBABELTRACE
- fprintf_filtered (stream, _("\
- --with-babeltrace\n\
-"));
-#else
- fprintf_filtered (stream, _("\
- --without-babeltrace\n\
-"));
-#endif
/* We assume "relocatable" will be printed at least once, thus we always
print this text. It's a reasonably safe assumption for now. */
fprintf_filtered (stream, _("\n\
struct qt_args
{
- char *args;
int from_tty;
};
static int
kill_or_detach (struct inferior *inf, void *args)
{
- struct qt_args *qt = args;
+ struct qt_args *qt = (struct qt_args *) args;
struct thread_info *thread;
if (inf->pid == 0)
if (target_has_execution)
{
if (inf->attach_flag)
- target_detach (qt->args, qt->from_tty);
+ target_detach (inf, qt->from_tty);
else
target_kill ();
}
static int
print_inferior_quit_action (struct inferior *inf, void *arg)
{
- struct ui_file *stb = arg;
+ struct ui_file *stb = (struct ui_file *) arg;
if (inf->pid == 0)
return 0;
int
quit_confirm (void)
{
- struct ui_file *stb;
- struct cleanup *old_chain;
- char *str;
- int qr;
-
/* Don't even ask if we're only debugging a core file inferior. */
if (!have_live_inferiors ())
return 1;
/* Build the query string as a single string. */
- stb = mem_fileopen ();
- old_chain = make_cleanup_ui_file_delete (stb);
+ string_file stb;
+
+ stb.puts (_("A debugging session is active.\n\n"));
+ iterate_over_inferiors (print_inferior_quit_action, &stb);
+ stb.puts (_("\nQuit anyway? "));
+
+ return query ("%s", stb.c_str ());
+}
- fprintf_filtered (stb, _("A debugging session is active.\n\n"));
- iterate_over_inferiors (print_inferior_quit_action, stb);
- fprintf_filtered (stb, _("\nQuit anyway? "));
+/* Prepare to exit GDB cleanly by undoing any changes made to the
+ terminal so that we leave the terminal in the state we acquired it. */
- str = ui_file_xstrdup (stb, NULL);
- make_cleanup (xfree, str);
+static void
+undo_terminal_modifications_before_exit (void)
+{
+ struct ui *saved_top_level = current_ui;
+
+ target_terminal::ours ();
- qr = query ("%s", str);
- do_cleanups (old_chain);
- return qr;
+ current_ui = main_ui;
+
+#if defined(TUI)
+ tui_disable ();
+#endif
+ gdb_disable_readline ();
+
+ current_ui = saved_top_level;
}
+
/* Quit without asking for confirmation. */
void
-quit_force (char *args, int from_tty)
+quit_force (int *exit_arg, int from_tty)
{
int exit_code = 0;
struct qt_args qt;
+ undo_terminal_modifications_before_exit ();
+
/* An optional expression may be used to cause gdb to terminate with the
value of that expression. */
- if (args)
- {
- struct value *val = parse_and_eval (args);
-
- exit_code = (int) value_as_long (val);
- }
+ if (exit_arg)
+ exit_code = *exit_arg;
else if (return_child_result)
exit_code = return_child_result_value;
- qt.args = args;
qt.from_tty = from_tty;
/* We want to handle any quit errors and exit regardless. */
/* Save the history information if it is appropriate to do so. */
TRY
{
- if (write_history_p && history_filename
- && input_from_terminal_p ())
- gdb_safe_append_history ();
+ if (write_history_p && history_filename)
+ {
+ struct ui *ui;
+ int save = 0;
+
+ /* History is currently shared between all UIs. If there's
+ any UI with a terminal, save history. */
+ ALL_UIS (ui)
+ {
+ if (input_interactive_p (ui))
+ {
+ save = 1;
+ break;
+ }
+ }
+
+ if (save)
+ gdb_safe_append_history ();
+ }
}
CATCH (ex, RETURN_MASK_ALL)
{
exit (exit_code);
}
-/* Returns whether GDB is running on a terminal and input is
- currently coming from that terminal. */
+/* The value of the "interactive-mode" setting. */
+static enum auto_boolean interactive_mode = AUTO_BOOLEAN_AUTO;
+
+/* Implement the "show interactive-mode" option. */
+
+static void
+show_interactive_mode (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ if (interactive_mode == AUTO_BOOLEAN_AUTO)
+ fprintf_filtered (file, "Debugger's interactive mode "
+ "is %s (currently %s).\n",
+ value, input_interactive_p (current_ui) ? "on" : "off");
+ else
+ fprintf_filtered (file, "Debugger's interactive mode is %s.\n", value);
+}
+
+/* Returns whether GDB is running on an interactive terminal. */
int
-input_from_terminal_p (void)
+input_interactive_p (struct ui *ui)
{
if (batch_flag)
return 0;
- if (gdb_has_a_terminal () && instream == stdin)
- return 1;
-
- /* If INSTREAM is unset, and we are not in a user command, we
- must be in Insight. That's like having a terminal, for our
- purposes. */
- if (instream == NULL && !in_user_command)
- return 1;
+ if (interactive_mode != AUTO_BOOLEAN_AUTO)
+ return interactive_mode == AUTO_BOOLEAN_TRUE;
- return 0;
+ return ui->input_interactive_p;
}
\f
static void
-dont_repeat_command (char *ignored, int from_tty)
+dont_repeat_command (const char *ignored, int from_tty)
{
/* Can't call dont_repeat here because we're not necessarily reading
from stdin. */
/* Number of commands to print in each call to show_commands. */
#define Hist_print 10
void
-show_commands (char *args, int from_tty)
+show_commands (const char *args, int from_tty)
{
/* Index for history commands. Relative to history_base. */
int offset;
"show commands +" does. This is unnecessary if arg is null,
because "show commands +" is not useful after "show commands". */
if (from_tty && args)
- {
- args[0] = '+';
- args[1] = '\0';
- }
+ set_repeat_arguments ("+");
}
-/* Called by do_setshow_command. */
-static void
-set_history_size_command (char *args, int from_tty, struct cmd_list_element *c)
-{
- /* Readline's history interface works with 'int', so it can only
- handle history sizes up to INT_MAX. The command itself is
- uinteger, so UINT_MAX means "unlimited", but we only get that if
- the user does "set history size 0" -- "set history size <UINT_MAX>"
- throws out-of-range. */
- if (history_size_setshow_var > INT_MAX
- && history_size_setshow_var != UINT_MAX)
- {
- unsigned int new_value = history_size_setshow_var;
+/* Update the size of our command history file to HISTORY_SIZE.
- /* Restore previous value before throwing. */
- if (history_is_stifled ())
- history_size_setshow_var = history_max_entries;
- else
- history_size_setshow_var = UINT_MAX;
+ A HISTORY_SIZE of -1 stands for unlimited. */
- error (_("integer %u out of range"), new_value);
- }
+static void
+set_readline_history_size (int history_size)
+{
+ gdb_assert (history_size >= -1);
- /* Commit the new value to readline's history. */
- if (history_size_setshow_var == UINT_MAX)
+ if (history_size == -1)
unstifle_history ();
else
- stifle_history (history_size_setshow_var);
+ stifle_history (history_size);
+}
+
+/* Called by do_setshow_command. */
+static void
+set_history_size_command (const char *args,
+ int from_tty, struct cmd_list_element *c)
+{
+ set_readline_history_size (history_size_setshow_var);
}
void
-set_history (char *args, int from_tty)
+set_history (const char *args, int from_tty)
{
printf_unfiltered (_("\"set history\" must be followed "
"by the name of a history subcommand.\n"));
}
void
-show_history (char *args, int from_tty)
+show_history (const char *args, int from_tty)
{
cmd_show_list (showhistlist, from_tty, "");
}
/* Called by do_setshow_command. An elaborate joke. */
void
-set_verbose (char *args, int from_tty, struct cmd_list_element *c)
+set_verbose (const char *args, int from_tty, struct cmd_list_element *c)
{
const char *cmdname = "verbose";
struct cmd_list_element *showcmd;
{
char *tmpenv;
- tmpenv = getenv ("HISTSIZE");
+ tmpenv = getenv ("GDBHISTSIZE");
if (tmpenv)
{
- int var;
+ long var;
+ int saved_errno;
+ char *endptr;
- var = atoi (tmpenv);
- if (var < 0)
- {
- /* Prefer ending up with no history rather than overflowing
- readline's history interface, which uses signed 'int'
- everywhere. */
- var = 0;
- }
-
- history_size_setshow_var = var;
+ tmpenv = skip_spaces (tmpenv);
+ errno = 0;
+ var = strtol (tmpenv, &endptr, 10);
+ saved_errno = errno;
+ endptr = skip_spaces (endptr);
+
+ /* If GDBHISTSIZE is non-numeric then ignore it. If GDBHISTSIZE is the
+ empty string, a negative number or a huge positive number (larger than
+ INT_MAX) then set the history size to unlimited. Otherwise set our
+ history size to the number we have read. This behavior is consistent
+ with how bash handles HISTSIZE. */
+ if (*endptr != '\0')
+ ;
+ else if (*tmpenv == '\0'
+ || var < 0
+ || var > INT_MAX
+ /* On targets where INT_MAX == LONG_MAX, we have to look at
+ errno after calling strtol to distinguish between a value that
+ is exactly INT_MAX and an overflowing value that was clamped
+ to INT_MAX. */
+ || (var == INT_MAX && saved_errno == ERANGE))
+ history_size_setshow_var = -1;
+ else
+ history_size_setshow_var = var;
}
- /* If the init file hasn't set a size yet, pick the default. */
- else if (history_size_setshow_var == 0)
+
+ /* If neither the init file nor GDBHISTSIZE has set a size yet, pick the
+ default. */
+ if (history_size_setshow_var == -2)
history_size_setshow_var = 256;
- /* Note that unlike "set history size 0", "HISTSIZE=0" really sets
- the history size to 0... */
- stifle_history (history_size_setshow_var);
+ set_readline_history_size (history_size_setshow_var);
tmpenv = getenv ("GDBHISTFILE");
if (tmpenv)
fprintf_filtered (file, _("Gdb's prompt is \"%s\".\n"), value);
}
+/* "set editing" command. */
+
+static void
+set_editing (const char *args, int from_tty, struct cmd_list_element *c)
+{
+ change_line_handler (set_editing_cmd_var);
+ /* Update the control variable so that MI's =cmd-param-changed event
+ shows the correct value. */
+ set_editing_cmd_var = current_ui->command_editing;
+}
+
static void
-show_async_command_editing_p (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
+show_editing (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("Editing of command lines as "
"they are typed is %s.\n"),
- value);
+ current_ui->command_editing ? _("on") : _("off"));
}
static void
/* "set" command for the gdb_datadir configuration variable. */
static void
-set_gdb_datadir (char *args, int from_tty, struct cmd_list_element *c)
+set_gdb_datadir (const char *args, int from_tty, struct cmd_list_element *c)
{
set_gdb_data_directory (staged_gdb_datadir);
- observer_notify_gdb_datadir_changed ();
+ gdb::observers::gdb_datadir_changed.notify ();
}
/* "show" command for the gdb_datadir configuration variable. */
}
static void
-set_history_filename (char *args, int from_tty, struct cmd_list_element *c)
+set_history_filename (const char *args,
+ int from_tty, struct cmd_list_element *c)
{
/* We include the current directory so that if the user changes
directories the file written will be the same as the one
static void
init_main (void)
{
+ struct cmd_list_element *c;
+
/* Initialize the prompt to a simple "(gdb) " prompt or to whatever
the DEFAULT_PROMPT is. */
set_prompt (DEFAULT_PROMPT);
- /* Set things up for annotation_level > 1, if the user ever decides
- to use it. */
- async_annotation_suffix = "prompt";
-
/* Set the important stuff up for command editing. */
command_editing_p = 1;
history_expansion_p = 0;
/* Setup important stuff for command line editing. */
rl_completion_word_break_hook = gdb_completion_word_break_characters;
- rl_completion_entry_function = readline_line_completion_function;
- rl_completer_word_break_characters = default_word_break_characters ();
+ rl_attempted_completion_function = gdb_rl_attempted_completion_function;
+ set_rl_completer_word_break_characters (default_word_break_characters ());
rl_completer_quote_characters = get_gdb_completer_quote_characters ();
rl_completion_display_matches_hook = cli_display_match_list;
rl_readline_name = "gdb";
hitting return."));
add_setshow_boolean_cmd ("editing", class_support,
- &async_command_editing_p, _("\
+ &set_editing_cmd_var, _("\
Set editing of command lines as they are typed."), _("\
Show editing of command lines as they are typed."), _("\
Use \"on\" to enable the editing, and \"off\" to disable it.\n\
Without an argument, command line editing is enabled. To edit, use\n\
EMACS-like or VI-like commands like control-P or ESC."),
- set_async_editing_command,
- show_async_command_editing_p,
+ set_editing,
+ show_editing,
&setlist, &showlist);
add_setshow_boolean_cmd ("save", no_class, &write_history_p, _("\
show_write_history_p,
&sethistlist, &showhistlist);
- add_setshow_uinteger_cmd ("size", no_class, &history_size_setshow_var, _("\
+ add_setshow_zuinteger_unlimited_cmd ("size", no_class,
+ &history_size_setshow_var, _("\
Set the size of the command history,"), _("\
Show the size of the command history,"), _("\
ie. the number of previous commands to keep a record of.\n\
If set to \"unlimited\", the number of commands kept in the history\n\
list is unlimited. This defaults to the value of the environment\n\
-variable \"HISTSIZE\", or to 256 if this variable is not set."),
+variable \"GDBHISTSIZE\", or to 256 if this variable is not set."),
set_history_size_command,
show_history_size,
&sethistlist, &showhistlist);
+ add_setshow_zuinteger_unlimited_cmd ("remove-duplicates", no_class,
+ &history_remove_duplicates, _("\
+Set how far back in history to look for and remove duplicate entries."), _("\
+Show how far back in history to look for and remove duplicate entries."), _("\
+If set to a nonzero value N, GDB will look back at the last N history entries\n\
+and remove the first history entry that is a duplicate of the most recent\n\
+entry, each time a new history entry is added.\n\
+If set to \"unlimited\", this lookbehind is unbounded.\n\
+Only history entries added during this session are considered for removal.\n\
+If set to 0, removal of duplicate history entries is disabled.\n\
+By default this option is set to 0."),
+ NULL,
+ show_history_remove_duplicates,
+ &sethistlist, &showhistlist);
+
add_setshow_filename_cmd ("filename", no_class, &history_filename, _("\
Set the filename in which to record the command history"), _("\
Show the filename in which to record the command history"), _("\
set_gdb_datadir, show_gdb_datadir,
&setlist,
&showlist);
+
+ add_setshow_auto_boolean_cmd ("interactive-mode", class_support,
+ &interactive_mode, _("\
+Set whether GDB's standard input is a terminal."), _("\
+Show whether GDB's standard input is a terminal."), _("\
+If on, GDB assumes that standard input is a terminal. In practice, it\n\
+means that GDB should wait for the user to answer queries associated to\n\
+commands entered at the command prompt. If off, GDB assumes that standard\n\
+input is not a terminal, and uses the default answer to all queries.\n\
+If auto (the default), determine which mode to use based on the standard\n\
+input settings."),
+ NULL,
+ show_interactive_mode,
+ &setlist, &showlist);
+
+ c = add_cmd ("new-ui", class_support, new_ui_command, _("\
+Create a new UI. It takes two arguments:\n\
+The first argument is the name of the interpreter to run.\n\
+The second argument is the terminal the UI runs on.\n"), &cmdlist);
+ set_cmd_completer (c, interpreter_completer);
}
void
set_language (language_c);
expected_language = current_language; /* Don't warn about the change. */
- /* Allow another UI to initialize. If the UI fails to initialize,
- and it wants GDB to revert to the CLI, it should clear
- deprecated_init_ui_hook. */
- if (deprecated_init_ui_hook)
- deprecated_init_ui_hook (argv0);
-
/* Python initialization, for example, can require various commands to be
installed. For example "info pretty-printer" needs the "info"
prefix to be installed. Keep things simple and just do final