#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"
value);
}
-/* 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];
-
/* The last command line executed on the console. Used for command
repetitions. */
char *saved_command_line;
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);
/* See top.h. */
-struct ui *
-new_ui (FILE *instream, FILE *outstream, FILE *errstream)
+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)
{
- struct ui *ui;
-
- ui = XCNEW (struct ui);
-
- ui->num = ++highest_ui_num;
- ui->stdin_stream = instream;
- ui->instream = instream;
- ui->outstream = outstream;
- ui->errstream = errstream;
-
- ui->input_fd = fileno (ui->instream);
-
- ui->input_interactive_p = ISATTY (ui->instream);
-
- ui->m_gdb_stdin = stdio_fileopen (ui->instream);
- ui->m_gdb_stdout = stdio_fileopen (ui->outstream);
- ui->m_gdb_stderr = stderr_fileopen (ui->errstream);
- ui->m_gdb_stdlog = ui->m_gdb_stderr;
-
- ui->prompt_state = PROMPT_NEEDED;
+ buffer_init (&line_buffer);
if (ui_list == NULL)
- ui_list = ui;
+ ui_list = this;
else
{
struct ui *last;
for (last = ui_list; last->next != NULL; last = last->next)
;
- last->next = ui;
+ last->next = this;
}
-
- return ui;
}
-static void
-free_ui (struct ui *ui)
-{
- ui_file_delete (ui->m_gdb_stdin);
- ui_file_delete (ui->m_gdb_stdout);
- ui_file_delete (ui->m_gdb_stderr);
-
- xfree (ui);
-}
-
-void
-delete_ui (struct ui *todel)
+ui::~ui ()
{
struct ui *ui, *uiprev;
uiprev = NULL;
for (ui = ui_list; ui != NULL; uiprev = ui, ui = ui->next)
- if (ui == todel)
+ if (ui == this)
break;
gdb_assert (ui != NULL);
if (uiprev != NULL)
- uiprev->next = ui->next;
+ uiprev->next = next;
else
- ui_list = ui->next;
+ ui_list = next;
- free_ui (ui);
-}
-
-/* Cleanup that deletes a UI. */
-
-static void
-delete_ui_cleanup (void *void_ui)
-{
- struct ui *ui = (struct ui *) void_ui;
-
- delete_ui (ui);
-}
-
-/* See top.h. */
-
-struct cleanup *
-make_delete_ui_cleanup (struct ui *ui)
-{
- return make_cleanup (delete_ui_cleanup, ui);
+ 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 FILE *
+static gdb_file_up
open_terminal_stream (const char *name)
{
int fd;
- fd = open (name, O_RDWR | O_NOCTTY);
+ fd = gdb_open_cloexec (name, O_RDWR | O_NOCTTY, 0);
if (fd < 0)
perror_with_name (_("opening terminal failed"));
- return fdopen (fd, "w+");
+ return gdb_file_up (fdopen (fd, "w+"));
}
/* Implementation of the "new-ui" command. */
static void
-new_ui_command (char *args, int from_tty)
+new_ui_command (const char *args, int from_tty)
{
- struct ui *ui;
struct interp *interp;
- FILE *stream[3] = { NULL, NULL, NULL };
+ gdb_file_up stream[3];
int i;
int res;
int argc;
- char **argv;
const char *interpreter_name;
const char *tty_name;
- struct cleanup *success_chain;
- struct cleanup *failure_chain;
dont_repeat ();
- argv = gdb_buildargv (args);
- success_chain = make_cleanup_freeargv (argv);
- argc = countargv (argv);
+ gdb_argv argv (args);
+ argc = argv.count ();
if (argc < 2)
error (_("usage: new-ui <interpreter> <tty>"));
{
scoped_restore save_ui = make_scoped_restore (¤t_ui);
- failure_chain = make_cleanup (null_cleanup, NULL);
-
/* Open specified terminal, once for each of
stdin/stdout/stderr. */
for (i = 0; i < 3; i++)
- {
- stream[i] = open_terminal_stream (tty_name);
- make_cleanup_fclose (stream[i]);
- }
+ stream[i] = open_terminal_stream (tty_name);
- ui = new_ui (stream[0], stream[1], stream[2]);
- make_cleanup (delete_ui_cleanup, ui);
+ std::unique_ptr<ui> ui
+ (new struct ui (stream[0].get (), stream[1].get (), stream[2].get ()));
ui->async = 1;
- current_ui = ui;
+ current_ui = ui.get ();
set_top_level_interpreter (interpreter_name);
interp_pre_command_loop (top_level_interpreter ());
- discard_cleanups (failure_chain);
+ /* Make sure the files are not closed. */
+ stream[0].release ();
+ stream[1].release ();
+ stream[2].release ();
- /* This restores the previous UI and frees argv. */
- do_cleanups (success_chain);
+ ui.release ();
}
printf_unfiltered ("New UI allocated\n");
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)
-{
- struct ui *ui = current_ui;
-
- /* Restore the previous input stream. */
- ui->instream = (FILE *) stream;
-}
-
/* Read commands from STREAM. */
void
read_command_file (FILE *stream)
{
struct ui *ui = current_ui;
- struct cleanup *cleanups;
- cleanups = make_cleanup (do_restore_instream_cleanup, ui->instream);
- ui->instream = stream;
+ 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. */
break;
command_handler (command);
}
-
- do_cleanups (cleanups);
}
\f
void (*pre_init_ui_hook) (void);
std::string
execute_command_to_string (char *p, int from_tty)
{
- struct ui_file *str_file;
- struct cleanup *cleanup;
-
/* GDB_STDOUT should be better already restored during these
restoration callbacks. */
- cleanup = set_batch_flag_and_make_cleanup_restore_page_info ();
+ set_batch_flag_and_restore_page_info save_page_info;
scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0);
- str_file = mem_fileopen ();
+ string_file str_file;
- make_cleanup_ui_file_delete (str_file);
-
- current_uiout->redirect (str_file);
- make_cleanup_ui_out_redirect_pop (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);
-
- std::string retval = ui_file_as_string (str_file);
-
- do_cleanups (cleanup);
+ {
+ 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 retval;
+ return std::move (str_file.string ());
}
\f
if (cleanup->target_is_async_orig)
target_async (0);
- /* Display our prompt and prevent double prompt display. */
- display_gdb_prompt (prompt);
+ /* 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;
gdb_safe_append_history (void)
{
int ret, saved_errno;
- char *local_history_filename;
- struct cleanup *old_chain;
- local_history_filename
- = xstrprintf ("%s-gdb%ld~", history_filename, (long) 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);
+ append_history (command_count, local_history_filename.c_str ());
if (history_is_stifled ())
- history_truncate_file (local_history_filename, history_max_entries);
+ 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 a local
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 struct buffer cmd_line_buffer;
static int cmd_line_buffer_initialized;
if (cmd != NULL)
break;
+ /* Got partial input. I.e., got a line that ends with a
+ continuation character (backslash). Suppress printing the
+ prompt again. */
prompt = NULL;
}
int
quit_confirm (void)
{
- struct ui_file *stb;
- struct cleanup *old_chain;
-
/* 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);
-
- fprintf_filtered (stb, _("A debugging session is active.\n\n"));
- iterate_over_inferiors (print_inferior_quit_action, stb);
- fprintf_filtered (stb, _("\nQuit anyway? "));
-
- std::string str = ui_file_as_string (stb);
+ string_file stb;
- do_cleanups (old_chain);
+ stb.puts (_("A debugging session is active.\n\n"));
+ iterate_over_inferiors (print_inferior_quit_action, &stb);
+ stb.puts (_("\nQuit anyway? "));
- return query ("%s", str.c_str ());
+ return query ("%s", stb.c_str ());
}
/* Prepare to exit GDB cleanly by undoing any changes made to the
{
struct ui *saved_top_level = current_ui;
- target_terminal_ours ();
+ target_terminal::ours ();
current_ui = main_ui;
/* 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";