diff options
Diffstat (limited to 'gdb/jv-exp.y')
-rw-r--r-- | gdb/jv-exp.y | 1434 |
1 files changed, 0 insertions, 1434 deletions
diff --git a/gdb/jv-exp.y b/gdb/jv-exp.y deleted file mode 100644 index 79b8127..0000000 --- a/gdb/jv-exp.y +++ /dev/null @@ -1,1434 +0,0 @@ -/* YACC parser for Java expressions, for GDB. - Copyright (C) 1997-2016 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -/* Parse a Java expression from text in a string, - and return the result as a struct expression pointer. - That structure contains arithmetic operations in reverse polish, - with constants represented by operations that are followed by special data. - See expression.h for the details of the format. - What is important here is that it can be built up sequentially - during the process of parsing; the lower levels of the tree always - come first in the result. Well, almost always; see ArrayAccess. - - Note that malloc's and realloc's in this file are transformed to - xmalloc and xrealloc respectively by the same sed command in the - makefile that remaps any other malloc/realloc inserted by the parser - generator. Doing this with #defines and trying to control the interaction - with include files (<malloc.h> and <stdlib.h> for example) just became - too messy, particularly when such includes can be inserted at random - times by the parser generator. */ - -%{ - -#include "defs.h" -#include <ctype.h> -#include "expression.h" -#include "value.h" -#include "parser-defs.h" -#include "language.h" -#include "jv-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 "completer.h" - -#define parse_type(ps) builtin_type (parse_gdbarch (ps)) -#define parse_java_type(ps) builtin_java_type (parse_gdbarch (ps)) - -/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, - etc). */ -#define GDB_YY_REMAP_PREFIX java_ -#include "yy-remap.h" - -/* The state of the parser, used internally when we are parsing the - expression. */ - -static struct parser_state *pstate = NULL; - -int yyparse (void); - -static int yylex (void); - -void yyerror (char *); - -static struct type *java_type_from_name (struct stoken); -static void push_expression_name (struct parser_state *, struct stoken); -static void push_fieldnames (struct parser_state *, struct stoken); - -static struct expression *copy_exp (struct expression *, int); -static void insert_exp (struct parser_state *, int, struct expression *); - -%} - -/* Although the yacc "value" of an expression is not used, - since the result is stored in the structure being created, - other node types do have values. */ - -%union - { - LONGEST lval; - struct { - LONGEST val; - struct type *type; - } typed_val_int; - struct { - DOUBLEST dval; - struct type *type; - } typed_val_float; - struct symbol *sym; - struct type *tval; - struct stoken sval; - struct ttype tsym; - struct symtoken ssym; - struct block *bval; - enum exp_opcode opcode; - struct internalvar *ivar; - int *ivec; - } - -%{ -/* YYSTYPE gets defined by %union */ -static int parse_number (struct parser_state *, const char *, int, - int, YYSTYPE *); -%} - -%type <lval> rcurly Dims Dims_opt -%type <tval> ClassOrInterfaceType ClassType /* ReferenceType Type ArrayType */ -%type <tval> IntegralType FloatingPointType NumericType PrimitiveType ArrayType PrimitiveOrArrayType - -%token <typed_val_int> INTEGER_LITERAL -%token <typed_val_float> FLOATING_POINT_LITERAL - -%token <sval> IDENTIFIER -%token <sval> STRING_LITERAL -%token <lval> BOOLEAN_LITERAL -%token <tsym> TYPENAME -%type <sval> Name SimpleName QualifiedName ForcedName - -/* A NAME_OR_INT is a symbol which is not known in the symbol table, - but which would parse as a valid number in the current input radix. - E.g. "c" when input_radix==16. Depending on the parse, it will be - turned into a name or into a number. */ - -%token <sval> NAME_OR_INT - -%token ERROR - -/* Special type cases, put in to allow the parser to distinguish different - legal basetypes. */ -%token LONG SHORT BYTE INT CHAR BOOLEAN DOUBLE FLOAT - -%token VARIABLE - -%token <opcode> ASSIGN_MODIFY - -%token SUPER NEW - -%left ',' -%right '=' ASSIGN_MODIFY -%right '?' -%left OROR -%left ANDAND -%left '|' -%left '^' -%left '&' -%left EQUAL NOTEQUAL -%left '<' '>' LEQ GEQ -%left LSH RSH -%left '+' '-' -%left '*' '/' '%' -%right INCREMENT DECREMENT -%right '.' '[' '(' - - -%% - -start : exp1 - | type_exp - ; - -type_exp: PrimitiveOrArrayType - { - write_exp_elt_opcode (pstate, OP_TYPE); - write_exp_elt_type (pstate, $1); - write_exp_elt_opcode (pstate, OP_TYPE); - } - ; - -PrimitiveOrArrayType: - PrimitiveType - | ArrayType - ; - -StringLiteral: - STRING_LITERAL - { - write_exp_elt_opcode (pstate, OP_STRING); - write_exp_string (pstate, $1); - write_exp_elt_opcode (pstate, OP_STRING); - } -; - -Literal: - INTEGER_LITERAL - { write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, $1.type); - write_exp_elt_longcst (pstate, (LONGEST)($1.val)); - write_exp_elt_opcode (pstate, OP_LONG); } -| NAME_OR_INT - { YYSTYPE val; - parse_number (pstate, $1.ptr, $1.length, 0, &val); - write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, val.typed_val_int.type); - write_exp_elt_longcst (pstate, - (LONGEST) val.typed_val_int.val); - write_exp_elt_opcode (pstate, OP_LONG); - } -| FLOATING_POINT_LITERAL - { write_exp_elt_opcode (pstate, OP_DOUBLE); - write_exp_elt_type (pstate, $1.type); - write_exp_elt_dblcst (pstate, $1.dval); - write_exp_elt_opcode (pstate, OP_DOUBLE); } -| BOOLEAN_LITERAL - { write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, - parse_java_type (pstate)->builtin_boolean); - write_exp_elt_longcst (pstate, (LONGEST)$1); - write_exp_elt_opcode (pstate, OP_LONG); } -| StringLiteral - ; - -/* UNUSED: -Type: - PrimitiveType -| ReferenceType -; -*/ - -PrimitiveType: - NumericType -| BOOLEAN - { $$ = parse_java_type (pstate)->builtin_boolean; } -; - -NumericType: - IntegralType -| FloatingPointType -; - -IntegralType: - BYTE - { $$ = parse_java_type (pstate)->builtin_byte; } -| SHORT - { $$ = parse_java_type (pstate)->builtin_short; } -| INT - { $$ = parse_java_type (pstate)->builtin_int; } -| LONG - { $$ = parse_java_type (pstate)->builtin_long; } -| CHAR - { $$ = parse_java_type (pstate)->builtin_char; } -; - -FloatingPointType: - FLOAT - { $$ = parse_java_type (pstate)->builtin_float; } -| DOUBLE - { $$ = parse_java_type (pstate)->builtin_double; } -; - -/* UNUSED: -ReferenceType: - ClassOrInterfaceType -| ArrayType -; -*/ - -ClassOrInterfaceType: - Name - { $$ = java_type_from_name ($1); } -; - -ClassType: - ClassOrInterfaceType -; - -ArrayType: - PrimitiveType Dims - { $$ = java_array_type ($1, $2); } -| Name Dims - { $$ = java_array_type (java_type_from_name ($1), $2); } -; - -Name: - IDENTIFIER -| QualifiedName -; - -ForcedName: - SimpleName -| QualifiedName -; - -SimpleName: - IDENTIFIER -| NAME_OR_INT -; - -QualifiedName: - Name '.' SimpleName - { $$.length = $1.length + $3.length + 1; - if ($1.ptr + $1.length + 1 == $3.ptr - && $1.ptr[$1.length] == '.') - $$.ptr = $1.ptr; /* Optimization. */ - else - { - char *buf; - - buf = (char *) malloc ($$.length + 1); - make_cleanup (free, buf); - sprintf (buf, "%.*s.%.*s", - $1.length, $1.ptr, $3.length, $3.ptr); - $$.ptr = buf; - } } -; - -/* -type_exp: type - { write_exp_elt_opcode(OP_TYPE); - write_exp_elt_type($1); - write_exp_elt_opcode(OP_TYPE);} - ; - */ - -/* Expressions, including the comma operator. */ -exp1 : Expression - | exp1 ',' Expression - { write_exp_elt_opcode (pstate, BINOP_COMMA); } - ; - -Primary: - PrimaryNoNewArray -| ArrayCreationExpression -; - -PrimaryNoNewArray: - Literal -| '(' Expression ')' -| ClassInstanceCreationExpression -| FieldAccess -| MethodInvocation -| ArrayAccess -| lcurly ArgumentList rcurly - { write_exp_elt_opcode (pstate, OP_ARRAY); - write_exp_elt_longcst (pstate, (LONGEST) 0); - write_exp_elt_longcst (pstate, (LONGEST) $3); - write_exp_elt_opcode (pstate, OP_ARRAY); } -; - -lcurly: - '{' - { start_arglist (); } -; - -rcurly: - '}' - { $$ = end_arglist () - 1; } -; - -ClassInstanceCreationExpression: - NEW ClassType '(' ArgumentList_opt ')' - { internal_error (__FILE__, __LINE__, - _("FIXME - ClassInstanceCreationExpression")); } -; - -ArgumentList: - Expression - { arglist_len = 1; } -| ArgumentList ',' Expression - { arglist_len++; } -; - -ArgumentList_opt: - /* EMPTY */ - { arglist_len = 0; } -| ArgumentList -; - -ArrayCreationExpression: - NEW PrimitiveType DimExprs Dims_opt - { internal_error (__FILE__, __LINE__, - _("FIXME - ArrayCreationExpression")); } -| NEW ClassOrInterfaceType DimExprs Dims_opt - { internal_error (__FILE__, __LINE__, - _("FIXME - ArrayCreationExpression")); } -; - -DimExprs: - DimExpr -| DimExprs DimExpr -; - -DimExpr: - '[' Expression ']' -; - -Dims: - '[' ']' - { $$ = 1; } -| Dims '[' ']' - { $$ = $1 + 1; } -; - -Dims_opt: - Dims -| /* EMPTY */ - { $$ = 0; } -; - -FieldAccess: - Primary '.' SimpleName - { push_fieldnames (pstate, $3); } -| VARIABLE '.' SimpleName - { push_fieldnames (pstate, $3); } -/*| SUPER '.' SimpleName { FIXME } */ -; - -FuncStart: - Name '(' - { push_expression_name (pstate, $1); } -; - -MethodInvocation: - FuncStart - { start_arglist(); } - ArgumentList_opt ')' - { write_exp_elt_opcode (pstate, OP_FUNCALL); - write_exp_elt_longcst (pstate, (LONGEST) end_arglist ()); - write_exp_elt_opcode (pstate, OP_FUNCALL); } -| Primary '.' SimpleName '(' ArgumentList_opt ')' - { error (_("Form of method invocation not implemented")); } -| SUPER '.' SimpleName '(' ArgumentList_opt ')' - { error (_("Form of method invocation not implemented")); } -; - -ArrayAccess: - Name '[' Expression ']' - { - /* Emit code for the Name now, then exchange it in the - expout array with the Expression's code. We could - introduce a OP_SWAP code or a reversed version of - BINOP_SUBSCRIPT, but that makes the rest of GDB pay - for our parsing kludges. */ - struct expression *name_expr; - - push_expression_name (pstate, $1); - name_expr = copy_exp (pstate->expout, pstate->expout_ptr); - pstate->expout_ptr -= name_expr->nelts; - insert_exp (pstate, - pstate->expout_ptr - - length_of_subexp (pstate->expout, - pstate->expout_ptr), - name_expr); - free (name_expr); - write_exp_elt_opcode (pstate, BINOP_SUBSCRIPT); - } -| VARIABLE '[' Expression ']' - { write_exp_elt_opcode (pstate, BINOP_SUBSCRIPT); } -| PrimaryNoNewArray '[' Expression ']' - { write_exp_elt_opcode (pstate, BINOP_SUBSCRIPT); } -; - -PostfixExpression: - Primary -| Name - { push_expression_name (pstate, $1); } -| VARIABLE - /* Already written by write_dollar_variable. */ -| PostIncrementExpression -| PostDecrementExpression -; - -PostIncrementExpression: - PostfixExpression INCREMENT - { write_exp_elt_opcode (pstate, UNOP_POSTINCREMENT); } -; - -PostDecrementExpression: - PostfixExpression DECREMENT - { write_exp_elt_opcode (pstate, UNOP_POSTDECREMENT); } -; - -UnaryExpression: - PreIncrementExpression -| PreDecrementExpression -| '+' UnaryExpression -| '-' UnaryExpression - { write_exp_elt_opcode (pstate, UNOP_NEG); } -| '*' UnaryExpression - { write_exp_elt_opcode (pstate, - UNOP_IND); } /*FIXME not in Java */ -| UnaryExpressionNotPlusMinus -; - -PreIncrementExpression: - INCREMENT UnaryExpression - { write_exp_elt_opcode (pstate, UNOP_PREINCREMENT); } -; - -PreDecrementExpression: - DECREMENT UnaryExpression - { write_exp_elt_opcode (pstate, UNOP_PREDECREMENT); } -; - -UnaryExpressionNotPlusMinus: - PostfixExpression -| '~' UnaryExpression - { write_exp_elt_opcode (pstate, UNOP_COMPLEMENT); } -| '!' UnaryExpression - { write_exp_elt_opcode (pstate, UNOP_LOGICAL_NOT); } -| CastExpression - ; - -CastExpression: - '(' PrimitiveType Dims_opt ')' UnaryExpression - { write_exp_elt_opcode (pstate, UNOP_CAST); - write_exp_elt_type (pstate, java_array_type ($2, $3)); - write_exp_elt_opcode (pstate, UNOP_CAST); } -| '(' Expression ')' UnaryExpressionNotPlusMinus - { - int last_exp_size = length_of_subexp (pstate->expout, - pstate->expout_ptr); - struct type *type; - int i; - int base = pstate->expout_ptr - last_exp_size - 3; - - if (base < 0 - || pstate->expout->elts[base+2].opcode != OP_TYPE) - error (_("Invalid cast expression")); - type = pstate->expout->elts[base+1].type; - /* Remove the 'Expression' and slide the - UnaryExpressionNotPlusMinus down to replace it. */ - for (i = 0; i < last_exp_size; i++) - pstate->expout->elts[base + i] - = pstate->expout->elts[base + i + 3]; - pstate->expout_ptr -= 3; - if (TYPE_CODE (type) == TYPE_CODE_STRUCT) - type = lookup_pointer_type (type); - write_exp_elt_opcode (pstate, UNOP_CAST); - write_exp_elt_type (pstate, type); - write_exp_elt_opcode (pstate, UNOP_CAST); - } -| '(' Name Dims ')' UnaryExpressionNotPlusMinus - { write_exp_elt_opcode (pstate, UNOP_CAST); - write_exp_elt_type (pstate, - java_array_type (java_type_from_name - ($2), $3)); - write_exp_elt_opcode (pstate, UNOP_CAST); } -; - - -MultiplicativeExpression: - UnaryExpression -| MultiplicativeExpression '*' UnaryExpression - { write_exp_elt_opcode (pstate, BINOP_MUL); } -| MultiplicativeExpression '/' UnaryExpression - { write_exp_elt_opcode (pstate, BINOP_DIV); } -| MultiplicativeExpression '%' UnaryExpression - { write_exp_elt_opcode (pstate, BINOP_REM); } -; - -AdditiveExpression: - MultiplicativeExpression -| AdditiveExpression '+' MultiplicativeExpression - { write_exp_elt_opcode (pstate, BINOP_ADD); } -| AdditiveExpression '-' MultiplicativeExpression - { write_exp_elt_opcode (pstate, BINOP_SUB); } -; - -ShiftExpression: - AdditiveExpression -| ShiftExpression LSH AdditiveExpression - { write_exp_elt_opcode (pstate, BINOP_LSH); } -| ShiftExpression RSH AdditiveExpression - { write_exp_elt_opcode (pstate, BINOP_RSH); } -/* | ShiftExpression >>> AdditiveExpression { FIXME } */ -; - -RelationalExpression: - ShiftExpression -| RelationalExpression '<' ShiftExpression - { write_exp_elt_opcode (pstate, BINOP_LESS); } -| RelationalExpression '>' ShiftExpression - { write_exp_elt_opcode (pstate, BINOP_GTR); } -| RelationalExpression LEQ ShiftExpression - { write_exp_elt_opcode (pstate, BINOP_LEQ); } -| RelationalExpression GEQ ShiftExpression - { write_exp_elt_opcode (pstate, BINOP_GEQ); } -/* | RelationalExpresion INSTANCEOF ReferenceType { FIXME } */ -; - -EqualityExpression: - RelationalExpression -| EqualityExpression EQUAL RelationalExpression - { write_exp_elt_opcode (pstate, BINOP_EQUAL); } -| EqualityExpression NOTEQUAL RelationalExpression - { write_exp_elt_opcode (pstate, BINOP_NOTEQUAL); } -; - -AndExpression: - EqualityExpression -| AndExpression '&' EqualityExpression - { write_exp_elt_opcode (pstate, BINOP_BITWISE_AND); } -; - -ExclusiveOrExpression: - AndExpression -| ExclusiveOrExpression '^' AndExpression - { write_exp_elt_opcode (pstate, BINOP_BITWISE_XOR); } -; -InclusiveOrExpression: - ExclusiveOrExpression -| InclusiveOrExpression '|' ExclusiveOrExpression - { write_exp_elt_opcode (pstate, BINOP_BITWISE_IOR); } -; - -ConditionalAndExpression: - InclusiveOrExpression -| ConditionalAndExpression ANDAND InclusiveOrExpression - { write_exp_elt_opcode (pstate, BINOP_LOGICAL_AND); } -; - -ConditionalOrExpression: - ConditionalAndExpression -| ConditionalOrExpression OROR ConditionalAndExpression - { write_exp_elt_opcode (pstate, BINOP_LOGICAL_OR); } -; - -ConditionalExpression: - ConditionalOrExpression -| ConditionalOrExpression '?' Expression ':' ConditionalExpression - { write_exp_elt_opcode (pstate, TERNOP_COND); } -; - -AssignmentExpression: - ConditionalExpression -| Assignment -; - -Assignment: - LeftHandSide '=' ConditionalExpression - { write_exp_elt_opcode (pstate, BINOP_ASSIGN); } -| LeftHandSide ASSIGN_MODIFY ConditionalExpression - { write_exp_elt_opcode (pstate, BINOP_ASSIGN_MODIFY); - write_exp_elt_opcode (pstate, $2); - write_exp_elt_opcode (pstate, BINOP_ASSIGN_MODIFY); } -; - -LeftHandSide: - ForcedName - { push_expression_name (pstate, $1); } -| VARIABLE - /* Already written by write_dollar_variable. */ -| FieldAccess -| ArrayAccess -; - - -Expression: - AssignmentExpression -; - -%% -/* 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. */ - -/*** Needs some error checking for the float case ***/ - -static int -parse_number (struct parser_state *par_state, - const char *p, int len, int parsed_float, YYSTYPE *putithere) -{ - ULONGEST n = 0; - ULONGEST limit, limit_div_base; - - int c; - int base = input_radix; - - struct type *type; - - if (parsed_float) - { - const char *suffix; - int suffix_len; - - if (! parse_float (p, len, &putithere->typed_val_float.dval, &suffix)) - return ERROR; - - suffix_len = p + len - suffix; - - if (suffix_len == 0) - putithere->typed_val_float.type - = parse_type (par_state)->builtin_double; - else if (suffix_len == 1) - { - /* See if it has `f' or `d' suffix (float or double). */ - if (tolower (*suffix) == 'f') - putithere->typed_val_float.type = - parse_type (par_state)->builtin_float; - else if (tolower (*suffix) == 'd') - putithere->typed_val_float.type = - parse_type (par_state)->builtin_double; - else - return ERROR; - } - else - return ERROR; - - return FLOATING_POINT_LITERAL; - } - - /* Handle base-switching prefixes 0x, 0t, 0d, 0 */ - if (p[0] == '0') - switch (p[1]) - { - case 'x': - case 'X': - if (len >= 3) - { - p += 2; - base = 16; - len -= 2; - } - break; - - case 't': - case 'T': - case 'd': - case 'D': - if (len >= 3) - { - p += 2; - base = 10; - len -= 2; - } - break; - - default: - base = 8; - break; - } - - 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 = parse_java_type (par_state)->builtin_long; - len--; - } - else - { - type = parse_java_type (par_state)->builtin_int; - } - limit_div_base = limit / (ULONGEST) base; - - while (--len >= 0) - { - c = *p++; - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - return ERROR; /* Char not a digit */ - if (c >= base) - return ERROR; - if (n > limit_div_base - || (n *= base) > limit - c) - error (_("Numeric constant too large")); - n += c; - } - - /* 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 - parse_type (par_state)->builtin_uint64 rather than - parse_java_type (par_state)->builtin_long. - 0x80000000 will become -0x80000000 instead of 0x80000000L, because we - don't know the sign at this point. */ - if (type == parse_java_type (par_state)->builtin_int - && n > (ULONGEST)0x80000000) - type = parse_type (par_state)->builtin_uint64; - - putithere->typed_val_int.val = n; - putithere->typed_val_int.type = type; - - return INTEGER_LITERAL; -} - -struct token -{ - char *oper; - int token; - enum exp_opcode opcode; -}; - -static const struct token tokentab3[] = - { - {">>=", ASSIGN_MODIFY, BINOP_RSH}, - {"<<=", ASSIGN_MODIFY, BINOP_LSH} - }; - -static const struct token tokentab2[] = - { - {"+=", ASSIGN_MODIFY, BINOP_ADD}, - {"-=", ASSIGN_MODIFY, BINOP_SUB}, - {"*=", ASSIGN_MODIFY, BINOP_MUL}, - {"/=", ASSIGN_MODIFY, BINOP_DIV}, - {"%=", ASSIGN_MODIFY, BINOP_REM}, - {"|=", ASSIGN_MODIFY, BINOP_BITWISE_IOR}, - {"&=", ASSIGN_MODIFY, BINOP_BITWISE_AND}, - {"^=", ASSIGN_MODIFY, BINOP_BITWISE_XOR}, - {"++", INCREMENT, BINOP_END}, - {"--", DECREMENT, BINOP_END}, - {"&&", ANDAND, BINOP_END}, - {"||", OROR, BINOP_END}, - {"<<", LSH, BINOP_END}, - {">>", RSH, BINOP_END}, - {"==", EQUAL, BINOP_END}, - {"!=", NOTEQUAL, BINOP_END}, - {"<=", LEQ, BINOP_END}, - {">=", GEQ, BINOP_END} - }; - -/* Read one token, getting characters through lexptr. */ - -static int -yylex (void) -{ - int c; - int namelen; - unsigned int i; - const char *tokstart; - const char *tokptr; - int tempbufindex; - static char *tempbuf; - static int tempbufsize; - - 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 (strncmp (tokstart, tokentab3[i].oper, 3) == 0) - { - lexptr += 3; - yylval.opcode = tokentab3[i].opcode; - return tokentab3[i].token; - } - - /* See if it is a special token of length 2. */ - for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++) - if (strncmp (tokstart, tokentab2[i].oper, 2) == 0) - { - lexptr += 2; - yylval.opcode = tokentab2[i].opcode; - return tokentab2[i].token; - } - - switch (c = *tokstart) - { - case 0: - return 0; - - case ' ': - case '\t': - case '\n': - lexptr++; - goto retry; - - case '\'': - /* We either have a character constant ('0' or '\177' for example) - or we have a quoted symbol reference ('foo(int,int)' in C++ - for example). */ - lexptr++; - c = *lexptr++; - if (c == '\\') - c = parse_escape (parse_gdbarch (pstate), &lexptr); - else if (c == '\'') - error (_("Empty character constant")); - - yylval.typed_val_int.val = c; - yylval.typed_val_int.type = parse_java_type (pstate)->builtin_char; - - c = *lexptr++; - if (c != '\'') - { - namelen = skip_quoted (tokstart) - tokstart; - if (namelen > 2) - { - lexptr = tokstart + namelen; - if (lexptr[-1] != '\'') - error (_("Unmatched single quote")); - namelen -= 2; - tokstart++; - goto tryname; - } - error (_("Invalid character constant")); - } - return INTEGER_LITERAL; - - 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 '.': - /* Might be a floating point number. */ - if (lexptr[1] < '0' || lexptr[1] > '9') - goto symbol; /* Nope, must be a symbol. */ - /* FALL THRU into number case. */ - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - /* It's a number. */ - int got_dot = 0, got_e = 0, toktype; - const char *p = tokstart; - int hex = input_radix > 10; - - if (c == '0' && (p[1] == 'x' || p[1] == 'X')) - { - p += 2; - hex = 1; - } - else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D')) - { - p += 2; - hex = 0; - } - - for (;; ++p) - { - /* This test includes !hex because 'e' is a valid hex digit - and thus does not indicate a floating point number when - the radix is hex. */ - if (!hex && !got_e && (*p == 'e' || *p == 'E')) - got_dot = got_e = 1; - /* This test does not include !hex, because a '.' always indicates - a decimal floating point number regardless of the radix. */ - else if (!got_dot && *p == '.') - got_dot = 1; - else if (got_e && (p[-1] == 'e' || p[-1] == 'E') - && (*p == '-' || *p == '+')) - /* This is the sign of the exponent, not the end of the - number. */ - continue; - /* We will take any letters or digits. parse_number will - complain if past the radix, or if L or U are not final. */ - else if ((*p < '0' || *p > '9') - && ((*p < 'a' || *p > 'z') - && (*p < 'A' || *p > 'Z'))) - break; - } - toktype = parse_number (pstate, tokstart, p - tokstart, - got_dot|got_e, &yylval); - if (toktype == ERROR) - { - char *err_copy = (char *) alloca (p - tokstart + 1); - - memcpy (err_copy, tokstart, p - tokstart); - err_copy[p - tokstart] = 0; - error (_("Invalid number \"%s\""), err_copy); - } - lexptr = p; - return toktype; - } - - case '+': - case '-': - case '*': - case '/': - case '%': - case '|': - case '&': - case '^': - case '~': - case '!': - case '<': - case '>': - case '[': - case ']': - case '?': - case ':': - case '=': - case '{': - case '}': - symbol: - lexptr++; - return c; - - case '"': - - /* Build the gdb internal form of the input string in tempbuf, - translating any standard C escape forms seen. Note that the - buffer is null byte terminated *only* for the convenience of - debugging gdb itself and printing the buffer contents when - the buffer contains no embedded nulls. Gdb does not depend - upon the buffer being null byte terminated, it uses the length - string instead. This allows gdb to handle C strings (as well - as strings in other languages) with embedded null bytes */ - - tokptr = ++tokstart; - tempbufindex = 0; - - do { - /* Grow the static temp buffer if necessary, including allocating - the first one on demand. */ - if (tempbufindex + 1 >= tempbufsize) - { - tempbuf = (char *) realloc (tempbuf, tempbufsize += 64); - } - switch (*tokptr) - { - case '\0': - case '"': - /* Do nothing, loop will terminate. */ - break; - case '\\': - tokptr++; - c = parse_escape (parse_gdbarch (pstate), &tokptr); - if (c == -1) - { - continue; - } - tempbuf[tempbufindex++] = c; - break; - default: - tempbuf[tempbufindex++] = *tokptr++; - break; - } - } while ((*tokptr != '"') && (*tokptr != '\0')); - if (*tokptr++ != '"') - { - error (_("Unterminated string in expression")); - } - tempbuf[tempbufindex] = '\0'; /* See note above */ - yylval.sval.ptr = tempbuf; - yylval.sval.length = tempbufindex; - lexptr = tokptr; - return (STRING_LITERAL); - } - - 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); - - /* 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 == '<'); - ) - { - 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. */ - if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f') - { - return 0; - } - - lexptr += namelen; - - tryname: - - /* Catch specific keywords. Should be done with a data structure. */ - switch (namelen) - { - case 7: - if (strncmp (tokstart, "boolean", 7) == 0) - return BOOLEAN; - break; - case 6: - if (strncmp (tokstart, "double", 6) == 0) - return DOUBLE; - break; - case 5: - if (strncmp (tokstart, "short", 5) == 0) - return SHORT; - if (strncmp (tokstart, "false", 5) == 0) - { - yylval.lval = 0; - return BOOLEAN_LITERAL; - } - if (strncmp (tokstart, "super", 5) == 0) - return SUPER; - if (strncmp (tokstart, "float", 5) == 0) - return FLOAT; - break; - case 4: - if (strncmp (tokstart, "long", 4) == 0) - return LONG; - if (strncmp (tokstart, "byte", 4) == 0) - return BYTE; - if (strncmp (tokstart, "char", 4) == 0) - return CHAR; - if (strncmp (tokstart, "true", 4) == 0) - { - yylval.lval = 1; - return BOOLEAN_LITERAL; - } - break; - case 3: - if (strncmp (tokstart, "int", 3) == 0) - return INT; - if (strncmp (tokstart, "new", 3) == 0) - return NEW; - break; - default: - break; - } - - yylval.sval.ptr = tokstart; - yylval.sval.length = namelen; - - if (*tokstart == '$') - { - write_dollar_variable (pstate, yylval.sval); - return VARIABLE; - } - - /* Input names that aren't symbols but ARE valid hex numbers, - when the input radix permits them, can be names or numbers - depending on the parse. Note we support radixes > 16 here. */ - if (((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) || - (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10))) - { - YYSTYPE newlval; /* Its value is ignored. */ - int hextype = parse_number (pstate, tokstart, namelen, 0, &newlval); - if (hextype == INTEGER_LITERAL) - return NAME_OR_INT; - } - return IDENTIFIER; -} - -int -java_parse (struct parser_state *par_state) -{ - int result; - struct cleanup *c = make_cleanup_clear_parser_state (&pstate); - - /* Setting up the parser state. */ - gdb_assert (par_state != NULL); - pstate = par_state; - - result = yyparse (); - do_cleanups (c); - - return result; -} - -void -yyerror (char *msg) -{ - 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 (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); - return typ; -} - -/* If NAME is a valid variable name in this scope, push it and return 1. - Otherwise, return 0. */ - -static int -push_variable (struct parser_state *par_state, struct stoken name) -{ - char *tmp = copy_name (name); - struct field_of_this_result is_a_field_of_this; - struct block_symbol sym; - - sym = lookup_symbol (tmp, expression_context_block, VAR_DOMAIN, - &is_a_field_of_this); - if (sym.symbol && SYMBOL_CLASS (sym.symbol) != LOC_TYPEDEF) - { - if (symbol_read_needs_frame (sym.symbol)) - { - if (innermost_block == 0 || - contained_in (sym.block, innermost_block)) - innermost_block = sym.block; - } - - write_exp_elt_opcode (par_state, OP_VAR_VALUE); - write_exp_elt_block (par_state, sym.block); - write_exp_elt_sym (par_state, sym.symbol); - write_exp_elt_opcode (par_state, OP_VAR_VALUE); - return 1; - } - if (is_a_field_of_this.type != NULL) - { - /* it hangs off of `this'. Must not inadvertently convert from a - method call to data ref. */ - if (innermost_block == 0 || - contained_in (sym.block, innermost_block)) - innermost_block = sym.block; - write_exp_elt_opcode (par_state, OP_THIS); - write_exp_elt_opcode (par_state, OP_THIS); - write_exp_elt_opcode (par_state, STRUCTOP_PTR); - write_exp_string (par_state, name); - write_exp_elt_opcode (par_state, STRUCTOP_PTR); - return 1; - } - return 0; -} - -/* Assuming a reference expression has been pushed, emit the - 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 (struct parser_state *par_state, struct stoken name) -{ - int i; - struct stoken token; - token.ptr = name.ptr; - for (i = 0; ; i++) - { - if (i == name.length || name.ptr[i] == '.') - { - /* token.ptr is start of current field name. */ - token.length = &name.ptr[i] - token.ptr; - write_exp_elt_opcode (par_state, STRUCTOP_PTR); - write_exp_string (par_state, token); - write_exp_elt_opcode (par_state, STRUCTOP_PTR); - token.ptr += token.length + 1; - } - if (i >= name.length) - break; - } -} - -/* Helper routine for push_expression_name. - Handle a qualified name, where DOT_INDEX is the index of the first '.' */ - -static void -push_qualified_expression_name (struct parser_state *par_state, - struct stoken name, int dot_index) -{ - struct stoken token; - char *tmp; - struct type *typ; - - token.ptr = name.ptr; - token.length = dot_index; - - if (push_variable (par_state, token)) - { - token.ptr = name.ptr + dot_index + 1; - token.length = name.length - dot_index - 1; - push_fieldnames (par_state, token); - return; - } - - token.ptr = name.ptr; - for (;;) - { - token.length = dot_index; - tmp = copy_name (token); - typ = java_lookup_class (tmp); - if (typ != NULL) - { - if (dot_index == name.length) - { - write_exp_elt_opcode (par_state, OP_TYPE); - write_exp_elt_type (par_state, typ); - write_exp_elt_opcode (par_state, OP_TYPE); - return; - } - dot_index++; /* Skip '.' */ - name.ptr += dot_index; - name.length -= dot_index; - dot_index = 0; - while (dot_index < name.length && name.ptr[dot_index] != '.') - dot_index++; - token.ptr = name.ptr; - token.length = dot_index; - write_exp_elt_opcode (par_state, OP_SCOPE); - write_exp_elt_type (par_state, typ); - write_exp_string (par_state, token); - write_exp_elt_opcode (par_state, OP_SCOPE); - if (dot_index < name.length) - { - dot_index++; - name.ptr += dot_index; - name.length -= dot_index; - push_fieldnames (par_state, name); - } - return; - } - else if (dot_index >= name.length) - break; - dot_index++; /* Skip '.' */ - while (dot_index < name.length && name.ptr[dot_index] != '.') - dot_index++; - } - 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 (struct parser_state *par_state, struct stoken name) -{ - char *tmp; - struct type *typ; - int i; - - for (i = 0; i < name.length; i++) - { - if (name.ptr[i] == '.') - { - /* It's a Qualified Expression Name. */ - push_qualified_expression_name (par_state, name, i); - return; - } - } - - /* It's a Simple Expression Name. */ - - if (push_variable (par_state, name)) - return; - tmp = copy_name (name); - typ = java_lookup_class (tmp); - if (typ != NULL) - { - write_exp_elt_opcode (par_state, OP_TYPE); - write_exp_elt_type (par_state, typ); - write_exp_elt_opcode (par_state, OP_TYPE); - } - else - { - struct bound_minimal_symbol msymbol; - - msymbol = lookup_bound_minimal_symbol (tmp); - if (msymbol.minsym != NULL) - write_exp_msymbol (par_state, msymbol); - else if (!have_full_symbols () && !have_partial_symbols ()) - error (_("No symbol table is loaded. Use the \"file\" command")); - else - error (_("No symbol \"%s\" in current context."), tmp); - } - -} - - -/* The following two routines, copy_exp and insert_exp, aren't specific to - Java, so they could go in parse.c, but their only purpose is to support - the parsing kludges we use in this file, so maybe it's best to isolate - them here. */ - -/* Copy the expression whose last element is at index ENDPOS - 1 in EXPR - into a freshly malloc'ed struct expression. Its language_defn is set - to null. */ -static struct expression * -copy_exp (struct expression *expr, int endpos) -{ - int len = length_of_subexp (expr, endpos); - struct expression *newobj - = (struct expression *) malloc (sizeof (*newobj) + EXP_ELEM_TO_BYTES (len)); - - newobj->nelts = len; - memcpy (newobj->elts, expr->elts + endpos - len, EXP_ELEM_TO_BYTES (len)); - newobj->language_defn = 0; - - return newobj; -} - -/* Insert the expression NEW into the current expression (expout) at POS. */ -static void -insert_exp (struct parser_state *par_state, int pos, struct expression *newobj) -{ - int newlen = newobj->nelts; - int i; - - /* Grow expout if necessary. In this function's only use at present, - this should never be necessary. */ - increase_expout_size (par_state, newlen); - - for (i = par_state->expout_ptr - 1; i >= pos; i--) - par_state->expout->elts[i + newlen] = par_state->expout->elts[i]; - - memcpy (par_state->expout->elts + pos, newobj->elts, - EXP_ELEM_TO_BYTES (newlen)); - par_state->expout_ptr += newlen; -} |