Tidy up formatting.
[deliverable/binutils-gdb.git] / gdb / event-top.c
index 376352eb2b886eb94f0828af6558da6f203bc576..34bf5dffc8c21b82bc38c5cbe0e25df6d40daf03 100644 (file)
 #include "defs.h"
 #include "top.h"
 #include "inferior.h"
+#include "target.h"
 #include "terminal.h"          /* for job_control */
-#include <signal.h>
+#include "signals.h"
 #include "event-loop.h"
+#include "event-top.h"
+
+/* For dont_repeat() */
+#include "gdbcmd.h"
 
 /* readline include files */
 #include <readline/readline.h>
 #include <readline/history.h>
 
+#include <signal.h>
+
 /* readline defines this.  */
 #undef savestring
 
-extern void _initialize_event_loop PARAMS ((void));
+extern void _initialize_event_loop (void);
 
-static void command_line_handler PARAMS ((char *));
-static void command_line_handler_continuation PARAMS ((struct continuation_arg *));
-void gdb_readline2 PARAMS ((void));
-void pop_prompt PARAMS ((void));
-void push_prompt PARAMS ((char *, char *, char *));
-static void change_line_handler PARAMS ((void));
-static void change_annotation_level PARAMS ((void));
-static void command_handler PARAMS ((char *));
+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. */
-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
+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. */
-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.  */
-#ifndef ISATTY
-#define ISATTY(FP)     (isatty (fileno (FP)))
-#endif
+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
@@ -92,8 +89,8 @@ static void async_stop_sig PARAMS ((gdb_client_data));
    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) PARAMS ((char *));
-void (*call_readline) PARAMS ((void));
+void (*input_handler) (char *);
+void (*call_readline) (gdb_client_data);
 
 /* Important variables for the event loop. */
 
@@ -113,6 +110,10 @@ char *new_async_prompt;
    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;
@@ -128,21 +129,19 @@ 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. */
-PTR sigint_token;
+void *sigint_token;
 #ifdef SIGHUP
-PTR sighup_token;
+void *sighup_token;
 #endif
-PTR sigquit_token;
-PTR sigfpe_token;
+void *sigquit_token;
+void *sigfpe_token;
 #if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
-PTR sigwinch_token;
+void *sigwinch_token;
 #endif
 #ifdef STOP_SIGNAL
-PTR sigtstp_token;
+void *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
    because each line of input is handled by a different call to
@@ -158,10 +157,19 @@ struct readline_input_state
 readline_input_state;
 \f
 
+/* Wrapper function foe 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 ();
+}
+
 /* Initialize all the necessary variables, start the event loop,
    register readline, and stdin, start the loop. */
 void
-cli_command_loop ()
+cli_command_loop (void)
 {
   int length;
   char *a_prompt;
@@ -195,12 +203,18 @@ cli_command_loop ()
    which the user sets editing on again, by restoring readline
    handling of the input. */
 static void
-change_line_handler ()
+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;
+      call_readline = rl_callback_read_char_wrapper;
       input_handler = command_line_handler;
     }
   else
@@ -213,18 +227,6 @@ change_line_handler ()
          first thing from .gdbinit. */
       input_handler = command_line_handler;
     }
-
-  /* To tell the event loop to change the handler associated with the
-     input file descriptor, we need to create a new event source,
-     corresponding to the same fd, but with a new event handler
-     function. */
-  /* 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. */
-  delete_file_handler (input_fd);
-  add_file_handler (input_fd, (file_handler_func *) call_readline, 0);
 }
 
 /* Displays the prompt. The prompt that is displayed is the current
@@ -239,29 +241,34 @@ change_line_handler ()
    3. Other????
    FIXME: 2. & 3. not implemented yet for async. */
 void
