From: Stu Grossman Date: Thu, 28 Jul 1994 22:07:02 +0000 (+0000) Subject: * Makefile.in (INSTALLED_LIBS, CLIBS, DEPFILES): Add support for X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=754e5da26e5fb9374d6768188944fbca8d49d37c;p=binutils-gdb.git * Makefile.in (INSTALLED_LIBS, CLIBS, DEPFILES): Add support for --enable-xxx configure option by adding ENABLE_{CLIBS DEPFILES} where appropriate. * General hackery to support alternate user-interface. * breakpoint.c (mention, delete_breakpoint, enable_breakpoint, disable_breakpoint): Call hooks for alternate user-interface. * defs.h: Add declarations for alternate user-interface hooks. * main.c (main): Add --nw (and --nowindows) options to disable the GUI. * (near call to command_loop): Call command_loop_hook if set. * (fputs_unfiltered): Call fputs_unfiltered_hook if set. * stack.c: Call print_frame_info_listing_hook if set. * top.c (gdb_init): Initialize targets.c and utils.c prior to other files to make sure that calls to error and warning will work. Call init_ui_hook after everything else. * utils.c (query): Call query_hook if set. * (gdb_flush): Call flush_hook if set. * Change _initialize_utils to initialize_utils cuz we don't use automatic initialization of utils.c anymore. * Support for TK GUI. * Makefile.in: Add rule for gdbtk.o. * configure.in: Add support for --enable-gdbtk. * gdbtk.c: New file. Contains support routines for TK interface. * gdbtk.tcl: New file. Implements GUI policy. * remote.c: Get rid of #ifdef DONT_USE_REMOTE. It's no longer necessary. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1c78a09a9a5..07455cb2de0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,35 @@ +Thu Jul 28 14:37:36 1994 Stu Grossman (grossman@cygnus.com) + + * Makefile.in (INSTALLED_LIBS, CLIBS, DEPFILES): Add support for + --enable-xxx configure option by adding ENABLE_{CLIBS DEPFILES} + where appropriate. + + * General hackery to support alternate user-interface. + * breakpoint.c (mention, delete_breakpoint, enable_breakpoint, + disable_breakpoint): Call hooks for alternate user-interface. + * defs.h: Add declarations for alternate user-interface hooks. + * main.c (main): Add --nw (and --nowindows) options to disable + the GUI. + * (near call to command_loop): Call command_loop_hook if set. + * (fputs_unfiltered): Call fputs_unfiltered_hook if set. + * stack.c: Call print_frame_info_listing_hook if set. + * top.c (gdb_init): Initialize targets.c and utils.c prior to + other files to make sure that calls to error and warning will + work. Call init_ui_hook after everything else. + * utils.c (query): Call query_hook if set. + * (gdb_flush): Call flush_hook if set. + * Change _initialize_utils to initialize_utils cuz we don't use + automatic initialization of utils.c anymore. + + * Support for TK GUI. + * Makefile.in: Add rule for gdbtk.o. + * configure.in: Add support for --enable-gdbtk. + * gdbtk.c: New file. Contains support routines for TK interface. + * gdbtk.tcl: New file. Implements GUI policy. + + * remote.c: Get rid of #ifdef DONT_USE_REMOTE. It's no longer + necessary. + Thu Jul 28 14:52:01 1994 J.T. Conklin (jtc@phishhead.cygnus.com) * Makefile.in (CC_FOR_TARGET, CXX_FOR_TARGET): Use newlib if it is diff --git a/gdb/Makefile.in b/gdb/Makefile.in index ca2c5008b77..cfbbd188247 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -169,9 +169,10 @@ REGEX1 = regex.o # If you have the Cygnus libraries installed, # you can use 'CLIBS=$(INSTALLED_LIBS)' 'CDEPS=' INSTALLED_LIBS=-lbfd -lreadline $(TERMCAP) -lopcodes -lmmalloc \ - -liberty $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) + -liberty $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(ENABLE_CLIBS) CLIBS = $(BFD) $(READLINE) $(OPCODES) $(MMALLOC) \ - $(LIBIBERTY) $(TERMCAP) $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) + $(LIBIBERTY) $(TERMCAP) $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) \ + $(ENABLE_CLIBS) CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) \ $(BFD) $(READLINE) $(OPCODES) $(MMALLOC) $(LIBIBERTY) @@ -454,7 +455,8 @@ TARDIRS = doc gdbserver sparclite # variables analogous to SER_HARDWIRE which get defaulted in this # Makefile.in -DEPFILES = $(TDEPFILES) $(XDEPFILES) $(SER_HARDWIRE) $(NATDEPFILES) $(REMOTE_O) +DEPFILES = $(TDEPFILES) $(XDEPFILES) $(SER_HARDWIRE) $(NATDEPFILES) $(REMOTE_O) \ + $(ENABLE_DEPFILES) SOURCES = $(SFILES) $(ALLDEPFILES) $(YYFILES) # Don't include YYFILES (*.tab.c) because we already include *.y in SFILES, @@ -1204,6 +1206,11 @@ findvar.o: findvar.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h fork-child.o: fork-child.c $(wait_h) $(defs_h) $(gdbcore_h) \ $(inferior_h) target.h terminal.h thread.h +gdbtk.o: gdbtk.c $(defs_h) $(symtab_h) $(inferior_h) $(command_h) \ + $(bfd_h) symfile.h objfiles.h target.h + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/gdbtk.c \ + -DGDBTK_FILENAME=\"$(libdir)/gdbtk.tcl\" + gdbtypes.o: gdbtypes.c $(bfd_h) complaints.h $(defs_h) $(expression_h) \ $(gdbtypes_h) language.h objfiles.h symfile.h $(symtab_h) target.h \ $(value_h) diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index acdeff2798e..a23afd442f2 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -2149,6 +2149,9 @@ mention (b) { int say_where = 0; + if (create_breakpoint_hook) + create_breakpoint_hook (b); + switch (b->type) { case bp_watchpoint: @@ -3181,6 +3184,9 @@ delete_breakpoint (bpt) register struct breakpoint *b; register bpstat bs; + if (delete_breakpoint_hook) + delete_breakpoint_hook (bpt); + if (bpt->inserted) remove_breakpoint (bpt); @@ -3539,6 +3545,9 @@ enable_breakpoint (bpt) int target_resources_ok, other_type_used; struct value *mark; + if (enable_breakpoint_hook) + enable_breakpoint_hook (bpt); + if (bpt->type == bp_hardware_breakpoint) { int i; @@ -3644,6 +3653,9 @@ disable_breakpoint (bpt) if (bpt->type == bp_watchpoint_scope) return; + if (disable_breakpoint_hook) + disable_breakpoint_hook (bpt); + bpt->enable = disabled; breakpoints_changed (); diff --git a/gdb/configure.in b/gdb/configure.in index f52ce11952e..c8e77752d4c 100644 --- a/gdb/configure.in +++ b/gdb/configure.in @@ -397,6 +397,12 @@ else links="${links} nm.h" fi +# Make it possible to use the GUI without doing a full install +if [ "${enable_gdbtk}" = "yes" ] ; then + files="${files} gdbtk.tcl" + links="${links} gdbtk.tcl" +fi + # post-target: case ${srcdir} in @@ -413,6 +419,15 @@ if [ "${nativefile}" = "" ] ; then mv -f Makefile.tem Makefile fi +if [ "${enable_gdbtk}" = "yes" ] ; then + sed -e '/# End of host and/i\ +\ +ENABLE_DEPFILES = gdbtk.o\ +ENABLE_CLIBS = -ltcl -ltk -lX11 -lm +' < Makefile > Makefile.tem + mv -f Makefile.tem Makefile +fi + sed -e '/^TM_FILE[ ]*=/s,^TM_FILE[ ]*=[ ]*,&config/'"${gdb_target_cpu}"'/, /^XM_FILE[ ]*=/s,^XM_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/, /^NAT_FILE[ ]*=/s,^NAT_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,' Makefile.tmp diff --git a/gdb/defs.h b/gdb/defs.h index 4b7b0c379e6..6bbf019cff2 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -92,7 +92,8 @@ enum language language_c, /* C */ language_cplus, /* C++ */ language_chill, /* Chill */ - language_m2 /* Modula-2 */ + language_m2, /* Modula-2 */ + language_asm /* Assembly language */ }; /* the cleanup list records things that have to be undone @@ -342,9 +343,6 @@ command_line_input PARAMS ((char *, int, char *)); extern void print_prompt PARAMS ((void)); -extern int -batch_mode PARAMS ((void)); - extern int input_from_terminal_p PARAMS ((void)); @@ -357,7 +355,7 @@ extern void print_address_symbolic PARAMS ((CORE_ADDR, GDB_FILE *, int, char *)); extern void -print_address_numeric PARAMS ((CORE_ADDR, GDB_FILE *)); +print_address_numeric PARAMS ((CORE_ADDR, int, GDB_FILE *)); extern void print_address PARAMS ((CORE_ADDR, GDB_FILE *)); @@ -941,4 +939,27 @@ push_word PARAMS ((CORE_ADDR, unsigned LONGEST)); #define MAINTENANCE_CMDS 1 #endif +/* Hooks for alternate command interfaces. */ + +#ifdef __STDC__ +struct symtab; +struct breakpoint; +#endif + +void (*init_ui_hook) PARAMS ((void)); +void (*command_loop_hook) PARAMS ((void)); +void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer)); +void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s, int line, + int stopline, int noerror)); +int (*query_hook) PARAMS (()); +void (*flush_hook) PARAMS ((FILE *stream)); +void (*create_breakpoint_hook) PARAMS ((struct breakpoint *b)); +void (*delete_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); +void (*enable_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); +void (*disable_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); + +/* Inhibit window interface if non-zero. */ + +extern int no_windows; + #endif /* !defined (DEFS_H) */ diff --git a/gdb/gdbtk.c b/gdb/gdbtk.c new file mode 100644 index 00000000000..4746f2a9bc1 --- /dev/null +++ b/gdb/gdbtk.c @@ -0,0 +1,424 @@ +/* TK interface routines. + Copyright 1994 Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "symtab.h" +#include "inferior.h" +#include "command.h" +#include "bfd.h" +#include "symfile.h" +#include "objfiles.h" +#include "target.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Non-zero means that we're doing the gdbtk interface. */ +int gdbtk = 0; + +/* Non-zero means we are reloading breakpoints, etc from the + Gdbtk kernel, and we should suppress various messages */ +static int gdbtk_reloading = 0; + +/* Handle for TCL interpreter */ +static Tcl_Interp *interp = NULL; + +/* Handle for TK main window */ +static Tk_Window mainWindow = NULL; + +static void +null_routine(arg) + int arg; +{ +} + + +/* This routine redirects the output of fputs_unfiltered so that + the user can see what's going on in his debugger window. */ + +static void +gdbtk_fputs (ptr) + const char *ptr; +{ + Tcl_VarEval (interp, "gdbtk_tcl_fputs ", "{", ptr, "}", NULL); +} + +static void +gdbtk_flush (stream) + FILE *stream; +{ + Tcl_VarEval (interp, "gdbtk_tcl_flush", NULL); +} + +static int +gdbtk_query (args) + va_list args; +{ + char *query; + char buf[200]; + long val; + + query = va_arg (args, char *); + + vsprintf(buf, query, args); + Tcl_VarEval (interp, "gdbtk_tcl_query ", "{", buf, "}", NULL); + + val = atol (interp->result); + return val; +} + +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; +} + +static void +breakpoint_notify(b, action) + struct breakpoint *b; + const char *action; +{ + struct symbol *sym; + char bpnum[50], line[50]; + struct symtab_and_line sal; + char *filename; + int v; + + if (b->type != bp_breakpoint) + return; + + sal = find_pc_line (b->address, 0); + + filename = full_filename (sal.symtab); + + sprintf (bpnum, "%d", b->number); + sprintf (line, "%d", sal.line); + + v = Tcl_VarEval (interp, + "gdbtk_tcl_breakpoint ", + action, + " ", bpnum, + " ", filename, + " ", line, + NULL); + + if (v != TCL_OK) + { + gdbtk_fputs (interp->result); + gdbtk_fputs ("\n"); + } + + if (filename) + free (filename); +} + +static void +gdbtk_create_breakpoint(b) + struct breakpoint *b; +{ + breakpoint_notify(b, "create"); +} + +static void +gdbtk_delete_breakpoint(b) + struct breakpoint *b; +{ + breakpoint_notify(b, "delete"); +} + +static void +gdbtk_enable_breakpoint(b) + struct breakpoint *b; +{ + breakpoint_notify(b, "enable"); +} + +static void +gdbtk_disable_breakpoint(b) + struct breakpoint *b; +{ + breakpoint_notify(b, "disable"); +} + +/* This implements the TCL command `gdb_loc', which returns a list consisting + of the source and line number associated with the current pc. */ + +static int +gdb_loc (clientData, interp, argc, argv) + ClientData clientData; + Tcl_Interp *interp; + int argc; + char *argv[]; +{ + char *filename; + char buf[100]; + struct symtab_and_line sal; + char *funcname; + + if (argc == 1) + { + struct frame_info *frame; + struct symbol *func; + CORE_ADDR pc; + + frame = get_frame_info (selected_frame); + pc = frame ? frame->pc : stop_pc; + func = find_pc_function (pc); + funcname = func ? SYMBOL_NAME (func) : ""; + sal = find_pc_line (pc, 0); + } + else if (argc == 2) + { + struct cleanup *old_chain; + struct symtabs_and_lines sals; + + sals = decode_line_spec (argv[1], 1); + + if (sals.nelts != 1) + { + Tcl_SetResult (interp, "Ambiguous line spec", TCL_STATIC); + free (sals.sals); + return TCL_ERROR; + } + + sal = sals.sals[0]; + free (sals.sals); + funcname = "*"; + } + else + { + Tcl_SetResult (interp, "wrong # args", TCL_STATIC); + return TCL_ERROR; + } + + filename = full_filename (sal.symtab); + + sprintf (buf, "%d", sal.line); + + if (sal.symtab) + Tcl_AppendElement (interp, sal.symtab->filename); + else + Tcl_AppendElement (interp, ""); + Tcl_AppendElement (interp, funcname); + Tcl_AppendElement (interp, filename); + Tcl_AppendElement (interp, buf); /* line number */ + + if (filename) + free(filename); + + return TCL_OK; +} + +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. */ + +static int +gdb_cmd (clientData, interp, argc, argv) + ClientData clientData; + Tcl_Interp *interp; + 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); + + bpstat_do_actions (&stop_bpstat); + do_cleanups (old_chain); + + /* 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; +} + +static int +gdb_listfiles (clientData, interp, argc, argv) + ClientData clientData; + Tcl_Interp *interp; + int argc; + char *argv[]; +{ + int val; + struct objfile *objfile; + struct partial_symtab *psymtab; + + ALL_PSYMTABS (objfile, psymtab) + Tcl_AppendElement (interp, psymtab->filename); + + return TCL_OK; +} + +static void +tk_command (cmd, from_tty) + char *cmd; + int from_tty; +{ + Tcl_VarEval (interp, cmd, NULL); + + gdbtk_fputs (interp->result); + gdbtk_fputs ("\n"); +} + +static void +cleanup_init (ignored) + int ignored; +{ + if (mainWindow != NULL) + Tk_DestroyWindow (mainWindow); + mainWindow = NULL; + + if (interp != NULL) + Tcl_DeleteInterp (interp); + interp = NULL; +} + +static void +gdbtk_init () +{ + struct cleanup *old_chain; + char *gdbtk_filename; + + old_chain = make_cleanup (cleanup_init, 0); + + /* First init tcl and tk. */ + + interp = Tcl_CreateInterp (); + + if (!interp) + error ("Tcl_CreateInterp failed"); + + mainWindow = Tk_CreateMainWindow (interp, NULL, "gdb", "Gdb"); + + if (!mainWindow) + return; /* DISPLAY probably not set */ + + if (Tcl_Init(interp) != TCL_OK) + error ("Tcl_Init failed: %s", interp->result); + + 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_listfiles", gdb_listfiles, NULL, NULL); + + gdbtk_filename = getenv ("GDBTK_FILENAME"); + if (gdbtk_filename) + { + if (Tcl_EvalFile (interp, gdbtk_filename) != TCL_OK) + error ("Failure reading %s: %s", gdbtk_filename, interp->result); + } + else + { + if (Tcl_EvalFile (interp, "gdbtk.tcl") != TCL_OK) + { + Tcl_ResetResult (interp); + if (Tcl_EvalFile (interp, GDBTK_FILENAME) != TCL_OK) + error ("Failure reading %s: %s", GDBTK_FILENAME, interp->result); + } + } + + command_loop_hook = Tk_MainLoop; + fputs_unfiltered_hook = gdbtk_fputs; + print_frame_info_listing_hook = null_routine; + query_hook = gdbtk_query; + flush_hook = gdbtk_flush; + create_breakpoint_hook = gdbtk_create_breakpoint; + delete_breakpoint_hook = gdbtk_delete_breakpoint; + enable_breakpoint_hook = gdbtk_enable_breakpoint; + disable_breakpoint_hook = gdbtk_disable_breakpoint; + + discard_cleanups (old_chain); + + add_com ("tk", class_obscure, tk_command, + "Send a command directly into tk."); +} + +/* Come here during initialze_all_files () */ + +void +_initialize_gdbtk () +{ + if (no_windows) + return; + + /* Tell the rest of the world that Gdbtk is now set up. */ + + init_ui_hook = gdbtk_init; +} diff --git a/gdb/gdbtk.tcl b/gdb/gdbtk.tcl new file mode 100644 index 00000000000..425041e87e6 --- /dev/null +++ b/gdb/gdbtk.tcl @@ -0,0 +1,399 @@ +# GDB GUI setup + +set cfile Blank +set wins($cfile) .text +set current_label {} +set screen_height 0 +set screen_top 0 +set screen_bot 0 + +proc test {} { + update_listing {termcap.c foo /etc/termcap 200} +} + +proc echo string {puts stdout $string} + +proc gdbtk_tcl_fputs {arg} { + .command.text insert end "$arg" + .command.text yview -pickplace end +} + +proc gdbtk_tcl_flush {} {update idletasks} + +proc gdbtk_tcl_query {message} { + tk_dialog .query "gdb : query" "$message" {} 1 "No" "Yes" + } + +if [info exists env(EDITOR)] then { + set editor $env(EDITOR) + } else { + set editor emacs +} + +proc gdbtk_tcl_start_variable_annotation {valaddr ref_type stor_cl cum_expr field type_cast} { + echo "gdbtk_tcl_start_variable_annotation $valaddr $ref_type $stor_cl $cum_expr $field $type_cast" +} + +proc gdbtk_tcl_end_variable_annotation {} { + echo gdbtk_tcl_end_variable_annotation +} + +proc insert_breakpoint_tag {win line} { + $win configure -state normal + $win delete $line.0 + $win insert $line.0 "B" + $win tag add $line $line.0 + $win tag bind $line <1> { +# echo "tag %W %X %Y %x" +# echo "tag names [$wins($cfile) tag names]" + } + + $win configure -state disabled +} + +proc delete_breakpoint_tag {win line} { + $win configure -state normal + $win delete $line.0 + $win insert $line.0 " " + $win tag delete $line + $win configure -state disabled +} + +# Callback from GDB to notify us of breakpoint creation. + +proc create_breakpoint {bpnum file line} { + global wins + global breakpoint_file + global breakpoint_line + +# Record breakpoint locations + + set breakpoint_file($bpnum) $file + set breakpoint_line($bpnum) $line + +# If there isn't a window for this file, don't try to update it + + if [info exists wins($file)] { + insert_breakpoint_tag $wins($file) $line + } +} + +proc delete_breakpoint {bpnum file line} { + global wins + global breakpoint_file + global breakpoint_line + +# Save line number for later + + set line $breakpoint_line($bpnum) + +# Reset breakpoint annotation info + + unset breakpoint_file($bpnum) + unset breakpoint_line($bpnum) + +# If there isn't a window for this file, don't try to update it + + if [info exists wins($file)] { + delete_breakpoint_tag $wins($file) $line + } +} + +# This is a callback from C code to notify us of breakpoint changes. ACTION +# can be one of create, delete, enable, or disable. + +proc gdbtk_tcl_breakpoint {action bpnum file line} { + ${action}_breakpoint $bpnum $file $line +} + +# Create the popup listing window menu + +menu .breakpoint -cursor hand2 +.breakpoint add command -label Break +.breakpoint add separator +.breakpoint add command -label "Edit" -command {exec $editor +$selected_line $selected_file &} +.breakpoint add command -label "Set breakpoint" -command {gdb_cmd "break $selected_file:$selected_line"} +#.breakpoint add command -label "Clear breakpoint" -command {echo "Clear"} +#.breakpoint add command -label "Enable breakpoint" -command {echo "Enable"} +#.breakpoint add command -label "Disable breakpoint" -command {echo "Disable"} + +# Come here when button is released in the popup menu + +bind .breakpoint { + global selected_win + +# First, remove the menu, and release the pointer + + .breakpoint unpost + grab release .breakpoint + +# Unhighlight the selected line + + $selected_win tag delete breaktag +# echo "after deleting $selected_win [$selected_win tag names]" +# echo "grab [grab current]" + +# Actually invoke the menubutton here! + + tk_invokeMenu %W +# destroy .breakpoint + grab release $selected_win +} + +# Button 1 has been pressed in a listing window. Pop up a menu. + +proc breakpoint_menu {win x y xrel yrel} { + global wins + global win_to_file + global file_to_debug_file + global highlight + global selected_line + global selected_file + global selected_win + + grab $win + +# echo "bpm grab current [grab current]" + +# Map TK window name back to file name. + + set file $win_to_file($win) + + set pos [$win index @$xrel,$yrel] + +# Record selected file and line for menu button actions + + set selected_file $file_to_debug_file($file) + set selected_line [lindex [split $pos .] 0] + set selected_win $win + +# Highlight the selected line + + eval $win tag config breaktag $highlight + $win tag add breaktag "$pos linestart" "$pos linestart + 1l" + +# Post the menu near the pointer, (and grab it) + + .breakpoint post [expr $x-[winfo width .breakpoint]/2] [expr $y-10] + grab .breakpoint +# echo "after grab [grab current]" +} + +proc do_nothing {} {} + +proc create_file_win {filename} { + global breakpoint_file + global breakpoint_line + + regsub -all {\.|/} $filename {} temp + set win .text$temp + text $win -height 25 -width 80 -relief raised -borderwidth 2 -yscrollcommand textscrollproc -setgrid true -cursor hand2 + bind $win {focus %W} +# bind $win <1> {breakpoint_menu %W %X %Y %x %y} + bind $win 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} + set fh [open $filename] + $win delete 0.0 end + $win insert 0.0 [read $fh] + close $fh + 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 wholebuf 0.0 end + $win tag bind wholebuf <1> {breakpoint_menu %W %X %Y %x %y} + foreach bpnum [array names breakpoint_file] { + if {$breakpoint_file($bpnum) == $filename} { + insert_breakpoint_tag $win $breakpoint_line($bpnum) + } + } + + $win configure -state disabled + return $win +} + +proc update_listing {linespec} { + global pointers + global screen_height + global screen_top + global screen_bot + global wins cfile + global current_label + global win_to_file + global file_to_debug_file + + set line [lindex $linespec 3] + set filename [lindex $linespec 2] + set funcname [lindex $linespec 1] + set debug_file [lindex $linespec 0] + + if {$filename == ""} {set filename Blank} + + if {$filename != $cfile} then { + pack forget $wins($cfile) + set cfile $filename + if ![info exists wins($cfile)] then { + set wins($cfile) [create_file_win $cfile] + set win_to_file($wins($cfile)) $cfile + set file_to_debug_file($cfile) $debug_file + set pointers($cfile) 1.1 + } + + pack $wins($cfile) -side left -expand yes -in .listing -fill both -after .label + $wins($cfile) yview [expr $line - $screen_height / 2] + } + + if {$current_label != "$filename.$funcname"} then { + set tail [expr [string last / $filename] + 1] + .label configure -text "[string range $filename $tail end] : ${funcname}()" + set current_label $filename.$funcname + } + + if [info exists pointers($cfile)] then { + $wins($cfile) configure -state normal + set pointer_pos $pointers($cfile) + $wins($cfile) configure -state normal + $wins($cfile) delete $pointer_pos + $wins($cfile) insert $pointer_pos " " + + set pointer_pos [$wins($cfile) index $line.1] + set pointers($cfile) $pointer_pos + + $wins($cfile) delete $pointer_pos + $wins($cfile) insert $pointer_pos "\xbb" + + if {$line < $screen_top + 1 + || $line > $screen_bot} then { + $wins($cfile) yview [expr $line - $screen_height / 2] + } + + $wins($cfile) configure -state disabled + } +} + +proc update_ptr {} {update_listing [gdb_loc]} + +# Setup listing window + +frame .listing + +wm minsize . 1 1 + +label .label -text "*No file*" -borderwidth 2 -relief raised +text $wins($cfile) -height 25 -width 80 -relief raised -borderwidth 2 -yscrollcommand textscrollproc -setgrid true -cursor hand2 +scrollbar .scroll -orient vertical -command {$wins($cfile) yview} + +if {[tk colormodel .text] == "color"} { + set highlight "-background red2 -borderwidth 2 -relief sunk" +} else { + set fg [lindex [.text config -foreground] 4] + set bg [lindex [.text config -background] 4] + set highlight "-foreground $bg -background $fg -borderwidth 0" +} + +proc textscrollproc {args} {global screen_height screen_top screen_bot + eval ".scroll set $args" + set screen_height [lindex $args 1] + set screen_top [lindex $args 2] + set screen_bot [lindex $args 3]} + +$wins($cfile) insert 0.0 " This page intentionally left blank." +$wins($cfile) configure -state disabled + +pack .label -side bottom -fill x -in .listing +pack $wins($cfile) -side left -expand yes -in .listing -fill both +pack .scroll -side left -fill y -in .listing + +button .start -text Start -command \ + {gdb_cmd {break main} + gdb_cmd {enable delete $bpnum} + gdb_cmd run + update_ptr } +button .step -text Step -command {gdb_cmd step ; update_ptr} +button .next -text Next -command {gdb_cmd next ; update_ptr} +button .continue -text Continue -command {gdb_cmd continue ; update_ptr} +button .finish -text Finish -command {gdb_cmd finish ; update_ptr} +#button .test -text Test -command {echo [info var]} +button .exit -text Exit -command {gdb_cmd quit} +button .up -text Up -command {gdb_cmd up ; update_ptr} +button .down -text Down -command {gdb_cmd down ; update_ptr} +button .bottom -text "Bottom" -command {gdb_cmd {frame 0} ; update_ptr} + +proc files_command {} { + toplevel .files_window + + wm minsize .files_window 1 1 +# wm overrideredirect .files_window true + listbox .files_window.list -geometry 30x20 -setgrid true + button .files_window.close -text Close -command {destroy .files_window} + tk_listboxSingleSelect .files_window.list + eval .files_window.list insert 0 [lsort [gdb_listfiles]] + pack .files_window.list -side top -fill both -expand yes + pack .files_window.close -side bottom -fill x -expand no -anchor s + bind .files_window.list { + set file [%W get [%W curselection]] + gdb_cmd "list $file:1,0" + update_listing [gdb_loc $file:1] + destroy .files_window} +} + +button .files -text Files -command files_command + +pack .listing -side bottom -fill both -expand yes +#pack .test -side bottom -fill x +pack .start .step .next .continue .finish .up .down .bottom .files .exit -side left +toplevel .command + +# Setup command window + +label .command.label -text "* Command Buffer *" -borderwidth 2 -relief raised +text .command.text -height 25 -width 80 -relief raised -borderwidth 2 -setgrid true -cursor hand2 + +pack .command.label -side top -fill x +pack .command.text -side top -expand yes -fill both + +set command_line {} + +gdb_cmd {set language c} +gdb_cmd {set height 0} +gdb_cmd {set width 0} + +bind .command.text { + global command_line + + %W insert end %A + %W yview -pickplace end + append command_line %A + } +bind .command.text { + global command_line + + %W insert end \n + %W yview -pickplace end + gdb_cmd $command_line + set command_line {} + update_ptr + %W insert end "(gdb) " + %W yview -pickplace end + } +bind .command.text {focus %W} +bind .command.text {delete_char %W} +bind .command.text {delete_char %W} +proc delete_char {win} { + global command_line + + tk_textBackspace $win + $win yview -pickplace insert + set tmp [expr [string length $command_line] - 2] + set command_line [string range $command_line 0 $tmp] +} + +wm minsize .command 1 1 + diff --git a/gdb/main.c b/gdb/main.c index ce21c83dc9a..e7c8070a1cd 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -174,6 +174,8 @@ 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}, /* Allow machine descriptions to add more options... */ #ifdef ADDITIONAL_OPTIONS ADDITIONAL_OPTIONS @@ -350,6 +352,7 @@ Options:\n\ -b BAUDRATE Set serial port baud rate used for remote debugging.\n\ --mapped Use mapped symbol files if supported on this system.\n\ --readnow Fully read symbol files on first access.\n\ + --nw Do not use a window interface.\n\ ", gdb_stdout); /* start-sanitize-mpw */ #endif /* MPW_C */ @@ -410,7 +413,7 @@ GDB manual (available as on-line info or a printed manual).\n", gdb_stdout); stat (gdbinit, &cwdbuf); /* We'll only need this if homedir was set. */ } - + /* Now perform all the actions indicated by the arguments. */ if (cdarg != NULL) { @@ -526,18 +529,13 @@ GDB manual (available as on-line info or a printed manual).\n", gdb_stdout); if (!SET_TOP_LEVEL ()) { do_cleanups (ALL_CLEANUPS); /* Do complete cleanup */ -/* start-sanitize-mpw */ -#ifdef MPW - /* If we're being a Mac application, go into a Mac-specific - event-handling loop instead. We still want to be inside - the outer loop, because that will catch longjmps resulting - from some command executions. */ - if (mac_app) - mac_command_loop (); + /* GUIs generally have their own command loop, mainloop, or whatever. + This is a good place to gain control because many error + conditions will end up here via longjmp(). */ + if (command_loop_hook) + command_loop_hook (); else -#endif /* MPW */ -/* end-sanitize-mpw */ - command_loop (); + command_loop (); quit_command ((char *)0, instream == stdin); } } @@ -570,5 +568,11 @@ fputs_unfiltered (linebuffer, stream) const char *linebuffer; FILE *stream; { + if (fputs_unfiltered_hook) + { + fputs_unfiltered_hook (linebuffer); + return; + } + fputs (linebuffer, stream); } diff --git a/gdb/remote.c b/gdb/remote.c index 40536ef5f44..d5b677e4eea 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -122,6 +122,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ general set QXXXX=yyyy Set value of XXXX to yyyy. query sect offs qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz + console output Otext Send text to stdout. Only comes from + remote target. Responses can be run-length encoded to save space. A '*' means that the next two characters are hex digits giving a repeat count which @@ -145,7 +147,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "dcache.h" -#if !defined(DONT_USE_REMOTE) #ifdef USG #include #endif @@ -199,7 +200,7 @@ static void remote_send PARAMS ((char *buf)); static int -readchar PARAMS ((void)); +readchar PARAMS ((int timeout)); static int remote_wait PARAMS ((int pid, struct target_waitstatus *status)); @@ -227,7 +228,7 @@ extern struct target_ops remote_ops; /* Forward decl */ Unless this is going though some terminal server or multiplexer or other form of hairy serial connection, I would think 2 seconds would be plenty. */ -static int timeout = 2; +static int remote_timeout = 2; #if 0 int icache; @@ -448,7 +449,6 @@ fromhex (a) return a - 'a' + 10; else error ("Reply contains invalid hex digit"); - return -1; } /* Convert number NIB to a hex digit. */ @@ -558,75 +558,82 @@ remote_wait (pid, status) getpkt ((char *) buf, 1); signal (SIGINT, ofunc); - if (buf[0] == 'E') - warning ("Remote failure reply: %s", buf); - else if (buf[0] == 'T') + switch (buf[0]) { - int i; - long regno; - char regs[MAX_REGISTER_RAW_SIZE]; + case 'E': /* Error of some sort */ + warning ("Remote failure reply: %s", buf); + continue; + case 'T': /* Status with PC, SP, FP, ... */ + { + int i; + long regno; + char regs[MAX_REGISTER_RAW_SIZE]; - /* Expedited reply, containing Signal, {regno, reg} repeat */ - /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where - ss = signal number - n... = register number - r... = register contents - */ + /* Expedited reply, containing Signal, {regno, reg} repeat */ + /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where + ss = signal number + n... = register number + r... = register contents + */ - p = &buf[3]; /* after Txx */ + p = &buf[3]; /* after Txx */ - while (*p) - { - unsigned char *p1; + while (*p) + { + unsigned char *p1; - regno = strtol (p, &p1, 16); /* Read the register number */ + regno = strtol (p, &p1, 16); /* Read the register number */ - if (p1 == p) - warning ("Remote sent badly formed register number: %s\nPacket: '%s'\n", - p1, buf); + if (p1 == p) + warning ("Remote sent badly formed register number: %s\nPacket: '%s'\n", + p1, buf); - p = p1; + p = p1; - if (*p++ != ':') - warning ("Malformed packet (missing colon): %s\nPacket: '%s'\n", - p, buf); + if (*p++ != ':') + warning ("Malformed packet (missing colon): %s\nPacket: '%s'\n", + p, buf); - if (regno >= NUM_REGS) - warning ("Remote sent bad register number %d: %s\nPacket: '%s'\n", - regno, p, buf); + if (regno >= NUM_REGS) + warning ("Remote sent bad register number %d: %s\nPacket: '%s'\n", + regno, p, buf); - for (i = 0; i < REGISTER_RAW_SIZE (regno); i++) - { - if (p[0] == 0 || p[1] == 0) - warning ("Remote reply is too short: %s", buf); - regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); - p += 2; - } + for (i = 0; i < REGISTER_RAW_SIZE (regno); i++) + { + if (p[0] == 0 || p[1] == 0) + warning ("Remote reply is too short: %s", buf); + regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); + p += 2; + } - if (*p++ != ';') - warning ("Remote register badly formatted: %s", buf); + if (*p++ != ';') + warning ("Remote register badly formatted: %s", buf); + + supply_register (regno, regs); + } + } + /* fall through */ + case 'S': /* Old style status, just signal only */ + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = (enum target_signal) + (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))); - supply_register (regno, regs); - } - break; - } - else if (buf[0] == 'W') - { - /* The remote process exited. */ - status->kind = TARGET_WAITKIND_EXITED; - status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]); return 0; + case 'W': /* Target exited */ + { + /* The remote process exited. */ + status->kind = TARGET_WAITKIND_EXITED; + status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]); + return 0; + } + case 'O': /* Console output */ + fputs_filtered (buf + 1, gdb_stdout); + continue; + default: + warning ("Invalid remote reply: %s", buf); + continue; } - else if (buf[0] == 'S') - break; - else - warning ("Invalid remote reply: %s", buf); } - - status->kind = TARGET_WAITKIND_STOPPED; - status->value.sig = (enum target_signal) - (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))); - return 0; } @@ -1039,16 +1046,24 @@ remote_files_info (ignore) /* Read a single character from the remote end, masking it down to 7 bits. */ static int -readchar () +readchar (timeout) + int timeout; { int ch; ch = SERIAL_READCHAR (remote_desc, timeout); - if (ch < 0) - return ch; - - return ch & 0x7f; + switch (ch) + { + case SERIAL_EOF: + error ("Remote connection closed"); + case SERIAL_ERROR: + perror_with_name ("Remote communication error"); + case SERIAL_TIMEOUT: + return ch; + default: + return ch & 0x7f; + } } /* Send the command in BUF to the remote machine, @@ -1117,7 +1132,7 @@ putpkt (buf) /* read until either a timeout occurs (-2) or '+' is read */ while (1) { - ch = readchar (); + ch = readchar (remote_timeout); if (remote_debug) { @@ -1125,8 +1140,6 @@ putpkt (buf) { case '+': case SERIAL_TIMEOUT: - case SERIAL_ERROR: - case SERIAL_EOF: case '$': if (started_error_output) { @@ -1144,10 +1157,6 @@ putpkt (buf) return; case SERIAL_TIMEOUT: break; /* Retransmit buffer */ - case SERIAL_ERROR: - perror_with_name ("putpkt: couldn't read ACK"); - case SERIAL_EOF: - error ("putpkt: EOF while trying to read ACK"); case '$': { unsigned char junkbuf[PBUFSIZ]; @@ -1187,151 +1196,157 @@ putpkt (buf) } } +/* Come here after finding the start of the frame. Collect the rest into BUF, + verifying the checksum, length, and handling run-length compression. + Returns 0 on any error, 1 on success. */ + +static int +read_frame (buf) + char *buf; +{ + unsigned char csum; + char *bp; + int c; + + csum = 0; + bp = buf; + + while (1) + { + c = readchar (remote_timeout); + + switch (c) + { + case SERIAL_TIMEOUT: + if (remote_debug) + puts_filtered ("Timeout in mid-packet, retrying\n"); + return 0; + case '$': + if (remote_debug) + puts_filtered ("Saw new packet start in middle of old one\n"); + return 0; /* Start a new packet, count retries */ + case '#': + { + unsigned char pktcsum; + + *bp = '\000'; + + pktcsum = fromhex (readchar (remote_timeout)) << 4 + | fromhex (readchar (remote_timeout)); + + if (csum == pktcsum) + return 1; + + printf_filtered ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=", + pktcsum, csum); + puts_filtered (buf); + puts_filtered ("\n"); + + return 0; + } + case '*': /* Run length encoding */ + c = readchar (remote_timeout); + csum += c; + c = c - ' ' + 3; /* Compute repeat count */ + + if (bp + c - 1 < buf + PBUFSIZ - 1) + { + memset (bp, *(bp - 1), c); + bp += c; + continue; + } + + *bp = '\0'; + printf_filtered ("Repeat count %d too large for buffer: ", c); + puts_filtered (buf); + puts_filtered ("\n"); + + return 0; + default: + if (bp < buf + PBUFSIZ - 1) + { + *bp++ = c; + csum += c; + continue; + } + + *bp = '\0'; + puts_filtered ("Remote packet too long: "); + puts_filtered (buf); + puts_filtered ("\n"); + + return 0; + } + } +} + /* Read a packet from the remote machine, with error checking, and store it in BUF. BUF is expected to be of size PBUFSIZ. If FOREVER, wait forever rather than timing out; this is used while the target is executing user code. */ static void -getpkt (retbuf, forever) - char *retbuf; +getpkt (buf, forever) + char *buf; int forever; { char *bp; - unsigned char csum; - int c = 0; - unsigned char c1, c2; - int retries = 0; - char buf[PBUFSIZ]; + int c; + int tries; + int timeout; + int val; -#define MAX_RETRIES 10 + if (forever) + timeout = -1; + else + timeout = remote_timeout; - while (1) - { -#if 0 - /* This is wrong. If doing a long backtrace, the user should be - able to get out time next we call QUIT, without anything as violent - as interrupt_query. If we want to provide a way out of here - without getting to the next QUIT, it should be based on hitting - ^C twice as in remote_wait. */ - if (quit_flag) - { - quit_flag = 0; - interrupt_query (); - } -#endif +#define MAX_TRIES 10 + for (tries = 1; tries <= MAX_TRIES; tries++) + { /* This can loop forever if the remote side sends us characters continuously, but if it pauses, we'll get a zero from readchar because of timeout. Then we'll count that as a retry. */ - c = readchar(); - if (c > 0 && c != '$') - continue; + /* Note that we will only wait forever prior to the start of a packet. + After that, we expect characters to arrive at a brisk pace. They + should show up within remote_timeout intervals. */ - if (c == SERIAL_TIMEOUT) + do { - if (forever) - continue; - if (remote_debug) - puts_filtered ("Timed out.\n"); - goto whole; - } - - if (c == SERIAL_EOF) - error ("Remote connection closed"); - if (c == SERIAL_ERROR) - perror_with_name ("Remote communication error"); + c = readchar (timeout); - /* Force csum to be zero here because of possible error retry. */ - csum = 0; - bp = buf; - - while (1) - { - c = readchar (); if (c == SERIAL_TIMEOUT) { if (remote_debug) - puts_filtered ("Timeout in mid-packet, retrying\n"); - goto whole; /* Start a new packet, count retries */ - } - if (c == '$') - { - if (remote_debug) - puts_filtered ("Saw new packet start in middle of old one\n"); - goto whole; /* Start a new packet, count retries */ + puts_filtered ("Timed out.\n"); + goto retry; } - if (c == '#') - break; - if (bp >= buf+PBUFSIZ-1) - { - *bp = '\0'; - puts_filtered ("Remote packet too long: "); - puts_filtered (buf); - puts_filtered ("\n"); - goto whole; - } - *bp++ = c; - csum += c; } - *bp = 0; + while (c != '$'); - c1 = fromhex (readchar ()); - c2 = fromhex (readchar ()); - if ((csum & 0xff) == (c1 << 4) + c2) - break; - printf_filtered ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=", - (c1 << 4) + c2, csum & 0xff); - puts_filtered (buf); - puts_filtered ("\n"); + /* We've found the start of a packet, now collect the data. */ - /* Try the whole thing again. */ -whole: - if (++retries < MAX_RETRIES) - { - SERIAL_WRITE (remote_desc, "-", 1); - } - else + val = read_frame (buf); + + if (val == 1) { - printf_unfiltered ("Ignoring packet error, continuing...\n"); - break; + if (remote_debug) + fprintf_unfiltered (gdb_stderr, "Packet received: %s\n", buf); + SERIAL_WRITE (remote_desc, "+", 1); + return; } + + /* Try the whole thing again. */ +retry: + SERIAL_WRITE (remote_desc, "-", 1); } - /* Deal with run-length encoding. */ - { - char *src = buf; - char *dest = retbuf; - int i; - int repeat; - do { - if (*src == '*') - { - if (src[1] == '\0' || src[2] == '\0') - { - if (remote_debug) - puts_filtered ("Packet too short, retrying\n"); - goto whole; - } - repeat = (fromhex (src[1]) << 4) + fromhex (src[2]); - for (i = 0; i < repeat; ++i) - { - *dest++ = src[-1]; - } - src += 2; - } - else - { - *dest++ = *src; - } - } while (*src++ != '\0'); - } + /* We have tried hard enough, and just can't receive the packet. Give up. */ + printf_unfiltered ("Ignoring packet error, continuing...\n"); SERIAL_WRITE (remote_desc, "+", 1); - - if (remote_debug) - fprintf_unfiltered (gdb_stderr,"Packet received: %s\n", buf); } static void @@ -1443,12 +1458,9 @@ Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */ NULL, /* sections_end */ OPS_MAGIC /* to_magic */ }; -#endif /* Use remote. */ void _initialize_remote () { -#if !defined(DONT_USE_REMOTE) add_target (&remote_ops); -#endif } diff --git a/gdb/top.c b/gdb/top.c index 8e6d56c9595..75acd4a337e 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -146,6 +146,10 @@ source_cleanup PARAMS ((FILE *)); char gdbinit[] = GDBINIT_FILENAME; int inhibit_gdbinit = 0; +/* Disable windows if non-zero */ + +int no_windows = 0; + /* Version number of GDB, as a string. */ extern char *version; @@ -488,6 +492,8 @@ gdb_init () current_directory = gdb_dirbuf; init_cmd_lists (); /* This needs to be done first */ + initialize_targets (); /* Setup target_terminal macros for utils.c */ + initialize_utils (); /* Make errors and warnings possible */ initialize_all_files (); init_main (); /* But that omits this file! Do it now */ init_signals (); @@ -499,6 +505,9 @@ gdb_init () or implicitly set by reading an executable during startup. */ set_language (language_c); expected_language = current_language; /* don't warn about the change. */ + + if (init_ui_hook) + init_ui_hook (); } void