/* YACC parser for Pascal expressions, for GDB.
- Copyright (C) 2000, 2006, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 2000, 2006-2012 Free Software Foundation, Inc.
This file is part of GDB.
#define yylval pascal_lval
#define yychar pascal_char
#define yydebug pascal_debug
-#define yypact pascal_pact
-#define yyr1 pascal_r1
-#define yyr2 pascal_r2
-#define yydef pascal_def
-#define yychk pascal_chk
-#define yypgo pascal_pgo
+#define yypact pascal_pact
+#define yyr1 pascal_r1
+#define yyr2 pascal_r2
+#define yydef pascal_def
+#define yychk pascal_chk
+#define yypgo pascal_pgo
#define yyact pascal_act
#define yyexca pascal_exca
#define yyerrflag pascal_errflag
static int yylex (void);
-void
-yyerror (char *);
+void yyerror (char *);
static char * uptok (char *, int);
%}
%{
/* YYSTYPE gets defined by %union */
-static int
-parse_number (char *, int, int, YYSTYPE *);
+static int parse_number (char *, int, int, YYSTYPE *);
static struct type *current_type;
+static struct internalvar *intvar;
static int leftdiv_is_integer;
static void push_current_type (void);
static void pop_current_type (void);
Contexts where this distinction is not important can use the
nonterminal "name", which matches either NAME or TYPENAME. */
-%token <sval> STRING
+%token <sval> STRING
%token <sval> FIELDNAME
+%token <voidval> COMPLETE
%token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
%token <tsym> TYPENAME
%type <sval> name
%%
start : { current_type = NULL;
+ intvar = NULL;
search_field = 0;
leftdiv_is_integer = 0;
}
/* Expressions, not including the comma operator. */
exp : exp '^' %prec UNARY
{ write_exp_elt_opcode (UNOP_IND);
- if (current_type)
+ if (current_type)
current_type = TYPE_TARGET_TYPE (current_type); }
;
exp : '@' exp %prec UNARY
- { write_exp_elt_opcode (UNOP_ADDR);
+ { write_exp_elt_opcode (UNOP_ADDR);
if (current_type)
current_type = TYPE_POINTER_TYPE (current_type); }
;
{ write_exp_elt_opcode (UNOP_PREDECREMENT); }
;
-exp : exp '.' { search_field = 1; }
- FIELDNAME
- /* name */
+
+field_exp : exp '.' %prec UNARY
+ { search_field = 1; }
+ ;
+
+exp : field_exp FIELDNAME
{ write_exp_elt_opcode (STRUCTOP_STRUCT);
- write_exp_string ($4);
+ write_exp_string ($2);
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ search_field = 0;
+ if (current_type)
+ {
+ while (TYPE_CODE (current_type)
+ == TYPE_CODE_PTR)
+ current_type =
+ TYPE_TARGET_TYPE (current_type);
+ current_type = lookup_struct_elt_type (
+ current_type, $2.ptr, 0);
+ }
+ }
+ ;
+
+
+exp : field_exp name
+ { mark_struct_expression ();
write_exp_elt_opcode (STRUCTOP_STRUCT);
- search_field = 0;
+ write_exp_string ($2);
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ search_field = 0;
if (current_type)
- { while (TYPE_CODE (current_type) == TYPE_CODE_PTR)
- current_type = TYPE_TARGET_TYPE (current_type);
+ {
+ while (TYPE_CODE (current_type)
+ == TYPE_CODE_PTR)
+ current_type =
+ TYPE_TARGET_TYPE (current_type);
current_type = lookup_struct_elt_type (
- current_type, $4.ptr, 0); };
- } ;
+ current_type, $2.ptr, 0);
+ }
+ }
+ ;
+
+exp : field_exp COMPLETE
+ { struct stoken s;
+ mark_struct_expression ();
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ s.ptr = "";
+ s.length = 0;
+ write_exp_string (s);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); }
+ ;
+
exp : exp '['
/* We need to save the current_type value. */
- { char *arrayname;
+ { const char *arrayname;
int arrayfieldindex;
arrayfieldindex = is_pascal_string_type (
current_type, NULL, NULL,
- NULL, NULL, &arrayname);
- if (arrayfieldindex)
+ NULL, NULL, &arrayname);
+ if (arrayfieldindex)
{
struct stoken stringsval;
stringsval.ptr = alloca (strlen (arrayname) + 1);
stringsval.length = strlen (arrayname);
strcpy (stringsval.ptr, arrayname);
current_type = TYPE_FIELD_TYPE (current_type,
- arrayfieldindex - 1);
+ arrayfieldindex - 1);
write_exp_elt_opcode (STRUCTOP_STRUCT);
- write_exp_string (stringsval);
+ write_exp_string (stringsval);
write_exp_elt_opcode (STRUCTOP_STRUCT);
}
push_current_type (); }
arglist ')' %prec ARROW
{ write_exp_elt_opcode (OP_FUNCALL);
write_exp_elt_longcst ((LONGEST) end_arglist ());
- write_exp_elt_opcode (OP_FUNCALL);
+ write_exp_elt_opcode (OP_FUNCALL);
pop_current_type ();
if (current_type)
current_type = TYPE_TARGET_TYPE (current_type);
}
write_exp_elt_opcode (UNOP_CAST);
write_exp_elt_type ($1);
- write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_opcode (UNOP_CAST);
current_type = $1; }
;
exp : exp '/' {
if (current_type && is_integral_type (current_type))
leftdiv_is_integer = 1;
- }
+ }
exp
- {
+ {
if (leftdiv_is_integer && current_type
&& is_integral_type (current_type))
{
leftdiv_is_integer = 0;
}
- write_exp_elt_opcode (BINOP_DIV);
+ write_exp_elt_opcode (BINOP_DIV);
}
;
;
exp : exp '=' exp
- { write_exp_elt_opcode (BINOP_EQUAL);
+ { write_exp_elt_opcode (BINOP_EQUAL);
current_type = parse_type->builtin_bool;
}
;
exp : exp NOTEQUAL exp
- { write_exp_elt_opcode (BINOP_NOTEQUAL);
+ { write_exp_elt_opcode (BINOP_NOTEQUAL);
current_type = parse_type->builtin_bool;
}
;
exp : exp LEQ exp
- { write_exp_elt_opcode (BINOP_LEQ);
+ { write_exp_elt_opcode (BINOP_LEQ);
current_type = parse_type->builtin_bool;
}
;
exp : exp GEQ exp
- { write_exp_elt_opcode (BINOP_GEQ);
+ { write_exp_elt_opcode (BINOP_GEQ);
current_type = parse_type->builtin_bool;
}
;
exp : exp '<' exp
- { write_exp_elt_opcode (BINOP_LESS);
+ { write_exp_elt_opcode (BINOP_LESS);
current_type = parse_type->builtin_bool;
}
;
exp : exp '>' exp
- { write_exp_elt_opcode (BINOP_GTR);
+ { write_exp_elt_opcode (BINOP_GTR);
current_type = parse_type->builtin_bool;
}
;
;
exp : VARIABLE
- /* Already written by write_dollar_variable. */
- ;
+ /* Already written by write_dollar_variable.
+ Handle current_type. */
+ { if (intvar) {
+ struct value * val, * mark;
+
+ mark = value_mark ();
+ val = value_of_internalvar (parse_gdbarch,
+ intvar);
+ current_type = value_type (val);
+ value_release_to_mark (mark);
+ }
+ }
+ ;
exp : SIZEOF '(' type ')' %prec UNARY
{ write_exp_elt_opcode (OP_LONG);
exp : SIZEOF '(' exp ')' %prec UNARY
{ write_exp_elt_opcode (UNOP_SIZEOF); }
-
+
exp : STRING
{ /* C strings are converted into array constants with
an explicit null byte added at the end. Thus
/* Object pascal */
exp : THIS
- {
+ {
struct value * this_val;
struct type * this_type;
write_exp_elt_opcode (OP_THIS);
- write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS);
/* We need type of this. */
- this_val = value_of_this (0);
+ this_val = value_of_this_silent (parse_language);
if (this_val)
this_type = value_type (this_val);
else
write_exp_elt_opcode (UNOP_IND);
}
}
-
+
current_type = this_type;
}
;
$$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem),
STATIC_BLOCK);
else
- error ("No file or function \"%s\".",
+ error (_("No file or function \"%s\"."),
copy_name ($1.stoken));
}
}
= lookup_symbol (copy_name ($3), $1,
VAR_DOMAIN, (int *) NULL);
if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
- error ("No function \"%s\" in specified context.",
+ error (_("No function \"%s\" in specified context."),
copy_name ($3));
$$ = SYMBOL_BLOCK_VALUE (tem); }
;
sym = lookup_symbol (copy_name ($3), $1,
VAR_DOMAIN, (int *) NULL);
if (sym == 0)
- error ("No symbol \"%s\" in specified context.",
+ error (_("No symbol \"%s\" in specified context."),
copy_name ($3));
write_exp_elt_opcode (OP_VAR_VALUE);
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.",
+ error (_("`%s' is not defined as an aggregate type."),
TYPE_NAME (type));
write_exp_elt_opcode (OP_SCOPE);
write_exp_msymbol (msymbol);
else if (!have_full_symbols ()
&& !have_partial_symbols ())
- error ("No symbol table is loaded. "
- "Use the \"file\" command.");
+ error (_("No symbol table is loaded. "
+ "Use the \"file\" command."));
else
- error ("No symbol \"%s\" in current context.",
+ error (_("No symbol \"%s\" in current context."),
name);
}
;
write_exp_string ($1.stoken);
write_exp_elt_opcode (STRUCTOP_PTR);
/* We need type of this. */
- this_val = value_of_this (0);
+ this_val = value_of_this_silent (parse_language);
if (this_val)
this_type = value_type (this_val);
else
this_type,
copy_name ($1.stoken), 0);
else
- current_type = NULL;
+ current_type = NULL;
}
else
{
write_exp_msymbol (msymbol);
else if (!have_full_symbols ()
&& !have_partial_symbols ())
- error ("No symbol table is loaded. "
- "Use the \"file\" command.");
+ error (_("No symbol table is loaded. "
+ "Use the \"file\" command."));
else
- error ("No symbol \"%s\" in current context.",
+ error (_("No symbol \"%s\" in current context."),
copy_name ($1.stoken));
}
}
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 && (ULONGEST) prevn >= (ULONGEST) n))
- error ("Numeric constant too large.");
+ error (_("Numeric constant too large."));
}
prevn = n;
}
tpnew->next = tp_top;
tpnew->stored = current_type;
current_type = NULL;
- tp_top = tpnew;
+ tp_top = tpnew;
}
static void
/* Allocate uppercased var: */
/* make an uppercased copy of tokstart. */
-static char * uptok (tokstart, namelen)
- char *tokstart;
- int namelen;
+static char *
+uptok (char *tokstart, int namelen)
{
int i;
char *uptokstart = (char *)malloc(namelen+1);
uptokstart[namelen]='\0';
return uptokstart;
}
-/* Read one token, getting characters through lexptr. */
+/* This is set if the previously-returned token was a structure
+ operator '.'. This is used only when parsing to
+ do field name completion. */
+static int last_was_structop;
+
+/* Read one token, getting characters through lexptr. */
static int
-yylex ()
+yylex (void)
{
int c;
int namelen;
int explen, tempbufindex;
static char *tempbuf;
static int tempbufsize;
+ int saw_structop = last_was_structop;
+ last_was_structop = 0;
retry:
prev_lexptr = lexptr;
switch (c = *tokstart)
{
case 0:
- return 0;
+ if (saw_structop && search_field)
+ return COMPLETE;
+ else
+ return 0;
case ' ':
case '\t':
if (c == '\\')
c = parse_escape (parse_gdbarch, &lexptr);
else if (c == '\'')
- error ("Empty character constant.");
+ error (_("Empty character constant."));
yylval.typed_val_int.val = c;
yylval.typed_val_int.type = parse_type->builtin_char;
{
lexptr = tokstart + namelen;
if (lexptr[-1] != '\'')
- error ("Unmatched single quote.");
+ error (_("Unmatched single quote."));
namelen -= 2;
tokstart++;
uptokstart = uptok(tokstart,namelen);
goto tryname;
}
- error ("Invalid character constant.");
+ error (_("Invalid character constant."));
}
return INT;
case '.':
/* Might be a floating point number. */
if (lexptr[1] < '0' || lexptr[1] > '9')
- goto symbol; /* Nope, must be a symbol. */
+ {
+ if (in_parse_field)
+ last_was_structop = 1;
+ goto symbol; /* Nope, must be a symbol. */
+ }
+
/* FALL THRU into number case. */
case '0':
memcpy (err_copy, tokstart, p - tokstart);
err_copy[p - tokstart] = 0;
- error ("Invalid number \"%s\".", err_copy);
+ error (_("Invalid number \"%s\"."), err_copy);
}
lexptr = p;
return toktype;
} while ((*tokptr != '"') && (*tokptr != '\0'));
if (*tokptr++ != '"')
{
- error ("Unterminated string in expression.");
+ error (_("Unterminated string in expression."));
}
tempbuf[tempbufindex] = '\0'; /* See note above. */
yylval.sval.ptr = tempbuf;
if (!(c == '_' || c == '$'
|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
/* We must have come across a bad character (e.g. ';'). */
- error ("Invalid character '%c' in expression.", c);
+ error (_("Invalid character '%c' in expression."), c);
/* It's a name. See how long it is. */
namelen = 0;
if (*tokstart == '$')
{
+ char c;
/* $ is the normal prefix for pascal hexadecimal values
but this conflicts with the GDB use for debugger variables
so in expression to enter hexadecimal values
we still need to use C syntax with 0xff */
write_dollar_variable (yylval.sval);
+ c = tokstart[namelen];
+ tokstart[namelen] = 0;
+ intvar = lookup_only_internalvar (++tokstart);
+ --tokstart;
+ tokstart[namelen] = c;
free (uptokstart);
return VARIABLE;
}
if (search_field && current_type)
is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL);
- if (is_a_field)
+ if (is_a_field || in_parse_field)
sym = NULL;
else
sym = lookup_symbol (tmp, expression_context_block,
}
if (search_field && current_type)
is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL);
- if (is_a_field)
+ if (is_a_field || in_parse_field)
sym = NULL;
else
sym = lookup_symbol (tmp, expression_context_block,
}
if (search_field && current_type)
is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL);
- if (is_a_field)
+ if (is_a_field || in_parse_field)
sym = NULL;
else
sym = lookup_symbol (tmp, expression_context_block,
tempbuf = (char *) realloc (tempbuf, namelen + 1);
strncpy (tempbuf, tokstart, namelen); tempbuf [namelen] = 0;
yylval.sval.ptr = tempbuf;
- yylval.sval.length = namelen;
+ yylval.sval.length = namelen;
free (uptokstart);
return FIELDNAME;
- }
+ }
/* Call lookup_symtab, not lookup_partial_symtab, in case there are
no psymtabs (coff, xcoff, or some future change to blow away the
psymtabs once once symbols are read). */
}
void
-yyerror (msg)
- char *msg;
+yyerror (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 ? msg : "error"), lexptr);
}