20000-05-18 H.J. Lu (hjl@gnu.org)
[binutils-gdb.git] / gdb / utils.c
index e657c5a374febb66c47ef346ad951f9388df78a9..45fdb1dd47b8055dd5858fac1ee51e0ccade7802 100644 (file)
@@ -1,5 +1,6 @@
 /* General utility routines for GDB, the GNU debugger.
-   Copyright 1986, 89, 90, 91, 92, 95, 96, 1998 Free Software Foundation, Inc.
+   Copyright 1986, 1989, 1990-1992, 1995, 1996, 1998, 2000
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include <term.h>
 #endif
 
+#ifdef __GO32__
+#include <pc.h>
+#endif
+
 /* SunOS's curses.h has a '#define reg register' in it.  Thank you Sun. */
 #ifdef reg
 #undef reg
@@ -57,14 +62,14 @@ void (*error_begin_hook) PARAMS ((void));
 
 /* Holds the last error message issued by gdb */
 
-static GDB_FILE *gdb_lasterr;
+static struct ui_file *gdb_lasterr;
 
 /* Prototypes for local functions */
 
-static void vfprintf_maybe_filtered PARAMS ((GDB_FILE *, const char *,
-                                            va_list, int));
+static void vfprintf_maybe_filtered (struct ui_file *, const char *,
+                                    va_list, int);
 
-static void fputs_maybe_filtered PARAMS ((const char *, GDB_FILE *, int));
+static void fputs_maybe_filtered (const char *, struct ui_file *, int);
 
 #if defined (USE_MMALLOC) && !defined (NO_MMCHECK)
 static void malloc_botch PARAMS ((void));
@@ -79,10 +84,6 @@ set_width_command PARAMS ((char *, int, struct cmd_list_element *));
 static void
 set_width PARAMS ((void));
 
-#ifndef GDB_FILE_ISATTY
-#define GDB_FILE_ISATTY(GDB_FILE_PTR)   (gdb_file_isatty(GDB_FILE_PTR))
-#endif
-
 /* Chain of cleanup actions established with make_cleanup,
    to be executed if an error happens.  */
 
@@ -98,6 +99,7 @@ static struct cleanup *exec_error_cleanup_chain;
    support async execution.  The finish and until commands use it. So
    does the target extended-remote command. */
 struct continuation *cmd_continuation;
+struct continuation *intermediate_continuation;
 
 /* Nonzero if we have job control. */
 
@@ -158,41 +160,31 @@ int pagination_enabled = 1;
    Args are FUNCTION to clean up with, and ARG to pass to it.  */
 
 struct cleanup *
-make_cleanup (function, arg)
-     void (*function) PARAMS ((PTR));
-     PTR arg;
+make_cleanup (make_cleanup_ftype *function, void *arg)
 {
   return make_my_cleanup (&cleanup_chain, function, arg);
 }
 
 struct cleanup *
-make_final_cleanup (function, arg)
-     void (*function) PARAMS ((PTR));
-     PTR arg;
+make_final_cleanup (make_cleanup_ftype *function, void *arg)
 {
   return make_my_cleanup (&final_cleanup_chain, function, arg);
 }
 
 struct cleanup *
-make_run_cleanup (function, arg)
-     void (*function) PARAMS ((PTR));
-     PTR arg;
+make_run_cleanup (make_cleanup_ftype *function, void *arg)
 {
   return make_my_cleanup (&run_cleanup_chain, function, arg);
 }
 
 struct cleanup *
-make_exec_cleanup (function, arg)
-     void (*function) PARAMS ((PTR));
-     PTR arg;
+make_exec_cleanup (make_cleanup_ftype *function, void *arg)
 {
   return make_my_cleanup (&exec_cleanup_chain, function, arg);
 }
 
 struct cleanup *
-make_exec_error_cleanup (function, arg)
-     void (*function) PARAMS ((PTR));
-     PTR arg;
+make_exec_error_cleanup (make_cleanup_ftype *function, void *arg)
 {
   return make_my_cleanup (&exec_error_cleanup_chain, function, arg);
 }
@@ -211,11 +203,33 @@ make_cleanup_freeargv (arg)
   return make_my_cleanup (&cleanup_chain, do_freeargv, arg);
 }
 
+static void
+do_bfd_close_cleanup (void *arg)
+{
+  bfd_close (arg);
+}
+
 struct cleanup *
