aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbtk.c
diff options
context:
space:
mode:
authorStu Grossman <grossman@cygnus>1994-10-21 00:59:20 +0000
committerStu Grossman <grossman@cygnus>1994-10-21 00:59:20 +0000
commit479f0f18d4a77e04b32cc7062ee31310b876e16b (patch)
tree3d0b2d2df5646de9741407942764a2e4981beed6 /gdb/gdbtk.c
parent1b79c34daa80f7cbbc3c16d603d44f482f9296bf (diff)
downloadgdb-479f0f18d4a77e04b32cc7062ee31310b876e16b.zip
gdb-479f0f18d4a77e04b32cc7062ee31310b876e16b.tar.gz
gdb-479f0f18d4a77e04b32cc7062ee31310b876e16b.tar.bz2
* defs.h, infrun.c (wait_for_inferior), top.c: Call
target_wait_hook to allow GUI to handle blocking for inferior. Call call_command_hook in execute_command to provide means for wrapping commands with GUI state change updates. * gdbtk.c (gdb_cmd): Force GUI into idle mode when errors occur. * (gdb_stop): New tcl command to stop the target process. * (x_event, gdbtk_wait): Allow GUI to interrupt gdb out of target waits. * (gdbtk_call_command): Wrapper around command processing to alert GUI of target state changes. * (gdbtk_init): Get the fd of X server for doing async notification of X events (via x_event). Setup new hooks. * gdbtk.tcl: Add scrollbars to assembly and command windows. * Change window foreground & background colors. * Create margin tag for breakpoints in source and assembly windows. * Add new routines to be invoked when target state changes to/from idle. * Add start of expression window. * Change bindings of mouse button 1 in assembly and source window to just set or clear breakpoints when in the margin tag. * Change shape of register window to be more vertical to better reflect it's contents. * Add stop button. * Cleanup some code around command window bindings. * infrun.c (wait_for_inferior): Make sure through_sigtramp_breakpoint is non-null before deleting.
Diffstat (limited to 'gdb/gdbtk.c')
-rw-r--r--gdb/gdbtk.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/gdb/gdbtk.c b/gdb/gdbtk.c
index 9843b43..e96ea19 100644
--- a/gdb/gdbtk.c
+++ b/gdb/gdbtk.c
@@ -54,6 +54,8 @@ static Tcl_Interp *interp = NULL;
/* Handle for TK main window */
static Tk_Window mainWindow = NULL;
+static int x_fd; /* X network socket */
+
static void
null_routine(arg)
int arg;
@@ -336,6 +338,12 @@ gdb_cmd (clientData, interp, argc, argv)
val = catch_errors (gdb_cmd_stub, argv[1], "", RETURN_MASK_ERROR);
+ /* In case of an error, we may need to force the GUI into idle mode because
+ gdbtk_call_command may have bombed out while in the command routine. */
+
+ if (val == 0)
+ Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
+
bpstat_do_actions (&stop_bpstat);
do_cleanups (old_chain);
@@ -367,6 +375,22 @@ gdb_listfiles (clientData, interp, argc, argv)
return TCL_OK;
}
+
+static int
+gdb_stop (clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char *argv[];
+{
+ extern pid_t inferior_process_group;
+
+ /* XXX - This is WRONG for remote targets. Probably need a target vector
+ entry to do this right. */
+
+ kill (-inferior_process_group, SIGINT);
+}
+
static void
tk_command (cmd, from_tty)
@@ -401,11 +425,59 @@ gdbtk_interactive ()
/* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
}
+/* Come here when there is activity on the X file descriptor. */
+
+static void
+x_event (signo)
+ int signo;
+{
+ /* Process pending events */
+
+ while (Tk_DoOneEvent (TK_DONT_WAIT|TK_ALL_EVENTS) != 0);
+}
+
+static int
+gdbtk_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ signal (SIGIO, x_event);
+
+ pid = target_wait (pid, ourstatus);
+
+ signal (SIGIO, SIG_IGN);
+
+ return pid;
+}
+
+/* This is called from execute_command, and provides a wrapper around
+ various command routines in a place where both protocol messages and
+ user input both flow through. Mostly this is used for indicating whether
+ the target process is running or not.
+*/
+
+static void
+gdbtk_call_command (cmdblk, arg, from_tty)
+ struct cmd_list_element *cmdblk;
+ char *arg;
+ int from_tty;
+{
+ if (cmdblk->class == class_run)
+ {
+ Tcl_VarEval (interp, "gdbtk_tcl_busy", NULL);
+ (*cmdblk->function.cfunc)(arg, from_tty);
+ Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
+ }
+ else
+ (*cmdblk->function.cfunc)(arg, from_tty);
+}
+
static void
gdbtk_init ()
{
struct cleanup *old_chain;
char *gdbtk_filename;
+ int i;
old_chain = make_cleanup (cleanup_init, 0);
@@ -430,6 +502,7 @@ gdbtk_init ()
Tcl_CreateCommand (interp, "gdb_cmd", gdb_cmd, NULL, NULL);
Tcl_CreateCommand (interp, "gdb_loc", gdb_loc, NULL, NULL);
Tcl_CreateCommand (interp, "gdb_listfiles", gdb_listfiles, NULL, NULL);
+ Tcl_CreateCommand (interp, "gdb_stop", gdb_stop, NULL, NULL);
gdbtk_filename = getenv ("GDBTK_FILENAME");
if (!gdbtk_filename)
@@ -441,6 +514,19 @@ gdbtk_init ()
if (Tcl_EvalFile (interp, gdbtk_filename) != TCL_OK)
error ("Failure reading %s: %s", gdbtk_filename, interp->result);
+ /* XXX - Get the file descriptor for the network socket. This is not Kosher
+ as it involves looking at data private to Xlib. */
+
+ x_fd = Tk_Display (mainWindow) -> fd;
+
+ /* Setup for I/O interrupts */
+
+ signal (SIGIO, SIG_IGN);
+
+ i = fcntl (x_fd, F_GETFL, 0);
+ fcntl (x_fd, F_SETFL, i|FASYNC);
+ fcntl (x_fd, F_SETOWN, getpid());
+
command_loop_hook = Tk_MainLoop;
fputs_unfiltered_hook = gdbtk_fputs;
print_frame_info_listing_hook = null_routine;
@@ -451,6 +537,8 @@ gdbtk_init ()
enable_breakpoint_hook = gdbtk_enable_breakpoint;
disable_breakpoint_hook = gdbtk_disable_breakpoint;
interactive_hook = gdbtk_interactive;
+ target_wait_hook = gdbtk_wait;
+ call_command_hook = gdbtk_call_command;
discard_cleanups (old_chain);