* 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.
This commit is contained in:
Stu Grossman 1994-07-28 22:07:02 +00:00
parent b98612f1fd
commit 754e5da26e
10 changed files with 1142 additions and 207 deletions

View File

@ -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) 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 * Makefile.in (CC_FOR_TARGET, CXX_FOR_TARGET): Use newlib if it is

View File

@ -169,9 +169,10 @@ REGEX1 = regex.o
# If you have the Cygnus libraries installed, # If you have the Cygnus libraries installed,
# you can use 'CLIBS=$(INSTALLED_LIBS)' 'CDEPS=' # you can use 'CLIBS=$(INSTALLED_LIBS)' 'CDEPS='
INSTALLED_LIBS=-lbfd -lreadline $(TERMCAP) -lopcodes -lmmalloc \ 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) \ 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) \ CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) \
$(BFD) $(READLINE) $(OPCODES) $(MMALLOC) $(LIBIBERTY) $(BFD) $(READLINE) $(OPCODES) $(MMALLOC) $(LIBIBERTY)
@ -454,7 +455,8 @@ TARDIRS = doc gdbserver sparclite
# variables analogous to SER_HARDWIRE which get defaulted in this # variables analogous to SER_HARDWIRE which get defaulted in this
# Makefile.in # Makefile.in
DEPFILES = $(TDEPFILES) $(XDEPFILES) $(SER_HARDWIRE) $(NATDEPFILES) $(REMOTE_O) DEPFILES = $(TDEPFILES) $(XDEPFILES) $(SER_HARDWIRE) $(NATDEPFILES) $(REMOTE_O) \
$(ENABLE_DEPFILES)
SOURCES = $(SFILES) $(ALLDEPFILES) $(YYFILES) SOURCES = $(SFILES) $(ALLDEPFILES) $(YYFILES)
# Don't include YYFILES (*.tab.c) because we already include *.y in SFILES, # 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) \ fork-child.o: fork-child.c $(wait_h) $(defs_h) $(gdbcore_h) \
$(inferior_h) target.h terminal.h thread.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.o: gdbtypes.c $(bfd_h) complaints.h $(defs_h) $(expression_h) \
$(gdbtypes_h) language.h objfiles.h symfile.h $(symtab_h) target.h \ $(gdbtypes_h) language.h objfiles.h symfile.h $(symtab_h) target.h \
$(value_h) $(value_h)

View File

