Obsolete stuff.c and kdb-start.c.
[deliverable/binutils-gdb.git] / gdb / utils.c
index 0046e0975cc0296314f9cd3fdcfb0562d5a062cd..b1205d6861cf5d3e97ff5377d165f22761cd68e4 100644 (file)
@@ -1,5 +1,6 @@
 /* General utility routines for GDB, the GNU debugger.
-   Copyright 1986, 1989, 1990-1992, 1995, 1996, 1998, 2000
+   Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+   1997, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -20,6 +21,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
+#include "gdb_assert.h"
 #include <ctype.h>
 #include "gdb_string.h"
 #include "event-top.h"
@@ -40,7 +42,7 @@
 #undef reg
 #endif
 
-#include "signals.h"
+#include <signal.h>
 #include "gdbcmd.h"
 #include "serial.h"
 #include "bfd.h"
 
 #include <readline/readline.h>
 
+#ifndef MALLOC_INCOMPATIBLE
+#ifdef NEED_DECLARATION_MALLOC
+extern PTR malloc ();
+#endif
+#ifdef NEED_DECLARATION_REALLOC
+extern PTR realloc ();
+#endif
+#ifdef NEED_DECLARATION_FREE
+extern void free ();
+#endif
+#endif
+
 #undef XMALLOC
 #define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
 
@@ -215,14 +229,17 @@ make_cleanup_bfd_close (bfd *abfd)
 static void
 do_close_cleanup (void *arg)
 {
-  close ((int) arg);
+  int *fd = arg;
+  close (*fd);
+  xfree (fd);
 }
 
 struct cleanup *
 make_cleanup_close (int fd)
 {
-  /* int into void*. Outch!! */
-  return make_cleanup (do_close_cleanup, (void *) fd);
+  int *saved_fd = xmalloc (sizeof (fd));
+  *saved_fd = fd;
+  return make_cleanup (do_close_cleanup, saved_fd);
 }
 
 static void
@@ -295,7 +312,7 @@ do_my_cleanups (register struct cleanup **pmy_chain,
     {
       *pmy_chain = ptr->next;  /* Do this first incase recursion */
       (*ptr->function) (ptr->arg);
-      free (ptr);
+      xfree (ptr);
     }
 }
 
@@ -328,7 +345,7 @@ discard_my_cleanups (register struct cleanup **pmy_chain,
   while ((ptr = *pmy_chain) != old_chain)
     {
       *pmy_chain = ptr->next;
-      free (ptr);
+      xfree (ptr);
     }
 }
 
@@ -386,10 +403,11 @@ free_current_contents (void *ptr)
 {
   void **location = ptr;
   if (location == NULL)
-    internal_error ("free_current_contents: NULL pointer");
+    internal_error (__FILE__, __LINE__,
+                   "free_current_contents: NULL pointer");
   if (*location != NULL)
     {
-      free (*location);
+      xfree (*location);
       *location = NULL;
     }
 }
@@ -407,12 +425,11 @@ null_cleanup (void *arg)
 {
 }
 
-/* Add a continuation to the continuation list, the gloabl list
+/* Add a continuation to the continuation list, the global list
    cmd_continuation. The new continuation will be added at the front.*/
 void
-add_continuation (continuation_hook, arg_list)
-     void (*continuation_hook) (struct continuation_arg *);
-     struct continuation_arg *arg_list;
+add_continuation (void (*continuation_hook) (struct continuation_arg *),
+                 struct continuation_arg *arg_list)
 {
   struct continuation *continuation_ptr;
 
@@ -450,7 +467,7 @@ do_all_continuations (void)
        (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
        saved_continuation = continuation_ptr;
        continuation_ptr = continuation_ptr->next;
-       free (saved_continuation);
+       xfree (saved_continuation);
      }
 }
 
@@ -465,16 +482,16 @@ discard_all_continuations (void)
     {
       continuation_ptr = cmd_continuation;
       cmd_continuation = continuation_ptr->next;
-      free (continuation_ptr);
+      xfree (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) (struct continuation_arg *);
-     struct continuation_arg *arg_list;
+add_intermediate_continuation (void (*continuation_hook)
+                              (struct continuation_arg *),
+                              struct continuation_arg *arg_list)
 {
   struct continuation *continuation_ptr;
 
@@ -512,7 +529,7 @@ do_all_intermediate_continuations (void)
        (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
        saved_continuation = continuation_ptr;
        continuation_ptr = continuation_ptr->next;
-       free (saved_continuation);
+       xfree (saved_continuation);
      }
 }
 
@@ -527,7 +544,7 @@ discard_all_intermediate_continuations (void)
     {
       continuation_ptr = intermediate_continuation;
       intermediate_continuation = continuation_ptr->next;
-      free (continuation_ptr);
+      xfree (continuation_ptr);
     }
 }
 
