2010-12-28 Michael Snyder <msnyder@vmware.com>

* event-loop.c: Comment clean-up.
	* event-loop.h: Ditto.
	* event-top.c: Ditto.
	* gdb.c: Ditto.
	* gdb.h: Ditto.
	* main.c: Ditto.
	* top.c: Ditto.
	* top.h: Ditto.
This commit is contained in:
Michael Snyder 2010-12-29 00:58:14 +00:00
parent 551ce43ca7
commit 371d5dec8e
9 changed files with 500 additions and 454 deletions

View file

@ -1,3 +1,14 @@
2010-12-28 Michael Snyder <msnyder@vmware.com>
* event-loop.c: Comment clean-up.
* event-loop.h: Ditto.
* event-top.c: Ditto.
* gdb.c: Ditto.
* gdb.h: Ditto.
* main.c: Ditto.
* top.c: Ditto.
* top.h: Ditto.
2010-12-28 Pedro Alves <pedro@codesourcery.com> 2010-12-28 Pedro Alves <pedro@codesourcery.com>
* ax-gdb.c (gen_expr) <OP_REGISTER>: Error out if trying to * ax-gdb.c (gen_expr) <OP_REGISTER>: Error out if trying to

View file

@ -16,7 +16,7 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h" #include "defs.h"
#include "event-loop.h" #include "event-loop.h"
@ -39,7 +39,7 @@
#include "gdb_select.h" #include "gdb_select.h"
/* Tell create_file_handler what events we are interested in. /* Tell create_file_handler what events we are interested in.
This is used by the select version of the event loop. */ This is used by the select version of the event loop. */
#define GDB_READABLE (1<<1) #define GDB_READABLE (1<<1)
#define GDB_WRITABLE (1<<2) #define GDB_WRITABLE (1<<2)
@ -56,12 +56,12 @@ typedef struct gdb_event gdb_event;
typedef void (event_handler_func) (event_data); typedef void (event_handler_func) (event_data);
/* Event for the GDB event system. Events are queued by calling /* Event for the GDB event system. Events are queued by calling
async_queue_event and serviced later on by gdb_do_one_event. An async_queue_event and serviced later on by gdb_do_one_event. An
event can be, for instance, a file descriptor becoming ready to be event can be, for instance, a file descriptor becoming ready to be
read. Servicing an event simply means that the procedure PROC will read. Servicing an event simply means that the procedure PROC will
be called. We have 2 queues, one for file handlers that we listen be called. We have 2 queues, one for file handlers that we listen
to in the event loop, and one for the file handlers+events that are to in the event loop, and one for the file handlers+events that are
ready. The procedure PROC associated with each event is dependant ready. The procedure PROC associated with each event is dependant
of the event source. In the case of monitored file descriptors, it of the event source. In the case of monitored file descriptors, it
is always the same (handle_file_event). Its duty is to invoke the is always the same (handle_file_event). Its duty is to invoke the
handler associated with the file descriptor whose state change handler associated with the file descriptor whose state change
@ -82,36 +82,39 @@ struct gdb_event
}; };
/* Information about each file descriptor we register with the event /* Information about each file descriptor we register with the event
loop. */ loop. */
typedef struct file_handler typedef struct file_handler
{ {
int fd; /* File descriptor. */ int fd; /* File descriptor. */
int mask; /* Events we want to monitor: POLLIN, etc. */ int mask; /* Events we want to monitor: POLLIN, etc. */
int ready_mask; /* Events that have been seen since int ready_mask; /* Events that have been seen since
the last time. */ the last time. */
handler_func *proc; /* Procedure to call when fd is ready. */ handler_func *proc; /* Procedure to call when fd is ready. */
gdb_client_data client_data; /* Argument to pass to proc. */ gdb_client_data client_data; /* Argument to pass to proc. */
int error; /* Was an error detected on this fd? */ int error; /* Was an error detected on this fd? */
struct file_handler *next_file; /* Next registered file descriptor. */ struct file_handler *next_file; /* Next registered file descriptor. */
} }
file_handler; file_handler;
/* PROC is a function to be invoked when the READY flag is set. This /* PROC is a function to be invoked when the READY flag is set. This
happens when there has been a signal and the corresponding signal happens when there has been a signal and the corresponding signal
handler has 'triggered' this async_signal_handler for handler has 'triggered' this async_signal_handler for execution.
execution. The actual work to be done in response to a signal will The actual work to be done in response to a signal will be carried
be carried out by PROC at a later time, within process_event. This out by PROC at a later time, within process_event. This provides a
provides a deferred execution of signal handlers. deferred execution of signal handlers.
Async_init_signals takes care of setting up such an Async_init_signals takes care of setting up such an
async_signal_handler for each interesting signal. */ async_signal_handler for each interesting signal. */
typedef struct async_signal_handler typedef struct async_signal_handler
{ {
int ready; /* If ready, call this handler from the main event loop, int ready; /* If ready, call this handler
using invoke_async_handler. */ from the main event loop, using
struct async_signal_handler *next_handler; /* Ptr to next handler */ invoke_async_handler. */
sig_handler_func *proc; /* Function to call to do the work */ struct async_signal_handler *next_handler; /* Ptr to next handler. */
gdb_client_data client_data; /* Argument to async_handler_func */ sig_handler_func *proc; /* Function to call to do the work. */
gdb_client_data client_data; /* Argument to async_handler_func. */
} }
async_signal_handler; async_signal_handler;
@ -150,25 +153,25 @@ async_event_handler;
the queue will be processed in a last in first out fashion, 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 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 in first out manner. All the fields are NULL if the queue is
empty. */ empty. */
static struct static struct
{ {
gdb_event *first_event; /* First pending event */ gdb_event *first_event; /* First pending event. */
gdb_event *last_event; /* Last pending event */ gdb_event *last_event; /* Last pending event. */
} }
event_queue; event_queue;
/* Gdb_notifier is just a list of file descriptors gdb is interested in. /* Gdb_notifier is just a list of file descriptors gdb is interested in.
These are the input file descriptor, and the target file These are the input file descriptor, and the target file
descriptor. We have two flavors of the notifier, one for platforms descriptor. We have two flavors of the notifier, one for platforms
that have the POLL function, the other for those that don't, and that have the POLL function, the other for those that don't, and
only support SELECT. Each of the elements in the gdb_notifier list is only support SELECT. Each of the elements in the gdb_notifier list is
basically a description of what kind of events gdb is interested basically a description of what kind of events gdb is interested
in, for each fd. */ in, for each fd. */
/* As of 1999-04-30 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. */ event loop. */
/* Do we use poll or select ? */ /* Do we use poll or select ? */
#ifdef HAVE_POLL #ifdef HAVE_POLL
@ -186,79 +189,79 @@ static unsigned char use_poll = USE_POLL;
static struct static struct
{ {
/* Ptr to head of file handler list. */ /* Ptr to head of file handler list. */
file_handler *first_file_handler; file_handler *first_file_handler;
#ifdef HAVE_POLL #ifdef HAVE_POLL
/* Ptr to array of pollfd structures. */ /* Ptr to array of pollfd structures. */
struct pollfd *poll_fds; struct pollfd *poll_fds;
/* Timeout in milliseconds for calls to poll(). */ /* Timeout in milliseconds for calls to poll(). */
int poll_timeout; int poll_timeout;
#endif #endif
/* Masks to be used in the next call to select. /* Masks to be used in the next call to select.
Bits are set in response to calls to create_file_handler. */ Bits are set in response to calls to create_file_handler. */
fd_set check_masks[3]; fd_set check_masks[3];
/* What file descriptors were found ready by select. */ /* What file descriptors were found ready by select. */
fd_set ready_masks[3]; fd_set ready_masks[3];
/* Number of file descriptors to monitor. (for poll) */ /* Number of file descriptors to monitor (for poll). */
/* Number of valid bits (highest fd value + 1). (for select) */ /* Number of valid bits (highest fd value + 1) (for select). */
int num_fds; int num_fds;
/* Time structure for calls to select(). */ /* Time structure for calls to select(). */
struct timeval select_timeout; struct timeval select_timeout;
/* Flag to tell whether the timeout should be used. */ /* Flag to tell whether the timeout should be used. */
int timeout_valid; int timeout_valid;
} }
gdb_notifier; gdb_notifier;
/* Structure associated with a timer. PROC will be executed at the /* Structure associated with a timer. PROC will be executed at the
first occasion after WHEN. */ first occasion after WHEN. */
struct gdb_timer struct gdb_timer
{ {
struct timeval when; struct timeval when;
int timer_id; int timer_id;
struct gdb_timer *next; struct gdb_timer *next;
timer_handler_func *proc; /* Function to call to do the work */ timer_handler_func *proc; /* Function to call to do the work. */
gdb_client_data client_data; /* Argument to async_handler_func */ gdb_client_data client_data; /* Argument to async_handler_func. */
}; };
/* List of currently active timers. It is sorted in order of /* List of currently active timers. It is sorted in order of
increasing timers. */ increasing timers. */
static struct static struct
{ {
/* Pointer to first in timer list. */ /* Pointer to first in timer list. */
struct gdb_timer *first_timer; struct gdb_timer *first_timer;
/* Id of the last timer created. */ /* Id of the last timer created. */
int num_timers; int num_timers;
} }
timer_list; timer_list;
/* All the async_signal_handlers gdb is interested in are kept onto /* All the async_signal_handlers gdb is interested in are kept onto
this list. */ this list. */
static struct static struct
{ {
/* Pointer to first in handler list. */ /* Pointer to first in handler list. */
async_signal_handler *first_handler; async_signal_handler *first_handler;
/* Pointer to last in handler list. */ /* Pointer to last in handler list. */
async_signal_handler *last_handler; async_signal_handler *last_handler;
} }
sighandler_list; sighandler_list;
/* All the async_event_handlers gdb is interested in are kept onto /* All the async_event_handlers gdb is interested in are kept onto
this list. */ this list. */
static struct static struct
{ {
/* Pointer to first in handler list. */ /* Pointer to first in handler list. */
async_event_handler *first_handler; async_event_handler *first_handler;
/* Pointer to last in handler list. */ /* Pointer to last in handler list. */
async_event_handler *last_handler; async_event_handler *last_handler;
} }
async_event_handler_list; async_event_handler_list;
@ -276,18 +279,18 @@ static void poll_timers (void);
the specified position. the specified position.
POSITION can be head or tail, with values TAIL, HEAD. POSITION can be head or tail, with values TAIL, HEAD.
EVENT_PTR points to the event to be inserted into the queue. EVENT_PTR points to the event to be inserted into the queue.
The caller must allocate memory for the event. It is freed The caller must allocate memory for the event. It is freed
after the event has ben handled. after the event has ben handled.
Events in the queue will be processed head to tail, therefore, Events in the queue will be processed head to tail, therefore,
events inserted at the head of the queue will be processed events inserted at the head of the queue will be processed
as last in first out. Event appended at the tail of the queue as last in first out. Event appended at the tail of the queue
will be processed first in first out. */ will be processed first in first out. */
static void static void
async_queue_event (gdb_event * event_ptr, queue_position position) async_queue_event (gdb_event * event_ptr, queue_position position)
{ {
if (position == TAIL) if (position == TAIL)
{ {
/* The event will become the new last_event. */ /* The event will become the new last_event. */
event_ptr->next_event = NULL; event_ptr->next_event = NULL;
if (event_queue.first_event == NULL) if (event_queue.first_event == NULL)
@ -298,7 +301,7 @@ async_queue_event (gdb_event * event_ptr, queue_position position)
} }
else if (position == HEAD) else if (position == HEAD)
{ {
/* The event becomes the new first_event. */ /* The event becomes the new first_event. */
event_ptr->next_event = event_queue.first_event; event_ptr->next_event = event_queue.first_event;
if (event_queue.first_event == NULL) if (event_queue.first_event == NULL)
@ -324,9 +327,9 @@ create_event (event_handler_func proc, event_data data)
} }
/* Create a file event, to be enqueued in the event queue for /* Create a file event, to be enqueued in the event queue for
processing. The procedure associated to this event is always processing. The procedure associated to this event is always
handle_file_event, which will in turn invoke the one that was handle_file_event, which will in turn invoke the one that was
associated to FD when it was registered with the event loop. */ associated to FD when it was registered with the event loop. */
static gdb_event * static gdb_event *
create_file_event (int fd) create_file_event (int fd)
{ {
@ -344,7 +347,7 @@ create_file_event (int fd)
0 is returned. 0 is returned.
Scan the queue from head to tail, processing therefore the high Scan the queue from head to tail, processing therefore the high
priority events first, by invoking the associated event handler priority events first, by invoking the associated event handler
procedure. */ procedure. */
static int static int
process_event (void) process_event (void)
{ {
@ -353,19 +356,19 @@ process_event (void)
event_data data; event_data data;
/* First let's see if there are any asynchronous event handlers that /* First let's see if there are any asynchronous event handlers that
are ready. These would be the result of invoking any of the are ready. These would be the result of invoking any of the
signal handlers. */ signal handlers. */
if (invoke_async_signal_handlers ()) if (invoke_async_signal_handlers ())
return 1; return 1;
/* Look in the event queue to find an event that is ready /* Look in the event queue to find an event that is ready
to be processed. */ to be processed. */
for (event_ptr = event_queue.first_event; event_ptr != NULL; for (event_ptr = event_queue.first_event; event_ptr != NULL;
event_ptr = event_ptr->next_event) event_ptr = event_ptr->next_event)
{ {
/* Call the handler for the event. */ /* Call the handler for the event. */
proc = event_ptr->proc; proc = event_ptr->proc;
data = event_ptr->data; data = event_ptr->data;
@ -373,9 +376,9 @@ process_event (void)
/* Let's get rid of the event from the event queue. We need to /* Let's get rid of the event from the event queue. We need to
do this now because while processing the event, the proc do this now because while processing the event, the proc
function could end up calling 'error' and therefore jump out function could end up calling 'error' and therefore jump out
to the caller of this function, gdb_do_one_event. In that to the caller of this function, gdb_do_one_event. In that
case, we would have on the event queue an event wich has been case, we would have on the event queue an event wich has been
processed, but not deleted. */ processed, but not deleted. */
if (event_queue.first_event == event_ptr) if (event_queue.first_event == event_ptr)
{ {
@ -395,12 +398,12 @@ process_event (void)
} }
xfree (event_ptr); xfree (event_ptr);
/* Now call the procedure associated with the event. */ /* Now call the procedure associated with the event. */
(*proc) (data); (*proc) (data);
return 1; return 1;
} }
/* this is the case if there are no event on the event queue. */ /* This is the case if there are no event on the event queue. */
return 0; return 0;
} }
@ -408,7 +411,7 @@ process_event (void)
wait for something to happen (via gdb_wait_for_event), then process wait for something to happen (via gdb_wait_for_event), then process
it. Returns >0 if something was done otherwise returns <0 (this it. Returns >0 if something was done otherwise returns <0 (this
can happen if there are no event sources to wait for). If an error can happen if there are no event sources to wait for). If an error
occurs catch_errors() which calls this function returns zero. */ occurs catch_errors() which calls this function returns zero. */
int int
gdb_do_one_event (void *data) gdb_do_one_event (void *data)
@ -429,7 +432,7 @@ gdb_do_one_event (void *data)
{ {
case 0: case 0:
/* Are any timers that are ready? If so, put an event on the /* Are any timers that are ready? If so, put an event on the
queue. */ queue. */
poll_timers (); poll_timers ();
break; break;
case 1: case 1:
@ -469,18 +472,18 @@ gdb_do_one_event (void *data)
return 1; return 1;
} }
/* Start up the event loop. This is the entry point to the event loop /* Start up the event loop. This is the entry point to the event loop
from the command loop. */ from the command loop. */
void void
start_event_loop (void) start_event_loop (void)
{ {
/* Loop until there is nothing to do. This is the entry point to the /* Loop until there is nothing to do. This is the entry point to the
event loop engine. gdb_do_one_event, called via catch_errors() event loop engine. gdb_do_one_event, called via catch_errors()
will process one event for each invocation. It blocks waits for will process one event for each invocation. It blocks waits for
an event and then processes it. >0 when an event is processed, 0 an event and then processes it. >0 when an event is processed, 0
when catch_errors() caught an error and <0 when there are no when catch_errors() caught an error and <0 when there are no
longer any event sources registered. */ longer any event sources registered. */
while (1) while (1)
{ {
int gdb_result; int gdb_result;
@ -491,7 +494,7 @@ start_event_loop (void)
/* If we long-jumped out of do_one_event, we probably /* If we long-jumped out of do_one_event, we probably
didn't get around to resetting the prompt, which leaves didn't get around to resetting the prompt, which leaves
readline in a messed-up state. Reset it here. */ readline in a messed-up state. Reset it here. */
if (gdb_result == 0) if (gdb_result == 0)
{ {
@ -501,7 +504,7 @@ start_event_loop (void)
async_enable_stdin (); async_enable_stdin ();
/* FIXME: this should really be a call to a hook that is /* FIXME: this should really be a call to a hook that is
interface specific, because interfaces can display the interface specific, because interfaces can display the
prompt in their own way. */ prompt in their own way. */
display_gdb_prompt (0); display_gdb_prompt (0);
/* This call looks bizarre, but it is required. If the user /* This call looks bizarre, but it is required. If the user
entered a command that caused an error, entered a command that caused an error,
@ -512,19 +515,19 @@ start_event_loop (void)
if (after_char_processing_hook) if (after_char_processing_hook)
(*after_char_processing_hook) (); (*after_char_processing_hook) ();
/* Maybe better to set a flag to be checked somewhere as to /* Maybe better to set a flag to be checked somewhere as to
whether display the prompt or not. */ whether display the prompt or not. */
} }
} }
/* We are done with the event loop. There are no more event sources /* We are done with the event loop. There are no more event sources
to listen to. So we exit GDB. */ to listen to. So we exit GDB. */
return; return;
} }
/* Wrapper function for create_file_handler, so that the caller /* Wrapper function for create_file_handler, so that the caller
doesn't have to know implementation details about the use of poll doesn't have to know implementation details about the use of poll
vs. select. */ vs. select. */
void void
add_file_handler (int fd, handler_func * proc, gdb_client_data client_data) add_file_handler (int fd, handler_func * proc, gdb_client_data client_data)
{ {
@ -535,11 +538,11 @@ add_file_handler (int fd, handler_func * proc, gdb_client_data client_data)
if (use_poll) if (use_poll)
{ {
#ifdef HAVE_POLL #ifdef HAVE_POLL
/* Check to see if poll () is usable. If not, we'll switch to /* Check to see if poll () is usable. If not, we'll switch to
use select. This can happen on systems like use select. This can happen on systems like
m68k-motorola-sys, `poll' cannot be used to wait for `stdin'. m68k-motorola-sys, `poll' cannot be used to wait for `stdin'.
On m68k-motorola-sysv, tty's are not stream-based and not On m68k-motorola-sysv, tty's are not stream-based and not
`poll'able. */ `poll'able. */
fds.fd = fd; fds.fd = fd;
fds.events = POLLIN; fds.events = POLLIN;
if (poll (&fds, 1, 0) == 1 && (fds.revents & POLLNVAL)) if (poll (&fds, 1, 0) == 1 && (fds.revents & POLLNVAL))
@ -559,26 +562,32 @@ add_file_handler (int fd, handler_func * proc, gdb_client_data client_data)
#endif #endif
} }
else else
create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION, proc, client_data); create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION,
proc, client_data);
} }
/* Add a file handler/descriptor to the list of descriptors we are /* Add a file handler/descriptor to the list of descriptors we are
interested in. interested in.
FD is the file descriptor for the file/stream to be listened to. FD is the file descriptor for the file/stream to be listened to.
For the poll case, MASK is a combination (OR) of
POLLIN, POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM, For the poll case, MASK is a combination (OR) of POLLIN,
POLLWRBAND: these are the events we are interested in. If any of them POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM, POLLWRBAND:
occurs, proc should be called. these are the events we are interested in. If any of them occurs,
For the select case, MASK is a combination of READABLE, WRITABLE, EXCEPTION. proc should be called.
PROC is the procedure that will be called when an event occurs for
FD. CLIENT_DATA is the argument to pass to PROC. */ 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. */
static void static void
create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data client_data) create_file_handler (int fd, int mask, handler_func * proc,
gdb_client_data client_data)
{ {
file_handler *file_ptr; file_handler *file_ptr;
/* Do we already have a file handler for this file? (We may be /* Do we already have a file handler for this file? (We may be
changing its associated procedure). */ changing its associated procedure). */
for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL; for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
file_ptr = file_ptr->next_file) file_ptr = file_ptr->next_file)
{ {
@ -586,8 +595,8 @@ create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data clie
break; break;
} }
/* It is a new file descriptor. Add it to the list. Otherwise, just /* It is a new file descriptor. Add it to the list. Otherwise, just
change the data associated with it. */ change the data associated with it. */
if (file_ptr == NULL) if (file_ptr == NULL)
{ {
file_ptr = (file_handler *) xmalloc (sizeof (file_handler)); file_ptr = (file_handler *) xmalloc (sizeof (file_handler));
@ -644,7 +653,7 @@ create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data clie
} }
/* Remove the file descriptor FD from the list of monitored fd's: /* Remove the file descriptor FD from the list of monitored fd's:
i.e. we don't care anymore about events on the FD. */ i.e. we don't care anymore about events on the FD. */
void void
delete_file_handler (int fd) delete_file_handler (int fd)
{ {
@ -655,7 +664,7 @@ delete_file_handler (int fd)
struct pollfd *new_poll_fds; struct pollfd *new_poll_fds;
#endif #endif
/* Find the entry for the given file. */ /* Find the entry for the given file. */
for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL; for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
file_ptr = file_ptr->next_file) file_ptr = file_ptr->next_file)
@ -670,11 +679,11 @@ delete_file_handler (int fd)
if (use_poll) if (use_poll)
{ {
#ifdef HAVE_POLL #ifdef HAVE_POLL
/* Create a new poll_fds array by copying every fd's information but the /* Create a new poll_fds array by copying every fd's information
one we want to get rid of. */ but the one we want to get rid of. */
new_poll_fds = new_poll_fds = (struct pollfd *)
(struct pollfd *) xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd)); xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd));
for (i = 0, j = 0; i < gdb_notifier.num_fds; i++) for (i = 0, j = 0; i < gdb_notifier.num_fds; i++)
{ {
@ -703,7 +712,7 @@ delete_file_handler (int fd)
if (file_ptr->mask & GDB_EXCEPTION) if (file_ptr->mask & GDB_EXCEPTION)
FD_CLR (fd, &gdb_notifier.check_masks[2]); FD_CLR (fd, &gdb_notifier.check_masks[2]);
/* Find current max fd. */ /* Find current max fd. */
if ((fd + 1) == gdb_notifier.num_fds) if ((fd + 1) == gdb_notifier.num_fds)
{ {
@ -720,11 +729,11 @@ delete_file_handler (int fd)
} }
/* Deactivate the file descriptor, by clearing its mask, /* Deactivate the file descriptor, by clearing its mask,
so that it will not fire again. */ so that it will not fire again. */
file_ptr->mask = 0; file_ptr->mask = 0;
/* Get rid of the file handler in the file handler list. */ /* Get rid of the file handler in the file handler list. */
if (file_ptr == gdb_notifier.first_file_handler) if (file_ptr == gdb_notifier.first_file_handler)
gdb_notifier.first_file_handler = file_ptr->next_file; gdb_notifier.first_file_handler = file_ptr->next_file;
else else
@ -741,7 +750,7 @@ delete_file_handler (int fd)
/* Handle the given event by calling the procedure associated to the /* Handle the given event by calling the procedure associated to the
corresponding file handler. Called by process_event indirectly, corresponding file handler. Called by process_event indirectly,
through event_ptr->proc. EVENT_FILE_DESC is file descriptor of the through event_ptr->proc. EVENT_FILE_DESC is file descriptor of the
event in the front of the event queue. */ event in the front of the event queue. */
static void static void
handle_file_event (event_data data) handle_file_event (event_data data)
{ {
@ -754,21 +763,21 @@ handle_file_event (event_data data)
int event_file_desc = data.integer; int event_file_desc = data.integer;
/* Search the file handler list to find one that matches the fd in /* Search the file handler list to find one that matches the fd in
the event. */ the event. */
for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL; for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
file_ptr = file_ptr->next_file) file_ptr = file_ptr->next_file)
{ {
if (file_ptr->fd == event_file_desc) if (file_ptr->fd == event_file_desc)
{ {
/* With poll, the ready_mask could have any of three events /* With poll, the ready_mask could have any of three events
set to 1: POLLHUP, POLLERR, POLLNVAL. These events cannot set to 1: POLLHUP, POLLERR, POLLNVAL. These events
be used in the requested event mask (events), but they cannot be used in the requested event mask (events), but
can be returned in the return mask (revents). We need to they can be returned in the return mask (revents). We
check for those event too, and add them to the mask which need to check for those event too, and add them to the
will be passed to the handler. */ mask which will be passed to the handler. */
/* See if the desired events (mask) match the received /* See if the desired events (mask) match the received
events (ready_mask). */ events (ready_mask). */
if (use_poll) if (use_poll)
{ {
@ -780,8 +789,8 @@ handle_file_event (event_data data)
if (error_mask_returned != 0) if (error_mask_returned != 0)
{ {
/* Work in progress. We may need to tell somebody what /* Work in progress. We may need to tell somebody
kind of error we had. */ what kind of error we had. */
if (error_mask_returned & POLLHUP) if (error_mask_returned & POLLHUP)
printf_unfiltered (_("Hangup detected on fd %d\n"), file_ptr->fd); printf_unfiltered (_("Hangup detected on fd %d\n"), file_ptr->fd);
if (error_mask_returned & POLLERR) if (error_mask_returned & POLLERR)
@ -809,10 +818,10 @@ handle_file_event (event_data data)
mask = file_ptr->ready_mask & file_ptr->mask; mask = file_ptr->ready_mask & file_ptr->mask;
} }
/* Clear the received events for next time around. */ /* Clear the received events for next time around. */
file_ptr->ready_mask = 0; file_ptr->ready_mask = 0;
/* If there was a match, then call the handler. */ /* If there was a match, then call the handler. */
if (mask != 0) if (mask != 0)
(*file_ptr->proc) (file_ptr->error, file_ptr->client_data); (*file_ptr->proc) (file_ptr->error, file_ptr->client_data);
break; break;
@ -823,8 +832,8 @@ handle_file_event (event_data data)
/* Called by gdb_do_one_event to wait for new events on the monitored /* Called by gdb_do_one_event to wait for new events on the monitored
file descriptors. Queue file events as they are detected by the file descriptors. Queue file events as they are detected by the
poll. If BLOCK and if there are no events, this function will poll. If BLOCK and if there are no events, this function will
block in the call to poll. Return -1 if there are no files block in the call to poll. Return -1 if there are no file
descriptors to monitor, otherwise return 0. */ descriptors to monitor, otherwise return 0. */
static int static int
gdb_wait_for_event (int block) gdb_wait_for_event (int block)
{ {
@ -833,7 +842,7 @@ gdb_wait_for_event (int block)
int num_found = 0; int num_found = 0;
int i; int i;
/* Make sure all output is done before getting another event. */ /* Make sure all output is done before getting another event. */
gdb_flush (gdb_stdout); gdb_flush (gdb_stdout);
gdb_flush (gdb_stderr); gdb_flush (gdb_stderr);
@ -885,7 +894,7 @@ gdb_wait_for_event (int block)
&gdb_notifier.ready_masks[2], &gdb_notifier.ready_masks[2],
timeout_p); timeout_p);
/* Clear the masks after an error from select. */ /* Clear the masks after an error from select. */
if (num_found == -1) if (num_found == -1)
{ {
FD_ZERO (&gdb_notifier.ready_masks[0]); FD_ZERO (&gdb_notifier.ready_masks[0]);
@ -899,7 +908,7 @@ gdb_wait_for_event (int block)
} }
} }
/* Enqueue all detected file events. */ /* Enqueue all detected file events. */
if (use_poll) if (use_poll)
{ {
@ -922,7 +931,7 @@ gdb_wait_for_event (int block)
if (file_ptr) if (file_ptr)
{ {
/* Enqueue an event only if this is still a new event for /* Enqueue an event only if this is still a new event for
this fd. */ this fd. */
if (file_ptr->ready_mask == 0) if (file_ptr->ready_mask == 0)
{ {
file_event_ptr = create_file_event (file_ptr->fd); file_event_ptr = create_file_event (file_ptr->fd);
@ -957,7 +966,7 @@ gdb_wait_for_event (int block)
num_found--; num_found--;
/* Enqueue an event only if this is still a new event for /* Enqueue an event only if this is still a new event for
this fd. */ this fd. */
if (file_ptr->ready_mask == 0) if (file_ptr->ready_mask == 0)
{ {
@ -976,7 +985,7 @@ gdb_wait_for_event (int block)
This pointer will be used to invoke the handler by This pointer will be used to invoke the handler by
invoke_async_signal_handler. invoke_async_signal_handler.
PROC is the function to call with CLIENT_DATA argument PROC is the function to call with CLIENT_DATA argument
whenever the handler is invoked. */ whenever the handler is invoked. */
async_signal_handler * async_signal_handler *
create_async_signal_handler (sig_handler_func * proc, gdb_client_data client_data) create_async_signal_handler (sig_handler_func * proc, gdb_client_data client_data)
{ {
@ -1005,10 +1014,10 @@ call_async_signal_handler (struct async_signal_handler *handler)
(*handler->proc) (handler->client_data); (*handler->proc) (handler->client_data);
} }
/* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information will /* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information
be used when the handlers are invoked, after we have waited for will be used when the handlers are invoked, after we have waited
some event. The caller of this function is the interrupt handler for some event. The caller of this function is the interrupt
associated with a signal. */ handler associated with a signal. */
void void
mark_async_signal_handler (async_signal_handler * async_handler_ptr) mark_async_signal_handler (async_signal_handler * async_handler_ptr)
{ {
@ -1177,19 +1186,20 @@ delete_async_event_handler (async_event_handler **async_handler_ptr)
*async_handler_ptr = NULL; *async_handler_ptr = NULL;
} }
/* Create a timer that will expire in MILLISECONDS from now. When the /* Create a timer that will expire in MILLISECONDS from now. When the
timer is ready, PROC will be executed. At creation, the timer is timer is ready, PROC will be executed. At creation, the timer is
aded to the timers queue. This queue is kept sorted in order of aded to the timers queue. This queue is kept sorted in order of
increasing timers. Return a handle to the timer struct. */ increasing timers. Return a handle to the timer struct. */
int int
create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data client_data) create_timer (int milliseconds, timer_handler_func * proc,
gdb_client_data client_data)
{ {
struct gdb_timer *timer_ptr, *timer_index, *prev_timer; struct gdb_timer *timer_ptr, *timer_index, *prev_timer;
struct timeval time_now, delta; struct timeval time_now, delta;
/* compute seconds */ /* Compute seconds. */
delta.tv_sec = milliseconds / 1000; delta.tv_sec = milliseconds / 1000;
/* compute microseconds */ /* Compute microseconds. */
delta.tv_usec = (milliseconds % 1000) * 1000; delta.tv_usec = (milliseconds % 1000) * 1000;
gettimeofday (&time_now, NULL); gettimeofday (&time_now, NULL);
@ -1197,7 +1207,7 @@ create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data clien
timer_ptr = (struct gdb_timer *) xmalloc (sizeof (*timer_ptr)); timer_ptr = (struct gdb_timer *) xmalloc (sizeof (*timer_ptr));
timer_ptr->when.tv_sec = time_now.tv_sec + delta.tv_sec; timer_ptr->when.tv_sec = time_now.tv_sec + delta.tv_sec;
timer_ptr->when.tv_usec = time_now.tv_usec + delta.tv_usec; timer_ptr->when.tv_usec = time_now.tv_usec + delta.tv_usec;
/* carry? */ /* Carry? */
if (timer_ptr->when.tv_usec >= 1000000) if (timer_ptr->when.tv_usec >= 1000000)
{ {
timer_ptr->when.tv_sec += 1; timer_ptr->when.tv_sec += 1;
@ -1209,14 +1219,14 @@ create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data clien
timer_ptr->timer_id = timer_list.num_timers; timer_ptr->timer_id = timer_list.num_timers;
/* Now add the timer to the timer queue, making sure it is sorted in /* Now add the timer to the timer queue, making sure it is sorted in
increasing order of expiration. */ increasing order of expiration. */
for (timer_index = timer_list.first_timer; for (timer_index = timer_list.first_timer;
timer_index != NULL; timer_index != NULL;
timer_index = timer_index->next) timer_index = timer_index->next)
{ {
/* If the seconds field is greater or if it is the same, but the /* If the seconds field is greater or if it is the same, but the
microsecond field is greater. */ microsecond field is greater. */
if ((timer_index->when.tv_sec > timer_ptr->when.tv_sec) if ((timer_index->when.tv_sec > timer_ptr->when.tv_sec)
|| ((timer_index->when.tv_sec == timer_ptr->when.tv_sec) || ((timer_index->when.tv_sec == timer_ptr->when.tv_sec)
&& (timer_index->when.tv_usec > timer_ptr->when.tv_usec))) && (timer_index->when.tv_usec > timer_ptr->when.tv_usec)))
@ -1245,13 +1255,13 @@ create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data clien
} }
/* There is a chance that the creator of the timer wants to get rid of /* There is a chance that the creator of the timer wants to get rid of
it before it expires. */ it before it expires. */
void void
delete_timer (int id) delete_timer (int id)
{ {
struct gdb_timer *timer_ptr, *prev_timer = NULL; struct gdb_timer *timer_ptr, *prev_timer = NULL;
/* Find the entry for the given timer. */ /* Find the entry for the given timer. */
for (timer_ptr = timer_list.first_timer; timer_ptr != NULL; for (timer_ptr = timer_list.first_timer; timer_ptr != NULL;
timer_ptr = timer_ptr->next) timer_ptr = timer_ptr->next)
@ -1262,7 +1272,7 @@ delete_timer (int id)
if (timer_ptr == NULL) if (timer_ptr == NULL)
return; return;
/* Get rid of the timer in the timer list. */ /* Get rid of the timer in the timer list. */
if (timer_ptr == timer_list.first_timer) if (timer_ptr == timer_list.first_timer)
timer_list.first_timer = timer_ptr->next; timer_list.first_timer = timer_ptr->next;
else else
@ -1298,11 +1308,11 @@ handle_timer_event (event_data dummy)
&& (timer_ptr->when.tv_usec > time_now.tv_usec))) && (timer_ptr->when.tv_usec > time_now.tv_usec)))
break; break;
/* Get rid of the timer from the beginning of the list. */ /* Get rid of the timer from the beginning of the list. */
timer_list.first_timer = timer_ptr->next; timer_list.first_timer = timer_ptr->next;
saved_timer = timer_ptr; saved_timer = timer_ptr;
timer_ptr = timer_ptr->next; timer_ptr = timer_ptr->next;
/* Call the procedure associated with that timer. */ /* Call the procedure associated with that timer. */
(*saved_timer->proc) (saved_timer->client_data); (*saved_timer->proc) (saved_timer->client_data);
xfree (saved_timer); xfree (saved_timer);
} }
@ -1310,12 +1320,12 @@ handle_timer_event (event_data dummy)
gdb_notifier.timeout_valid = 0; gdb_notifier.timeout_valid = 0;
} }
/* Check whether any timers in the timers queue are ready. If at least /* Check whether any timers in the timers queue are ready. If at least
one timer is ready, stick an event onto the event queue. Even in one timer is ready, stick an event onto the event queue. Even in
case more than one timer is ready, one event is enough, because the case more than one timer is ready, one event is enough, because the
handle_timer_event() will go through the timers list and call the handle_timer_event() will go through the timers list and call the
procedures associated with all that have expired. Update the procedures associated with all that have expired.l Update the
timeout for the select() or poll() as well. */ timeout for the select() or poll() as well. */
static void static void
poll_timers (void) poll_timers (void)
{ {
@ -1327,15 +1337,15 @@ poll_timers (void)
gettimeofday (&time_now, NULL); gettimeofday (&time_now, NULL);
delta.tv_sec = timer_list.first_timer->when.tv_sec - time_now.tv_sec; delta.tv_sec = timer_list.first_timer->when.tv_sec - time_now.tv_sec;
delta.tv_usec = timer_list.first_timer->when.tv_usec - time_now.tv_usec; delta.tv_usec = timer_list.first_timer->when.tv_usec - time_now.tv_usec;
/* borrow? */ /* Borrow? */
if (delta.tv_usec < 0) if (delta.tv_usec < 0)
{ {
delta.tv_sec -= 1; delta.tv_sec -= 1;
delta.tv_usec += 1000000; delta.tv_usec += 1000000;
} }
/* Oops it expired already. Tell select / poll to return /* Oops it expired already. Tell select / poll to return
immediately. (Cannot simply test if delta.tv_sec is negative immediately. (Cannot simply test if delta.tv_sec is negative
because time_t might be unsigned.) */ because time_t might be unsigned.) */
if (timer_list.first_timer->when.tv_sec < time_now.tv_sec if (timer_list.first_timer->when.tv_sec < time_now.tv_sec
|| (timer_list.first_timer->when.tv_sec == time_now.tv_sec || (timer_list.first_timer->when.tv_sec == time_now.tv_sec
@ -1353,8 +1363,8 @@ poll_timers (void)
async_queue_event (event_ptr, TAIL); async_queue_event (event_ptr, TAIL);
} }
/* Now we need to update the timeout for select/ poll, because we /* Now we need to update the timeout for select/ poll, because
don't want to sit there while this timer is expiring. */ we don't want to sit there while this timer is expiring. */
if (use_poll) if (use_poll)
{ {
#ifdef HAVE_POLL #ifdef HAVE_POLL

View file

@ -18,10 +18,10 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* An event loop listens for events from multiple event sources. When /* An event loop listens for events from multiple event sources. When
an event arrives, it is queued and processed by calling the an event arrives, it is queued and processed by calling the
appropriate event handler. The event loop then continues to listen appropriate event handler. The event loop then continues to listen
for more events. An event loop completes when there are no event for more events. An event loop completes when there are no event
sources to listen on. External event sources can be plugged into sources to listen on. External event sources can be plugged into
the loop. the loop.
@ -66,7 +66,7 @@
when the SIGHANDLER_LIST is scanned, the next time through the when the SIGHANDLER_LIST is scanned, the next time through the
infinite loop. infinite loop.
Corollary tasks are the creation and deletion of event sources. */ Corollary tasks are the creation and deletion of event sources. */
typedef void *gdb_client_data; typedef void *gdb_client_data;
struct async_signal_handler; struct async_signal_handler;
@ -76,14 +76,14 @@ typedef void (sig_handler_func) (gdb_client_data);
typedef void (async_event_handler_func) (gdb_client_data); typedef void (async_event_handler_func) (gdb_client_data);
typedef void (timer_handler_func) (gdb_client_data); typedef void (timer_handler_func) (gdb_client_data);
/* Where to add an event onto the event queue, by queue_event. */ /* Where to add an event onto the event queue, by queue_event. */
typedef enum typedef enum
{ {
/* Add at tail of queue. It will be processed in first in first /* Add at tail of queue. It will be processed in first in first
out order. */ out order. */
TAIL, TAIL,
/* Add at head of queue. It will be processed in last in first out /* Add at head of queue. It will be processed in last in first
order. */ out order. */
HEAD HEAD
} }
queue_position; queue_position;
@ -93,11 +93,15 @@ queue_position;
extern void start_event_loop (void); extern void start_event_loop (void);
extern int gdb_do_one_event (void *data); extern int gdb_do_one_event (void *data);
extern void delete_file_handler (int fd); extern void delete_file_handler (int fd);
extern void add_file_handler (int fd, handler_func * proc, gdb_client_data client_data); extern void add_file_handler (int fd, handler_func *proc,
gdb_client_data client_data);
extern struct async_signal_handler * extern struct async_signal_handler *
create_async_signal_handler (sig_handler_func * proc, gdb_client_data client_data); create_async_signal_handler (sig_handler_func *proc,
gdb_client_data client_data);
extern void delete_async_signal_handler (struct async_signal_handler **async_handler_ptr); extern void delete_async_signal_handler (struct async_signal_handler **async_handler_ptr);
extern int create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data client_data); extern int create_timer (int milliseconds,
timer_handler_func *proc,
gdb_client_data client_data);
extern void delete_timer (int id); extern void delete_timer (int id);
/* Call the handler from HANDLER immediately. This function /* Call the handler from HANDLER immediately. This function

View file

@ -18,7 +18,7 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h" #include "defs.h"
#include "top.h" #include "top.h"
@ -34,10 +34,9 @@
#include "main.h" #include "main.h"
#include "gdbthread.h" #include "gdbthread.h"
/* For dont_repeat() */ #include "gdbcmd.h" /* for dont_repeat() */
#include "gdbcmd.h"
/* readline include files */ /* readline include files. */
#include "readline/readline.h" #include "readline/readline.h"
#include "readline/history.h" #include "readline/history.h"
@ -50,7 +49,7 @@ static void change_line_handler (void);
static void change_annotation_level (void); static void change_annotation_level (void);
static void command_handler (char *command); static void command_handler (char *command);
/* Signal handlers. */ /* Signal handlers. */
#ifdef SIGQUIT #ifdef SIGQUIT
static void handle_sigquit (int sig); static void handle_sigquit (int sig);
#endif #endif
@ -63,7 +62,7 @@ static void handle_sigwinch (int sig);
#endif #endif
/* Functions to be invoked by the event loop in response to /* Functions to be invoked by the event loop in response to
signals. */ signals. */
#if defined (SIGQUIT) || defined (SIGHUP) #if defined (SIGQUIT) || defined (SIGHUP)
static void async_do_nothing (gdb_client_data); static void async_do_nothing (gdb_client_data);
#endif #endif
@ -76,65 +75,65 @@ static void async_stop_sig (gdb_client_data);
#endif #endif
/* Readline offers an alternate interface, via callback /* Readline offers an alternate interface, via callback
functions. These are all included in the file callback.c in the functions. These are all included in the file callback.c in the
readline distribution. This file provides (mainly) a function, which readline distribution. This file provides (mainly) a function, which
the event loop uses as callback (i.e. event handler) whenever an event the event loop uses as callback (i.e. event handler) whenever an event
is detected on the standard input file descriptor. is detected on the standard input file descriptor.
readline_callback_read_char is called (by the GDB event loop) whenever readline_callback_read_char is called (by the GDB event loop) whenever
there is a new character ready on the input stream. This function there is a new character ready on the input stream. This function
incrementally builds a buffer internal to readline where it incrementally builds a buffer internal to readline where it
accumulates the line read up to the point of invocation. In the accumulates the line read up to the point of invocation. In the
special case in which the character read is newline, the function special case in which the character read is newline, the function
invokes a GDB supplied callback routine, which does the processing of invokes a GDB supplied callback routine, which does the processing of
a full command line. This latter routine is the asynchronous analog a full command line. This latter routine is the asynchronous analog
of the old command_line_input in gdb. Instead of invoking (and waiting 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 for) readline to read the command line and pass it back to
command_loop for processing, the new command_line_handler function has command_loop for processing, the new command_line_handler function has
the command line already available as its parameter. INPUT_HANDLER is the command line already available as its parameter. INPUT_HANDLER is
to be set to the function that readline will invoke when a complete 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 line of input is ready. CALL_READLINE is to be set to the function
that readline offers as callback to the event_loop. */ that readline offers as callback to the event_loop. */
void (*input_handler) (char *); void (*input_handler) (char *);
void (*call_readline) (gdb_client_data); void (*call_readline) (gdb_client_data);
/* Important variables for the event loop. */ /* Important variables for the event loop. */
/* This is used to determine if GDB is using the readline library or /* 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 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 ezannoni: as of 1999-04-29 I expect that this
variable will not be used after gdb is changed to use the event 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. */ loop as default engine, and event-top.c is merged into top.c. */
int async_command_editing_p; int async_command_editing_p;
/* This variable contains the new prompt that the user sets with the /* This variable contains the new prompt that the user sets with the
set prompt command. */ set prompt command. */
char *new_async_prompt; char *new_async_prompt;
/* This is the annotation suffix that will be used when the /* This is the annotation suffix that will be used when the
annotation_level is 2. */ annotation_level is 2. */
char *async_annotation_suffix; char *async_annotation_suffix;
/* This is used to display the notification of the completion of an /* This is used to display the notification of the completion of an
asynchronous execution command. */ asynchronous execution command. */
int exec_done_display_p = 0; int exec_done_display_p = 0;
/* This is the file descriptor for the input stream that GDB uses to /* This is the file descriptor for the input stream that GDB uses to
read commands from. */ read commands from. */
int input_fd; int input_fd;
/* This is the prompt stack. Prompts will be pushed on the stack as /* This is the prompt stack. Prompts will be pushed on the stack as
needed by the different 'kinds' of user inputs GDB is asking needed by the different 'kinds' of user inputs GDB is asking
for. See event-loop.h. */ for. See event-loop.h. */
struct prompts the_prompts; struct prompts the_prompts;
/* signal handling variables */ /* Signal handling variables. */
/* Each of these is a pointer to a function that the event loop will /* Each of these is a pointer to a function that the event loop will
invoke if the corresponding signal has received. The real signal invoke if the corresponding signal has received. The real signal
handlers mark these functions as ready to be executed and the event handlers mark these functions as ready to be executed and the event
loop, in a later iteration, calls them. See the function loop, in a later iteration, calls them. See the function
invoke_async_signal_handler. */ invoke_async_signal_handler. */
void *sigint_token; void *sigint_token;
#ifdef SIGHUP #ifdef SIGHUP
void *sighup_token; void *sighup_token;
@ -151,10 +150,10 @@ void *sigtstp_token;
#endif #endif
/* Structure to save a partially entered command. This is used when /* Structure to save a partially entered command. This is used when
the user types '\' at the end of a command line. This is necessary 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 because each line of input is handled by a different call to
command_line_handler, and normally there is no state retained command_line_handler, and normally there is no state retained
between different calls. */ between different calls. */
int more_to_come = 0; int more_to_come = 0;
struct readline_input_state struct readline_input_state
@ -169,9 +168,9 @@ readline_input_state;
void (*after_char_processing_hook) (); void (*after_char_processing_hook) ();
/* Wrapper function for calling into the readline library. The event /* Wrapper function for calling into the readline library. The event
loop expects the callback function to have a paramter, while readline loop expects the callback function to have a paramter, while
expects none. */ readline expects none. */
static void static void
rl_callback_read_char_wrapper (gdb_client_data client_data) rl_callback_read_char_wrapper (gdb_client_data client_data)
{ {
@ -181,21 +180,21 @@ rl_callback_read_char_wrapper (gdb_client_data client_data)
} }
/* Initialize all the necessary variables, start the event loop, /* Initialize all the necessary variables, start the event loop,
register readline, and stdin, start the loop. */ register readline, and stdin, start the loop. */
void void
cli_command_loop (void) cli_command_loop (void)
{ {
/* If we are using readline, set things up and display the first /* If we are using readline, set things up and display the first
prompt, otherwise just print the prompt. */ prompt, otherwise just print the prompt. */
if (async_command_editing_p) if (async_command_editing_p)
{ {
int length; int length;
char *a_prompt; char *a_prompt;
char *gdb_prompt = get_prompt (); char *gdb_prompt = get_prompt ();
/* Tell readline what the prompt to display is and what function it /* Tell readline what the prompt to display is and what function
will need to call after a whole line is read. This also displays it will need to call after a whole line is read. This also
the first prompt. */ displays the first prompt. */
length = strlen (PREFIX (0)) length = strlen (PREFIX (0))
+ strlen (gdb_prompt) + strlen (SUFFIX (0)) + 1; + strlen (gdb_prompt) + strlen (SUFFIX (0)) + 1;
a_prompt = (char *) alloca (length); a_prompt = (char *) alloca (length);
@ -207,54 +206,54 @@ cli_command_loop (void)
else else
display_gdb_prompt (0); display_gdb_prompt (0);
/* Now it's time to start the event loop. */ /* Now it's time to start the event loop. */
start_event_loop (); start_event_loop ();
} }
/* Change the function to be invoked every time there is a character /* 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, ready on stdin. This is used when the user sets the editing off,
therefore bypassing readline, and letting gdb handle the input therefore bypassing readline, and letting gdb handle the input
itself, via gdb_readline2. Also it is used in the opposite case in itself, via gdb_readline2. Also it is used in the opposite case in
which the user sets editing on again, by restoring readline which the user sets editing on again, by restoring readline
handling of the input. */ handling of the input. */
static void static void
change_line_handler (void) change_line_handler (void)
{ {
/* NOTE: this operates on input_fd, not instream. If we are reading /* NOTE: this operates on input_fd, not instream. If we are reading
commands from a file, instream will point to the file. However in commands from a file, instream will point to the file. However in
async mode, we always read commands from a file with editing async mode, we always read commands from a file with editing
off. This means that the 'set editing on/off' will have effect off. This means that the 'set editing on/off' will have effect
only on the interactive session. */ only on the interactive session. */
if (async_command_editing_p) if (async_command_editing_p)
{ {
/* Turn on editing by using readline. */ /* Turn on editing by using readline. */
call_readline = rl_callback_read_char_wrapper; call_readline = rl_callback_read_char_wrapper;
input_handler = command_line_handler; input_handler = command_line_handler;
} }
else else
{ {
/* Turn off editing by using gdb_readline2. */ /* Turn off editing by using gdb_readline2. */
rl_callback_handler_remove (); rl_callback_handler_remove ();
call_readline = gdb_readline2; call_readline = gdb_readline2;
/* Set up the command handler as well, in case we are called as /* Set up the command handler as well, in case we are called as
first thing from .gdbinit. */ first thing from .gdbinit. */
input_handler = command_line_handler; input_handler = command_line_handler;
} }
} }
/* Displays the prompt. The prompt that is displayed is the current /* Displays the prompt. The prompt that is displayed is the current
top of the prompt stack, if the argument NEW_PROMPT is top of the prompt stack, if the argument NEW_PROMPT is
0. Otherwise, it displays whatever NEW_PROMPT is. This is used 0. Otherwise, it displays whatever NEW_PROMPT is. This is used
after each gdb command has completed, and in the following cases: after each gdb command has completed, and in the following cases:
1. when the user enters a command line which is ended by '\' 1. When the user enters a command line which is ended by '\'
indicating that the command will continue on the next line. indicating that the command will continue on the next line.
In that case the prompt that is displayed is the empty string. In that case the prompt that is displayed is the empty string.
2. When the user is entering 'commands' for a breakpoint, or 2. When the user is entering 'commands' for a breakpoint, or
actions for a tracepoint. In this case the prompt will be '>' actions for a tracepoint. In this case the prompt will be '>'
3. Other???? 3. Other????
FIXME: 2. & 3. not implemented yet for async. */ FIXME: 2. & 3. not implemented yet for async. */
void void
display_gdb_prompt (char *new_prompt) display_gdb_prompt (char *new_prompt)
{ {
@ -276,15 +275,15 @@ display_gdb_prompt (char *new_prompt)
function, readline still tries to do its own display if we function, readline still tries to do its own display if we
don't call rl_callback_handler_install and don't call rl_callback_handler_install and
rl_callback_handler_remove (which readline detects because a rl_callback_handler_remove (which readline detects because a
global variable is not set). If readline did that, it could global variable is not set). If readline did that, it could
mess up gdb signal handlers for SIGINT. Readline assumes mess up gdb signal handlers for SIGINT. Readline assumes
that between calls to rl_set_signals and rl_clear_signals gdb that between calls to rl_set_signals and rl_clear_signals gdb
doesn't do anything with the signal handlers. Well, that's doesn't do anything with the signal handlers. Well, that's
not the case, because when the target executes we change the not the case, because when the target executes we change the
SIGINT signal handler. If we allowed readline to display the SIGINT signal handler. If we allowed readline to display the
prompt, the signal handler change would happen exactly prompt, the signal handler change would happen exactly
between the calls to the above two functions. between the calls to the above two functions.
Calling rl_callback_handler_remove(), does the job. */ Calling rl_callback_handler_remove(), does the job. */
rl_callback_handler_remove (); rl_callback_handler_remove ();
return; return;
@ -292,18 +291,18 @@ display_gdb_prompt (char *new_prompt)
if (!new_prompt) if (!new_prompt)
{ {
/* Just use the top of the prompt stack. */ /* Just use the top of the prompt stack. */
prompt_length = strlen (PREFIX (0)) + prompt_length = strlen (PREFIX (0)) +
strlen (SUFFIX (0)) + strlen (SUFFIX (0)) +
strlen (gdb_prompt) + 1; strlen (gdb_prompt) + 1;
new_prompt = (char *) alloca (prompt_length); new_prompt = (char *) alloca (prompt_length);
/* Prefix needs to have new line at end. */ /* Prefix needs to have new line at end. */
strcpy (new_prompt, PREFIX (0)); strcpy (new_prompt, PREFIX (0));
strcat (new_prompt, gdb_prompt); strcat (new_prompt, gdb_prompt);
/* Suffix needs to have a new line at end and \032 \032 at /* Suffix needs to have a new line at end and \032 \032 at
beginning. */ beginning. */
strcat (new_prompt, SUFFIX (0)); strcat (new_prompt, SUFFIX (0));
} }
@ -312,7 +311,8 @@ display_gdb_prompt (char *new_prompt)
rl_callback_handler_remove (); rl_callback_handler_remove ();
rl_callback_handler_install (new_prompt, input_handler); 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 */ /* new_prompt at this point can be the top of the stack or the one
passed in. */
else if (new_prompt) else if (new_prompt)
{ {
/* Don't use a _filtered function here. It causes the assumed /* Don't use a _filtered function here. It causes the assumed
@ -324,10 +324,10 @@ display_gdb_prompt (char *new_prompt)
} }
/* Used when the user requests a different annotation level, with /* Used when the user requests a different annotation level, with
'set annotate'. It pushes a new prompt (with prefix and suffix) on top '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 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 it pops the top of the prompt stack when we want the annotation level
to be the normal ones (1 or 0). */ to be the normal ones (1 or 0). */
static void static void
change_annotation_level (void) change_annotation_level (void)
{ {
@ -336,7 +336,7 @@ change_annotation_level (void)
if (!PREFIX (0) || !PROMPT (0) || !SUFFIX (0)) if (!PREFIX (0) || !PROMPT (0) || !SUFFIX (0))
{ {
/* The prompt stack has not been initialized to "", we are /* The prompt stack has not been initialized to "", we are
using gdb w/o the --async switch */ using gdb w/o the --async switch. */
warning (_("Command has same effect as set annotate")); warning (_("Command has same effect as set annotate"));
return; return;
} }
@ -345,7 +345,7 @@ change_annotation_level (void)
{ {
if (!strcmp (PREFIX (0), "") && !strcmp (SUFFIX (0), "")) if (!strcmp (PREFIX (0), "") && !strcmp (SUFFIX (0), ""))
{ {
/* Push a new prompt if the previous annotation_level was not >1. */ /* Push a new prompt if the previous annotation_level was not >1. */
prefix = (char *) alloca (strlen (async_annotation_suffix) + 10); prefix = (char *) alloca (strlen (async_annotation_suffix) + 10);
strcpy (prefix, "\n\032\032pre-"); strcpy (prefix, "\n\032\032pre-");
strcat (prefix, async_annotation_suffix); strcat (prefix, async_annotation_suffix);
@ -363,16 +363,16 @@ change_annotation_level (void)
{ {
if (strcmp (PREFIX (0), "") && strcmp (SUFFIX (0), "")) if (strcmp (PREFIX (0), "") && strcmp (SUFFIX (0), ""))
{ {
/* Pop the top of the stack, we are going back to annotation < 1. */ /* Pop the top of the stack, we are going back to annotation < 1. */
pop_prompt (); pop_prompt ();
} }
} }
} }
/* Pushes a new prompt on the prompt stack. Each prompt has three /* Pushes a new prompt on the prompt stack. Each prompt has three
parts: prefix, prompt, suffix. Usually prefix and suffix are empty parts: prefix, prompt, suffix. Usually prefix and suffix are empty
strings, except when the annotation level is 2. Memory is allocated strings, except when the annotation level is 2. Memory is allocated
within xstrdup for the new prompt. */ within xstrdup for the new prompt. */
void void
push_prompt (char *prefix, char *prompt, char *suffix) push_prompt (char *prefix, char *prompt, char *suffix)
{ {
@ -380,8 +380,8 @@ push_prompt (char *prefix, char *prompt, char *suffix)
PREFIX (0) = xstrdup (prefix); PREFIX (0) = xstrdup (prefix);
/* Note that this function is used by the set annotate 2 /* Note that this function is used by the set annotate 2
command. This is why we take care of saving the old prompt command. This is why we take care of saving the old prompt
in case a new one is not specified. */ in case a new one is not specified. */
if (prompt) if (prompt)
PROMPT (0) = xstrdup (prompt); PROMPT (0) = xstrdup (prompt);
else else
@ -390,17 +390,18 @@ push_prompt (char *prefix, char *prompt, char *suffix)
SUFFIX (0) = xstrdup (suffix); SUFFIX (0) = xstrdup (suffix);
} }
/* Pops the top of the prompt stack, and frees the memory allocated for it. */ /* Pops the top of the prompt stack, and frees the memory allocated
for it. */
void void
pop_prompt (void) pop_prompt (void)
{ {
/* If we are not during a 'synchronous' execution command, in which /* If we are not during a 'synchronous' execution command, in which
case, the top prompt would be empty. */ case, the top prompt would be empty. */
if (strcmp (PROMPT (0), "")) if (strcmp (PROMPT (0), ""))
/* This is for the case in which the prompt is set while the /* 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 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 we return to annotation level < 2, we want that new prompt to be
in effect, until the user does another 'set prompt'. */ in effect, until the user does another 'set prompt'. */
if (strcmp (PROMPT (0), PROMPT (-1))) if (strcmp (PROMPT (0), PROMPT (-1)))
{ {
xfree (PROMPT (-1)); xfree (PROMPT (-1));
@ -416,7 +417,7 @@ pop_prompt (void)
/* When there is an event ready on the stdin file desriptor, instead /* When there is an event ready on the stdin file desriptor, instead
of calling readline directly throught the callback function, or of calling readline directly throught the callback function, or
instead of calling gdb_readline2, give gdb a chance to detect instead of calling gdb_readline2, give gdb a chance to detect
errors and do something. */ errors and do something. */
void void
stdin_event_handler (int error, gdb_client_data client_data) stdin_event_handler (int error, gdb_client_data client_data)
{ {
@ -426,7 +427,7 @@ stdin_event_handler (int error, gdb_client_data client_data)
delete_file_handler (input_fd); delete_file_handler (input_fd);
discard_all_continuations (); discard_all_continuations ();
discard_all_intermediate_continuations (); discard_all_intermediate_continuations ();
/* If stdin died, we may as well kill gdb. */ /* If stdin died, we may as well kill gdb. */
quit_command ((char *) 0, stdin == instream); quit_command ((char *) 0, stdin == instream);
} }
else else
@ -435,17 +436,17 @@ stdin_event_handler (int error, gdb_client_data client_data)
/* Re-enable stdin after the end of an execution command in /* Re-enable stdin after the end of an execution command in
synchronous mode, or after an error from the target, and we aborted synchronous mode, or after an error from the target, and we aborted
the exec operation. */ the exec operation. */
void void
async_enable_stdin (void) async_enable_stdin (void)
{ {
if (sync_execution) if (sync_execution)
{ {
/* See NOTE in async_disable_stdin() */ /* See NOTE in async_disable_stdin(). */
/* FIXME: cagney/1999-09-27: Call this before clearing /* FIXME: cagney/1999-09-27: Call this before clearing
sync_execution. Current target_terminal_ours() implementations sync_execution. Current target_terminal_ours() implementations
check for sync_execution before switching the terminal. */ check for sync_execution before switching the terminal. */
target_terminal_ours (); target_terminal_ours ();
pop_prompt (); pop_prompt ();
sync_execution = 0; sync_execution = 0;
@ -453,7 +454,7 @@ async_enable_stdin (void)
} }
/* Disable reads from stdin (the console) marking the command as /* Disable reads from stdin (the console) marking the command as
synchronous. */ synchronous. */
void void
async_disable_stdin (void) async_disable_stdin (void)
@ -466,12 +467,12 @@ async_disable_stdin (void)
} }
/* Handles a gdb command. This function is called by /* Handles a gdb command. This function is called by
command_line_handler, which has processed one or more input lines command_line_handler, which has processed one or more input lines
into COMMAND. */ into COMMAND. */
/* NOTE: 1999-04-30 This is the asynchronous version of the command_loop /* NOTE: 1999-04-30 This is the asynchronous version of the command_loop
function. The command_loop function will be obsolete when we function. The command_loop function will be obsolete when we
switch to use the event loop at every execution of gdb. */ switch to use the event loop at every execution of gdb. */
static void static void
command_handler (char *command) command_handler (char *command)
{ {
@ -482,11 +483,11 @@ command_handler (char *command)
if (instream == stdin && stdin_is_tty) if (instream == stdin && stdin_is_tty)
reinitialize_more_filter (); reinitialize_more_filter ();
/* If readline returned a NULL command, it means that the /* If readline returned a NULL command, it means that the connection
connection with the terminal is gone. This happens at the with the terminal is gone. This happens at the end of a
end of a testsuite run, after Expect has hung up testsuite run, after Expect has hung up but GDB is still alive.
but GDB is still alive. In such a case, we just quit gdb In such a case, we just quit gdb killing the inferior program
killing the inferior program too. */ too. */
if (command == 0) if (command == 0)
{ {
printf_unfiltered ("quit\n"); printf_unfiltered ("quit\n");
@ -503,14 +504,15 @@ command_handler (char *command)
do_cleanups (stat_chain); do_cleanups (stat_chain);
} }
/* Handle a complete line of input. This is called by the callback /* Handle a complete line of input. This is called by the callback
mechanism within the readline library. Deal with incomplete commands mechanism within the readline library. Deal with incomplete
as well, by saving the partial input in a global buffer. */ commands as well, by saving the partial input in a global
buffer. */
/* NOTE: 1999-04-30 This is the asynchronous version of the /* NOTE: 1999-04-30 This is the asynchronous version of the
command_line_input function. command_line_input will become command_line_input function; command_line_input will become
obsolete once we use the event loop as the default mechanism in obsolete once we use the event loop as the default mechanism in
GDB. */ GDB. */
static void static void
command_line_handler (char *rl) command_line_handler (char *rl)
{ {
@ -555,7 +557,8 @@ command_line_handler (char *rl)
#endif #endif
/* Make sure that all output has been output. Some machines may let /* 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. */ you get away with leaving out some of the gdb_flush, but not
all. */
wrap_here (""); wrap_here ("");
gdb_flush (gdb_stdout); gdb_flush (gdb_stdout);
gdb_flush (gdb_stderr); gdb_flush (gdb_stderr);
@ -564,12 +567,12 @@ command_line_handler (char *rl)
++source_line_number; ++source_line_number;
/* If we are in this case, then command_handler will call quit /* If we are in this case, then command_handler will call quit
and exit from gdb. */ and exit from gdb. */
if (!rl || rl == (char *) EOF) if (!rl || rl == (char *) EOF)
{ {
got_eof = 1; got_eof = 1;
command_handler (0); command_handler (0);
return; /* Lint. */ return; /* Lint. */
} }
if (strlen (rl) + 1 + (p - linebuffer) > linelength) if (strlen (rl) + 1 + (p - linebuffer) > linelength)
{ {
@ -580,7 +583,7 @@ command_line_handler (char *rl)
} }
p1 = rl; p1 = rl;
/* Copy line. Don't copy null at end. (Leaves line alone /* Copy line. Don't copy null at end. (Leaves line alone
if this was just a newline) */ if this was just a newline). */
while (*p1) while (*p1)
*p++ = *p1++; *p++ = *p1++;
@ -595,8 +598,8 @@ command_line_handler (char *rl)
readline_input_state.linebuffer_ptr = p; readline_input_state.linebuffer_ptr = p;
/* We will not invoke a execute_command if there is more /* We will not invoke a execute_command if there is more
input expected to complete the command. So, we need to input expected to complete the command. So, we need to
print an empty prompt here. */ print an empty prompt here. */
more_to_come = 1; more_to_come = 1;
push_prompt ("", "", ""); push_prompt ("", "", "");
display_gdb_prompt (0); display_gdb_prompt (0);
@ -654,9 +657,8 @@ command_line_handler (char *rl)
xfree (history_value); xfree (history_value);
} }
/* If we just got an empty line, and that is supposed /* If we just got an empty line, and that is supposed to repeat the
to repeat the previous command, return the value in the previous command, return the value in the global buffer. */
global buffer. */
if (repeat && p == linebuffer && *p != '\\') if (repeat && p == linebuffer && *p != '\\')
{ {
command_handler (line); command_handler (line);
@ -686,7 +688,7 @@ command_line_handler (char *rl)
and remove the '#'. The kill ring is probably better, but some and remove the '#'. The kill ring is probably better, but some
people are in the habit of commenting things out. */ people are in the habit of commenting things out. */
if (*p1 == '#') if (*p1 == '#')
*p1 = '\0'; /* Found a comment. */ *p1 = '\0'; /* Found a comment. */
/* Save into global buffer if appropriate. */ /* Save into global buffer if appropriate. */
if (repeat) if (repeat)
@ -711,11 +713,11 @@ command_line_handler (char *rl)
} }
/* Does reading of input from terminal w/o the editing features /* Does reading of input from terminal w/o the editing features
provided by the readline library. */ provided by the readline library. */
/* NOTE: 1999-04-30 Asynchronous version of gdb_readline. gdb_readline /* NOTE: 1999-04-30 Asynchronous version of gdb_readline; gdb_readline
will become obsolete when the event loop is made the default will become obsolete when the event loop is made the default
execution for gdb. */ execution for gdb. */
void void
gdb_readline2 (gdb_client_data client_data) gdb_readline2 (gdb_client_data client_data)
{ {
@ -726,11 +728,11 @@ gdb_readline2 (gdb_client_data client_data)
static int done_once = 0; static int done_once = 0;
/* Unbuffer the input stream, so that, later on, the calls to fgetc /* 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 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 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 after '\n'. If we buffer the input and fgetc drains the
stream, getting stuff beyond the newline as well, a select, done stream, getting stuff beyond the newline as well, a select, done
afterwards will not trigger. */ afterwards will not trigger. */
if (!done_once && !ISATTY (instream)) if (!done_once && !ISATTY (instream))
{ {
setbuf (instream, NULL); setbuf (instream, NULL);
@ -742,9 +744,9 @@ gdb_readline2 (gdb_client_data client_data)
/* We still need the while loop here, even though it would seem /* We still need the while loop here, even though it would seem
obvious to invoke gdb_readline2 at every character entered. If obvious to invoke gdb_readline2 at every character entered. If
not using the readline library, the terminal is in cooked mode, not using the readline library, the terminal is in cooked mode,
which sends the characters all at once. Poll will notice that the which sends the characters all at once. Poll will notice that the
input fd has changed state only after enter is pressed. At this input fd has changed state only after enter is pressed. At this
point we still need to fetch all the chars entered. */ point we still need to fetch all the chars entered. */
while (1) while (1)
{ {
@ -755,9 +757,9 @@ gdb_readline2 (gdb_client_data client_data)
if (c == EOF) if (c == EOF)
{ {
if (input_index > 0) if (input_index > 0)
/* The last line does not end with a newline. Return it, and /* The last line does not end with a newline. Return it,
if we are called again fgetc will still return EOF and and if we are called again fgetc will still return EOF
we'll return NULL then. */ and we'll return NULL then. */
break; break;
xfree (result); xfree (result);
(*input_handler) (0); (*input_handler) (0);
@ -785,17 +787,17 @@ gdb_readline2 (gdb_client_data client_data)
/* Initialization of signal handlers and tokens. There is a function /* Initialization of signal handlers and tokens. There is a function
handle_sig* for each of the signals GDB cares about. Specifically: handle_sig* for each of the signals GDB cares about. Specifically:
SIGINT, SIGFPE, SIGQUIT, SIGTSTP, SIGHUP, SIGWINCH. These SIGINT, SIGFPE, SIGQUIT, SIGTSTP, SIGHUP, SIGWINCH. These
functions are the actual signal handlers associated to the signals functions are the actual signal handlers associated to the signals
via calls to signal(). The only job for these functions is to via calls to signal(). The only job for these functions is to
enqueue the appropriate event/procedure with the event loop. Such enqueue the appropriate event/procedure with the event loop. Such
procedures are the old signal handlers. The event loop will take procedures are the old signal handlers. The event loop will take
care of invoking the queued procedures to perform the usual tasks care of invoking the queued procedures to perform the usual tasks
associated with the reception of the signal. */ associated with the reception of the signal. */
/* NOTE: 1999-04-30 This is the asynchronous version of init_signals. /* 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 init_signals will become obsolete as we move to have to event loop
as the default for gdb. */ as the default for gdb. */
void void
async_init_signals (void) async_init_signals (void)
{ {
@ -854,7 +856,7 @@ mark_async_signal_handler_wrapper (void *token)
} }
/* Tell the event loop what to do if SIGINT is received. /* Tell the event loop what to do if SIGINT is received.
See event-signal.c. */ See event-signal.c. */
void void
handle_sigint (int sig) handle_sigint (int sig)
{ {
@ -862,19 +864,19 @@ handle_sigint (int sig)
/* We could be running in a loop reading in symfiles or something so /* We could be running in a loop reading in symfiles or something so
it may be quite a while before we get back to the event loop. So it may be quite a while before we get back to the event loop. So
set quit_flag to 1 here. Then if QUIT is called before we get to set quit_flag to 1 here. Then if QUIT is called before we get to
the event loop, we will unwind as expected. */ the event loop, we will unwind as expected. */
quit_flag = 1; quit_flag = 1;
/* If immediate_quit is set, we go ahead and process the SIGINT right /* 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 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 assumption here is that it is safe to process ^C immediately if
immediate_quit is set. If we didn't, SIGINT would be really immediate_quit is set. If we didn't, SIGINT would be really
processed only the next time through the event loop. To get to processed only the next time through the event loop. To get to
that point, though, the command that we want to interrupt needs to that point, though, the command that we want to interrupt needs to
finish first, which is unacceptable. If immediate quit is not set, finish first, which is unacceptable. If immediate quit is not set,
we process SIGINT the next time through the loop, which is fine. */ we process SIGINT the next time through the loop, which is fine. */
gdb_call_async_signal_handler (sigint_token, immediate_quit); gdb_call_async_signal_handler (sigint_token, immediate_quit);
} }
@ -887,7 +889,7 @@ handle_sigterm (int sig)
quit_force ((char *) 0, stdin == instream); quit_force ((char *) 0, stdin == instream);
} }
/* Do the quit. All the checks have been done by the caller. */ /* Do the quit. All the checks have been done by the caller. */
void void
async_request_quit (gdb_client_data arg) async_request_quit (gdb_client_data arg)
{ {
@ -895,7 +897,7 @@ async_request_quit (gdb_client_data arg)
back here, that means that an exception was thrown to unwind the back here, that means that an exception was thrown to unwind the
current command before we got back to the event loop. So there current command before we got back to the event loop. So there
is no reason to call quit again here, unless immediate_quit is is no reason to call quit again here, unless immediate_quit is
set.*/ set. */
if (quit_flag || immediate_quit) if (quit_flag || immediate_quit)
quit (); quit ();
@ -903,7 +905,7 @@ async_request_quit (gdb_client_data arg)
#ifdef SIGQUIT #ifdef SIGQUIT
/* Tell the event loop what to do if SIGQUIT is received. /* Tell the event loop what to do if SIGQUIT is received.
See event-signal.c. */ See event-signal.c. */
static void static void
handle_sigquit (int sig) handle_sigquit (int sig)
{ {
@ -918,13 +920,13 @@ handle_sigquit (int sig)
static void static void
async_do_nothing (gdb_client_data arg) async_do_nothing (gdb_client_data arg)
{ {
/* Empty function body. */ /* Empty function body. */
} }
#endif #endif
#ifdef SIGHUP #ifdef SIGHUP
/* Tell the event loop what to do if SIGHUP is received. /* Tell the event loop what to do if SIGHUP is received.
See event-signal.c. */ See event-signal.c. */
static void static void
handle_sighup (int sig) handle_sighup (int sig)
{ {
@ -932,14 +934,14 @@ handle_sighup (int sig)
signal (sig, handle_sighup); signal (sig, handle_sighup);
} }
/* Called by the event loop to process a SIGHUP */ /* Called by the event loop to process a SIGHUP. */
static void static void
async_disconnect (gdb_client_data arg) async_disconnect (gdb_client_data arg)
{ {
catch_errors (quit_cover, NULL, catch_errors (quit_cover, NULL,
"Could not kill the program being debugged", "Could not kill the program being debugged",
RETURN_MASK_ALL); RETURN_MASK_ALL);
signal (SIGHUP, SIG_DFL); /*FIXME: ??????????? */ signal (SIGHUP, SIG_DFL); /*FIXME: ??????????? */
raise (SIGHUP); raise (SIGHUP);
} }
#endif #endif
@ -977,13 +979,14 @@ async_stop_sig (gdb_client_data arg)
printf_unfiltered ("%s", prompt); printf_unfiltered ("%s", prompt);
gdb_flush (gdb_stdout); gdb_flush (gdb_stdout);
/* Forget about any previous command -- null line now will do nothing. */ /* Forget about any previous command -- null line now will do
nothing. */
dont_repeat (); dont_repeat ();
} }
#endif /* STOP_SIGNAL */ #endif /* STOP_SIGNAL */
/* Tell the event loop what to do if SIGFPE is received. /* Tell the event loop what to do if SIGFPE is received.
See event-signal.c. */ See event-signal.c. */
static void static void
handle_sigfpe (int sig) handle_sigfpe (int sig)
{ {
@ -991,17 +994,17 @@ handle_sigfpe (int sig)
signal (sig, handle_sigfpe); signal (sig, handle_sigfpe);
} }
/* Event loop will call this functin to process a SIGFPE. */ /* Event loop will call this functin to process a SIGFPE. */
static void static void
async_float_handler (gdb_client_data arg) async_float_handler (gdb_client_data arg)
{ {
/* This message is based on ANSI C, section 4.7. Note that integer /* This message is based on ANSI C, section 4.7. Note that integer
divide by zero causes this, so "float" is a misnomer. */ divide by zero causes this, so "float" is a misnomer. */
error (_("Erroneous arithmetic operation.")); error (_("Erroneous arithmetic operation."));
} }
/* Tell the event loop what to do if SIGWINCH is received. /* Tell the event loop what to do if SIGWINCH is received.
See event-signal.c. */ See event-signal.c. */
#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER) #if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
static void static void
handle_sigwinch (int sig) handle_sigwinch (int sig)
@ -1014,14 +1017,16 @@ handle_sigwinch (int sig)
/* Called by do_setshow_command. */ /* Called by do_setshow_command. */
void void
set_async_editing_command (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 (); change_line_handler ();
} }
/* Called by do_setshow_command. */ /* Called by do_setshow_command. */
void void
set_async_annotation_level (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 (); change_annotation_level ();
} }
@ -1035,7 +1040,7 @@ set_async_prompt (char *args, int from_tty, struct cmd_list_element *c)
/* Set things up for readline to be invoked via the alternate /* Set things up for readline to be invoked via the alternate
interface, i.e. via a callback function (rl_callback_read_char), interface, i.e. via a callback function (rl_callback_read_char),
and hook up instream to the event loop. */ and hook up instream to the event loop. */
void void
gdb_setup_readline (void) gdb_setup_readline (void)
{ {
@ -1054,7 +1059,7 @@ gdb_setup_readline (void)
editing. */ editing. */
if (ISATTY (instream)) if (ISATTY (instream))
{ {
/* Tell gdb that we will be using the readline library. This /* Tell gdb that we will be using the readline library. This
could be overwritten by a command in .gdbinit like 'set could be overwritten by a command in .gdbinit like 'set
editing on' or 'off'. */ editing on' or 'off'. */
async_command_editing_p = 1; async_command_editing_p = 1;
@ -1070,11 +1075,11 @@ gdb_setup_readline (void)
} }
/* When readline has read an end-of-line character, it passes the /* When readline has read an end-of-line character, it passes the
complete line to gdb for processing. command_line_handler is the complete line to gdb for processing; command_line_handler is the
function that does this. */ function that does this. */
input_handler = command_line_handler; input_handler = command_line_handler;
/* Tell readline to use the same input stream that gdb uses. */ /* Tell readline to use the same input stream that gdb uses. */
rl_instream = instream; rl_instream = instream;
/* Get a file descriptor for the input stream, so that we can /* Get a file descriptor for the input stream, so that we can
@ -1084,7 +1089,7 @@ gdb_setup_readline (void)
/* Now we need to create the event sources for the input file /* Now we need to create the event sources for the input file
descriptor. */ descriptor. */
/* At this point in time, this is the only event source that we /* 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 register with the even loop. Another source is going to be the
target program (inferior), but that must be registered only when target program (inferior), but that must be registered only when
it actually exists (I.e. after we say 'run' or after we connect it actually exists (I.e. after we say 'run' or after we connect
to a remote target. */ to a remote target. */

View file

@ -20,16 +20,21 @@
#include "main.h" #include "main.h"
#include "gdb_string.h" #include "gdb_string.h"
#include "interps.h" #include "interps.h"
#include <mcheck.h>
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
struct captured_main_args args; struct captured_main_args args;
int ret;
mtrace ();
memset (&args, 0, sizeof args); memset (&args, 0, sizeof args);
args.argc = argc; args.argc = argc;
args.argv = argv; args.argv = argv;
args.use_windows = 0; args.use_windows = 0;
args.interpreter_p = INTERP_CONSOLE; args.interpreter_p = INTERP_CONSOLE;
return gdb_main (&args); ret = gdb_main (&args);
muntrace();
return ret;
} }

View file

@ -32,27 +32,27 @@ enum gdb_rc {
set to a freshly allocated copy of the error message. */ set to a freshly allocated copy of the error message. */
/* NOTE: Since ``defs.h:catch_errors()'' does not return an error / /* NOTE: Since ``defs.h:catch_errors()'' does not return an error /
internal / quit indication it is not possible to return that internal / quit indication it is not possible to return that
here. */ here. */
GDB_RC_FAIL = 0, GDB_RC_FAIL = 0,
/* No error occured but nothing happened. Due to the catch_errors() /* No error occured but nothing happened. Due to the catch_errors()
interface, this must be non-zero. */ interface, this must be non-zero. */
GDB_RC_NONE = 1, GDB_RC_NONE = 1,
/* The operation was successful. Due to the catch_errors() /* The operation was successful. Due to the catch_errors()
interface, this must be non-zero. */ interface, this must be non-zero. */
GDB_RC_OK = 2 GDB_RC_OK = 2
}; };
/* Print the specified breakpoint on GDB_STDOUT. (Eventually this /* Print the specified breakpoint on GDB_STDOUT. (Eventually this
function will ``print'' the object on ``output''). */ function will ``print'' the object on ``output''). */
enum gdb_rc gdb_breakpoint_query (struct ui_out *uiout, int bnum, enum gdb_rc gdb_breakpoint_query (struct ui_out *uiout, int bnum,
char **error_message); char **error_message);
/* Switch thread and print notification. */ /* Switch thread and print notification. */
enum gdb_rc gdb_thread_select (struct ui_out *uiout, char *tidstr, enum gdb_rc gdb_thread_select (struct ui_out *uiout, char *tidstr,
char **error_message); char **error_message);
/* Print a list of known thread ids. */ /* Print a list of known thread ids. */
enum gdb_rc gdb_list_thread_ids (struct ui_out *uiout, enum gdb_rc gdb_list_thread_ids (struct ui_out *uiout,
char **error_message); char **error_message);

View file

@ -46,13 +46,13 @@
/* The selected interpreter. This will be used as a set command /* The selected interpreter. This will be used as a set command
variable, so it should always be malloc'ed - since variable, so it should always be malloc'ed - since
do_setshow_command will free it. */ do_setshow_command will free it. */
char *interpreter_p; char *interpreter_p;
/* Whether xdb commands will be handled */ /* Whether xdb commands will be handled. */
int xdb_commands = 0; int xdb_commands = 0;
/* Whether dbx commands will be handled */ /* Whether dbx commands will be handled. */
int dbx_commands = 0; int dbx_commands = 0;
/* System root path, used to find libraries etc. */ /* System root path, used to find libraries etc. */
@ -69,7 +69,7 @@ struct ui_file *gdb_stdout;
struct ui_file *gdb_stderr; struct ui_file *gdb_stderr;
struct ui_file *gdb_stdlog; struct ui_file *gdb_stdlog;
struct ui_file *gdb_stdin; struct ui_file *gdb_stdin;
/* target IO streams */ /* Target IO streams. */
struct ui_file *gdb_stdtargin; struct ui_file *gdb_stdtargin;
struct ui_file *gdb_stdtarg; struct ui_file *gdb_stdtarg;
struct ui_file *gdb_stdtargerr; struct ui_file *gdb_stdtargerr;
@ -86,7 +86,7 @@ int batch_silent = 0;
int return_child_result = 0; int return_child_result = 0;
int return_child_result_value = -1; int return_child_result_value = -1;
/* Whether to enable writing into executable and core files */ /* Whether to enable writing into executable and core files. */
extern int write_files; extern int write_files;
/* GDB as it has been invoked from the command line (i.e. argv[0]). */ /* GDB as it has been invoked from the command line (i.e. argv[0]). */
@ -94,8 +94,8 @@ static char *gdb_program_name;
static void print_gdb_help (struct ui_file *); static void print_gdb_help (struct ui_file *);
/* These two are used to set the external editor commands when gdb is farming /* These two are used to set the external editor commands when gdb is
out files to be edited by another program. */ farming out files to be edited by another program. */
extern char *external_editor_command; extern char *external_editor_command;
@ -151,11 +151,11 @@ relocate_directory (const char *progname, const char *initial, int flag)
return dir; return dir;
} }
/* Compute the locations of init files that GDB should source and return /* Compute the locations of init files that GDB should source and
them in SYSTEM_GDBINIT, HOME_GDBINIT, LOCAL_GDBINIT. If there is return them in SYSTEM_GDBINIT, HOME_GDBINIT, LOCAL_GDBINIT. If
no system gdbinit (resp. home gdbinit and local gdbinit) to be loaded, there is no system gdbinit (resp. home gdbinit and local gdbinit)
then SYSTEM_GDBINIT (resp. HOME_GDBINIT and LOCAL_GDBINIT) is set to to be loaded, then SYSTEM_GDBINIT (resp. HOME_GDBINIT and
NULL. */ LOCAL_GDBINIT) is set to NULL. */
static void static void
get_init_files (char **system_gdbinit, get_init_files (char **system_gdbinit,
char **home_gdbinit, char **home_gdbinit,
@ -220,7 +220,7 @@ get_init_files (char **system_gdbinit,
} }
/* Call command_loop. If it happens to return, pass that through as a /* Call command_loop. If it happens to return, pass that through as a
non-zero return status. */ non-zero return status. */
static int static int
captured_command_loop (void *data) captured_command_loop (void *data)
@ -232,12 +232,12 @@ captured_command_loop (void *data)
the do_cleanups() below is redundant. Unfortunately, many FUNCs the do_cleanups() below is redundant. Unfortunately, many FUNCs
are not that well behaved. do_cleanups should either be replaced are not that well behaved. do_cleanups should either be replaced
with a do_cleanups call (to cover the problem) or an assertion with a do_cleanups call (to cover the problem) or an assertion
check to detect bad FUNCs code. */ check to detect bad FUNCs code. */
do_cleanups (ALL_CLEANUPS); do_cleanups (ALL_CLEANUPS);
/* If the command_loop returned, normally (rather than threw an /* If the command_loop returned, normally (rather than threw an
error) we try to quit. If the quit is aborted, catch_errors() error) we try to quit. If the quit is aborted, catch_errors()
which called this catch the signal and restart the command which called this catch the signal and restart the command
loop. */ loop. */
quit_command (NULL, instream == stdin); quit_command (NULL, instream == stdin);
return 1; return 1;
} }
@ -260,7 +260,8 @@ captured_main (void *data)
char *cdarg = NULL; char *cdarg = NULL;
char *ttyarg = NULL; char *ttyarg = NULL;
/* These are static so that we can take their address in an initializer. */ /* These are static so that we can take their address in an
initializer. */
static int print_help; static int print_help;
static int print_version; static int print_version;
@ -317,7 +318,7 @@ captured_main (void *data)
quit_flag = 0; quit_flag = 0;
line = (char *) xmalloc (linesize); line = (char *) xmalloc (linesize);
line[0] = '\0'; /* Terminate saved (now empty) cmd line */ line[0] = '\0'; /* Terminate saved (now empty) cmd line. */
instream = stdin; instream = stdin;
gdb_stdout = stdio_fileopen (stdout); gdb_stdout = stdio_fileopen (stdout);
@ -332,7 +333,7 @@ captured_main (void *data)
if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf))) if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
/* Don't use *_filtered or warning() (which relies on /* Don't use *_filtered or warning() (which relies on
current_target) until after initialize_all_files(). */ current_target) until after initialize_all_files(). */
fprintf_unfiltered (gdb_stderr, fprintf_unfiltered (gdb_stderr,
_("%s: warning: error finding working directory: %s\n"), _("%s: warning: error finding working directory: %s\n"),
argv[0], safe_strerror (errno)); argv[0], safe_strerror (errno));
@ -400,9 +401,9 @@ captured_main (void *data)
{"batch", no_argument, &batch_flag, 1}, {"batch", no_argument, &batch_flag, 1},
{"epoch", no_argument, &epoch_interface, 1}, {"epoch", no_argument, &epoch_interface, 1},
/* This is a synonym for "--annotate=1". --annotate is now preferred, /* This is a synonym for "--annotate=1". --annotate is now
but keep this here for a long time because people will be running preferred, but keep this here for a long time because people
emacses which use --fullname. */ will be running emacses which use --fullname. */
{"fullname", no_argument, 0, 'f'}, {"fullname", no_argument, 0, 'f'},
{"f", no_argument, 0, 'f'}, {"f", no_argument, 0, 'f'},
@ -559,10 +560,12 @@ captured_main (void *data)
#ifdef GDBTK #ifdef GDBTK
case 'z': case 'z':
{ {
extern int gdbtk_test (char *); extern int gdbtk_test (char *);
if (!gdbtk_test (optarg)) if (!gdbtk_test (optarg))
{ {
fprintf_unfiltered (gdb_stderr, _("%s: unable to load tclcommand file \"%s\""), fprintf_unfiltered (gdb_stderr,
_("%s: unable to load tclcommand file \"%s\""),
argv[0], optarg); argv[0], optarg);
exit (1); exit (1);
} }
@ -605,7 +608,7 @@ extern int gdbtk_test (char *);
if (i == 0 && p == optarg) if (i == 0 && p == optarg)
/* Don't use *_filtered or warning() (which relies on /* Don't use *_filtered or warning() (which relies on
current_target) until after initialize_all_files(). */ current_target) until after initialize_all_files(). */
fprintf_unfiltered fprintf_unfiltered
(gdb_stderr, (gdb_stderr,
@ -623,7 +626,7 @@ extern int gdbtk_test (char *);
if (i == 0 && p == optarg) if (i == 0 && p == optarg)
/* Don't use *_filtered or warning() (which relies on /* Don't use *_filtered or warning() (which relies on
current_target) until after initialize_all_files(). */ current_target) until after initialize_all_files(). */
fprintf_unfiltered fprintf_unfiltered
(gdb_stderr, (gdb_stderr,
@ -655,8 +658,8 @@ extern int gdbtk_test (char *);
control of the console via the deprecated_init_ui_hook (). */ control of the console via the deprecated_init_ui_hook (). */
gdb_init (argv[0]); gdb_init (argv[0]);
/* Now that gdb_init has created the initial inferior, we're in position /* Now that gdb_init has created the initial inferior, we're in
to set args for that inferior. */ position to set args for that inferior. */
if (set_args) if (set_args)
{ {
/* The remaining options are the command-line options for the /* The remaining options are the command-line options for the
@ -706,9 +709,9 @@ Excess command line arguments ignored. (%s%s)\n"),
(optind == argc - 1) ? "" : " ..."); (optind == argc - 1) ? "" : " ...");
} }
/* Lookup gdbinit files. Note that the gdbinit file name may be overriden /* Lookup gdbinit files. Note that the gdbinit file name may be
during file initialization, so get_init_files should be called after overriden during file initialization, so get_init_files should be
gdb_init. */ called after gdb_init. */
get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit); get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit);
/* Do these (and anything which might call wrap_here or *_filtered) /* Do these (and anything which might call wrap_here or *_filtered)
@ -737,19 +740,19 @@ Excess command line arguments ignored. (%s%s)\n"),
it isn't encapsulated in MI output. */ it isn't encapsulated in MI output. */
if (!quiet && strcmp (interpreter_p, INTERP_MI1) == 0) if (!quiet && strcmp (interpreter_p, INTERP_MI1) == 0)
{ {
/* Print all the junk at the top, with trailing "..." if we are about /* Print all the junk at the top, with trailing "..." if we are
to read a symbol file (possibly slowly). */ about to read a symbol file (possibly slowly). */
print_gdb_version (gdb_stdout); print_gdb_version (gdb_stdout);
if (symarg) if (symarg)
printf_filtered (".."); printf_filtered ("..");
wrap_here (""); wrap_here ("");
printf_filtered ("\n"); printf_filtered ("\n");
gdb_flush (gdb_stdout); /* Force to screen during slow operations */ gdb_flush (gdb_stdout); /* Force to screen during slow
operations. */
} }
/* Install the default UI. All the interpreters should have had a /* Install the default UI. All the interpreters should have had a
look at things by now. Initialize the default interpreter. */ look at things by now. Initialize the default interpreter. */
{ {
/* Find it. */ /* Find it. */
@ -773,14 +776,15 @@ Excess command line arguments ignored. (%s%s)\n"),
any sane interpreter. */ any sane interpreter. */
if (!quiet && !current_interp_named_p (INTERP_MI1)) if (!quiet && !current_interp_named_p (INTERP_MI1))
{ {
/* Print all the junk at the top, with trailing "..." if we are about /* Print all the junk at the top, with trailing "..." if we are
to read a symbol file (possibly slowly). */ about to read a symbol file (possibly slowly). */
print_gdb_version (gdb_stdout); print_gdb_version (gdb_stdout);
if (symarg) if (symarg)
printf_filtered (".."); printf_filtered ("..");
wrap_here (""); wrap_here ("");
printf_filtered ("\n"); printf_filtered ("\n");
gdb_flush (gdb_stdout); /* Force to screen during slow operations */ gdb_flush (gdb_stdout); /* Force to screen during slow
operations. */
} }
/* Set off error and warning messages with a blank line. */ /* Set off error and warning messages with a blank line. */
@ -814,7 +818,8 @@ Excess command line arguments ignored. (%s%s)\n"),
xfree (dirarg); xfree (dirarg);
/* Skip auto-loading section-specified scripts until we've sourced /* Skip auto-loading section-specified scripts until we've sourced
local_gdbinit (which is often used to augment the source search path). */ local_gdbinit (which is often used to augment the source search
path). */
save_auto_load = gdbpy_global_auto_load; save_auto_load = gdbpy_global_auto_load;
gdbpy_global_auto_load = 0; gdbpy_global_auto_load = 0;
@ -824,7 +829,7 @@ Excess command line arguments ignored. (%s%s)\n"),
{ {
/* The exec file and the symbol-file are the same. If we can't /* The exec file and the symbol-file are the same. If we can't
open it, better only print one error message. open it, better only print one error message.
catch_command_errors returns non-zero on success! */ catch_command_errors returns non-zero on success! */
if (catch_command_errors (exec_file_attach, execarg, !batch_flag, RETURN_MASK_ALL)) if (catch_command_errors (exec_file_attach, execarg, !batch_flag, RETURN_MASK_ALL))
catch_command_errors (symbol_file_add_main, symarg, !batch_flag, RETURN_MASK_ALL); catch_command_errors (symbol_file_add_main, symarg, !batch_flag, RETURN_MASK_ALL);
} }
@ -867,7 +872,7 @@ Can't attach to process and specify a core file at the same time."));
if (ttyarg != NULL) if (ttyarg != NULL)
set_inferior_io_terminal (ttyarg); set_inferior_io_terminal (ttyarg);
/* Error messages should no longer be distinguished with extra output. */ /* Error messages should no longer be distinguished with extra output. */
error_pre_print = NULL; error_pre_print = NULL;
quit_pre_print = NULL; quit_pre_print = NULL;
warning_pre_print = _("warning: "); warning_pre_print = _("warning: ");
@ -896,7 +901,8 @@ Can't attach to process and specify a core file at the same time."));
} }
xfree (cmdarg); xfree (cmdarg);
/* Read in the old history after all the command files have been read. */ /* Read in the old history after all the command files have been
read. */
init_history (); init_history ();
if (batch_flag) if (batch_flag)
@ -911,7 +917,7 @@ Can't attach to process and specify a core file at the same time."));
/* NOTE: cagney/1999-11-07: There is probably no reason for not /* NOTE: cagney/1999-11-07: There is probably no reason for not
moving this loop and the code found in captured_command_loop() moving this loop and the code found in captured_command_loop()
into the command_loop() proper. The main thing holding back that into the command_loop() proper. The main thing holding back that
change - SET_TOP_LEVEL() - has been eliminated. */ change - SET_TOP_LEVEL() - has been eliminated. */
while (1) while (1)
{ {
catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL); catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL);

157
gdb/top.c
View file

@ -49,7 +49,7 @@
#include "gdbthread.h" #include "gdbthread.h"
#include "python/python.h" #include "python/python.h"
/* readline include files */ /* readline include files. */
#include "readline/readline.h" #include "readline/readline.h"
#include "readline/history.h" #include "readline/history.h"
@ -65,7 +65,7 @@
#include "ui-out.h" #include "ui-out.h"
#include "cli-out.h" #include "cli-out.h"
/* Default command line prompt. This is overriden in some configs. */ /* Default command line prompt. This is overriden in some configs. */
#ifndef DEFAULT_PROMPT #ifndef DEFAULT_PROMPT
#define DEFAULT_PROMPT "(gdb) " #define DEFAULT_PROMPT "(gdb) "
@ -97,7 +97,7 @@ extern char lang_frame_mismatch_warn[]; /* language.c */
/* Flag for whether we want all the "from_tty" gubbish printed. */ /* Flag for whether we want all the "from_tty" gubbish printed. */
int caution = 1; /* Default is yes, sigh. */ int caution = 1; /* Default is yes, sigh. */
static void static void
show_caution (struct ui_file *file, int from_tty, show_caution (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value) struct cmd_list_element *c, const char *value)
@ -107,9 +107,10 @@ Whether to confirm potentially dangerous operations is %s.\n"),
value); value);
} }
/* stdio stream that command input is being read from. Set to stdin normally. /* stdio stream that command input is being read from. Set to stdin
Set by source_command to the file we are sourcing. Set to NULL if we are normally. Set by source_command to the file we are sourcing. Set
executing a user-defined command or interacting via a GUI. */ to NULL if we are executing a user-defined command or interacting
via a GUI. */
FILE *instream; FILE *instream;
@ -149,12 +150,12 @@ int server_command;
/* Baud rate specified for talking to serial target systems. Default /* Baud rate specified for talking to serial target systems. Default
is left as -1, so targets can choose their own defaults. */ is left as -1, so targets can choose their own defaults. */
/* FIXME: This means that "show remotebaud" and gr_files_info can print -1 /* FIXME: This means that "show remotebaud" and gr_files_info can
or (unsigned int)-1. This is a Bad User Interface. */ print -1 or (unsigned int)-1. This is a Bad User Interface. */
int baud_rate = -1; int baud_rate = -1;
/* Timeout limit for response from target. */ /* Timeout limit for response from target. */
/* The default value has been changed many times over the years. It /* The default value has been changed many times over the years. It
was originally 5 seconds. But that was thought to be a long time was originally 5 seconds. But that was thought to be a long time
@ -172,7 +173,7 @@ int baud_rate = -1;
a single variable for all protocol timeouts. a single variable for all protocol timeouts.
As remote.c is used much more than remote-e7000.c, it was changed As remote.c is used much more than remote-e7000.c, it was changed
back to 2 seconds in 1999. */ back to 2 seconds in 1999. */
int remote_timeout = 2; int remote_timeout = 2;
@ -187,17 +188,18 @@ char *lim_at_start;
/* Hooks for alternate command interfaces. */ /* Hooks for alternate command interfaces. */
/* Called after most modules have been initialized, but before taking users /* Called after most modules have been initialized, but before taking
command file. users command file.
If the UI fails to initialize and it wants GDB to continue If the UI fails to initialize and it wants GDB to continue using
using the default UI, then it should clear this hook before returning. */ the default UI, then it should clear this hook before returning. */
void (*deprecated_init_ui_hook) (char *argv0); void (*deprecated_init_ui_hook) (char *argv0);
/* This hook is called from within gdb's many mini-event loops which could /* This hook is called from within gdb's many mini-event loops which
steal control from a real user interface's event loop. It returns could steal control from a real user interface's event loop. It
non-zero if the user is requesting a detach, zero otherwise. */ returns non-zero if the user is requesting a detach, zero
otherwise. */
int (*deprecated_ui_loop_hook) (int); int (*deprecated_ui_loop_hook) (int);
@ -209,8 +211,10 @@ void (*deprecated_command_loop_hook) (void);
/* Called from print_frame_info to list the line we stopped in. */ /* Called from print_frame_info to list the line we stopped in. */
void (*deprecated_print_frame_info_listing_hook) (struct symtab * s, int line, void (*deprecated_print_frame_info_listing_hook) (struct symtab * s,
int stopline, int noerror); int line,
int stopline,
int noerror);
/* Replaces most of query. */ /* Replaces most of query. */
int (*deprecated_query_hook) (const char *, va_list); int (*deprecated_query_hook) (const char *, va_list);
@ -236,33 +240,33 @@ char *(*deprecated_readline_hook) (char *);
void (*deprecated_readline_end_hook) (void); void (*deprecated_readline_end_hook) (void);
/* Called as appropriate to notify the interface that we have attached /* Called as appropriate to notify the interface that we have attached
to or detached from an already running process. */ to or detached from an already running process. */
void (*deprecated_attach_hook) (void); void (*deprecated_attach_hook) (void);
void (*deprecated_detach_hook) (void); void (*deprecated_detach_hook) (void);
/* Called during long calculations to allow GUI to repair window damage, and to /* Called during long calculations to allow GUI to repair window
check for stop buttons, etc... */ damage, and to check for stop buttons, etc... */
void (*deprecated_interactive_hook) (void); void (*deprecated_interactive_hook) (void);
/* Tell the GUI someone changed the register REGNO. -1 means /* Tell the GUI someone changed the register REGNO. -1 means
that the caller does not know which register changed or that the caller does not know which register changed or
that several registers have changed (see value_assign). */ that several registers have changed (see value_assign). */
void (*deprecated_register_changed_hook) (int regno); void (*deprecated_register_changed_hook) (int regno);
/* Called when going to wait for the target. Usually allows the GUI to run /* Called when going to wait for the target. Usually allows the GUI
while waiting for target events. */ to run while waiting for target events. */
ptid_t (*deprecated_target_wait_hook) (ptid_t ptid, ptid_t (*deprecated_target_wait_hook) (ptid_t ptid,
struct target_waitstatus *status, struct target_waitstatus *status,
int options); int options);
/* Used by UI as a wrapper around command execution. May do various things /* Used by UI as a wrapper around command execution. May do various
like enabling/disabling buttons, etc... */ things like enabling/disabling buttons, etc... */
void (*deprecated_call_command_hook) (struct cmd_list_element * c, char *cmd, void (*deprecated_call_command_hook) (struct cmd_list_element * c,
int from_tty); char *cmd, int from_tty);
/* Called after a `set' command has finished. Is only run if the /* Called after a `set' command has finished. Is only run if the
`set' command succeeded. */ `set' command succeeded. */
@ -283,7 +287,8 @@ void (*deprecated_context_hook) (int id);
quit_cover (void *s) quit_cover (void *s)
{ {
caution = 0; /* Throw caution to the wind -- we're exiting. caution = 0; /* Throw caution to the wind -- we're exiting.
This prevents asking the user dumb questions. */ This prevents asking the user dumb
questions. */
quit_command ((char *) 0, 0); quit_command ((char *) 0, 0);
return 0; return 0;
} }
@ -339,10 +344,10 @@ prepare_execute_command (void)
{ {
free_all_values (); free_all_values ();
/* With multiple threads running while the one we're examining is stopped, /* With multiple threads running while the one we're examining is
the dcache can get stale without us being able to detect it. stopped, the dcache can get stale without us being able to detect
For the duration of the command, though, use the dcache to help it. For the duration of the command, though, use the dcache to
things like backtrace. */ help things like backtrace. */
if (non_stop) if (non_stop)
target_dcache_invalidate (); target_dcache_invalidate ();
} }
@ -405,7 +410,7 @@ execute_command (char *p, int from_tty)
*(p + 1) = '\0'; *(p + 1) = '\0';
} }
/* If this command has been pre-hooked, run the hook first. */ /* If this command has been pre-hooked, run the hook first. */
execute_cmd_pre_hook (c); execute_cmd_pre_hook (c);
if (c->flags & DEPRECATED_WARN_USER) if (c->flags & DEPRECATED_WARN_USER)
@ -422,7 +427,7 @@ execute_command (char *p, int from_tty)
else else
cmd_func (c, arg, from_tty & caution); cmd_func (c, arg, from_tty & caution);
/* If this command has been post-hooked, run the hook last. */ /* If this command has been post-hooked, run the hook last. */
execute_cmd_post_hook (c); execute_cmd_post_hook (c);
} }
@ -442,7 +447,7 @@ execute_command (char *p, int from_tty)
/* Warn the user if the working language does not match the /* Warn the user if the working language does not match the
language of the current frame. Only warn the user if we are language of the current frame. Only warn the user if we are
actually running the program, i.e. there is a stack. */ actually running the program, i.e. there is a stack. */
/* FIXME: This should be cacheing the frame and only running when /* FIXME: This should be cacheing the frame and only running when
the frame changes. */ the frame changes. */
@ -523,7 +528,7 @@ command_loop (void)
reinitialize_more_filter (); reinitialize_more_filter ();
old_chain = make_cleanup (null_cleanup, 0); old_chain = make_cleanup (null_cleanup, 0);
/* Get a command-line. This calls the readline package. */ /* Get a command-line. This calls the readline package. */
command = command_line_input (instream == stdin ? command = command_line_input (instream == stdin ?
get_prompt () : (char *) NULL, get_prompt () : (char *) NULL,
instream == stdin, "prompt"); instream == stdin, "prompt");
@ -550,8 +555,8 @@ dont_repeat (void)
return; return;
/* If we aren't reading from standard input, we are saving the last /* If we aren't reading from standard input, we are saving the last
thing read from stdin in line and don't want to delete it. Null lines thing read from stdin in line and don't want to delete it. Null
won't repeat here in any case. */ lines won't repeat here in any case. */
if (instream == stdin) if (instream == stdin)
*line = 0; *line = 0;
} }
@ -880,8 +885,9 @@ command_line_input (char *prompt_arg, int repeat, char *annotation_suffix)
while (1) while (1)
{ {
/* Make sure that all output has been output. Some machines may let /* Make sure that all output has been output. Some machines may
you get away with leaving out some of the gdb_flush, but not all. */ let you get away with leaving out some of the gdb_flush, but
not all. */
wrap_here (""); wrap_here ("");
gdb_flush (gdb_stdout); gdb_flush (gdb_stdout);
gdb_flush (gdb_stderr); gdb_flush (gdb_stderr);
@ -931,7 +937,7 @@ command_line_input (char *prompt_arg, int repeat, char *annotation_suffix)
} }
p1 = rl; p1 = rl;
/* Copy line. Don't copy null at end. (Leaves line alone /* Copy line. Don't copy null at end. (Leaves line alone
if this was just a newline) */ if this was just a newline). */
while (*p1) while (*p1)
*p++ = *p1++; *p++ = *p1++;
@ -997,9 +1003,8 @@ command_line_input (char *prompt_arg, int repeat, char *annotation_suffix)
xfree (history_value); xfree (history_value);
} }
/* If we just got an empty line, and that is supposed /* If we just got an empty line, and that is supposed to repeat the
to repeat the previous command, return the value in the previous command, return the value in the global buffer. */
global buffer. */
if (repeat && p == linebuffer) if (repeat && p == linebuffer)
return line; return line;
for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++); for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++);
@ -1020,7 +1025,7 @@ command_line_input (char *prompt_arg, int repeat, char *annotation_suffix)
and remove the '#'. The kill ring is probably better, but some and remove the '#'. The kill ring is probably better, but some
people are in the habit of commenting things out. */ people are in the habit of commenting things out. */
if (*p1 == '#') if (*p1 == '#')
*p1 = '\0'; /* Found a comment. */ *p1 = '\0'; /* Found a comment. */
/* Save into global buffer if appropriate. */ /* Save into global buffer if appropriate. */
if (repeat) if (repeat)
@ -1037,24 +1042,24 @@ command_line_input (char *prompt_arg, int repeat, char *annotation_suffix)
return linebuffer; return linebuffer;
} }
/* Print the GDB banner. */ /* Print the GDB banner. */
void void
print_gdb_version (struct ui_file *stream) print_gdb_version (struct ui_file *stream)
{ {
/* From GNU coding standards, first line is meant to be easy for a /* From GNU coding standards, first line is meant to be easy for a
program to parse, and is just canonical program name and version program to parse, and is just canonical program name and version
number, which starts after last space. */ number, which starts after last space. */
fprintf_filtered (stream, "GNU gdb %s%s\n", PKGVERSION, version); fprintf_filtered (stream, "GNU gdb %s%s\n", PKGVERSION, version);
/* Second line is a copyright notice. */ /* Second line is a copyright notice. */
fprintf_filtered (stream, "Copyright (C) 2010 Free Software Foundation, Inc.\n"); fprintf_filtered (stream, "Copyright (C) 2010 Free Software Foundation, Inc.\n");
/* Following the copyright is a brief statement that the program is /* Following the copyright is a brief statement that the program is
free software, that users are free to copy and change it on free software, that users are free to copy and change it on
certain conditions, that it is covered by the GNU GPL, and that certain conditions, that it is covered by the GNU GPL, and that
there is no warranty. */ there is no warranty. */
fprintf_filtered (stream, "\ fprintf_filtered (stream, "\
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\ License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
@ -1062,7 +1067,7 @@ This is free software: you are free to change and redistribute it.\n\
There is NO WARRANTY, to the extent permitted by law. Type \"show copying\"\n\ There is NO WARRANTY, to the extent permitted by law. Type \"show copying\"\n\
and \"show warranty\" for details.\n"); and \"show warranty\" for details.\n");
/* After the required info we print the configuration information. */ /* After the required info we print the configuration information. */
fprintf_filtered (stream, "This GDB was configured as \""); fprintf_filtered (stream, "This GDB was configured as \"");
if (strcmp (host_name, target_name) != 0) if (strcmp (host_name, target_name) != 0)
@ -1097,7 +1102,7 @@ set_prompt (char *s)
/* ??rehrauer: I don't know why this fails, since it looks as though /* ??rehrauer: I don't know why this fails, since it looks as though
assignments to prompt are wrapped in calls to xstrdup... assignments to prompt are wrapped in calls to xstrdup...
if (prompt != NULL) if (prompt != NULL)
xfree (prompt); xfree (prompt);
*/ */
PROMPT (0) = xstrdup (s); PROMPT (0) = xstrdup (s);
} }
@ -1221,8 +1226,8 @@ quit_target (void *arg)
if (write_history_p && history_filename) if (write_history_p && history_filename)
write_history (history_filename); write_history (history_filename);
do_final_cleanups (ALL_CLEANUPS); /* Do any final cleanups before exiting */ do_final_cleanups (ALL_CLEANUPS); /* Do any final cleanups before
exiting. */
return 0; return 0;
} }
@ -1235,7 +1240,7 @@ quit_force (char *args, int from_tty)
struct qt_args qt; struct qt_args qt;
/* An optional expression may be used to cause gdb to terminate with the /* An optional expression may be used to cause gdb to terminate with the
value of that expression. */ value of that expression. */
if (args) if (args)
{ {
struct value *val = parse_and_eval (args); struct value *val = parse_and_eval (args);
@ -1305,8 +1310,8 @@ input_from_terminal_p (void)
static void static void
dont_repeat_command (char *ignored, int from_tty) dont_repeat_command (char *ignored, int from_tty)
{ {
*line = 0; /* Can't call dont_repeat here because we're not *line = 0; /* Can't call dont_repeat here because we're
necessarily reading from stdin. */ not necessarily reading from stdin. */
} }
/* Functions to manipulate command line editing control variables. */ /* Functions to manipulate command line editing control variables. */
@ -1414,7 +1419,7 @@ show_history (char *args, int from_tty)
cmd_show_list (showhistlist, from_tty, ""); cmd_show_list (showhistlist, from_tty, "");
} }
int info_verbose = 0; /* Default verbose msgs off */ int info_verbose = 0; /* Default verbose msgs off. */
/* Called by do_setshow_command. An elaborate joke. */ /* Called by do_setshow_command. An elaborate joke. */
void void
@ -1438,10 +1443,9 @@ set_verbose (char *args, int from_tty, struct cmd_list_element *c)
} }
/* Init the history buffer. Note that we are called after the init file(s) /* Init the history buffer. Note that we are called after the init file(s)
* have been read so that the user can change the history file via his have been read so that the user can change the history file via his
* .gdbinit file (for instance). The GDBHISTFILE environment variable .gdbinit file (for instance). The GDBHISTFILE environment variable
* overrides all of this. overrides all of this. */
*/
void void
init_history (void) init_history (void)
@ -1647,7 +1651,7 @@ gdb_init (char *argv0)
if (pre_init_ui_hook) if (pre_init_ui_hook)
pre_init_ui_hook (); pre_init_ui_hook ();
/* Run the init function of each source file */ /* Run the init function of each source file. */
#ifdef __MSDOS__ #ifdef __MSDOS__
/* Make sure we return to the original directory upon exit, come /* Make sure we return to the original directory upon exit, come
@ -1655,9 +1659,9 @@ gdb_init (char *argv0)
make_final_cleanup (do_chdir_cleanup, xstrdup (current_directory)); make_final_cleanup (do_chdir_cleanup, xstrdup (current_directory));
#endif #endif
init_cmd_lists (); /* This needs to be done first */ init_cmd_lists (); /* This needs to be done first. */
initialize_targets (); /* Setup target_terminal macros for utils.c */ initialize_targets (); /* Setup target_terminal macros for utils.c. */
initialize_utils (); /* Make errors and warnings possible */ initialize_utils (); /* Make errors and warnings possible. */
/* Here is where we call all the _initialize_foo routines. */ /* Here is where we call all the _initialize_foo routines. */
initialize_all_files (); initialize_all_files ();
@ -1671,17 +1675,18 @@ gdb_init (char *argv0)
initialize_inferiors (); initialize_inferiors ();
initialize_current_architecture (); initialize_current_architecture ();
init_cli_cmds(); init_cli_cmds();
init_main (); /* But that omits this file! Do it now */ init_main (); /* But that omits this file! Do it now. */
initialize_stdin_serial (); initialize_stdin_serial ();
async_init_signals (); async_init_signals ();
/* We need a default language for parsing expressions, so simple things like /* We need a default language for parsing expressions, so simple
"set width 0" won't fail if no language is explicitly set in a config file things like "set width 0" won't fail if no language is explicitly
or implicitly set by reading an executable during startup. */ set in a config file or implicitly set by reading an executable
during startup. */
set_language (language_c); set_language (language_c);
expected_language = current_language; /* don't warn about the change. */ expected_language = current_language; /* Don't warn about the change. */
/* Allow another UI to initialize. If the UI fails to initialize, /* Allow another UI to initialize. If the UI fails to initialize,
and it wants GDB to revert to the CLI, it should clear and it wants GDB to revert to the CLI, it should clear
@ -1690,10 +1695,10 @@ gdb_init (char *argv0)
deprecated_init_ui_hook (argv0); deprecated_init_ui_hook (argv0);
#ifdef HAVE_PYTHON #ifdef HAVE_PYTHON
/* Python initialization can require various commands to be installed. /* Python initialization can require various commands to be
For example "info pretty-printer" needs the "info" prefix to be installed. For example "info pretty-printer" needs the "info"
installed. Keep things simple and just do final python initialization prefix to be installed. Keep things simple and just do final
here. */ python initialization here. */
finish_python_initialization (); finish_python_initialization ();
#endif #endif
} }

View file

@ -52,21 +52,21 @@ extern void execute_command (char *, int);
extern void prepare_execute_command (void); extern void prepare_execute_command (void);
/* This function returns a pointer to the string that is used /* This function returns a pointer to the string that is used
by gdb for its command prompt. */ by gdb for its command prompt. */
extern char *get_prompt (void); extern char *get_prompt (void);
/* This function copies the specified string into the string that /* This function copies the specified string into the string that
is used by gdb for its command prompt. */ is used by gdb for its command prompt. */
extern void set_prompt (char *); extern void set_prompt (char *);
/* From random places. */ /* From random places. */
extern int readnow_symbol_files; extern int readnow_symbol_files;
/* Perform _initialize initialization */ /* Perform _initialize initialization. */
extern void gdb_init (char *); extern void gdb_init (char *);
/* For use by event-top.c */ /* For use by event-top.c. */
/* Variables from top.c. */ /* Variables from top.c. */
extern int source_line_number; extern int source_line_number;
extern const char *source_file_name; extern const char *source_file_name;
extern int history_expansion_p; extern int history_expansion_p;