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. */
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
-#include "event-loop.h"
-#include <readline/readline.h>
-#include <setjmp.h>
-#include "top.h"
-
-/* For config.h which may define HAVE_POLL */
#include "defs.h"
-
+#include "top.h"
+#include "event-loop.h"
#ifdef HAVE_POLL
-#include <sys/poll.h>
+#include <poll.h>
+#else
+#include <sys/types.h>
#endif
#include <errno.h>
+#include <setjmp.h>
/* Event queue:
- the first event in the queue is the head of the queue.
Events can be inserted at the front of the queue or at the end of
the queue. Events will be extracted from the queue for processing
starting from the head. Therefore, events inserted at the head of
- the queue will be processed in a last in first out fashoin, while
+ the queue will be processed in a last in first out fashion, while
those inserted at the tail of the queue will be processed in a first
in first out manner. All the fields are NULL if the queue is
empty. */
basically a description of what kind of events gdb is interested
in, for each fd. */
-/* As of 4/30/99 only the input file descriptor is registered with the
+/* As of 1999-04-30 only the input file descriptor is registered with the
event loop. */
#ifdef HAVE_POLL
static struct
{
/* Pointer to first in handler list. */
- async_signal_handler *first_handler;
-
+ async_signal_handler *first_handler;
+
/* Pointer to last in handler list. */
- async_signal_handler *last_handler;
+ async_signal_handler *last_handler;
}
sighandler_list;
function. */
static int async_handler_ready = 0;
+static void create_file_handler PARAMS ((int, int, handler_func *, gdb_client_data));
static void invoke_async_signal_handler PARAMS ((void));
+static void handle_file_event PARAMS ((int));
static int gdb_wait_for_event PARAMS ((void));
+static int gdb_do_one_event PARAMS ((void));
static int check_async_ready PARAMS ((void));
-extern display_gdb_prompt PARAMS ((char *));
\f
/* Insert an event object into the gdb event queue at
}
}
+/* Create a file event, to be enqueued in the event queue for
+ processing. The procedure associated to this event is always
+ handle_file_event, which will in turn invoke the one that was
+ associated to FD when it was registered with the event loop. */
+gdb_event *
+create_file_event (fd)
+ int fd;
+{
+ gdb_event *file_event_ptr;
+
+ file_event_ptr = (gdb_event *) xmalloc (sizeof (gdb_event));
+ file_event_ptr->proc = handle_file_event;
+ file_event_ptr->fd = fd;
+ return (file_event_ptr);
+}
+
/* Process one event.
The event can be the next one to be serviced in the event queue,
or an asynchronous event handler can be invoked in response to
wait for something to happen (via gdb_wait_for_event), then process
it. Returns 1 if something was done otherwise returns 0 (this can
happen if there are no event sources to wait for). */
-int
+static int
gdb_do_one_event ()
{
int result = 0;
} /* end of if !set_top_level */
else
{
+ /* FIXME: this should really be a call to a hook that is
+ interface specific, because interfaces can display the
+ prompt in their own way. */
display_gdb_prompt (0);
/* Maybe better to set a flag to be checked somewhere as to
whether display the prompt or not. */
}
\f
+/* Start up the event loop. This is the entry point to the event loop
+ from the command loop. */
+void
+start_event_loop ()
+{
+ /* 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
+ for each invocation. It always returns 1, unless there are no
+ more event sources registered. In this case it returns 0. */
+ while (gdb_do_one_event () != 0)
+ ;
+
+ /* We are done with the event loop. There are no more event sources
+ to listen to. So we exit GDB. */
+ return;
+}
+\f
+
+
+/* Wrapper function for create_file_handler, so that the caller
+ doesn't have to know implementation details about the use of poll
+ vs. select. */
+void
+add_file_handler (fd, proc, client_data)
+ int fd;
+ void (*proc) (void);
+ gdb_client_data client_data;
+{
+#ifdef HAVE_POLL
+ create_file_handler (fd, POLLIN, (handler_func *) proc, client_data);
+#else
+ create_file_handler (fd, GDB_READABLE, (handler_func *) proc, client_data);
+#endif
+}
+
/* Add a file handler/descriptor to the list of descriptors we are
interested in.
FD is the file descriptor for the file/stream to be listened to.
For the select case, MASK is a combination of READABLE, WRITABLE, EXCEPTION.
PROC is the procedure that will be called when an event occurs for
FD. CLIENT_DATA is the argument to pass to PROC. */
-void
+static void
create_file_handler (fd, mask, proc, client_data)
int fd;
int mask;
- file_handler_func *proc;
+ handler_func *proc;
gdb_client_data client_data;
{
file_handler *file_ptr;
#ifdef HAVE_POLL
gdb_notifier.num_fds++;
- gdb_notifier.poll_fds =
- (struct pollfd *) realloc (gdb_notifier.poll_fds,
+ if (gdb_notifier.poll_fds)
+ gdb_notifier.poll_fds =
+ (struct pollfd *) realloc (gdb_notifier.poll_fds,
(gdb_notifier.num_fds) * sizeof (struct pollfd));
+ else
+ gdb_notifier.poll_fds =
+ (struct pollfd *) xmalloc (sizeof (struct pollfd));
(gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->fd = fd;
(gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->events = mask;
(gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->revents = 0;
if (file_ptr == NULL)
return;
- /* Deactivate the file descriptor, by clearing its mask,
- so that it will not fire again. */
-
- file_ptr->mask = 0;
-
#ifdef HAVE_POLL
/* Create a new poll_fds array by copying every fd's information but the
one we want to get rid of. */
}
#endif /* HAVE_POLL */
+ /* Deactivate the file descriptor, by clearing its mask,
+ so that it will not fire again. */
+
+ file_ptr->mask = 0;
+
/* Get rid of the file handler in the file handler list. */
if (file_ptr == gdb_notifier.first_file_handler)
gdb_notifier.first_file_handler = file_ptr->next_file;
else
{
for (prev_ptr = gdb_notifier.first_file_handler;
- prev_ptr->next_file == file_ptr;
+ prev_ptr->next_file != file_ptr;
prev_ptr = prev_ptr->next_file)
;
prev_ptr->next_file = file_ptr->next_file;
/* If there was a match, then call the handler. */
if (mask != 0)
- (*file_ptr->proc) (file_ptr->client_data, mask);
+ (*file_ptr->proc) (file_ptr->client_data);
break;
}
}
{
file_handler *file_ptr;
gdb_event *file_event_ptr;
- int num_found, i;
+ int num_found = 0;
+ int i;
#ifndef HAVE_POLL
int mask, bit, index;
#endif
+ /* Make sure all output is done before getting another event. */
+ gdb_flush (gdb_stdout);
+ gdb_flush (gdb_stderr);
+
if (gdb_notifier.num_fds == 0)
return -1;
this fd. */
if (file_ptr->ready_mask == 0)
{
- file_event_ptr =
- (gdb_event *) xmalloc (sizeof (gdb_event));
- file_event_ptr->proc = handle_file_event;
- file_event_ptr->fd = file_ptr->fd;
+ file_event_ptr = create_file_event (file_ptr->fd);
async_queue_event (file_event_ptr, TAIL);
}
}
if (file_ptr->ready_mask == 0)
{
- file_event_ptr =
- (gdb_event *) xmalloc (sizeof (gdb_event));
- file_event_ptr->proc = handle_file_event;
- file_event_ptr->fd = file_ptr->fd;
+ file_event_ptr = create_file_event (file_ptr->fd);
async_queue_event (file_event_ptr, TAIL);
}
file_ptr->ready_mask = mask;
whenever the handler is invoked. */
async_signal_handler *
create_async_signal_handler (proc, client_data)
- async_handler_func *proc;
+ handler_func *proc;
gdb_client_data client_data;
{
async_signal_handler *async_handler_ptr;
while (1)
{
- for (async_handler_ptr = sighandler_list.first_handler;
+ for (async_handler_ptr = sighandler_list.first_handler;
async_handler_ptr != NULL;
async_handler_ptr = async_handler_ptr->next_handler)
{
Free the space allocated for it. */
void
delete_async_signal_handler (async_handler_ptr)
- async_signal_handler *async_handler_ptr;
+ async_signal_handler **async_handler_ptr;
{
async_signal_handler *prev_ptr;
- if (sighandler_list.first_handler == async_handler_ptr)
+ if (sighandler_list.first_handler == (*async_handler_ptr))
{
- sighandler_list.first_handler = async_handler_ptr->next_handler;
+ sighandler_list.first_handler = (*async_handler_ptr)->next_handler;
if (sighandler_list.first_handler == NULL)
sighandler_list.last_handler = NULL;
}
else
{
prev_ptr = sighandler_list.first_handler;
- while (prev_ptr->next_handler != async_handler_ptr)
+ while (prev_ptr->next_handler != (*async_handler_ptr) && prev_ptr)
prev_ptr = prev_ptr->next_handler;
- prev_ptr->next_handler = async_handler_ptr->next_handler;
- if (sighandler_list.last_handler == async_handler_ptr)
+ prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
+ if (sighandler_list.last_handler == (*async_handler_ptr))
sighandler_list.last_handler = prev_ptr;
}
- free ((char *) async_handler_ptr);
+ free ((char *) (*async_handler_ptr));
+ (*async_handler_ptr) = NULL;
}
/* Is it necessary to call invoke_async_signal_handler? */