+2017-10-25 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * doublest.c (floatformat_from_string): New function.
+ * doublest.h (floatformat_from_string): Add prototype.
+
+ * std-operator.def (OP_DOUBLE, OP_DECFLOAT): Remove, replace by ...
+ (OP_FLOAT): ... this.
+ * expression.h: Do not include "doublest.h".
+ (union exp_element): Replace doubleconst and decfloatconst by
+ new element floatconst.
+ * ada-lang.c (resolve_subexp): Handle OP_FLOAT instead of OP_DOUBLE.
+ (ada_evaluate_subexp): Likewise.
+ * eval.c (evaluate_subexp_standard): Handle OP_FLOAT instead of
+ OP_DOUBLE and OP_DECFLOAT.
+ * expprint.c (print_subexp_standard): Likewise.
+ (dump_subexp_body_standard): Likewise.
+ * breakpoint.c (watchpoint_exp_is_const): Likewise.
+
+ * parse.c: Include "dfp.h".
+ (write_exp_elt_dblcst, write_exp_elt_decfloatcst): Remove.
+ (write_exp_elt_floatcst): New function.
+ (operator_length_standard): Handle OP_FLOAT instead of OP_DOUBLE
+ and OP_DECFLOAT.
+ (operator_check_standard): Likewise.
+ (parse_float): Do not accept suffix. Take type as input. Return bool.
+ Return target format buffer instead of host DOUBLEST.
+ Use floatformat_from_string and decimal_from_string to parse
+ either binary or decimal floating-point types.
+ (parse_c_float): Remove.
+ * parser-defs.h: Do not include "doublest.h".
+ (write_exp_elt_dblcst, write_exp_elt_decfloatcst): Remove.
+ (write_exp_elt_floatcst): Add prototype.
+ (parse_float): Update prototype.
+ (parse_c_float): Remove.
+
+ * c-exp.y: Do not include "dfp.h".
+ (typed_val_float): Use byte buffer instead of DOUBLEST.
+ (typed_val_decfloat): Remove.
+ (DECFLOAT): Remove.
+ (FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+ (parse_number): Update to new parse_float interface.
+ Parse suffixes and determine type before calling parse_float.
+ Handle decimal and binary FP types the same way.
+
+ * d-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
+ (FLOAT_LITERAL): Use OP_FLOAT and write_exp_elt_floatcst.
+ (parse_number): Update to new parse_float interface.
+ Parse suffixes and determine type before calling parse_float.
+
+ * f-exp.y: Replace dval by typed_val_float.
+ (FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+ (parse_number): Use parse_float instead of atof.
+
+ * go-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
+ (parse_go_float): Remove.
+ (FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+ (parse_number): Call parse_float instead of parse_go_float.
+ Parse suffixes and determine type before calling parse_float.
+
+ * p-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
+ (FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+ (parse_number): Update to new parse_float interface.
+ Parse suffixes and determine type before calling parse_float.
+
+ * m2-exp.y: Replace dval by byte buffer val.
+ (FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+ (parse_number): Call parse_float instead of atof.
+
+ * rust-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
+ (lex_number): Call parse_float instead of strtod.
+ (ast_dliteral): Use OP_FLOAT instead of OP_DOUBLE.
+ (convert_ast_to_expression): Handle OP_FLOAT instead of OP_DOUBLE.
+ Use write_exp_elt_floatcst.
+ (unit_testing): Remove static variable.
+ (rust_type): Do not check unit_testing.
+ (rust_lex_tests): Do not set uint_testing. Set up dummy rust_parser.
+
+ * ada-exp.y (type_float, type_double): Remove.
+ (typed_val_float): Use byte buffer instead of DOUBLEST.
+ (FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+ * ada-lex.l (processReal): Use parse_float instead of sscanf.
+
2017-10-25 Alan Hayward <alan.hayward@arm.com>
* aarch64-tdep.h (enum aarch64_regnum): Remove.
static struct type *type_long_long (struct parser_state *);
-static struct type *type_float (struct parser_state *);
-
-static struct type *type_double (struct parser_state *);
-
static struct type *type_long_double (struct parser_state *);
static struct type *type_char (struct parser_state *);
struct type *type;
} typed_val;
struct {
- DOUBLEST dval;
+ gdb_byte val[16];
struct type *type;
} typed_val_float;
struct type *tval;
;
primary : FLOAT
- { write_exp_elt_opcode (pstate, OP_DOUBLE);
+ { write_exp_elt_opcode (pstate, OP_FLOAT);
write_exp_elt_type (pstate, $1.type);
- write_exp_elt_dblcst (pstate, $1.dval);
- write_exp_elt_opcode (pstate, OP_DOUBLE);
+ write_exp_elt_floatcst (pstate, $1.val);
+ write_exp_elt_opcode (pstate, OP_FLOAT);
}
;
return parse_type (par_state)->builtin_long_long;
}
-static struct type *
-type_float (struct parser_state *par_state)
-{
- return parse_type (par_state)->builtin_float;
-}
-
-static struct type *
-type_double (struct parser_state *par_state)
-{
- return parse_type (par_state)->builtin_double;
-}
-
static struct type *
type_long_double (struct parser_state *par_state)
{
break;
case OP_LONG:
- case OP_DOUBLE:
+ case OP_FLOAT:
case OP_VAR_VALUE:
case OP_VAR_MSYM_VALUE:
*pos += 4;
if (noside == EVAL_NORMAL)
arg1 = unwrap_value (arg1);
- /* If evaluating an OP_DOUBLE and an EXPECT_TYPE was provided,
+ /* If evaluating an OP_FLOAT and an EXPECT_TYPE was provided,
then we need to perform the conversion manually, because
evaluate_subexp_standard doesn't do it. This conversion is
necessary in Ada because the different kinds of float/fixed
Similarly, we need to perform the conversion from OP_LONG
ourselves. */
- if ((op == OP_DOUBLE || op == OP_LONG) && expect_type != NULL)
+ if ((op == OP_FLOAT || op == OP_LONG) && expect_type != NULL)
arg1 = ada_value_cast (expect_type, arg1, noside);
return arg1;
static int
processReal (struct parser_state *par_state, const char *num0)
{
- sscanf (num0, "%" DOUBLEST_SCAN_FORMAT, &yylval.typed_val_float.dval);
-
- yylval.typed_val_float.type = type_float (par_state);
- if (sizeof(DOUBLEST) >= gdbarch_double_bit (parse_gdbarch (par_state))
- / TARGET_CHAR_BIT)
- yylval.typed_val_float.type = type_double (par_state);
- if (sizeof(DOUBLEST) >= gdbarch_long_double_bit (parse_gdbarch (par_state))
- / TARGET_CHAR_BIT)
- yylval.typed_val_float.type = type_long_double (par_state);
+ yylval.typed_val_float.type = type_long_double (par_state);
+ bool parsed = parse_float (num0, strlen (num0),
+ yylval.typed_val_float.type,
+ yylval.typed_val_float.val);
+ gdb_assert (parsed);
return FLOAT;
}
case TERNOP_SLICE:
case OP_LONG:
- case OP_DOUBLE:
- case OP_DECFLOAT:
+ case OP_FLOAT:
case OP_LAST:
case OP_COMPLEX:
case OP_STRING:
#include "charset.h"
#include "block.h"
#include "cp-support.h"
-#include "dfp.h"
#include "macroscope.h"
#include "objc-lang.h"
#include "typeprint.h"
LONGEST val;
struct type *type;
} typed_val_int;
- struct {
- DOUBLEST dval;
- struct type *type;
- } typed_val_float;
struct {
gdb_byte val[16];
struct type *type;
- } typed_val_decfloat;
+ } typed_val_float;
struct type *tval;
struct stoken sval;
struct typed_stoken tsval;
%token <typed_val_int> INT
%token <typed_val_float> FLOAT
-%token <typed_val_decfloat> DECFLOAT
/* Both NAME and TYPENAME tokens represent symbols in the input,
and both convey their data as strings.
exp : FLOAT
- { write_exp_elt_opcode (pstate, OP_DOUBLE);
+ { write_exp_elt_opcode (pstate, OP_FLOAT);
write_exp_elt_type (pstate, $1.type);
- write_exp_elt_dblcst (pstate, $1.dval);
- write_exp_elt_opcode (pstate, OP_DOUBLE); }
- ;
-
-exp : DECFLOAT
- { write_exp_elt_opcode (pstate, OP_DECFLOAT);
- write_exp_elt_type (pstate, $1.type);
- write_exp_elt_decfloatcst (pstate, $1.val);
- write_exp_elt_opcode (pstate, OP_DECFLOAT); }
+ write_exp_elt_floatcst (pstate, $1.val);
+ write_exp_elt_opcode (pstate, OP_FLOAT); }
;
exp : variable
if (parsed_float)
{
- /* If it ends at "df", "dd" or "dl", take it as type of decimal floating
- point. Return DECFLOAT. */
-
+ /* Handle suffixes for decimal floating-point: "df", "dd" or "dl". */
if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'f')
{
- putithere->typed_val_decfloat.type
+ putithere->typed_val_float.type
= parse_type (par_state)->builtin_decfloat;
- decimal_from_string (putithere->typed_val_decfloat.val, 4,
- gdbarch_byte_order (parse_gdbarch (par_state)),
- std::string (p, len - 2));
- return DECFLOAT;
+ len -= 2;
}
-
- if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd')
+ else if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd')
{
- putithere->typed_val_decfloat.type
+ putithere->typed_val_float.type
= parse_type (par_state)->builtin_decdouble;
- decimal_from_string (putithere->typed_val_decfloat.val, 8,
- gdbarch_byte_order (parse_gdbarch (par_state)),
- std::string (p, len - 2));
- return DECFLOAT;
+ len -= 2;
}
-
- if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l')
+ else if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l')
{
- putithere->typed_val_decfloat.type
+ putithere->typed_val_float.type
= parse_type (par_state)->builtin_declong;
- decimal_from_string (putithere->typed_val_decfloat.val, 16,
- gdbarch_byte_order (parse_gdbarch (par_state)),
- std::string (p, len - 2));
- return DECFLOAT;
+ len -= 2;
+ }
+ /* Handle suffixes: 'f' for float, 'l' for long double. */
+ else if (len >= 1 && tolower (p[len - 1]) == 'f')
+ {
+ putithere->typed_val_float.type
+ = parse_type (par_state)->builtin_float;
+ len -= 1;
+ }
+ else if (len >= 1 && tolower (p[len - 1]) == 'l')
+ {
+ putithere->typed_val_float.type
+ = parse_type (par_state)->builtin_long_double;
+ len -= 1;
+ }
+ /* Default type for floating-point literals is double. */
+ else
+ {
+ putithere->typed_val_float.type
+ = parse_type (par_state)->builtin_double;
}
- if (! parse_c_float (parse_gdbarch (par_state), p, len,
- &putithere->typed_val_float.dval,
- &putithere->typed_val_float.type))
- return ERROR;
+ if (!parse_float (p, len,
+ putithere->typed_val_float.type,
+ putithere->typed_val_float.val))
+ return ERROR;
return FLOAT;
}
struct type *type;
} typed_val_int;
struct {
- DOUBLEST dval;
+ gdb_byte val[16];
struct type *type;
} typed_val_float;
struct symbol *sym;
write_exp_elt_longcst (pstate, (LONGEST)($1.val));
write_exp_elt_opcode (pstate, OP_LONG); }
| FLOAT_LITERAL
- { write_exp_elt_opcode (pstate, OP_DOUBLE);
+ { write_exp_elt_opcode (pstate, OP_FLOAT);
write_exp_elt_type (pstate, $1.type);
- write_exp_elt_dblcst (pstate, $1.dval);
- write_exp_elt_opcode (pstate, OP_DOUBLE); }
+ write_exp_elt_floatcst (pstate, $1.val);
+ write_exp_elt_opcode (pstate, OP_FLOAT); }
| CHARACTER_LITERAL
{ struct stoken_vector vec;
vec.len = 1;
if (parsed_float)
{
- const char *suffix;
- int suffix_len;
char *s, *sp;
/* Strip out all embedded '_' before passing to parse_float. */
*sp = '\0';
len = strlen (s);
- if (! parse_float (s, len, &putithere->typed_val_float.dval, &suffix))
- return ERROR;
-
- suffix_len = s + len - suffix;
-
- if (suffix_len == 0)
- {
- putithere->typed_val_float.type
- = parse_d_type (ps)->builtin_double;
- }
- else if (suffix_len == 1)
+ /* Check suffix for `i' , `fi' or `li' (idouble, ifloat or ireal). */
+ if (len >= 1 && tolower (s[len - 1]) == 'i')
{
- /* Check suffix for `f', `l', or `i' (float, real, or idouble). */
- if (tolower (*suffix) == 'f')
+ if (len >= 2 && tolower (s[len - 2]) == 'f')
{
putithere->typed_val_float.type
- = parse_d_type (ps)->builtin_float;
+ = parse_d_type (ps)->builtin_ifloat;
+ len -= 2;
}
- else if (tolower (*suffix) == 'l')
+ else if (len >= 2 && tolower (s[len - 2]) == 'l')
{
putithere->typed_val_float.type
- = parse_d_type (ps)->builtin_real;
+ = parse_d_type (ps)->builtin_ireal;
+ len -= 2;
}
- else if (tolower (*suffix) == 'i')
+ else
{
putithere->typed_val_float.type
= parse_d_type (ps)->builtin_idouble;
+ len -= 1;
}
- else
- return ERROR;
}
- else if (suffix_len == 2)
+ /* Check suffix for `f' or `l'' (float or real). */
+ else if (len >= 1 && tolower (s[len - 1]) == 'f')
{
- /* Check suffix for `fi' or `li' (ifloat or ireal). */
- if (tolower (suffix[0]) == 'f' && tolower (suffix[1] == 'i'))
- {
- putithere->typed_val_float.type
- = parse_d_type (ps)->builtin_ifloat;
- }
- else if (tolower (suffix[0]) == 'l' && tolower (suffix[1] == 'i'))
- {
- putithere->typed_val_float.type
- = parse_d_type (ps)->builtin_ireal;
- }
- else
- return ERROR;
+ putithere->typed_val_float.type
+ = parse_d_type (ps)->builtin_float;
+ len -= 1;
}
+ else if (len >= 1 && tolower (s[len - 1]) == 'l')
+ {
+ putithere->typed_val_float.type
+ = parse_d_type (ps)->builtin_real;
+ len -= 1;
+ }
+ /* Default type if no suffix. */
else
+ {
+ putithere->typed_val_float.type
+ = parse_d_type (ps)->builtin_double;
+ }
+
+ if (!parse_float (s, len,
+ putithere->typed_val_float.type,
+ putithere->typed_val_float.val))
return ERROR;
return FLOAT_LITERAL;
floatformat_to_doublest (fmt, in, &doub);
return string_printf (host_format.c_str (), doub);
}
+
+/* Parse string STRING into a target floating-number of format FMT and
+ store it as byte-stream ADDR. Return whether parsing succeeded. */
+bool
+floatformat_from_string (const struct floatformat *fmt, gdb_byte *out,
+ const std::string &in)
+{
+ DOUBLEST doub;
+ int n, num;
+#ifdef HAVE_LONG_DOUBLE
+ const char *scan_format = "%Lg%n";
+#else
+ const char *scan_format = "%lg%n";
+#endif
+ num = sscanf (in.c_str (), scan_format, &doub, &n);
+
+ /* The sscanf man page suggests not making any assumptions on the effect
+ of %n on the result, so we don't.
+ That is why we simply test num == 0. */
+ if (num == 0)
+ return false;
+
+ /* We only accept the whole string. */
+ if (in[n])
+ return false;
+
+ floatformat_from_doublest (fmt, &doub, out);
+ return true;
+}
\f
/* Extract a floating-point number of type TYPE from a target-order
byte-stream at ADDR. Returns the value as type DOUBLEST. */
extern std::string floatformat_to_string (const struct floatformat *fmt,
const gdb_byte *in,
const char *format = nullptr);
+extern bool floatformat_from_string (const struct floatformat *fmt,
+ gdb_byte *out, const std::string &in);
/* Return the floatformat's total size in host bytes. */
return value_from_longest (exp->elts[pc + 1].type,
exp->elts[pc + 2].longconst);
- case OP_DOUBLE:
+ case OP_FLOAT:
(*pos) += 3;
- return value_from_double (exp->elts[pc + 1].type,
- exp->elts[pc + 2].doubleconst);
-
- case OP_DECFLOAT:
- (*pos) += 3;
- return value_from_decfloat (exp->elts[pc + 1].type,
- exp->elts[pc + 2].decfloatconst);
+ return value_from_contents (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].floatconst);
case OP_ADL_FUNC:
case OP_VAR_VALUE:
}
return;
- case OP_DOUBLE:
+ case OP_FLOAT:
{
struct value_print_options opts;
get_no_prettyformat_print_options (&opts);
(*pos) += 3;
- value_print (value_from_double (exp->elts[pc + 1].type,
- exp->elts[pc + 2].doubleconst),
+ value_print (value_from_contents (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].floatconst),
stream, &opts);
}
return;
(long) exp->elts[elt + 1].longconst);
elt += 3;
break;
- case OP_DOUBLE:
+ case OP_FLOAT:
fprintf_filtered (stream, "Type @");
gdb_print_host_address (exp->elts[elt].type, stream);
fprintf_filtered (stream, " (");
type_print (exp->elts[elt].type, NULL, stream, 0);
- fprintf_filtered (stream, "), value %g",
- (double) exp->elts[elt + 1].doubleconst);
+ fprintf_filtered (stream, "), value ");
+ print_floating (exp->elts[elt + 1].floatconst,
+ exp->elts[elt].type, stream);
elt += 3;
break;
case OP_VAR_VALUE:
#include "symtab.h" /* Needed for "struct block" type. */
-#include "doublest.h" /* Needed for DOUBLEST. */
/* Definitions for saved C expressions. */
struct symbol *symbol;
struct minimal_symbol *msymbol;
LONGEST longconst;
- DOUBLEST doubleconst;
- gdb_byte decfloatconst[16];
+ gdb_byte floatconst[16];
/* Really sizeof (union exp_element) characters (or less for the last
element of a string). */
char string;
LONGEST val;
struct type *type;
} typed_val;
- DOUBLEST dval;
+ struct {
+ gdb_byte val[16];
+ struct type *type;
+ } typed_val_float;
struct symbol *sym;
struct type *tval;
struct stoken sval;
%type <tval> ptype
%token <typed_val> INT
-%token <dval> FLOAT
+%token <typed_val_float> FLOAT
/* Both NAME and TYPENAME tokens represent symbols in the input,
and both convey their data as strings.
;
exp : FLOAT
- { write_exp_elt_opcode (pstate, OP_DOUBLE);
- write_exp_elt_type (pstate,
- parse_f_type (pstate)
- ->builtin_real_s8);
- write_exp_elt_dblcst (pstate, $1);
- write_exp_elt_opcode (pstate, OP_DOUBLE); }
+ { write_exp_elt_opcode (pstate, OP_FLOAT);
+ write_exp_elt_type (pstate, $1.type);
+ write_exp_elt_floatcst (pstate, $1.val);
+ write_exp_elt_opcode (pstate, OP_FLOAT); }
;
exp : variable
if (parsed_float)
{
/* It's a float since it contains a point or an exponent. */
- /* [dD] is not understood as an exponent by atof, change it to 'e'. */
+ /* [dD] is not understood as an exponent by parse_float,
+ change it to 'e'. */
char *tmp, *tmp2;
tmp = xstrdup (p);
for (tmp2 = tmp; *tmp2; ++tmp2)
if (*tmp2 == 'd' || *tmp2 == 'D')
*tmp2 = 'e';
- putithere->dval = atof (tmp);
+
+ /* FIXME: Should this use different types? */
+ putithere->typed_val_float.type = parse_f_type (pstate)->builtin_real_s8;
+ bool parsed = parse_float (tmp, len,
+ putithere->typed_val_float.type,
+ putithere->typed_val_float.val);
free (tmp);
- return FLOAT;
+ return parsed? FLOAT : ERROR;
}
/* Handle base-switching prefixes 0x, 0t, 0d, 0 */
struct type *type;
} typed_val_int;
struct {
- DOUBLEST dval;
+ gdb_byte val[16];
struct type *type;
} typed_val_float;
struct stoken sval;
/* YYSTYPE gets defined by %union. */
static int parse_number (struct parser_state *,
const char *, int, int, YYSTYPE *);
-static int parse_go_float (struct gdbarch *gdbarch, const char *p, int len,
- DOUBLEST *d, struct type **t);
%}
%type <voidval> exp exp1 type_exp start variable lcurly
exp : FLOAT
- { write_exp_elt_opcode (pstate, OP_DOUBLE);
+ { write_exp_elt_opcode (pstate, OP_FLOAT);
write_exp_elt_type (pstate, $1.type);
- write_exp_elt_dblcst (pstate, $1.dval);
- write_exp_elt_opcode (pstate, OP_DOUBLE); }
+ write_exp_elt_floatcst (pstate, $1.val);
+ write_exp_elt_opcode (pstate, OP_FLOAT); }
;
exp : variable
%%
-/* Wrapper on parse_c_float to get the type right for Go. */
-
-static int
-parse_go_float (struct gdbarch *gdbarch, const char *p, int len,
- DOUBLEST *d, struct type **t)
-{
- int result = parse_c_float (gdbarch, p, len, d, t);
- const struct builtin_type *builtin_types = builtin_type (gdbarch);
- const struct builtin_go_type *builtin_go_types = builtin_go_type (gdbarch);
-
- if (*t == builtin_types->builtin_float)
- *t = builtin_go_types->builtin_float32;
- else if (*t == builtin_types->builtin_double)
- *t = builtin_go_types->builtin_float64;
-
- return result;
-}
-
/* Take care of parsing a number (anything that starts with a digit).
Set yylval and return the token type; update lexptr.
LEN is the number of characters in it. */
if (parsed_float)
{
- if (! parse_go_float (parse_gdbarch (par_state), p, len,
- &putithere->typed_val_float.dval,
- &putithere->typed_val_float.type))
- return ERROR;
+ const struct builtin_go_type *builtin_go_types
+ = builtin_go_type (parse_gdbarch (par_state));
+
+ /* Handle suffixes: 'f' for float32, 'l' for long double.
+ FIXME: This appears to be an extension -- do we want this? */
+ if (len >= 1 && tolower (p[len - 1]) == 'f')
+ {
+ putithere->typed_val_float.type
+ = builtin_go_types->builtin_float32;
+ len--;
+ }
+ else if (len >= 1 && tolower (p[len - 1]) == 'l')
+ {
+ putithere->typed_val_float.type
+ = parse_type (par_state)->builtin_long_double;
+ len--;
+ }
+ /* Default type for floating-point literals is float64. */
+ else
+ {
+ putithere->typed_val_float.type
+ = builtin_go_types->builtin_float64;
+ }
+
+ if (!parse_float (p, len,
+ putithere->typed_val_float.type,
+ putithere->typed_val_float.val))
+ return ERROR;
return FLOAT;
}
{
LONGEST lval;
ULONGEST ulval;
- DOUBLEST dval;
+ gdb_byte val[16];
struct symbol *sym;
struct type *tval;
struct stoken sval;
%token <lval> INT HEX ERROR
%token <ulval> UINT M2_TRUE M2_FALSE CHAR
-%token <dval> FLOAT
+%token <val> FLOAT
/* Both NAME and TYPENAME tokens represent symbols in the input,
and both convey their data as strings.
exp : FLOAT
- { write_exp_elt_opcode (pstate, OP_DOUBLE);
+ { write_exp_elt_opcode (pstate, OP_FLOAT);
write_exp_elt_type (pstate,
parse_m2_type (pstate)
->builtin_real);
- write_exp_elt_dblcst (pstate, $1);
- write_exp_elt_opcode (pstate, OP_DOUBLE); }
+ write_exp_elt_floatcst (pstate, $1);
+ write_exp_elt_opcode (pstate, OP_FLOAT); }
;
exp : variable
if (p[c] == '.' && base == 10)
{
/* It's a float since it contains a point. */
- yylval.dval = atof (p);
+ if (!parse_float (p, len,
+ parse_m2_type (pstate)->builtin_real,
+ yylval.val))
+ return ERROR;
+
lexptr += len;
return FLOAT;
}
struct type *type;
} typed_val_int;
struct {
- DOUBLEST dval;
+ gdb_byte val[16];
struct type *type;
} typed_val_float;
struct symbol *sym;
exp : FLOAT
- { write_exp_elt_opcode (pstate, OP_DOUBLE);
+ { write_exp_elt_opcode (pstate, OP_FLOAT);
write_exp_elt_type (pstate, $1.type);
current_type = $1.type;
- write_exp_elt_dblcst (pstate, $1.dval);
- write_exp_elt_opcode (pstate, OP_DOUBLE); }
+ write_exp_elt_floatcst (pstate, $1.val);
+ write_exp_elt_opcode (pstate, OP_FLOAT); }
;
exp : variable
if (parsed_float)
{
- if (! parse_c_float (parse_gdbarch (par_state), p, len,
- &putithere->typed_val_float.dval,
- &putithere->typed_val_float.type))
+ /* Handle suffixes: 'f' for float, 'l' for long double.
+ FIXME: This appears to be an extension -- do we want this? */
+ if (len >= 1 && tolower (p[len - 1]) == 'f')
+ {
+ putithere->typed_val_float.type
+ = parse_type (par_state)->builtin_float;
+ len--;
+ }
+ else if (len >= 1 && tolower (p[len - 1]) == 'l')
+ {
+ putithere->typed_val_float.type
+ = parse_type (par_state)->builtin_long_double;
+ len--;
+ }
+ /* Default type for floating-point literals is double. */
+ else
+ {
+ putithere->typed_val_float.type
+ = parse_type (par_state)->builtin_double;
+ }
+
+ if (!parse_float (p, len,
+ putithere->typed_val_float.type,
+ putithere->typed_val_float.val))
return ERROR;
return FLOAT;
}
#include "symfile.h" /* for overlay functions */
#include "inferior.h"
#include "doublest.h"
+#include "dfp.h"
#include "block.h"
#include "source.h"
#include "objfiles.h"
}
void
-write_exp_elt_dblcst (struct parser_state *ps, DOUBLEST expelt)
-{
- union exp_element tmp;
-
- memset (&tmp, 0, sizeof (union exp_element));
- tmp.doubleconst = expelt;
- write_exp_elt (ps, &tmp);
-}
-
-void
-write_exp_elt_decfloatcst (struct parser_state *ps, gdb_byte expelt[16])
+write_exp_elt_floatcst (struct parser_state *ps, const gdb_byte expelt[16])
{
union exp_element tmp;
int index;
for (index = 0; index < 16; index++)
- tmp.decfloatconst[index] = expelt[index];
+ tmp.floatconst[index] = expelt[index];
write_exp_elt (ps, &tmp);
}
break;
case OP_LONG:
- case OP_DOUBLE:
- case OP_DECFLOAT:
+ case OP_FLOAT:
case OP_VAR_VALUE:
case OP_VAR_MSYM_VALUE:
oplen = 4;
}
/* Parse floating point value P of length LEN.
- Return 0 (false) if invalid, 1 (true) if valid.
- The successfully parsed number is stored in D.
- *SUFFIX points to the suffix of the number in P.
+ Return false if invalid, true if valid.
+ The successfully parsed number is stored in DATA in
+ target format for floating-point type TYPE.
NOTE: This accepts the floating point syntax that sscanf accepts. */
-int
-parse_float (const char *p, int len, DOUBLEST *d, const char **suffix)
-{
- char *copy;
- int n, num;
-
- copy = (char *) xmalloc (len + 1);
- memcpy (copy, p, len);
- copy[len] = 0;
-
- num = sscanf (copy, "%" DOUBLEST_SCAN_FORMAT "%n", d, &n);
- xfree (copy);
-
- /* The sscanf man page suggests not making any assumptions on the effect
- of %n on the result, so we don't.
- That is why we simply test num == 0. */
- if (num == 0)
- return 0;
-
- *suffix = p + n;
- return 1;
-}
-
-/* Parse floating point value P of length LEN, using the C syntax for floats.
- Return 0 (false) if invalid, 1 (true) if valid.
- The successfully parsed number is stored in *D.
- Its type is taken from builtin_type (gdbarch) and is stored in *T. */
-
-int
-parse_c_float (struct gdbarch *gdbarch, const char *p, int len,
- DOUBLEST *d, struct type **t)
+bool
+parse_float (const char *p, int len,
+ const struct type *type, gdb_byte *data)
{
- const char *suffix;
- int suffix_len;
- const struct builtin_type *builtin_types = builtin_type (gdbarch);
-
- if (! parse_float (p, len, d, &suffix))
- return 0;
-
- suffix_len = p + len - suffix;
-
- if (suffix_len == 0)
- *t = builtin_types->builtin_double;
- else if (suffix_len == 1)
- {
- /* Handle suffixes: 'f' for float, 'l' for long double. */
- if (tolower (*suffix) == 'f')
- *t = builtin_types->builtin_float;
- else if (tolower (*suffix) == 'l')
- *t = builtin_types->builtin_long_double;
- else
- return 0;
- }
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ return floatformat_from_string (floatformat_from_type (type),
+ data, std::string (p, len));
else
- return 0;
-
- return 1;
+ return decimal_from_string (data, TYPE_LENGTH (type),
+ gdbarch_byte_order (get_type_arch (type)),
+ std::string (p, len));
}
\f
/* Stuff for maintaining a stack of types. Currently just used by C, but
{
case BINOP_VAL:
case OP_COMPLEX:
- case OP_DECFLOAT:
- case OP_DOUBLE:
+ case OP_FLOAT:
case OP_LONG:
case OP_SCOPE:
case OP_TYPE:
#if !defined (PARSER_DEFS_H)
#define PARSER_DEFS_H 1
-#include "doublest.h"
#include "vec.h"
#include "expression.h"
extern void write_exp_elt_longcst (struct parser_state *, LONGEST);
-extern void write_exp_elt_dblcst (struct parser_state *, DOUBLEST);
-
-extern void write_exp_elt_decfloatcst (struct parser_state *, gdb_byte *);
+extern void write_exp_elt_floatcst (struct parser_state *, const gdb_byte *);
extern void write_exp_elt_type (struct parser_state *, struct type *);
extern void null_post_parser (struct expression **, int);
-extern int parse_float (const char *p, int len, DOUBLEST *d,
- const char **suffix);
-
-extern int parse_c_float (struct gdbarch *gdbarch, const char *p, int len,
- DOUBLEST *d, struct type **t);
+extern bool parse_float (const char *p, int len,
+ const struct type *type, gdb_byte *data);
/* During parsing of a C expression, the pointer to the next character
is in this variable. */
struct typed_val_float
{
- DOUBLEST dval;
+ gdb_byte val[16];
struct type *type;
};
static regex_t number_regex;
-/* True if we're running unit tests. */
-
-static int unit_testing;
-
/* Obstack for data temporarily allocated during parsing. Points to
the obstack in the rust_parser, or to a temporary obstack during
unit testing. */
{
struct type *type;
- /* When unit testing, we don't bother checking the types, so avoid a
- possibly-failing lookup here. */
- if (unit_testing)
- return NULL;
-
type = language_lookup_primitive_type (current_parser->language (),
current_parser->arch (),
name);
}
else
{
- rustyylval.typed_val_float.dval = strtod (number.c_str (), NULL);
rustyylval.typed_val_float.type = type;
+ bool parsed = parse_float (number.c_str (), number.length (),
+ rustyylval.typed_val_float.type,
+ rustyylval.typed_val_float.val);
+ gdb_assert (parsed);
}
return is_integer ? (could_be_decimal ? DECIMAL_INTEGER : INTEGER) : FLOAT;
{
struct rust_op *result = OBSTACK_ZALLOC (work_obstack, struct rust_op);
- result->opcode = OP_DOUBLE;
+ result->opcode = OP_FLOAT;
result->left.typed_val_float = val;
return result;
write_exp_elt_opcode (state, OP_LONG);
break;
- case OP_DOUBLE:
- write_exp_elt_opcode (state, OP_DOUBLE);
+ case OP_FLOAT:
+ write_exp_elt_opcode (state, OP_FLOAT);
write_exp_elt_type (state, operation->left.typed_val_float.type);
- write_exp_elt_dblcst (state, operation->left.typed_val_float.dval);
- write_exp_elt_opcode (state, OP_DOUBLE);
+ write_exp_elt_floatcst (state, operation->left.typed_val_float.val);
+ write_exp_elt_opcode (state, OP_FLOAT);
break;
case STRUCTOP_STRUCT:
scoped_restore obstack_holder = make_scoped_restore (&work_obstack,
&test_obstack);
- unit_testing = 1;
+ // Set up dummy "parser", so that rust_type works.
+ struct parser_state ps;
+ initialize_expout (&ps, 0, &rust_language_defn, target_gdbarch ());
+ rust_parser parser (&ps);
rust_lex_test_one ("", 0);
rust_lex_test_one (" \t \n \r ", 0);
rust_lex_test_completion ();
rust_lex_test_push_back ();
-
- unit_testing = 0;
}
#endif /* GDB_SELF_TEST */
Thus, the operation occupies four exp_elements. */
OP (OP_LONG)
-/* OP_DOUBLE is similar but takes a DOUBLEST constant instead of a
- long. */
-OP (OP_DOUBLE)
+/* OP_FLOAT is similar but takes a floating-point constant encoded in
+ the target format for the given type instead of a long. */
+OP (OP_FLOAT)
/* OP_VAR_VALUE takes one struct block * in the following element,
and one struct symbol * in the following exp_element, followed
":exp" and ":"). */
OP (OP_RANGE)
-/* OP_DECFLOAT is followed by a type pointer in the next exp_element
- and a dec long constant value in the following exp_element.
- Then comes another OP_DECFLOAT. */
-OP (OP_DECFLOAT)
-
/* OP_ADL_FUNC specifies that the function is to be looked up in an
Argument Dependent manner (Koenig lookup). */
OP (OP_ADL_FUNC)