]> Git Repo - binutils.git/blobdiff - gdb/utils.c
Wed Jul 31 13:17:10 1996 Martin M. Hunt <[email protected]>
[binutils.git] / gdb / utils.c
index fdf793820a53d66064d98f9b438e0426c9057c68..37a6ec9acf198418a7eb3d720294243bca9d7914 100644 (file)
@@ -15,10 +15,10 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
-#if !defined(__GO32__) && !defined(WIN32)
+#if !defined(__GO32__) && !defined(__WIN32__) && !defined(MPW)
 #include <sys/ioctl.h>
 #include <sys/param.h>
 #include <pwd.h>
@@ -29,7 +29,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <varargs.h>
 #endif
 #include <ctype.h>
-#include <string.h>
+#include "gdb_string.h"
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -51,13 +51,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* Prototypes for local functions */
 
-#if defined (NO_MMALLOC) || defined (NO_MMALLOC_CHECK)
-#else
+static void vfprintf_maybe_filtered PARAMS ((FILE *, const char *, va_list, int));
 
-static void
-malloc_botch PARAMS ((void));
+static void fputs_maybe_filtered PARAMS ((const char *, FILE *, int));
 
-#endif /* NO_MMALLOC, etc */
+#if !defined (NO_MMALLOC) && !defined (NO_MMCHECK)
+static void malloc_botch PARAMS ((void));
+#endif
 
 static void
 fatal_dump_core PARAMS((char *, ...));
@@ -225,7 +225,7 @@ free_current_contents (location)
 /* ARGSUSED */
 void
 null_cleanup (arg)
-    char **arg;
+    PTR arg;
 {
 }
 
@@ -536,7 +536,7 @@ quit ()
 }
 
 
-#if defined(__GO32__)||defined(WIN32)
+#if defined(__GO32__)||defined(WINGDB)
 
 /* In the absence of signals, poll keyboard for a quit.
    Called from #define QUIT pollquit() in xm-go32.h. */
@@ -565,7 +565,7 @@ pollquit()
 
 
 #endif