@ -2149,6 +2149,9 @@ mention (b)
{ {
int say_where = 0; int say_where = 0;
if (create_breakpoint_hook)
create_breakpoint_hook (b);
switch (b->type) switch (b->type)
{ {
case bp_watchpoint: case bp_watchpoint:
@ -3181,6 +3184,9 @@ delete_breakpoint (bpt)
register struct breakpoint *b; register struct breakpoint *b;
register bpstat bs; register bpstat bs;
if (delete_breakpoint_hook)
delete_breakpoint_hook (bpt);
if (bpt->inserted) if (bpt->inserted)
remove_breakpoint (bpt); remove_breakpoint (bpt);
@ -3539,6 +3545,9 @@ enable_breakpoint (bpt)
int target_resources_ok, other_type_used; int target_resources_ok, other_type_used;
struct value *mark; struct value *mark;
if (enable_breakpoint_hook)
enable_breakpoint_hook (bpt);
if (bpt->type == bp_hardware_breakpoint) if (bpt->type == bp_hardware_breakpoint)
{ {
int i; int i;
@ -3644,6 +3653,9 @@ disable_breakpoint (bpt)
if (bpt->type == bp_watchpoint_scope) if (bpt->type == bp_watchpoint_scope)
return; return;
if (disable_breakpoint_hook)
disable_breakpoint_hook (bpt);
bpt->enable = disabled; bpt->enable = disabled;
breakpoints_changed (); breakpoints_changed ();

View File

@ -397,6 +397,12 @@ else
links="${links} nm.h" links="${links} nm.h"
fi 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: # post-target:
case ${srcdir} in case ${srcdir} in
@ -413,6 +419,15 @@ if [ "${nativefile}" = "" ] ; then
mv -f Makefile.tem Makefile mv -f Makefile.tem Makefile
fi 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}"'/, sed -e '/^TM_FILE[ ]*=/s,^TM_FILE[ ]*=[ ]*,&config/'"${gdb_target_cpu}"'/,
/^XM_FILE[ ]*=/s,^XM_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/, /^XM_FILE[ ]*=/s,^XM_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,
/^NAT_FILE[ ]*=/s,^NAT_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,' <Makefile >Makefile.tmp /^NAT_FILE[ ]*=/s,^NAT_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,' <Makefile >Makefile.tmp

View File

@ -92,7 +92,8 @@ enum language
language_c, /* C */ language_c, /* C */
language_cplus, /* C++ */ language_cplus, /* C++ */
language_chill, /* Chill */ 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 /* the cleanup list records things that have to be undone
@ -342,9 +343,6 @@ command_line_input PARAMS ((char *, int, char *));
extern void extern void
print_prompt PARAMS ((void)); print_prompt PARAMS ((void));
extern int
batch_mode PARAMS ((void));
extern int extern int
input_from_terminal_p PARAMS ((void)); input_from_terminal_p PARAMS ((void));
@ -357,7 +355,7 @@ extern void
print_address_symbolic PARAMS ((CORE_ADDR, GDB_FILE *, int, char *)); print_address_symbolic PARAMS ((CORE_ADDR, GDB_FILE *, int, char *));
extern void extern void
print_address_numeric PARAMS ((CORE_ADDR, GDB_FILE *)); print_address_numeric PARAMS ((CORE_ADDR, int, GDB_FILE *));
extern void extern void
print_address PARAMS ((CORE_ADDR, GDB_FILE *)); print_address PARAMS ((CORE_ADDR, GDB_FILE *));
@ -941,4 +939,27 @@ push_word PARAMS ((CORE_ADDR, unsigned LONGEST));
#define MAINTENANCE_CMDS 1 #define MAINTENANCE_CMDS 1
#endif #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) */ #endif /* !defined (DEFS_H) */

424
gdb/gdbtk.c Normal file
View File

@ -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 <sys/types.h>
#include <sys/time.h>
#include <sys/param.h>
#include <varargs.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/filio.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/errno.h>
#include <termios.h>
#include <string.h>
#include <tcl.h>
#include <tk.h>
/* 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;
}

399
gdb/gdbtk.tcl Normal file
View File

@ -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 <Any-ButtonRelease-1> {
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 <Enter> {focus %W}
# bind $win <1> {breakpoint_menu %W %X %Y %x %y}
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}
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 <Any-ButtonRelease-1> {
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 <Any-Key> {
global command_line
%W insert end %A
%W yview -pickplace end
append command_line %A
}
bind .command.text <Key-Return> {
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 <Enter> {focus %W}
bind .command.text <Delete> {delete_char %W}
bind .command.text <BackSpace> {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

View File

@ -174,6 +174,8 @@ main (argc, argv)
{"tty", required_argument, 0, 't'}, {"tty", required_argument, 0, 't'},
{"baud", required_argument, 0, 'b'}, {"baud", required_argument, 0, 'b'},
{"b", 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... */ /* Allow machine descriptions to add more options... */
#ifdef ADDITIONAL_OPTIONS #ifdef ADDITIONAL_OPTIONS
ADDITIONAL_OPTIONS ADDITIONAL_OPTIONS
@ -350,6 +352,7 @@ Options:\n\
-b BAUDRATE Set serial port baud rate used for remote debugging.\n\ -b BAUDRATE Set serial port baud rate used for remote debugging.\n\
--mapped Use mapped symbol files if supported on this system.\n\ --mapped Use mapped symbol files if supported on this system.\n\
--readnow Fully read symbol files on first access.\n\ --readnow Fully read symbol files on first access.\n\
--nw Do not use a window interface.\n\
", gdb_stdout); ", gdb_stdout);
/* start-sanitize-mpw */ /* start-sanitize-mpw */
#endif /* MPW_C */ #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 stat (gdbinit, &cwdbuf); /* We'll only need this if
homedir was set. */ homedir was set. */
} }
/* Now perform all the actions indicated by the arguments. */ /* Now perform all the actions indicated by the arguments. */
if (cdarg != NULL) 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 ()) if (!SET_TOP_LEVEL ())
{ {
do_cleanups (ALL_CLEANUPS); /* Do complete cleanup */ do_cleanups (ALL_CLEANUPS); /* Do complete cleanup */
/* start-sanitize-mpw */ /* GUIs generally have their own command loop, mainloop, or whatever.
#ifdef MPW This is a good place to gain control because many error
/* If we're being a Mac application, go into a Mac-specific conditions will end up here via longjmp(). */
event-handling loop instead. We still want to be inside if (command_loop_hook)
the outer loop, because that will catch longjmps resulting command_loop_hook ();
from some command executions. */
if (mac_app)
mac_command_loop ();
else else
#endif /* MPW */ command_loop ();
/* end-sanitize-mpw */
command_loop ();
quit_command ((char *)0, instream == stdin); quit_command ((char *)0, instream == stdin);
} }
} }
@ -570,5 +568,11 @@ fputs_unfiltered (linebuffer, stream)
const char *linebuffer; const char *linebuffer;
FILE *stream; FILE *stream;
{ {
if (fputs_unfiltered_hook)
{
fputs_unfiltered_hook (linebuffer);
return;
}
fputs (linebuffer, stream); fputs (linebuffer, stream);
} }