@@ -622,7 +639,7 @@ verror (const char *string, va_list args)
   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);
+  err_string_cleanup = make_cleanup (xfree, err_string);
   fputs_filtered (err_string, gdb_stderr);
   fprintf_filtered (gdb_stderr, "\n");
   do_cleanups (err_string_cleanup);
@@ -643,7 +660,7 @@ error_stream (struct ui_file *stream)
 {
   long size;
   char *msg = ui_file_xstrdup (stream, &size);
-  make_cleanup (free, msg);
+  make_cleanup (xfree, msg);
   error ("%s", msg);
 }
 
@@ -668,7 +685,8 @@ error_init (void)
    want to continue, dump core, or just exit. */
 
 NORETURN void
-internal_verror (const char *fmt, va_list ap)
+internal_verror (const char *file, int line,
+                const char *fmt, va_list ap)
 {
   static char msg[] = "Internal GDB error: recursive internal error.\n";
   static int dejavu = 0;
@@ -684,7 +702,7 @@ internal_verror (const char *fmt, va_list ap)
     case 1:
       dejavu = 2;
       fputs_unfiltered (msg, gdb_stderr);
-      abort ();
+      internal_error (__FILE__, __LINE__, "failed internal consistency check");
     default:
       dejavu = 3;
       write (STDERR_FILENO, msg, sizeof (msg));
@@ -693,14 +711,14 @@ internal_verror (const char *fmt, va_list ap)
 
   /* Try to get the message out */
   target_terminal_ours ();
-  fputs_unfiltered ("gdb-internal-error: ", gdb_stderr);
+  fprintf_unfiltered (gdb_stderr, "%s:%d: gdb-internal-error: ", file, line);
   vfprintf_unfiltered (gdb_stderr, fmt, ap);
   fputs_unfiltered ("\n", gdb_stderr);
 
   /* Default (no case) is to quit GDB.  When in batch mode this
      lessens the likelhood of GDB going into an infinate loop. */
   continue_p = query ("\
-An internal GDB error was detected.  This may make make further\n\
+An internal GDB error was detected.  This may make further\n\
 debugging unreliable.  Continue this debugging session? ");
 
   /* Default (no case) is to not dump core.  Lessen the chance of GDB
@@ -713,13 +731,13 @@ Create a core file containing the current state of GDB? ");
       if (dump_core_p)
        {
          if (fork () == 0)
-           abort ();
+           internal_error (__FILE__, __LINE__, "failed internal consistency check");
        }
     }
   else
     {
       if (dump_core_p)
-       abort ();
+       internal_error (__FILE__, __LINE__, "failed internal consistency check");
       else
        exit (1);
     }
@@ -729,12 +747,12 @@ Create a core file containing the current state of GDB? ");
 }
 
 NORETURN void
-internal_error (char *string, ...)
+internal_error (const char *file, int line, const char *string, ...)
 {
   va_list ap;
   va_start (ap, string);
 
-  internal_verror (string, ap);
+  internal_verror (file, line, string, ap);
   va_end (ap);
 }
 
@@ -933,7 +951,7 @@ mrealloc (PTR md, PTR ptr, size_t size)
 void
 mfree (PTR md, PTR ptr)
 {
-  free (ptr);
+  xfree (ptr);
 }
 
 #endif /* USE_MMALLOC */
@@ -951,7 +969,7 @@ static void
 malloc_botch (void)
 {
   fprintf_unfiltered (gdb_stderr, "Memory corruption\n");
-  abort ();
+  internal_error (__FILE__, __LINE__, "failed internal consistency check");
 }
 
 /* Attempt to install hooks in mmalloc/mrealloc/mfree for the heap specified
@@ -1000,11 +1018,13 @@ nomem (long size)
 {
   if (size > 0)
     {
-      internal_error ("virtual memory exhausted: can't allocate %ld bytes.", size);
+      internal_error (__FILE__, __LINE__,
+                     "virtual memory exhausted: can't allocate %ld bytes.", size);
     }
   else
     {
-      internal_error ("virtual memory exhausted.");
+      internal_error (__FILE__, __LINE__,
+                     "virtual memory exhausted.");
     }
 }
 
@@ -1036,17 +1056,26 @@ xmrealloc (PTR md, PTR ptr, long size)
 {
   register PTR val;
 
-  if (ptr != NULL)
+  if (size == 0)
     {
-      val = mrealloc (md, ptr, size);
+      if (ptr != NULL)
+       mfree (md, ptr);
+      val = NULL;
     }
   else
     {
-      val = mmalloc (md, size);
-    }
-  if (val == NULL)
-    {
-      nomem (size);
+      if (ptr != NULL)
+       {
+         val = mrealloc (md, ptr, size);
+       }
+      else
+       {
+         val = mmalloc (md, size);
+       }
+      if (val == NULL)
+       {
+         nomem (size);
+       }
     }
   return (val);
 }
@@ -1065,9 +1094,16 @@ xmalloc (size_t size)
 PTR
 xcalloc (size_t number, size_t size)
 {
-  void *mem = mcalloc (NULL, number, size);
-  if (mem == NULL)
-    nomem (number * size);
+  void *mem;
+
+  if (number == 0 || size == 0)
+    mem = NULL;
+  else
+    {
+      mem = mcalloc (NULL, number, size);
+      if (mem == NULL)
+       nomem (number * size);
+    }
   return mem;
 }
 
@@ -1078,8 +1114,49 @@ xrealloc (PTR ptr, size_t size)
 {
   return (xmrealloc ((PTR) NULL, ptr, size));
 }
+
+/* Free up space allocated by one of xmalloc(), xcalloc(), or
+   xrealloc().  */
+
+void
+xfree (void *ptr)
+{
+  if (ptr != NULL)
+    free (ptr); /* NOTE: GDB's only call to free() */
+}
 \f
 
+/* Like asprintf/vasprintf but get an internal_error if the call
+   fails. */
+
+void
+xasprintf (char **ret, const char *format, ...)
+{
+  va_list args;
+  va_start (args, format);
+  xvasprintf (ret, format, args);
+  va_end (args);
+}
+
+void
+xvasprintf (char **ret, const char *format, va_list ap)
+{
+  int status = vasprintf (ret, format, ap);
+  /* NULL could be returned due to a memory allocation problem; a
+     badly format string; or something else. */
+  if ((*ret) == NULL)
+    internal_error (__FILE__, __LINE__,
+                   "vasprintf returned NULL buffer (errno %d)",
+                   errno);
+  /* A negative status with a non-NULL buffer shouldn't never
+     happen. But to be sure. */
+  if (status < 0)
+    internal_error (__FILE__, __LINE__,
+                   "vasprintf call failed (errno %d)",
+                   errno);
+}
+
+
 /* My replacement for the read system call.
    Used like `read' but keeps going if `read' returns too soon.  */
 
@@ -1107,7 +1184,7 @@ myread (int desc, char *addr, int len)
    Uses malloc to get the space.  Returns the address of the copy.  */
 
 char *
-savestring (const char *ptr, int size)
+savestring (const char *ptr, size_t size)
 {
   register char *p = (char *) xmalloc (size + 1);
   memcpy (p, ptr, size);
@@ -1116,7 +1193,7 @@ savestring (const char *ptr, int size)
 }
 
 char *
-msavestring (void *md, const char *ptr, int size)
+msavestring (void *md, const char *ptr, size_t size)
 {
   register char *p = (char *) xmmalloc (md, size + 1);
   memcpy (p, ptr, size);
@@ -1124,15 +1201,6 @@ msavestring (void *md, const char *ptr, int size)
   return p;
 }
 
-/* The "const" is so it compiles under DGUX (which prototypes strsave
-   in <string.h>.  FIXME: This should be named "xstrsave", shouldn't it?
-   Doesn't real strsave return NULL if out of memory?  */
-char *
-strsave (const char *ptr)
-{
-  return savestring (ptr, strlen (ptr));
-}
-
 char *
 mstrsave (void *md, const char *ptr)
 {
@@ -1351,15 +1419,10 @@ parse_escape (char **string_ptr)
    be call for printing things which are independent of the language
    of the program being debugged. */
 
-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) (const char *, struct ui_file *);
-     void (*do_fprintf) (struct ui_file *, const char *, ...);
-     struct ui_file *stream;
-     int quoter;
+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)
 {
 
   c &= 0xFF;                   /* Avoid sign bit follies */
@@ -1613,7 +1676,7 @@ prompt_for_continue (void)
          else
            async_request_quit (0);
        }
