Let print_decimal_chars handle signed values
authorTom Tromey <tom@tromey.com>
Mon, 22 May 2017 22:32:25 +0000 (16:32 -0600)
committerTom Tromey <tom@tromey.com>
Mon, 12 Jun 2017 21:04:57 +0000 (15:04 -0600)
This changes print_decimal_chars to handle signed values.

gdb/ChangeLog
2017-06-12  Tom Tromey  <tom@tromey.com>

PR exp/16225:
* valprint.h (print_decimal_chars): Update.
* valprint.c (maybe_negate_by_bytes): New function.
(print_decimal_chars): Add "is_signed" argument.
* printcmd.c (print_scalar_formatted): Update.

gdb/ChangeLog
gdb/printcmd.c
gdb/valprint.c
gdb/valprint.h

index 16b5a3a..07ba5f2 100644 (file)
@@ -1,6 +1,14 @@
 2017-06-12  Tom Tromey  <tom@tromey.com>
 
        PR exp/16225:
+       * valprint.h (print_decimal_chars): Update.
+       * valprint.c (maybe_negate_by_bytes): New function.
+       (print_decimal_chars): Add "is_signed" argument.
+       * printcmd.c (print_scalar_formatted): Update.
+
+2017-06-12  Tom Tromey  <tom@tromey.com>
+
+       PR exp/16225:
        * valprint.h (print_binary_chars, print_hex_chars): Update.
        * valprint.c (val_print_type_code_int): Update.
        (print_binary_chars): Add "zero_pad" argument.
index 66395d5..84f41f5 100644 (file)
@@ -374,7 +374,8 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
          return;
        case 'u':
        case 'd':
-         print_decimal_chars (stream, valaddr, len, byte_order);
+         print_decimal_chars (stream, valaddr, len, !TYPE_UNSIGNED (type),
+                              byte_order);
          return;
        case 't':
          print_binary_chars (stream, valaddr, len, byte_order, size > 0);
index aa34b68..2420fb5 100644 (file)
@@ -1763,12 +1763,58 @@ print_octal_chars (struct ui_file *stream, const gdb_byte *valaddr,
 
 }
 
+/* Possibly negate the integer represented by BYTES.  It contains LEN
+   bytes in the specified byte order.  If the integer is negative,
+   copy it into OUT_VEC, negate it, and return true.  Otherwise, do
+   nothing and return false.  */
+
+static bool
+maybe_negate_by_bytes (const gdb_byte *bytes, unsigned len,
+                      enum bfd_endian byte_order,
+                      std::vector<gdb_byte> *out_vec)
+{
+  gdb_byte sign_byte;
+  if (byte_order == BFD_ENDIAN_BIG)
+    sign_byte = bytes[0];
+  else
+    sign_byte = bytes[len - 1];
+  if ((sign_byte & 0x80) == 0)
+    return false;
+
+  out_vec->resize (len);
+
+  /* Compute -x == 1 + ~x.  */
+  if (byte_order == BFD_ENDIAN_LITTLE)
+    {
+      unsigned carry = 1;
+      for (unsigned i = 0; i < len; ++i)
+       {
+         unsigned tem = (0xff & ~bytes[i]) + carry;
+         (*out_vec)[i] = tem & 0xff;
+         carry = tem / 256;
+       }
+    }
+  else
+    {
+      unsigned carry = 1;
+      for (unsigned i = len; i > 0; --i)
+       {
+         unsigned tem = (0xff & ~bytes[i - 1]) + carry;
+         (*out_vec)[i - 1] = tem & 0xff;
+         carry = tem / 256;
+       }
+    }
+
+  return true;
+}
+
 /* VALADDR points to an integer of LEN bytes.
    Print it in decimal on stream or format it in buf.  */
 
 void
 print_decimal_chars (struct ui_file *stream, const gdb_byte *valaddr,
-                    unsigned len, enum bfd_endian byte_order)
+                    unsigned len, bool is_signed,
+                    enum bfd_endian byte_order)
 {
 #define TEN             10
 #define CARRY_OUT(  x ) ((x) / TEN)    /* extend char to int */
@@ -1784,6 +1830,14 @@ print_decimal_chars (struct ui_file *stream, const gdb_byte *valaddr,
   int dummy;
   int flip;
 
+  std::vector<gdb_byte> negated_bytes;
+  if (is_signed
+      && maybe_negate_by_bytes (valaddr, len, byte_order, &negated_bytes))
+    {
+      fputs_filtered ("-", stream);
+      valaddr = negated_bytes.data ();
+    }
+
   /* Base-ten number is less than twice as many digits
      as the base 16 number, which is 2 digits per byte.  */
 
index 8bfad21..f71d4ab 100644 (file)
@@ -138,7 +138,7 @@ extern void print_octal_chars (struct ui_file *, const gdb_byte *,
                               unsigned int, enum bfd_endian);
 
 extern void print_decimal_chars (struct ui_file *, const gdb_byte *,
-                                unsigned int, enum bfd_endian);
+                                unsigned int, bool, enum bfd_endian);
 
 extern void print_hex_chars (struct ui_file *, const gdb_byte *,
                             unsigned int, enum bfd_endian, bool);