-make_my_cleanup (pmy_chain, function, arg)
-     struct cleanup **pmy_chain;
-     void (*function) PARAMS ((PTR));
-     PTR arg;
+make_cleanup_bfd_close (bfd *abfd)
+{
+  return make_cleanup (do_bfd_close_cleanup, abfd);
+}
+
+static void
+do_ui_file_delete (void *arg)
+{
+  ui_file_delete (arg);
+}
+
+struct cleanup *
+make_cleanup_ui_file_delete (struct ui_file *arg)
+{
+  return make_my_cleanup (&cleanup_chain, do_ui_file_delete, arg);
+}
+
+struct cleanup *
+make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
+                void *arg)
 {
   register struct cleanup *new
   = (struct cleanup *) xmalloc (sizeof (struct cleanup));
@@ -314,7 +328,7 @@ discard_my_cleanups (pmy_chain, old_chain)
   while ((ptr = *pmy_chain) != old_chain)
     {
       *pmy_chain = ptr->next;
-      free ((PTR) ptr);
+      free (ptr);
     }
 }
 
@@ -373,10 +387,16 @@ restore_my_cleanups (pmy_chain, chain)
    to arrange to free the object thus allocated.  */
 
 void
-free_current_contents (location)
-     char **location;
+free_current_contents (void *ptr)
 {
-  free (*location);
+  void **location = ptr;
+  if (location == NULL)
+    internal_error ("free_current_contents: NULL pointer");
+  if (*location != NULL)
+    {
+      free (*location);
+      *location = NULL;
+    }
 }
 
 /* Provide a known function that does nothing, to use as a base for
@@ -388,13 +408,12 @@ free_current_contents (location)
 
 /* ARGSUSED */
 void
-null_cleanup (arg)
-     PTR arg;
+null_cleanup (void *arg)
 {
 }
 
 /* Add a continuation to the continuation list, the gloabl list
-   cmd_continuation. */
+   cmd_continuation. The new continuation will be added at the front.*/
 void
 add_continuation (continuation_hook, arg_list)
      void (*continuation_hook) PARAMS ((struct continuation_arg *));
@@ -410,32 +429,109 @@ add_continuation (continuation_hook, arg_list)
 }
 
 /* Walk down the cmd_continuation list, and execute all the
-   continuations. */
+   continuations. There is a problem though. In some cases new
+   continuations may be added while we are in the middle of this
+   loop. If this happens they will be added in the front, and done
+   before we have a chance of exhausting those that were already
+   there. We need to then save the beginning of the list in a pointer
+   and do the continuations from there on, instead of using the
+   global beginning of list as our iteration pointer.*/
 void
 do_all_continuations ()
