import gdb-2000-01-31 snapshot
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 @@
 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 @@
 	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 @@
 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 @@
 	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 @@
 
 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 @@
 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 @@
 #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 @@
    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 @@
      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 @@
   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 @@
     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 @@
 
       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 @@
 		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 @@
 	  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 @@
 	  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 @@
 {
   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 @@
   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 @@
 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 @@
 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 @@
 
 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 @@
 
 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 @@
 
 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 @@
 # 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 @@
 
 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 @@
 
 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 @@
 
 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 @@
 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 @@
 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 @@
 
 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 @@
 #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 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 @@
 				   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 @@
 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 @@
   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 @@
       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 @@
 
 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 @@
        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 @@
 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 @@
 /* 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 @@
 
 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,171 +22,18 @@
 #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>
-
-/* @@@ 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.
- */
-
-static int reg_offset[] =
-{
-  REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
-  REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
-  REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
-  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))
-
-/*
- * Fetch inferiors registers for gdb.
- * REG specifies which (as gdb views it) register, -1 for all.
- */
-void
-gnu_fetch_registers (int reg)
-{
-  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);
-
-  if (!state)
-    warning ("Couldn't fetch register %s from %s (invalid thread).",
-	     REGISTER_NAME (reg), proc_string (thread));
-  else if (reg >= 0)
-    {
-      proc_debug (thread, "fetching register: %s", REGISTER_NAME (reg));
-      supply_register (reg, REG_ADDR (state, reg));
-      thread->fetched_regs |= (1 << reg);
-    }
-  else
-    {
-      proc_debug (thread, "fetching all registers");
-      for (reg = 0; reg < NUM_REGS; reg++)
-	supply_register (reg, REG_ADDR (state, reg));
-      thread->fetched_regs = ~0;
-    }
-}
-
-/* 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.
- */
-void
-gnu_store_registers (reg)
-     int reg;
-{
-  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.  */
-
-  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));
-
-  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 (!was_aborted && was_valid)
-	/* See which registers have changed after aborting the thread.  */
-	{
-	  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...");
-	      }
-	}
-
-      if (reg >= 0)
-	{
-	  proc_debug (thread, "storing register: %s", REGISTER_NAME (reg));
-	  STORE_REGS (state, reg, 1);
-	}
-      else
-	{
-	  proc_debug (thread, "storing all registers");
-	  for (reg = 0; reg < NUM_REGS; reg++)
-	    STORE_REGS (state, reg, 1);
-	}
-    }
-}
-
-/* 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
- */
+/* The FPU hardware state.  */
 struct env387
 {
   unsigned short control;
@@ -203,166 +50,283 @@
   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;
+
+
+/* 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[] =
 {
-  int i;
-  int bothstatus;
-  int top;
-  int fpreg;
-  unsigned char *p;
+  REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
+  REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
+  REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
+  REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
+};
 
-  bothstatus = ((status != 0) && (ep->status != 0));
-  if (status != 0)
-    {
-      if (bothstatus)
-	printf_unfiltered ("u: ");
-      print_387_status_word (status);
-    }
+#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
 
-  if (ep->status != 0)
-    {
-      if (bothstatus)
-	printf_unfiltered ("e: ");
-      print_387_status_word (ep->status);
-    }
-
-  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--)
-    {
-      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);
-    }
-  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
+
+/* Get the whole floating-point state of THREAD and record the
+   values of the corresponding (pseudo) registers.  */
+static void
+fetch_fpregs (struct proc *thread)
 {
-#if 1
-  unsigned char state[FP_STATE_BYTES];	/* "hardware" state */
-#else
-  struct env387 state;		/* Actually this */
-#endif
-  int status;			/* Duplicate status */
-}
- *fpstate_t;
-
-/* Mach 3 specific routines.
- */
-static int
-get_i387_state (fstate)
-     struct fpstate *fstate;
-{
+  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;
-  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);
+  int i;
 
-  if (!thread)
-    error ("get_i387_state: Invalid thread");
-
-  proc_abort (thread, 0);	/* Make sure THREAD's in a reasonable state. */
-
-  err = thread_get_state (thread->port, i386_FLOAT_STATE, state, &fsCnt);
+  err = thread_get_state (thread->port, i386_FLOAT_STATE,
+			  (thread_state_t) &state, &count);
   if (err)
     {
-      warning ("Can not get live floating point state: %s",
-	       mach_error_string (err));
-      return 0;
-    }
-
-  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));
-
-  fstate->status = fsp->exc_status;
-
-  memcpy (fstate->state, (char *) &fsp->hw_state, FP_STATE_BYTES);
-
-  return 1;
-}
-
-/*
- * 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 (target_has_execution)
-    valid = get_i387_state (buf);
-
-  if (!valid)
-    {
-      warning ("no floating point status saved");
+      warning ("Couldn't fetch floating-point state from %s",
+	       proc_string (thread));
       return;
     }
 
-  fps = (fpstate_t) buf;
+  if (! state.initialized)
+    /* The floating-point state isn't initialized.  */
+    {
+      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);
 
