aboutsummaryrefslogtreecommitdiff
path: root/gdb/expread.y
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/expread.y')
-rw-r--r--gdb/expread.y235
1 files changed, 213 insertions, 22 deletions
diff --git a/gdb/expread.y b/gdb/expread.y
index 468d409..d9a18ea 100644
--- a/gdb/expread.y
+++ b/gdb/expread.y
@@ -93,10 +93,14 @@ struct stoken
struct block *bval;
enum exp_opcode opcode;
struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
}
%type <voidval> exp exp1 start variable
%type <tval> type typebase
+%type <tvec> nonempty_typelist
%type <bval> block
%token <lval> INT CHAR
@@ -122,6 +126,9 @@ struct stoken
%token <opcode> ASSIGN_MODIFY
+/* C++ */
+%token THIS
+
%left ','
%left ABOVE_COMMA
%right '=' ASSIGN_MODIFY
@@ -196,12 +203,20 @@ exp : exp ARROW name
write_exp_elt (STRUCTOP_PTR); }
;
+exp : exp ARROW '*' exp
+ { write_exp_elt (STRUCTOP_MPTR); }
+ ;
+
exp : exp '.' name
{ write_exp_elt (STRUCTOP_STRUCT);
write_exp_string ($3);
write_exp_elt (STRUCTOP_STRUCT); }
;
+exp : exp '.' '*' exp
+ { write_exp_elt (STRUCTOP_MEMBER); }
+ ;
+
exp : exp '[' exp1 ']'
{ write_exp_elt (BINOP_SUBSCRIPT); }
;
@@ -390,8 +405,17 @@ exp : STRING
write_exp_elt (OP_STRING); }
;
+/* C++. */
+exp : THIS
+ { write_exp_elt (OP_THIS);
+ write_exp_elt (OP_THIS); }
+ ;
+
+/* end of C++. */
+
block : name
- { struct symtab *tem = lookup_symtab (copy_name ($1));
+ {
+ struct symtab *tem = lookup_symtab (copy_name ($1));
struct symbol *sym;
if (tem)
@@ -406,34 +430,88 @@ block : name
else
error ("No file or function \"%s\".",
copy_name ($1));
- }}
+ }
+ }
;
block : block COLONCOLON name
- { struct symbol *tem
+ {
+ struct symbol *tem
= lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE);
if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
error ("No function \"%s\" in specified context.",
- copy_name ($3));
- $$ = SYMBOL_BLOCK_VALUE (tem); }
+ copy_name ($1));
+ $$ = SYMBOL_BLOCK_VALUE (tem);
+ }
;
variable: block COLONCOLON name
- { struct symbol *sym;
- sym = lookup_symbol ($3, copy_name ($1), VAR_NAMESPACE);
+ {
+ struct symbol *sym;
+ sym = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE);
if (sym == 0)
error ("No symbol \"%s\" in specified context.",
copy_name ($3));
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
- write_exp_elt (OP_VAR_VALUE); }
+ write_exp_elt (OP_VAR_VALUE);
+ }
+ ;
+
+variable: typebase COLONCOLON name
+ {
+ struct type *type = $1;
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION)
+ error ("`%s' is not defined as an aggregate type.",
+ TYPE_NAME (type));
+
+ write_exp_elt (OP_SCOPE);
+ write_exp_elt (type);
+ write_exp_string ($3);
+ write_exp_elt (OP_SCOPE);
+ }
+ | COLONCOLON name
+ {
+ char *name = copy_name ($2);
+ struct symbol *sym;
+ int i;
+
+ sym = lookup_symbol_2 (name, 0, VAR_NAMESPACE);
+ if (sym)
+ {
+ write_exp_elt (OP_VAR_VALUE);
+ write_exp_elt (sym);
+ write_exp_elt (OP_VAR_VALUE);
+ break;
+ }
+ for (i = 0; i < misc_function_count; i++)
+ if (!strcmp (misc_function_vector[i].name, name))
+ break;
+
+ if (i < misc_function_count)
+ {
+ write_exp_elt (OP_LONG);
+ write_exp_elt (builtin_type_int);
+ write_exp_elt (misc_function_vector[i].address);
+ write_exp_elt (OP_LONG);
+ write_exp_elt (UNOP_MEMVAL);
+ write_exp_elt (builtin_type_char);
+ write_exp_elt (UNOP_MEMVAL);
+ }
+ else
+ if (symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"symbol-file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.", name);
+ }
;
variable: NAME
{ struct symbol *sym;
- sym = lookup_symbol (copy_name ($1),
- expression_context_block,
- VAR_NAMESPACE);
+ sym = lookup_symbol_1 (copy_name ($1),
+ expression_context_block,
+ VAR_NAMESPACE);
if (sym)
{
write_exp_elt (OP_VAR_VALUE);
@@ -444,6 +522,32 @@ variable: NAME
{
register char *arg = copy_name ($1);
register int i;
+ int v, val;
+ /* C++: see if it hangs off of `this'. Must
+ not inadvertently convert from a method call
+ to data ref. */
+ v = (int)value_of_this (0);
+ if (v)
+ {
+ val = check_field (v, arg);
+ if (val)
+ {
+ write_exp_elt (OP_THIS);
+ write_exp_elt (OP_THIS);
+ write_exp_elt (STRUCTOP_PTR);
+ write_exp_string ($1);
+ write_exp_elt (STRUCTOP_PTR);
+ break;
+ }
+ }
+ sym = lookup_symbol_2 (arg, 0, VAR_NAMESPACE);
+ if (sym)
+ {
+ write_exp_elt (OP_VAR_VALUE);
+ write_exp_elt (sym);
+ write_exp_elt (OP_VAR_VALUE);
+ break; /* YACC-dependent */
+ }
for (i = 0; i < misc_function_count; i++)
if (!strcmp (misc_function_vector[i].name, arg))
break;
@@ -471,6 +575,17 @@ variable: NAME
type : typebase
| type '*'
{ $$ = lookup_pointer_type ($1); }
+ | type '&'
+ { $$ = lookup_reference_type ($1); }
+ | typebase COLONCOLON '*'
+ { $$ = lookup_member_pointer_type (builtin_type_int, $1); }
+ | type '(' typebase COLONCOLON '*' ')'
+ { $$ = lookup_member_pointer_type ($1, $3); }
+ | type '(' typebase COLONCOLON '*' ')' '(' ')'
+ { $$ = lookup_member_pointer_type (lookup_function_type ($1, 0), $3); }
+ | type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')'
+ { $$ = lookup_member_pointer_type (lookup_function_type ($1, $8), $3);
+ free ($8); }
;
typebase
@@ -490,6 +605,19 @@ typebase
{ $$ = lookup_unsigned_typename (copy_name ($2)); }
;
+nonempty_typelist
+ : type
+ { $$ = (struct type **)xmalloc (sizeof (struct type *) * 2);
+ $$[0] = (struct type *)0;
+ $$[1] = $1;
+ }
+ | nonempty_typelist ',' type
+ { int len = sizeof (struct type *) * ++($<ivec>1[0]);
+ $$ = (struct type **)xrealloc ($1, len);
+ $$[$<ivec>$[0]] = $3;
+ }
+ ;
+
name : NAME
| TYPENAME
;
@@ -598,6 +726,14 @@ static char *lexptr;
static char *namecopy;
+/* Current depth in parentheses within the expression. */
+
+static int paren_depth;
+
+/* Nonzero means stop parsing on first comma (if not within parentheses). */
+
+static int comma_terminates;
+
/* 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. */
@@ -753,6 +889,24 @@ yylex ()
error ("Invalid character constant.");
return CHAR;
+ case '(':
+ paren_depth++;
+ lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ lexptr++;
+ return c;
+
+ case ',':
+ if (comma_terminates && paren_depth == 0)
+ return 0;
+ lexptr++;
+ return c;
+
case '+':
case '-':
case '*':
@@ -766,8 +920,6 @@ yylex ()
case '@':
case '<':
case '>':
- case '(':
- case ')':
case '[':
case ']':
case '.':
@@ -776,7 +928,6 @@ yylex ()
case '=':
case '{':
case '}':
- case ',':
lexptr++;
return c;
@@ -881,13 +1032,23 @@ yylex ()
{
return STRUCT;
}
- if (namelen == 5 && !strncmp (tokstart, "union", 5))
+ if (namelen == 5)
{
- return UNION;
+ if (!strncmp (tokstart, "union", 5))
+ {
+ return UNION;
+ }
}
- if (namelen == 4 && !strncmp (tokstart, "enum", 4))
+ if (namelen == 4)
{
- return ENUM;
+ if (!strncmp (tokstart, "enum", 4))
+ {
+ return ENUM;
+ }
+ if (!strncmp (tokstart, "this", 4))
+ {
+ return THIS;
+ }
}
if (namelen == 6 && !strncmp (tokstart, "sizeof", 6))
{
@@ -968,10 +1129,20 @@ length_of_subexp (expr, endpos)
register int args = 0;
register int i;
+ if (endpos < 0)
+ error ("?error in length_of_subexp");
+
i = (int) expr->elts[endpos - 1].opcode;
switch (i)
{
+ /* C++ */
+ case OP_SCOPE:
+ oplen = 4 + ((expr->elts[endpos - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ break;
+
case OP_LONG:
case OP_DOUBLE:
oplen = 4;
@@ -1002,7 +1173,6 @@ length_of_subexp (expr, endpos)
oplen = 3 + ((expr->elts[endpos - 2].longconst
+ sizeof (union exp_element))
/ sizeof (union exp_element));
-
break;
case TERNOP_COND:
@@ -1014,6 +1184,11 @@ length_of_subexp (expr, endpos)
args = 2;
break;
+ /* C++ */
+ case OP_THIS:
+ oplen = 2;
+ break;
+
default:
args = 1 + (i < (int) BINOP_END);
}
@@ -1051,6 +1226,13 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
opcode = inexpr->elts[inend - 1].opcode;
switch (opcode)
{
+ /* C++ */
+ case OP_SCOPE:
+ oplen = 4 + ((inexpr->elts[inend - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ break;
+
case OP_LONG:
case OP_DOUBLE:
oplen = 4;
@@ -1093,6 +1275,11 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
args = 2;
break;
+ /* C++ */
+ case OP_THIS:
+ oplen = 2;
+ break;
+
default:
args = 1 + ((int) opcode < (int) BINOP_END);
}
@@ -1136,10 +1323,12 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
if BLOCK is zero, use the block of the selected stack frame.
Meanwhile, advance *STRINGPTR to point after the expression,
at the first nonwhite character that is not part of the expression
- (possibly a null character). */
+ (possibly a null character).
+
+ If COMMA is nonzero, stop if a comma is reached. */
struct expression *
-parse_c_1 (stringptr, block)
+parse_c_1 (stringptr, block, comma)
char **stringptr;
struct block *block;
{
@@ -1147,6 +1336,8 @@ parse_c_1 (stringptr, block)
lexptr = *stringptr;
+ comma_terminates = comma;
+
if (lexptr == 0 || *lexptr == 0)
error_no_arg ("expression to compute");
@@ -1182,7 +1373,7 @@ parse_c_expression (string)
char *string;
{
register struct expression *exp;
- exp = parse_c_1 (&string, 0);
+ exp = parse_c_1 (&string, 0, 0);
if (*string)
error ("Junk after end of expression.");
return exp;