aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog108
-rw-r--r--gdb/Makefile.in17
-rw-r--r--gdb/arm-tdep.c153
-rw-r--r--gdb/config/alpha/alpha-osf2.mh2
-rw-r--r--gdb/config/alpha/alpha-osf3.mh2
-rw-r--r--gdb/config/i386/i386dgux.mh2
-rw-r--r--gdb/config/i386/i386sol2.mh2
-rw-r--r--gdb/config/i386/i386v4.mh2
-rw-r--r--gdb/config/i386/i386v42mp.mh2
-rw-r--r--gdb/config/i386/ncr3000.mh2
-rw-r--r--gdb/config/i386/tm-i386gnu.h18
-rw-r--r--gdb/config/m68k/m68kv4.mh2
-rw-r--r--gdb/config/m88k/delta88v4.mh2
-rw-r--r--gdb/config/mips/irix4.mh2
-rw-r--r--gdb/config/mips/irix5.mh2
-rw-r--r--gdb/config/mips/mipsv4.mh2
-rw-r--r--gdb/config/powerpc/solaris.mh2
-rw-r--r--gdb/defs.h76
-rw-r--r--gdb/doc/gdbint.texinfo33
-rw-r--r--gdb/findvar.c27
-rw-r--r--gdb/gdb-file.c511
-rw-r--r--gdb/gdb-file.h93
-rw-r--r--gdb/gnu-nat.c5
-rw-r--r--gdb/gnu-nat.h10
-rw-r--r--gdb/i386gnu-nat.c502
-rw-r--r--gdb/infcmd.c27
-rw-r--r--gdb/main.c21
-rw-r--r--gdb/remote-rdi.c7
-rw-r--r--gdb/symtab.c61
-rw-r--r--gdb/top.c4
-rw-r--r--gdb/tui/ChangeLog10
-rw-r--r--gdb/tui/tui-file.c298
-rw-r--r--gdb/tui/tui-file.h34
-rw-r--r--gdb/utils.c757
-rw-r--r--gdb/valops.c25
35 files changed, 1622 insertions, 1201 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2d45b2a..dbe6edc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,111 @@
+2000-01-31 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * config/alpha/alpha-osf2.mh, config/alpha/alpha-osf3.mh,
+ config/i386/i386dgux.mh, config/i386/i386sol2.mh,
+ config/i386/i386v4.mh, config/i386/i386v42mp.mh,
+ config/i386/ncr3000.mh, config/m68k/m68kv4.mh,
+ config/m88k/delta88v4.mh, config/mips/irix4.mh,
+ config/mips/irix5.mh, config/mips/mipsv4.mh,
+ config/powerpc/solaris.mh (NATDEPFILES): Change references to
+ proc_api.o, proc_events.o, proc_flags.o, and proc_why.o to
+ proc-api.o, proc-events.o, proc-flags.o, and proc-why.o.
+
+Mon Jan 31 17:14:52 2000 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * top.c (fputs_unfiltered_hook): Moved to tui/tui-file.c.
+
+ * main.c (captured_main): Only use the legacy tui_file code when
+ linking in older code such as the TUI.
+
+ * gdb-file.h, gdb-file.c: New files.
+ * utils.c, defs.h (struct gdb_file, gdb_file_new, gdb_file_delete,
+ null_file_isatty, null_file_rewind, null_file_put,
+ null_file_flush, null_file_write, null_file_fputs,
+ null_file_delete, gdb_file_data, gdb_flush, gdb_file_isatty,
+ gdb_file_rewind, gdb_file_put, gdb_file_write, fputs_unfiltered,
+ set_gdb_file_flush, set_gdb_file_isatty, set_gdb_file_rewind,
+ set_gdb_file_put, set_gdb_file_write, set_gdb_file_fputs,
+ set_gdb_file_data, struct accumulated_gdb_file,
+ do_gdb_file_xstrdup, gdb_file_xstrdup, struct mem_file):
+ mem_file_new, mem_file_delete, mem_fileopen, mem_file_rewind,
+ mem_file_put, mem_file_write, struct stdio_file): stdio_file_new,
+ stdio_file_delete, stdio_file_flush, stdio_file_write,
+ stdio_file_fputs, stdio_file_isatty, stdio_fileopen, gdb_fopen):
+ Moved to gdb-file.h and gdb-file.c.
+ * utils.c (enum streamtype, struct tui_stream, tui_file_new,
+ tui_file_delete, tui_fileopen, tui_sfileopen, tui_file_isatty,
+ tui_file_rewind, tui_file_put, tui_file_fputs,
+ tui_file_get_strbuf, tui_file_adjust_strbuf, tui_file_flush,
+ fputs_unfiltered_hook):
+ Moved to tui/tui-file.c and tui/tui-file.h.
+
+ * Makefile.in (COMMON_OBS): Add gdb-file.o, tui-file.o.
+ (tui-file.o, gdb-file.o): Add dependencies.
+ (corefile.o, main.o, utils.o, simmisc.o): Update dependencies.
+ * main.c: #include tui/tui-file.h.
+
+2000-01-28 Fred Fish <fnf@cygnus.com>
+
+ * findvar.c (value_from_register): Special case handling of D10V
+ pointer values fetched from registers.
+
+2000-01-28 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ * arm-tdep.c (thumb_skip_prologue, thumb_scan_prologue): Add
+ support for new style thumb prologues.
+
+2000-01-28 Nick Clifton <nickc@redhat.com>
+
+ * arm-tdep.c: Remove extraneous dash at start of strings
+ introduced in previous delta.
+
+2000-01-27 Nick Clifton <nickc@redhat.com>
+
+ * arm-tdep.c: Replace uses of arm_toggle_renames() with
+ parse_arm_disassembler_option().
+
+2000-01-27 Jim Blandy <jimb@cygnus.com>
+
+ * symtab.c (decode_line_1): Don't let commas that are within
+ quotes or parenthesis terminate the line spec. Don't use pp when
+ removing the final double quote of a double-quoted string. Don't
+ forget to skip the opening double quote. I have no clue whether
+ this change is correct; probably we've just moved this function
+ from one buggy place to another buggy place, and never came within
+ an outhouse whiff of correctness.
+ (find_toplevel_char): New function.
+
+2000-01-27 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ * arm-tdep.c (arm_push_arguments): Set the thumb mode bit when
+ passing the pointer to a thumb function as an argument.
+
+2000-01-27 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ * remote-rdi.c (arm_rdi_mourn_inferior): Make sure breakpoints
+ are reinserted for another run.
+
+2000-01-27 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ * infcmd.c (run_stack_dummy): Account for a random signal stopping
+ the inferior as well as breakpoints being hit while performing an
+ inferior function call.
+ * valops.c (hand_function_call): Ditto.
+
+2000-01-27 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ From Mark Kettenis <kettenis@gnu.org>
+
+ * config/i386/tm-i386gnu.h (THREAD_STATE_FLAVOR): Define to
+ i386_REGS_SEGS_STATE.
+ (HAVE_I387_REGS): Define.
+ (FLOAT_INFO): Remove.
+ * i386gnu-nat.c: Almost completely rewritten to use new i386
+ register layout and `float info' implementation.
+ * gnu-nat.c (inf_update_procs, proc_get_state, proc_string):
+ Move prototypes from here.
+ * gnu-nat.h: To here.
+
2000-01-24 Kevin Buettner <kevinb@redhat.com>
* utils.c (get_field, put_field): Fix buffer underruns and
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index a8cfafe..9de1d83 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -229,7 +229,7 @@ CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \
ADD_FILES = $(REGEX) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
ADD_DEPS = $(REGEX1) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
-VERSION = 20000126
+VERSION = 20000131
DIST=gdb
LINT=/usr/5bin/lint
@@ -402,7 +402,9 @@ SFILES = ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.c \
tui/tuiGeneralWin.h tui/tuiIO.c tui/tuiIO.h tui/tuiLayout.c \
tui/tuiLayout.h tui/tuiRegs.c tui/tuiRegs.h tui/tuiSource.c \
tui/tuiSource.h tui/tuiSourceWin.c tui/tuiSourceWin.h \
- tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h
+ tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h \
+ tui/tui-file.h tui/tui-file.c \
+ gdb-file.h gdb-file.c
LINTFILES = $(SFILES) $(YYFILES) @CONFIG_SRCS@ init.c
@@ -451,7 +453,7 @@ command_h = command.h
gdbcmd_h = gdbcmd.h $(command_h)
call_cmds_h = call-cmds.h
-defs_h = defs.h xm.h tm.h nm.h config.status config.h gdbarch.h
+defs_h = defs.h xm.h tm.h nm.h config.status config.h gdbarch.h gdb-file.h
top_h = top.h
inferior_h = inferior.h $(breakpoint_h)
@@ -532,7 +534,8 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o stack.o thread.o \
scm-exp.o scm-lang.o scm-valprint.o complaints.o typeprint.o \
c-typeprint.o ch-typeprint.o f-typeprint.o m2-typeprint.o \
c-valprint.o cp-valprint.o ch-valprint.o f-valprint.o m2-valprint.o \
- nlmread.o serial.o mdebugread.o os9kread.o top.o utils.o
+ nlmread.o serial.o mdebugread.o os9kread.o top.o utils.o \
+ gdb-file.o tui-file.o
OBS = $(COMMON_OBS) $(ANNOTATE_OBS)
@@ -1300,7 +1303,7 @@ m88k-tdep.o: m88k-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
mac-nat.o: mac-nat.c $(defs_h) gdb_string.h
-main.o: main.c top.h $(defs_h) gdb_string.h $(event_loop_h)
+main.o: main.c top.h $(defs_h) gdb_string.h $(event_loop_h) tui/tui-file.h
maint.o: maint.c $(defs_h) $(gdbcmd_h) $(gdbtypes_h) $(symtab_h) language.h \
$(expression_h) objfiles.h symfile.h
@@ -1602,6 +1605,10 @@ stabsread.o: stabsread.c $(bfd_h) $(INCLUDE_DIR)/aout/stab.def \
stack.o: stack.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) $(inferior_h) \
language.h target.h gdb_string.h
+gdb-file.o: gdb-file.c $(defs_h) gdb-file.h
+tui-file.o: $(srcdir)/tui/tui-file.c $(defs_h) $(srcdir)/tui/tui-file.h
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-file.c
+
ax-general.o: ax-general.c $(ax_h) $(defs_h) $(value_h)
ax-gdb.o: ax-gdb.c $(defs_h) $(symtab_h) symfile.h $(gdbtypes_h) \
$(value_h) $(expression_h) $(command_h) $(ax_h) $(gdbcmd_h) ax-gdb.h
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 71a000a..f10f661 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -1,5 +1,5 @@
/* Common target dependent code for GDB on ARM systems.
- Copyright 1988, 1989, 1991, 1992, 1993, 1995-1999
+ Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000
Free Software Foundation, Inc.
This file is part of GDB.
@@ -45,33 +45,33 @@ extern void _initialize_arm_tdep (void);
#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
/* Default register names as specified by APCS. */
-static char *apcs_register_names[] =
+static char * atpcs_register_names[] =
{"a1", "a2", "a3", "a4", /* 0 1 2 3 */
"v1", "v2", "v3", "v4", /* 4 5 6 7 */
- "v5", "v6", "sl", "fp", /* 8 9 10 11 */
- "ip", "sp", "lr", "pc", /* 12 13 14 15 */
+ "v5", "v6", "v7", "v8", /* 8 9 10 11 */
+ "IP", "SP", "LR", "PC", /* 12 13 14 15 */
"f0", "f1", "f2", "f3", /* 16 17 18 19 */
"f4", "f5", "f6", "f7", /* 20 21 22 23 */
- "fps", "ps"} /* 24 25 */ ;
+ "FPS", "PS" }; /* 24 25 */
/* Alternate set of registers names used by GCC. */
-static char *additional_register_names[] =
-{"r0", "r1", "r2", "r3", /* 0 1 2 3 */
- "r4", "r5", "r6", "r7", /* 4 5 6 7 */
- "r8", "r9", "r10", "r11", /* 8 9 10 11 */
- "r12", "r13", "r14", "pc", /* 12 13 14 15 */
- "f0", "f1", "f2", "f3", /* 16 17 18 19 */
- "f4", "f5", "f6", "f7", /* 20 21 22 23 */
- "fps", "ps"} /* 24 25 */ ;
+static char * additional_register_names[] =
+{"r0", "r1", "r2", "r3", /* 0 1 2 3 */
+ "r4", "r5", "r6", "r7", /* 4 5 6 7 */
+ "r8", "r9", "r10", "r11", /* 8 9 10 11 */
+ "r12", "sp", "lr", "pc", /* 12 13 14 15 */
+ "f0", "f1", "f2", "f3", /* 16 17 18 19 */
+ "f4", "f5", "f6", "f7", /* 20 21 22 23 */
+ "fps", "ps" }; /* 24 25 */
/* This is the variable that is set with "set disassembly-flavor".
By default use the APCS registers names. */
-char **arm_register_names = apcs_register_names;
+char ** arm_register_names = atpcs_register_names;
/* Valid register name flavours. */
static char apcs_flavor[] = "apcs";
static char r_prefix_flavor[] = "r-prefix";
-static char *valid_flavors[] =
+static char * valid_flavors[] =
{
apcs_flavor,
r_prefix_flavor,
@@ -296,24 +296,65 @@ arm_frameless_function_invocation (struct frame_info *fi)
add sp, sp, #-28
add r7, sp, #12
Sometimes the latter instruction may be replaced by:
- mov r7, sp
+ mov r7, sp
+
+ or like this:
+ push {r7, lr}
+ mov r7, sp
+ sub sp, #12
+
+ or, on tpcs, like this:
+ sub sp,#16
+ push {r7, lr}
+ (many instructions)
+ mov r7, sp
+ sub sp, #12
+
+ There is always one instruction of three classes:
+ 1 - push
+ 2 - setting of r7
+ 3 - adjusting of sp
+
+ When we have found at least one of each class we are done with the prolog.
+ Note that the "sub sp, #NN" before the push does not count.
*/
static CORE_ADDR
thumb_skip_prologue (CORE_ADDR pc)
{
CORE_ADDR current_pc;
+ int findmask = 0; /* findmask:
+ bit 0 - push { rlist }
+ bit 1 - mov r7, sp OR add r7, sp, #imm (setting of r7)
+ bit 2 - sub sp, #simm OR add sp, #simm (adjusting of sp)
+ */
- for (current_pc = pc; current_pc < pc + 20; current_pc += 2)
+ for (current_pc = pc; current_pc < pc + 40; current_pc += 2)
{
unsigned short insn = read_memory_unsigned_integer (current_pc, 2);
- if ((insn & 0xfe00) != 0xb400 /* push {..., r7, lr} */
- && (insn & 0xff00) != 0xb000 /* add sp, #simm */
- && (insn & 0xff00) != 0xaf00 /* add r7, sp, #imm */
- && insn != 0x466f /* mov r7, sp */
- && (insn & 0xffc0) != 0x4640) /* mov r0-r7, r8-r15 */
- break;
+ if ((insn & 0xfe00) == 0xb400) /* push { rlist } */
+ {
+ findmask |= 1; /* push found */
+ }
+ else if ((insn & 0xff00) == 0xb000) /* add sp, #simm OR sub sp, #simm */
+ {
+ if ((findmask & 1) == 0) /* before push ? */
+ continue;
+ else
+ findmask |= 4; /* add/sub sp found */
+ }
+ else if ((insn & 0xff00) == 0xaf00) /* add r7, sp, #imm */
+ {
+ findmask |= 2; /* setting of r7 found */
+ }
+ else if (insn == 0x466f) /* mov r7, sp */
+ {
+ findmask |= 2; /* setting of r7 found */
+ }
+ else
+ continue; /* something in the prolog that we don't care about or some
+ instruction from outside the prolog scheduled here for optimization */
}
return current_pc;
@@ -408,18 +449,18 @@ arm_skip_prologue (CORE_ADDR pc)
4) the offset from the stack pointer to the frame pointer
This information is stored in the "extra" fields of the frame_info.
- A typical Thumb function prologue might look like this:
- push {r7, lr}
- sub sp, #28,
- add r7, sp, #12
- Which would create this stack frame (offsets relative to FP)
+ A typical Thumb function prologue would create this stack frame
+ (offsets relative to FP)
old SP -> 24 stack parameters
20 LR
16 R7
R7 -> 0 local variables (16 bytes)
SP -> -12 additional stack space (12 bytes)
The frame size would thus be 36 bytes, and the frame offset would be
- 12 bytes. The frame register is R7. */
+ 12 bytes. The frame register is R7.
+
+ The comments for thumb_skip_prolog() describe the algorithm we use to detect
+ the end of the prolog */
/* *INDENT-ON* */
static void
@@ -429,6 +470,11 @@ thumb_scan_prologue (struct frame_info *fi)
CORE_ADDR prologue_end;
CORE_ADDR current_pc;
int saved_reg[16]; /* which register has been copied to register n? */
+ int findmask = 0; /* findmask:
+ bit 0 - push { rlist }
+ bit 1 - mov r7, sp OR add r7, sp, #imm (setting of r7)
+ bit 2 - sub sp, #simm OR add sp, #simm (adjusting of sp)
+ */
int i;
if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
@@ -452,10 +498,13 @@ thumb_scan_prologue (struct frame_info *fi)
saved_reg[i] = i;
/* Search the prologue looking for instructions that set up the
- frame pointer, adjust the stack pointer, and save registers. */
+ frame pointer, adjust the stack pointer, and save registers.
+ Do this until all basic prolog instructions are found. */
fi->framesize = 0;
- for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 2)
+ for (current_pc = prologue_start;
+ (current_pc < prologue_end) && ((findmask & 7) != 7);
+ current_pc += 2)
{
unsigned short insn;
int regno;
@@ -465,9 +514,11 @@ thumb_scan_prologue (struct frame_info *fi)
if ((insn & 0xfe00) == 0xb400) /* push { rlist } */
{
+ int mask;
+ findmask |= 1; /* push found */
/* Bits 0-7 contain a mask for registers R0-R7. Bit 8 says
whether to save LR (R14). */
- int mask = (insn & 0xff) | ((insn & 0x100) << 6);
+ mask = (insn & 0xff) | ((insn & 0x100) << 6);
/* Calculate offsets of saved R0-R7 and LR. */
for (regno = LR_REGNUM; regno >= 0; regno--)
@@ -478,20 +529,30 @@ thumb_scan_prologue (struct frame_info *fi)
saved_reg[regno] = regno; /* reset saved register map */
}
}
- else if ((insn & 0xff00) == 0xb000) /* add sp, #simm */
+ else if ((insn & 0xff00) == 0xb000) /* add sp, #simm OR sub sp, #simm */
{
+ if ((findmask & 1) == 0) /* before push ? */
+ continue;
+ else
+ findmask |= 4; /* add/sub sp found */
+
offset = (insn & 0x7f) << 2; /* get scaled offset */
- if (insn & 0x80) /* is it signed? */
- offset = -offset;
+ if (insn & 0x80) /* is it signed? (==subtracting) */
+ {
+ fi->frameoffset += offset;
+ offset = -offset;
+ }
fi->framesize -= offset;
}
else if ((insn & 0xff00) == 0xaf00) /* add r7, sp, #imm */
{
+ findmask |= 2; /* setting of r7 found */
fi->framereg = THUMB_FP_REGNUM;
fi->frameoffset = (insn & 0xff) << 2; /* get scaled offset */
}
- else if (insn == 0x466f) /* mov r7, sp */
+ else if (insn == 0x466f) /* mov r7, sp */
{
+ findmask |= 2; /* setting of r7 found */
fi->framereg = THUMB_FP_REGNUM;
fi->frameoffset = 0;
saved_reg[THUMB_FP_REGNUM] = SP_REGNUM;
@@ -503,7 +564,8 @@ thumb_scan_prologue (struct frame_info *fi)
saved_reg[lo_reg] = hi_reg; /* remember hi reg was saved */
}
else
- break; /* anything else isn't prologue */
+ continue; /* something in the prolog that we don't care about or some
+ instruction from outside the prolog scheduled here for optimization */
}
}
@@ -1170,7 +1232,10 @@ arm_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp,
val = (char *) &dbl_arg;
len = sizeof (double);
}
-#if 0
+#if 1
+ /* I don't know why this code was disable. The only logical use
+ for a function pointer is to call that function, so setting
+ the mode bit is perfectly fine. FN */
/* If the argument is a pointer to a function, and it is a Thumb
function, set the low bit of the pointer. */
if (TYPE_CODE_PTR == typecode
@@ -1278,14 +1343,12 @@ set_disassembly_flavor (void)
{
if (disassembly_flavor == apcs_flavor)
{
- if (arm_toggle_regnames () == 0)
- arm_toggle_regnames ();
- arm_register_names = apcs_register_names;
+ parse_arm_disassembler_option ("reg-names-atpcs");
+ arm_register_names = atpcs_register_names;
}
else if (disassembly_flavor == r_prefix_flavor)
{
- if (arm_toggle_regnames () == 1)
- arm_toggle_regnames ();
+ parse_arm_disassembler_option ("reg-names-std");
arm_register_names = additional_register_names;
}
}
@@ -1917,9 +1980,7 @@ _initialize_arm_tdep (void)
tm_print_insn = gdb_print_insn_arm;
/* Sync the opcode insn printer with our register viewer: */
-
- if (arm_toggle_regnames () != 1)
- arm_toggle_regnames ();
+ parse_arm_disassembler_option ("reg-names-atpcs");
/* Add the deprecated "othernames" command */
diff --git a/gdb/config/alpha/alpha-osf2.mh b/gdb/config/alpha/alpha-osf2.mh
index 8d9ea02..bb200d8 100644
--- a/gdb/config/alpha/alpha-osf2.mh
+++ b/gdb/config/alpha/alpha-osf2.mh
@@ -3,4 +3,4 @@ XDEPFILES=
XM_FILE= xm-alphaosf.h
NAT_FILE= nm-osf2.h
NATDEPFILES= infptrace.o inftarg.o corelow.o alpha-nat.o fork-child.o \
- osfsolib.o procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
+ osfsolib.o procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o
diff --git a/gdb/config/alpha/alpha-osf3.mh b/gdb/config/alpha/alpha-osf3.mh
index 63019b0..6de8bca 100644
--- a/gdb/config/alpha/alpha-osf3.mh
+++ b/gdb/config/alpha/alpha-osf3.mh
@@ -3,5 +3,5 @@ XDEPFILES=
XM_FILE= xm-alphaosf.h
NAT_FILE= nm-osf3.h
NATDEPFILES= infptrace.o inftarg.o corelow.o alpha-nat.o fork-child.o \
- osfsolib.o procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
+ osfsolib.o procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o
diff --git a/gdb/config/i386/i386dgux.mh b/gdb/config/i386/i386dgux.mh
index 2ac7972..ab8eab2 100644
--- a/gdb/config/i386/i386dgux.mh
+++ b/gdb/config/i386/i386dgux.mh
@@ -7,4 +7,4 @@ XM_CLIBS= -lsocket -lnsl
NAT_FILE= nm-i386v4.h
NATDEPFILES= corelow.o core-regset.o solib.o fork-child.o i386v4-nat.o \
- procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
+ procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o
diff --git a/gdb/config/i386/i386sol2.mh b/gdb/config/i386/i386sol2.mh
index 11077cb..f080429 100644
--- a/gdb/config/i386/i386sol2.mh
+++ b/gdb/config/i386/i386sol2.mh
@@ -5,4 +5,4 @@ XDEPFILES=
NAT_FILE= nm-i386sol2.h
NATDEPFILES= core-regset.o fork-child.o i386v4-nat.o corelow.o procfs.o \
- proc_api.o proc_events.o proc_flags.o proc_why.o
+ proc-api.o proc-events.o proc-flags.o proc-why.o
diff --git a/gdb/config/i386/i386v4.mh b/gdb/config/i386/i386v4.mh
index d7a2003..191b492 100644
--- a/gdb/config/i386/i386v4.mh
+++ b/gdb/config/i386/i386v4.mh
@@ -7,4 +7,4 @@ XM_CLIBS= -lsocket -lnsl
NAT_FILE= nm-i386v4.h
NATDEPFILES= corelow.o core-regset.o solib.o fork-child.o i386v4-nat.o \
- procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
+ procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o
diff --git a/gdb/config/i386/i386v42mp.mh b/gdb/config/i386/i386v42mp.mh
index 6db1035..185b5f0 100644
--- a/gdb/config/i386/i386v42mp.mh
+++ b/gdb/config/i386/i386v42mp.mh
@@ -9,5 +9,5 @@ XM_CLIBS= -lsocket -lnsl
# appropriate for i386v42mp
NAT_FILE= nm-i386v42mp.h
NATDEPFILES= corelow.o core-regset.o solib.o fork-child.o i386v4-nat.o \
- procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o uw-thread.o
+ procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o uw-thread.o
diff --git a/gdb/config/i386/ncr3000.mh b/gdb/config/i386/ncr3000.mh
index 7af5ecf..553c42c 100644
--- a/gdb/config/i386/ncr3000.mh
+++ b/gdb/config/i386/ncr3000.mh
@@ -14,4 +14,4 @@ XDEPFILES=
NAT_FILE= nm-i386v4.h
NATDEPFILES= corelow.o core-regset.o fork-child.o i386v4-nat.o procfs.o \
- proc_api.o proc_events.o proc_flags.o proc_why.o
+ proc-api.o proc-events.o proc-flags.o proc-why.o
diff --git a/gdb/config/i386/tm-i386gnu.h b/gdb/config/i386/tm-i386gnu.h
index aa34094..f25bce0 100644
--- a/gdb/config/i386/tm-i386gnu.h
+++ b/gdb/config/i386/tm-i386gnu.h
@@ -1,4 +1,4 @@
-/* Macro definitions for i386, GNU Hurd
+/* Macro definitions for i386 running the GNU Hurd.
Copyright (C) 1992, 1999 Free Software Foundation, Inc.
This file is part of GDB.
@@ -21,27 +21,27 @@
#ifndef TM_I386GNU_H
#define TM_I386GNU_H 1
-/* Include common definitions for gnu systems */
+/* Include common definitions for GNU systems.
+ FIXME: This does not belong here since this is supposed to contain
+ only native-dependent information. */
#include "nm-gnu.h"
/* Thread flavors used in re-setting the T bit.
- * @@ this is also bad for cross debugging.
- */
-#define THREAD_STATE_FLAVOR i386_THREAD_STATE
+ FIXME: This is native-dependent. */
+#define THREAD_STATE_FLAVOR i386_REGS_SEGS_STATE
#define THREAD_STATE_SIZE i386_THREAD_STATE_COUNT
#define THREAD_STATE_SET_TRACED(state) \
((struct i386_thread_state *)state)->efl |= 0x100
#define THREAD_STATE_CLEAR_TRACED(state) \
((((struct i386_thread_state *)state)->efl &= ~0x100), 1)
-/* we can do it */
+/* We can attach and detach.
+ FIXME: This is probably native-dependent too. */
#define ATTACH_DETACH 1
+#define HAVE_I387_REGS
#include "i386/tm-i386.h"
-#undef FLOAT_INFO
-#define FLOAT_INFO { i386_mach3_float_info (); }
-
/* Offset to saved PC in sigcontext. */
#define SIGCONTEXT_PC_OFFSET 68
diff --git a/gdb/config/m68k/m68kv4.mh b/gdb/config/m68k/m68kv4.mh
index 1ecf9bb..714f415 100644
--- a/gdb/config/m68k/m68kv4.mh
+++ b/gdb/config/m68k/m68kv4.mh
@@ -5,4 +5,4 @@ XDEPFILES=
NAT_FILE= nm-sysv4.h
NATDEPFILES= corelow.o core-regset.o solib.o fork-child.o procfs.o \
- proc_api.o proc_events.o proc_flags.o proc_why.o
+ proc-api.o proc-events.o proc-flags.o proc-why.o
diff --git a/gdb/config/m88k/delta88v4.mh b/gdb/config/m88k/delta88v4.mh
index cd26cad..5eec21a 100644
--- a/gdb/config/m88k/delta88v4.mh
+++ b/gdb/config/m88k/delta88v4.mh
@@ -5,4 +5,4 @@ XDEPFILES=
NAT_FILE= nm-delta88v4.h
NATDEPFILES= fork-child.o m88k-nat.o corelow.o core-regset.o solib.o \
- procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
+ procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o
diff --git a/gdb/config/mips/irix4.mh b/gdb/config/mips/irix4.mh
index ce27ed2..ad61b66 100644
--- a/gdb/config/mips/irix4.mh
+++ b/gdb/config/mips/irix4.mh
@@ -3,7 +3,7 @@ XDEPFILES= ser-tcp.o
XM_FILE= xm-irix4.h
NAT_FILE= nm-irix4.h
NATDEPFILES= fork-child.o irix4-nat.o corelow.o procfs.o \
- proc_api.o proc_events.o proc_flags.o proc_why.o
+ proc-api.o proc-events.o proc-flags.o proc-why.o
XM_CLIBS=-lbsd -lsun
diff --git a/gdb/config/mips/irix5.mh b/gdb/config/mips/irix5.mh
index 47d80f5..5413f41 100644
--- a/gdb/config/mips/irix5.mh
+++ b/gdb/config/mips/irix5.mh
@@ -3,6 +3,6 @@ XDEPFILES= ser-tcp.o
XM_FILE= xm-irix5.h
NAT_FILE= nm-irix5.h
NATDEPFILES= fork-child.o irix5-nat.o corelow.o procfs.o \
- proc_api.o proc_events.o proc_flags.o proc_why.o
+ proc-api.o proc-events.o proc-flags.o proc-why.o
XM_CLIBS=-lbsd -lsun
diff --git a/gdb/config/mips/mipsv4.mh b/gdb/config/mips/mipsv4.mh
index cea9883..ab8e239 100644
--- a/gdb/config/mips/mipsv4.mh
+++ b/gdb/config/mips/mipsv4.mh
@@ -2,4 +2,4 @@
XM_FILE= xm-mipsv4.h
NAT_FILE= ../nm-sysv4.h
NATDEPFILES= fork-child.o mipsv4-nat.o corelow.o core-regset.o solib.o \
- procfs.o proc_api.o proc_events.o proc_flags.o proc_why.o
+ procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o
diff --git a/gdb/config/powerpc/solaris.mh b/gdb/config/powerpc/solaris.mh
index efc3a1b..9c740ea 100644
--- a/gdb/config/powerpc/solaris.mh
+++ b/gdb/config/powerpc/solaris.mh
@@ -6,7 +6,7 @@ XM_CLIBS= -lsocket -lnsl
NAT_FILE= nm-solaris.h
NATDEPFILES= corelow.o core-sol2.o solib.o fork-child.o procfs.o \
- proc_api.o proc_events.o proc_flags.o proc_why.o
+ proc-api.o proc-events.o proc-flags.o proc-why.o
# If you are compiling with Sun's compiler, add the -xs option to CC
# (e.g. `make CC="cc -xs"').
diff --git a/gdb/defs.h b/gdb/defs.h
index ef4049d..8a40098 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -386,68 +386,7 @@ extern GDB_FILE *gdb_stdtarg;
#include "tuiWin.h"
#endif
-/* Create a generic gdb_file object with null methods. */
-
-extern struct gdb_file *gdb_file_new (void);
-
-/* Override methods used by specific implementations of a GDB_FILE
- object. */
-
-typedef void (gdb_file_flush_ftype) (struct gdb_file * stream);
-extern void set_gdb_file_flush (struct gdb_file *stream, gdb_file_flush_ftype * flush);
-
-/* NOTE: Both fputs and write methods are available. Default
- implementations that mapping one onto the other are included. */
-typedef void (gdb_file_write_ftype) (struct gdb_file * stream, const char *buf, long length_buf);
-extern void set_gdb_file_write (struct gdb_file *stream, gdb_file_write_ftype *fputs);
-
-typedef void (gdb_file_fputs_ftype) (const char *, struct gdb_file * stream);
-extern void set_gdb_file_fputs (struct gdb_file *stream, gdb_file_fputs_ftype * fputs);
-
-typedef int (gdb_file_isatty_ftype) (struct gdb_file * stream);
-extern void set_gdb_file_isatty (struct gdb_file *stream, gdb_file_isatty_ftype * isatty);
-
-typedef void (gdb_file_rewind_ftype) (struct gdb_file * stream);
-extern void set_gdb_file_rewind (struct gdb_file *stream, gdb_file_rewind_ftype * rewind);
-
-typedef void (gdb_file_put_method_ftype) (void *object, const char *buffer, long length_buffer);
-typedef void (gdb_file_put_ftype) (struct gdb_file *stream, gdb_file_put_method_ftype * method, void *context);
-extern void set_gdb_file_put (struct gdb_file *stream, gdb_file_put_ftype * put);
-
-typedef void (gdb_file_delete_ftype) (struct gdb_file * stream);
-extern void set_gdb_file_data (struct gdb_file *stream, void *data, gdb_file_delete_ftype * delete);
-
-extern void *gdb_file_data (struct gdb_file *file);
-
-
-/* Open the specified FILE as a gdb_file. */
-extern struct gdb_file *stdio_fileopen (FILE *file);
-
-/* Open NAME returning a GDB_FILE. */
-extern GDB_FILE *gdb_fopen (char *name, char *mode);
-
-/* Create/open a memory based file. Can be used as a scratch
- buffer for collecting output. */
-extern struct gdb_file *mem_fileopen (void);
-
-extern void gdb_flush (GDB_FILE *);
-
-extern void gdb_file_delete (struct gdb_file *stream);
-
-extern void gdb_file_rewind (struct gdb_file *stream);
-
-extern int gdb_file_isatty (GDB_FILE *);
-
-extern void gdb_file_write (struct gdb_file *file, const char *buf, long length_buf);
-
-/* NOTE: copies left to right */
-extern void gdb_file_put (struct gdb_file *src, gdb_file_put_method_ftype *write, void *dest);
-
-/* Returns a freshly allocated buffer containing the entire contents
- of FILE (as determined by gdb_file_put()) with a NUL character
- appended. LENGTH is set to the size of the buffer minus that
- appended NUL. */
-extern char *gdb_file_xstrdup (struct gdb_file *file, long *length);
+#include "gdb-file.h"
/* More generic printf like operations */
@@ -487,14 +426,6 @@ extern void fprintf_unfiltered (GDB_FILE *, const char *, ...) ATTR_FORMAT (prin
extern void printf_unfiltered (const char *, ...) ATTR_FORMAT (printf, 1, 2);
-/* #if defined (TUI) */
-/* DEPRECATED: Only the TUI should use these methods. */
-extern struct gdb_file *tui_fileopen (FILE *);
-extern struct gdb_file *tui_sfileopen (int);
-extern char *tui_file_get_strbuf (struct gdb_file *);
-extern void tui_file_adjust_strbuf (int, struct gdb_file *);
-/* #endif */
-
extern void print_spaces (int, GDB_FILE *);
extern void print_spaces_filtered (int, GDB_FILE *);
@@ -1199,11 +1130,6 @@ extern void (*show_load_progress) (const char *section,
unsigned long section_size,
unsigned long total_sent,
unsigned long total_size);
-/* NOTE: cagney/1999-10-14: fputs_unfiltered_hook is deprecated.
- Instead code wanting to control GDB's output should be overriding
- the gdb_std* files. */
-extern void (*fputs_unfiltered_hook) (const char *linebuffer,
- GDB_FILE * stream);
extern void (*print_frame_info_listing_hook) (struct symtab * s,
int line, int stopline,
int noerror);
diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo
index 21ec1e3..db293ef 100644
--- a/gdb/doc/gdbint.texinfo
+++ b/gdb/doc/gdbint.texinfo
@@ -1545,6 +1545,39 @@ A function that inserts or removes (dependant on
the next instruction. See @code{sparc-tdep.c} and @code{rs6000-tdep.c}
for examples.
+@item SOFUN_ADDRESS_MAYBE_MISSING
+
+Somebody clever observed that, the more actual addresses you have in the
+debug information, the more time the linker has to spend relocating
+them. So whenever there's some other way the debugger could find the
+address it needs, you should omit it from the debug info, to make
+linking faster.
+
+@code{SOFUN_ADDRESS_MAYBE_MISSING} indicates that a particular set of
+hacks of this sort are in use, affecting @code{N_SO} and @code{N_FUN}
+entries in stabs-format debugging information. @code{N_SO} stabs mark
+the beginning and ending addresses of compilation units in the text
+segment. @code{N_FUN} stabs mark the starts and ends of functions.
+
+@code{SOFUN_ADDRESS_MAYBE_MISSING} means two things:
+@itemize @bullet
+
+@item
+@code{N_FUN} stabs have an address of zero. Instead, you should find the
+addresses where the function starts by taking the function name from
+the stab, and then looking that up in the minsyms (the linker/
+assembler symbol table). In other words, the stab has the name, and
+the linker / assembler symbol table is the only place that carries
+the address.
+
+@item
+@code{N_SO} stabs have an address of zero, too. You just look at the
+@code{N_FUN} stabs that appear before and after the @code{N_SO} stab,
+and guess the starting and ending addresses of the compilation unit from
+them.
+
+@end itemize
+
@item PCC_SOL_BROKEN
(Used only in the Convex target.)
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 163e9f7..4a5a3a0 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -1454,6 +1454,10 @@ value_from_register (type, regnum, frame)
CHECK_TYPEDEF (type);
len = TYPE_LENGTH (type);
+ /* Pointers on D10V are really only 16 bits, but we lie to gdb elsewhere... */
+ if (GDB_TARGET_IS_D10V && TYPE_CODE (type) == TYPE_CODE_PTR)
+ len = 2;
+
VALUE_REGNO (v) = regnum;
num_storage_locs = (len > REGISTER_VIRTUAL_SIZE (regnum) ?
@@ -1652,6 +1656,29 @@ value_from_register (type, regnum, frame)
memcpy (VALUE_CONTENTS_RAW (v), raw_buffer + VALUE_OFFSET (v), len);
}
+ if (GDB_TARGET_IS_D10V
+ && TYPE_CODE (type) == TYPE_CODE_PTR
+ && TYPE_TARGET_TYPE (type)
+ && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC))
+ {
+ /* pointer to function */
+ unsigned long num;
+ unsigned short snum;
+ snum = (unsigned short) extract_unsigned_integer (VALUE_CONTENTS_RAW (v), 2);
+ num = D10V_MAKE_IADDR (snum);
+ store_address (VALUE_CONTENTS_RAW (v), 4, num);
+ }
+ else if (GDB_TARGET_IS_D10V
+ && TYPE_CODE (type) == TYPE_CODE_PTR)
+ {
+ /* pointer to data */
+ unsigned long num;
+ unsigned short snum;
+ snum = (unsigned short) extract_unsigned_integer (VALUE_CONTENTS_RAW (v), 2);
+ num = D10V_MAKE_DADDR (snum);
+ store_address (VALUE_CONTENTS_RAW (v), 4, num);
+ }
+
return v;
}
diff --git a/gdb/gdb-file.c b/gdb/gdb-file.c
new file mode 100644
index 0000000..88d550a
--- /dev/null
+++ b/gdb/gdb-file.c
@@ -0,0 +1,511 @@
+/* GDB_FILE - a generic STDIO like output stream.
+ Copyright (C) 1999, 2000 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* Implement the ``struct gdb_file'' object. */
+
+#include "defs.h"
+#include "gdb-file.h"
+
+#undef XMALLOC
+#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
+
+static gdb_file_isatty_ftype null_file_isatty;
+static gdb_file_write_ftype null_file_write;
+static gdb_file_fputs_ftype null_file_fputs;
+static gdb_file_flush_ftype null_file_flush;
+static gdb_file_delete_ftype null_file_delete;
+static gdb_file_rewind_ftype null_file_rewind;
+static gdb_file_put_ftype null_file_put;
+
+struct gdb_file
+ {
+ int *magic;
+ gdb_file_flush_ftype *to_flush;
+ gdb_file_write_ftype *to_write;
+ gdb_file_fputs_ftype *to_fputs;
+ gdb_file_delete_ftype *to_delete;
+ gdb_file_isatty_ftype *to_isatty;
+ gdb_file_rewind_ftype *to_rewind;
+ gdb_file_put_ftype *to_put;
+ void *to_data;
+ };
+int gdb_file_magic;
+
+struct gdb_file *
+gdb_file_new ()
+{
+ struct gdb_file *file = xmalloc (sizeof (struct gdb_file));
+ file->magic = &gdb_file_magic;
+ set_gdb_file_data (file, NULL, null_file_delete);
+ set_gdb_file_flush (file, null_file_flush);
+ set_gdb_file_write (file, null_file_write);
+ set_gdb_file_fputs (file, null_file_fputs);
+ set_gdb_file_isatty (file, null_file_isatty);
+ set_gdb_file_rewind (file, null_file_rewind);
+ set_gdb_file_put (file, null_file_put);
+ return file;
+}
+
+void
+gdb_file_delete (file)
+ struct gdb_file *file;
+{
+ file->to_delete (file);
+ free (file);
+}
+
+static int
+null_file_isatty (file)
+ struct gdb_file *file;
+{
+ return 0;
+}
+
+static void
+null_file_rewind (file)
+ struct gdb_file *file;
+{
+ return;
+}
+
+static void
+null_file_put (struct gdb_file *file,
+ gdb_file_put_method_ftype *write,
+ void *dest)
+{
+ return;
+}
+
+static void
+null_file_flush (file)
+ struct gdb_file *file;
+{
+ return;
+}
+
+static void
+null_file_write (struct gdb_file *file,
+ const char *buf,
+ long sizeof_buf)
+{
+ if (file->to_fputs == null_file_fputs)
+ /* Both the write and fputs methods are null. Discard the
+ request. */
+ return;
+ else
+ {
+ /* The fputs method isn't null, slowly pass the write request
+ onto that. FYI, this isn't as bad as it may look - the
+ current (as of 1999-11-07) printf_* function calls fputc and
+ fputc does exactly the below. By having a write function it
+ is possible to clean up that code. */
+ int i;
+ char b[2];
+ b[1] = '\0';
+ for (i = 0; i < sizeof_buf; i++)
+ {
+ b[0] = buf[i];
+ file->to_fputs (b, file);
+ }
+ return;
+ }
+}
+
+static void
+null_file_fputs (buf, file)
+ const char *buf;
+ struct gdb_file *file;
+{
+ if (file->to_write == null_file_write)
+ /* Both the write and fputs methods are null. Discard the
+ request. */
+ return;
+ else
+ {
+ /* The write method was implemented, use that. */
+ file->to_write (file, buf, strlen (buf));
+ }
+}
+
+static void
+null_file_delete (file)
+ struct gdb_file *file;
+{
+ return;
+}
+
+void *
+gdb_file_data (file)
+ struct gdb_file *file;
+{
+ if (file->magic != &gdb_file_magic)
+ internal_error ("gdb_file_data: bad magic number");
+ return file->to_data;
+}
+
+void
+gdb_flush (file)
+ struct gdb_file *file;
+{
+ file->to_flush (file);
+}
+
+int
+gdb_file_isatty (file)
+ struct gdb_file *file;
+{
+ return file->to_isatty (file);
+}
+
+void
+gdb_file_rewind (file)
+ struct gdb_file *file;
+{
+ file->to_rewind (file);
+}
+
+void
+gdb_file_put (struct gdb_file *file,
+ gdb_file_put_method_ftype *write,
+ void *dest)
+{
+ file->to_put (file, write, dest);
+}
+
+void
+gdb_file_write (struct gdb_file *file,
+ const char *buf,
+ long length_buf)
+{
+ file->to_write (file, buf, length_buf);
+}
+
+void
+fputs_unfiltered (buf, file)
+ const char *buf;
+ struct gdb_file *file;
+{
+ file->to_fputs (buf, file);
+}
+
+void
+set_gdb_file_flush (file, flush)
+ struct gdb_file *file;
+ gdb_file_flush_ftype *flush;
+{
+ file->to_flush = flush;
+}
+
+void
+set_gdb_file_isatty (file, isatty)
+ struct gdb_file *file;
+ gdb_file_isatty_ftype *isatty;
+{
+ file->to_isatty = isatty;
+}
+
+void
+set_gdb_file_rewind (file, rewind)
+ struct gdb_file *file;
+ gdb_file_rewind_ftype *rewind;
+{
+ file->to_rewind = rewind;
+}
+
+void
+set_gdb_file_put (file, put)
+ struct gdb_file *file;
+ gdb_file_put_ftype *put;
+{
+ file->to_put = put;
+}
+
+void
+set_gdb_file_write (struct gdb_file *file,
+ gdb_file_write_ftype *write)
+{
+ file->to_write = write;
+}
+
+void
+set_gdb_file_fputs (file, fputs)
+ struct gdb_file *file;
+ gdb_file_fputs_ftype *fputs;
+{
+ file->to_fputs = fputs;
+}
+
+void
+set_gdb_file_data (file, data, delete)
+ struct gdb_file *file;
+ void *data;
+ gdb_file_delete_ftype *delete;
+{
+ file->to_data = data;
+ file->to_delete = delete;
+}
+
+/* gdb_file utility function for converting a ``struct gdb_file'' into
+ a memory buffer''. */
+
+struct accumulated_gdb_file
+{
+ char *buffer;
+ long length;
+};
+
+static void
+do_gdb_file_xstrdup (void *context, const char *buffer, long length)
+{
+ struct accumulated_gdb_file *acc = context;
+ if (acc->buffer == NULL)
+ acc->buffer = xmalloc (length + 1);
+ else
+ acc->buffer = xrealloc (acc->buffer, acc->length + length + 1);
+ memcpy (acc->buffer + acc->length, buffer, length);
+ acc->length += length;
+ acc->buffer[acc->length] = '\0';
+}
+
+char *
+gdb_file_xstrdup (struct gdb_file *file,
+ long *length)
+{
+ struct accumulated_gdb_file acc;
+ acc.buffer = NULL;
+ acc.length = 0;
+ gdb_file_put (file, do_gdb_file_xstrdup, &acc);
+ if (acc.buffer == NULL)
+ acc.buffer = xstrdup ("");
+ *length = acc.length;
+ return acc.buffer;
+}
+
+/* A pure memory based ``struct gdb_file'' that can be used an output
+ buffer. The buffers accumulated contents are available via
+ gdb_file_put(). */
+
+struct mem_file
+ {
+ int *magic;
+ char *buffer;
+ int sizeof_buffer;
+ int length_buffer;
+ };
+
+static gdb_file_rewind_ftype mem_file_rewind;
+static gdb_file_put_ftype mem_file_put;
+static gdb_file_write_ftype mem_file_write;
+static gdb_file_delete_ftype mem_file_delete;
+static struct gdb_file *mem_file_new PARAMS ((void));
+static int mem_file_magic;
+
+static struct gdb_file *
+mem_file_new (void)
+{
+ struct mem_file *stream = XMALLOC (struct mem_file);
+ struct gdb_file *file = gdb_file_new ();
+ set_gdb_file_data (file, stream, mem_file_delete);
+ set_gdb_file_rewind (file, mem_file_rewind);
+ set_gdb_file_put (file, mem_file_put);
+ set_gdb_file_write (file, mem_file_write);
+ stream->magic = &mem_file_magic;
+ stream->buffer = NULL;
+ stream->sizeof_buffer = 0;
+ stream->length_buffer = 0;
+ return file;
+}
+
+static void
+mem_file_delete (struct gdb_file *file)
+{
+ struct mem_file *stream = gdb_file_data (file);
+ if (stream->magic != &mem_file_magic)
+ internal_error ("mem_file_delete: bad magic number");
+ if (stream->buffer != NULL)
+ free (stream->buffer);
+ free (stream);
+}
+
+struct gdb_file *
+mem_fileopen (void)
+{
+ return mem_file_new ();
+}
+
+static void
+mem_file_rewind (struct gdb_file *file)
+{
+ struct mem_file *stream = gdb_file_data (file);
+ if (stream->magic != &mem_file_magic)
+ internal_error ("mem_file_rewind: bad magic number");
+ stream->length_buffer = 0;
+}
+
+static void
+mem_file_put (struct gdb_file *file,
+ gdb_file_put_method_ftype *write,
+ void *dest)
+{
+ struct mem_file *stream = gdb_file_data (file);
+ if (stream->magic != &mem_file_magic)
+ internal_error ("mem_file_put: bad magic number");
+ if (stream->length_buffer > 0)
+ write (dest, stream->buffer, stream->length_buffer);
+}
+
+void
+mem_file_write (struct gdb_file *file,
+ const char *buffer,
+ long length_buffer)
+{
+ struct mem_file *stream = gdb_file_data (file);
+ if (stream->magic != &mem_file_magic)
+ internal_error ("mem_file_write: bad magic number");
+ if (stream->buffer == NULL)
+ {
+ stream->length_buffer = length_buffer;
+ stream->sizeof_buffer = length_buffer;
+ stream->buffer = xmalloc (stream->sizeof_buffer);
+ memcpy (stream->buffer, buffer, length_buffer);
+ }
+ else
+ {
+ int new_length = stream->length_buffer + length_buffer;
+ if (new_length >= stream->sizeof_buffer)
+ {
+ stream->sizeof_buffer = new_length;
+ stream->buffer = xrealloc (stream->buffer, stream->sizeof_buffer);
+ }
+ memcpy (stream->buffer + stream->length_buffer, buffer, length_buffer);
+ stream->length_buffer = new_length;
+ }
+}
+
+/* ``struct gdb_file'' implementation that maps directly onto
+ <stdio.h>'s FILE. */
+
+static gdb_file_write_ftype stdio_file_write;
+static gdb_file_fputs_ftype stdio_file_fputs;
+static gdb_file_isatty_ftype stdio_file_isatty;
+static gdb_file_delete_ftype stdio_file_delete;
+static struct gdb_file *stdio_file_new PARAMS ((FILE * file, int close_p));
+static gdb_file_flush_ftype stdio_file_flush;
+
+static int stdio_file_magic;
+
+struct stdio_file
+ {
+ int *magic;
+ FILE *file;
+ int close_p;
+ };
+
+static struct gdb_file *
+stdio_file_new (file, close_p)
+ FILE *file;
+ int close_p;
+{
+ struct gdb_file *gdb_file = gdb_file_new ();
+ struct stdio_file *stdio = xmalloc (sizeof (struct stdio_file));
+ stdio->magic = &stdio_file_magic;
+ stdio->file = file;
+ stdio->close_p = close_p;
+ set_gdb_file_data (gdb_file, stdio, stdio_file_delete);
+ set_gdb_file_flush (gdb_file, stdio_file_flush);
+ set_gdb_file_write (gdb_file, stdio_file_write);
+ set_gdb_file_fputs (gdb_file, stdio_file_fputs);
+ set_gdb_file_isatty (gdb_file, stdio_file_isatty);
+ return gdb_file;
+}
+
+static void
+stdio_file_delete (file)
+ struct gdb_file *file;
+{
+ struct stdio_file *stdio = gdb_file_data (file);
+ if (stdio->magic != &stdio_file_magic)
+ internal_error ("stdio_file_delete: bad magic number");
+ if (stdio->close_p)
+ {
+ fclose (stdio->file);
+ }
+ free (stdio);
+}
+
+static void
+stdio_file_flush (file)
+ struct gdb_file *file;
+{
+ struct stdio_file *stdio = gdb_file_data (file);
+ if (stdio->magic != &stdio_file_magic)
+ internal_error ("stdio_file_flush: bad magic number");
+ fflush (stdio->file);
+}
+
+static void
+stdio_file_write (struct gdb_file *file, const char *buf, long length_buf)
+{
+ struct stdio_file *stdio = gdb_file_data (file);
+ if (stdio->magic != &stdio_file_magic)
+ internal_error ("stdio_file_write: bad magic number");
+ fwrite (buf, length_buf, 1, stdio->file);
+}
+
+static void
+stdio_file_fputs (linebuffer, file)
+ const char *linebuffer;
+ struct gdb_file *file;
+{
+ struct stdio_file *stdio = gdb_file_data (file);
+ if (stdio->magic != &stdio_file_magic)
+ internal_error ("stdio_file_fputs: bad magic number");
+ fputs (linebuffer, stdio->file);
+}
+
+static int
+stdio_file_isatty (file)
+ struct gdb_file *file;
+{
+ struct stdio_file *stdio = gdb_file_data (file);
+ if (stdio->magic != &stdio_file_magic)
+ internal_error ("stdio_file_isatty: bad magic number");
+ return (isatty (fileno (stdio->file)));
+}
+
+/* Like fdopen(). Create a gdb_file from a previously opened FILE. */
+
+struct gdb_file *
+stdio_fileopen (file)
+ FILE *file;
+{
+ return stdio_file_new (file, 0);
+}
+
+GDB_FILE *
+gdb_fopen (name, mode)
+ char *name;
+ char *mode;
+{
+ FILE *f = fopen (name, mode);
+ if (f == NULL)
+ return NULL;
+ return stdio_file_new (f, 1);
+}
diff --git a/gdb/gdb-file.h b/gdb/gdb-file.h
new file mode 100644
index 0000000..90b9774
--- /dev/null
+++ b/gdb/gdb-file.h
@@ -0,0 +1,93 @@
+/* GDB_FILE - a generic STDIO like output stream.
+ Copyright (C) 1999, 2000 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef GDB_FILE_H
+#define GDB_FILE_H
+
+struct gdb_file;
+
+/* Create a generic gdb_file object with null methods. */
+
+extern struct gdb_file *gdb_file_new (void);
+
+/* Override methods used by specific implementations of a GDB_FILE
+ object. */
+
+typedef void (gdb_file_flush_ftype) (struct gdb_file * stream);
+extern void set_gdb_file_flush (struct gdb_file *stream, gdb_file_flush_ftype * flush);
+
+/* NOTE: Both fputs and write methods are available. Default
+ implementations that mapping one onto the other are included. */
+typedef void (gdb_file_write_ftype) (struct gdb_file * stream, const char *buf, long length_buf);
+extern void set_gdb_file_write (struct gdb_file *stream, gdb_file_write_ftype *fputs);
+
+typedef void (gdb_file_fputs_ftype) (const char *, struct gdb_file * stream);
+extern void set_gdb_file_fputs (struct gdb_file *stream, gdb_file_fputs_ftype * fputs);
+
+typedef int (gdb_file_isatty_ftype) (struct gdb_file * stream);
+extern void set_gdb_file_isatty (struct gdb_file *stream, gdb_file_isatty_ftype * isatty);
+
+typedef void (gdb_file_rewind_ftype) (struct gdb_file * stream);
+extern void set_gdb_file_rewind (struct gdb_file *stream, gdb_file_rewind_ftype * rewind);
+
+typedef void (gdb_file_put_method_ftype) (void *object, const char *buffer, long length_buffer);
+typedef void (gdb_file_put_ftype) (struct gdb_file *stream, gdb_file_put_method_ftype * method, void *context);
+extern void set_gdb_file_put (struct gdb_file *stream, gdb_file_put_ftype * put);
+
+typedef void (gdb_file_delete_ftype) (struct gdb_file * stream);
+extern void set_gdb_file_data (struct gdb_file *stream, void *data, gdb_file_delete_ftype * delete);
+
+extern void *gdb_file_data (struct gdb_file *file);
+
+
+extern void gdb_flush (struct gdb_file *);
+
+extern void gdb_file_delete (struct gdb_file *stream);
+
+extern void gdb_file_rewind (struct gdb_file *stream);
+
+extern int gdb_file_isatty (struct gdb_file *);
+
+extern void gdb_file_write (struct gdb_file *file, const char *buf, long length_buf);
+
+/* NOTE: copies left to right */
+extern void gdb_file_put (struct gdb_file *src, gdb_file_put_method_ftype *write, void *dest);
+
+/* Returns a freshly allocated buffer containing the entire contents
+ of FILE (as determined by gdb_file_put()) with a NUL character
+ appended. LENGTH is set to the size of the buffer minus that
+ appended NUL. */
+extern char *gdb_file_xstrdup (struct gdb_file *file, long *length);
+
+
+
+/* Create/open a memory based file. Can be used as a scratch buffer
+ for collecting output. */
+extern struct gdb_file *mem_fileopen (void);
+
+
+
+/* Open/create a an STDIO based GDB_FILE using the already open FILE. */
+extern struct gdb_file *stdio_fileopen (FILE *file);
+
+/* Open NAME returning an STDIO based GDB_FILE. */
+extern GDB_FILE *gdb_fopen (char *name, char *mode);
+
+#endif
diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c
index de5631b..9ae9484 100644
--- a/gdb/gnu-nat.c
+++ b/gdb/gnu-nat.c
@@ -1,4 +1,4 @@
-/* Interface GDB to the GNU Hurd
+/* Interface GDB to the GNU Hurd.
Copyright (C) 1992, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
This file is part of GDB.
@@ -88,7 +88,6 @@ int gnu_debug_flag = 0;
extern struct target_ops gnu_ops;
-int inf_update_procs (struct inf *inf);
struct inf *make_inf ();
void inf_clear_wait (struct inf *inf);
void inf_cleanup (struct inf *inf);
@@ -116,7 +115,6 @@ void inf_continue (struct inf *inf);
debug ("{inf %d %p}: " msg, __inf->pid, __inf , ##args); } while (0)
void proc_abort (struct proc *proc, int force);
-thread_state_t proc_get_state (struct proc *proc, int force);
struct proc *make_proc (struct inf *inf, mach_port_t port, int tid);
struct proc *_proc_free (struct proc *proc);
int proc_update_sc (struct proc *proc);
@@ -126,7 +124,6 @@ static mach_port_t _proc_get_exc_port (struct proc *proc);
void proc_steal_exc_port (struct proc *proc, mach_port_t exc_port);
void proc_restore_exc_port (struct proc *proc);
int proc_trace (struct proc *proc, int set);
-char *proc_string (struct proc *proc);
/* Evaluate RPC_EXPR in a scope with the variables MSGPORT and REFPORT bound
to INF's msg port and task port respectively. If it has no msg port,
diff --git a/gdb/gnu-nat.h b/gdb/gnu-nat.h
index 8cc6c12..f2f0f02 100644
--- a/gdb/gnu-nat.h
+++ b/gdb/gnu-nat.h
@@ -31,6 +31,9 @@ extern struct inf *current_inferior;
/* Converts a GDB pid to a struct proc. */
struct proc *inf_tid_to_thread (struct inf *inf, int tid);
+/* Makes sure that INF's thread list is synced with the actual process. */
+int inf_update_procs (struct inf *inf);
+
/* A proc is either a thread, or the task (there can only be one task proc
because it always has the same TID, PROC_TID_TASK). */
struct proc
@@ -75,8 +78,15 @@ struct proc
extern int __proc_pid (struct proc *proc);
+/* Make sure that the state field in PROC is up to date, and return a
+ pointer to it, or 0 if something is wrong. If WILL_MODIFY is true,
+ makes sure that the thread is stopped and aborted first, and sets
+ the state_changed field in PROC to true. */
extern thread_state_t proc_get_state (struct proc *proc, int will_modify);
+/* Return printable description of proc. */
+extern char *proc_string (struct proc *proc);
+
#define proc_debug(_proc, msg, args...) \
do { struct proc *__proc = (_proc); \
debug ("{proc %d/%d %p}: " msg, \
diff --git a/gdb/i386gnu-nat.c b/gdb/i386gnu-nat.c
index 6834ea0..bc13229 100644
--- a/gdb/i386gnu-nat.c
+++ b/gdb/i386gnu-nat.c
@@ -1,4 +1,4 @@
-/* Low level interface to I386 running the GNU Hurd
+/* Low level interface to i386 running the GNU Hurd.
Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
This file is part of GDB.
@@ -22,36 +22,41 @@
#include "inferior.h"
#include "floatformat.h"
+#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include <mach.h>
+#include <mach_error.h>
#include <mach/message.h>
#include <mach/exception.h>
-#include <mach_error.h>
#include "gnu-nat.h"
-/* Hmmm... Should this not be here?
- * Now for i386_float_info() target_has_execution
- */
-#include <target.h>
+/* The FPU hardware state. */
+struct env387
+{
+ unsigned short control;
+ unsigned short r0;
+ unsigned short status;
+ unsigned short r1;
+ unsigned short tag;
+ unsigned short r2;
+ unsigned long eip;
+ unsigned short code_seg;
+ unsigned short opcode;
+ unsigned long operand;
+ unsigned short operand_seg;
+ unsigned short r3;
+ unsigned char regs[8][10];
+};
-/* @@@ Should move print_387_status() to i387-tdep.c */
-extern void print_387_control_word (); /* i387-tdep.h */
-extern void print_387_status_word ();
-/* Find offsets to thread states at compile time.
- * If your compiler does not grok this, calculate offsets
- * offsets yourself and use them (or get a compatible compiler :-)
- */
-
-#define REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg)
-
-/* at reg_offset[i] is the offset to the i386_thread_state
- * location where the gdb registers[i] is stored.
- */
+/* Offset to the thread_state_t location where REG is stored. */
+#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
+/* At reg_offset[i] is the offset to the thread_state_t location where
+ the gdb registers[i] is stored. */
static int reg_offset[] =
{
REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
@@ -60,309 +65,268 @@ static int reg_offset[] =
REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
};
-#define REG_ADDR(state,regnum) ((char *)(state)+reg_offset[regnum])
-
-/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
- * Caller knows that the regs handled in one transaction are of same size.
- */
-#define FETCH_REGS(state, regnum, count) \
- memcpy (&registers[REGISTER_BYTE (regnum)], \
- REG_ADDR (state, regnum), \
- count * REGISTER_RAW_SIZE (regnum))
-
-/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
-#define STORE_REGS(state, regnum, count) \
- memcpy (REG_ADDR (state, regnum), \
- &registers[REGISTER_BYTE (regnum)], \
- count * REGISTER_RAW_SIZE (regnum))
+#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
+
-/*
- * Fetch inferiors registers for gdb.
- * REG specifies which (as gdb views it) register, -1 for all.
- */
-void
-gnu_fetch_registers (int reg)
+/* Get the whole floating-point state of THREAD and record the
+ values of the corresponding (pseudo) registers. */
+static void
+fetch_fpregs (struct proc *thread)
{
- struct proc *thread;
- thread_state_t state;
-
- inf_update_procs (current_inferior); /* Make sure we know about new threads. */
-
- thread = inf_tid_to_thread (current_inferior, inferior_pid);
- if (!thread)
- error ("fetch inferior registers: %d: Invalid thread", inferior_pid);
-
- state = proc_get_state (thread, 0);
+ mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
+ struct i386_float_state state;
+ struct env387 *ep = (struct env387 *) state.hw_state;
+ error_t err;
+ int i;
- if (!state)
- warning ("Couldn't fetch register %s from %s (invalid thread).",
- REGISTER_NAME (reg), proc_string (thread));
- else if (reg >= 0)
+ err = thread_get_state (thread->port, i386_FLOAT_STATE,
+ (thread_state_t) &state, &count);
+ if (err)
{
- proc_debug (thread, "fetching register: %s", REGISTER_NAME (reg));
- supply_register (reg, REG_ADDR (state, reg));
- thread->fetched_regs |= (1 << reg);
+ warning ("Couldn't fetch floating-point state from %s",
+ proc_string (thread));
+ return;
}
- else
+
+ if (! state.initialized)
+ /* The floating-point state isn't initialized. */
{
- proc_debug (thread, "fetching all registers");
- for (reg = 0; reg < NUM_REGS; reg++)
- supply_register (reg, REG_ADDR (state, reg));
- thread->fetched_regs = ~0;
+ for (i = FP0_REGNUM; i <= FP7_REGNUM; i++)
+ supply_register (i, NULL);
+ for (i = FIRST_FPU_CTRL_REGNUM; i <= LAST_FPU_CTRL_REGNUM; i++)
+ supply_register (i, NULL);
+
+ return;
}
+
+ /* Supply the floating-point registers. */
+ for (i = 0; i < 8; i++)
+ supply_register (FP0_REGNUM + i, ep->regs[i]);
+
+ supply_register (FCTRL_REGNUM, (char *) &ep->control);
+ supply_register (FSTAT_REGNUM, (char *) &ep->status);
+ supply_register (FTAG_REGNUM, (char *) &ep->tag);
+ supply_register (FCOFF_REGNUM, (char *) &ep->eip);
+ supply_register (FDS_REGNUM, (char *) &ep->operand_seg);
+ supply_register (FDOFF_REGNUM, (char *) &ep->operand);
+
+ /* Store the code segment and opcode pseudo registers. */
+ {
+ long l;
+
+ l = ep->code_seg;
+ supply_register (FCS_REGNUM, (char *) &l);
+ l = ep->opcode & ((1 << 11) - 1);
+ supply_register (FOP_REGNUM, (char *) &l);
+ }
}
-
-/* Store our register values back into the inferior.
- * If REG is -1, do this for all registers.
- * Otherwise, REG specifies which register
- *
- * On mach3 all registers are always saved in one call.
- */
+
+/* Fetch register REGNO, or all regs if REGNO is -1. */
void
-gnu_store_registers (reg)
- int reg;
+gnu_fetch_registers (int regno)
{
struct proc *thread;
- int was_aborted, was_valid;
- thread_state_t state;
- thread_state_data_t old_state;
- inf_update_procs (current_inferior); /* Make sure we know about new threads. */
+ /* Make sure we know about new threads. */
+ inf_update_procs (current_inferior);
thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (!thread)
- error ("store inferior registers: %d: Invalid thread", inferior_pid);
-
- proc_debug (thread, "storing register %s.", REGISTER_NAME (reg));
+ error ("Can't fetch registers from thread %d: No such thread",
+ inferior_pid);
- was_aborted = thread->aborted;
- was_valid = thread->state_valid;
- if (!was_aborted && was_valid)
- bcopy (&thread->state, &old_state, sizeof (old_state));
-
- state = proc_get_state (thread, 1);
-
- if (!state)
- warning ("Couldn't store register %s from %s (invalid thread).",
- REGISTER_NAME (reg), proc_string (thread));
- else
+ if (regno < NUM_GREGS || regno == -1)
{
- if (!was_aborted && was_valid)
- /* See which registers have changed after aborting the thread. */
+ thread_state_t state;
+
+ /* This does the dirty work for us. */
+ state = proc_get_state (thread, 0);
+ if (!state)
{
- int check_reg;
- for (check_reg = 0; check_reg < NUM_REGS; check_reg++)
- if ((thread->fetched_regs & (1 << check_reg))
- && bcmp (REG_ADDR (&old_state, check_reg),
- REG_ADDR (state, check_reg),
- REGISTER_RAW_SIZE (check_reg)))
- /* Register CHECK_REG has changed! Ack! */
- {
- warning ("Register %s changed after thread was aborted.",
- REGISTER_NAME (check_reg));
- if (reg >= 0 && reg != check_reg)
- /* Update gdb's copy of the register. */
- supply_register (check_reg, REG_ADDR (state, check_reg));
- else
- warning ("... also writing this register! Suspicious...");
- }
+ warning ("Couldn't fetch registers from %s",
+ proc_string (thread));
+ return;
}
- if (reg >= 0)
+ if (regno == -1)
{
- proc_debug (thread, "storing register: %s", REGISTER_NAME (reg));
- STORE_REGS (state, reg, 1);
+ int i;
+
+ proc_debug (thread, "fetching all register");
+
+ for (i = 0; i < NUM_GREGS; i++)
+ supply_register (i, REG_ADDR (state, i));
+ thread->fetched_regs = ~0;
}
else
{
- proc_debug (thread, "storing all registers");
- for (reg = 0; reg < NUM_REGS; reg++)
- STORE_REGS (state, reg, 1);
+ proc_debug (thread, "fetching register %s", REGISTER_NAME (regno));
+
+ supply_register (regno, REG_ADDR (state, regno));
+ thread->fetched_regs |= (1 << regno);
}
}
+
+ if (regno >= NUM_GREGS || regno == -1)
+ {
+ proc_debug (thread, "fetching floating-point registers");
+
+ fetch_fpregs (thread);
+ }
}
+
-/* jtv@hut.fi: I copied and modified this 387 code from
- * gdb/i386-xdep.c. Modifications for Mach 3.0.
- *
- * i387 status dumper. See also i387-tdep.c
- */
-struct env387
-{
- unsigned short control;
- unsigned short r0;
- unsigned short status;
- unsigned short r1;
- unsigned short tag;
- unsigned short r2;
- unsigned long eip;
- unsigned short code_seg;
- unsigned short opcode;
- unsigned long operand;
- unsigned short operand_seg;
- unsigned short r3;
- unsigned char regs[8][10];
-};
-/* This routine is machine independent?
- * Should move it to i387-tdep.c but you need to export struct env387
- */
-static
-print_387_status (status, ep)
- unsigned short status;
- struct env387 *ep;
+/* Fill the i387 hardware state EP with selected data from the set of
+ (pseudo) registers specified by REGS and VALID. VALID is an array
+ indicating which registers in REGS are valid. If VALID is zero,
+ all registers are assumed to be valid. */
+static void
+convert_to_env387 (struct env387 *ep, char *regs, signed char *valid)
{
int i;
- int bothstatus;
- int top;
- int fpreg;
- unsigned char *p;
- bothstatus = ((status != 0) && (ep->status != 0));
- if (status != 0)
- {
- if (bothstatus)
- printf_unfiltered ("u: ");
- print_387_status_word (status);
- }
+ /* Fill in the floating-point registers. */
+ for (i = 0; i < 8; i++)
+ if (!valid || valid[i])
+ memcpy (ep->regs[i], &regs[REGISTER_BYTE (FP0_REGNUM + i)],
+ REGISTER_RAW_SIZE (FP0_REGNUM + i));
+
+#define fill(member, regno) \
+ if (!valid || valid[(regno)]) \
+ memcpy (&ep->member, &regs[REGISTER_BYTE (regno)], \
+ sizeof (ep->member));
+
+ fill (control, FCTRL_REGNUM);
+ fill (status, FSTAT_REGNUM);
+ fill (tag, FTAG_REGNUM);
+ fill (eip, FCOFF_REGNUM);
+ fill (operand, FDOFF_REGNUM);
+ fill (operand_seg, FDS_REGNUM);
+
+#undef fill
+
+ if (!valid || valid[FCS_REGNUM])
+ ep->code_seg =
+ (* (int *) &registers[REGISTER_BYTE (FCS_REGNUM)] & 0xffff);
+
+ if (!valid || valid[FOP_REGNUM])
+ ep->opcode =
+ ((* (int *) &registers[REGISTER_BYTE (FOP_REGNUM)] & ((1 << 11) - 1)));
+}
+
+/* Store the whole floating-point state into THREAD using information
+ from the corresponding (pseudo) registers. */
+static void
+store_fpregs (struct proc *thread)
+{
+ mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
+ struct i386_float_state state;
+ error_t err;
- if (ep->status != 0)
+ err = thread_get_state (thread->port, i386_FLOAT_STATE,
+ (thread_state_t) &state, &count);
+ if (err)
{
- if (bothstatus)
- printf_unfiltered ("e: ");
- print_387_status_word (ep->status);
+ warning ("Couldn't fetch floating-point state from %s",
+ proc_string (thread));
+ return;
}
- print_387_control_word (ep->control);
- printf_unfiltered ("last exception: ");
- printf_unfiltered ("opcode %s; ", local_hex_string (ep->opcode));
- printf_unfiltered ("pc %s:", local_hex_string (ep->code_seg));
- printf_unfiltered ("%s; ", local_hex_string (ep->eip));
- printf_unfiltered ("operand %s", local_hex_string (ep->operand_seg));
- printf_unfiltered (":%s\n", local_hex_string (ep->operand));
-
- top = (ep->status >> 11) & 7;
-
- printf_unfiltered ("regno tag msb lsb value\n");
- for (fpreg = 7; fpreg >= 0; fpreg--)
+ convert_to_env387 ((struct env387 *) state.hw_state,
+ registers, register_valid);
+
+ err = thread_set_state (thread->port, i386_FLOAT_STATE,
+ (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
+ if (err)
{
- double val;
-
- printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
-
- switch ((ep->tag >> (fpreg * 2)) & 3)
- {
- case 0:
- printf_unfiltered ("valid ");
- break;
- case 1:
- printf_unfiltered ("zero ");
- break;
- case 2:
- printf_unfiltered ("trap ");
- break;
- case 3:
- printf_unfiltered ("empty ");
- break;
- }
- for (i = 9; i >= 0; i--)
- printf_unfiltered ("%02x", ep->regs[fpreg][i]);
-
- floatformat_to_double (&floatformat_i387_ext, (char *) ep->regs[fpreg],
- &val);
- printf_unfiltered (" %g\n", val);
+ warning ("Couldn't store floating-point state into %s",
+ proc_string (thread));
+ return;
}
- if (ep->r0)
- printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string (ep->r0));
- if (ep->r1)
- printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string (ep->r1));
- if (ep->r2)
- printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string (ep->r2));
- if (ep->r3)
- printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string (ep->r3));
}
-/*
- * values that go into fp_kind (from <i386/fpreg.h>)
- */
-#define FP_NO 0 /* no fp chip, no emulator (no fp support) */
-#define FP_SW 1 /* no fp chip, using software emulator */
-#define FP_HW 2 /* chip present bit */
-#define FP_287 2 /* 80287 chip present */
-#define FP_387 3 /* 80387 chip present */
-
-typedef struct fpstate
+/* Store at least register REGNO, or all regs if REGNO == -1. */
+void
+gnu_store_registers (int regno)
{
-#if 1
- unsigned char state[FP_STATE_BYTES]; /* "hardware" state */
-#else
- struct env387 state; /* Actually this */
-#endif
- int status; /* Duplicate status */
-}
- *fpstate_t;
+ struct proc *thread;
-/* Mach 3 specific routines.
- */
-static int
-get_i387_state (fstate)
- struct fpstate *fstate;
-{
- error_t err;
- thread_state_data_t state;
- unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
- struct i386_float_state *fsp;
- struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
+ /* Make sure we know about new threads. */
+ inf_update_procs (current_inferior);
+ thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (!thread)
- error ("get_i387_state: Invalid thread");
-
- proc_abort (thread, 0); /* Make sure THREAD's in a reasonable state. */
+ error ("Couldn't store registers into thread %d: No such thread",
+ inferior_pid);
- err = thread_get_state (thread->port, i386_FLOAT_STATE, state, &fsCnt);
- if (err)
+ if (regno < NUM_GREGS || regno == -1)
{
- warning ("Can not get live floating point state: %s",
- mach_error_string (err));
- return 0;
- }
+ thread_state_t state;
+ thread_state_data_t old_state;
+ int was_aborted = thread->aborted;
+ int was_valid = thread->state_valid;
- fsp = (struct i386_float_state *) state;
- /* The 387 chip (also 486 counts) or a software emulator? */
- if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW))
- return 0;
-
- /* Clear the target then copy thread's float state there.
- Make a copy of the status word, for some reason?
- */
- memset (fstate, 0, sizeof (struct fpstate));
+ if (!was_aborted && was_valid)
+ memcpy (&old_state, &thread->state, sizeof (old_state));
- fstate->status = fsp->exc_status;
+ state = proc_get_state (thread, 1);
+ if (!state)
+ {
+ warning ("Couldn't store registers into %s", proc_string (thread));
+ return;
+ }
- memcpy (fstate->state, (char *) &fsp->hw_state, FP_STATE_BYTES);
+ if (!was_aborted && was_valid)
+ /* See which registers have changed after aborting the thread. */
+ {
+ int check_regno;
+
+ for (check_regno = 0; check_regno < NUM_GREGS; check_regno++)
+ if ((thread->fetched_regs & (1 << check_regno))
+ && memcpy (REG_ADDR (&old_state, check_regno),
+ REG_ADDR (state, check_regno),
+ REGISTER_RAW_SIZE (check_regno)))
+ /* Register CHECK_REGNO has changed! Ack! */
+ {
+ warning ("Register %s changed after the thread was aborted",
+ REGISTER_NAME (check_regno));
+ if (regno >= 0 && regno != check_regno)
+ /* Update gdb's copy of the register. */
+ supply_register (check_regno, REG_ADDR (state, check_regno));
+ else
+ warning ("... also writing this register! Suspicious...");
+ }
+ }
- return 1;
-}
+#define fill(state, regno) \
+ memcpy (REG_ADDR(state, regno), &registers[REGISTER_BYTE (regno)], \
+ REGISTER_RAW_SIZE (regno))
-/*
- * This is called by "info float" command
- */
-void
-i386_mach3_float_info ()
-{
- char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
- int valid = 0;
- fpstate_t fps;
+ if (regno == -1)
+ {
+ int i;
+
+ proc_debug (thread, "storing all registers");
- if (target_has_execution)
- valid = get_i387_state (buf);
+ for (i = 0; i < NUM_GREGS; i++)
+ if (register_valid[i])
+ fill (state, i);
+ }
+ else
+ {
+ proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
- if (!valid)
- {
- warning ("no floating point status saved");
- return;
+ assert (register_valid[regno]);
+ fill (state, regno);
+ }
}
- fps = (fpstate_t) buf;
+#undef fill
- print_387_status (fps->status, (struct env387 *) fps->state);
+ if (regno >= NUM_GREGS || regno == -1)
+ {
+ proc_debug (thread, "storing floating-point registers");
+
+ store_fpregs (thread);
+ }
}
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index e61221a..082d957 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -838,8 +838,13 @@ breakpoint_auto_delete_contents (arg)
The dummy's frame is automatically popped whenever that break is hit.
If that is the first time the program stops, run_stack_dummy
returns to its caller with that frame already gone and returns 0.
- Otherwise, run_stack-dummy returns 1 (the frame will eventually be popped
- when we do hit that breakpoint). */
+
+ Otherwise, run_stack-dummy returns a non-zero value.
+ If the called function receives a random signal, we do not allow the user
+ to continue executing it as this may not work. The dummy frame is poped
+ and we return 1.
+ If we hit a breakpoint, we leave the frame in place and return 2 (the frame
+ will eventually be popped when we do hit the dummy end breakpoint). */
int
run_stack_dummy (addr, buffer)
@@ -907,10 +912,24 @@ run_stack_dummy (addr, buffer)
discard_cleanups (old_cleanups);
+ if (stopped_by_random_signal)
+ {
+ /* If the inferior execution fails we need to restore our
+ stack. It is not done by proceed() in this case. */
+ /* Pop the empty frame that contains the stack dummy.
+ POP_FRAME ends with a setting of the current frame, so we
+ can use that next. */
+ POP_FRAME;
+ return 1;
+ }
+
+ /* We may also stop prematurely because we hit a breakpoint in the
+ called routine. We do not pop the frame as the user may wish
+ to single step or continue from there. */
if (!stop_stack_dummy)
- return 1;
+ return 2;
- /* On return, the stack dummy has been popped already. */
+ /* On normal return, the stack dummy has been popped already. */
memcpy (buffer, stop_registers, REGISTER_BYTES);
return 0;
diff --git a/gdb/main.c b/gdb/main.c
index 1eb36ae..7ccc47f 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -33,6 +33,11 @@
#include "gdb_string.h"
#include "event-loop.h"
+#if defined (TUI) || defined (GDBTK)
+/* FIXME: cagney/2000-01-31: This #include is to allow older code such
+ as that found in the TUI to continue to build. */
+#include "tui/tui-file.h"
+#endif
/* If nonzero, display time usage both at startup and for each command. */
@@ -187,17 +192,19 @@ captured_main (void *data)
getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
current_directory = gdb_dirbuf;
-#if 0
- /* not yet */
- gdb_stdout = stdio_fileopen (stdout);
- gdb_stderr = stdio_fileopen (stderr);
- gdb_stdlog = gdb_stderr; /* for moment */
- gdb_stdtarg = gdb_stderr; /* for moment */
-#else
+#if defined (TUI) || defined (GDBTK)
+ /* Older code uses the tui_file and fputs_unfiltered_hook(). It
+ should be using a customized GDB_FILE object and re-initializing
+ within its own _initialize function. */
gdb_stdout = tui_fileopen (stdout);
gdb_stderr = tui_fileopen (stderr);
gdb_stdlog = gdb_stdout; /* for moment */
gdb_stdtarg = gdb_stderr; /* for moment */
+#else
+ gdb_stdout = stdio_fileopen (stdout);
+ gdb_stderr = stdio_fileopen (stderr);
+ gdb_stdlog = gdb_stderr; /* for moment */
+ gdb_stdtarg = gdb_stderr; /* for moment */
#endif
/* initialize error() */
diff --git a/gdb/remote-rdi.c b/gdb/remote-rdi.c
index 63c8d60..d187223 100644
--- a/gdb/remote-rdi.c
+++ b/gdb/remote-rdi.c
@@ -32,6 +32,7 @@
#include "gdb-stabs.h"
#include "gdbthread.h"
#include "gdbcore.h"
+#include "breakpoint.h"
#ifdef USG
#include <sys/types.h>
@@ -738,6 +739,12 @@ arm_rdi_kill ()
static void
arm_rdi_mourn_inferior ()
{
+ /* We remove the inserted breakpoints in case the user wants to
+ issue another target and load commands to rerun his application;
+ This is something that wouldn't work on a native target, for instance,
+ as the process goes away when the inferior exits, but it works with
+ some remote targets like this one. That is why this is done here. */
+ remove_breakpoints();
unpush_target (&arm_rdi_ops);
generic_mourn_inferior ();
}
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 92af60a..91febd6 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -2400,6 +2400,43 @@ build_canonical_line_spec (sal, symname, canonical)
canonical_arr[0] = canonical_name;
}
+
+
+/* Find an instance of the character C in the string S that is outside
+ of all parenthesis pairs, single-quoted strings, and double-quoted
+ strings. */
+static char *
+find_toplevel_char (char *s, char c)
+{
+ int quoted = 0; /* zero if we're not in quotes;
+ '"' if we're in a double-quoted string;
+ '\'' if we're in a single-quoted string. */
+ int depth = 0; /* number of unclosed parens we've seen */
+ char *scan;
+
+ for (scan = s; *scan; scan++)
+ {
+ if (quoted)
+ {
+ if (*scan == quoted)
+ quoted = 0;
+ else if (*scan == '\\' && *(scan + 1))
+ scan++;
+ }
+ else if (*scan == c && ! quoted && depth == 0)
+ return scan;
+ else if (*scan == '"' || *scan == '\'')
+ quoted = *scan;
+ else if (*scan == '(')
+ depth++;
+ else if (*scan == ')' && depth > 0)
+ depth--;
+ }
+
+ return 0;
+}
+
+
/* Parse a string that specifies a line number.
Pass the address of a char * variable; that variable will be
advanced over the characters actually parsed.
@@ -2576,9 +2613,14 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
/* Maybe we were called with a line range FILENAME:LINENUM,FILENAME:LINENUM
and we must isolate the first half. Outer layers will call again later
- for the second half */
- if ((ii = strchr (*argptr, ',')) != NULL)
- has_comma = 1;
+ for the second half.
+
+ Don't count commas that appear in argument lists of overloaded
+ functions, or in quoted strings. It's stupid to go to this much
+ trouble when the rest of the function is such an obvious roach hotel. */
+ ii = find_toplevel_char (*argptr, ',');
+ has_comma = (ii != 0);
+
/* Temporarily zap out second half to not
* confuse the code below.
* This is undone below. Do not change ii!!
@@ -2632,10 +2674,14 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
}
while (p[0] == ' ' || p[0] == '\t')
p++;
+
/* if the closing double quote was left at the end, remove it */
- if (is_quote_enclosed && ((pp = strchr (p, '"')) != NULL))
- if (!*(pp + 1))
- *pp = '\0';
+ if (is_quote_enclosed)
+ {
+ char *closing_quote = strchr (p, '"');
+ if (closing_quote && closing_quote[1] == '\0')
+ *closing_quote = '\0';
+ }
/* Now that we've safely parsed the first half,
* put back ',' so outer layers can see it
@@ -3068,6 +3114,9 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
p = skip_quoted (*argptr);
}
+ if (is_quote_enclosed && **argptr == '"')
+ (*argptr)++;
+
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = '\0';
diff --git a/gdb/top.c b/gdb/top.c
index 198a554..c19818c 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -376,10 +376,6 @@ int (*ui_loop_hook) PARAMS ((int));
void (*command_loop_hook) PARAMS ((void));
-/* Called instead of fputs for all output. */
-
-void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, GDB_FILE * stream));
-
/* Called from print_frame_info to list the line we stopped in. */
void (*print_frame_info_listing_hook) PARAMS ((struct symtab * s, int line,
diff --git a/gdb/tui/ChangeLog b/gdb/tui/ChangeLog
index 2af1a8f..8f8f179 100644
--- a/gdb/tui/ChangeLog
+++ b/gdb/tui/ChangeLog
@@ -1,3 +1,13 @@
+Mon Jan 31 18:12:43 2000 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * tui-file.c (enum streamtype, struct tui_stream, tui_file_new,
+ tui_file_delete, tui_fileopen, tui_sfileopen, tui_file_isatty,
+ tui_file_rewind, tui_file_put, tui_file_fputs,
+ tui_file_get_strbuf, tui_file_adjust_strbuf, tui_file_flush,
+ fputs_unfiltered_hook): Move to here from ../utils.c
+
+ * tui-file.h, tui-file.c: New files.
+
Mon Nov 8 17:47:37 1999 Andrew Cagney <cagney@b1.cygnus.com>
* tuiRegs.c (_tuiRegisterFormat), tuiDisassem.c
diff --git a/gdb/tui/tui-file.c b/gdb/tui/tui-file.c
new file mode 100644
index 0000000..ae3f842
--- /dev/null
+++ b/gdb/tui/tui-file.c
@@ -0,0 +1,298 @@
+/* GDB_FILE - a generic STDIO like output stream.
+ Copyright (C) 1999, 2000 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb-file.h"
+#include "tui/tui-file.h"
+
+#include <string.h>
+
+/* Called instead of fputs for all TUI_FILE output. */
+
+void (*fputs_unfiltered_hook) (const char *linebuffer, GDB_FILE * stream);
+
+/* A ``struct gdb_file'' that is compatible with all the legacy
+ code. */
+
+/* new */
+enum streamtype
+{
+ afile,
+ astring
+};
+
+/* new */
+struct tui_stream
+{
+ int *ts_magic;
+ enum streamtype ts_streamtype;
+ FILE *ts_filestream;
+ char *ts_strbuf;
+ int ts_buflen;
+};
+
+static gdb_file_flush_ftype tui_file_flush;
+extern gdb_file_fputs_ftype tui_file_fputs;
+static gdb_file_isatty_ftype tui_file_isatty;
+static gdb_file_rewind_ftype tui_file_rewind;
+static gdb_file_put_ftype tui_file_put;
+static gdb_file_delete_ftype tui_file_delete;
+static struct gdb_file *tui_file_new PARAMS ((void));
+static int tui_file_magic;
+
+static struct gdb_file *
+tui_file_new ()
+{
+ struct tui_stream *tui = xmalloc (sizeof (struct tui_stream));
+ struct gdb_file *file = gdb_file_new ();
+ set_gdb_file_data (file, tui, tui_file_delete);
+ set_gdb_file_flush (file, tui_file_flush);
+ set_gdb_file_fputs (file, tui_file_fputs);
+ set_gdb_file_isatty (file, tui_file_isatty);
+ set_gdb_file_rewind (file, tui_file_rewind);
+ set_gdb_file_put (file, tui_file_put);
+ tui->ts_magic = &tui_file_magic;
+ return file;
+}
+
+static void
+tui_file_delete (file)
+ struct gdb_file *file;
+{
+ struct tui_stream *tmpstream = gdb_file_data (file);
+ if (tmpstream->ts_magic != &tui_file_magic)
+ internal_error ("tui_file_delete: bad magic number");
+ if ((tmpstream->ts_streamtype == astring) &&
+ (tmpstream->ts_strbuf != NULL))
+ {
+ free (tmpstream->ts_strbuf);
+ }
+ free (tmpstream);
+}
+
+struct gdb_file *
+tui_fileopen (stream)
+ FILE *stream;
+{
+ struct gdb_file *file = tui_file_new ();
+ struct tui_stream *tmpstream = gdb_file_data (file);
+ tmpstream->ts_streamtype = afile;
+ tmpstream->ts_filestream = stream;
+ tmpstream->ts_strbuf = NULL;
+ tmpstream->ts_buflen = 0;
+ return file;
+}
+
+struct gdb_file *
+tui_sfileopen (n)
+ int n;
+{
+ struct gdb_file *file = tui_file_new ();
+ struct tui_stream *tmpstream = gdb_file_data (file);
+ tmpstream->ts_streamtype = astring;
+ tmpstream->ts_filestream = NULL;
+ if (n > 0)
+ {
+ tmpstream->ts_strbuf = xmalloc ((n + 1) * sizeof (char));
+ tmpstream->ts_strbuf[0] = '\0';
+ }
+ else
+ /* Do not allocate the buffer now. The first time something is printed
+ one will be allocated by tui_file_adjust_strbuf() */
+ tmpstream->ts_strbuf = NULL;
+ tmpstream->ts_buflen = n;
+ return file;
+}
+
+static int
+tui_file_isatty (file)
+ struct gdb_file *file;
+{
+ struct tui_stream *stream = gdb_file_data (file);
+ if (stream->ts_magic != &tui_file_magic)
+ internal_error ("tui_file_isatty: bad magic number");
+ if (stream->ts_streamtype == afile)
+ return (isatty (fileno (stream->ts_filestream)));
+ else
+ return 0;
+}
+
+static void
+tui_file_rewind (file)
+ struct gdb_file *file;
+{
+ struct tui_stream *stream = gdb_file_data (file);
+ if (stream->ts_magic != &tui_file_magic)
+ internal_error ("tui_file_rewind: bad magic number");
+ stream->ts_strbuf[0] = '\0';
+}
+
+static void
+tui_file_put (struct gdb_file *file,
+ gdb_file_put_method_ftype *write,
+ void *dest)
+{
+ struct tui_stream *stream = gdb_file_data (file);
+ if (stream->ts_magic != &tui_file_magic)
+ internal_error ("tui_file_put: bad magic number");
+ if (stream->ts_streamtype == astring)
+ write (dest, stream->ts_strbuf, strlen (stream->ts_strbuf));
+}
+
+/* All TUI I/O sent to the *_filtered and *_unfiltered functions
+ eventually ends up here. The fputs_unfiltered_hook is primarily
+ used by GUIs to collect all output and send it to the GUI, instead
+ of the controlling terminal. Only output to gdb_stdout and
+ gdb_stderr are sent to the hook. Everything else is sent on to
+ fputs to allow file I/O to be handled appropriately. */
+
+/* FIXME: Should be broken up and moved to a TUI specific file. */
+
+void
+tui_file_fputs (linebuffer, file)
+ const char *linebuffer;
+ GDB_FILE *file;
+{
+ struct tui_stream *stream = gdb_file_data (file);
+#if defined(TUI)
+ extern int tui_owns_terminal;
+#endif
+ /* NOTE: cagney/1999-10-13: The use of fputs_unfiltered_hook is
+ seriously discouraged. Those wanting to hook output should
+ instead implement their own gdb_file object and install that. See
+ also tui_file_flush(). */
+ if (fputs_unfiltered_hook
+ && (file == gdb_stdout
+ || file == gdb_stderr))
+ fputs_unfiltered_hook (linebuffer, file);
+ else
+ {
+#if defined(TUI)
+ if (tui_version && tui_owns_terminal)
+ {
+ /* If we get here somehow while updating the TUI (from
+ * within a tuiDo(), then we need to temporarily
+ * set up the terminal for GDB output. This probably just
+ * happens on error output.
+ */
+
+ if (stream->ts_streamtype == astring)
+ {
+ tui_file_adjust_strbuf (strlen (linebuffer), stream);
+ strcat (stream->ts_strbuf, linebuffer);
+ }
+ else
+ {
+ tuiTermUnsetup (0, (tui_version) ? cmdWin->detail.commandInfo.curch : 0);
+ fputs (linebuffer, stream->ts_filestream);
+ tuiTermSetup (0);
+ if (linebuffer[strlen (linebuffer) - 1] == '\n')
+ tuiClearCommandCharCount ();
+ else
+ tuiIncrCommandCharCountBy (strlen (linebuffer));
+ }
+ }
+ else
+ {
+ /* The normal case - just do a fputs() */
+ if (stream->ts_streamtype == astring)
+ {
+ tui_file_adjust_strbuf (strlen (linebuffer), stream);
+ strcat (stream->ts_strbuf, linebuffer);
+ }
+ else
+ fputs (linebuffer, stream->ts_filestream);
+ }
+
+
+#else
+ if (stream->ts_streamtype == astring)
+ {
+ tui_file_adjust_strbuf (strlen (linebuffer), file);
+ strcat (stream->ts_strbuf, linebuffer);
+ }
+ else
+ fputs (linebuffer, stream->ts_filestream);
+#endif
+ }
+}
+
+char *
+tui_file_get_strbuf (struct gdb_file *file)
+{
+ struct tui_stream *stream = gdb_file_data (file);
+ if (stream->ts_magic != &tui_file_magic)
+ internal_error ("tui_file_get_strbuf: bad magic number");
+ return (stream->ts_strbuf);
+}
+
+/* adjust the length of the buffer by the amount necessary
+ to accomodate appending a string of length N to the buffer contents */
+void
+tui_file_adjust_strbuf (int n, struct gdb_file *file)
+{
+ struct tui_stream *stream = gdb_file_data (file);
+ int non_null_chars;
+ if (stream->ts_magic != &tui_file_magic)
+ internal_error ("tui_file_adjust_strbuf: bad magic number");
+
+ if (stream->ts_streamtype != astring)
+ return;
+
+ if (stream->ts_strbuf)
+ {
+ /* There is already a buffer allocated */
+ non_null_chars = strlen (stream->ts_strbuf);
+
+ if (n > (stream->ts_buflen - non_null_chars - 1))
+ {
+ stream->ts_buflen = n + non_null_chars + 1;
+ stream->ts_strbuf = xrealloc (stream->ts_strbuf, stream->ts_buflen);
+ }
+ }
+ else
+ /* No buffer yet, so allocate one of the desired size */
+ stream->ts_strbuf = xmalloc ((n + 1) * sizeof (char));
+}
+
+static void
+tui_file_flush (file)
+ GDB_FILE *file;
+{
+ struct tui_stream *stream = gdb_file_data (file);
+ if (stream->ts_magic != &tui_file_magic)
+ internal_error ("tui_file_flush: bad magic number");
+
+ /* NOTE: cagney/1999-10-12: If we've been linked with code that uses
+ fputs_unfiltered_hook then we assume that it doesn't need to know
+ about flushes. Code that does need to know about flushes can
+ implement a proper gdb_file object. */
+ if (fputs_unfiltered_hook)
+ return;
+
+ switch (stream->ts_streamtype)
+ {
+ case astring:
+ break;
+ case afile:
+ fflush (stream->ts_filestream);
+ break;
+ }
+}
diff --git a/gdb/tui/tui-file.h b/gdb/tui/tui-file.h
new file mode 100644
index 0000000..c962d4f
--- /dev/null
+++ b/gdb/tui/tui-file.h
@@ -0,0 +1,34 @@
+/* GDB_FILE - a generic STDIO like output stream.
+ Copyright (C) 1999, 2000 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_FILE_H
+#define TUI_FILE_H
+
+extern struct gdb_file *tui_fileopen (FILE *);
+extern struct gdb_file *tui_sfileopen (int);
+extern char *tui_file_get_strbuf (struct gdb_file *);
+extern void tui_file_adjust_strbuf (int, struct gdb_file *);
+
+/* NOTE: cagney/1999-10-14: fputs_unfiltered_hook is deprecated. Code
+ wanting to control GDB's output should override the gdb_std...
+ files. */
+extern void (*fputs_unfiltered_hook) (const char *linebuffer,
+ GDB_FILE * stream);
+#endif
diff --git a/gdb/utils.c b/gdb/utils.c
index ab790d9..1111eea 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1772,763 +1772,6 @@ begin_line ()
}
-/* ``struct gdb_file'' implementation that maps directly onto
- <stdio.h>'s FILE. */
-
-static gdb_file_write_ftype stdio_file_write;
-static gdb_file_fputs_ftype stdio_file_fputs;
-static gdb_file_isatty_ftype stdio_file_isatty;
-static gdb_file_delete_ftype stdio_file_delete;
-static struct gdb_file *stdio_file_new PARAMS ((FILE * file, int close_p));
-static gdb_file_flush_ftype stdio_file_flush;
-
-static int stdio_file_magic;
-
-struct stdio_file
- {
- int *magic;
- FILE *file;
- int close_p;
- };
-
-static struct gdb_file *
-stdio_file_new (file, close_p)
- FILE *file;
- int close_p;
-{
- struct gdb_file *gdb_file = gdb_file_new ();
- struct stdio_file *stdio = xmalloc (sizeof (struct stdio_file));
- stdio->magic = &stdio_file_magic;
- stdio->file = file;
- stdio->close_p = close_p;
- set_gdb_file_data (gdb_file, stdio, stdio_file_delete);
- set_gdb_file_flush (gdb_file, stdio_file_flush);
- set_gdb_file_write (gdb_file, stdio_file_write);
- set_gdb_file_fputs (gdb_file, stdio_file_fputs);
- set_gdb_file_isatty (gdb_file, stdio_file_isatty);
- return gdb_file;
-}
-
-static void
-stdio_file_delete (file)
- struct gdb_file *file;
-{
- struct stdio_file *stdio = gdb_file_data (file);
- if (stdio->magic != &stdio_file_magic)
- internal_error ("stdio_file_delete: bad magic number");
- if (stdio->close_p)
- {
- fclose (stdio->file);
- }
- free (stdio);
-}
-
-static void
-stdio_file_flush (file)
- struct gdb_file *file;
-{
- struct stdio_file *stdio = gdb_file_data (file);
- if (stdio->magic != &stdio_file_magic)
- internal_error ("stdio_file_flush: bad magic number");
- fflush (stdio->file);
-}
-
-static void
-stdio_file_write (struct gdb_file *file, const char *buf, long length_buf)
-{
- struct stdio_file *stdio = gdb_file_data (file);
- if (stdio->magic != &stdio_file_magic)
- internal_error ("stdio_file_write: bad magic number");
- fwrite (buf, length_buf, 1, stdio->file);
-}
-
-static void
-stdio_file_fputs (linebuffer, file)
- const char *linebuffer;
- struct gdb_file *file;
-{
- struct stdio_file *stdio = gdb_file_data (file);
- if (stdio->magic != &stdio_file_magic)
- internal_error ("stdio_file_fputs: bad magic number");
- fputs (linebuffer, stdio->file);
-}
-
-static int
-stdio_file_isatty (file)
- struct gdb_file *file;
-{
- struct stdio_file *stdio = gdb_file_data (file);
- if (stdio->magic != &stdio_file_magic)
- internal_error ("stdio_file_isatty: bad magic number");
- return (isatty (fileno (stdio->file)));
-}
-
-/* Like fdopen(). Create a gdb_file from a previously opened FILE. */
-
-struct gdb_file *
-stdio_fileopen (file)
- FILE *file;
-{
- return stdio_file_new (file, 0);
-}
-
-
-/* A pure memory based ``struct gdb_file'' that can be used an output
- buffer. The buffers accumulated contents are available via
- gdb_file_put(). */
-
-struct mem_file
- {
- int *magic;
- char *buffer;
- int sizeof_buffer;
- int length_buffer;
- };
-
-static gdb_file_rewind_ftype mem_file_rewind;
-static gdb_file_put_ftype mem_file_put;
-static gdb_file_write_ftype mem_file_write;
-static gdb_file_delete_ftype mem_file_delete;
-static struct gdb_file *mem_file_new PARAMS ((void));
-static int mem_file_magic;
-
-static struct gdb_file *
-mem_file_new (void)
-{
- struct mem_file *stream = XMALLOC (struct mem_file);
- struct gdb_file *file = gdb_file_new ();
- set_gdb_file_data (file, stream, mem_file_delete);
- set_gdb_file_rewind (file, mem_file_rewind);
- set_gdb_file_put (file, mem_file_put);
- set_gdb_file_write (file, mem_file_write);
- stream->magic = &mem_file_magic;
- stream->buffer = NULL;
- stream->sizeof_buffer = 0;
- stream->length_buffer = 0;
- return file;
-}
-
-static void
-mem_file_delete (struct gdb_file *file)
-{
- struct mem_file *stream = gdb_file_data (file);
- if (stream->magic != &mem_file_magic)
- internal_error ("mem_file_delete: bad magic number");
- if (stream->buffer != NULL)
- free (stream->buffer);
- free (stream);
-}
-
-struct gdb_file *
-mem_fileopen (void)
-{
- return mem_file_new ();
-}
-
-static void
-mem_file_rewind (struct gdb_file *file)
-{
- struct mem_file *stream = gdb_file_data (file);
- if (stream->magic != &mem_file_magic)
- internal_error ("mem_file_rewind: bad magic number");
- stream->length_buffer = 0;
-}
-
-static void
-mem_file_put (struct gdb_file *file,
- gdb_file_put_method_ftype *write,
- void *dest)
-{
- struct mem_file *stream = gdb_file_data (file);
- if (stream->magic != &mem_file_magic)
- internal_error ("mem_file_put: bad magic number");
- if (stream->length_buffer > 0)
- write (dest, stream->buffer, stream->length_buffer);
-}
-
-void
-mem_file_write (struct gdb_file *file,
- const char *buffer,
- long length_buffer)
-{
- struct mem_file *stream = gdb_file_data (file);
- if (stream->magic != &mem_file_magic)
- internal_error ("mem_file_write: bad magic number");
- if (stream->buffer == NULL)
- {
- stream->length_buffer = length_buffer;
- stream->sizeof_buffer = length_buffer;
- stream->buffer = xmalloc (stream->sizeof_buffer);
- memcpy (stream->buffer, buffer, length_buffer);
- }
- else
- {
- int new_length = stream->length_buffer + length_buffer;
- if (new_length >= stream->sizeof_buffer)
- {
- stream->sizeof_buffer = new_length;
- stream->buffer = xrealloc (stream->buffer, stream->sizeof_buffer);
- }
- memcpy (stream->buffer + stream->length_buffer, buffer, length_buffer);
- stream->length_buffer = new_length;
- }
-}
-
-/* A ``struct gdb_file'' that is compatible with all the legacy
- code. */
-
-/* new */
-enum streamtype
-{
- afile,
- astring
-};
-
-/* new */
-struct tui_stream
-{
- int *ts_magic;
- enum streamtype ts_streamtype;
- FILE *ts_filestream;
- char *ts_strbuf;
- int ts_buflen;
-};
-
-static gdb_file_flush_ftype tui_file_flush;
-extern gdb_file_fputs_ftype tui_file_fputs;
-static gdb_file_isatty_ftype tui_file_isatty;
-static gdb_file_rewind_ftype tui_file_rewind;
-static gdb_file_put_ftype tui_file_put;
-static gdb_file_delete_ftype tui_file_delete;
-static struct gdb_file *tui_file_new PARAMS ((void));
-static int tui_file_magic;
-
-static struct gdb_file *
-tui_file_new ()
-{
- struct tui_stream *tui = xmalloc (sizeof (struct tui_stream));
- struct gdb_file *file = gdb_file_new ();
- set_gdb_file_data (file, tui, tui_file_delete);
- set_gdb_file_flush (file, tui_file_flush);
- set_gdb_file_fputs (file, tui_file_fputs);
- set_gdb_file_isatty (file, tui_file_isatty);
- set_gdb_file_rewind (file, tui_file_rewind);
- set_gdb_file_put (file, tui_file_put);
- tui->ts_magic = &tui_file_magic;
- return file;
-}
-
-static void
-tui_file_delete (file)
- struct gdb_file *file;
-{
- struct tui_stream *tmpstream = gdb_file_data (file);
- if (tmpstream->ts_magic != &tui_file_magic)
- internal_error ("tui_file_delete: bad magic number");
- if ((tmpstream->ts_streamtype == astring) &&
- (tmpstream->ts_strbuf != NULL))
- {
- free (tmpstream->ts_strbuf);
- }
- free (tmpstream);
-}
-
-struct gdb_file *
-tui_fileopen (stream)
- FILE *stream;
-{
- struct gdb_file *file = tui_file_new ();
- struct tui_stream *tmpstream = gdb_file_data (file);
- tmpstream->ts_streamtype = afile;
- tmpstream->ts_filestream = stream;
- tmpstream->ts_strbuf = NULL;
- tmpstream->ts_buflen = 0;
- return file;
-}
-
-struct gdb_file *
-tui_sfileopen (n)
- int n;
-{
- struct gdb_file *file = tui_file_new ();
- struct tui_stream *tmpstream = gdb_file_data (file);
- tmpstream->ts_streamtype = astring;
- tmpstream->ts_filestream = NULL;
- if (n > 0)
- {
- tmpstream->ts_strbuf = xmalloc ((n + 1) * sizeof (char));
- tmpstream->ts_strbuf[0] = '\0';
- }
- else
- /* Do not allocate the buffer now. The first time something is printed
- one will be allocated by tui_file_adjust_strbuf() */
- tmpstream->ts_strbuf = NULL;
- tmpstream->ts_buflen = n;
- return file;
-}
-
-static int
-tui_file_isatty (file)
- struct gdb_file *file;
-{
- struct tui_stream *stream = gdb_file_data (file);
- if (stream->ts_magic != &tui_file_magic)
- internal_error ("tui_file_isatty: bad magic number");
- if (stream->ts_streamtype == afile)
- return (isatty (fileno (stream->ts_filestream)));
- else
- return 0;
-}
-
-static void
-tui_file_rewind (file)
- struct gdb_file *file;
-{
- struct tui_stream *stream = gdb_file_data (file);
- if (stream->ts_magic != &tui_file_magic)
- internal_error ("tui_file_rewind: bad magic number");
- stream->ts_strbuf[0] = '\0';
-}
-
-static void
-tui_file_put (struct gdb_file *file,
- gdb_file_put_method_ftype *write,
- void *dest)
-{
- struct tui_stream *stream = gdb_file_data (file);
- if (stream->ts_magic != &tui_file_magic)
- internal_error ("tui_file_put: bad magic number");
- if (stream->ts_streamtype == astring)
- write (dest, stream->ts_strbuf, strlen (stream->ts_strbuf));
-}
-
-/* All TUI I/O sent to the *_filtered and *_unfiltered functions
- eventually ends up here. The fputs_unfiltered_hook is primarily
- used by GUIs to collect all output and send it to the GUI, instead
- of the controlling terminal. Only output to gdb_stdout and
- gdb_stderr are sent to the hook. Everything else is sent on to
- fputs to allow file I/O to be handled appropriately. */
-
-/* FIXME: Should be broken up and moved to a TUI specific file. */
-
-void
-tui_file_fputs (linebuffer, file)
- const char *linebuffer;
- GDB_FILE *file;
-{
- struct tui_stream *stream = gdb_file_data (file);
-#if defined(TUI)
- extern int tui_owns_terminal;
-#endif
- /* NOTE: cagney/1999-10-13: The use of fputs_unfiltered_hook is
- seriously discouraged. Those wanting to hook output should
- instead implement their own gdb_file object and install that. See
- also tui_file_flush(). */
- if (fputs_unfiltered_hook
- && (file == gdb_stdout
- || file == gdb_stderr))
- fputs_unfiltered_hook (linebuffer, file);
- else
- {
-#if defined(TUI)
- if (tui_version && tui_owns_terminal)
- {
- /* If we get here somehow while updating the TUI (from
- * within a tuiDo(), then we need to temporarily
- * set up the terminal for GDB output. This probably just
- * happens on error output.
- */
-
- if (stream->ts_streamtype == astring)
- {
- tui_file_adjust_strbuf (strlen (linebuffer), stream);
- strcat (stream->ts_strbuf, linebuffer);
- }
- else
- {
- tuiTermUnsetup (0, (tui_version) ? cmdWin->detail.commandInfo.curch : 0);
- fputs (linebuffer, stream->ts_filestream);
- tuiTermSetup (0);
- if (linebuffer[strlen (linebuffer) - 1] == '\n')
- tuiClearCommandCharCount ();
- else
- tuiIncrCommandCharCountBy (strlen (linebuffer));
- }
- }
- else
- {
- /* The normal case - just do a fputs() */
- if (stream->ts_streamtype == astring)
- {
- tui_file_adjust_strbuf (strlen (linebuffer), stream);
- strcat (stream->ts_strbuf, linebuffer);
- }
- else
- fputs (linebuffer, stream->ts_filestream);
- }
-
-
-#else
- if (stream->ts_streamtype == astring)
- {
- tui_file_adjust_strbuf (strlen (linebuffer), file);
- strcat (stream->ts_strbuf, linebuffer);
- }
- else
- fputs (linebuffer, stream->ts_filestream);
-#endif
- }
-}
-
-char *
-tui_file_get_strbuf (struct gdb_file *file)
-{
- struct tui_stream *stream = gdb_file_data (file);
- if (stream->ts_magic != &tui_file_magic)
- internal_error ("tui_file_get_strbuf: bad magic number");
- return (stream->ts_strbuf);
-}
-
-/* adjust the length of the buffer by the amount necessary
- to accomodate appending a string of length N to the buffer contents */
-void
-tui_file_adjust_strbuf (int n, struct gdb_file *file)
-{
- struct tui_stream *stream = gdb_file_data (file);
- int non_null_chars;
- if (stream->ts_magic != &tui_file_magic)
- internal_error ("tui_file_adjust_strbuf: bad magic number");
-
- if (stream->ts_streamtype != astring)
- return;
-
- if (stream->ts_strbuf)
- {
- /* There is already a buffer allocated */
- non_null_chars = strlen (stream->ts_strbuf);
-
- if (n > (stream->ts_buflen - non_null_chars - 1))
- {
- stream->ts_buflen = n + non_null_chars + 1;
- stream->ts_strbuf = xrealloc (stream->ts_strbuf, stream->ts_buflen);
- }
- }
- else
- /* No buffer yet, so allocate one of the desired size */
- stream->ts_strbuf = xmalloc ((n + 1) * sizeof (char));
-}
-
-GDB_FILE *
-gdb_fopen (name, mode)
- char *name;
- char *mode;
-{
- FILE *f = fopen (name, mode);
- if (f == NULL)
- return NULL;
- return stdio_file_new (f, 1);
-}
-
-static void
-tui_file_flush (file)
- GDB_FILE *file;
-{
- struct tui_stream *stream = gdb_file_data (file);
- if (stream->ts_magic != &tui_file_magic)
- internal_error ("tui_file_flush: bad magic number");
-
- /* NOTE: cagney/1999-10-12: If we've been linked with code that uses
- fputs_unfiltered_hook then we assume that it doesn't need to know
- about flushes. Code that does need to know about flushes can
- implement a proper gdb_file object. */
- if (fputs_unfiltered_hook)
- return;
-
- switch (stream->ts_streamtype)
- {
- case astring:
- break;
- case afile:
- fflush (stream->ts_filestream);
- break;
- }
-}
-
-/* Implement the ``struct gdb_file'' object. */
-
-static gdb_file_isatty_ftype null_file_isatty;
-static gdb_file_write_ftype null_file_write;
-static gdb_file_fputs_ftype null_file_fputs;
-static gdb_file_flush_ftype null_file_flush;
-static gdb_file_delete_ftype null_file_delete;
-static gdb_file_rewind_ftype null_file_rewind;
-static gdb_file_put_ftype null_file_put;
-
-struct gdb_file
- {
- int *magic;
- gdb_file_flush_ftype *to_flush;
- gdb_file_write_ftype *to_write;
- gdb_file_fputs_ftype *to_fputs;
- gdb_file_delete_ftype *to_delete;
- gdb_file_isatty_ftype *to_isatty;
- gdb_file_rewind_ftype *to_rewind;
- gdb_file_put_ftype *to_put;
- void *to_data;
- };
-int gdb_file_magic;
-
-struct gdb_file *
-gdb_file_new ()
-{
- struct gdb_file *file = xmalloc (sizeof (struct gdb_file));
- file->magic = &gdb_file_magic;
- set_gdb_file_data (file, NULL, null_file_delete);
- set_gdb_file_flush (file, null_file_flush);
- set_gdb_file_write (file, null_file_write);
- set_gdb_file_fputs (file, null_file_fputs);
- set_gdb_file_isatty (file, null_file_isatty);
- set_gdb_file_rewind (file, null_file_rewind);
- set_gdb_file_put (file, null_file_put);
- return file;
-}
-
-void
-gdb_file_delete (file)
- struct gdb_file *file;
-{
- file->to_delete (file);
- free (file);
-}
-
-static int
-null_file_isatty (file)
- struct gdb_file *file;
-{
- return 0;
-}
-
-static void
-null_file_rewind (file)
- struct gdb_file *file;
-{
- return;
-}
-
-static void
-null_file_put (struct gdb_file *file,
- gdb_file_put_method_ftype *write,
- void *dest)
-{
- return;
-}
-
-static void
-null_file_flush (file)
- struct gdb_file *file;
-{
- return;
-}
-
-static void
-null_file_write (struct gdb_file *file,
- const char *buf,
- long sizeof_buf)
-{
- if (file->to_fputs == null_file_fputs)
- /* Both the write and fputs methods are null. Discard the
- request. */
- return;
- else
- {
- /* The fputs method isn't null, slowly pass the write request
- onto that. FYI, this isn't as bad as it may look - the
- current (as of 1999-11-07) printf_* function calls fputc and
- fputc does exactly the below. By having a write function it
- is possible to clean up that code. */
- int i;
- char b[2];
- b[1] = '\0';
- for (i = 0; i < sizeof_buf; i++)
- {
- b[0] = buf[i];
- file->to_fputs (b, file);
- }
- return;
- }
-}
-
-static void
-null_file_fputs (buf, file)
- const char *buf;
- struct gdb_file *file;
-{
- if (file->to_write == null_file_write)
- /* Both the write and fputs methods are null. Discard the
- request. */
- return;
- else
- {
- /* The write method was implemented, use that. */
- file->to_write (file, buf, strlen (buf));
- }
-}
-
-static void
-null_file_delete (file)
- struct gdb_file *file;
-{
- return;
-}
-
-void *
-gdb_file_data (file)
- struct gdb_file *file;
-{
- if (file->magic != &gdb_file_magic)
- internal_error ("gdb_file_data: bad magic number");
- return file->to_data;
-}
-
-void
-gdb_flush (file)
- struct gdb_file *file;
-{
- file->to_flush (file);
-}
-
-int
-gdb_file_isatty (file)
- struct gdb_file *file;
-{
- return file->to_isatty (file);
-}
-
-void
-gdb_file_rewind (file)
- struct gdb_file *file;
-{
- file->to_rewind (file);
-}
-
-void
-gdb_file_put (struct gdb_file *file,
- gdb_file_put_method_ftype *write,
- void *dest)
-{
- file->to_put (file, write, dest);
-}
-
-void
-gdb_file_write (struct gdb_file *file,
- const char *buf,
- long length_buf)
-{
- file->to_write (file, buf, length_buf);
-}
-
-void
-fputs_unfiltered (buf, file)
- const char *buf;
- struct gdb_file *file;
-{
- file->to_fputs (buf, file);
-}
-
-void
-set_gdb_file_flush (file, flush)
- struct gdb_file *file;
- gdb_file_flush_ftype *flush;
-{
- file->to_flush = flush;
-}
-
-void
-set_gdb_file_isatty (file, isatty)
- struct gdb_file *file;
- gdb_file_isatty_ftype *isatty;
-{
- file->to_isatty = isatty;
-}
-
-void
-set_gdb_file_rewind (file, rewind)
- struct gdb_file *file;
- gdb_file_rewind_ftype *rewind;
-{
- file->to_rewind = rewind;
-}
-
-void
-set_gdb_file_put (file, put)
- struct gdb_file *file;
- gdb_file_put_ftype *put;
-{
- file->to_put = put;
-}
-
-void
-set_gdb_file_write (struct gdb_file *file,
- gdb_file_write_ftype *write)
-{
- file->to_write = write;
-}
-
-void
-set_gdb_file_fputs (file, fputs)
- struct gdb_file *file;
- gdb_file_fputs_ftype *fputs;
-{
- file->to_fputs = fputs;
-}
-
-void
-set_gdb_file_data (file, data, delete)
- struct gdb_file *file;
- void *data;
- gdb_file_delete_ftype *delete;
-{
- file->to_data = data;
- file->to_delete = delete;
-}
-
-/* gdb_file utility function for converting a ``struct gdb_file'' into
- a memory buffer''. */
-
-struct accumulated_gdb_file
-{
- char *buffer;
- long length;
-};
-
-static void
-do_gdb_file_xstrdup (void *context, const char *buffer, long length)
-{
- struct accumulated_gdb_file *acc = context;
- if (acc->buffer == NULL)
- acc->buffer = xmalloc (length + 1);
- else
- acc->buffer = xrealloc (acc->buffer, acc->length + length + 1);
- memcpy (acc->buffer + acc->length, buffer, length);
- acc->length += length;
- acc->buffer[acc->length] = '\0';
-}
-
-char *
-gdb_file_xstrdup (struct gdb_file *file,
- long *length)
-{
- struct accumulated_gdb_file acc;
- acc.buffer = NULL;
- acc.length = 0;
- gdb_file_put (file, do_gdb_file_xstrdup, &acc);
- if (acc.buffer == NULL)
- acc.buffer = xstrdup ("");
- *length = acc.length;
- return acc.buffer;
-}
-
-
/* Like fputs but if FILTER is true, pause after every screenful.
Regardless of FILTER can wrap at points other than the final
diff --git a/gdb/valops.c b/gdb/valops.c
index 66e35e7..3e1a619 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -1292,6 +1292,7 @@ hand_function_call (function, nargs, args)
{
register CORE_ADDR sp;
register int i;
+ int rc;
CORE_ADDR start_sp;
/* CALL_DUMMY is an array of words (REGISTER_SIZE), but each word
is in host byte order. Before calling FIX_CALL_DUMMY, we byteswap it
@@ -1687,9 +1688,28 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
/* Execute the stack dummy routine, calling FUNCTION.
When it is done, discard the empty frame
after storing the contents of all regs into retbuf. */
- if (run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf))
+ rc = run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf);
+
+ if (rc == 1)
+ {
+ /* We stopped inside the FUNCTION because of a random signal.
+ Further execution of the FUNCTION is not allowed. */
+
+ /* In this case, we must do the cleanups because we don't
+ want the dummy anymore (the dummy frame has been poped already. */
+ do_cleanups (old_chain);
+
+ /* FIXME: Insert a bunch of wrap_here; name can be very long if it's
+ a C++ name with arguments and stuff. */
+ error ("\
+The program being debugged stopped while in a function called from GDB.\n\
+Evaluation of the expression containing the function (%s) will be abandoned.",
+ name);
+ }
+
+ if (rc == 2)
{
- /* We stopped somewhere besides the call dummy. */
+ /* We hit a breakpoint inside the FUNCTION. */
/* If we did the cleanups, we would print a spurious error
message (Unable to restore previously selected frame),
@@ -1714,6 +1734,7 @@ stop (instead of continuing to evaluate the expression containing\n\
the function call).", name);
}
+ /* If we get here the called FUNCTION run to completion. */
do_cleanups (old_chain);
/* Figure out the value returned by the function. */