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.c1168
1 files changed, 0 insertions, 1168 deletions
diff --git a/gdb/event-top.c b/gdb/event-top.c
deleted file mode 100644
index 86c658d..0000000
--- a/gdb/event-top.c
+++ /dev/null
@@ -1,1168 +0,0 @@
-/* Top level stuff for GDB, the GNU debugger.
- Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
- Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#include "defs.h"
-#include "top.h"
-#include "inferior.h"
-#include "target.h"
-#include "terminal.h" /* for job_control */
-#include "event-loop.h"
-#include "event-top.h"
-#include <signal.h>
-
-/* For dont_repeat() */
-#include "gdbcmd.h"
-
-/* readline include files */
-#include <readline/readline.h>
-#include <readline/history.h>
-
-/* readline defines this. */
-#undef savestring
-
-extern void _initialize_event_loop (void);
-
-static void rl_callback_read_char_wrapper (gdb_client_data client_data);
-static void command_line_handler (char *rl);
-static void command_line_handler_continuation (struct continuation_arg *arg);
-static void change_line_handler (void);
-static void change_annotation_level (void);
-static void command_handler (char *command);
-void cli_command_loop (void);
-static void async_do_nothing (gdb_client_data arg);
-static void async_disconnect (gdb_client_data arg);
-static void async_stop_sig (gdb_client_data arg);
-static void async_float_handler (gdb_client_data arg);
-
-/* Signal handlers. */
-static void handle_sigquit (int sig);
-static void handle_sighup (int sig);
-static void handle_sigfpe (int sig);
-#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
-static void handle_sigwinch (int sig);
-#endif
-
-/* Functions to be invoked by the event loop in response to
- signals. */
-static void async_do_nothing (gdb_client_data);
-static void async_disconnect (gdb_client_data);
-static void async_float_handler (gdb_client_data);
-static void async_stop_sig (gdb_client_data);
-
-/* 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
- the event loop uses as callback (i.e. event handler) whenever an event
- is detected on the standard input file descriptor.
- readline_callback_read_char is called (by the GDB event loop) whenever
- there is a new character ready on the input stream. This function
- incrementally builds a buffer internal to readline where it
- accumulates the line read up to the point of invocation. In the
- special case in which the character read is newline, the function
- invokes a GDB supplied callback routine, which does the processing of
- a full command line. This latter routine is the asynchronous analog
- of the old command_line_input in gdb. Instead of invoking (and waiting
- for) readline to read the command line and pass it back to
- command_loop for processing, the new command_line_handler function has
- the command line already available as its parameter. INPUT_HANDLER is
- to be set to the function that readline will invoke when a complete
- line of input is ready. CALL_READLINE is to be set to the function
- that readline offers as callback to the event_loop. */
-
-void (*input_handler) (char *);
-void (*call_readline) (gdb_client_data);
-
-/* Important variables for the event loop. */
-
-/* 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.
- 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. */
-int async_command_editing_p;
-
-/* This variable contains the new prompt that the user sets with the
- set prompt command. */
-char *new_async_prompt;
-
-/* This is the annotation suffix that will be used when the
- annotation_level is 2. */
-char *async_annotation_suffix;
-
-/* This is used to display the notification of the completion of an
- asynchronous execution command. */
-int exec_done_display_p = 0;
-
-/* This is the file descriptor for the input stream that GDB uses to
- read commands from. */
-int input_fd;
-
-/* This is the prompt stack. Prompts will be pushed on the stack as
- needed by the different 'kinds' of user inputs GDB is asking
- for. See event-loop.h. */
-struct prompts the_prompts;
-
-/* signal handling variables */
-/* Each of these is a pointer to a function that the event loop will
- invoke if the corresponding signal has received. The real signal
- 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. */
-void *sigint_token;
-#ifdef SIGHUP
-void *sighup_token;
-#endif
-void *sigquit_token;
-void *sigfpe_token;
-#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
-void *sigwinch_token;
-#endif
-#ifdef STOP_SIGNAL
-void *sigtstp_token;
-#endif
-
-/* Structure to save a partially entered command. This is used when
- the user types '\' at the end of a command line. This is necessary
- because each line of input is handled by a different call to
- command_line_handler, and normally there is no state retained
- between different calls. */
-int more_to_come = 0;
-
-struct readline_input_state
- {
- char *linebuffer;
- char *linebuffer_ptr;
- }
-readline_input_state;
-
-/* This hook is called by rl_callback_read_char_wrapper after each
- character is processed. */
-void (*after_char_processing_hook) ();
-
-
-/* Wrapper function for calling into the readline library. The event
- loop expects the callback function to have a paramter, while readline
- expects none. */
-static void
-rl_callback_read_char_wrapper (gdb_client_data client_data)
-{
- rl_callback_read_char ();
- if (after_char_processing_hook)
- (*after_char_processing_hook) ();
-}
-
-/* Initialize all the necessary variables, start the event loop,
- register readline, and stdin, start the loop. */
-void
-cli_command_loop (void)
-{
- int length;
- char *a_prompt;
- char *gdb_prompt = get_prompt ();
-
- /* 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 (gdb_prompt) + strlen (SUFFIX (0)) + 1;
- a_prompt = (char *) xmalloc (length);
- strcpy (a_prompt, PREFIX (0));
- strcat (a_prompt, gdb_prompt);
- strcat (a_prompt, SUFFIX (0));
- rl_callback_handler_install (a_prompt, input_handler);
- }
- else
- display_gdb_prompt (0);
-
- /* Now it's time to start the event loop. */
- start_event_loop ();
-}
-
-/* Change the function to be invoked every time there is a character
- ready on stdin. This is used when the user sets the editing off,
- therefore bypassing readline, and letting gdb handle the input
- itself, via gdb_readline2. Also it is used in the opposite case in
- which the user sets editing on again, by restoring readline
- handling of the input. */
-static void
-change_line_handler (void)
-{
- /* NOTE: this operates on input_fd, not instream. If we are reading
- commands from a file, instream will point to the file. However in
- async mode, we always read commands from a file with editing
- off. This means that the 'set editing on/off' will have effect
- only on the interactive session. */
-
- if (async_command_editing_p)
- {
- /* Turn on editing by using readline. */
- call_readline = rl_callback_read_char_wrapper;
- 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;
- }
-}
-
-/* Displays the prompt. The prompt that is displayed is the current
- 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.
- 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????
- FIXME: 2. & 3. not implemented yet for async. */
-void
-display_gdb_prompt (char *new_prompt)
-{
- int prompt_length = 0;
- char *gdb_prompt = get_prompt ();
-
- /* When an alternative interpreter has been installed, do not
- display the comand prompt. */
- if (interpreter_p)
- return;
-
- if (target_executing && sync_execution)
- {
- /* This is to trick readline into not trying to display the
- prompt. Even though we display the prompt using this
- function, readline still tries to do its own display if we
- don't call rl_callback_handler_install and
- rl_callback_handler_remove (which readline detects because a
- global variable is not set). If readline did that, it could
- mess up gdb signal handlers for SIGINT. Readline assumes
- that between calls to rl_set_signals and rl_clear_signals gdb
- doesn't do anything with the signal handlers. Well, that's
- not the case, because when the target executes we change the
- SIGINT signal handler. If we allowed readline to display the
- prompt, the signal handler change would happen exactly
- between the calls to the above two functions.
- Calling rl_callback_handler_remove(), does the job. */
-
- rl_callback_handler_remove ();
- return;
- }
-
- if (!new_prompt)
- {
- /* Just use the top of the prompt stack. */
- prompt_length = strlen (PREFIX (0)) +
- strlen (SUFFIX (0)) +
- strlen (gdb_prompt) + 1;
-
- new_prompt = (char *) alloca (prompt_length);
-
- /* Prefix needs to have new line at end. */
- strcpy (new_prompt, PREFIX (0));
- strcat (new_prompt, gdb_prompt);
- /* Suffix needs to have a new line at end and \032 \032 at
- beginning. */
- strcat (new_prompt, SUFFIX (0));
- }
-
- if (async_command_editing_p)
- {
- rl_callback_handler_remove ();
- rl_callback_handler_install (new_prompt, input_handler);
- }
- /* new_prompt at this point can be the top of the stack or the one passed in */
- else if (new_prompt)
- {
- /* 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 (new_prompt, gdb_stdout);
- gdb_flush (gdb_stdout);
- }
-}
-
-/* Used when the user requests a different annotation level, with
- 'set annotate'. It pushes a new prompt (with prefix and suffix) on top
- of the prompt stack, if the annotation level desired is 2, otherwise
- it pops the top of the prompt stack when we want the annotation level
- to be the normal ones (1 or 0). */
-static void
-change_annotation_level (void)
-{
- char *prefix, *suffix;
-
- if (!PREFIX (0) || !PROMPT (0) || !SUFFIX (0))
- {
- /* The prompt stack has not been initialized to "", we are
- using gdb w/o the --async switch */
- warning ("Command has same effect as set annotate");
- return;
- }
-
- if (annotation_level > 1)
- {
- if (!strcmp (PREFIX (0), "") && !strcmp (SUFFIX (0), ""))
- {
- /* Push a new prompt if the previous annotation_level was not >1. */
- prefix = (char *) alloca (strlen (async_annotation_suffix) + 10);
- strcpy (prefix, "\n\032\032pre-");
- strcat (prefix, async_annotation_suffix);
- strcat (prefix, "\n");
-
- suffix = (char *) alloca (strlen (async_annotation_suffix) + 6);
- strcpy (suffix, "\n\032\032");
- strcat (suffix, async_annotation_suffix);
- strcat (suffix, "\n");
-
- push_prompt (prefix, (char *) 0, suffix);
- }
- }
- else
- {
- if (strcmp (PREFIX (0), "") && strcmp (SUFFIX (0), ""))
- {
- /* Pop the top of the stack, we are going back to annotation < 1. */
- pop_prompt ();
- }
- }
-}
-
-/* Pushes a new prompt on the prompt stack. Each prompt has three
- parts: prefix, prompt, suffix. Usually prefix and suffix are empty
- strings, except when the annotation level is 2. Memory is allocated
- within savestring for the new prompt. */
-void
-push_prompt (char *prefix, char *prompt, char *suffix)
-{
- the_prompts.top++;
- PREFIX (0) = savestring (prefix, strlen (prefix));
-
- /* Note that this function is used by the set annotate 2
- command. This is why we take care of saving the old prompt
- in case a new one is not specified. */
- if (prompt)
- PROMPT (0) = savestring (prompt, strlen (prompt));
- else
- PROMPT (0) = savestring (PROMPT (-1), strlen (PROMPT (-1)));
-
- SUFFIX (0) = savestring (suffix, strlen (suffix));
-}
-
-/* Pops the top of the prompt stack, and frees the memory allocated for it. */
-void
-pop_prompt (void)
-{
- /* If we are not during a 'synchronous' execution command, in which
- case, the top prompt would be empty. */
- if (strcmp (PROMPT (0), ""))
- /* This is for the case in which the prompt is set while the
- annotation level is 2. The top prompt will be changed, but when
- we return to annotation level < 2, we want that new prompt to be
- in effect, until the user does another 'set prompt'. */
- if (strcmp (PROMPT (0), PROMPT (-1)))
- {
- xfree (PROMPT (-1));
- PROMPT (-1) = savestring (PROMPT (0), strlen (PROMPT (0)));
- }
-
- xfree (PREFIX (0));
- xfree (PROMPT (0));
- xfree (SUFFIX (0));
- the_prompts.top--;
-}
-
-/* When there is an event ready on the stdin file desriptor, instead
- of calling readline directly throught the callback function, or
- instead of calling gdb_readline2, give gdb a chance to detect
- errors and do something. */
-void
-stdin_event_handler (int error, gdb_client_data client_data)
-{
- if (error)
- {
- printf_unfiltered ("error detected on stdin\n");
- delete_file_handler (input_fd);
- discard_all_continuations ();
- /* If stdin died, we may as well kill gdb. */
- quit_command ((char *) 0, stdin == instream);
- }
- else
- (*call_readline) (client_data);
-}
-
-/* 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. */
-
-void
-async_enable_stdin (void *dummy)
-{
- /* See NOTE in async_disable_stdin() */
- /* FIXME: cagney/1999-09-27: Call this before clearing
- sync_execution. Current target_terminal_ours() implementations
- check for sync_execution before switching the terminal. */
- target_terminal_ours ();
- pop_prompt ();
- sync_execution = 0;
-}
-
-/* Disable reads from stdin (the console) marking the command as
- synchronous. */
-
-void
-async_disable_stdin (void)
-{
- sync_execution = 1;
- push_prompt ("", "", "");
- /* FIXME: cagney/1999-09-27: At present this call is technically
- redundant since infcmd.c and infrun.c both already call
- target_terminal_inferior(). As the terminal handling (in
- sync/async mode) is refined, the duplicate calls can be
- eliminated (Here or in infcmd.c/infrun.c). */
- target_terminal_inferior ();
- /* Add the reinstate of stdin to the list of cleanups to be done
- in case the target errors out and dies. These cleanups are also
- done in case of normal successful termination of the execution
- command, by complete_execution(). */
- make_exec_error_cleanup (async_enable_stdin, NULL);
-}
-
-
-/* Handles a gdb command. This function is called by
- command_line_handler, which has processed one or more input lines
- into COMMAND. */
-/* NOTE: 1999-04-30 This is the asynchronous version of the command_loop
- function. The command_loop function will be obsolete when we
- switch to use the event loop at every execution of gdb. */
-static void
-command_handler (char *command)
-{
- struct cleanup *old_chain;
- int stdin_is_tty = ISATTY (stdin);
- struct continuation_arg *arg1;
- struct continuation_arg *arg2;
- long time_at_cmd_start;
-#ifdef HAVE_SBRK
- long space_at_cmd_start = 0;
-#endif
- extern int display_time;
- extern int display_space;
-
- quit_flag = 0;
- if (instream == stdin && stdin_is_tty)
- reinitialize_more_filter ();
- old_chain = make_cleanup (null_cleanup, 0);
-
- /* If readline returned a NULL command, it means that the
- connection with the terminal is gone. This happens at the
- end of a testsuite run, after Expect has hung up
- but GDB is still alive. In such a case, we just quit gdb
- killing the inferior program too. */
- if (command == 0)
- quit_command ((char *) 0, stdin == instream);
-
- time_at_cmd_start = get_run_time ();
-
- if (display_space)
- {
-#ifdef HAVE_SBRK
- extern char **environ;
- char *lim = (char *) sbrk (0);
-
- space_at_cmd_start = (long) (lim - (char *) &environ);
-#endif
- }
-
- execute_command (command, instream == stdin);
-
- /* Set things up for this function to be compete later, once the
- execution has completed, if we are doing an execution command,
- otherwise, just go ahead and finish. */
- if (target_can_async_p () && target_executing)
- {
- arg1 =
- (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
- arg2 =
- (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
- arg1->next = arg2;
- arg2->next = NULL;
- arg1->data.longint = time_at_cmd_start;
-#ifdef HAVE_SBRK
- arg2->data.longint = space_at_cmd_start;
-#endif
- add_continuation (command_line_handler_continuation, arg1);
- }
-
- /* Do any commands attached to breakpoint we stopped at. Only if we
- are always running synchronously. Or if we have just executed a
- command that doesn't start the target. */
- if (!target_can_async_p () || !target_executing)
- {
- bpstat_do_actions (&stop_bpstat);
- do_cleanups (old_chain);
-
- if (display_time)
- {
- long cmd_time = get_run_time () - time_at_cmd_start;
-
- printf_unfiltered ("Command execution time: %ld.%06ld\n",
- cmd_time / 1000000, cmd_time % 1000000);
- }
-
- if (display_space)
- {
-#ifdef HAVE_SBRK
- extern char **environ;
- char *lim = (char *) sbrk (0);
- long space_now = lim - (char *) &environ;
- long space_diff = space_now - space_at_cmd_start;
-
- printf_unfiltered ("Space used: %ld (%c%ld for this command)\n",
- space_now,
- (space_diff >= 0 ? '+' : '-'),
- space_diff);
-#endif
- }
- }
-}
-
-/* Do any commands attached to breakpoint we stopped at. Only if we
- are always running synchronously. Or if we have just executed a
- command that doesn't start the target. */
-void
-command_line_handler_continuation (struct continuation_arg *arg)
-{
- extern int display_time;
- extern int display_space;
-
- long time_at_cmd_start = arg->data.longint;
- long space_at_cmd_start = arg->next->data.longint;
-
- bpstat_do_actions (&stop_bpstat);
- /*do_cleanups (old_chain); *//*?????FIXME????? */
-
- if (display_time)
- {
- long cmd_time = get_run_time () - time_at_cmd_start;
-
- printf_unfiltered ("Command execution time: %ld.%06ld\n",
- cmd_time / 1000000, cmd_time % 1000000);
- }
- if (display_space)
- {
-#ifdef HAVE_SBRK
- extern char **environ;
- char *lim = (char *) sbrk (0);
- long space_now = lim - (char *) &environ;
- long space_diff = space_now - space_at_cmd_start;
-
- printf_unfiltered ("Space used: %ld (%c%ld for this command)\n",
- space_now,
- (space_diff >= 0 ? '+' : '-'),
- space_diff);
-#endif
- }
-}
-
-/* Handle a complete line of input. This is called by the callback
- mechanism within the readline library. Deal with incomplete commands
- as well, by saving the partial input in a global buffer. */
-
-/* NOTE: 1999-04-30 This is the asynchronous version of the
- command_line_input function. command_line_input will become
- obsolete once we use the event loop as the default mechanism in
- GDB. */
-static void
-command_line_handler (char *rl)
-{
- static char *linebuffer = 0;
- static unsigned linelength = 0;
- register char *p;
- char *p1;
- extern char *line;
- extern int linesize;
- char *nline;
- char got_eof = 0;
-
-
- int repeat = (instream == stdin);
-
- if (annotation_level > 1 && instream == stdin)
- {
- printf_unfiltered ("\n\032\032post-");
- printf_unfiltered (async_annotation_suffix);
- printf_unfiltered ("\n");
- }
-
- if (linebuffer == 0)
- {
- linelength = 80;
- linebuffer = (char *) xmalloc (linelength);
- }
-
- p = linebuffer;
-
- if (more_to_come)
- {
- strcpy (linebuffer, readline_input_state.linebuffer);
- p = readline_input_state.linebuffer_ptr;
- xfree (readline_input_state.linebuffer);
- more_to_come = 0;
- pop_prompt ();
- }
-
-#ifdef STOP_SIGNAL
- if (job_control)
- signal (STOP_SIGNAL, handle_stop_sig);
-#endif
-
- /* 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. */
- wrap_here ("");
- gdb_flush (gdb_stdout);
- gdb_flush (gdb_stderr);
-
- if (source_file_name != NULL)
- {
- ++source_line_number;
- sprintf (source_error,
- "%s%s:%d: Error in sourced command file:\n",
- source_pre_error,
- source_file_name,
- source_line_number);
- error_pre_print = source_error;
- }
-
- /* If we are in this case, then command_handler will call quit
- and exit from gdb. */
- if (!rl || rl == (char *) EOF)
- {
- got_eof = 1;
- command_handler (0);
- }
- 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) == '\\')
- {
- p--; /* Put on top of '\'. */
-
- readline_input_state.linebuffer = savestring (linebuffer,
- strlen (linebuffer));
- readline_input_state.linebuffer_ptr = p;
-
- /* We will not invoke a execute_command if there is more
- input expected to complete the command. So, we need to
- print an empty prompt here. */
- more_to_come = 1;
- push_prompt ("", "", "");
- display_gdb_prompt (0);
- return;
- }
-
-#ifdef STOP_SIGNAL
- if (job_control)
- signal (STOP_SIGNAL, SIG_DFL);
-#endif
-
-#define SERVER_COMMAND_LENGTH 7
- server_command =
- (p - linebuffer > SERVER_COMMAND_LENGTH)
- && STREQN (linebuffer, "server ", SERVER_COMMAND_LENGTH);
- 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';
- command_handler (linebuffer + SERVER_COMMAND_LENGTH);
- display_gdb_prompt (0);
- return;
- }
-
- /* 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;
- }
- 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 && *p != '\\')
- {
- command_handler (line);
- display_gdb_prompt (0);
- return;
- }
-
- for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++);
- if (repeat && !*p1)
- {
- command_handler (line);
- display_gdb_prompt (0);
- return;
- }
-
- *p = 0;
-
- /* Add line to history if appropriate. */
- if (instream == stdin
- && ISATTY (stdin) && *linebuffer)
- add_history (linebuffer);
-
- /* Note: lines consisting solely of comments are added to the command
- history. This is useful when you type a command, and then
- realize you don't want to execute it quite yet. You can comment
- out the command 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 (*p1 == '#')
- *p1 = '\0'; /* Found a comment. */
-
- /* Save into global buffer if appropriate. */
- if (repeat)
- {
- if (linelength > linesize)
- {
- line = xrealloc (line, linelength);
- linesize = linelength;
- }
- strcpy (line, linebuffer);
- if (!more_to_come)
- {
- command_handler (line);
- display_gdb_prompt (0);
- }
- return;
- }
-
- command_handler (linebuffer);
- display_gdb_prompt (0);
- return;
-}
-
-/* Does reading of input from terminal w/o the editing features
- provided by the readline library. */
-
-/* NOTE: 1999-04-30 Asynchronous version of gdb_readline. gdb_readline
- will become obsolete when the event loop is made the default
- execution for gdb. */
-void
-gdb_readline2 (gdb_client_data client_data)
-{
- int c;
- char *result;
- int input_index = 0;
- int result_size = 80;
- static int done_once = 0;
-
- /* Unbuffer the input stream, so that, later on, the calls to fgetc
- fetch only one char at the time from the stream. The fgetc's will
- get up to the first newline, but there may be more chars in the
- stream after '\n'. If we buffer the input and fgetc drains the
- stream, getting stuff beyond the newline as well, a select, done
- afterwards will not trigger. */
- if (!done_once && !ISATTY (instream))
- {
- setbuf (instream, NULL);
- done_once = 1;
- }
-
- result = (char *) xmalloc (result_size);
-
- /* We still need the while loop here, even though it would seem
- obvious to invoke gdb_readline2 at every character entered. If
- not using the readline library, the terminal is in cooked mode,
- which sends the characters all at once. Poll will notice that the
- input fd has changed state only after enter is pressed. At this
- point we still need to fetch all the chars entered. */
-
- 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);
-
- if (c == EOF)
- {
- if (input_index > 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);
- (*input_handler) (0);
- }
-
- if (c == '\n')
-#ifndef CRLF_SOURCE_FILES
- break;
-#else
- {
- if (input_index > 0 && result[input_index - 1] == '\r')
- input_index--;
- break;
- }
-#endif
-
- result[input_index++] = c;
- while (input_index >= result_size)
- {
- result_size *= 2;
- result = (char *) xrealloc (result, result_size);
- }
- }
-
- result[input_index++] = '\0';
- (*input_handler) (result);
-}
-
-
-/* Initialization of signal handlers and tokens. There is a function
- handle_sig* for each of the signals GDB cares about. Specifically:
- SIGINT, SIGFPE, SIGQUIT, SIGTSTP, SIGHUP, SIGWINCH. These
- functions are the actual signal handlers associated to the signals
- via calls to signal(). The only job for these functions is to
- enqueue the appropriate event/procedure with the event loop. Such
- procedures are the old signal handlers. The event loop will take
- care of invoking the queued procedures to perform the usual tasks
- associated with the reception of the signal. */
-/* NOTE: 1999-04-30 This is the asynchronous version of init_signals.
- init_signals will become obsolete as we move to have to event loop
- as the default for gdb. */
-void
-async_init_signals (void)
-{
- signal (SIGINT, handle_sigint);
- sigint_token =
- 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. */
-#ifdef SIGTRAP
- signal (SIGTRAP, SIG_DFL);
-#endif
-
- /* If we initialize SIGQUIT to SIG_IGN, then the SIG_IGN will get
- passed to the inferior, which we don't want. It would be
- possible to do a "signal (SIGQUIT, SIG_DFL)" after we fork, but
- on BSD4.3 systems using vfork, that can affect the
- GDB process as well as the inferior (the signal handling tables
- might be in memory, shared between the two). Since we establish
- a handler for SIGQUIT, when we call exec it will set the signal
- to SIG_DFL for us. */
- signal (SIGQUIT, handle_sigquit);
- sigquit_token =
- create_async_signal_handler (async_do_nothing, NULL);
-#ifdef SIGHUP
- if (signal (SIGHUP, handle_sighup) != SIG_IGN)
- sighup_token =
- create_async_signal_handler (async_disconnect, NULL);
- else
- sighup_token =
- create_async_signal_handler (async_do_nothing, NULL);
-#endif
- signal (SIGFPE, handle_sigfpe);
- sigfpe_token =
- create_async_signal_handler (async_float_handler, NULL);
-
-#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
- signal (SIGWINCH, handle_sigwinch);
- sigwinch_token =
- 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 (void *token)
-{
- mark_async_signal_handler ((struct async_signal_handler *) token);
-}
-
-/* Tell the event loop what to do if SIGINT is received.
- See event-signal.c. */
-void
-handle_sigint (int sig)
-{
- signal (sig, handle_sigint);
-
- /* If immediate_quit is set, we go ahead and process the SIGINT right
- away, even if we usually would defer this to the event loop. The
- assumption here is that it is safe to process ^C immediately if
- immediate_quit is set. If we didn't, SIGINT would be really
- processed only the next time through the event loop. To get to
- that point, though, the command that we want to interrupt needs to
- finish first, which is unacceptable. */
- if (immediate_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_wrapper (sigint_token);
-}
-
-/* Do the quit. All the checks have been done by the caller. */
-void
-async_request_quit (gdb_client_data arg)
-{
- quit_flag = 1;
-#ifdef REQUEST_QUIT
- REQUEST_QUIT;
-#else
- quit ();
-#endif
-}
-
-/* Tell the event loop what to do if SIGQUIT is received.
- See event-signal.c. */
-static void
-handle_sigquit (int sig)
-{
- mark_async_signal_handler_wrapper (sigquit_token);
- signal (sig, handle_sigquit);
-}
-
-/* Called by the event loop in response to a SIGQUIT. */
-static void
-async_do_nothing (gdb_client_data arg)
-{
- /* Empty function body. */
-}
-
-#ifdef SIGHUP
-/* Tell the event loop what to do if SIGHUP is received.
- See event-signal.c. */
-static void
-handle_sighup (int sig)
-{
- mark_async_signal_handler_wrapper (sighup_token);
- signal (sig, handle_sighup);
-}
-
-/* Called by the event loop to process a SIGHUP */
-static void
-async_disconnect (gdb_client_data arg)
-{
- catch_errors (quit_cover, NULL,
- "Could not kill the program being debugged",
- RETURN_MASK_ALL);
- signal (SIGHUP, SIG_DFL); /*FIXME: ??????????? */
- kill (getpid (), SIGHUP);
-}
-#endif
-
-#ifdef STOP_SIGNAL
-void
-handle_stop_sig (int sig)
-{
- mark_async_signal_handler_wrapper (sigtstp_token);
- signal (sig, handle_stop_sig);
-}
-
-static void
-async_stop_sig (gdb_client_data arg)
-{
- char *prompt = get_prompt ();
-#if STOP_SIGNAL == SIGTSTP
- signal (SIGTSTP, SIG_DFL);
-#if HAVE_SIGPROCMASK
- {
- sigset_t zero;
-
- sigemptyset (&zero);
- sigprocmask (SIG_SETMASK, &zero, 0);
- }
-#elif HAVE_SIGSETMASK
- sigsetmask (0);
-#endif
- 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. */
-static void
-handle_sigfpe (int sig)
-{
- mark_async_signal_handler_wrapper (sigfpe_token);
- signal (sig, handle_sigfpe);
-}
-
-/* Event loop will call this functin to process a SIGFPE. */
-static void
-async_float_handler (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. */
- error ("Erroneous arithmetic operation.");
-}
-
-/* Tell the event loop what to do if SIGWINCH is received.
- See event-signal.c. */
-#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
-static void
-handle_sigwinch (int sig)
-{
- mark_async_signal_handler_wrapper (sigwinch_token);
- signal (sig, handle_sigwinch);
-}
-#endif
-
-
-/* Called by do_setshow_command. */
-/* ARGSUSED */
-void
-set_async_editing_command (char *args, int from_tty, struct cmd_list_element *c)
-{
- change_line_handler ();
-}
-
-/* Called by do_setshow_command. */
-/* ARGSUSED */
-void
-set_async_annotation_level (char *args, int from_tty, struct cmd_list_element *c)
-{
- change_annotation_level ();
-}
-
-/* Called by do_setshow_command. */
-/* ARGSUSED */
-void
-set_async_prompt (char *args, int from_tty, struct cmd_list_element *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 (void)
-{
- if (event_loop_p)
- {
- /* If the input stream is connected to a terminal, turn on
- editing. */
- if (ISATTY (instream))
- {
- /* Tell gdb that we will be using the readline library. This
- could be overwritten by a command in .gdbinit like 'set
- editing on' or 'off'. */
- async_command_editing_p = 1;
-
- /* 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_wrapper;
- }
- else
- {
- async_command_editing_p = 0;
- call_readline = gdb_readline2;
- }
-
- /* 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);
-
- /* Tell gdb to use the cli_command_loop as the main loop. */
- command_loop_hook = cli_command_loop;
-
- /* 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. */
- add_file_handler (input_fd, stdin_event_handler, 0);
- }
-}