| /* Handling of inferior events for the event loop for GDB, the GNU debugger. | 
 |    Copyright (C) 1999, 2007, 2008, 2009 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 3 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, see <http://www.gnu.org/licenses/>. */ | 
 |  | 
 | #include "defs.h" | 
 | #include "inferior.h"		/* For fetch_inferior_event. */ | 
 | #include "target.h"             /* For enum inferior_event_type. */ | 
 | #include "event-loop.h" | 
 | #include "event-top.h" | 
 | #include "inf-loop.h" | 
 | #include "remote.h" | 
 | #include "exceptions.h" | 
 | #include "language.h" | 
 | #include "gdbthread.h" | 
 |  | 
 | static int fetch_inferior_event_wrapper (gdb_client_data client_data); | 
 |  | 
 | void | 
 | inferior_event_handler_wrapper (gdb_client_data client_data) | 
 | { | 
 |   inferior_event_handler (INF_QUIT_REQ, client_data); | 
 | } | 
 |  | 
 | /* General function to handle events in the inferior. So far it just | 
 |    takes care of detecting errors reported by select() or poll(), | 
 |    otherwise it assumes that all is OK, and goes on reading data from | 
 |    the fd. This however may not always be what we want to do. */ | 
 | void | 
 | inferior_event_handler (enum inferior_event_type event_type,  | 
 | 			gdb_client_data client_data) | 
 | { | 
 |   struct gdb_exception e; | 
 |   int was_sync = 0; | 
 |   switch (event_type) | 
 |     { | 
 |     case INF_ERROR: | 
 |       printf_unfiltered (_("error detected from target.\n")); | 
 |       pop_all_targets_above (file_stratum, 0); | 
 |       discard_all_intermediate_continuations (); | 
 |       discard_all_continuations (); | 
 |       async_enable_stdin (); | 
 |       break; | 
 |  | 
 |     case INF_REG_EVENT: | 
 |       /* Use catch errors for now, until the inner layers of | 
 | 	 fetch_inferior_event (i.e. readchar) can return meaningful | 
 | 	 error status.  If an error occurs while getting an event from | 
 | 	 the target, just get rid of the target. */ | 
 |       if (!catch_errors (fetch_inferior_event_wrapper,  | 
 | 			 client_data, "", RETURN_MASK_ALL)) | 
 | 	{ | 
 | 	  pop_all_targets_above (file_stratum, 0); | 
 | 	  discard_all_intermediate_continuations (); | 
 | 	  discard_all_continuations (); | 
 | 	  async_enable_stdin (); | 
 | 	  display_gdb_prompt (0); | 
 | 	} | 
 |       break; | 
 |  | 
 |     case INF_EXEC_COMPLETE: | 
 |  | 
 |       if (!non_stop) | 
 | 	{ | 
 | 	  /* Unregister the inferior from the event loop. This is done | 
 | 	     so that when the inferior is not running we don't get | 
 | 	     distracted by spurious inferior output.  */ | 
 | 	  if (target_has_execution) | 
 | 	    target_async (NULL, 0); | 
 | 	} | 
 |  | 
 |       /* The call to async_enable_stdin below resets 'sync_execution'. | 
 | 	 However, if sync_execution is 1 now, we also need to show the | 
 | 	 prompt below, so save the current value.  */ | 
 |       was_sync = sync_execution; | 
 |       async_enable_stdin (); | 
 |  | 
 |       /* Do all continuations associated with the whole inferior (not | 
 | 	 a particular thread).  */ | 
 |       if (!ptid_equal (inferior_ptid, null_ptid)) | 
 | 	do_all_inferior_continuations (); | 
 |  | 
 |       /* If we were doing a multi-step (eg: step n, next n), but it | 
 | 	 got interrupted by a breakpoint, still do the pending | 
 | 	 continuations.  The continuation itself is responsible for | 
 | 	 distinguishing the cases.  The continuations are allowed to | 
 | 	 touch the inferior memory, e.g. to remove breakpoints, so run | 
 | 	 them before running breakpoint commands, which may resume the | 
 | 	 target.  */ | 
 |       if (non_stop | 
 | 	  && target_has_execution | 
 | 	  && !ptid_equal (inferior_ptid, null_ptid)) | 
 | 	do_all_intermediate_continuations_thread (inferior_thread ()); | 
 |       else | 
 | 	do_all_intermediate_continuations (); | 
 |  | 
 |       /* Always finish the previous command before running any | 
 | 	 breakpoint commands.  Any stop cancels the previous command. | 
 | 	 E.g. a "finish" or "step-n" command interrupted by an | 
 | 	 unrelated breakpoint is canceled.  */ | 
 |       if (non_stop | 
 | 	  && target_has_execution | 
 | 	  && !ptid_equal (inferior_ptid, null_ptid)) | 
 | 	do_all_continuations_thread (inferior_thread ()); | 
 |       else | 
 | 	do_all_continuations (); | 
 |  | 
 |       if (current_language != expected_language | 
 | 	  && language_mode == language_mode_auto) | 
 | 	language_info (1);	/* Print what changed.  */ | 
 |  | 
 |       /* Don't propagate breakpoint commands errors.  Either we're | 
 | 	 stopping or some command resumes the inferior.  The user will | 
 | 	 be informed.  */ | 
 |       TRY_CATCH (e, RETURN_MASK_ALL) | 
 | 	{ | 
 | 	  bpstat_do_actions (); | 
 | 	} | 
 |  | 
 |       if (!was_sync | 
 | 	  && exec_done_display_p | 
 | 	  && (ptid_equal (inferior_ptid, null_ptid) | 
 | 	      || !is_running (inferior_ptid))) | 
 | 	printf_unfiltered (_("completed.\n")); | 
 |       break; | 
 |  | 
 |     case INF_EXEC_CONTINUE: | 
 |       /* Is there anything left to do for the command issued to | 
 |          complete? */ | 
 |  | 
 |       if (non_stop) | 
 | 	do_all_intermediate_continuations_thread (inferior_thread ()); | 
 |       else | 
 | 	do_all_intermediate_continuations (); | 
 |       break; | 
 |  | 
 |     case INF_QUIT_REQ:  | 
 |       /* FIXME: ezannoni 1999-10-04. This call should really be a | 
 | 	 target vector entry, so that it can be used for any kind of | 
 | 	 targets. */ | 
 |       async_remote_interrupt_twice (NULL); | 
 |       break; | 
 |  | 
 |     case INF_TIMER: | 
 |     default: | 
 |       printf_unfiltered (_("Event type not recognized.\n")); | 
 |       break; | 
 |     } | 
 | } | 
 |  | 
 | static int  | 
 | fetch_inferior_event_wrapper (gdb_client_data client_data) | 
 | { | 
 |   fetch_inferior_event (client_data); | 
 |   return 1; | 
 | } |