+{
+  struct continuation *continuation_ptr;
+  struct continuation *saved_continuation;
+
+  /* Copy the list header into another pointer, and set the global
+     list header to null, so that the global list can change as a side
+     effect of invoking the continuations and the processing of
+     the preexisting continuations will not be affected. */
+  continuation_ptr = cmd_continuation;
+  cmd_continuation = NULL;
+
+  /* Work now on the list we have set aside. */
+  while (continuation_ptr)
+     {
+       (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
+       saved_continuation = continuation_ptr;
+       continuation_ptr = continuation_ptr->next;
+       free (saved_continuation);
+     }
+}
+
+/* Walk down the cmd_continuation list, and get rid of all the
+   continuations. */
+void
+discard_all_continuations ()
 {
   struct continuation *continuation_ptr;
 
   while (cmd_continuation)
     {
-      (cmd_continuation->continuation_hook) (cmd_continuation->arg_list);
       continuation_ptr = cmd_continuation;
       cmd_continuation = continuation_ptr->next;
       free (continuation_ptr);
     }
 }
 
+/* Add a continuation to the continuation list, the global list
+   intermediate_continuation. The new continuation will be added at the front.*/
+void
+add_intermediate_continuation (continuation_hook, arg_list)
+     void (*continuation_hook) PARAMS ((struct continuation_arg *));
+     struct continuation_arg *arg_list;
+{
+  struct continuation *continuation_ptr;
+
+  continuation_ptr = (struct continuation *) xmalloc (sizeof (struct continuation));
+  continuation_ptr->continuation_hook = continuation_hook;
+  continuation_ptr->arg_list = arg_list;
+  continuation_ptr->next = intermediate_continuation;
+  intermediate_continuation = continuation_ptr;
+}
+
+/* Walk down the cmd_continuation list, and execute all the
+   continuations. There is a problem though. In some cases new
+   continuations may be added while we are in the middle of this
+   loop. If this happens they will be added in the front, and done
+   before we have a chance of exhausting those that were already
+   there. We need to then save the beginning of the list in a pointer
+   and do the continuations from there on, instead of using the
+   global beginning of list as our iteration pointer.*/
+void
+do_all_intermediate_continuations ()
+{
+  struct continuation *continuation_ptr;
+  struct continuation *saved_continuation;
+
+  /* Copy the list header into another pointer, and set the global
+     list header to null, so that the global list can change as a side
+     effect of invoking the continuations and the processing of
+     the preexisting continuations will not be affected. */
+  continuation_ptr = intermediate_continuation;
+  intermediate_continuation = NULL;
+
+  /* Work now on the list we have set aside. */
+  while (continuation_ptr)
+     {
+       (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
+       saved_continuation = continuation_ptr;
+       continuation_ptr = continuation_ptr->next;
+       free (saved_continuation);
+     }
+}
+
 /* Walk down the cmd_continuation list, and get rid of all the
    continuations. */
 void
-discard_all_continuations ()
+discard_all_intermediate_continuations ()
 {
   struct continuation *continuation_ptr;
 
-  while (cmd_continuation)
+  while (intermediate_continuation)
     {
-      continuation_ptr = cmd_continuation;
-      cmd_continuation = continuation_ptr->next;
+      continuation_ptr = intermediate_continuation;
+      intermediate_continuation = continuation_ptr->next;
       free (continuation_ptr);
     }
 }
@@ -510,32 +606,50 @@ error_begin ()
    The first argument STRING is the error message, used as a fprintf string,
    and the remaining args are passed as arguments to it.  */
 
+NORETURN void
+verror (const char *string, va_list args)
+{
+  char *err_string;
+  struct cleanup *err_string_cleanup;
+  /* FIXME: cagney/1999-11-10: All error calls should come here.
+     Unfortunatly some code uses the sequence: error_begin(); print
+     error message; return_to_top_level.  That code should be
+     flushed. */
+  error_begin ();
+  /* NOTE: It's tempting to just do the following...
+       vfprintf_filtered (gdb_stderr, string, args);
+     and then follow with a similar looking statement to cause the message
+     to also go to gdb_lasterr.  But if we do this, we'll be traversing the
+     va_list twice which works on some platforms and fails miserably on
+     others. */
+  /* Save it as the last error */
+  ui_file_rewind (gdb_lasterr);
+  vfprintf_filtered (gdb_lasterr, string, args);
+  /* Retrieve the last error and print it to gdb_stderr */
+  err_string = error_last_message ();
+  err_string_cleanup = make_cleanup (free, err_string);
+  fputs_filtered (err_string, gdb_stderr);
+  fprintf_filtered (gdb_stderr, "\n");
+  do_cleanups (err_string_cleanup);
+  return_to_top_level (RETURN_ERROR);
+}
+
 NORETURN void
 error (const char *string,...)
 {
   va_list args;
   va_start (args, string);
-  if (error_hook)
-    (*error_hook) ();
-  else
-    {
-      error_begin ();
-      vfprintf_filtered (gdb_stderr, string, args);
-      fprintf_filtered (gdb_stderr, "\n");
-      /* Save it as the last error as well (no newline) */
-      gdb_file_rewind (gdb_lasterr);
-      vfprintf_filtered (gdb_lasterr, string, args);
-      va_end (args);
-      return_to_top_level (RETURN_ERROR);
-    }
+  verror (string, args);
+  va_end (args);
 }
 
-/* Allows the error message to be passed on a stream buffer */
-
 NORETURN void
-error_stream (GDB_FILE *stream)
+error_stream (struct ui_file *stream)
 {
-  error (gdb_file_get_strbuf (stream));
+  long size;
+  char *msg = ui_file_xstrdup (stream, &size);
+  make_cleanup (free, msg);
+  error ("%s", msg);
 }
 
 /* Get the last error message issued by gdb */
@@ -543,26 +657,26 @@ error_stream (GDB_FILE *stream)
 char *
 error_last_message (void)
 {
-  return (gdb_file_get_strbuf (gdb_lasterr));
+  long len;
+  return ui_file_xstrdup (gdb_lasterr, &len);
 }
-
+  
 /* This is to be called by main() at the very beginning */
 
 void
 error_init (void)
 {
-  gdb_lasterr = tui_sfileopen (132);
+  gdb_lasterr = mem_fileopen ();
 }
 
 /* Print a message reporting an internal error. Ask the user if they
    want to continue, dump core, or just exit. */
 
 NORETURN void
-internal_error (char *string, ...)
+internal_verror (const char *fmt, va_list ap)
 {
   static char msg[] = "Internal GDB error: recursive internal error.\n";
   static int dejavu = 0;
-  va_list args;
   int continue_p;
   int dump_core_p;
 
@@ -583,10 +697,9 @@ internal_error (char *string, ...)
     }
 
   /* Try to get the message out */
+  target_terminal_ours ();
   fputs_unfiltered ("gdb-internal-error: ", gdb_stderr);
-  va_start (args, string);
-  vfprintf_unfiltered (gdb_stderr, string, args);
-  va_end (args);
+  vfprintf_unfiltered (gdb_stderr, fmt, ap);
   fputs_unfiltered ("\n", gdb_stderr);
 
   /* Default (no case) is to quit GDB.  When in batch mode this
@@ -620,6 +733,16 @@ Create a core file containing the current state of GDB? ");
   return_to_top_level (RETURN_ERROR);
 }
 
+NORETURN void
+internal_error (char *string, ...)
+{
+  va_list ap;
+  va_start (ap, string);
+
+  internal_verror (string, ap);
+  va_end (ap);
+}
+
 /* The strerror() function can return NULL for errno values that are
    out of range.  Provide a "safe" version that always returns a
    printable string. */
@@ -775,7 +898,7 @@ notice_quit ()
     immediate_quit = 1;
 }
 
-#else /* !defined(__GO32__) && !defined(_MSC_VER) */
+#else /* !defined(_MSC_VER) */
 
 void
 notice_quit ()
@@ -783,7 +906,7 @@ notice_quit ()
   /* Done by signals */
 }
 
