/* YACC parser for Fortran expressions, for GDB.
- Copyright 1986, 1989, 1990, 1991, 1993, 1994
- Free Software Foundation, Inc.
+ Copyright 1986, 1989, 1990, 1991, 1993, 1994, 1995, 1996, 2000, 2001
+ Free Software Foundation, Inc.
+
Contributed by Motorola. Adapted from the C parser by Farooq Butt
(fmbutt@engage.sps.mot.com).
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. */
/* This was blantantly ripped off the C expression parser, please
be aware of that as you look at its basic structure -FMB */
%{
#include "defs.h"
+#include "gdb_string.h"
#include "expression.h"
-#include "parser-defs.h"
#include "value.h"
+#include "parser-defs.h"
#include "language.h"
#include "f-lang.h"
#include "bfd.h" /* Required by objfiles.h. */
#include "symfile.h" /* Required by objfiles.h. */
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+#include "block.h"
+#include <ctype.h>
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
#define yylloc f_lloc
#define yyreds f_reds /* With YYDEBUG defined */
#define yytoks f_toks /* With YYDEBUG defined */
+#define yyname f_name /* With YYDEBUG defined */
+#define yyrule f_rule /* With YYDEBUG defined */
+#define yylhs f_yylhs
+#define yylen f_yylen
+#define yydefred f_yydefred
+#define yydgoto f_yydgoto
+#define yysindex f_yysindex
+#define yyrindex f_yyrindex
+#define yygindex f_yygindex
+#define yytable f_yytable
+#define yycheck f_yycheck
#ifndef YYDEBUG
-#define YYDEBUG 1 /* Default to no yydebug support */
+#define YYDEBUG 1 /* Default to yydebug support */
#endif
-int yyparse PARAMS ((void));
+#define YYFPRINTF parser_fprintf
+
+int yyparse (void);
+
+static int yylex (void);
+
+void yyerror (char *);
-static int yylex PARAMS ((void));
+static void growbuf_by_size (int);
-void yyerror PARAMS ((char *));
+static int match_string_literal (void);
%}
LONGEST val;
struct type *type;
} typed_val;
- double dval;
+ DOUBLEST dval;
struct symbol *sym;
struct type *tval;
struct stoken sval;
%{
/* YYSTYPE gets defined by %union */
-static int parse_number PARAMS ((char *, int, int, YYSTYPE *));
+static int parse_number (char *, int, int, YYSTYPE *);
%}
%type <voidval> exp type_exp start variable
%token LOGICAL_KEYWORD REAL_KEYWORD REAL_S8_KEYWORD REAL_S16_KEYWORD
%token COMPLEX_S8_KEYWORD COMPLEX_S16_KEYWORD COMPLEX_S32_KEYWORD
%token BOOL_AND BOOL_OR BOOL_NOT
-%token <lval> LAST REGNAME CHARACTER
+%token <lval> CHARACTER
-%token <ivar> VARIABLE
+%token <voidval> VARIABLE
%token <opcode> ASSIGN_MODIFY
write_exp_elt_opcode(OP_TYPE); }
;
-
exp : '(' exp ')'
{ }
;
/* Expressions, not including the comma operator. */
exp : '*' exp %prec UNARY
{ write_exp_elt_opcode (UNOP_IND); }
+ ;
exp : '&' exp %prec UNARY
{ write_exp_elt_opcode (UNOP_ADDR); }
+ ;
exp : '-' exp %prec UNARY
{ write_exp_elt_opcode (UNOP_NEG); }
arglist : substring
{ arglist_len = 2;}
+ ;
arglist : arglist ',' exp %prec ABOVE_COMMA
{ arglist_len++; }
;
exp : '(' complexnum ')'
- { write_exp_elt_opcode(OP_F77_LITERAL_COMPLEX); }
+ { write_exp_elt_opcode(OP_COMPLEX); }
;
exp : '(' type ')' exp %prec UNARY
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (val.typed_val.type);
write_exp_elt_longcst ((LONGEST)val.typed_val.val);
- write_exp_elt_opcode (OP_LONG);
- }
+ write_exp_elt_opcode (OP_LONG); }
;
exp : FLOAT
exp : variable
;
-exp : LAST
- { write_exp_elt_opcode (OP_LAST);
- write_exp_elt_longcst ((LONGEST) $1);
- write_exp_elt_opcode (OP_LAST); }
- ;
-
-exp : REGNAME
- { write_exp_elt_opcode (OP_REGISTER);
- write_exp_elt_longcst ((LONGEST) $1);
- write_exp_elt_opcode (OP_REGISTER); }
- ;
-
exp : VARIABLE
- { write_exp_elt_opcode (OP_INTERNALVAR);
- write_exp_elt_intern ($1);
- write_exp_elt_opcode (OP_INTERNALVAR); }
;
exp : SIZEOF '(' type ')' %prec UNARY
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_f_integer);
+ CHECK_TYPEDEF ($3);
write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
write_exp_elt_opcode (OP_LONG); }
;
;
exp : STRING_LITERAL
- { /* In F77, we encounter string literals
- basically in only one place:
- when we are setting up manual parameter
- lists to functions we call by hand or
- when setting string vars to manual values.
- These are character*N type variables.
- They are treated specially behind the
- scenes. Remember that the literal strings's
- OPs are being emitted in reverse order, thus
- we first have the elements and then
- the array descriptor itself. */
- char *sp = $1.ptr; int count = $1.length;
-
- while (count-- > 0)
- {
- write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type (builtin_type_f_character);
- write_exp_elt_longcst ((LONGEST)(*sp++));
- write_exp_elt_opcode (OP_LONG);
- }
- write_exp_elt_opcode (OP_ARRAY);
- write_exp_elt_longcst ((LONGEST) 1);
- write_exp_elt_longcst ((LONGEST) ($1.length));
- write_exp_elt_opcode (OP_ARRAY);
+ {
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_STRING);
}
-
;
variable: name_not_typename
innermost_block = block_found;
}
write_exp_elt_opcode (OP_VAR_VALUE);
+ /* We want to use the selected frame, not
+ another more inner frame which happens to
+ be in the same block. */
+ write_exp_elt_block (NULL);
write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE);
break;
struct minimal_symbol *msymbol;
register char *arg = copy_name ($1.stoken);
- msymbol = lookup_minimal_symbol (arg, NULL);
+ msymbol =
+ lookup_minimal_symbol (arg, NULL, NULL);
if (msymbol != NULL)
{
write_exp_msymbol (msymbol,
func_mod: '(' ')'
{ $$ = 0; }
| '(' nonempty_typelist ')'
- { free ((PTR)$2); $$ = 0; }
+ { free ($2); $$ = 0; }
;
typebase /* Implements (approximately): (type-qualifier)* type-specifier */
{
register LONGEST n = 0;
register LONGEST prevn = 0;
- register int i;
register int c;
register int base = input_radix;
int unsigned_p = 0;
int long_p = 0;
- unsigned LONGEST high_bit;
+ ULONGEST high_bit;
struct type *signed_type;
struct type *unsigned_type;
if (parsed_float)
{
/* It's a float since it contains a point or an exponent. */
- putithere->dval = atof (p);
+ /* [dD] is not understood as an exponent by atof, 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);
+ free (tmp);
return FLOAT;
}
while (len-- > 0)
{
c = *p++;
- if (c >= 'A' && c <= 'Z')
- c += 'a' - 'A';
- if (c != 'l' && c != 'u')
- n *= base;
- if (c >= '0' && c <= '9')
- n += i = c - '0';
+ if (isupper (c))
+ c = tolower (c);
+ if (len == 0 && c == 'l')
+ long_p = 1;
+ else if (len == 0 && c == 'u')
+ unsigned_p = 1;
else
{
- if (base > 10 && c >= 'a' && c <= 'f')
- n += i = c - 'a' + 10;
- else if (len == 0 && c == 'l')
- long_p = 1;
- else if (len == 0 && c == 'u')
- unsigned_p = 1;
+ int i;
+ if (c >= '0' && c <= '9')
+ i = c - '0';
+ else if (c >= 'a' && c <= 'f')
+ i = c - 'a' + 10;
else
return ERROR; /* Char not a digit */
+ if (i >= base)
+ return ERROR; /* Invalid digit in this base */
+ n *= base;
+ n += i;
}
- if (i >= base)
- return ERROR; /* Invalid digit in this base */
-
/* Portably test for overflow (only works for nonzero values, so make
a second check for zero). */
if ((prevn >= n) && n != 0)
&& ((n >> 2) >> (TARGET_INT_BIT-2))) /* Avoid shift warning */
|| long_p)
{
- high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
+ high_bit = ((ULONGEST)1) << (TARGET_LONG_BIT-1);
unsigned_type = builtin_type_unsigned_long;
signed_type = builtin_type_long;
}
else
{
- high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
+ high_bit = ((ULONGEST)1) << (TARGET_INT_BIT-1);
unsigned_type = builtin_type_unsigned_int;
signed_type = builtin_type_int;
}
int namelen;
unsigned int i,token;
char *tokstart;
- char *tokptr;
- int tempbufindex;
- static char *tempbuf;
- static int tempbufsize;
retry:
-
+
+ prev_lexptr = lexptr;
+
tokstart = lexptr;
/* First of all, let us make sure we are not dealing with the
if (*lexptr == '.')
{
- for (i=0;boolean_values[i].name != NULL;i++)
+ for (i = 0; boolean_values[i].name != NULL; i++)
{
- if STREQN(tokstart,boolean_values[i].name,
- strlen(boolean_values[i].name))
+ if STREQN (tokstart, boolean_values[i].name,
+ strlen (boolean_values[i].name))
{
- lexptr += strlen(boolean_values[i].name);
+ lexptr += strlen (boolean_values[i].name);
yylval.lval = boolean_values[i].value;
- return (BOOLEAN_LITERAL);
+ return BOOLEAN_LITERAL;
}
}
}
/* See if it is a special .foo. operator */
for (i = 0; dot_ops[i].operator != NULL; i++)
- if (STREQN(tokstart, dot_ops[i].operator,
- strlen(dot_ops[i].operator)))
+ if (STREQN (tokstart, dot_ops[i].operator, strlen (dot_ops[i].operator)))
{
- lexptr += strlen(dot_ops[i].operator);
+ lexptr += strlen (dot_ops[i].operator);
yylval.opcode = dot_ops[i].opcode;
return dot_ops[i].token;
}
{
if (!hex && !got_e && (*p == 'e' || *p == 'E'))
got_dot = got_e = 1;
- else if (!hex && !got_e && (*p == 'd' || *p == 'D'))
+ else if (!hex && !got_d && (*p == 'd' || *p == 'D'))
got_dot = got_d = 1;
else if (!hex && !got_dot && *p == '.')
got_dot = 1;
- else if ((got_e && (p[-1] == 'e' || p[-1] == 'E')
- || got_d && (p[-1] == 'd' || p[-1] == 'D'))
+ else if (((got_e && (p[-1] == 'e' || p[-1] == 'E'))
+ || (got_d && (p[-1] == 'd' || p[-1] == 'D')))
&& (*p == '-' || *p == '+'))
/* This is the sign of the exponent, not the end of the
number. */
lexptr += namelen;
- /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
- and $$digits (equivalent to $<-digits> if you could type that).
- Make token type LAST, and put the number (the digits) in yylval. */
-
- tryname:
- if (*tokstart == '$')
- {
- register int negate = 0;
-
- c = 1;
- /* Double dollar means negate the number and add -1 as well.
- Thus $$ alone means -1. */
- if (namelen >= 2 && tokstart[1] == '$')
- {
- negate = 1;
- c = 2;
- }
- if (c == namelen)
- {
- /* Just dollars (one or two) */
- yylval.lval = - negate;
- return LAST;
- }
- /* Is the rest of the token digits? */
- for (; c < namelen; c++)
- if (!(tokstart[c] >= '0' && tokstart[c] <= '9'))
- break;
- if (c == namelen)
- {
- yylval.lval = atoi (tokstart + 1 + negate);
- if (negate)
- yylval.lval = - yylval.lval;
- return LAST;
- }
- }
-
- /* Handle tokens that refer to machine registers:
- $ followed by a register name. */
-
- if (*tokstart == '$') {
- for (c = 0; c < NUM_REGS; c++)
- if (namelen - 1 == strlen (reg_names[c])
- && STREQN (tokstart + 1, reg_names[c], namelen - 1))
- {
- yylval.lval = c;
- return REGNAME;
- }
- for (c = 0; c < num_std_regs; c++)
- if (namelen - 1 == strlen (std_regs[c].name)
- && STREQN (tokstart + 1, std_regs[c].name, namelen - 1))
- {
- yylval.lval = std_regs[c].regnum;
- return REGNAME;
- }
- }
/* Catch specific keywords. */
for (i = 0; f77_keywords[i].operator != NULL; i++)
yylval.sval.ptr = tokstart;
yylval.sval.length = namelen;
- /* Any other names starting in $ are debugger internal variables. */
-
if (*tokstart == '$')
{
- yylval.ivar = lookup_internalvar (copy_name (yylval.sval) + 1);
+ write_dollar_variable (yylval.sval);
return VARIABLE;
}
int hextype;
sym = lookup_symbol (tmp, expression_context_block,
- VAR_NAMESPACE,
+ VAR_DOMAIN,
current_language->la_language == language_cplus
? &is_a_field_of_this : NULL,
NULL);
yyerror (msg)
char *msg;
{
+ if (prev_lexptr)
+ lexptr = prev_lexptr;
+
error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
}