-      free (ignore);
+      xfree (ignore);
     }
   immediate_quit--;
 
@@ -1659,7 +1722,7 @@ wrap_here (char *indent)
 {
   /* This should have been allocated, but be paranoid anyway. */
   if (!wrap_buffer)
-    abort ();
+    internal_error (__FILE__, __LINE__, "failed internal consistency check");
 
   if (wrap_buffer[0])
     {
@@ -1833,6 +1896,15 @@ putchar_unfiltered (int c)
   return c;
 }
 
+/* Write character C to gdb_stdout using GDB's paging mechanism and return C.
+   May return nonlocally.  */
+
+int
+putchar_filtered (int c)
+{
+  return fputc_filtered (c, gdb_stdout);
+}
+
 int
 fputc_unfiltered (int c, struct ui_file *stream)
 {
@@ -1958,13 +2030,8 @@ vfprintf_maybe_filtered (struct ui_file *stream, const char *format,
   char *linebuffer;
   struct cleanup *old_cleanups;
 
-  vasprintf (&linebuffer, format, args);
-  if (linebuffer == NULL)
-    {
-      fputs_unfiltered ("\ngdb: virtual memory exhausted.\n", gdb_stderr);
-      exit (1);
-    }
-  old_cleanups = make_cleanup (free, linebuffer);
+  xvasprintf (&linebuffer, format, args);
+  old_cleanups = make_cleanup (xfree, linebuffer);
   fputs_maybe_filtered (linebuffer, stream, filter);
   do_cleanups (old_cleanups);
 }
@@ -1982,13 +2049,8 @@ vfprintf_unfiltered (struct ui_file *stream, const char *format, va_list args)
   char *linebuffer;
   struct cleanup *old_cleanups;
 
-  vasprintf (&linebuffer, format, args);
-  if (linebuffer == NULL)
-    {
-      fputs_unfiltered ("\ngdb: virtual memory exhausted.\n", gdb_stderr);
-      exit (1);
-    }
-  old_cleanups = make_cleanup (free, linebuffer);
+  xvasprintf (&linebuffer, format, args);
+  old_cleanups = make_cleanup (xfree, linebuffer);
   fputs_unfiltered (linebuffer, stream);
   do_cleanups (old_cleanups);
 }
@@ -2099,7 +2161,7 @@ n_spaces (int n)
   if (n > max_spaces)
     {
       if (spaces)
-       free (spaces);
+       xfree (spaces);
       spaces = (char *) xmalloc (n + 1);
       for (t = spaces + n; t != spaces;)
        *--t = ' ';
@@ -2157,7 +2219,7 @@ fprintf_symbol_filtered (struct ui_file *stream, char *name, enum language lang,
          fputs_filtered (demangled ? demangled : name, stream);
          if (demangled != NULL)
            {
-             free (demangled);
+             xfree (demangled);
            }
        }
     }
@@ -2708,6 +2770,106 @@ floatformat_from_doublest (CONST struct floatformat *fmt, DOUBLEST *from,
     }
 }
 