-#endif /* !defined(__GO32__) && !defined(_MSC_VER) */
+#endif /* !defined(_MSC_VER) */
 
 /* Control C comes here */
 void
@@ -816,6 +939,12 @@ request_quit (signo)
 
 #if !defined (USE_MMALLOC)
 
+PTR
+mcalloc (PTR md, size_t number, size_t size)
+{
+  return calloc (number, size);
+}
+
 PTR
 mmalloc (md, size)
      PTR md;
@@ -849,8 +978,7 @@ mfree (md, ptr)
 #if !defined (USE_MMALLOC) || defined (NO_MMCHECK)
 
 void
-init_malloc (md)
-     PTR md;
+init_malloc (void *md)
 {
 }
 
@@ -882,8 +1010,7 @@ malloc_botch ()
 #endif
 
 void
-init_malloc (md)
-     PTR md;
+init_malloc (void *md)
 {
   if (!mmcheckf (md, malloc_botch, MMCHECK_FORCE))
     {
@@ -977,6 +1104,17 @@ xmalloc (size)
   return (xmmalloc ((PTR) NULL, size));
 }
 
+/* Like calloc but get error if no storage available */
+
+PTR
+xcalloc (size_t number, size_t size)
+{
+  void *mem = mcalloc (NULL, number, size);
+  if (mem == NULL)
+    nomem (number * size);
+  return mem;
+}
+
 /* Like mrealloc but get error if no storage available.  */
 
 PTR
@@ -1029,10 +1167,7 @@ savestring (ptr, size)
 }
 
 char *
-msavestring (md, ptr, size)
-     PTR md;
-     const char *ptr;
-     int size;
+msavestring (void *md, const char *ptr, int size)
 {
   register char *p = (char *) xmmalloc (md, size + 1);
   memcpy (p, ptr, size);
@@ -1051,9 +1186,7 @@ strsave (ptr)
 }
 
 char *
-mstrsave (md, ptr)
-     PTR md;
-     const char *ptr;
+mstrsave (void *md, const char *ptr)
 {
   return (msavestring (md, ptr, strlen (ptr)));
 }
@@ -1061,7 +1194,7 @@ mstrsave (md, ptr)
 void
 print_spaces (n, file)
      register int n;
-     register GDB_FILE *file;
+     register struct ui_file *file;
 {
   fputs_unfiltered (n_spaces (n), file);
 }
@@ -1069,7 +1202,7 @@ print_spaces (n, file)
 /* Print a host address.  */
 
 void
