/* Top level stuff for GDB, the GNU debugger.
- Copyright (C) 1999-2016 Free Software Foundation, Inc.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions.
sjlj-based TRY/CATCH mechanism, which knows to handle multiple
levels of active setjmp/longjmp frames, needed in order to handle
the readline callback recursing, as happens with e.g., secondary
- prompts / queries, through gdb_readline_wrapper. */
+ prompts / queries, through gdb_readline_wrapper. This must be
+ noexcept in order to avoid problems with mixing sjlj and
+ (sjlj-based) C++ exceptions. */
-static void
-gdb_rl_callback_read_char_wrapper (gdb_client_data client_data)
+static struct gdb_exception
+gdb_rl_callback_read_char_wrapper_noexcept () noexcept
{
struct gdb_exception gdb_expt = exception_none;
}
END_CATCH_SJLJ
+ return gdb_expt;
+}
+
+static void
+gdb_rl_callback_read_char_wrapper (gdb_client_data client_data)
+{
+ struct gdb_exception gdb_expt
+ = gdb_rl_callback_read_char_wrapper_noexcept ();
+
/* Rethrow using the normal EH mechanism. */
if (gdb_expt.reason < 0)
throw_exception (gdb_expt);
/* GDB's readline callback handler. Calls the current INPUT_HANDLER,
and propagates GDB exceptions/errors thrown from INPUT_HANDLER back
- across readline. See gdb_rl_callback_read_char_wrapper. */
+ across readline. See gdb_rl_callback_read_char_wrapper. This must
+ be noexcept in order to avoid problems with mixing sjlj and
+ (sjlj-based) C++ exceptions. */
static void
-gdb_rl_callback_handler (char *rl)
+gdb_rl_callback_handler (char *rl) noexcept
{
struct gdb_exception gdb_rl_expt = exception_none;
struct ui *ui = current_ui;
struct ui *current_ui;
struct ui *ui_list;
-/* See top.h. */
-
-void
-restore_ui_cleanup (void *data)
-{
- current_ui = (struct ui *) data;
-}
-
-/* See top.h. */
-
-void
-switch_thru_all_uis_init (struct switch_thru_all_uis *state)
-{
- state->iter = ui_list;
- state->old_chain = make_cleanup (restore_ui_cleanup, current_ui);
-}
-
-/* See top.h. */
-
-int
-switch_thru_all_uis_cond (struct switch_thru_all_uis *state)
-{
- if (state->iter != NULL)
- {
- current_ui = state->iter;
- return 1;
- }
- else
- {
- do_cleanups (state->old_chain);
- return 0;
- }
-}
-
-/* See top.h. */
-
-void
-switch_thru_all_uis_next (struct switch_thru_all_uis *state)
-{
- state->iter = state->iter->next;
-}
-
/* Get a pointer to the current UI's line buffer. This is used to
construct a whole line of input from partial input. */
{
struct ui *ui = (struct ui *) client_data;
- /* Switch to the UI whose input descriptor woke up the event
- loop. */
- current_ui = ui;
-
if (error)
{
- printf_unfiltered (_("error detected on stdin\n"));
+ /* Switch to the main UI, so diagnostics always go there. */
+ current_ui = main_ui;
+
delete_file_handler (ui->input_fd);
- /* If stdin died, we may as well kill gdb. */
- quit_command ((char *) 0, stdin == ui->instream);
+ if (main_ui == ui)
+ {
+ /* If stdin died, we may as well kill gdb. */
+ printf_unfiltered (_("error detected on stdin\n"));
+ quit_command ((char *) 0, 0);
+ }
+ else
+ {
+ /* Simply delete the UI. */
+ delete_ui (ui);
+ }
}
else
{
- /* This makes sure a ^C immediately followed by further input is
- always processed in that order. E.g,. with input like
- "^Cprint 1\n", the SIGINT handler runs, marks the async signal
- handler, and then select/poll may return with stdin ready,
- instead of -1/EINTR. The
- gdb.base/double-prompt-target-event-error.exp test exercises
- this. */
+ /* Switch to the UI whose input descriptor woke up the event
+ loop. */
+ current_ui = ui;
+
+ /* This makes sure a ^C immediately followed by further input is
+ always processed in that order. E.g,. with input like
+ "^Cprint 1\n", the SIGINT handler runs, marks the async
+ signal handler, and then select/poll may return with stdin
+ ready, instead of -1/EINTR. The
+ gdb.base/double-prompt-target-event-error.exp test exercises
+ this. */
QUIT;
do
{
call_stdin_event_handler_again_p = 0;
ui->call_readline (client_data);
- } while (call_stdin_event_handler_again_p != 0);
+ }
+ while (call_stdin_event_handler_again_p != 0);
}
}
+/* See top.h. */
+
+void
+ui_register_input_event_handler (struct ui *ui)
+{
+ add_file_handler (ui->input_fd, stdin_event_handler, ui);
+}
+
+/* See top.h. */
+
+void
+ui_unregister_input_event_handler (struct ui *ui)
+{
+ delete_file_handler (ui->input_fd);
+}
+
/* Re-enable stdin after the end of an execution command in
synchronous mode, or after an error from the target, and we aborted
the exec operation. */
if (ui->prompt_state == PROMPT_BLOCKED)
{
target_terminal_ours ();
+ ui_register_input_event_handler (ui);
ui->prompt_state = PROMPT_NEEDED;
}
}
struct ui *ui = current_ui;
ui->prompt_state = PROMPT_BLOCKED;
+ delete_file_handler (ui->input_fd);
}
\f
command_handler (char *command)
{
struct ui *ui = current_ui;
- struct cleanup *stat_chain;
char *c;
- if (ui->instream == stdin)
+ if (ui->instream == ui->stdin_stream)
reinitialize_more_filter ();
- stat_chain = make_command_stats_cleanup (1);
+ scoped_command_stats stat_reporter (true);
/* Do not execute commented lines. */
for (c = command; *c == ' ' || *c == '\t'; c++)
;
if (c[0] != '#')
{
- execute_command (command, ui->instream == stdin);
+ execute_command (command, ui->instream == ui->stdin_stream);
/* Do any commands attached to breakpoint we stopped at. */
bpstat_do_actions ();
}
-
- do_cleanups (stat_chain);
}
/* Append RL, an input line returned by readline or one of its
char *rl, int repeat, char *annotation_suffix)
{
struct ui *ui = current_ui;
+ int from_tty = ui->instream == ui->stdin_stream;
char *p1;
char *cmd;
command, but leave ownership of memory to the buffer . */
cmd_line_buffer->used_size = 0;
- if (annotation_level > 1 && ui->instream == stdin)
+ if (from_tty && annotation_level > 1)
{
printf_unfiltered (("\n\032\032post-"));
puts_unfiltered (annotation_suffix);
}
/* Do history expansion if that is wished. */
- if (history_expansion_p && ui->instream == stdin
- && ISATTY (ui->instream))
+ if (history_expansion_p && from_tty && input_interactive_p (current_ui))
{
char *history_value;
int expanded;
and then later fetch it from the value history and remove the
'#'. The kill ring is probably better, but some people are in
the habit of commenting things out. */
- if (*cmd != '\0' && input_from_terminal_p ())
+ if (*cmd != '\0' && from_tty && input_interactive_p (current_ui))
gdb_add_history (cmd);
/* Save into global buffer if appropriate. */
struct ui *ui = current_ui;
char *cmd;
- cmd = handle_line_of_input (line_buffer, rl, ui->instream == stdin,
- "prompt");
+ cmd = handle_line_of_input (line_buffer, rl, 1, "prompt");
if (cmd == (char *) EOF)
{
/* stdin closed. The connection with the terminal is gone.
hung up but GDB is still alive. In such a case, we just quit
gdb killing the inferior program too. */
printf_unfiltered ("quit\n");
- execute_command ("quit", stdin == ui->instream);
+ execute_command ("quit", 1);
}
else if (cmd == NULL)
{
{
/* Read from stdin if we are executing a user defined command.
This is the right thing for prompt_for_continue, at least. */
- c = fgetc (ui->instream ? ui->instream : stdin);
+ c = fgetc (ui->instream != NULL ? ui->instream : ui->stdin_stream);
if (c == EOF)
{
static void
async_sigterm_handler (gdb_client_data arg)
{
- quit_force (NULL, stdin == current_ui->instream);
+ quit_force (NULL, 0);
}
/* See defs.h. */
mess it up here. The sync stuff should really go away over
time. */
if (!batch_silent)
- gdb_stdout = stdio_fileopen (ui->outstream);
- gdb_stderr = stderr_fileopen (ui->errstream);
+ gdb_stdout = new stdio_file (ui->outstream);
+ gdb_stderr = new stderr_file (ui->errstream);
gdb_stdlog = gdb_stderr; /* for moment */
gdb_stdtarg = gdb_stderr; /* for moment */
gdb_stdtargerr = gdb_stderr; /* for moment */
Another source is going to be the target program (inferior), but
that must be registered only when it actually exists (I.e. after
we say 'run' or after we connect to a remote target. */
- add_file_handler (ui->input_fd, stdin_event_handler, ui);
+ ui_register_input_event_handler (ui);
}
/* Disable command input through the standard CLI channels. Used in