+/* Check if VAL (which is assumed to be a floating point number whose
+   format is described by FMT) is negative.  */
+
+int
+floatformat_is_negative (const struct floatformat *fmt, char *val)
+{
+  unsigned char *uval = (unsigned char *) val;
+
+  return get_field (uval, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1);
+}
+
+/* Check if VAL is "not a number" (NaN) for FMT.  */
+
+int
+floatformat_is_nan (const struct floatformat *fmt, char *val)
+{
+  unsigned char *uval = (unsigned char *) val;
+  long exponent;
+  unsigned long mant;
+  unsigned int mant_bits, mant_off;
+  int mant_bits_left;
+
+  if (! fmt->exp_nan)
+    return 0;
+
+  exponent = get_field (uval, fmt->byteorder, fmt->totalsize,
+                       fmt->exp_start, fmt->exp_len);
+
+  if (exponent != fmt->exp_nan)
+    return 0;
+
+  mant_bits_left = fmt->man_len;
+  mant_off = fmt->man_start;
+
+  while (mant_bits_left > 0)
+    {
+      mant_bits = min (mant_bits_left, 32);
+
+      mant = get_field (uval, fmt->byteorder, fmt->totalsize,
+                       mant_off, mant_bits);
+
+      /* If there is an explicit integer bit, mask it off.  */
+      if (mant_off == fmt->man_start
+         && fmt->intbit == floatformat_intbit_yes)
+       mant &= ~(1 << (mant_bits - 1));
+
+      if (mant)
+       return 1;
+
+      mant_off += mant_bits;
+      mant_bits_left -= mant_bits;
+    }
+
+  return 0;
+}
+
+/* Convert the mantissa of VAL (which is assumed to be a floating
+   point number whose format is described by FMT) into a hexadecimal
+   and store it in a static string.  Return a pointer to that string.  */
+
+char *
+floatformat_mantissa (const struct floatformat *fmt, char *val)
+{
+  unsigned char *uval = (unsigned char *) val;
+  unsigned long mant;
+  unsigned int mant_bits, mant_off;
+  int mant_bits_left;
+  static char res[50];
+  char buf[9];
+
+  /* Make sure we have enough room to store the mantissa.  */
+  gdb_assert (sizeof res > ((fmt->man_len + 7) / 8) * 2);
+
+  mant_off = fmt->man_start;
+  mant_bits_left = fmt->man_len;
+  mant_bits = (mant_bits_left % 32) > 0 ? mant_bits_left % 32 : 32;
+
+  mant = get_field (uval, fmt->byteorder, fmt->totalsize,
+                   mant_off, mant_bits);
+
+  sprintf (res, "%lx", mant);
+
+  mant_off += mant_bits;
+  mant_bits_left -= mant_bits;
+  
+  while (mant_bits_left > 0)
+    {
+      mant = get_field (uval, fmt->byteorder, fmt->totalsize,
+                       mant_off, 32);
+
+      sprintf (buf, "%08lx", mant);
+      strcat (res, buf);
+
+      mant_off += 32;
+      mant_bits_left -= 32;
+    }
+
+  return res;
+}
+
 /* print routines to handle variable size regs, etc. */
 
 /* temporary storage using circular buffer */
