aboutsummaryrefslogtreecommitdiff
path: root/gdb/event-top.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/event-top.c')
-rw-r--r--gdb/event-top.c273
1 files changed, 168 insertions, 105 deletions
diff --git a/gdb/event-top.c b/gdb/event-top.c
index d241dda..ad269eb 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -20,10 +20,12 @@
#include "defs.h"
#include "event-loop.h"
+#include "top.h"
#ifdef HAVE_POLL
#include <sys/poll.h>
#endif
#include "inferior.h"
+#include "terminal.h" /* for job_control*/
/* readline include files */
#include <readline/readline.h>
@@ -32,7 +34,7 @@
/* readline defines this. */
#undef savestring
-extern FILE *instream;
+extern void _initialize_event_loop (void);
static void command_line_handler PARAMS ((char *));
static void gdb_readline2 PARAMS ((void));
@@ -43,32 +45,26 @@ static void change_annotation_level PARAMS ((void));
static void command_handler PARAMS ((char *));
/* Signal handlers. */
-void handle_sigint PARAMS ((int));
-void handle_sigquit PARAMS ((int));
-void handle_sighup PARAMS ((int));
-void handle_sigfpe PARAMS ((int));
-void handle_sigwinch PARAMS ((int));
+static void handle_sigint PARAMS ((int));
+static void handle_sigquit PARAMS ((int));
+static void handle_sighup PARAMS ((int));
+static void handle_sigfpe PARAMS ((int));
+static void handle_sigwinch PARAMS ((int));
+/* Signal to catch ^Z typed while reading a command: SIGTSTP or SIGCONT. */
+#ifndef STOP_SIGNAL
+#ifdef SIGTSTP
+#define STOP_SIGNAL SIGTSTP
+void handle_stop_sig PARAMS ((int));
+#endif
+#endif
/* Functions to be invoked by the event loop in response to
signals. */
-void async_request_quit PARAMS ((void));
-void async_do_nothing PARAMS ((void));
-void async_disconnect PARAMS ((void));
-void async_float_handler PARAMS ((void));
-
-/* Functions from top.c. */
-extern void command_loop_marker PARAMS ((int));
-extern int quit_cover PARAMS ((PTR));
-extern void quit_command PARAMS ((char *, int));
-extern void execute_command PARAMS ((char *, int));
-
-/* Variables from top.c. */
-extern int source_line_number;
-extern char *source_file_name;
-extern char *source_error;
-extern char *source_pre_error;
-extern int history_expansion_p;
-extern int server_command;
+void async_request_quit PARAMS ((gdb_client_data));
+static void async_do_nothing PARAMS ((gdb_client_data));
+static void async_disconnect PARAMS ((gdb_client_data));
+static void async_float_handler PARAMS ((gdb_client_data));
+static void async_stop_sig PARAMS ((gdb_client_data));
/* If this definition isn't overridden by the header files, assume
that isatty and fileno exist on this system. */
@@ -76,9 +72,6 @@ extern int server_command;
#define ISATTY(FP) (isatty (fileno (FP)))
#endif
-/* Hook for alternate command interface. */
-void (*async_hook) PARAMS ((void));
-
/* Readline offers an alternate interface, via callback
functions. These are all included in the file callback.c in the
readline distribution. This file provides (mainly) a function, which
@@ -106,7 +99,7 @@ void (*call_readline) PARAMS ((void));
/* This is used to determine if GDB is using the readline library or
its own simplified form of readline. It is used by the asynchronous
- form of the set editing command.
+ form of the set editing command.
ezannoni: as of 1999-04-29 I expect that this
variable will not be used after gdb is changed to use the event
loop as default engine, and event-top.c is merged into top.c. */
@@ -135,15 +128,20 @@ struct prompts the_prompts;
handlers mark these functions as ready to be executed and the event
loop, in a later iteration, calls them. See the function
invoke_async_signal_handler. */
-async_signal_handler *sigint_token;
+PTR sigint_token;
#ifdef SIGHUP
-async_signal_handler *sighup_token;
+PTR sighup_token;
#endif
-async_signal_handler *sigquit_token;
-async_signal_handler *sigfpe_token;
+PTR sigquit_token;
+PTR sigfpe_token;
#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
-async_signal_handler *sigwinch_token;
+PTR sigwinch_token;
#endif
+#ifdef STOP_SIGNAL
+PTR sigtstp_token;
+#endif
+
+void mark_async_signal_handler_wrapper PARAMS ((void *));
/* Structure to save a partially entered command. This is used when
the user types '\' at the end of a command line. This is necessary
@@ -163,46 +161,27 @@ readline_input_state;
/* Initialize all the necessary variables, start the event loop,
register readline, and stdin. */
void
-setup_event_loop ()
+start_event_loop ()
{
- int length = strlen (PREFIX (0)) + strlen (PROMPT (0)) + strlen (SUFFIX (0)) + 1;
- char *a_prompt = (char *) xmalloc (length);
-
- /* Set things up for readline to be invoked via the alternate
- interface, i.e. via a callback function (rl_callback_read_char). */
- call_readline = rl_callback_read_char;
-
- /* When readline has read an end-of-line character, it passes the
- complete line to gdb for processing. command_line_handler is the
- function that does this. */
- input_handler = command_line_handler;
-
- /* Tell readline what the prompt to display is and what function it
- will need to call after a whole line is read. */
- strcpy (a_prompt, PREFIX (0));
- strcat (a_prompt, PROMPT (0));
- strcat (a_prompt, SUFFIX (0));
- rl_callback_handler_install (a_prompt, input_handler);
-
- /* Tell readline to use the same input stream that gdb uses. */
- rl_instream = instream;
- /* Get a file descriptor for the input stream, so that we can
- register it with the event loop. */
- input_fd = fileno (instream);
+ int length;
+ char *a_prompt;
- /* Now we need to create the event sources for the input file descriptor. */
- /* At this point in time, this is the only event source that we
- register with the even loop. 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. */
-#ifdef HAVE_POLL
- create_file_handler (input_fd, POLLIN,
- (file_handler_func *) call_readline, 0);
-#else
- create_file_handler (input_fd, GDB_READABLE,
- (file_handler_func *) call_readline, 0);
-#endif
+ /* If we are using readline, set things up and display the first
+ prompt, otherwise just print the prompt. */
+ if (async_command_editing_p)
+ {
+ /* Tell readline what the prompt to display is and what function it
+ will need to call after a whole line is read. This also displays
+ the first prompt.*/
+ length = strlen (PREFIX (0)) + strlen (PROMPT (0)) + strlen (SUFFIX (0)) + 1;
+ a_prompt = (char *) xmalloc (length);
+ strcpy (a_prompt, PREFIX (0));
+ strcat (a_prompt, PROMPT (0));
+ strcat (a_prompt, SUFFIX (0));
+ rl_callback_handler_install (a_prompt, input_handler);
+ }
+ else
+ display_gdb_prompt (0);
/* Loop until there is something to do. This is the entry point to
the event loop engine. gdb_do_one_event will process one event
@@ -229,12 +208,17 @@ change_line_handler ()
{
/* Turn on editing by using readline. */
call_readline = rl_callback_read_char;
+ input_handler = command_line_handler;
}
else
{
/* Turn off editing by using gdb_readline2. */
rl_callback_handler_remove ();
call_readline = gdb_readline2;
+
+ /* Set up the command handler as well, in case we are called as
+ first thing from .gdbinit. */
+ input_handler = command_line_handler;
}
/* To tell the event loop to change the handler associated with the
@@ -255,12 +239,12 @@ change_line_handler ()
top of the prompt stack, if the argument NEW_PROMPT is
0. Otherwise, it displays whatever NEW_PROMPT is. This is used
after each gdb command has completed, and in the following cases:
- 1. when the user enters a command line which is ended by '\'
- indicating that the command will continue on the next line.
+ 1. when the user enters a command line which is ended by '\'
+ indicating that the command will continue on the next line.
In that case the prompt that is displayed is the empty string.
- 2. When the user is entering 'commands' for a breakpoint, or
- actions for a tracepoint. In this case the prompt will be '>'
- 3. Other????
+ 2. When the user is entering 'commands' for a breakpoint, or
+ actions for a tracepoint. In this case the prompt will be '>'
+ 3. Other????
FIXME: 2. & 3. not implemented yet for async. */
void
display_gdb_prompt (new_prompt)
@@ -521,7 +505,7 @@ command_line_handler (rl)
#ifdef STOP_SIGNAL
if (job_control)
- signal (STOP_SIGNAL, stop_sig);
+ signal (STOP_SIGNAL, handle_stop_sig);
#endif
/* Make sure that all output has been output. Some machines may let
@@ -726,7 +710,7 @@ gdb_readline2 ()
we'll return NULL then. */
break;
free (result);
- command_line_handler (0);
+ (*input_handler) (0);
}
if (c == '\n')
@@ -749,7 +733,7 @@ gdb_readline2 ()
}
result[input_index++] = '\0';
- command_line_handler (result);
+ (*input_handler) (result);
}
@@ -767,10 +751,10 @@ gdb_readline2 ()
as the default for gdb. */
void
async_init_signals ()
-{
+{
signal (SIGINT, handle_sigint);
sigint_token =
- create_async_signal_handler ((async_handler_func *) async_request_quit, NULL);
+ create_async_signal_handler (async_request_quit, NULL);
/* If SIGTRAP was set to SIG_IGN, then the SIG_IGN will get passed
to the inferior and breakpoints will be ignored. */
@@ -788,29 +772,41 @@ async_init_signals ()
to SIG_DFL for us. */
signal (SIGQUIT, handle_sigquit);
sigquit_token =
- create_async_signal_handler ((async_handler_func *) async_do_nothing, NULL);
+ create_async_signal_handler (async_do_nothing, NULL);
#ifdef SIGHUP
if (signal (SIGHUP, handle_sighup) != SIG_IGN)
sighup_token =
- create_async_signal_handler ((async_handler_func *) async_disconnect, NULL);
+ create_async_signal_handler (async_disconnect, NULL);
else
sighup_token =
- create_async_signal_handler ((async_handler_func *) async_do_nothing, NULL);
+ create_async_signal_handler (async_do_nothing, NULL);
#endif
signal (SIGFPE, handle_sigfpe);
sigfpe_token =
- create_async_signal_handler ((async_handler_func *) async_float_handler, NULL);
+ create_async_signal_handler (async_float_handler, NULL);
#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
signal (SIGWINCH, handle_sigwinch);
sigwinch_token =
- create_async_signal_handler ((async_handler_func *) SIGWINCH_HANDLER, NULL);
+ create_async_signal_handler (SIGWINCH_HANDLER, NULL);
#endif
+#ifdef STOP_SIGNAL
+ sigtstp_token =
+ create_async_signal_handler (async_stop_sig, NULL);
+#endif
+
+}
+
+void
+mark_async_signal_handler_wrapper (token)
+ void *token;
+{
+ mark_async_signal_handler ((async_signal_handler *) token);
}
/* Tell the event loop what to do if SIGINT is received.
See event-signal.c. */
-void
+static void
handle_sigint (sig)
int sig;
{
@@ -824,16 +820,17 @@ handle_sigint (sig)
that point, though, the command that we want to interrupt needs to
finish first, which is unacceptable. */
if (immediate_quit)
- async_request_quit ();
+ async_request_quit (0);
else
/* If immediate quit is not set, we process SIGINT the next time
through the loop, which is fine. */
- mark_async_signal_handler (sigint_token);
+ mark_async_signal_handler_wrapper (sigint_token);
}
/* Do the quit. All the checks have been done by the caller. */
void
-async_request_quit ()
+async_request_quit (arg)
+ gdb_client_data arg;
{
quit_flag = 1;
#ifdef REQUEST_QUIT
@@ -845,17 +842,18 @@ async_request_quit ()
/* Tell the event loop what to do if SIGQUIT is received.
See event-signal.c. */
-void
+static void
handle_sigquit (sig)
int sig;
{
- mark_async_signal_handler (sigquit_token);
+ mark_async_signal_handler_wrapper (sigquit_token);
signal (sig, handle_sigquit);
}
/* Called by the event loop in response to a SIGQUIT. */
-void
-async_do_nothing ()
+static void
+async_do_nothing (arg)
+ gdb_client_data arg;
{
/* Empty function body. */
}
@@ -863,17 +861,18 @@ async_do_nothing ()
#ifdef SIGHUP
/* Tell the event loop what to do if SIGHUP is received.
See event-signal.c. */
-void
+static void
handle_sighup (sig)
int sig;
{
- mark_async_signal_handler (sighup_token);
+ mark_async_signal_handler_wrapper (sighup_token);
signal (sig, handle_sighup);
}
-/* Called by the event loop to process a SIGHUP. */
-void
-async_disconnect ()
+/* Called by the event loop to process a SIGHUP */
+static void
+async_disconnect (arg)
+ gdb_client_data arg;
{
catch_errors (quit_cover, NULL,
"Could not kill the program being debugged",
@@ -883,19 +882,49 @@ async_disconnect ()
}
#endif
+#ifdef STOP_SIGNAL
+void handle_stop_sig (sig)
+ int sig;
+{
+ mark_async_signal_handler_wrapper (sigtstp_token);
+ signal (sig, handle_stop_sig);
+}
+
+static void
+async_stop_sig (arg)
+ gdb_client_data arg;
+{
+ char *prompt = PROMPT (0);
+#if STOP_SIGNAL == SIGTSTP
+ signal (SIGTSTP, SIG_DFL);
+ sigsetmask (0);
+ kill (getpid (), SIGTSTP);
+ signal (SIGTSTP, handle_stop_sig);
+#else
+ signal (STOP_SIGNAL, handle_stop_sig);
+#endif
+ printf_unfiltered ("%s", prompt);
+ gdb_flush (gdb_stdout);
+
+ /* Forget about any previous command -- null line now will do nothing. */
+ dont_repeat ();
+}
+#endif /* STOP_SIGNAL */
+
/* Tell the event loop what to do if SIGFPE is received.
See event-signal.c. */
-void
+static void
handle_sigfpe (sig)
int sig;
{
- mark_async_signal_handler (sigfpe_token);
+ mark_async_signal_handler_wrapper (sigfpe_token);
signal (sig, handle_sigfpe);
}
/* Event loop will call this functin to process a SIGFPE. */
-void
-async_float_handler ()
+static void
+async_float_handler (arg)
+ gdb_client_data arg;
{
/* This message is based on ANSI C, section 4.7. Note that integer
divide by zero causes this, so "float" is a misnomer. */
@@ -905,11 +934,11 @@ async_float_handler ()
/* Tell the event loop what to do if SIGWINCH is received.
See event-signal.c. */
#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
-void
+static void
handle_sigwinch (sig)
int sig;
{
- mark_async_signal_handler (sigwinch_token);
+ mark_async_signal_handler_wrapper (sigwinch_token);
signal (sig, handle_sigwinch);
}
#endif
@@ -948,6 +977,40 @@ set_async_prompt (args, from_tty, c)
PROMPT (0) = savestring (new_async_prompt, strlen (new_async_prompt));
}
+/* Set things up for readline to be invoked via the alternate
+ interface, i.e. via a callback function (rl_callback_read_char),
+ and hook up instream to the event loop.*/
+void
+_initialize_event_loop ()
+{
+ /* When a character is detected on instream by select or poll, readline
+ will be invoked via this callback function. */
+ call_readline = rl_callback_read_char;
+ /* When readline has read an end-of-line character, it passes the
+ complete line to gdb for processing. command_line_handler is the
+ function that does this. */
+ input_handler = command_line_handler;
+
+ /* Tell readline to use the same input stream that gdb uses. */
+ rl_instream = instream;
+
+ /* Get a file descriptor for the input stream, so that we can
+ register it with the event loop. */
+ input_fd = fileno (instream);
+ /* Now we need to create the event sources for the input file descriptor. */
+ /* At this point in time, this is the only event source that we
+ register with the even loop. 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. */
+#ifdef HAVE_POLL
+ create_file_handler (input_fd, POLLIN,
+ (file_handler_func *) call_readline, 0);
+#else
+ create_file_handler (input_fd, GDB_READABLE,
+ (file_handler_func *) call_readline, 0);
+#endif
+}