-#if defined(__GO32__)||defined(WIN32)
+#if defined(__GO32__)||defined(WINGDB)
 void notice_quit()
 {
   if (kbhit ())
@@ -597,16 +597,21 @@ request_quit (signo)
      int signo;
 {
   quit_flag = 1;
-
   /* Restore the signal handler.  Harmless with BSD-style signals, needed
      for System V-style signals.  So just always do it, rather than worrying
      about USG defines and stuff like that.  */
   signal (signo, request_quit);
 
+/* start-sanitize-gm */
+#ifdef GENERAL_MAGIC
+  target_kill ();
+#endif /* GENERAL_MAGIC */
+/* end-sanitize-gm */
+
 #ifdef REQUEST_QUIT
   REQUEST_QUIT;
 #else
-  if (immediate_quit)
+  if (immediate_quit) 
     quit ();
 #endif
 }
@@ -658,7 +663,7 @@ mfree (md, ptr)
 
 #endif /* NO_MMALLOC */
 
-#if defined (NO_MMALLOC) || defined (NO_MMALLOC_CHECK)
+#if defined (NO_MMALLOC) || defined (NO_MMCHECK)
 
 void
 init_malloc (md)
@@ -666,7 +671,7 @@ init_malloc (md)
 {
 }
 
-#else /* have mmalloc and want corruption checking  */
+#else /* Have mmalloc and want corruption checking */
 
 static void
 malloc_botch ()
@@ -678,7 +683,7 @@ malloc_botch ()
    by MD, to detect memory corruption.  Note that MD may be NULL to specify
    the default heap that grows via sbrk.
 
-   Note that for freshly created regions, we must call mmcheck prior to any
+   Note that for freshly created regions, we must call mmcheckf prior to any
    mallocs in the region.  Otherwise, any region which was allocated prior to
    installing the checking hooks, which is later reallocated or freed, will
    fail the checks!  The mmcheck function only allows initial hooks to be
@@ -688,13 +693,24 @@ malloc_botch ()
 
    Returns zero on failure, non-zero on success. */
 
+#ifndef MMCHECK_FORCE
+#define MMCHECK_FORCE 0
+#endif
+
 void
 init_malloc (md)
      PTR md;
 {
-  if (!mmcheck (md, malloc_botch))
+  if (!mmcheckf (md, malloc_botch, MMCHECK_FORCE))
     {
-      warning ("internal error: failed to install memory consistency checks");
+      /* Don't use warning(), which relies on current_target being set
+        to something other than dummy_target, until after
+        initialize_all_files(). */
+
+      fprintf_unfiltered
+       (gdb_stderr, "warning: failed to install memory consistency checks; ");
+      fprintf_unfiltered
+       (gdb_stderr, "configuration should define NO_MMCHECK or MMCHECK_FORCE\n");
     }
 
   mmtrace ();
@@ -1487,7 +1503,7 @@ fputc_unfiltered (c, stream)
 static void
 vfprintf_maybe_filtered (stream, format, args, filter)
      FILE *stream;
-     char *format;
+     const char *format;
      va_list args;
      int filter;
 {
@@ -1509,7 +1525,7 @@ vfprintf_maybe_filtered (stream, format, args, filter)
 void
 vfprintf_filtered (stream, format, args)
      FILE *stream;
-     char *format;
+     const char *format;
      va_list args;
 {
   vfprintf_maybe_filtered (stream, format, args, 1);
@@ -1518,7 +1534,7 @@ vfprintf_filtered (stream, format, args)
 void
 vfprintf_unfiltered (stream, format, args)
      FILE *stream;
-     char *format;
+     const char *format;
      va_list args;
 {
   char *linebuffer;
@@ -1537,7 +1553,7 @@ vfprintf_unfiltered (stream, format, args)
 
 void
 vprintf_filtered (format, args)
-     char *format;
+     const char *format;
      va_list args;
 {
   vfprintf_maybe_filtered (gdb_stdout, format, args, 1);
@@ -1545,7 +1561,7 @@ vprintf_filtered (format, args)
 
 void
 vprintf_unfiltered (format, args)
-     char *format;
+     const char *format;
      va_list args;
 {
   vfprintf_unfiltered (gdb_stdout, format, args);
@@ -1554,7 +1570,7 @@ vprintf_unfiltered (format, args)
 /* VARARGS */
 void
 #ifdef ANSI_PROTOTYPES
-fprintf_filtered (FILE *stream, char *format, ...)
+fprintf_filtered (FILE *stream, const char *format, ...)
 #else
 fprintf_filtered (va_alist)
      va_dcl
@@ -1578,7 +1594,7 @@ fprintf_filtered (va_alist)
 /* VARARGS */
 void
 #ifdef ANSI_PROTOTYPES
-fprintf_unfiltered (FILE *stream, char *format, ...)
+fprintf_unfiltered (FILE *stream, const char *format, ...)
 #else
 fprintf_unfiltered (va_alist)
      va_dcl
@@ -1605,7 +1621,7 @@ fprintf_unfiltered (va_alist)
 /* VARARGS */
 void
 #ifdef ANSI_PROTOTYPES
-fprintfi_filtered (int spaces, FILE *stream, char *format, ...)
+fprintfi_filtered (int spaces, FILE *stream, const char *format, ...)
 #else
 fprintfi_filtered (va_alist)
      va_dcl
@@ -1634,7 +1650,7 @@ fprintfi_filtered (va_alist)
 /* VARARGS */
 void
 #ifdef ANSI_PROTOTYPES
-printf_filtered (char *format, ...)
+printf_filtered (const char *format, ...)
 #else
 printf_filtered (va_alist)
      va_dcl
@@ -1657,7 +1673,7 @@ printf_filtered (va_alist)
 /* VARARGS */
 void
 #ifdef ANSI_PROTOTYPES
-printf_unfiltered (char *format, ...)
+printf_unfiltered (const char *format, ...)
 #else
 printf_unfiltered (va_alist)
      va_dcl
@@ -1682,7 +1698,7 @@ printf_unfiltered (va_alist)
 /* VARARGS */
 void
 #ifdef ANSI_PROTOTYPES
-printfi_filtered (int spaces, char *format, ...)
+printfi_filtered (int spaces, const char *format, ...)
 #else
 printfi_filtered (va_alist)
      va_dcl
@@ -1711,14 +1727,14 @@ printfi_filtered (va_alist)
 
 void
 puts_filtered (string)
-     char *string;
+     const char *string;
 {
   fputs_filtered (string, gdb_stdout);
 }
 
 void
 puts_unfiltered (string)
-     char *string;
+     const char *string;
 {
   fputs_unfiltered (string, gdb_stdout);
 }
@@ -1860,7 +1876,7 @@ initialize_utils ()
   
   /* These defaults will be used if we are unable to get the correct
      values from termcap.  */
-#if defined(__GO32__) || defined(WIN32)
+#if defined(__GO32__) || defined(__WIN32__)
   lines_per_page = ScreenRows();
   chars_per_line = ScreenCols();
 #else  
@@ -1945,4 +1961,325 @@ initialize_utils ()
 #ifdef  SIGWINCH_HANDLER_BODY
         SIGWINCH_HANDLER_BODY
 #endif
+\f
+/* Support for converting target fp numbers into host DOUBLEST format.  */
+
+/* XXX - This code should really be in libiberty/floatformat.c, however
+   configuration issues with libiberty made this very difficult to do in the
+   available time.  */
+
+#include "floatformat.h"
+#include <math.h>              /* ldexp */
+
+/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
+   going to bother with trying to muck around with whether it is defined in
+   a system header, what we do if not, etc.  */
+#define FLOATFORMAT_CHAR_BIT 8
+
+static unsigned long get_field PARAMS ((unsigned char *,
+                                       enum floatformat_byteorders,
+                                       unsigned int,
+                                       unsigned int,
+                                       unsigned int));
+
+/* Extract a field which starts at START and is LEN bytes long.  DATA and
+   TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
+static unsigned long
+get_field (data, order, total_len, start, len)
+     unsigned char *data;
+     enum floatformat_byteorders order;
+     unsigned int total_len;
+     unsigned int start;
+     unsigned int len;
+{
+  unsigned long result;
+  unsigned int cur_byte;
+  int cur_bitshift;
+
+  /* Start at the least significant part of the field.  */
+  cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
+  if (order == floatformat_little)
+    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);
+  cur_bitshift += FLOATFORMAT_CHAR_BIT;
+  if (order == floatformat_little)
+    ++cur_byte;
+  else
+    --cur_byte;
+
+  /* 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;
+      cur_bitshift += FLOATFORMAT_CHAR_BIT;
+      if (order == floatformat_little)
+       ++cur_byte;
+      else
+       --cur_byte;
+    }
+  return result;
+}
+  
+/* Convert from FMT to a DOUBLEST.
+   FROM is the address of the extended float.
+   Store the DOUBLEST in *TO.  */
+
+void
+floatformat_to_doublest (fmt, from, to)
+     const struct floatformat *fmt;
+     char *from;
+     DOUBLEST *to;
+{
+  unsigned char *ufrom = (unsigned char *)from;
+  DOUBLEST dto;
+  long exponent;
+  unsigned long mant;
+  unsigned int mant_bits, mant_off;
+  int mant_bits_left;
+  int special_exponent;                /* It's a NaN, denorm or zero */
+
+  exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
+                       fmt->exp_start, fmt->exp_len);
+  /* Note that if exponent indicates a NaN, we can't really do anything useful
+     (not knowing if the host has NaN's, or how to build one).  So it will
+     end up as an infinity or something close; that is OK.  */
+
+  mant_bits_left = fmt->man_len;
+  mant_off = fmt->man_start;
+  dto = 0.0;
+
+  special_exponent = exponent == 0 || exponent == fmt->exp_nan;
+
+/* Don't bias zero's, denorms or NaNs.  */
+  if (!special_exponent)
+    exponent -= fmt->exp_bias;
+
+  /* Build the result algebraically.  Might go infinite, underflow, etc;
+     who cares. */
+
+/* If this format uses a hidden bit, explicitly add it in now.  Otherwise,
+   increment the exponent by one to account for the integer bit.  */
+
+  if (!special_exponent)
+    if (fmt->intbit == floatformat_intbit_no)
+      dto = ldexp (1.0, exponent);
+    else
+      exponent++;
+
+  while (mant_bits_left > 0)
+    {
+      mant_bits = min (mant_bits_left, 32);
+
+      mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
+                        mant_off, mant_bits);
+
+      dto += ldexp ((double)mant, exponent - mant_bits);
+      exponent -= mant_bits;
+      mant_off += mant_bits;
+      mant_bits_left -= mant_bits;
+    }
+
+  /* Negate it if negative.  */
+  if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
+    dto = -dto;
+  *to = dto;
+}
+\f
+static void put_field PARAMS ((unsigned char *, enum floatformat_byteorders,
+                              unsigned int,
+                              unsigned int,
+                              unsigned int,
+                              unsigned long));
+
+/* Set a field which starts at START and is LEN bytes long.  DATA and
+   TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
+static void
+put_field (data, order, total_len, start, len, stuff_to_put)
+     unsigned char *data;
+     enum floatformat_byteorders order;
+     unsigned int total_len;
+     unsigned int start;
+     unsigned int len;
+     unsigned long stuff_to_put;
+{
+  unsigned int cur_byte;
+  int cur_bitshift;
+
+  /* Start at the least significant part of the field.  */
+  cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
+  if (order == floatformat_little)
+    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);
+  cur_bitshift += FLOATFORMAT_CHAR_BIT;
+  if (order == floatformat_little)
+    ++cur_byte;
+  else
+    --cur_byte;
+
+  /* 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.  */
+         *(data + cur_byte) &=
+           ~((1 << (len - cur_bitshift)) - 1);
+         *(data + cur_byte) |= (stuff_to_put >> cur_bitshift);
+       }
+      else
+       *(data + cur_byte) = ((stuff_to_put >> cur_bitshift)
+                             & ((1 << FLOATFORMAT_CHAR_BIT) - 1));
+      cur_bitshift += FLOATFORMAT_CHAR_BIT;
+      if (order == floatformat_little)
+       ++cur_byte;
+      else
+       --cur_byte;
+    }
+}
+
+#ifdef HAVE_LONG_DOUBLE
+/* Return the fractional part of VALUE, and put the exponent of VALUE in *EPTR.
+   The range of the returned value is >= 0.5 and < 1.0.  This is equivalent to
+   frexp, but operates on the long double data type.  */
+
+static long double ldfrexp PARAMS ((long double value, int *eptr));
+
+static long double
+ldfrexp (value, eptr)
+     long double value;
+     int *eptr;
+{
+  long double tmp;
+  int exp;
+
+  /* Unfortunately, there are no portable functions for extracting the exponent
+     of a long double, so we have to do it iteratively by multiplying or dividing
+     by two until the fraction is between 0.5 and 1.0.  */
+
+  if (value < 0.0l)
+    value = -value;
+
+  tmp = 1.0l;
+  exp = 0;
+
+  if (value >= tmp)            /* Value >= 1.0 */
+    while (value >= tmp)
+      {
+       tmp *= 2.0l;
+       exp++;
+      }
+  else if (value != 0.0l)      /* Value < 1.0  and > 0.0 */
+    {
+      while (value < tmp)
+       {
+         tmp /= 2.0l;
+         exp--;
+       }
+      tmp *= 2.0l;
+      exp++;
+    }
+
+  *eptr = exp;
+  return value/tmp;
+}
+#endif /* HAVE_LONG_DOUBLE */
+
+
+/* The converse: convert the DOUBLEST *FROM to an extended float
+   and store where TO points.  Neither FROM nor TO have any alignment
+   restrictions.  */
+
+void
+floatformat_from_doublest (fmt, from, to)
+     CONST struct floatformat *fmt;
+     DOUBLEST *from;
+     char *to;
+{
+  DOUBLEST dfrom;
+  int exponent;
+  DOUBLEST mant;
+  unsigned int mant_bits, mant_off;
+  int mant_bits_left;
+  unsigned char *uto = (unsigned char *)to;
+
+  memcpy (&dfrom, from, sizeof (dfrom));
+  memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
+  if (dfrom == 0)
+    return;                    /* Result is zero */
+  if (dfrom != dfrom)
+    {
+      /* From is NaN */
+      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
+                fmt->exp_len, fmt->exp_nan);
+      /* Be sure it's not infinity, but NaN value is irrel */
+      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
+                32, 1);
+      return;
+    }
+
+  /* If negative, set the sign bit.  */
+  if (dfrom < 0)
+    {
+      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
+      dfrom = -dfrom;
+    }
+
+  /* How to tell an infinity from an ordinary number?  FIXME-someday */
+
+#ifdef HAVE_LONG_DOUBLE
+  mant = ldfrexp (dfrom, &exponent);
+#else
+  mant = frexp (dfrom, &exponent);
+#endif
 
+  put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len,
+            exponent + fmt->exp_bias - 1);
+
+  mant_bits_left = fmt->man_len;
+  mant_off = fmt->man_start;
+  while (mant_bits_left > 0)
+    {
+      unsigned long mant_long;
+      mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
+
+      mant *= 4294967296.0;
+      mant_long = (unsigned long)mant;
+      mant -= mant_long;
+
+      /* If the integer bit is implicit, then we need to discard it.
+        If we are discarding a zero, we should be (but are not) creating
+        a denormalized number which means adjusting the exponent
+        (I think).  */
+      if (mant_bits_left == fmt->man_len
+         && fmt->intbit == floatformat_intbit_no)
+       {
+         mant_long &= 0x7fffffff;
+         mant_bits -= 1;
+       }
+      else if (mant_bits < 32)
+       {
+         /* The bits we want are in the most significant MANT_BITS bits of
+            mant_long.  Move them to the least significant.  */
+         mant_long >>= 32 - mant_bits;
+       }
+
+      put_field (uto, fmt->byteorder, fmt->totalsize,
+                mant_off, mant_bits, mant_long);
+      mant_off += mant_bits;
+      mant_bits_left -= mant_bits;
+    }
+}
This page took 0.042716 seconds and 4 git commands to generate.