-gdb_print_host_address (void *addr, struct gdb_file *stream)
+gdb_print_host_address (void *addr, struct ui_file *stream)
 {
 
   /* We could use the %p conversion specifier to fprintf if we had any
@@ -1273,14 +1406,14 @@ parse_escape (string_ptr)
    be call for printing things which are independent of the language
    of the program being debugged. */
 
-static void printchar PARAMS ((int c, void (*do_fputs) (const char *, GDB_FILE*), void (*do_fprintf) (GDB_FILE*, const char *, ...), GDB_FILE *stream, int quoter));
+static void printchar (int c, void (*do_fputs) (const char *, struct ui_file*), void (*do_fprintf) (struct ui_file*, const char *, ...), struct ui_file *stream, int quoter);
 
 static void
 printchar (c, do_fputs, do_fprintf, stream, quoter)
      int c;
-     void (*do_fputs) PARAMS ((const char *, GDB_FILE*));
-     void (*do_fprintf) PARAMS ((GDB_FILE*, const char *, ...));
-     GDB_FILE *stream;
+     void (*do_fputs) PARAMS ((const char *, struct ui_file*));
+     void (*do_fprintf) PARAMS ((struct ui_file*, const char *, ...));
+     struct ui_file *stream;
      int quoter;
 {
 
@@ -1335,7 +1468,7 @@ void
 fputstr_filtered (str, quoter, stream)
      const char *str;
      int quoter;
-     GDB_FILE *stream;
+     struct ui_file *stream;
 {
   while (*str)
     printchar (*str++, fputs_filtered, fprintf_filtered, stream, quoter);
@@ -1345,7 +1478,7 @@ void
 fputstr_unfiltered (str, quoter, stream)
      const char *str;
      int quoter;
-     GDB_FILE *stream;
+     struct ui_file *stream;
 {
   while (*str)
     printchar (*str++, fputs_unfiltered, fprintf_unfiltered, stream, quoter);
@@ -1356,7 +1489,7 @@ fputstrn_unfiltered (str, n, quoter, stream)
      const char *str;
      int n;
      int quoter;
-     GDB_FILE *stream;
+     struct ui_file *stream;
 {
   int i;
   for (i = 0; i < n; i++)
@@ -1466,7 +1599,7 @@ init_page_info ()
 #endif
 #endif
       /* If the output is not a terminal, don't paginate it.  */
-      if (!GDB_FILE_ISATTY (gdb_stdout))
+      if (!ui_file_isatty (gdb_stdout))
        lines_per_page = UINT_MAX;
     }                          /* the command_line_version */
   set_width ();
@@ -1640,704 +1773,6 @@ begin_line ()
 }
 
 
-/* ``struct gdb_file'' implementation that maps directly onto
-   <stdio.h>'s FILE. */
-
-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_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)
-    error ("Internal error: 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)
-    error ("Internal error: bad magic number");
-  fflush (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)
-    error ("Internal error: 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)
-    error ("Internal error: 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
-   collector. It's input is available through gdb_file_put(). */
-
-struct mem_file
-  {
-    int *magic;
-    char *buffer;
-    int sizeof_buffer;
-    int strlen_buffer;
-  };
-
-extern gdb_file_fputs_ftype mem_file_fputs;
-static gdb_file_rewind_ftype mem_file_rewind;
-static gdb_file_put_ftype mem_file_put;
-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_fputs (file, mem_file_fputs);
-  set_gdb_file_rewind (file, mem_file_rewind);
-  set_gdb_file_put (file, mem_file_put);
-  stream->magic = &mem_file_magic;
-  stream->buffer = NULL;
-  stream->sizeof_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");
-  if (stream->buffer != NULL)
-    {
-      stream->buffer[0] = '\0';
-      stream->strlen_buffer = 0;
-    }
-}
-
-static void
-mem_file_put (struct gdb_file *file, struct gdb_file *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->buffer != NULL)
-    fputs_unfiltered (stream->buffer, dest);
-}
-
-void
-mem_file_fputs (const char *linebuffer, struct gdb_file *file)
-{
-  struct mem_file *stream = gdb_file_data (file);
-  if (stream->magic != &mem_file_magic)
-    internal_error ("mem_file_fputs: bad magic number");
-  if (stream->buffer == NULL)
-    {
-      stream->strlen_buffer = strlen (linebuffer);
-      stream->sizeof_buffer = stream->strlen_buffer + 1;
-      stream->buffer = xmalloc (stream->sizeof_buffer);
-      strcpy (stream->buffer, linebuffer);
-    }
-  else
-    {
-      int len = strlen (linebuffer);
-      int new_strlen = stream->strlen_buffer + len;
-      int new_sizeof = new_strlen + 1;
-      if (new_sizeof >= stream->sizeof_buffer)
-       {
-         stream->sizeof_buffer = new_sizeof;
-         stream->buffer = xrealloc (stream->buffer, stream->sizeof_buffer);
-       }
-      strcpy (stream->buffer + stream->strlen_buffer, linebuffer);
-      stream->strlen_buffer = new_strlen;
-    }
-}
-
-
-/* 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)
-    error ("Internal error: 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 gdb_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)
-    error ("Internal error: 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)
-    error ("Internal error: bad magic number");
-  stream->ts_strbuf[0] = '\0';
-}
-
-static void
-tui_file_put (file, dest)
-     struct gdb_file *file;
-     struct gdb_file *dest;
-{
-  struct tui_stream *stream = gdb_file_data (file);
-  if (stream->ts_magic != &tui_file_magic)
-    error ("Internal error: bad magic number");
-  if (stream->ts_streamtype == astring)
-    {
-      fputs_unfiltered (stream->ts_strbuf, dest);
-    }
-}
-
-/* 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)
-           {
-             gdb_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)
-           {
-             gdb_file_adjust_strbuf (strlen (linebuffer), stream);
-             strcat (stream->ts_strbuf, linebuffer);
-           }
-         else
-           fputs (linebuffer, stream->ts_filestream);
-       }
-
-
-#else
-      if (stream->ts_streamtype == astring)
-       {
-         gdb_file_adjust_strbuf (strlen (linebuffer), file);
-         strcat (stream->ts_strbuf, linebuffer);
-       }
-      else
-       fputs (linebuffer, stream->ts_filestream);
-#endif
-    }
-}
-
-/* DEPRECATED: Use tui_sfileopen() instead */
-
-GDB_FILE *
-gdb_file_init_astring (n)
-     int n;
-{
-  struct gdb_file *file = tui_file_new ();
-  struct tui_stream *tmpstream = gdb_file_data (file);
-  if (tmpstream->ts_magic != &tui_file_magic)
-    error ("Internal error: bad magic number");
-
-  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
-    tmpstream->ts_strbuf = NULL;
-  tmpstream->ts_buflen = n;
-
-  return file;
-}
-
-void
-gdb_file_deallocate (streamptr)
-     GDB_FILE **streamptr;
-{
-  gdb_file_delete (*streamptr);
-  *streamptr = NULL;
-}
-
-char *
-gdb_file_get_strbuf (file)
-     GDB_FILE *file;
-{
-  struct tui_stream *stream = gdb_file_data (file);
-  if (stream->ts_magic != &tui_file_magic)
-    error ("Internal error: 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
-gdb_file_adjust_strbuf (n, file)
-     int n;
-     GDB_FILE *file;
-{
-  struct tui_stream *stream = gdb_file_data (file);
-  int non_null_chars;
-  if (stream->ts_magic != &tui_file_magic)
-    error ("Internal error: 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;
-    }
-}
-
-void
-gdb_fclose (streamptr)
-     GDB_FILE **streamptr;
-{
-  gdb_file_delete (*streamptr);
-  *streamptr = NULL;
-}
-
-
-/* Implement the ``struct gdb_file'' object. */
-
-static gdb_file_isatty_ftype null_file_isatty;
-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
-  {
-    gdb_file_flush_ftype *to_flush;
-    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;
-  };
-
-struct gdb_file *
-gdb_file_new ()
-{
-  struct gdb_file *file = xmalloc (sizeof (struct gdb_file));
-  set_gdb_file_data (file, NULL, null_file_delete);
-  set_gdb_file_flush (file, null_file_flush);
-  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 (file, src)
-     struct gdb_file *file;
-     struct gdb_file *src;
-{
-  return;
-}
-
-static void
-null_file_flush (file)
-     struct gdb_file *file;
-{
-  return;
-}
-
-static void
-null_file_fputs (buf, file)
-     const char *buf;
-     struct gdb_file *file;
-{
-  return;
-}
-
-static void
-null_file_delete (file)
-     struct gdb_file *file;
-{
-  return;
-}
-
-void *
-gdb_file_data (file)
-     struct gdb_file *file;
-{
-  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 (file, dest)
-     struct gdb_file *file;
-     struct gdb_file *dest;
-{
-  file->to_put (file, dest);
-}
-
-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_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;
-}
-
 /* Like fputs but if FILTER is true, pause after every screenful.
 
    Regardless of FILTER can wrap at points other than the final
@@ -2354,7 +1789,7 @@ set_gdb_file_data (file, data, delete)
 static void
 fputs_maybe_filtered (linebuffer, stream, filter)
      const char *linebuffer;
-     GDB_FILE *stream;
+     struct ui_file *stream;
      int filter;
 {
   const char *lineptr;
@@ -2458,7 +1893,7 @@ fputs_maybe_filtered (linebuffer, stream, filter)
 void
 fputs_filtered (linebuffer, stream)
      const char *linebuffer;
-     GDB_FILE *stream;
+     struct ui_file *stream;
 {
   fputs_maybe_filtered (linebuffer, stream, 1);
 }
@@ -2467,31 +1902,25 @@ int
 putchar_unfiltered (c)
      int c;
 {
-  char buf[2];
-
-  buf[0] = c;
-  buf[1] = 0;
-  fputs_unfiltered (buf, gdb_stdout);
+  char buf = c;
+  ui_file_write (gdb_stdout, &buf, 1);
   return c;
 }
 
 int
 fputc_unfiltered (c, stream)
      int c;
-     GDB_FILE *stream;
+     struct ui_file *stream;
 {
-  char buf[2];
-
-  buf[0] = c;
-  buf[1] = 0;
-  fputs_unfiltered (buf, stream);
+  char buf = c;
+  ui_file_write (stream, &buf, 1);
   return c;
 }
 
 int
 fputc_filtered (c, stream)
      int c;
-     GDB_FILE *stream;
+     struct ui_file *stream;
 {
   char buf[2];
 
@@ -2605,7 +2034,7 @@ puts_debug (prefix, string, suffix)
 
 static void
 vfprintf_maybe_filtered (stream, format, args, filter)
-     GDB_FILE *stream;
+     struct ui_file *stream;
      const char *format;
      va_list args;
      int filter;
@@ -2627,7 +2056,7 @@ vfprintf_maybe_filtered (stream, format, args, filter)
 
 void
 vfprintf_filtered (stream, format, args)
-     GDB_FILE *stream;
+     struct ui_file *stream;
      const char *format;
      va_list args;
 {
@@ -2636,7 +2065,7 @@ vfprintf_filtered (stream, format, args)
 
 void
 vfprintf_unfiltered (stream, format, args)
-     GDB_FILE *stream;
+     struct ui_file *stream;
      const char *format;
      va_list args;
 {
@@ -2671,7 +2100,7 @@ vprintf_unfiltered (format, args)
 }
 
 void
-fprintf_filtered (GDB_FILE * stream, const char *format,...)
+fprintf_filtered (struct ui_file * stream, const char *format,...)
 {
   va_list args;
   va_start (args, format);
@@ -2680,7 +2109,7 @@ fprintf_filtered (GDB_FILE * stream, const char *format,...)
 }
 
 void
-fprintf_unfiltered (GDB_FILE * stream, const char *format,...)
+fprintf_unfiltered (struct ui_file * stream, const char *format,...)
 {
   va_list args;
   va_start (args, format);
@@ -2692,7 +2121,7 @@ fprintf_unfiltered (GDB_FILE * stream, const char *format,...)
    Called as fprintfi_filtered (spaces, stream, format, ...);  */
 
 void
-fprintfi_filtered (int spaces, GDB_FILE * stream, const char *format,...)
+fprintfi_filtered (int spaces, struct ui_file * stream, const char *format,...)
 {
   va_list args;
   va_start (args, format);
@@ -2782,7 +2211,7 @@ n_spaces (n)
 void
 print_spaces_filtered (n, stream)
      int n;
-     GDB_FILE *stream;
+     struct ui_file *stream;
 {
   fputs_filtered (n_spaces (n), stream);
 }
@@ -2796,7 +2225,7 @@ print_spaces_filtered (n, stream)
 
 void
 fprintf_symbol_filtered (stream, name, lang, arg_mode)
-     GDB_FILE *stream;
+     struct ui_file *stream;
      char *name;
      enum language lang;
      int arg_mode;
@@ -2937,7 +2366,7 @@ initialize_utils ()
   init_page_info ();
 
   /* If the output is not a terminal, don't paginate it.  */
-  if (!GDB_FILE_ISATTY (gdb_stdout))
+  if (!ui_file_isatty (gdb_stdout))
     lines_per_page = UINT_MAX;
 
   set_width_command ((char *) NULL, 0, c);
@@ -2954,6 +2383,7 @@ initialize_utils ()
                  var_boolean, (char *) &pagination_enabled,
                  "Set state of pagination.", &setlist),
      &showlist);
+
   if (xdb_commands)
     {
       add_com ("am", class_support, pagination_on_command,
@@ -3018,12 +2448,31 @@ get_field (data, order, total_len, start, len)
   int cur_bitshift;
 
   /* Start at the least significant part of the field.  */
-  cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
   if (order == floatformat_little || order == floatformat_littlebyte_bigword)
-    cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
-  cur_bitshift =
-    ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
-  result = *(data + cur_byte) >> (-cur_bitshift);
+    {
+      /* We start counting from the other end (i.e, from the high bytes
+        rather than the low bytes).  As such, we need to be concerned
+        with what happens if bit 0 doesn't start on a byte boundary. 
+        I.e, we need to properly handle the case where total_len is
+        not evenly divisible by 8.  So we compute ``excess'' which
+        represents the number of bits from the end of our starting
+        byte needed to get to bit 0. */
+      int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT);
+      cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) 
+                 - ((start + len + excess) / FLOATFORMAT_CHAR_BIT);
+      cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT) 
+                     - FLOATFORMAT_CHAR_BIT;
+    }
+  else
+    {
+      cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
+      cur_bitshift =
+       ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
+    }
+  if (cur_bitshift > -FLOATFORMAT_CHAR_BIT)
+    result = *(data + cur_byte) >> (-cur_bitshift);
+  else
+    result = 0;
   cur_bitshift += FLOATFORMAT_CHAR_BIT;
   if (order == floatformat_little || order == floatformat_littlebyte_bigword)
     ++cur_byte;
@@ -3033,20 +2482,16 @@ get_field (data, order, total_len, start, len)
   /* Move towards the most significant part of the field.  */
   while (cur_bitshift < len)
     {
-      if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
-       /* This is the last byte; zero out the bits which are not part of
-          this field.  */
-       result |=
-         (*(data + cur_byte) & ((1 << (len - cur_bitshift)) - 1))
-         << cur_bitshift;
-      else
-       result |= *(data + cur_byte) << cur_bitshift;
+      result |= (unsigned long)*(data + cur_byte) << cur_bitshift;
       cur_bitshift += FLOATFORMAT_CHAR_BIT;
       if (order == floatformat_little || order == floatformat_littlebyte_bigword)
        ++cur_byte;
       else
        --cur_byte;
     }
+  if (len < sizeof(result) * FLOATFORMAT_CHAR_BIT)
+    /* Mask out bits which are not part of the field */
+    result &= ((1UL << len) - 1);
   return result;
 }
 
@@ -3122,9 +2567,12 @@ floatformat_to_doublest (fmt, from, to)
 
   special_exponent = exponent == 0 || exponent == fmt->exp_nan;
 
-/* Don't bias zero's, denorms or NaNs.  */
+/* Don't bias NaNs. Use minimum exponent for denorms. For simplicity,
+   we don't check for zero as the exponent doesn't matter. */
   if (!special_exponent)
     exponent -= fmt->exp_bias;
+  else if (exponent == 0)
+    exponent = 1 - fmt->exp_bias;
 
   /* Build the result algebraically.  Might go infinite, underflow, etc;
      who cares. */
@@ -3180,15 +2628,28 @@ put_field (data, order, total_len, start, len, stuff_to_put)
   int cur_bitshift;
 
   /* Start at the least significant part of the field.  */
-  cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
   if (order == floatformat_little || order == floatformat_littlebyte_bigword)
-    cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
-  cur_bitshift =
-    ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
-  *(data + cur_byte) &=
-    ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1) << (-cur_bitshift));
-  *(data + cur_byte) |=
-    (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift);
+    {
+      int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT);
+      cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) 
+                 - ((start + len + excess) / FLOATFORMAT_CHAR_BIT);
+      cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT) 
+                     - FLOATFORMAT_CHAR_BIT;
+    }
+  else
+    {
+      cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
+      cur_bitshift =
+       ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
+    }
+  if (cur_bitshift > -FLOATFORMAT_CHAR_BIT)
+    {
+      *(data + cur_byte) &=
+       ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1)
+         << (-cur_bitshift));
+      *(data + cur_byte) |=
+       (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift);
+    }
   cur_bitshift += FLOATFORMAT_CHAR_BIT;
   if (order == floatformat_little || order == floatformat_littlebyte_bigword)
     ++cur_byte;
