2017-10-05 Ulrich Weigand <uweigand@de.ibm.com>
+ * dfp.h (MAX_DECIMAL_STRING): Move to dfp.c.
+ (decimal_to_string): Return std::string object.
+ (decimal_from_string): Accept std::string object. Return bool.
+ (decimal_from_integral, decimal_from_doublest): Remove.
+ (decimal_from_longest): Add prototype.
+ (decimal_from_ulongest): Likewise.
+ (decimal_to_longest): Likewise.
+ (decimal_from_doublest): Likewise.
+ * dfp.c: Do not include "gdbtypes.h" or "value.h".
+ (MAX_DECIMAL_STRING): Move here.
+ (decimal_to_string): Return std::string object.
+ (decimal_from_string): Accept std::string object. Return bool.
+ (decimal_from_integral): Remove, replace by ...
+ (decimal_from_longest, decimal_from_ulongest): ... these new functions.
+ (decimal_to_longest): New function.
+ (decimal_from_floating): Remove, replace by ...
+ (decimal_from_doublest): ... this new function.
+ (decimal_to_doublest): Update to new decimal_to_string interface.
+
+ * value.c (unpack_long): Use decimal_to_longest.
+ * valops.c (value_cast): Use decimal_from_doublest instead of
+ decimal_from_floating. Use decimal_from_[u]longest isntead of
+ decimal_from_integral.
+ * valarith.c (value_args_as_decimal): Likewise.
+ * valprint.c (print_decimal_floating): Update to new
+ decimal_to_string interface.
+ * printcmd.c (printf_decfloat): Likewise.
+ * c-exp.y (parse_number): Update to new decimal_from_string interface.
+
+2017-10-05 Ulrich Weigand <uweigand@de.ibm.com>
+
* doublest.h: Do not include "floatformat.h". Remove stale comments.
* gdbtypes.c: Include "floatformat.h".
* value.c: Likewise.
if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'f')
{
- p[len - 2] = '\0';
putithere->typed_val_decfloat.type
= parse_type (par_state)->builtin_decfloat;
decimal_from_string (putithere->typed_val_decfloat.val, 4,
gdbarch_byte_order (parse_gdbarch (par_state)),
- p);
- p[len - 2] = 'd';
+ std::string (p, len - 2));
return DECFLOAT;
}
if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd')
{
- p[len - 2] = '\0';
putithere->typed_val_decfloat.type
= parse_type (par_state)->builtin_decdouble;
decimal_from_string (putithere->typed_val_decfloat.val, 8,
gdbarch_byte_order (parse_gdbarch (par_state)),
- p);
- p[len - 2] = 'd';
+ std::string (p, len - 2));
return DECFLOAT;
}
if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l')
{
- p[len - 2] = '\0';
putithere->typed_val_decfloat.type
= parse_type (par_state)->builtin_declong;
decimal_from_string (putithere->typed_val_decfloat.val, 16,
gdbarch_byte_order (parse_gdbarch (par_state)),
- p);
- p[len - 2] = 'd';
+ std::string (p, len - 2));
return DECFLOAT;
}
#include "defs.h"
#include "expression.h"
-#include "gdbtypes.h"
-#include "value.h"
#include "dfp.h"
/* The order of the following headers is important for making sure
#include "dpd/decimal64.h"
#include "dpd/decimal32.h"
+/* When using decimal128, this is the maximum string length + 1
+ (value comes from libdecnumber's DECIMAL128_String constant). */
+#define MAX_DECIMAL_STRING 43
+
/* In GDB, we are using an array of gdb_byte to represent decimal values.
They are stored in host byte order. This routine does the conversion if
the target byte order is different. */
/* Convert decimal type to its string representation. LEN is the length
of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
16 bytes for decimal128. */
-void
+std::string
decimal_to_string (const gdb_byte *decbytes, int len,
- enum bfd_endian byte_order, char *s)
+ enum bfd_endian byte_order)
{
gdb_byte dec[16];
match_endianness (decbytes, len, byte_order, dec);
+ std::string result;
+ result.resize (MAX_DECIMAL_STRING);
+
switch (len)
{
case 4:
- decimal32ToString ((decimal32 *) dec, s);
+ decimal32ToString ((decimal32 *) dec, &result[0]);
break;
case 8:
- decimal64ToString ((decimal64 *) dec, s);
+ decimal64ToString ((decimal64 *) dec, &result[0]);
break;
case 16:
- decimal128ToString ((decimal128 *) dec, s);
+ decimal128ToString ((decimal128 *) dec, &result[0]);
break;
default:
error (_("Unknown decimal floating point type."));
break;
}
+
+ return result;
}
/* Convert the string form of a decimal value to its decimal representation.
LEN is the length of the decimal type, 4 bytes for decimal32, 8 bytes for
decimal64 and 16 bytes for decimal128. */
-int
+bool
decimal_from_string (gdb_byte *decbytes, int len, enum bfd_endian byte_order,
- const char *string)
+ std::string string)
{
decContext set;
gdb_byte dec[16];
switch (len)
{
case 4:
- decimal32FromString ((decimal32 *) dec, string, &set);
+ decimal32FromString ((decimal32 *) dec, string.c_str (), &set);
break;
case 8:
- decimal64FromString ((decimal64 *) dec, string, &set);
+ decimal64FromString ((decimal64 *) dec, string.c_str (), &set);
break;
case 16:
- decimal128FromString ((decimal128 *) dec, string, &set);
+ decimal128FromString ((decimal128 *) dec, string.c_str (), &set);
break;
default:
error (_("Unknown decimal floating point type."));
/* Check for errors in the DFP operation. */
decimal_check_errors (&set);
- return 1;
+ return true;
}
-/* Converts a value of an integral type to a decimal float of
- specified LEN bytes. */
+/* Converts a LONGEST to a decimal float of specified LEN bytes. */
void
-decimal_from_integral (struct value *from,
- gdb_byte *to, int len, enum bfd_endian byte_order)
+decimal_from_longest (LONGEST from,
+ gdb_byte *to, int len, enum bfd_endian byte_order)
{
- LONGEST l;
gdb_byte dec[16];
decNumber number;
- struct type *type;
+ if ((int32_t) from != from)
+ /* libdecnumber can convert only 32-bit integers. */
+ error (_("Conversion of large integer to a "
+ "decimal floating type is not supported."));
+
+ decNumberFromInt32 (&number, (int32_t) from);
+
+ decimal_from_number (&number, dec, len);
+ match_endianness (dec, len, byte_order, to);
+}
- type = check_typedef (value_type (from));
+/* Converts a ULONGEST to a decimal float of specified LEN bytes. */
+void
+decimal_from_ulongest (ULONGEST from,
+ gdb_byte *to, int len, enum bfd_endian byte_order)
+{
+ gdb_byte dec[16];
+ decNumber number;
- if (TYPE_LENGTH (type) > 4)
+ if ((uint32_t) from != from)
/* libdecnumber can convert only 32-bit integers. */
error (_("Conversion of large integer to a "
"decimal floating type is not supported."));
- l = value_as_long (from);
-
- if (TYPE_UNSIGNED (type))
- decNumberFromUInt32 (&number, (unsigned int) l);
- else
- decNumberFromInt32 (&number, (int) l);
+ decNumberFromUInt32 (&number, (uint32_t) from);
decimal_from_number (&number, dec, len);
match_endianness (dec, len, byte_order, to);
}
+/* Converts a decimal float of LEN bytes to a LONGEST. */
+LONGEST
+decimal_to_longest (const gdb_byte *from, int len, enum bfd_endian byte_order)
+{
+ /* libdecnumber has a function to convert from decimal to integer, but
+ it doesn't work when the decimal number has a fractional part. */
+ std::string str = decimal_to_string (from, len, byte_order);
+ return strtoll (str.c_str (), NULL, 10);
+}
+
/* Converts a value of a float type to a decimal float of
specified LEN bytes.
This is an ugly way to do the conversion, but libdecnumber does
not offer a direct way to do it. */
void
-decimal_from_floating (struct value *from,
+decimal_from_doublest (DOUBLEST from,
gdb_byte *to, int len, enum bfd_endian byte_order)
{
- char *buffer;
-
- buffer = xstrprintf ("%.30" DOUBLEST_PRINT_FORMAT, value_as_double (from));
-
- decimal_from_string (to, len, byte_order, buffer);
-
- xfree (buffer);
+ std::string str = string_printf ("%.30" DOUBLEST_PRINT_FORMAT, from);
+ decimal_from_string (to, len, byte_order, str);
}
/* Converts a decimal float of LEN bytes to a double value. */
DOUBLEST
decimal_to_doublest (const gdb_byte *from, int len, enum bfd_endian byte_order)
{
- char buffer[MAX_DECIMAL_STRING];
-
/* This is an ugly way to do the conversion, but libdecnumber does
not offer a direct way to do it. */
- decimal_to_string (from, len, byte_order, buffer);
- return strtod (buffer, NULL);
+ std::string str = decimal_to_string (from, len, byte_order);
+ return strtod (str.c_str (), NULL);
}
/* Perform operation OP with operands X and Y with sizes LEN_X and LEN_Y
#include "doublest.h" /* For DOUBLEST. */
#include "expression.h" /* For enum exp_opcode. */
-/* When using decimal128, this is the maximum string length + 1
- * (value comes from libdecnumber's DECIMAL128_String constant). */
-#define MAX_DECIMAL_STRING 43
-
-extern void decimal_to_string (const gdb_byte *, int, enum bfd_endian, char *);
-extern int decimal_from_string (gdb_byte *, int, enum bfd_endian,
- const char *);
-extern void decimal_from_integral (struct value *from, gdb_byte *to,
+extern std::string decimal_to_string (const gdb_byte *, int, enum bfd_endian);
+extern bool decimal_from_string (gdb_byte *, int, enum bfd_endian,
+ std::string string);
+extern void decimal_from_longest (LONGEST from, gdb_byte *to,
+ int len, enum bfd_endian byte_order);
+extern void decimal_from_ulongest (ULONGEST from, gdb_byte *to,
int len, enum bfd_endian byte_order);
-extern void decimal_from_floating (struct value *from, gdb_byte *to,
+extern LONGEST decimal_to_longest (const gdb_byte *from, int len,
+ enum bfd_endian byte_order);
+extern void decimal_from_doublest (DOUBLEST from, gdb_byte *to,
int len, enum bfd_endian byte_order);
extern DOUBLEST decimal_to_doublest (const gdb_byte *from, int len,
enum bfd_endian byte_order);
int dfp_len = 16;
gdb_byte dec[16];
struct type *dfp_type = NULL;
- char decstr[MAX_DECIMAL_STRING];
/* Points to the end of the string so that we can go back
and check for DFP length modifiers. */
dfp_ptr = (gdb_byte *) value_contents (dfp_value);
- decimal_to_string (dfp_ptr, dfp_len, byte_order, decstr);
-
- /* Print the DFP value. */
- fprintf_filtered (stream, "%s", decstr);
+ /* Convert the value to a string and print it. */
+ std::string str = decimal_to_string (dfp_ptr, dfp_len, byte_order);
+ fputs_filtered (str.c_str (), stream);
#endif
}
+2017-10-05 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * gdb.base/dfp-exprs.exp: Update tests to larger range of supported
+ integer-to-dfp conversion.
+ * gdb.base/dfp-test.exp: Likewise.
+
2017-10-04 Pedro Alves <palves@redhat.com>
* gdb.multi/hangout.c: Include <unistd.h>.
gdb_test "ptype 3 + 2.1dl" " = _Decimal128"
# Reject operation with integral larger than 32-bits
- gdb_test "p 1.2df + 2ll" "Conversion of large integer to a decimal floating type is not supported."
+ gdb_test "p 1.2dd + 2ll" "= 3.2"
+ gdb_test "p 1.2dd + 2147483648ll" "Conversion of large integer to a decimal floating type is not supported."
+ gdb_test "p 1.2dd + 2147483648ull" "= 2147483649.2"
+ gdb_test "p 1.2dd + 4294967296ull" "Conversion of large integer to a decimal floating type is not supported."
# Reject operation with DFP and Binary FP
gdb_test "p 1.2df + 1.2f" "Mixing decimal floating types with other floating types is not allowed."
gdb_test "p d32 + 1" " = 1.1"
gdb_test "p 2 + d64" " = 2.1"
gdb_test "p ds.int4 + d128" " = 1.1"
+gdb_test "p d32 + ds.long8" " = 2.1"
gdb_test "ptype d32 + 1" " = volatile _Decimal32"
gdb_test "ptype ds.int4 + d128" " = volatile _Decimal128"
gdb_test "p ds.int4 > ds.dec64" " = 0"
gdb_test "p ds.dec128 > ds.int4" " = 1"
-# Reject operation with integral larger than 32-bits
-if { ${sizeof_long} > 4 } {
- gdb_test "p d32 + ds.long8" "Conversion of large integer to a decimal floating type is not supported."
-}
-
# Reject operation with DFP and Binary FP
gdb_test "p d64 + ds.float4" "Mixing decimal floating types with other floating types is not allowed."
gdb_test "p ds.double8 + d128" "Mixing decimal floating types with other floating types is not allowed."
{
*byte_order_x = gdbarch_byte_order (get_type_arch (type2));
*len_x = TYPE_LENGTH (type2);
- decimal_from_integral (arg1, x, *len_x, *byte_order_x);
+ if (TYPE_UNSIGNED (type1))
+ decimal_from_ulongest (value_as_long (arg1), x, *len_x, *byte_order_x);
+ else
+ decimal_from_longest (value_as_long (arg1), x, *len_x, *byte_order_x);
}
else
error (_("Don't know how to convert from %s to %s."), TYPE_NAME (type1),
{
*byte_order_y = gdbarch_byte_order (get_type_arch (type1));
*len_y = TYPE_LENGTH (type1);
- decimal_from_integral (arg2, y, *len_y, *byte_order_y);
+ if (TYPE_UNSIGNED (type2))
+ decimal_from_ulongest (value_as_long (arg2), y, *len_y, *byte_order_y);
+ else
+ decimal_from_longest (value_as_long (arg2), y, *len_y, *byte_order_y);
}
else
error (_("Don't know how to convert from %s to %s."), TYPE_NAME (type1),
gdb_byte dec[16];
if (code2 == TYPE_CODE_FLT)
- decimal_from_floating (arg2, dec, dec_len, byte_order);
+ decimal_from_doublest (value_as_double (arg2),
+ dec, dec_len, byte_order);
else if (code2 == TYPE_CODE_DECFLOAT)
decimal_convert (value_contents (arg2), TYPE_LENGTH (type2),
byte_order, dec, dec_len, byte_order);
+ /* The only option left is an integral type. */
+ else if (TYPE_UNSIGNED (type2))
+ decimal_from_ulongest (value_as_long (arg2),
+ dec, dec_len, byte_order);
else
- /* The only option left is an integral type. */
- decimal_from_integral (arg2, dec, dec_len, byte_order);
+ decimal_from_longest (value_as_long (arg2),
+ dec, dec_len, byte_order);
return value_from_decfloat (to_type, dec);
}
struct ui_file *stream)
{
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
- char decstr[MAX_DECIMAL_STRING];
unsigned len = TYPE_LENGTH (type);
- decimal_to_string (valaddr, len, byte_order, decstr);
- fputs_filtered (decstr, stream);
- return;
+ std::string str = decimal_to_string (valaddr, len, byte_order);
+ fputs_filtered (str.c_str (), stream);
}
void
return (LONGEST) extract_typed_floating (valaddr, type);
case TYPE_CODE_DECFLOAT:
- /* libdecnumber has a function to convert from decimal to integer, but
- it doesn't work when the decimal number has a fractional part. */
- return (LONGEST) decimal_to_doublest (valaddr, len, byte_order);
+ return decimal_to_longest (valaddr, len, byte_order);
case TYPE_CODE_PTR:
case TYPE_CODE_REF: