X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ff-exp.y;h=7e838b0a93a459b931ed41808692217b215ad71d;hb=efbecbc143f19cb308ae220fb386505f41ff4bc3;hp=8dcc811b6816f8af5a318d9047a9a52559f3d942;hpb=eae49211e13efa075d57ab354ea4207666eadc96;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/f-exp.y b/gdb/f-exp.y index 8dcc811b68..7e838b0a93 100644 --- a/gdb/f-exp.y +++ b/gdb/f-exp.y @@ -1,6 +1,6 @@ /* YACC parser for Fortran expressions, for GDB. - Copyright (C) 1986-2017 Free Software Foundation, Inc. + Copyright (C) 1986-2019 Free Software Foundation, Inc. Contributed by Motorola. Adapted from the C parser by Farooq Butt (fmbutt@engage.sps.mot.com). @@ -72,12 +72,16 @@ int yyparse (void); static int yylex (void); -void yyerror (const char *); +static void yyerror (const char *); static void growbuf_by_size (int); static int match_string_literal (void); +static void push_kind_type (LONGEST val, struct type *type); + +static struct type *convert_to_kind_type (struct type *basetype, int kind); + %} /* Although the yacc "value" of an expression is not used, @@ -91,7 +95,10 @@ static int match_string_literal (void); 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; @@ -122,7 +129,7 @@ static int parse_number (struct parser_state *, const char *, int, %type ptype %token INT -%token FLOAT +%token FLOAT /* Both NAME and TYPENAME tokens represent symbols in the input, and both convey their data as strings. @@ -146,7 +153,7 @@ static int parse_number (struct parser_state *, const char *, int, %token NAME_OR_INT -%token SIZEOF +%token SIZEOF KIND %token ERROR /* Special type cases, put in to allow the parser to distinguish different @@ -158,9 +165,10 @@ static int parse_number (struct parser_state *, const char *, int, %token BOOL_AND BOOL_OR BOOL_NOT %token CHARACTER -%token VARIABLE +%token DOLLAR_VARIABLE %token ASSIGN_MODIFY +%token UNOP_INTRINSIC %left ',' %left ABOVE_COMMA @@ -225,6 +233,10 @@ exp : SIZEOF exp %prec UNARY { write_exp_elt_opcode (pstate, UNOP_SIZEOF); } ; +exp : KIND '(' exp ')' %prec UNARY + { write_exp_elt_opcode (pstate, UNOP_KIND); } + ; + /* No more explicit array operators, we treat everything in F77 as a function call. The disambiguation as to whether we are doing a subscript operation or a function call is done @@ -241,6 +253,10 @@ exp : exp '(' OP_F77_UNDETERMINED_ARGLIST); } ; +exp : UNOP_INTRINSIC '(' exp ')' + { write_exp_elt_opcode (pstate, $1); } + ; + arglist : ; @@ -414,18 +430,16 @@ exp : NAME_OR_INT ; 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 ; -exp : VARIABLE +exp : DOLLAR_VARIABLE ; exp : SIZEOF '(' type ')' %prec UNARY @@ -460,12 +474,7 @@ variable: name_not_typename if (sym.symbol) { if (symbol_read_needs_frame (sym.symbol)) - { - if (innermost_block == 0 - || contained_in (sym.block, - innermost_block)) - innermost_block = sym.block; - } + innermost_block.update (sym); write_exp_elt_opcode (pstate, OP_VAR_VALUE); write_exp_elt_block (pstate, sym.block); write_exp_elt_sym (pstate, sym.symbol); @@ -534,6 +543,13 @@ ptype : typebase case tp_function: follow_type = lookup_function_type (follow_type); break; + case tp_kind: + { + int kind_val = pop_type_int (); + follow_type + = convert_to_kind_type (follow_type, kind_val); + } + break; } $$ = follow_type; } @@ -552,6 +568,10 @@ abs_decl: '*' direct_abs_decl: '(' abs_decl ')' { $$ = $2; } + | '(' KIND '=' INT ')' + { push_kind_type ($4.val, $4.type); } + | '*' INT + { push_kind_type ($2.val, $2.type); } | direct_abs_decl func_mod { push_type (tp_function); } | func_mod @@ -647,16 +667,22 @@ parse_number (struct parser_state *par_state, 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 */ @@ -771,74 +797,164 @@ parse_number (struct parser_state *par_state, return INT; } +/* Called to setup the type stack when we encounter a '(kind=N)' type + modifier, performs some bounds checking on 'N' and then pushes this to + the type stack followed by the 'tp_kind' marker. */ +static void +push_kind_type (LONGEST val, struct type *type) +{ + int ival; + + if (TYPE_UNSIGNED (type)) + { + ULONGEST uval = static_cast (val); + if (uval > INT_MAX) + error (_("kind value out of range")); + ival = static_cast (uval); + } + else + { + if (val > INT_MAX || val < 0) + error (_("kind value out of range")); + ival = static_cast (val); + } + + push_type_int (ival); + push_type (tp_kind); +} + +/* Called when a type has a '(kind=N)' modifier after it, for example + 'character(kind=1)'. The BASETYPE is the type described by 'character' + in our example, and KIND is the integer '1'. This function returns a + new type that represents the basetype of a specific kind. */ +static struct type * +convert_to_kind_type (struct type *basetype, int kind) +{ + if (basetype == parse_f_type (pstate)->builtin_character) + { + /* Character of kind 1 is a special case, this is the same as the + base character type. */ + if (kind == 1) + return parse_f_type (pstate)->builtin_character; + } + else if (basetype == parse_f_type (pstate)->builtin_complex_s8) + { + if (kind == 4) + return parse_f_type (pstate)->builtin_complex_s8; + else if (kind == 8) + return parse_f_type (pstate)->builtin_complex_s16; + else if (kind == 16) + return parse_f_type (pstate)->builtin_complex_s32; + } + else if (basetype == parse_f_type (pstate)->builtin_real) + { + if (kind == 4) + return parse_f_type (pstate)->builtin_real; + else if (kind == 8) + return parse_f_type (pstate)->builtin_real_s8; + else if (kind == 16) + return parse_f_type (pstate)->builtin_real_s16; + } + else if (basetype == parse_f_type (pstate)->builtin_logical) + { + if (kind == 1) + return parse_f_type (pstate)->builtin_logical_s1; + else if (kind == 2) + return parse_f_type (pstate)->builtin_logical_s2; + else if (kind == 4) + return parse_f_type (pstate)->builtin_logical; + else if (kind == 8) + return parse_f_type (pstate)->builtin_logical_s8; + } + else if (basetype == parse_f_type (pstate)->builtin_integer) + { + if (kind == 2) + return parse_f_type (pstate)->builtin_integer_s2; + else if (kind == 4) + return parse_f_type (pstate)->builtin_integer; + else if (kind == 8) + return parse_f_type (pstate)->builtin_integer_s8; + } + + error (_("unsupported kind %d for type %s"), + kind, TYPE_SAFE_NAME (basetype)); + + /* Should never get here. */ + return nullptr; +} + struct token { + /* The string to match against. */ const char *oper; + + /* The lexer token to return. */ int token; + + /* The expression opcode to embed within the token. */ enum exp_opcode opcode; + + /* When this is true the string in OPER is matched exactly including + case, when this is false OPER is matched case insensitively. */ + bool case_sensitive; }; static const struct token dot_ops[] = { - { ".and.", BOOL_AND, BINOP_END }, - { ".AND.", BOOL_AND, BINOP_END }, - { ".or.", BOOL_OR, BINOP_END }, - { ".OR.", BOOL_OR, BINOP_END }, - { ".not.", BOOL_NOT, BINOP_END }, - { ".NOT.", BOOL_NOT, BINOP_END }, - { ".eq.", EQUAL, BINOP_END }, - { ".EQ.", EQUAL, BINOP_END }, - { ".eqv.", EQUAL, BINOP_END }, - { ".NEQV.", NOTEQUAL, BINOP_END }, - { ".neqv.", NOTEQUAL, BINOP_END }, - { ".EQV.", EQUAL, BINOP_END }, - { ".ne.", NOTEQUAL, BINOP_END }, - { ".NE.", NOTEQUAL, BINOP_END }, - { ".le.", LEQ, BINOP_END }, - { ".LE.", LEQ, BINOP_END }, - { ".ge.", GEQ, BINOP_END }, - { ".GE.", GEQ, BINOP_END }, - { ".gt.", GREATERTHAN, BINOP_END }, - { ".GT.", GREATERTHAN, BINOP_END }, - { ".lt.", LESSTHAN, BINOP_END }, - { ".LT.", LESSTHAN, BINOP_END }, - { NULL, 0, BINOP_END } + { ".and.", BOOL_AND, BINOP_END, false }, + { ".or.", BOOL_OR, BINOP_END, false }, + { ".not.", BOOL_NOT, BINOP_END, false }, + { ".eq.", EQUAL, BINOP_END, false }, + { ".eqv.", EQUAL, BINOP_END, false }, + { ".neqv.", NOTEQUAL, BINOP_END, false }, + { ".ne.", NOTEQUAL, BINOP_END, false }, + { ".le.", LEQ, BINOP_END, false }, + { ".ge.", GEQ, BINOP_END, false }, + { ".gt.", GREATERTHAN, BINOP_END, false }, + { ".lt.", LESSTHAN, BINOP_END, false }, }; -struct f77_boolean_val +/* Holds the Fortran representation of a boolean, and the integer value we + substitute in when one of the matching strings is parsed. */ +struct f77_boolean_val { + /* The string representing a Fortran boolean. */ const char *name; + + /* The integer value to replace it with. */ int value; -}; +}; -static const struct f77_boolean_val boolean_values[] = +/* The set of Fortran booleans. These are matched case insensitively. */ +static const struct f77_boolean_val boolean_values[] = { { ".true.", 1 }, - { ".TRUE.", 1 }, - { ".false.", 0 }, - { ".FALSE.", 0 }, - { NULL, 0 } + { ".false.", 0 } }; -static const struct token f77_keywords[] = +static const struct token f77_keywords[] = { - { "complex_16", COMPLEX_S16_KEYWORD, BINOP_END }, - { "complex_32", COMPLEX_S32_KEYWORD, BINOP_END }, - { "character", CHARACTER, BINOP_END }, - { "integer_2", INT_S2_KEYWORD, BINOP_END }, - { "logical_1", LOGICAL_S1_KEYWORD, BINOP_END }, - { "logical_2", LOGICAL_S2_KEYWORD, BINOP_END }, - { "logical_8", LOGICAL_S8_KEYWORD, BINOP_END }, - { "complex_8", COMPLEX_S8_KEYWORD, BINOP_END }, - { "integer", INT_KEYWORD, BINOP_END }, - { "logical", LOGICAL_KEYWORD, BINOP_END }, - { "real_16", REAL_S16_KEYWORD, BINOP_END }, - { "complex", COMPLEX_S8_KEYWORD, BINOP_END }, - { "sizeof", SIZEOF, BINOP_END }, - { "real_8", REAL_S8_KEYWORD, BINOP_END }, - { "real", REAL_KEYWORD, BINOP_END }, - { NULL, 0, BINOP_END } -}; + /* Historically these have always been lowercase only in GDB. */ + { "complex_16", COMPLEX_S16_KEYWORD, BINOP_END, true }, + { "complex_32", COMPLEX_S32_KEYWORD, BINOP_END, true }, + { "character", CHARACTER, BINOP_END, true }, + { "integer_2", INT_S2_KEYWORD, BINOP_END, true }, + { "logical_1", LOGICAL_S1_KEYWORD, BINOP_END, true }, + { "logical_2", LOGICAL_S2_KEYWORD, BINOP_END, true }, + { "logical_8", LOGICAL_S8_KEYWORD, BINOP_END, true }, + { "complex_8", COMPLEX_S8_KEYWORD, BINOP_END, true }, + { "integer", INT_KEYWORD, BINOP_END, true }, + { "logical", LOGICAL_KEYWORD, BINOP_END, true }, + { "real_16", REAL_S16_KEYWORD, BINOP_END, true }, + { "complex", COMPLEX_S8_KEYWORD, BINOP_END, true }, + { "sizeof", SIZEOF, BINOP_END, true }, + { "real_8", REAL_S8_KEYWORD, BINOP_END, true }, + { "real", REAL_KEYWORD, BINOP_END, true }, + /* The following correspond to actual functions in Fortran and are case + insensitive. */ + { "kind", KIND, BINOP_END, false }, + { "abs", UNOP_INTRINSIC, UNOP_ABS, false } +}; /* Implementation of a dynamically expandable buffer for processing input characters acquired through lexptr and building a value to return in @@ -921,7 +1037,7 @@ yylex (void) { int c; int namelen; - unsigned int i,token; + unsigned int token; const char *tokstart; retry: @@ -929,35 +1045,35 @@ yylex (void) prev_lexptr = lexptr; tokstart = lexptr; - - /* First of all, let us make sure we are not dealing with the + + /* First of all, let us make sure we are not dealing with the special tokens .true. and .false. which evaluate to 1 and 0. */ - + if (*lexptr == '.') - { - for (i = 0; boolean_values[i].name != NULL; i++) + { + for (int i = 0; i < ARRAY_SIZE (boolean_values); i++) { - if (strncmp (tokstart, boolean_values[i].name, - strlen (boolean_values[i].name)) == 0) + if (strncasecmp (tokstart, boolean_values[i].name, + strlen (boolean_values[i].name)) == 0) { - lexptr += strlen (boolean_values[i].name); - yylval.lval = boolean_values[i].value; + lexptr += strlen (boolean_values[i].name); + yylval.lval = boolean_values[i].value; return BOOLEAN_LITERAL; } } } - + /* See if it is a special .foo. operator. */ - - for (i = 0; dot_ops[i].oper != NULL; i++) - if (strncmp (tokstart, dot_ops[i].oper, - strlen (dot_ops[i].oper)) == 0) + for (int i = 0; i < ARRAY_SIZE (dot_ops); i++) + if (strncasecmp (tokstart, dot_ops[i].oper, + strlen (dot_ops[i].oper)) == 0) { + gdb_assert (!dot_ops[i].case_sensitive); lexptr += strlen (dot_ops[i].oper); yylval.opcode = dot_ops[i].opcode; return dot_ops[i].token; } - + /* See if it is an exponentiation operator. */ if (strncmp (tokstart, "**", 2) == 0) @@ -1006,7 +1122,7 @@ yylex (void) /* Might be a floating point number. */ if (lexptr[1] < '0' || lexptr[1] > '9') goto symbol; /* Nope, must be a symbol. */ - /* FALL THRU into number case. */ + /* FALL THRU. */ case '0': case '1': @@ -1117,23 +1233,25 @@ yylex (void) lexptr += namelen; /* Catch specific keywords. */ - - for (i = 0; f77_keywords[i].oper != NULL; i++) + + for (int i = 0; i < ARRAY_SIZE (f77_keywords); i++) if (strlen (f77_keywords[i].oper) == namelen - && strncmp (tokstart, f77_keywords[i].oper, namelen) == 0) + && ((!f77_keywords[i].case_sensitive + && strncasecmp (tokstart, f77_keywords[i].oper, namelen) == 0) + || (f77_keywords[i].case_sensitive + && strncmp (tokstart, f77_keywords[i].oper, namelen) == 0))) { - /* lexptr += strlen(f77_keywords[i].operator); */ yylval.opcode = f77_keywords[i].opcode; return f77_keywords[i].token; } - + yylval.sval.ptr = tokstart; yylval.sval.length = namelen; if (*tokstart == '$') { write_dollar_variable (pstate, yylval.sval); - return VARIABLE; + return DOLLAR_VARIABLE; } /* Use token-type TYPENAME for symbols that happen to be defined @@ -1149,10 +1267,9 @@ yylex (void) VAR_DOMAIN, MODULE_DOMAIN }; - int i; int hextype; - for (i = 0; i < ARRAY_SIZE (lookup_domains); ++i) + for (int i = 0; i < ARRAY_SIZE (lookup_domains); ++i) { /* Initialize this in case we *don't* use it in this call; that way we can refer to it unconditionally below. */ @@ -1208,17 +1325,19 @@ f_parse (struct parser_state *par_state) { /* Setting up the parser state. */ scoped_restore pstate_restore = make_scoped_restore (&pstate); + scoped_restore restore_yydebug = make_scoped_restore (&yydebug, + parser_debug); gdb_assert (par_state != NULL); pstate = par_state; return yyparse (); } -void +static void yyerror (const char *msg) { if (prev_lexptr) lexptr = prev_lexptr; - error (_("A %s in expression, near `%s'."), (msg ? msg : "error"), lexptr); + error (_("A %s in expression, near `%s'."), msg, lexptr); }