/* YACC parser for Java expressions, for GDB.
- Copyright (C) 1997.
+ Copyright (C) 1997, 1998, 1999, 2000, 2006, 2007, 2008, 2009
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Parse a Java expression from text in a string,
and return the result as a struct expression pointer.
#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"
+
+#define parse_type builtin_type (parse_gdbarch)
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
#define yylloc java_lloc
#define yyreds java_reds /* With YYDEBUG defined */
#define yytoks java_toks /* With YYDEBUG defined */
+#define yyname java_name /* With YYDEBUG defined */
+#define yyrule java_rule /* With YYDEBUG defined */
#define yylhs java_yylhs
#define yylen java_yylen
#define yydefred java_yydefred
#define yycheck java_yycheck
#ifndef YYDEBUG
-#define YYDEBUG 0 /* Default to no yydebug support */
+#define YYDEBUG 1 /* Default to yydebug support */
#endif
-int
-yyparse PARAMS ((void));
+#define YYFPRINTF parser_fprintf
-static int
-yylex PARAMS ((void));
+int yyparse (void);
-void
-yyerror PARAMS ((char *));
+static int yylex (void);
-static struct type * java_type_from_name PARAMS ((struct stoken));
-static void push_expression_name PARAMS ((struct stoken));
-static void push_fieldnames PARAMS ((struct stoken));
+void yyerror (char *);
-static struct expression *copy_exp PARAMS ((struct expression *, int));
-static void insert_exp PARAMS ((int, struct expression *));
+static struct type *java_type_from_name (struct stoken);
+static void push_expression_name (struct stoken);
+static void push_fieldnames (struct stoken);
+
+static struct expression *copy_exp (struct expression *, int);
+static void insert_exp (int, struct expression *);
%}
%{
/* YYSTYPE gets defined by %union */
-static int
-parse_number PARAMS ((char *, int, int, YYSTYPE *));
+static int parse_number (char *, int, int, YYSTYPE *);
%}
%type <lval> rcurly Dims Dims_opt
%type <tval> ClassOrInterfaceType ClassType /* ReferenceType Type ArrayType */
-%type <tval> IntegralType FloatingPointType NumericType PrimitiveType
+%type <tval> IntegralType FloatingPointType NumericType PrimitiveType ArrayType PrimitiveOrArrayType
%token <typed_val_int> INTEGER_LITERAL
%token <typed_val_float> FLOATING_POINT_LITERAL
%token <opcode> ASSIGN_MODIFY
-%token THIS SUPER NEW
+%token SUPER NEW
%left ','
%right '=' ASSIGN_MODIFY
%%
start : exp1
-/* | type_exp FIXME */
+ | type_exp
+ ;
+
+type_exp: PrimitiveOrArrayType
+ {
+ write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1);
+ write_exp_elt_opcode(OP_TYPE);
+ }
+ ;
+
+PrimitiveOrArrayType:
+ PrimitiveType
+ | ArrayType
;
StringLiteral:
ClassOrInterfaceType
;
-/* UNUSED:
ArrayType:
PrimitiveType Dims
{ $$ = java_array_type ($1, $2); }
| Name Dims
{ $$ = java_array_type (java_type_from_name ($1), $2); }
;
-*/
Name:
IDENTIFIER
PrimaryNoNewArray:
Literal
-| THIS
- { write_exp_elt_opcode (OP_THIS);
- write_exp_elt_opcode (OP_THIS); }
| '(' Expression ')'
| ClassInstanceCreationExpression
| FieldAccess
ClassInstanceCreationExpression:
NEW ClassType '(' ArgumentList_opt ')'
- { error ("FIXME - ClassInstanceCreationExpression"); }
+ { internal_error (__FILE__, __LINE__,
+ _("FIXME - ClassInstanceCreationExpression")); }
;
ArgumentList:
ArrayCreationExpression:
NEW PrimitiveType DimExprs Dims_opt
- { error ("FIXME - ArrayCreatiionExpression"); }
+ { internal_error (__FILE__, __LINE__,
+ _("FIXME - ArrayCreationExpression")); }
| NEW ClassOrInterfaceType DimExprs Dims_opt
- { error ("FIXME - ArrayCreatiionExpression"); }
+ { internal_error (__FILE__, __LINE__,
+ _("FIXME - ArrayCreationExpression")); }
;
DimExprs:
/*| SUPER '.' SimpleName { FIXME } */
;
+FuncStart:
+ Name '('
+ { push_expression_name ($1); }
+;
+
MethodInvocation:
- Name '(' ArgumentList_opt ')'
- { error ("method invocation not implemented"); }
+ FuncStart
+ { start_arglist(); }
+ ArgumentList_opt ')'
+ { write_exp_elt_opcode (OP_FUNCALL);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_FUNCALL); }
| Primary '.' SimpleName '(' ArgumentList_opt ')'
- { error ("method invocation not implemented"); }
+ { error (_("Form of method invocation not implemented")); }
| SUPER '.' SimpleName '(' ArgumentList_opt ')'
- { error ("method invocation not implemented"); }
+ { error (_("Form of method invocation not implemented")); }
;
ArrayAccess:
int i;
int base = expout_ptr - last_exp_size - 3;
if (base < 0 || expout->elts[base+2].opcode != OP_TYPE)
- error ("invalid cast expression");
+ error (_("Invalid cast expression"));
type = expout->elts[base+1].type;
/* Remove the 'Expression' and slide the
UnaryExpressionNotPlusMinus down to replace it. */
/*** Needs some error checking for the float case ***/
static int
-parse_number (p, len, parsed_float, putithere)
- register char *p;
- register int len;
- int parsed_float;
- YYSTYPE *putithere;
+parse_number (char *p, int len, int parsed_float, YYSTYPE *putithere)
{
- register ULONGEST n = 0;
+ ULONGEST n = 0;
ULONGEST limit, limit_div_base;
- register int c;
- register int base = input_radix;
+ int c;
+ int base = input_radix;
struct type *type;
char saved_char = p[len];
p[len] = 0; /* null-terminate the token */
- if (sizeof (putithere->typed_val_float.dval) <= sizeof (float))
- num = sscanf (p, "%g%c", (float *) &putithere->typed_val_float.dval, &c);
- else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double))
- num = sscanf (p, "%lg%c", (double *) &putithere->typed_val_float.dval, &c);
- else
- {
-#ifdef PRINTF_HAS_LONG_DOUBLE
- num = sscanf (p, "%Lg%c", &putithere->typed_val_float.dval, &c);
-#else
- /* Scan it into a double, then assign it to the long double.
- This at least wins with values representable in the range
- of doubles. */
- double temp;
- num = sscanf (p, "%lg%c", &temp, &c);
- putithere->typed_val_float.dval = temp;
-#endif
- }
+ num = sscanf (p, "%" DOUBLEST_SCAN_FORMAT "%c",
+ &putithere->typed_val_float.dval, &c);
p[len] = saved_char; /* restore the input stream */
if (num != 1) /* check scanf found ONLY a float ... */
return ERROR;
c = tolower (p[len - 1]);
if (c == 'f' || c == 'F')
- putithere->typed_val_float.type = builtin_type_float;
+ putithere->typed_val_float.type = parse_type->builtin_float;
else if (isdigit (c) || c == '.' || c == 'd' || c == 'D')
- putithere->typed_val_float.type = builtin_type_double;
+ putithere->typed_val_float.type = parse_type->builtin_double;
else
return ERROR;
return FLOATING_POINT_LITERAL;
-}
+ }
/* Handle base-switching prefixes 0x, 0t, 0d, 0 */
if (p[0] == '0')
}
c = p[len-1];
+ /* A paranoid calculation of (1<<64)-1. */
limit = (ULONGEST)0xffffffff;
+ limit = ((limit << 16) << 16) | limit;
if (c == 'l' || c == 'L')
{
type = java_long_type;
len--;
- /* A paranoid calculation of (1<<64)-1. */
- limit = ((limit << 16) << 16) | limit;
}
else
{
return ERROR;
if (n > limit_div_base
|| (n *= base) > limit - c)
- error ("Numeric constant too large.");
+ error (_("Numeric constant too large"));
n += c;
}
- putithere->typed_val_int.val = n;
- putithere->typed_val_int.type = type;
- return INTEGER_LITERAL;
+ /* If the type is bigger than a 32-bit signed integer can be, implicitly
+ promote to long. Java does not do this, so mark it as builtin_type_uint64
+ rather than java_long_type. 0x80000000 will become -0x80000000 instead
+ of 0x80000000L, because we don't know the sign at this point.
+ */
+ if (type == java_int_type && n > (ULONGEST)0x80000000)
+ type = builtin_type_uint64;
+
+ putithere->typed_val_int.val = n;
+ putithere->typed_val_int.type = type;
+
+ return INTEGER_LITERAL;
}
struct token
/* Read one token, getting characters through lexptr. */
static int
-yylex ()
+yylex (void)
{
int c;
int namelen;
retry:
+ prev_lexptr = lexptr;
+
tokstart = lexptr;
/* See if it is a special token of length 3. */
for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
- if (STREQN (tokstart, tokentab3[i].operator, 3))
+ if (strncmp (tokstart, tokentab3[i].operator, 3) == 0)
{
lexptr += 3;
yylval.opcode = tokentab3[i].opcode;
/* See if it is a special token of length 2. */
for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
- if (STREQN (tokstart, tokentab2[i].operator, 2))
+ if (strncmp (tokstart, tokentab2[i].operator, 2) == 0)
{
lexptr += 2;
yylval.opcode = tokentab2[i].opcode;
if (c == '\\')
c = parse_escape (&lexptr);
else if (c == '\'')
- error ("Empty character constant.");
+ error (_("Empty character constant"));
yylval.typed_val_int.val = c;
- yylval.typed_val_int.type = builtin_type_char;
+ yylval.typed_val_int.type = java_char_type;
c = *lexptr++;
if (c != '\'')
{
lexptr = tokstart + namelen;
if (lexptr[-1] != '\'')
- error ("Unmatched single quote.");
+ error (_("Unmatched single quote"));
namelen -= 2;
tokstart++;
goto tryname;
}
- error ("Invalid character constant.");
+ error (_("Invalid character constant"));
}
return INTEGER_LITERAL;
{
/* It's a number. */
int got_dot = 0, got_e = 0, toktype;
- register char *p = tokstart;
+ char *p = tokstart;
int hex = input_radix > 10;
if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
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;
for (c = tokstart[namelen];
- (c == '_' || c == '$' || (c >= '0' && c <= '9')
- || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');)
+ (c == '_'
+ || c == '$'
+ || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || c == '<');
+ )
{
- if (c == '<')
- {
- int i = namelen;
- while (tokstart[++i] && tokstart[i] != '>');
- if (tokstart[i] == '>')
- namelen = i;
- }
+ if (c == '<')
+ {
+ int i = namelen;
+ while (tokstart[++i] && tokstart[i] != '>');
+ if (tokstart[i] == '>')
+ namelen = i;
+ }
c = tokstart[++namelen];
}
switch (namelen)
{
case 7:
- if (STREQN (tokstart, "boolean", 7))
+ if (strncmp (tokstart, "boolean", 7) == 0)
return BOOLEAN;
break;
case 6:
- if (STREQN (tokstart, "double", 6))
+ if (strncmp (tokstart, "double", 6) == 0)
return DOUBLE;
break;
case 5:
- if (STREQN (tokstart, "short", 5))
+ if (strncmp (tokstart, "short", 5) == 0)
return SHORT;
- if (STREQN (tokstart, "false", 5))
+ if (strncmp (tokstart, "false", 5) == 0)
{
yylval.lval = 0;
return BOOLEAN_LITERAL;
}
- if (STREQN (tokstart, "super", 5))
+ if (strncmp (tokstart, "super", 5) == 0)
return SUPER;
- if (STREQN (tokstart, "float", 5))
+ if (strncmp (tokstart, "float", 5) == 0)
return FLOAT;
break;
case 4:
- if (STREQN (tokstart, "long", 4))
+ if (strncmp (tokstart, "long", 4) == 0)
return LONG;
- if (STREQN (tokstart, "byte", 4))
+ if (strncmp (tokstart, "byte", 4) == 0)
return BYTE;
- if (STREQN (tokstart, "char", 4))
+ if (strncmp (tokstart, "char", 4) == 0)
return CHAR;
- if (STREQN (tokstart, "true", 4))
+ if (strncmp (tokstart, "true", 4) == 0)
{
yylval.lval = 1;
return BOOLEAN_LITERAL;
}
- if (current_language->la_language == language_cplus
- && STREQN (tokstart, "this", 4))
- {
- static const char this_name[] =
- { CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
-
- if (lookup_symbol (this_name, expression_context_block,
- VAR_NAMESPACE, (int *) NULL,
- (struct symtab **) NULL))
- return THIS;
- }
break;
case 3:
- if (STREQN (tokstart, "int", 3))
+ if (strncmp (tokstart, "int", 3) == 0)
return INT;
- if (STREQN (tokstart, "new", 3))
+ if (strncmp (tokstart, "new", 3) == 0)
return NEW;
break;
default:
}
void
-yyerror (msg)
- char *msg;
+yyerror (char *msg)
{
- error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+ if (prev_lexptr)
+ lexptr = prev_lexptr;
+
+ if (msg)
+ error (_("%s: near `%s'"), msg, lexptr);
+ else
+ error (_("error in expression, near `%s'"), lexptr);
}
static struct type *
-java_type_from_name (name)
- struct stoken name;
-
+java_type_from_name (struct stoken name)
{
char *tmp = copy_name (name);
struct type *typ = java_lookup_class (tmp);
if (typ == NULL || TYPE_CODE (typ) != TYPE_CODE_STRUCT)
- error ("No class named %s.", tmp);
+ error (_("No class named `%s'"), tmp);
return typ;
}
Otherwise, return 0. */
static int
-push_variable (name)
- struct stoken name;
-
+push_variable (struct stoken name)
{
char *tmp = copy_name (name);
int is_a_field_of_this = 0;
struct symbol *sym;
- sym = lookup_symbol (tmp, expression_context_block, VAR_NAMESPACE,
- &is_a_field_of_this, (struct symtab **) NULL);
+ sym = lookup_symbol (tmp, expression_context_block, VAR_DOMAIN,
+ &is_a_field_of_this);
if (sym && SYMBOL_CLASS (sym) != LOC_TYPEDEF)
{
if (symbol_read_needs_frame (sym))
}
/* Assuming a reference expression has been pushed, emit the
- STRUCTOP_STRUCT ops to access the field named NAME. If NAME is a
+ STRUCTOP_PTR ops to access the field named NAME. If NAME is a
qualified name (has '.'), generate a field access for each part. */
static void
-push_fieldnames (name)
- struct stoken name;
+push_fieldnames (struct stoken name)
{
int i;
struct stoken token;
{
/* token.ptr is start of current field name. */
token.length = &name.ptr[i] - token.ptr;
- write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_elt_opcode (STRUCTOP_PTR);
write_exp_string (token);
- write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_elt_opcode (STRUCTOP_PTR);
token.ptr += token.length + 1;
}
if (i >= name.length)
Handle a qualified name, where DOT_INDEX is the index of the first '.' */
static void
-push_qualified_expression_name (name, dot_index)
- struct stoken name;
- int dot_index;
+push_qualified_expression_name (struct stoken name, int dot_index)
{
struct stoken token;
char *tmp;
while (dot_index < name.length && name.ptr[dot_index] != '.')
dot_index++;
}
- error ("unknown type `%.*s'", name.length, name.ptr);
+ error (_("unknown type `%.*s'"), name.length, name.ptr);
}
/* Handle Name in an expression (or LHS).
Handle VAR, TYPE, TYPE.FIELD1....FIELDN and VAR.FIELD1....FIELDN. */
static void
-push_expression_name (name)
- struct stoken name;
+push_expression_name (struct stoken name)
{
char *tmp;
struct type *typ;
msymbol = lookup_minimal_symbol (tmp, NULL, NULL);
if (msymbol != NULL)
- {
- write_exp_msymbol (msymbol,
- lookup_function_type (builtin_type_int),
- builtin_type_int);
- }
+ 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.", tmp);
+ error (_("No symbol \"%s\" in current context"), tmp);
}
}
/* Insert the expression NEW into the current expression (expout) at POS. */
static void
-insert_exp (int pos,
- struct expression *new)
+insert_exp (int pos, struct expression *new)
{
int newlen = new->nelts;