View File

@ -122,6 +122,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
general set QXXXX=yyyy Set value of XXXX to yyyy. general set QXXXX=yyyy Set value of XXXX to yyyy.
query sect offs qOffsets Get section offsets. Reply is query sect offs qOffsets Get section offsets. Reply is
Text=xxx;Data=yyy;Bss=zzz 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 Responses can be run-length encoded to save space. A '*' means that
the next two characters are hex digits giving a repeat count which 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" #include "dcache.h"
#if !defined(DONT_USE_REMOTE)
#ifdef USG #ifdef USG
#include <sys/types.h> #include <sys/types.h>
#endif #endif
@ -199,7 +200,7 @@ static void
remote_send PARAMS ((char *buf)); remote_send PARAMS ((char *buf));
static int static int
readchar PARAMS ((void)); readchar PARAMS ((int timeout));
static int remote_wait PARAMS ((int pid, struct target_waitstatus *status)); 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 Unless this is going though some terminal server or multiplexer or
other form of hairy serial connection, I would think 2 seconds would other form of hairy serial connection, I would think 2 seconds would
be plenty. */ be plenty. */
static int timeout = 2; static int remote_timeout = 2;
#if 0 #if 0
int icache; int icache;
@ -448,7 +449,6 @@ fromhex (a)
return a - 'a' + 10; return a - 'a' + 10;
else else
error ("Reply contains invalid hex digit"); error ("Reply contains invalid hex digit");
return -1;
} }
/* Convert number NIB to a hex digit. */ /* Convert number NIB to a hex digit. */
@ -558,75 +558,82 @@ remote_wait (pid, status)
getpkt ((char *) buf, 1); getpkt ((char *) buf, 1);
signal (SIGINT, ofunc); signal (SIGINT, ofunc);
if (buf[0] == 'E') switch (buf[0])
warning ("Remote failure reply: %s", buf);
else if (buf[0] == 'T')
{ {
int i; case 'E': /* Error of some sort */
long regno; warning ("Remote failure reply: %s", buf);
char regs[MAX_REGISTER_RAW_SIZE]; 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 */ /* Expedited reply, containing Signal, {regno, reg} repeat */
/* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where
ss = signal number ss = signal number
n... = register number n... = register number
r... = register contents r... = register contents
*/ */
p = &buf[3]; /* after Txx */ p = &buf[3]; /* after Txx */
while (*p) while (*p)
{ {
unsigned char *p1; unsigned char *p1;
regno = strtol (p, &p1, 16); /* Read the register number */ regno = strtol (p, &p1, 16); /* Read the register number */
if (p1 == p) if (p1 == p)
warning ("Remote sent badly formed register number: %s\nPacket: '%s'\n", warning ("Remote sent badly formed register number: %s\nPacket: '%s'\n",
p1, buf); p1, buf);
p = p1; p = p1;
if (*p++ != ':') if (*p++ != ':')
warning ("Malformed packet (missing colon): %s\nPacket: '%s'\n", warning ("Malformed packet (missing colon): %s\nPacket: '%s'\n",
p, buf); p, buf);
if (regno >= NUM_REGS) if (regno >= NUM_REGS)
warning ("Remote sent bad register number %d: %s\nPacket: '%s'\n", warning ("Remote sent bad register number %d: %s\nPacket: '%s'\n",
regno, p, buf); regno, p, buf);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i++) for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
{ {
if (p[0] == 0 || p[1] == 0) if (p[0] == 0 || p[1] == 0)
warning ("Remote reply is too short: %s", buf); warning ("Remote reply is too short: %s", buf);
regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
p += 2; p += 2;
} }
if (*p++ != ';') if (*p++ != ';')
warning ("Remote register badly formatted: %s", buf); 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; 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; return 0;
} }
@ -1039,16 +1046,24 @@ remote_files_info (ignore)
/* Read a single character from the remote end, masking it down to 7 bits. */ /* Read a single character from the remote end, masking it down to 7 bits. */
static int static int
readchar () readchar (timeout)
int timeout;
{ {
int ch; int ch;
ch = SERIAL_READCHAR (remote_desc, timeout); ch = SERIAL_READCHAR (remote_desc, timeout);
if (ch < 0) switch (ch)
return ch; {
case SERIAL_EOF:
return ch & 0x7f; 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, /* 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 */ /* read until either a timeout occurs (-2) or '+' is read */
while (1) while (1)
{ {
ch = readchar (); ch = readchar (remote_timeout);
if (remote_debug) if (remote_debug)
{ {
@ -1125,8 +1140,6 @@ putpkt (buf)
{ {
case '+': case '+':
case SERIAL_TIMEOUT: case SERIAL_TIMEOUT:
case SERIAL_ERROR:
case SERIAL_EOF:
case '$': case '$':
if (started_error_output) if (started_error_output)
{ {
@ -1144,10 +1157,6 @@ putpkt (buf)
return; return;
case SERIAL_TIMEOUT: case SERIAL_TIMEOUT:
break; /* Retransmit buffer */ 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 '$': case '$':
{ {
unsigned char junkbuf[PBUFSIZ]; 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, /* Read a packet from the remote machine, with error checking,
and store it in BUF. BUF is expected to be of size PBUFSIZ. and store it in BUF. BUF is expected to be of size PBUFSIZ.
If FOREVER, wait forever rather than timing out; this is used If FOREVER, wait forever rather than timing out; this is used
while the target is executing user code. */ while the target is executing user code. */
static void static void
getpkt (retbuf, forever) getpkt (buf, forever)
char *retbuf; char *buf;
int forever; int forever;
{ {
char *bp; char *bp;
unsigned char csum; int c;
int c = 0; int tries;
unsigned char c1, c2; int timeout;
int retries = 0; int val;
char buf[PBUFSIZ];
#define MAX_RETRIES 10 if (forever)
timeout = -1;
else
timeout = remote_timeout;
while (1) #define MAX_TRIES 10
for (tries = 1; tries <= MAX_TRIES; tries++)
{ {
#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
/* This can loop forever if the remote side sends us characters /* This can loop forever if the remote side sends us characters
continuously, but if it pauses, we'll get a zero from readchar continuously, but if it pauses, we'll get a zero from readchar
because of timeout. Then we'll count that as a retry. */ because of timeout. Then we'll count that as a retry. */
c = readchar(); /* Note that we will only wait forever prior to the start of a packet.
if (c > 0 && c != '$') After that, we expect characters to arrive at a brisk pace. They
continue; should show up within remote_timeout intervals. */
if (c == SERIAL_TIMEOUT) do
{ {
if (forever) c = readchar (timeout);
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");
/* Force csum to be zero here because of possible error retry. */
csum = 0;
bp = buf;
while (1)
{
c = readchar ();
if (c == SERIAL_TIMEOUT) if (c == SERIAL_TIMEOUT)
{ {
if (remote_debug) if (remote_debug)
puts_filtered ("Timeout in mid-packet, retrying\n"); puts_filtered ("Timed out.\n");
goto whole; /* Start a new packet, count retries */ goto retry;
}
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 */
} }
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 ()); /* We've found the start of a packet, now collect the data. */
c2 = fromhex (readchar ());
if ((csum & 0xff) == (c1 << 4) + c2) val = read_frame (buf);
break;
printf_filtered ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=", if (val == 1)
(c1 << 4) + c2, csum & 0xff); {
puts_filtered (buf); if (remote_debug)
puts_filtered ("\n"); fprintf_unfiltered (gdb_stderr, "Packet received: %s\n", buf);
SERIAL_WRITE (remote_desc, "+", 1);
return;
}
/* Try the whole thing again. */ /* Try the whole thing again. */
whole: retry:
if (++retries < MAX_RETRIES) SERIAL_WRITE (remote_desc, "-", 1);
{
SERIAL_WRITE (remote_desc, "-", 1);
}
else
{
printf_unfiltered ("Ignoring packet error, continuing...\n");
break;
}
} }
/* Deal with run-length encoding. */ /* We have tried hard enough, and just can't receive the packet. Give up. */
{
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');
}
printf_unfiltered ("Ignoring packet error, continuing...\n");
SERIAL_WRITE (remote_desc, "+", 1); SERIAL_WRITE (remote_desc, "+", 1);
if (remote_debug)
fprintf_unfiltered (gdb_stderr,"Packet received: %s\n", buf);
} }
static void static void
@ -1443,12 +1458,9 @@ Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */
NULL, /* sections_end */ NULL, /* sections_end */
OPS_MAGIC /* to_magic */ OPS_MAGIC /* to_magic */
}; };
#endif /* Use remote. */
void void
_initialize_remote () _initialize_remote ()
{ {
#if !defined(DONT_USE_REMOTE)
add_target (&remote_ops); add_target (&remote_ops);
#endif
} }

View File

@ -146,6 +146,10 @@ source_cleanup PARAMS ((FILE *));
char gdbinit[] = GDBINIT_FILENAME; char gdbinit[] = GDBINIT_FILENAME;
int inhibit_gdbinit = 0; int inhibit_gdbinit = 0;
/* Disable windows if non-zero */
int no_windows = 0;
/* Version number of GDB, as a string. */ /* Version number of GDB, as a string. */
extern char *version; extern char *version;
@ -488,6 +492,8 @@ gdb_init ()
current_directory = gdb_dirbuf; current_directory = gdb_dirbuf;
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_utils (); /* Make errors and warnings possible */
initialize_all_files (); initialize_all_files ();
init_main (); /* But that omits this file! Do it now */ init_main (); /* But that omits this file! Do it now */
init_signals (); init_signals ();
@ -499,6 +505,9 @@ gdb_init ()
or implicitly set by reading an executable during startup. */ 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. */
if (init_ui_hook)
init_ui_hook ();
} }
void void