-display_gdb_prompt (new_prompt)
-     char *new_prompt;
+display_gdb_prompt (char *new_prompt)
 {
   int prompt_length = 0;
   char *gdb_prompt = get_prompt ();
 
+#ifdef UI_OUT
+  /* When an alternative interpreter has been installed, do not
+     display the comand prompt. */
+  if (interpreter_p)
+    return;
+#endif
 
-  if (target_executing && sync_execution) 
+  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. */
+         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;
@@ -312,7 +319,7 @@ display_gdb_prompt (new_prompt)
    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 ()
+change_annotation_level (void)
 {
   char *prefix, *suffix;
 
@@ -357,10 +364,7 @@ change_annotation_level ()
    strings, except when the annotation level is 2. Memory is allocated
    within savestring for the new prompt. */
 void
-push_prompt (prefix, prompt, suffix)
-     char *prefix;
-     char *prompt;
-     char *suffix;
+push_prompt (char *prefix, char *prompt, char *suffix)
 {
   the_prompts.top++;
   PREFIX (0) = savestring (prefix, strlen (prefix));
@@ -378,7 +382,7 @@ push_prompt (prefix, prompt, suffix)
 
 /* Pops the top of the prompt stack, and frees the memory allocated for it. */
 void
-pop_prompt ()
+pop_prompt (void)
 {
   /* If we are not during a 'synchronous' execution command, in which
      case, the top prompt would be empty. */
@@ -398,7 +402,64 @@ pop_prompt ()
   free (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);
+}
 \f
+
 /* Handles a gdb command. This function is called by
    command_line_handler, which has processed one or more input lines
    into COMMAND. */
@@ -406,8 +467,7 @@ pop_prompt ()
    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 (command)
-     char *command;
+command_handler (char *command)
 {
   struct cleanup *old_chain;
   int stdin_is_tty = ISATTY (stdin);
@@ -427,7 +487,7 @@ command_handler (command)
   quit_flag = 0;
   if (instream == stdin && stdin_is_tty)
     reinitialize_more_filter ();
-  old_chain = make_cleanup ((make_cleanup_func) command_loop_marker, 0);
+  old_chain = make_cleanup (command_loop_marker, 0);
 
 #if defined(TUI)
   insert_mode = 0;
@@ -457,7 +517,7 @@ command_handler (command)
   /* Set things up for this function to be compete later, once the
      executin has completed, if we are doing an execution command,
      otherwise, just go ahead and finish. */
-  if (target_has_async && target_executing)
+  if (target_can_async_p () && target_executing)
     {
       arg1 =
        (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
@@ -465,15 +525,15 @@ command_handler (command)
        (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
       arg1->next = arg2;
       arg2->next = NULL;
-      arg1->data = (PTR) time_at_cmd_start;
-      arg2->data = (PTR) space_at_cmd_start;
+      arg1->data.integer = time_at_cmd_start;
+      arg2->data.integer = space_at_cmd_start;
       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_has_async || !target_executing)
+  if (!target_can_async_p () || !target_executing)
     {
       bpstat_do_actions (&stop_bpstat);
       do_cleanups (old_chain);
@@ -507,14 +567,13 @@ command_handler (command)
    are always running synchronously. Or if we have just executed a
    command that doesn't start the target. */
 void
-command_line_handler_continuation (arg)
-     struct continuation_arg *arg;
+command_line_handler_continuation (struct continuation_arg *arg)
 {
   extern int display_time;
   extern int display_space;
 
-  long time_at_cmd_start = (long) arg->data;
-  long space_at_cmd_start = (long) arg->next->data;
+  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????? */
@@ -551,8 +610,7 @@ command_line_handler_continuation (arg)
    obsolete once we use the event loop as the default mechanism in
    GDB. */
 static void
-command_line_handler (rl)
-     char *rl;
+command_line_handler (char *rl)
 {
   static char *linebuffer = 0;
   static unsigned linelength = 0;
@@ -634,9 +692,8 @@ command_line_handler (rl)
 
   free (rl);                   /* Allocated in readline.  */
 
-  if (p == linebuffer || *(p - 1) == '\\')
+  if (*(p - 1) == '\\')
     {
-      /* We come here also if the line entered is empty (just a 'return') */
       p--;                     /* Put on top of '\'.  */
 
       if (*p == '\\')
@@ -769,12 +826,25 @@ command_line_handler (rl)
    will become obsolete when the event loop is made the default
    execution for gdb. */
 void
-gdb_readline2 ()
+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);
 
@@ -839,7 +909,7 @@ gdb_readline2 ()
    init_signals will become obsolete as we move to have to event loop
    as the default for gdb. */
 void
-async_init_signals ()
+async_init_signals (void)
 {
   signal (SIGINT, handle_sigint);
   sigint_token =
@@ -887,17 +957,15 @@ async_init_signals ()
 }
 
 void
-mark_async_signal_handler_wrapper (token)
-     void *token;
+mark_async_signal_handler_wrapper (void *token)
 {
-  mark_async_signal_handler ((async_signal_handler *) 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 (sig)
-     int sig;
+handle_sigint (int sig)
 {
   signal (sig, handle_sigint);
 
@@ -918,8 +986,7 @@ handle_sigint (sig)
 
 /* Do the quit. All the checks have been done by the caller. */
 void
-async_request_quit (arg)
-     gdb_client_data arg;
+async_request_quit (gdb_client_data arg)
 {
   quit_flag = 1;
 #ifdef REQUEST_QUIT
@@ -932,8 +999,7 @@ async_request_quit (arg)
 /* Tell the event loop what to do if SIGQUIT is received. 
    See event-signal.c. */
 static void
-handle_sigquit (sig)
-     int sig;
+handle_sigquit (int sig)
 {
   mark_async_signal_handler_wrapper (sigquit_token);
   signal (sig, handle_sigquit);
@@ -941,8 +1007,7 @@ handle_sigquit (sig)
 
 /* Called by the event loop in response to a SIGQUIT. */
 static void
-async_do_nothing (arg)
-     gdb_client_data arg;
+async_do_nothing (gdb_client_data arg)
 {
   /* Empty function body. */
 }
@@ -960,8 +1025,7 @@ handle_sighup (sig)
 
 /* Called by the event loop to process a SIGHUP */
 static void
-async_disconnect (arg)
-     gdb_client_data arg;
+async_disconnect (gdb_client_data arg)
 {
   catch_errors (quit_cover, NULL,
                "Could not kill the program being debugged",
@@ -973,21 +1037,27 @@ async_disconnect (arg)
 
 #ifdef STOP_SIGNAL
 void
-handle_stop_sig (sig)
-     int sig;
+handle_stop_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;
+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);
+  }
+#else
   sigsetmask (0);
+#endif
   kill (getpid (), SIGTSTP);
   signal (SIGTSTP, handle_stop_sig);
 #else
@@ -1004,8 +1074,7 @@ async_stop_sig (arg)
 /* Tell the event loop what to do if SIGFPE is received. 
    See event-signal.c. */
 static void
-handle_sigfpe (sig)
-     int sig;
+handle_sigfpe (int sig)
 {
   mark_async_signal_handler_wrapper (sigfpe_token);
   signal (sig, handle_sigfpe);
@@ -1013,8 +1082,7 @@ handle_sigfpe (sig)
 
 /* Event loop will call this functin to process a SIGFPE. */
 static void
-async_float_handler (arg)
-     gdb_client_data arg;
+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. */
@@ -1025,8 +1093,7 @@ async_float_handler (arg)
    See event-signal.c. */
 #if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
 static void
-handle_sigwinch (sig)
-     int sig;
+handle_sigwinch (int sig)
 {
   mark_async_signal_handler_wrapper (sigwinch_token);
   signal (sig, handle_sigwinch);
@@ -1037,10 +1104,7 @@ handle_sigwinch (sig)
 /* Called by do_setshow_command.  */
 /* ARGSUSED */
 void
-set_async_editing_command (args, from_tty, c)
-     char *args;
-     int from_tty;
-     struct cmd_list_element *c;
+set_async_editing_command (char *args, int from_tty, struct cmd_list_element *c)
 {
   change_line_handler ();
 }
@@ -1048,10 +1112,7 @@ set_async_editing_command (args, from_tty, c)
 /* Called by do_setshow_command.  */
 /* ARGSUSED */
 void
-set_async_annotation_level (args, from_tty, c)
-     char *args;
-     int from_tty;
-     struct cmd_list_element *c;
+set_async_annotation_level (char *args, int from_tty, struct cmd_list_element *c)
 {
   change_annotation_level ();
 }
@@ -1059,10 +1120,7 @@ set_async_annotation_level (args, from_tty, c)
 /* Called by do_setshow_command.  */
 /* ARGSUSED */
 void
-set_async_prompt (args, from_tty, c)
-     char *args;
-     int from_tty;
-     struct cmd_list_element *c;
+set_async_prompt (char *args, int from_tty, struct cmd_list_element *c)
 {
   PROMPT (0) = savestring (new_async_prompt, strlen (new_async_prompt));
 }
@@ -1071,13 +1129,29 @@ set_async_prompt (args, from_tty, c)
    interface, i.e. via a callback function (rl_callback_read_char),
    and hook up instream to the event loop. */
 void
-_initialize_event_loop ()
+_initialize_event_loop (void)
 {
-  if (async_p)
+  if (event_loop_p)
     {
-      /* 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;
+      /* 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
@@ -1101,11 +1175,6 @@ _initialize_event_loop ()
          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, (file_handler_func *) call_readline, 0);
-
-      /* 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;
+      add_file_handler (input_fd, stdin_event_handler, 0);
     }
 }
This page took 0.047545 seconds and 4 git commands to generate.