-  print_387_status (fps->status, (struct env387 *) fps->state);
+      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);
+  }
+}
+
+/* Fetch register REGNO, or all regs if REGNO is -1.  */
+void
+gnu_fetch_registers (int regno)
+{
+  struct proc *thread;
+
+  /* Make sure we know about new threads.  */
+  inf_update_procs (current_inferior);
+
+  thread = inf_tid_to_thread (current_inferior, inferior_pid);
+  if (!thread)
+    error ("Can't fetch registers from thread %d: No such thread",
+	   inferior_pid);
+
+  if (regno < NUM_GREGS || regno == -1)
+    {
+      thread_state_t state;
+      
+      /* This does the dirty work for us.  */
+      state = proc_get_state (thread, 0);
+      if (!state)
+	{
+	  warning ("Couldn't fetch registers from %s",
+		   proc_string (thread));
+	  return;
+	}
+
+      if (regno == -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, "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);
+    }
+}
+
+
+/* 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;
+
+  /* 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;
+
+  err = thread_get_state (thread->port, i386_FLOAT_STATE,
+			  (thread_state_t) &state, &count);
+  if (err)
+    {
+      warning ("Couldn't fetch floating-point state from %s",
+	       proc_string (thread));
+      return;
+    }
+
+  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)
+    {
+      warning ("Couldn't store floating-point state into %s",
+	       proc_string (thread));
+      return;
+    }
+}
+
+/* Store at least register REGNO, or all regs if REGNO == -1.  */
+void
+gnu_store_registers (int regno)
+{
+  struct proc *thread;
+
+  /* Make sure we know about new threads.  */
+  inf_update_procs (current_inferior);
+
+  thread = inf_tid_to_thread (current_inferior, inferior_pid);
+  if (!thread)
+    error ("Couldn't store registers into thread %d: No such thread",
+	   inferior_pid);
+
+  if (regno < NUM_GREGS || regno == -1)
+    {
+      thread_state_t state;
+      thread_state_data_t old_state;
+      int was_aborted = thread->aborted;
+      int was_valid = thread->state_valid;
+
+      if (!was_aborted && was_valid)
+	memcpy (&old_state, &thread->state, sizeof (old_state));
+
+      state = proc_get_state (thread, 1);
+      if (!state)
+	{
+	  warning ("Couldn't store registers into %s", proc_string (thread));
+	  return;
+	}
+
+      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...");
+	      }
+	}
+
+#define fill(state, regno)                                               \
+  memcpy (REG_ADDR(state, regno), &registers[REGISTER_BYTE (regno)],     \
+          REGISTER_RAW_SIZE (regno))
+
+      if (regno == -1)
+	{
+	  int i;
+	  
+	  proc_debug (thread, "storing all registers");
+
+	  for (i = 0; i < NUM_GREGS; i++)
+	    if (register_valid[i])
+	      fill (state, i);
+	}
+      else
+	{
+	  proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
+
+	  assert (register_valid[regno]);
+	  fill (state, regno);
+	}
+    }
+
+#undef fill
+
+  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 @@
    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 @@
 
   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 @@
   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 @@
 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 @@
   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 @@
 
   /* 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 @@
     }
   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 @@
       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 @@
 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 @@
 }
 
 
-/* ``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 @@
 {
   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 @@
     /* 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 somewhere besides the call dummy.  */
+	/* 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 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 @@
 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.  */