* defs.h, gdbtk.c (gdbtk_fputs), main.c (gdb_fputs), top.c: Add stream arg
to fputs_unfiltered_hook. Differentiate stdout from stderr when passing text into tcl land. * defs.h, top.c, utils.c (error): Add error_hook. * gdbtk.c: Improve mechanism for capturing output values. * (full_filename): Remove. * (gdb_cmd call_wrapper gdbtk_init): Protect all calls from tcl land with call_wrapper. This prevents longjmps (usually via error()) from jumping out of tcl/tk and leaving things in an indeterminate state. * gdbtk.tcl: New view option to disable line numbers. Put catch around most uses of gdb_cmd. Add update button to reg config window. Stop doing immediate updates when selecting registers. Change register view values into checkbuttons.
This commit is contained in:
parent
243babd424
commit
86db943ceb
|
@ -1,3 +1,20 @@
|
|||
Thu Dec 15 16:40:10 1994 Stu Grossman (grossman@cygnus.com)
|
||||
|
||||
* defs.h, gdbtk.c (gdbtk_fputs), main.c (gdb_fputs), top.c: Add stream arg
|
||||
to fputs_unfiltered_hook. Differentiate stdout from stderr when
|
||||
passing text into tcl land.
|
||||
* defs.h, top.c, utils.c (error): Add error_hook.
|
||||
* gdbtk.c: Improve mechanism for capturing output values.
|
||||
* (full_filename): Remove.
|
||||
* (gdb_cmd call_wrapper gdbtk_init): Protect all calls from tcl
|
||||
land with call_wrapper. This prevents longjmps (usually via
|
||||
error()) from jumping out of tcl/tk and leaving things in an
|
||||
indeterminate state.
|
||||
* gdbtk.tcl: New view option to disable line numbers. Put catch
|
||||
around most uses of gdb_cmd. Add update button to reg config
|
||||
window. Stop doing immediate updates when selecting registers.
|
||||
Change register view values into checkbuttons.
|
||||
|
||||
Tue Dec 13 15:15:33 1994 Stan Shebs <shebs@andros.cygnus.com>
|
||||
|
||||
* breakpoint.c, infrun.c, printcmd.c: Change long command help
|
||||
|
|
40
gdb/defs.h
40
gdb/defs.h
|
@ -33,6 +33,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
/* libiberty.h can't declare this one, but evidently we can. */
|
||||
extern char *strsignal PARAMS ((int));
|
||||
|
||||
#include "mmalloc.h"
|
||||
|
||||
/* For BFD64 and bfd_vma. */
|
||||
#include "bfd.h"
|
||||
|
||||
|
@ -138,28 +140,6 @@ extern int inside_main_func PARAMS ((CORE_ADDR pc));
|
|||
|
||||
extern char *chill_demangle PARAMS ((const char *));
|
||||
|
||||
/* From libiberty.a */
|
||||
|
||||
extern char *cplus_demangle PARAMS ((const char *, int));
|
||||
|
||||
extern char *cplus_mangle_opname PARAMS ((char *, int));
|
||||
|
||||
/* From libmmalloc.a (memory mapped malloc library) */
|
||||
|
||||
extern PTR mmalloc_attach PARAMS ((int, PTR));
|
||||
|
||||
extern PTR mmalloc_detach PARAMS ((PTR));
|
||||
|
||||
extern PTR mmalloc PARAMS ((PTR, long));
|
||||
|
||||
extern PTR mrealloc PARAMS ((PTR, PTR, long));
|
||||
|
||||
extern void mfree PARAMS ((PTR, PTR));
|
||||
|
||||
extern int mmalloc_setkey PARAMS ((PTR, int, PTR));
|
||||
|
||||
extern PTR mmalloc_getkey PARAMS ((PTR, int));
|
||||
|
||||
/* From utils.c */
|
||||
|
||||
extern int strcmp_iw PARAMS ((const char *, const char *));
|
||||
|
@ -544,19 +524,9 @@ extern PTR xmmalloc PARAMS ((PTR, long));
|
|||
|
||||
extern PTR xmrealloc PARAMS ((PTR, PTR, long));
|
||||
|
||||
extern PTR mmalloc PARAMS ((PTR, long));
|
||||
|
||||
extern PTR mrealloc PARAMS ((PTR, PTR, long));
|
||||
|
||||
extern void mfree PARAMS ((PTR, PTR));
|
||||
|
||||
extern int mmcheck PARAMS ((PTR, void (*) (void)));
|
||||
|
||||
extern int mmtrace PARAMS ((void));
|
||||
|
||||
extern int parse_escape PARAMS ((char **));
|
||||
|
||||
extern const char * const reg_names[];
|
||||
extern char *reg_names[];
|
||||
|
||||
/* Message to be printed before the error message, when an error occurs. */
|
||||
|
||||
|
@ -862,7 +832,7 @@ extern CORE_ADDR push_word PARAMS ((CORE_ADDR, unsigned LONGEST));
|
|||
|
||||
extern void (*init_ui_hook) PARAMS ((void));
|
||||
extern void (*command_loop_hook) PARAMS ((void));
|
||||
extern void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer));
|
||||
extern void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, FILE *stream));
|
||||
extern void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s, int line,
|
||||
int stopline, int noerror));
|
||||
extern int (*query_hook) PARAMS (());
|
||||
|
@ -884,6 +854,8 @@ extern int (*target_wait_hook) PARAMS ((int pid,
|
|||
extern void (*call_command_hook) PARAMS ((struct cmd_list_element *c,
|
||||
char *cmd, int from_tty));
|
||||
|
||||
extern NORETURN void (*error_hook) PARAMS (());
|
||||
|
||||
/* Inhibit window interface if non-zero. */
|
||||
|
||||
extern int use_windows;
|
||||
|
|
247
gdb/gdbtk.c
247
gdb/gdbtk.c
|
@ -31,6 +31,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <setjmp.h>
|
||||
#include "top.h"
|
||||
|
||||
/* Non-zero means that we're doing the gdbtk interface. */
|
||||
int gdbtk = 0;
|
||||
|
@ -53,6 +55,70 @@ null_routine(arg)
|
|||
{
|
||||
}
|
||||
|
||||
static char *saved_output_buf = NULL; /* Start of output buffer */
|
||||
static char *saved_output_data_end = NULL; /* Ptr to nul at end of data */
|
||||
static int saved_output_buf_free = 0; /* Amount of free space in buffer */
|
||||
static char saved_output_static_buf[200]; /* Default buffer */
|
||||
|
||||
static void
|
||||
start_saving_output ()
|
||||
{
|
||||
if (saved_output_buf)
|
||||
abort (); /* Should always be zero at this point */
|
||||
|
||||
saved_output_buf = saved_output_static_buf;
|
||||
saved_output_data_end = saved_output_buf;
|
||||
*saved_output_data_end = '\000';
|
||||
saved_output_buf_free = sizeof saved_output_static_buf - 1;
|
||||
}
|
||||
|
||||
static void
|
||||
save_output (ptr)
|
||||
const char *ptr;
|
||||
{
|
||||
int len;
|
||||
int needed, data_len;
|
||||
|
||||
len = strlen (ptr);
|
||||
|
||||
if (len <= saved_output_buf_free)
|
||||
{
|
||||
strcpy (saved_output_data_end, ptr);
|
||||
saved_output_data_end += len;
|
||||
saved_output_buf_free -= len;
|
||||
return;
|
||||
}
|
||||
|
||||
data_len = saved_output_data_end - saved_output_buf;
|
||||
needed = (data_len + len + 1) * 2;
|
||||
|
||||
if (saved_output_buf == saved_output_static_buf)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
tmp = xmalloc (needed);
|
||||
strcpy (tmp, saved_output_buf);
|
||||
saved_output_buf = tmp;
|
||||
}
|
||||
else
|
||||
saved_output_buf = xrealloc (saved_output_buf, needed);
|
||||
|
||||
saved_output_data_end = saved_output_buf + data_len;
|
||||
saved_output_buf_free = (needed - data_len) - 1;
|
||||
|
||||
save_output (ptr);
|
||||
}
|
||||
|
||||
#define get_saved_output() saved_output_buf
|
||||
|
||||
static void
|
||||
finish_saving_output ()
|
||||
{
|
||||
if (saved_output_buf != saved_output_static_buf)
|
||||
free (saved_output_buf);
|
||||
|
||||
saved_output_buf = NULL;
|
||||
}
|
||||
|
||||
/* This routine redirects the output of fputs_unfiltered so that
|
||||
the user can see what's going on in his debugger window. */
|
||||
|
@ -76,17 +142,37 @@ static void
|
|||
gdbtk_flush (stream)
|
||||
FILE *stream;
|
||||
{
|
||||
if (stream != gdb_stdout || saved_output_buf)
|
||||
return;
|
||||
|
||||
/* Flush output from C to tcl land. */
|
||||
|
||||
flush_holdbuf ();
|
||||
|
||||
/* Force immediate screen update */
|
||||
|
||||
Tcl_VarEval (interp, "gdbtk_tcl_flush", NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdbtk_fputs (ptr)
|
||||
gdbtk_fputs (ptr, stream)
|
||||
const char *ptr;
|
||||
FILE *stream;
|
||||
{
|
||||
int len;
|
||||
|
||||
if (stream != gdb_stdout)
|
||||
{
|
||||
Tcl_VarEval (interp, "gdbtk_tcl_fputs_error ", "{", ptr, "}", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (saved_output_buf)
|
||||
{
|
||||
save_output (ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen (ptr) + 1;
|
||||
|
||||
if (len > holdfree)
|
||||
|
@ -122,43 +208,6 @@ gdbtk_query (args)
|
|||
return val;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char *
|
||||
full_filename(symtab)
|
||||
struct symtab *symtab;
|
||||
{
|
||||
int pathlen;
|
||||
char *filename;
|
||||
|
||||
if (!symtab)
|
||||
return NULL;
|
||||
|
||||
if (symtab->fullname)
|
||||
return savestring(symtab->fullname, strlen(symtab->fullname));
|
||||
|
||||
if (symtab->filename[0] == '/')
|
||||
return savestring(symtab->filename, strlen(symtab->filename));
|
||||
|
||||
if (symtab->dirname)
|
||||
pathlen = strlen(symtab->dirname);
|
||||
else
|
||||
pathlen = 0;
|
||||
if (symtab->filename)
|
||||
pathlen += strlen(symtab->filename);
|
||||
|
||||
filename = xmalloc(pathlen+1);
|
||||
|
||||
if (symtab->dirname)
|
||||
strcpy(filename, symtab->dirname);
|
||||
else
|
||||
*filename = '\000';
|
||||
if (symtab->filename)
|
||||
strcat(filename, symtab->filename);
|
||||
|
||||
return filename;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
breakpoint_notify(b, action)
|
||||
struct breakpoint *b;
|
||||
|
@ -420,22 +469,6 @@ gdb_regnames (clientData, interp, argc, argv)
|
|||
return map_arg_registers (argc, argv, get_register_name, 0);
|
||||
}
|
||||
|
||||
static char reg_value[200];
|
||||
static char *reg_valp = reg_value;
|
||||
|
||||
static void
|
||||
save_reg_value (ptr)
|
||||
const char *ptr;
|
||||
{
|
||||
int len;
|
||||
|
||||
len = strlen (ptr);
|
||||
|
||||
strncpy (reg_valp, ptr, len + 1);
|
||||
|
||||
reg_valp += len;
|
||||
}
|
||||
|
||||
#ifndef REGISTER_CONVERTIBLE
|
||||
#define REGISTER_CONVERTIBLE(x) (0 != 0)
|
||||
#endif
|
||||
|
@ -462,9 +495,7 @@ get_register (regnum, fp)
|
|||
return;
|
||||
}
|
||||
|
||||
fputs_unfiltered_hook = save_reg_value;
|
||||
flush_hook = 0;
|
||||
reg_valp = reg_value;
|
||||
start_saving_output (); /* Start collecting stdout */
|
||||
|
||||
/* Convert raw data to virtual format if necessary. */
|
||||
|
||||
|
@ -479,10 +510,9 @@ get_register (regnum, fp)
|
|||
val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0,
|
||||
gdb_stdout, format, 1, 0, Val_pretty_default);
|
||||
|
||||
fputs_unfiltered_hook = gdbtk_fputs;
|
||||
flush_hook = gdbtk_flush;
|
||||
Tcl_AppendElement (interp, get_saved_output ());
|
||||
|
||||
Tcl_AppendElement (interp, reg_value);
|
||||
finish_saving_output (); /* Set stdout back to normal */
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -552,15 +582,6 @@ gdb_changed_register_list (clientData, interp, argc, argv)
|
|||
return map_arg_registers (argc, argv, register_changed_p, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
gdb_cmd_stub (cmd)
|
||||
char *cmd;
|
||||
{
|
||||
execute_command (cmd, 1);
|
||||
|
||||
return 1; /* Indicate success */
|
||||
}
|
||||
|
||||
/* This implements the TCL command `gdb_cmd', which sends it's argument into
|
||||
the GDB command scanner. */
|
||||
|
||||
|
@ -571,40 +592,72 @@ gdb_cmd (clientData, interp, argc, argv)
|
|||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int val;
|
||||
struct cleanup *old_chain;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
old_chain = make_cleanup (null_routine, 0);
|
||||
|
||||
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);
|
||||
execute_command (argv[1], 1);
|
||||
|
||||
bpstat_do_actions (&stop_bpstat);
|
||||
do_cleanups (old_chain);
|
||||
|
||||
/* Drain all buffered command output */
|
||||
|
||||
gdb_flush (gdb_stderr);
|
||||
gdb_flush (gdb_stdout);
|
||||
|
||||
/* We could base the return value on val, but that would require most users
|
||||
to use catch. Since GDB errors are already being handled elsewhere, I
|
||||
see no reason to pass them up to the caller. */
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/* This routine acts as a top-level for all GDB code called by tcl/Tk. It
|
||||
handles cleanups, and calls to return_to_top_level (usually via error).
|
||||
This is necessary in order to prevent a longjmp out of the bowels of Tk,
|
||||
possibly leaving things in a bad state. Since this routine can be called
|
||||
recursively, it needs to save and restore the contents of the jmp_buf as
|
||||
necessary. */
|
||||
|
||||
static int
|
||||
call_wrapper (clientData, interp, argc, argv)
|
||||
ClientData clientData;
|
||||
Tcl_Interp *interp;
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int val;
|
||||
struct cleanup *saved_cleanup_chain;
|
||||
Tcl_CmdProc *func;
|
||||
jmp_buf saved_error_return;
|
||||
|
||||
func = (Tcl_CmdProc *)clientData;
|
||||
memcpy (saved_error_return, error_return, sizeof (jmp_buf));
|
||||
|
||||
saved_cleanup_chain = save_cleanups ();
|
||||
|
||||
if (!setjmp (error_return))
|
||||
val = func (clientData, interp, argc, argv);
|
||||
else
|
||||
{
|
||||
val = TCL_ERROR; /* Flag an error for TCL */
|
||||
|
||||
finish_saving_output (); /* Restore stdout to normal */
|
||||
|
||||
gdb_flush (gdb_stderr); /* Flush error output */
|
||||
|
||||
/* 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. */
|
||||
|
||||
Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
|
||||
}
|
||||
|
||||
do_cleanups (ALL_CLEANUPS);
|
||||
|
||||
restore_cleanups (saved_cleanup_chain);
|
||||
|
||||
memcpy (error_return, saved_error_return, sizeof (jmp_buf));
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int
|
||||
gdb_listfiles (clientData, interp, argc, argv)
|
||||
ClientData clientData;
|
||||
|
@ -740,16 +793,18 @@ gdbtk_init ()
|
|||
if (Tk_Init(interp) != TCL_OK)
|
||||
error ("Tk_Init failed: %s", interp->result);
|
||||
|
||||
Tcl_CreateCommand (interp, "gdb_cmd", gdb_cmd, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_loc", gdb_loc, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_sourcelines", gdb_sourcelines, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_listfiles", gdb_listfiles, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_stop", gdb_stop, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_regnames", gdb_regnames, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_fetch_registers", gdb_fetch_registers, NULL,
|
||||
Tcl_CreateCommand (interp, "gdb_cmd", call_wrapper, gdb_cmd, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_loc", call_wrapper, gdb_loc, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_sourcelines", call_wrapper, gdb_sourcelines,
|
||||
NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_changed_register_list",
|
||||
gdb_changed_register_list, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_listfiles", call_wrapper, gdb_listfiles,
|
||||
NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_stop", call_wrapper, gdb_stop, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_regnames", call_wrapper, gdb_regnames, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_fetch_registers", call_wrapper,
|
||||
gdb_fetch_registers, NULL);
|
||||
Tcl_CreateCommand (interp, "gdb_changed_register_list", call_wrapper,
|
||||
gdb_changed_register_list, NULL);
|
||||
|
||||
gdbtk_filename = getenv ("GDBTK_FILENAME");
|
||||
if (!gdbtk_filename)
|
||||
|
|
248
gdb/gdbtk.tcl
248
gdb/gdbtk.tcl
|
@ -8,6 +8,8 @@ set screen_top 0
|
|||
set screen_bot 0
|
||||
set current_output_win .cmd.text
|
||||
set cfunc NIL
|
||||
set line_numbers 1
|
||||
|
||||
#option add *Foreground Black
|
||||
#option add *Background White
|
||||
#option add *Font -*-*-medium-r-normal--18-*-*-*-m-*-*-1
|
||||
|
@ -46,6 +48,11 @@ proc gdbtk_tcl_fputs {arg} {
|
|||
$current_output_win yview -pickplace end
|
||||
}
|
||||
|
||||
proc gdbtk_tcl_fputs_error {arg} {
|
||||
.cmd.text insert end "$arg"
|
||||
.cmd.text yview -pickplace end
|
||||
}
|
||||
|
||||
#
|
||||
# GDB Callback:
|
||||
#
|
||||
|
@ -354,43 +361,52 @@ proc delete_breakpoint_tag {win line} {
|
|||
}
|
||||
|
||||
proc gdbtk_tcl_busy {} {
|
||||
.src.start configure -state disabled
|
||||
.src.stop configure -state normal
|
||||
.src.step configure -state disabled
|
||||
.src.next configure -state disabled
|
||||
.src.continue configure -state disabled
|
||||
.src.finish configure -state disabled
|
||||
.src.up configure -state disabled
|
||||
.src.down configure -state disabled
|
||||
.src.bottom configure -state disabled
|
||||
.asm.stepi configure -state disabled
|
||||
.asm.nexti configure -state disabled
|
||||
.asm.continue configure -state disabled
|
||||
.asm.finish configure -state disabled
|
||||
.asm.up configure -state disabled
|
||||
.asm.down configure -state disabled
|
||||
.asm.bottom configure -state disabled
|
||||
.asm.close configure -state disabled
|
||||
if [winfo exists .src] {
|
||||
.src.start configure -state disabled
|
||||
.src.stop configure -state normal
|
||||
.src.step configure -state disabled
|
||||
.src.next configure -state disabled
|
||||
.src.continue configure -state disabled
|
||||
.src.finish configure -state disabled
|
||||
.src.up configure -state disabled
|
||||
.src.down configure -state disabled
|
||||
.src.bottom configure -state disabled
|
||||
}
|
||||
if [winfo exists .asm] {
|
||||
.asm.stepi configure -state disabled
|
||||
.asm.nexti configure -state disabled
|
||||
.asm.continue configure -state disabled
|
||||
.asm.finish configure -state disabled
|
||||
.asm.up configure -state disabled
|
||||
.asm.down configure -state disabled
|
||||
.asm.bottom configure -state disabled
|
||||
.asm.close configure -state disabled
|
||||
}
|
||||
}
|
||||
|
||||
proc gdbtk_tcl_idle {} {
|
||||
.src.start configure -state normal
|
||||
.src.stop configure -state disabled
|
||||
.src.step configure -state normal
|
||||
.src.next configure -state normal
|
||||
.src.continue configure -state normal
|
||||
.src.finish configure -state normal
|
||||
.src.up configure -state normal
|
||||
.src.down configure -state normal
|
||||
.src.bottom configure -state normal
|
||||
.asm.stepi configure -state normal
|
||||
.asm.nexti configure -state normal
|
||||
.asm.continue configure -state normal
|
||||
.asm.finish configure -state normal
|
||||
.asm.up configure -state normal
|
||||
.asm.down configure -state normal
|
||||
.asm.bottom configure -state normal
|
||||
.asm.close configure -state normal
|
||||
if [winfo exists .src] {
|
||||
.src.start configure -state normal
|
||||
.src.stop configure -state disabled
|
||||
.src.step configure -state normal
|
||||
.src.next configure -state normal
|
||||
.src.continue configure -state normal
|
||||
.src.finish configure -state normal
|
||||
.src.up configure -state normal
|
||||
.src.down configure -state normal
|
||||
.src.bottom configure -state normal
|
||||
}
|
||||
|
||||
if [winfo exists .asm] {
|
||||
.asm.stepi configure -state normal
|
||||
.asm.nexti configure -state normal
|
||||
.asm.continue configure -state normal
|
||||
.asm.finish configure -state normal
|
||||
.asm.up configure -state normal
|
||||
.asm.down configure -state normal
|
||||
.asm.bottom configure -state normal
|
||||
.asm.close configure -state normal
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
|
@ -732,6 +748,7 @@ proc display_expression {expression} {
|
|||
proc create_file_win {filename debug_file} {
|
||||
global breakpoint_file
|
||||
global breakpoint_line
|
||||
global line_numbers
|
||||
|
||||
# Replace all the dirty characters in $filename with clean ones, and generate
|
||||
# a unique name for the text widget.
|
||||
|
@ -767,25 +784,32 @@ proc create_file_win {filename debug_file} {
|
|||
bind $win <1> do_nothing
|
||||
bind $win <B1-Motion> do_nothing
|
||||
|
||||
bind $win n {gdb_cmd next ; update_ptr}
|
||||
bind $win s {gdb_cmd step ; update_ptr}
|
||||
bind $win c {gdb_cmd continue ; update_ptr}
|
||||
bind $win f {gdb_cmd finish ; update_ptr}
|
||||
bind $win u {gdb_cmd up ; update_ptr}
|
||||
bind $win d {gdb_cmd down ; update_ptr}
|
||||
bind $win n {catch {gdb_cmd next} ; update_ptr}
|
||||
bind $win s {catch {gdb_cmd step} ; update_ptr}
|
||||
bind $win c {catch {gdb_cmd continue} ; update_ptr}
|
||||
bind $win f {catch {gdb_cmd finish} ; update_ptr}
|
||||
bind $win u {catch {gdb_cmd up} ; update_ptr}
|
||||
bind $win d {catch {gdb_cmd down} ; update_ptr}
|
||||
|
||||
$win delete 0.0 end
|
||||
$win insert 0.0 [read $fh]
|
||||
close $fh
|
||||
|
||||
# Add margins (for annotations) and a line number to each line
|
||||
# Add margins (for annotations) and a line number to each line (if requested)
|
||||
|
||||
set numlines [$win index end]
|
||||
set numlines [lindex [split $numlines .] 0]
|
||||
for {set i 1} {$i <= $numlines} {incr i} {
|
||||
$win insert $i.0 [format " %4d " $i]
|
||||
$win tag add source $i.8 "$i.0 lineend"
|
||||
}
|
||||
if $line_numbers {
|
||||
for {set i 1} {$i <= $numlines} {incr i} {
|
||||
$win insert $i.0 [format " %4d " $i]
|
||||
$win tag add source $i.8 "$i.0 lineend"
|
||||
}
|
||||
} else {
|
||||
for {set i 1} {$i <= $numlines} {incr i} {
|
||||
$win insert $i.0 " "
|
||||
$win tag add source $i.8 "$i.0 lineend"
|
||||
}
|
||||
}
|
||||
|
||||
# Add the breakdots
|
||||
|
||||
|
@ -873,12 +897,12 @@ proc create_asm_win {funcname pc} {
|
|||
bind $win <Enter> {focus %W}
|
||||
bind $win <1> {asm_window_button_1 %W %X %Y %x %y}
|
||||
bind $win <B1-Motion> do_nothing
|
||||
bind $win n {gdb_cmd nexti ; update_ptr}
|
||||
bind $win s {gdb_cmd stepi ; update_ptr}
|
||||
bind $win c {gdb_cmd continue ; update_ptr}
|
||||
bind $win f {gdb_cmd finish ; update_ptr}
|
||||
bind $win u {gdb_cmd up ; update_ptr}
|
||||
bind $win d {gdb_cmd down ; update_ptr}
|
||||
bind $win n {catch {gdb_cmd nexti} ; update_ptr}
|
||||
bind $win s {catch {gdb_cmd stepi} ; update_ptr}
|
||||
bind $win c {catch {gdb_cmd continue} ; update_ptr}
|
||||
bind $win f {catch {gdb_cmd finish} ; update_ptr}
|
||||
bind $win u {catch {gdb_cmd up} ; update_ptr}
|
||||
bind $win d {catch {gdb_cmd down} ; update_ptr}
|
||||
|
||||
# Disassemble the code, and read it into the new text widget
|
||||
|
||||
|
@ -1090,23 +1114,23 @@ proc create_asm_window {} {
|
|||
frame .asm.row2
|
||||
|
||||
button .asm.stepi -width 6 -text Stepi \
|
||||
-command {gdb_cmd stepi ; update_ptr}
|
||||
-command {catch {gdb_cmd stepi} ; update_ptr}
|
||||
button .asm.nexti -width 6 -text Nexti \
|
||||
-command {gdb_cmd nexti ; update_ptr}
|
||||
-command {catch {gdb_cmd nexti} ; update_ptr}
|
||||
button .asm.continue -width 6 -text Cont \
|
||||
-command {gdb_cmd continue ; update_ptr}
|
||||
-command {catch {gdb_cmd continue} ; update_ptr}
|
||||
button .asm.finish -width 6 -text Finish \
|
||||
-command {gdb_cmd finish ; update_ptr}
|
||||
button .asm.up -width 6 -text Up -command {gdb_cmd up ; update_ptr}
|
||||
-command {catch {gdb_cmd finish} ; update_ptr}
|
||||
button .asm.up -width 6 -text Up -command {catch {gdb_cmd up} ; update_ptr}
|
||||
button .asm.down -width 6 -text Down \
|
||||
-command {gdb_cmd down ; update_ptr}
|
||||
-command {catch {gdb_cmd down} ; update_ptr}
|
||||
button .asm.bottom -width 6 -text Bottom \
|
||||
-command {gdb_cmd {frame 0} ; update_ptr}
|
||||
-command {catch {gdb_cmd {frame 0}} ; update_ptr}
|
||||
|
||||
pack .asm.stepi .asm.continue .asm.up .asm.bottom -side left -padx 3 -pady 5 -in .asm.row1
|
||||
pack .asm.nexti .asm.finish .asm.down -side left -padx 3 -pady 5 -in .asm.row2
|
||||
|
||||
pack .asm.row1 .asm.row2 -side top -anchor w
|
||||
pack .asm.row2 .asm.row1 -side bottom -anchor w -before .asm.info
|
||||
|
||||
update
|
||||
|
||||
|
@ -1127,9 +1151,23 @@ proc reg_config_menu {} {
|
|||
set regnames [gdb_regnames]
|
||||
set num_regs [llength $regnames]
|
||||
|
||||
button .reg.config.done -text Done -command {destroy .reg.config}
|
||||
frame .reg.config.buts
|
||||
|
||||
pack .reg.config.done -side bottom -fill x
|
||||
button .reg.config.done -text " Done " -command "
|
||||
recompute_reg_display_list $num_regs
|
||||
populate_reg_window
|
||||
update_registers all
|
||||
destroy .reg.config "
|
||||
|
||||
button .reg.config.update -text Update -command "
|
||||
recompute_reg_display_list $num_regs
|
||||
populate_reg_window
|
||||
update_registers all "
|
||||
|
||||
pack .reg.config.buts -side bottom -fill x
|
||||
|
||||
pack .reg.config.done -side left -fill x -expand yes -in .reg.config.buts
|
||||
pack .reg.config.update -side right -fill x -expand yes -in .reg.config.buts
|
||||
|
||||
# Since there can be lots of registers, we build the window with no more than
|
||||
# 32 rows, and as many columns as needed.
|
||||
|
@ -1151,10 +1189,7 @@ proc reg_config_menu {} {
|
|||
for {set regnum 0} {$regnum < $num_regs} {incr regnum} {
|
||||
set regname [lindex $regnames $regnum]
|
||||
checkbutton .reg.config.col$col.$row -text $regname -pady 0 \
|
||||
-variable regena($regnum) -relief flat -anchor w -bd 1 \
|
||||
-command "recompute_reg_display_list $num_regs
|
||||
populate_reg_window
|
||||
update_registers all"
|
||||
-variable regena($regnum) -relief flat -anchor w -bd 1
|
||||
|
||||
pack .reg.config.col$col.$row -side top -fill both
|
||||
|
||||
|
@ -1199,44 +1234,38 @@ proc create_registers_window {} {
|
|||
|
||||
build_framework .reg Registers
|
||||
|
||||
.reg.menubar.view.menu add command -label Natural
|
||||
.reg.menubar.view.menu add command -label Config -command {
|
||||
reg_config_menu }
|
||||
# First, delete all the old menu entries
|
||||
|
||||
.reg.menubar.view.menu delete 0 last
|
||||
|
||||
# Hex menu item
|
||||
.reg.menubar.view.menu entryconfigure 0 -command {
|
||||
global reg_format
|
||||
.reg.menubar.view.menu add radiobutton -variable reg_format \
|
||||
-label Hex -value x -command {update_registers all}
|
||||
|
||||
set reg_format x
|
||||
update_registers all
|
||||
}
|
||||
# Decimal menu item
|
||||
.reg.menubar.view.menu entryconfigure 1 -command {
|
||||
global reg_format
|
||||
.reg.menubar.view.menu add radiobutton -variable reg_format \
|
||||
-label Decimal -value d -command {update_registers all}
|
||||
|
||||
set reg_format d
|
||||
update_registers all
|
||||
}
|
||||
# Octal menu item
|
||||
.reg.menubar.view.menu entryconfigure 2 -command {
|
||||
global reg_format
|
||||
.reg.menubar.view.menu add radiobutton -variable reg_format \
|
||||
-label Octal -value o -command {update_registers all}
|
||||
|
||||
set reg_format o
|
||||
update_registers all
|
||||
}
|
||||
# Natural menu item
|
||||
.reg.menubar.view.menu entryconfigure 3 -command {
|
||||
global reg_format
|
||||
.reg.menubar.view.menu add radiobutton -variable reg_format \
|
||||
-label Natural -value {} -command {update_registers all}
|
||||
|
||||
set reg_format {}
|
||||
update_registers all
|
||||
}
|
||||
# Config menu item
|
||||
.reg.menubar.view.menu add separator
|
||||
|
||||
.reg.menubar.view.menu add command -label Config -command {
|
||||
reg_config_menu }
|
||||
|
||||
destroy .reg.label
|
||||
|
||||
# Install the reg names
|
||||
|
||||
populate_reg_window
|
||||
update_registers all
|
||||
}
|
||||
|
||||
# Convert regena into a list of the enabled $regnums
|
||||
|
@ -1534,7 +1563,7 @@ proc build_framework {win {title GDBtk} {label {}}} {
|
|||
${win}.menubar.file.menu add command -label Close \
|
||||
-command "destroy ${win}"
|
||||
${win}.menubar.file.menu add command -label Quit \
|
||||
-command {gdb_cmd quit}
|
||||
-command {catch {gdb_cmd quit}}
|
||||
|
||||
menubutton ${win}.menubar.view -padx 12 -text View \
|
||||
-menu ${win}.menubar.view.menu -underline 0
|
||||
|
@ -1598,36 +1627,53 @@ proc create_source_window {} {
|
|||
|
||||
build_framework .src Source "*No file*"
|
||||
|
||||
# First, delete all the old view menu entries
|
||||
|
||||
.src.menubar.view.menu delete 0 last
|
||||
|
||||
# Line numbers enable/disable menu item
|
||||
.src.menubar.view.menu add checkbutton -variable line_numbers \
|
||||
-label "Line numbers" -onvalue 1 -offvalue 0 -command {
|
||||
foreach source [array names wins] {
|
||||
if {$source == "Blank"} continue
|
||||
destroy $wins($source)
|
||||
unset wins($source)
|
||||
}
|
||||
set cfile Blank
|
||||
update_listing [gdb_loc]
|
||||
}
|
||||
|
||||
frame .src.row1
|
||||
frame .src.row2
|
||||
|
||||
button .src.start -width 6 -text Start -command \
|
||||
{gdb_cmd {break main}
|
||||
gdb_cmd {enable delete $bpnum}
|
||||
gdb_cmd run
|
||||
{catch {gdb_cmd {break main}}
|
||||
catch {gdb_cmd {enable delete $bpnum}}
|
||||
catch {gdb_cmd run}
|
||||
update_ptr }
|
||||
button .src.stop -width 6 -text Stop -fg red -activeforeground red \
|
||||
-state disabled -command gdb_stop
|
||||
button .src.step -width 6 -text Step \
|
||||
-command {gdb_cmd step ; update_ptr}
|
||||
-command {catch {gdb_cmd step} ; update_ptr}
|
||||
button .src.next -width 6 -text Next \
|
||||
-command {gdb_cmd next ; update_ptr}
|
||||
-command {catch {gdb_cmd next} ; update_ptr}
|
||||
button .src.continue -width 6 -text Cont \
|
||||
-command {gdb_cmd continue ; update_ptr}
|
||||
-command {catch {gdb_cmd continue} ; update_ptr}
|
||||
button .src.finish -width 6 -text Finish \
|
||||
-command {gdb_cmd finish ; update_ptr}
|
||||
button .src.up -width 6 -text Up -command {gdb_cmd up ; update_ptr}
|
||||
-command {catch {gdb_cmd finish} ; update_ptr}
|
||||
button .src.up -width 6 -text Up \
|
||||
-command {catch {gdb_cmd up} ; update_ptr}
|
||||
button .src.down -width 6 -text Down \
|
||||
-command {gdb_cmd down ; update_ptr}
|
||||
-command {catch {gdb_cmd down} ; update_ptr}
|
||||
button .src.bottom -width 6 -text Bottom \
|
||||
-command {gdb_cmd {frame 0} ; update_ptr}
|
||||
-command {catch {gdb_cmd {frame 0}} ; update_ptr}
|
||||
|
||||
pack .src.start .src.step .src.continue .src.up .src.bottom \
|
||||
-side left -padx 3 -pady 5 -in .src.row1
|
||||
pack .src.stop .src.next .src.finish .src.down -side left -padx 3 \
|
||||
-pady 5 -in .src.row2
|
||||
|
||||
pack .src.row1 .src.row2 -side top -anchor w
|
||||
pack .src.row2 .src.row1 -side bottom -anchor w -before .src.info
|
||||
|
||||
$wins($cfile) insert 0.0 " This page intentionally left blank."
|
||||
$wins($cfile) configure -width 88 -state disabled \
|
||||
|
@ -1667,7 +1713,7 @@ proc create_command_window {} {
|
|||
|
||||
%W insert end \n
|
||||
%W yview -pickplace end
|
||||
gdb_cmd $command_line
|
||||
catch "gdb_cmd {$command_line}"
|
||||
set command_line {}
|
||||
update_ptr
|
||||
%W insert end "(gdb) "
|
||||
|
|
51
gdb/main.c
51
gdb/main.c
|
@ -41,6 +41,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#endif
|
||||
|
||||
/* Temporary variable for SET_TOP_LEVEL. */
|
||||
|
||||
static int top_level_val;
|
||||
|
||||
/* Do a setjmp on error_return and quit_return. catch_errors is
|
||||
|
@ -52,6 +53,14 @@ static int top_level_val;
|
|||
? (PTR) 0 : (PTR) memcpy (quit_return, error_return, sizeof (jmp_buf))) \
|
||||
, top_level_val)
|
||||
|
||||
/* If nonzero, display time usage both at startup and for each command. */
|
||||
|
||||
int display_time;
|
||||
|
||||
/* If nonzero, display space usage both at startup and for each command. */
|
||||
|
||||
int display_space;
|
||||
|
||||
extern void gdb_init PARAMS ((void));
|
||||
|
||||
int
|
||||
|
@ -93,6 +102,8 @@ main (argc, argv)
|
|||
|
||||
register int i;
|
||||
|
||||
long time_at_startup = get_run_time ();
|
||||
|
||||
/* start-sanitize-mpw */
|
||||
#ifdef MPW
|
||||
/* Drop into MacsBug, but only if the executable is specially named. */
|
||||
|
@ -174,13 +185,16 @@ main (argc, argv)
|
|||
{"tty", required_argument, 0, 't'},
|
||||
{"baud", required_argument, 0, 'b'},
|
||||
{"b", required_argument, 0, 'b'},
|
||||
{"nw", no_argument, &no_windows, 1},
|
||||
{"nowindows", no_argument, &no_windows, 1},
|
||||
{"nw", no_argument, &use_windows, 0},
|
||||
{"nowindows", no_argument, &use_windows, 0},
|
||||
{"w", no_argument, &use_windows, 1},
|
||||
{"windows", no_argument, &use_windows, 1},
|
||||
{"statistics", no_argument, 0, 13},
|
||||
/* Allow machine descriptions to add more options... */
|
||||
#ifdef ADDITIONAL_OPTIONS
|
||||
ADDITIONAL_OPTIONS
|
||||
#endif
|
||||
{0, no_argument, 0, 0},
|
||||
{0, no_argument, 0, 0}
|
||||
};
|
||||
|
||||
while (1)
|
||||
|
@ -212,6 +226,11 @@ main (argc, argv)
|
|||
/* FIXME: what if the syntax is wrong (e.g. not digits)? */
|
||||
annotation_level = atoi (optarg);
|
||||
break;
|
||||
case 13:
|
||||
/* Enable the display of both time and space usage. */
|
||||
display_time = 1;
|
||||
display_space = 1;
|
||||
break;
|
||||
case 'f':
|
||||
annotation_level = 1;
|
||||
break;
|
||||
|
@ -522,6 +541,25 @@ GDB manual (available as on-line info or a printed manual).\n", gdb_stdout);
|
|||
BEFORE_MAIN_LOOP_HOOK;
|
||||
#endif
|
||||
|
||||
/* Show time and/or space usage. */
|
||||
|
||||
if (display_time)
|
||||
{
|
||||
long init_time = get_run_time () - time_at_startup;
|
||||
|
||||
printf_unfiltered ("Startup time: %ld.%06ld\n",
|
||||
init_time / 1000000, init_time % 1000000);
|
||||
}
|
||||
|
||||
if (display_space)
|
||||
{
|
||||
extern char **environ;
|
||||
char *lim = (char *) sbrk (0);
|
||||
|
||||
printf_unfiltered ("Startup size: data size %ld\n",
|
||||
(long) (lim - (char *) &environ));
|
||||
}
|
||||
|
||||
/* The command loop. */
|
||||
|
||||
while (1)
|
||||
|
@ -570,7 +608,12 @@ fputs_unfiltered (linebuffer, stream)
|
|||
{
|
||||
if (fputs_unfiltered_hook)
|
||||
{
|
||||
fputs_unfiltered_hook (linebuffer);
|
||||
/* FIXME: I think we should only be doing this for stdout or stderr.
|
||||
Either that or we should be passing stream to the hook so it can
|
||||
deal with it. If that is cleaned up, this function can go back
|
||||
into utils.c and the fputs_unfiltered_hook can replace the current
|
||||
ability to avoid this function by not linking with main.c. */
|
||||
fputs_unfiltered_hook (linebuffer, stream);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -354,7 +354,7 @@ void (*command_loop_hook) PARAMS ((void));
|
|||
|
||||
/* Called instead of fputs for all output. */
|
||||
|
||||
void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer));
|
||||
void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, FILE *stream));
|
||||
|
||||
/* Called from print_frame_info to list the line we stopped in. */
|
||||
|
||||
|
@ -391,6 +391,12 @@ int (*target_wait_hook) PARAMS ((int pid, struct target_waitstatus *status));
|
|||
|
||||
void (*call_command_hook) PARAMS ((struct cmd_list_element *c, char *cmd,
|
||||
int from_tty));
|
||||
|
||||
/* Takes control from error (). Typically used to prevent longjmps out of the
|
||||
middle of the GUI. Usually used in conjunction with a catch routine. */
|
||||
|
||||
NORETURN void (*error_hook) PARAMS (());
|
||||
|
||||
|
||||
/* Where to go for return_to_top_level (RETURN_ERROR). */
|
||||
jmp_buf error_return;
|
||||
|
|
Loading…
Reference in New Issue