@@ -3282,7 +2743,8 @@ floatformat_from_doublest (fmt, from, to)
   unsigned char *uto = (unsigned char *) to;
 
   memcpy (&dfrom, from, sizeof (dfrom));
-  memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
+  memset (uto, 0, (fmt->totalsize + FLOATFORMAT_CHAR_BIT - 1) 
+                    / FLOATFORMAT_CHAR_BIT);
   if (dfrom == 0)
     return;                    /* Result is zero */
   if (dfrom != dfrom)          /* Result is NaN */
@@ -3331,7 +2793,7 @@ floatformat_from_doublest (fmt, from, to)
       mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
 
       mant *= 4294967296.0;
-      mant_long = (unsigned long) mant;
+      mant_long = ((unsigned long) mant) & 0xffffffffL;
       mant -= mant_long;
 
       /* If the integer bit is implicit, then we need to discard it.
@@ -3342,6 +2804,7 @@ floatformat_from_doublest (fmt, from, to)
          && fmt->intbit == floatformat_intbit_no)
        {
          mant_long <<= 1;
+         mant_long &= 0xffffffffL;
          mant_bits -= 1;
        }
 
@@ -3564,20 +3027,3 @@ preg_nz (reg)
     }
   return preg_str;
 }
-
-/* Helper functions for INNER_THAN */
-int
-core_addr_lessthan (lhs, rhs)
-     CORE_ADDR lhs;
-     CORE_ADDR rhs;
-{
-  return (lhs < rhs);
-}
-
-int
-core_addr_greaterthan (lhs, rhs)
-     CORE_ADDR lhs;
-     CORE_ADDR rhs;
-{
-  return (lhs > rhs);
-}