@@ -2726,19 +2888,19 @@ get_cell (void)
 int
 strlen_paddr (void)
 {
-  return (TARGET_PTR_BIT / 8 * 2);
+  return (TARGET_ADDR_BIT / 8 * 2);
 }
 
 char *
 paddr (CORE_ADDR addr)
 {
-  return phex (addr, TARGET_PTR_BIT / 8);
+  return phex (addr, TARGET_ADDR_BIT / 8);
 }
 
 char *
 paddr_nz (CORE_ADDR addr)
 {
-  return phex_nz (addr, TARGET_PTR_BIT / 8);
+  return phex_nz (addr, TARGET_ADDR_BIT / 8);
 }
 
 static void
@@ -2770,7 +2932,7 @@ decimal2str (char *paddr_str, char *sign, ULONGEST addr)
               sign, temp[2], temp[1], temp[0]);
       break;
     default:
-      abort ();
+      internal_error (__FILE__, __LINE__, "failed internal consistency check");
     }
 }
 
@@ -2856,7 +3018,8 @@ CORE_ADDR
 host_pointer_to_address (void *ptr)
 {
   if (sizeof (ptr) != TYPE_LENGTH (builtin_type_ptr))
-    internal_error ("core_addr_to_void_ptr: bad cast");
+    internal_error (__FILE__, __LINE__,
+                   "core_addr_to_void_ptr: bad cast");
   return POINTER_TO_ADDRESS (builtin_type_ptr, &ptr);
 }
 
@@ -2865,7 +3028,8 @@ address_to_host_pointer (CORE_ADDR addr)
 {
   void *ptr;
   if (sizeof (ptr) != TYPE_LENGTH (builtin_type_ptr))
-    internal_error ("core_addr_to_void_ptr: bad cast");
+    internal_error (__FILE__, __LINE__,
+                   "core_addr_to_void_ptr: bad cast");
   ADDRESS_TO_POINTER (builtin_type_ptr, &ptr, addr);
   return ptr;
 }
This page took 0.039727 seconds and 4 git commands to generate.