/* YACC parser for C expressions, for GDB.
- Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994
+ Free Software Foundation, Inc.
This file is part of GDB.
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. */
/* Parse a C expression from text in a string,
and return the result as a struct expression pointer.
%{
#include "defs.h"
+#include <string.h>
#include "expression.h"
#include "value.h"
#include "parser-defs.h"
#define yylloc c_lloc
#define yyreds c_reds /* With YYDEBUG defined */
#define yytoks c_toks /* With YYDEBUG defined */
+#define yylhs c_yylhs
+#define yylen c_yylen
+#define yydefred c_yydefred
+#define yydgoto c_yydgoto
+#define yysindex c_yysindex
+#define yyrindex c_yyrindex
+#define yygindex c_yygindex
+#define yytable c_yytable
+#define yycheck c_yycheck
#ifndef YYDEBUG
#define YYDEBUG 0 /* Default to no yydebug support */
/* Special type cases, put in to allow the parser to distinguish different
legal basetypes. */
%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD
-%token <lval> LAST REGNAME
-%token <ivar> VARIABLE
+%token <voidval> VARIABLE
%token <opcode> ASSIGN_MODIFY
write_exp_elt_opcode (STRUCTOP_STRUCT); }
;
+/* start-sanitize-gm
+Need to find a better way to do this...
+exp : exp '@' name
+ { write_exp_elt_opcode (STRUCTOP_FIELD);
+ write_exp_string ($3);
+ write_exp_elt_opcode (STRUCTOP_FIELD);
+ }
+ end-sanitize-gm */
+
exp : exp '.' qualified_name
{ /* exp.type::name becomes exp.*(&type::name) */
/* Note: this doesn't work if name is a
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); }
+ /* Already written by write_dollar_variable. */
;
exp : SIZEOF '(' type ')' %prec UNARY
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
+ CHECK_TYPEDEF ($3);
write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
write_exp_elt_opcode (OP_LONG); }
;
struct symtab *tem =
lookup_symtab (copy_name ($1.stoken));
if (tem)
- $$ = BLOCKVECTOR_BLOCK
- (BLOCKVECTOR (tem), STATIC_BLOCK);
+ $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), STATIC_BLOCK);
else
error ("No file or function \"%s\".",
copy_name ($1.stoken));
break;
}
- msymbol = lookup_minimal_symbol (name,
- (struct objfile *) NULL);
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
if (msymbol != NULL)
{
write_exp_msymbol (msymbol,
struct minimal_symbol *msymbol;
register char *arg = copy_name ($1.stoken);
- msymbol = lookup_minimal_symbol (arg,
- (struct objfile *) NULL);
+ msymbol =
+ lookup_minimal_symbol (arg, NULL, NULL);
if (msymbol != NULL)
{
write_exp_msymbol (msymbol,
int parsed_float;
YYSTYPE *putithere;
{
+ /* FIXME: Shouldn't these be unsigned? We don't deal with negative values
+ here, and we do kind of silly things like cast to unsigned. */
register LONGEST n = 0;
register LONGEST prevn = 0;
+ unsigned LONGEST un;
+
register int i = 0;
register int c;
register int base = input_radix;
int unsigned_p = 0;
+
+ /* Number of "L" suffixes encountered. */
int long_p = 0;
+
+ /* We have found a "L" or "U" suffix. */
+ int found_suffix = 0;
+
unsigned LONGEST high_bit;
struct type *signed_type;
struct type *unsigned_type;
if (c != 'l' && c != 'u')
n *= base;
if (c >= '0' && c <= '9')
- n += i = c - '0';
+ {
+ if (found_suffix)
+ return ERROR;
+ n += i = c - '0';
+ }
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;
+ {
+ if (found_suffix)
+ return ERROR;
+ n += i = c - 'a' + 10;
+ }
+ else if (c == 'l')
+ {
+ ++long_p;
+ found_suffix = 1;
+ }
+ else if (c == 'u')
+ {
+ unsigned_p = 1;
+ found_suffix = 1;
+ }
else
return ERROR; /* Char not a digit */
}
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)
- unsigned_p=1; /* Try something unsigned */
- /* If range checking enabled, portably test for unsigned overflow. */
- if(RANGE_CHECK && n!=0)
- {
- if((unsigned_p && (unsigned)prevn >= (unsigned)n))
- range_error("Overflow on numeric constant.");
- }
- prevn=n;
+ a second check for zero). FIXME: Can't we just make n and prevn
+ unsigned and avoid this? */
+ if (c != 'l' && c != 'u' && (prevn >= n) && n != 0)
+ unsigned_p = 1; /* Try something unsigned */
+
+ /* Portably test for unsigned overflow.
+ FIXME: This check is wrong; for example it doesn't find overflow
+ on 0x123456789 when LONGEST is 32 bits. */
+ if (c != 'l' && c != 'u' && n != 0)
+ {
+ if ((unsigned_p && (unsigned LONGEST) prevn >= (unsigned LONGEST) n))
+ error ("Numeric constant too large.");
+ }
+ prevn = n;
+ }
+
+ /* An integer constant is an int, a long, or a long long. An L
+ suffix forces it to be long; an LL suffix forces it to be long
+ long. If not forced to a larger size, it gets the first type of
+ the above that it fits in. To figure out whether it fits, we
+ shift it right and see whether anything remains. Note that we
+ can't shift sizeof (LONGEST) * HOST_CHAR_BIT bits or more in one
+ operation, because many compilers will warn about such a shift
+ (which always produces a zero result). Sometimes TARGET_INT_BIT
+ or TARGET_LONG_BIT will be that big, sometimes not. To deal with
+ the case where it is we just always shift the value more than
+ once, with fewer bits each time. */
+
+ un = (unsigned LONGEST)n >> 2;
+ if (long_p == 0
+ && (un >> (TARGET_INT_BIT - 2)) == 0)
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
+
+ /* A large decimal (not hex or octal) constant (between INT_MAX
+ and UINT_MAX) is a long or unsigned long, according to ANSI,
+ never an unsigned int, but this code treats it as unsigned
+ int. This probably should be fixed. GCC gives a warning on
+ such constants. */
+
+ unsigned_type = builtin_type_unsigned_int;
+ signed_type = builtin_type_int;
+ }
+ else if (long_p <= 1
+ && (un >> (TARGET_LONG_BIT - 2)) == 0)
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
+ unsigned_type = builtin_type_unsigned_long;
+ signed_type = builtin_type_long;
+ }
+ else
+ {
+ high_bit = (((unsigned LONGEST)1)
+ << (TARGET_LONG_LONG_BIT - 32 - 1)
+ << 16
+ << 16);
+ if (high_bit == 0)
+ /* A long long does not fit in a LONGEST. */
+ high_bit =
+ (unsigned LONGEST)1 << (sizeof (LONGEST) * HOST_CHAR_BIT - 1);
+ unsigned_type = builtin_type_unsigned_long_long;
+ signed_type = builtin_type_long_long;
}
-
- /* If the number is too big to be an int, or it's got an l suffix
- then it's a long. Work out if this has to be a long by
- shifting right and and seeing if anything remains, and the
- target int size is different to the target long size.
-
- In the expression below, we could have tested
- (n >> TARGET_INT_BIT)
- to see if it was zero,
- but too many compilers warn about that, when ints and longs
- are the same size. So we shift it twice, with fewer bits
- each time, for the same result. */
-
- if ( (TARGET_INT_BIT != TARGET_LONG_BIT
- && ((n >> 2) >> (TARGET_INT_BIT-2))) /* Avoid shift warning */
- || long_p)
- {
- high_bit = ((unsigned LONGEST)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);
- unsigned_type = builtin_type_unsigned_int;
- signed_type = builtin_type_int;
- }
putithere->typed_val.val = n;
if (unsigned_p || (n & high_bit))
{
- putithere->typed_val.type = unsigned_type;
+ putithere->typed_val.type = unsigned_type;
}
else
{
- putithere->typed_val.type = signed_type;
+ putithere->typed_val.type = signed_type;
}
return INT;
c = *lexptr++;
if (c == '\\')
c = parse_escape (&lexptr);
+ else if (c == '\'')
+ error ("Empty character constant.");
yylval.typed_val.val = c;
yylval.typed_val.type = builtin_type_char;
namelen = 0;
for (c = tokstart[namelen];
(c == '_' || c == '$' || (c >= '0' && c <= '9')
- || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
- c = tokstart[++namelen])
- ;
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');)
+ {
+ if (c == '<')
+ {
+ int i = namelen;
+ while (tokstart[++i] && tokstart[i] != '>');
+ if (tokstart[i] == '>')
+ namelen = i;
+ }
+ c = tokstart[++namelen];
+ }
/* The token "if" terminates the expression and is NOT
removed from the input stream. */
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. Should be done with a data structure. */
switch (namelen)
{
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;
}
}
if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
{
+#if 1
+ /* Despite the following flaw, we need to keep this code enabled.
+ Because we can get called from check_stub_method, if we don't
+ handle nested types then it screws many operations in any
+ program which uses nested types. */
+ /* In "A::x", if x is a member function of A and there happens
+ to be a type (nested or not, since the stabs don't make that
+ distinction) named x, then this code incorrectly thinks we
+ are dealing with nested types rather than a member function. */
+
char *p;
char *namestart;
struct symbol *best_sym;
struct symbol *cur_sym;
/* As big as the whole rest of the expression, which is
at least big enough. */
- char *tmp = alloca (strlen (namestart));
-
- memcpy (tmp, namestart, p - namestart);
- tmp[p - namestart] = '\0';
- cur_sym = lookup_symbol (tmp, expression_context_block,
+ char *ncopy = alloca (strlen (tmp)+strlen (namestart)+3);
+ char *tmp1;
+
+ tmp1 = ncopy;
+ memcpy (tmp1, tmp, strlen (tmp));
+ tmp1 += strlen (tmp);
+ memcpy (tmp1, "::", 2);
+ tmp1 += 2;
+ memcpy (tmp1, namestart, p - namestart);
+ tmp1[p - namestart] = '\0';
+ cur_sym = lookup_symbol (ncopy, expression_context_block,
VAR_NAMESPACE, (int *) NULL,
(struct symtab **) NULL);
if (cur_sym)
}
yylval.tsym.type = SYMBOL_TYPE (best_sym);
+#else /* not 0 */
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+#endif /* not 0 */
return TYPENAME;
}
if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
yyerror (msg)
char *msg;
{
- error (msg ? msg : "Invalid syntax in expression.");
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
}