* jv-lang.h (java_type_print): Added declaration.
* jv-typeprint.c: New file. Provides java_print_type.
* jv-lang.c (java_link_class_type): New function.
(java_language_defn): Replace c_print_type by java_print_type.
* Makefile.in: Update accordingly.
irix4-nat.c
irix5-nat.c
isi-xdep.c
-java-exp.y
-java-lang.c
-java-lang.h
-java-valprint.c
+jv-exp.y
+jv-lang.c
+jv-lang.h
+jv-valprint.c
+jv-typeprint.c
kdb-start.c
language.c
language.h
+Wed Jul 30 14:04:18 1997 Per Bothner <bothner@cygnus.com>
+
+ * java-*: Renamed to jv-*, to make fit within 14 characters.
+ * jv-lang.h (java_type_print): Added declaration.
+ * jv-typeprint.c: New file. Provides java_print_type.
+ * jv-lang.c (java_link_class_type): New function.
+ (java_language_defn): Replace c_print_type by java_print_type.
+ * Makefile.in: Update accordingly.
+
Tue Jul 29 10:12:44 1997 Felix Lee <flee@cygnus.com>
* Makefile.in (init.c): except some mswin files do need to be
elfread.c environ.c eval.c expprint.c \
f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c \
gdbtypes.c infcmd.c inflow.c infrun.c language.c \
- java-exp.y java-lang.c java-valprint.c \
+ jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \
m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \
mem-break.c minsyms.c mipsread.c nlmread.c objfiles.c parse.c \
printcmd.c remote.c remote-nrom.c scm-exp.c scm-lang.c scm-valprint.c \
gdb-stabs.h $(inferior_h) language.h minimon.h monitor.h \
objfiles.h parser-defs.h partial-stab.h serial.h signals.h solib.h \
symfile.h stabsread.h target.h terminal.h typeprint.h xcoffsolib.h \
- c-lang.h ch-lang.h f-lang.h java-lang.h m2-lang.h \
+ c-lang.h ch-lang.h f-lang.h jv-lang.h m2-lang.h \
complaints.h valprint.h \
29k-share/udi/udiids.h 29k-share/udi_soc nindy-share/b.out.h \
nindy-share/block_io.h nindy-share/coff.h \
dbxread.o coffread.o elfread.o \
dwarfread.o dwarf2read.o mipsread.o stabsread.o corefile.o \
c-lang.o ch-exp.o ch-lang.o f-lang.o \
- java-lang.o java-valprint.o m2-lang.o \
+ jv-lang.o jv-valprint.o jv-typeprint.o m2-lang.o \
scm-exp.o scm-lang.o scm-valprint.o complaints.o typeprint.o \
c-typeprint.o ch-typeprint.o f-typeprint.o m2-typeprint.o \
c-valprint.o cp-valprint.o ch-valprint.o f-valprint.o m2-valprint.o \
SUBDIRS = doc testsuite nlm mswin
# For now, shortcut the "configure GDB for fewer languages" stuff.
-YYFILES = c-exp.tab.c java-exp.tab.c f-exp.tab.c m2-exp.tab.c
-YYOBJ = c-exp.tab.o java-exp.tab.o f-exp.tab.o m2-exp.tab.o
+YYFILES = c-exp.tab.c jv-exp.tab.c f-exp.tab.c m2-exp.tab.c
+YYOBJ = c-exp.tab.o jv-exp.tab.o f-exp.tab.o m2-exp.tab.o
# Things which need to be built when making a distribution.
saber_gdb: $(SFILES) $(DEPFILES) copying.c version.c
#setopt load_flags $(CFLAGS) $(BFD_CFLAGS) -DHOST_SYS=SUN4_SYS
#load ./init.c $(SFILES)
- #unload $(srcdir)/c-exp.y $(srcdir)/java-exp.y $(srcdir)/m2-exp.y
+ #unload $(srcdir)/c-exp.y $(srcdir)/jv-exp.y $(srcdir)/m2-exp.y
#unload vx-share/*.h
#unload nindy-share/[A-Z]*
- #load c-exp.tab.c java-exp.tab.c m2-exp.tab.c
+ #load c-exp.tab.c jv-exp.tab.c m2-exp.tab.c
#load copying.c version.c
#load ../opcodes/libopcodes.a
#load ../libiberty/libiberty.a
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
@$(MAKE) $(FLAGS_TO_PASS) DO=maintainer-clean "DODIRS=$(SUBDIRS)" subdir_do
- rm -f c-exp.tab.c java-exp.tab.c f-exp.tab.c m2-exp.tab.c
+ rm -f c-exp.tab.c jv-exp.tab.c f-exp.tab.c m2-exp.tab.c
rm -f TAGS $(INFOFILES)
rm -f nm.h tm.h xm.h config.status
-rm y.tab.c
mv c-exp.new ./c-exp.tab.c
-java-exp.tab.o: java-exp.tab.c
-java-exp.tab.c: java-exp.y
- $(YACC) $(YFLAGS) $(srcdir)/java-exp.y
+jv-exp.tab.o: jv-exp.tab.c
+jv-exp.tab.c: jv-exp.y
+ $(YACC) $(YFLAGS) $(srcdir)/jv-exp.y
-sed -e '/extern.*malloc/d' \
-e '/extern.*realloc/d' \
-e '/extern.*free/d' \
-e 's/malloc/xmalloc/g' \
-e 's/realloc/xrealloc/g' \
-e '/^#line.*y.tab.c/d' \
- < y.tab.c > java-exp.new
+ < y.tab.c > jv-exp.new
-rm y.tab.c
- mv java-exp.new ./java-exp.tab.c
+ mv jv-exp.new ./jv-exp.tab.c
f-exp.tab.o: f-exp.tab.c
f-exp.tab.c: f-exp.y c-exp.tab.c
mv m2-exp.new ./m2-exp.tab.c
# These files are updated atomically, so make never has to remove them
-.PRECIOUS: m2-exp.tab.c java-exp.tab.c f-exp.tab.c c-exp.tab.c
+.PRECIOUS: m2-exp.tab.c jv-exp.tab.c f-exp.tab.c c-exp.tab.c
lint: $(LINTFILES)
$(LINT) $(INCLUDE_CFLAGS) $(LINTFLAGS) $(LINTFILES) \
$(gdbtypes_h) language.h parser-defs.h $(symtab_h) $(value_h) \
$(bfd_h) objfiles.h symfile.h
-java-exp.tab.o: java-exp.tab.c java-lang.h $(defs_h) $(expression_h) \
+jv-exp.tab.o: jv-exp.tab.c jv-lang.h $(defs_h) $(expression_h) \
$(gdbtypes_h) language.h parser-defs.h $(symtab_h) $(value_h) \
$(bfd_h) objfiles.h symfile.h
+++ /dev/null
-/* YACC parser for Java expressions, for GDB.
- Copyright (C) 1997.
- 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 2 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, write to the Free Software
-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.
- 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.
-
- 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 "gdb_string.h"
-#include <ctype.h>
-#include "expression.h"
-#include "value.h"
-#include "parser-defs.h"
-#include "language.h"
-#include "java-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 */
-
-/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
- as well as gratuitiously global symbol names, so we can have multiple
- yacc generated parsers in gdb. Note that these are only the variables
- produced by yacc. If other parser generators (bison, byacc, etc) produce
- additional global names that conflict at link time, then those parser
- generators need to be fixed instead of adding those names to this list. */
-
-#define yymaxdepth java_maxdepth
-#define yyparse java_parse
-#define yylex java_lex
-#define yyerror java_error
-#define yylval java_lval
-#define yychar java_char
-#define yydebug java_debug
-#define yypact java_pact
-#define yyr1 java_r1
-#define yyr2 java_r2
-#define yydef java_def
-#define yychk java_chk
-#define yypgo java_pgo
-#define yyact java_act
-#define yyexca java_exca
-#define yyerrflag java_errflag
-#define yynerrs java_nerrs
-#define yyps java_ps
-#define yypv java_pv
-#define yys java_s
-#define yy_yys java_yys
-#define yystate java_state
-#define yytmp java_tmp
-#define yyv java_v
-#define yy_yyv java_yyv
-#define yyval java_val
-#define yylloc java_lloc
-#define yyreds java_reds /* With YYDEBUG defined */
-#define yytoks java_toks /* With YYDEBUG defined */
-#define yylhs java_yylhs
-#define yylen java_yylen
-#define yydefred java_yydefred
-#define yydgoto java_yydgoto
-#define yysindex java_yysindex
-#define yyrindex java_yyrindex
-#define yygindex java_yygindex
-#define yytable java_yytable
-#define yycheck java_yycheck
-
-#ifndef YYDEBUG
-#define YYDEBUG 0 /* Default to no yydebug support */
-#endif
-
-int
-yyparse PARAMS ((void));
-
-static int
-yylex PARAMS ((void));
-
-void
-yyerror PARAMS ((char *));
-
-static struct type * java_type_from_name PARAMS ((struct stoken));
-static void push_variable PARAMS ((struct stoken));
-
-%}
-
-/* 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 PARAMS ((char *, int, int, YYSTYPE *));
-%}
-
-%type <lval> rcurly Dims Dims_opt
-%type <tval> ClassOrInterfaceType ClassType /* ReferenceType Type ArrayType */
-%type <tval> IntegralType FloatingPointType NumericType PrimitiveType
-
-%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 THIS 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 '.' '[' '('
-
-\f
-%%
-
-start : exp1
-/* | type_exp FIXME */
- ;
-
-StringLiteral:
- STRING_LITERAL
- {
- write_exp_elt_opcode (OP_STRING);
- write_exp_string ($1);
- write_exp_elt_opcode (OP_STRING);
- }
-;
-
-Literal :
- INTEGER_LITERAL
- { write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type ($1.type);
- write_exp_elt_longcst ((LONGEST)($1.val));
- write_exp_elt_opcode (OP_LONG); }
-| NAME_OR_INT
- { YYSTYPE val;
- parse_number ($1.ptr, $1.length, 0, &val);
- write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type (val.typed_val_int.type);
- write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
- write_exp_elt_opcode (OP_LONG);
- }
-| FLOATING_POINT_LITERAL
- { write_exp_elt_opcode (OP_DOUBLE);
- write_exp_elt_type ($1.type);
- write_exp_elt_dblcst ($1.dval);
- write_exp_elt_opcode (OP_DOUBLE); }
-| BOOLEAN_LITERAL
- { write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type (java_boolean_type);
- write_exp_elt_longcst ((LONGEST)$1);
- write_exp_elt_opcode (OP_LONG); }
-| StringLiteral
- ;
-
-/* UNUSED:
-Type:
- PrimitiveType
-| ReferenceType
-;
-*/
-
-PrimitiveType:
- NumericType
-| BOOLEAN
- { $$ = java_boolean_type; }
-;
-
-NumericType:
- IntegralType
-| FloatingPointType
-;
-
-IntegralType:
- BYTE
- { $$ = java_byte_type; }
-| SHORT
- { $$ = java_short_type; }
-| INT
- { $$ = java_int_type; }
-| LONG
- { $$ = java_long_type; }
-| CHAR
- { $$ = java_char_type; }
-;
-
-FloatingPointType:
- FLOAT
- { $$ = java_float_type; }
-| DOUBLE
- { $$ = java_double_type; }
-;
-
-/* UNUSED:
-ReferenceType:
- ClassOrInterfaceType
-| ArrayType
-;
-*/
-
-ClassOrInterfaceType:
- Name
- { $$ = java_type_from_name ($1); }
-;
-
-ClassType:
- ClassOrInterfaceType
-;
-
-/* UNUSED:
-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
- {
- $$.ptr = (char *) malloc ($$.length + 1);
- make_cleanup (free, $$.ptr);
- sprintf ($$.ptr, "%.*s.%.*s",
- $1.length, $1.ptr, $3.length, $3.ptr);
- } }
-;
-
-/*
-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 (BINOP_COMMA); }
- ;
-
-Primary:
- PrimaryNoNewArray
-| ArrayCreationExpression
-;
-
-PrimaryNoNewArray:
- Literal
-| THIS
- { write_exp_elt_opcode (OP_THIS);
- write_exp_elt_opcode (OP_THIS); }
-| '(' Expression ')'
-| ClassInstanceCreationExpression
-| FieldAccess
-| MethodInvocation
-| ArrayAccess
-| lcurly ArgumentList rcurly
- { write_exp_elt_opcode (OP_ARRAY);
- write_exp_elt_longcst ((LONGEST) 0);
- write_exp_elt_longcst ((LONGEST) $3);
- write_exp_elt_opcode (OP_ARRAY); }
-;
-
-lcurly:
- '{'
- { start_arglist (); }
-;
-
-rcurly:
- '}'
- { $$ = end_arglist () - 1; }
-;
-
-ClassInstanceCreationExpression:
- NEW ClassType '(' ArgumentList_opt ')'
- { error ("FIXME - ClassInstanceCreationExpression"); }
-;
-
-ArgumentList:
- Expression
- { arglist_len = 1; }
-| ArgumentList ',' Expression
- { arglist_len++; }
-;
-
-ArgumentList_opt:
- /* EMPTY */
- { arglist_len = 0; }
-| ArgumentList
-;
-
-ArrayCreationExpression:
- NEW PrimitiveType DimExprs Dims_opt
- { error ("FIXME - ArrayCreatiionExpression"); }
-| NEW ClassOrInterfaceType DimExprs Dims_opt
- { error ("FIXME - ArrayCreatiionExpression"); }
-;
-
-DimExprs:
- DimExpr
-| DimExprs DimExpr
-;
-
-DimExpr:
- '[' Expression ']'
-;
-
-Dims:
- '[' ']'
- { $$ = 1; }
-| Dims '[' ']'
- { $$ = $1 + 1; }
-;
-
-Dims_opt:
- Dims
-| /* EMPTY */
- { $$ = 0; }
-;
-
-FieldAccess:
- Primary '.' SimpleName
- { write_exp_elt_opcode (STRUCTOP_STRUCT);
- write_exp_string ($3);
- write_exp_elt_opcode (STRUCTOP_STRUCT); }
-/*| SUPER '.' SimpleName { FIXME } */
-;
-
-MethodInvocation:
- Name '(' ArgumentList_opt ')'
- { error ("method invocation not implemented"); }
-| Primary '.' SimpleName '(' ArgumentList_opt ')'
- { error ("method invocation not implemented"); }
-| SUPER '.' SimpleName '(' ArgumentList_opt ')'
- { error ("method invocation not implemented"); }
-;
-
-ArrayAccess:
- Name '[' Expression ']'
- { error ("ArrayAccess"); } /* FIXME - NASTY */
-| PrimaryNoNewArray '[' Expression ']'
- { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
-;
-
-PostfixExpression:
- Primary
-| Name
- { push_variable ($1); }
-| VARIABLE
- /* Already written by write_dollar_variable. */
-| PostIncrementExpression
-| PostDecrementExpression
-;
-
-PostIncrementExpression:
- PostfixExpression INCREMENT
- { write_exp_elt_opcode (UNOP_POSTINCREMENT); }
-;
-
-PostDecrementExpression:
- PostfixExpression DECREMENT
- { write_exp_elt_opcode (UNOP_POSTDECREMENT); }
-;
-
-UnaryExpression:
- PreIncrementExpression
-| PreDecrementExpression
-| '+' UnaryExpression
-| '-' UnaryExpression
- { write_exp_elt_opcode (UNOP_NEG); }
-| '*' UnaryExpression
- { write_exp_elt_opcode (UNOP_IND); } /*FIXME not in Java */
-| UnaryExpressionNotPlusMinus
-;
-
-PreIncrementExpression:
- INCREMENT UnaryExpression
- { write_exp_elt_opcode (UNOP_PREINCREMENT); }
-;
-
-PreDecrementExpression:
- DECREMENT UnaryExpression
- { write_exp_elt_opcode (UNOP_PREDECREMENT); }
-;
-
-UnaryExpressionNotPlusMinus:
- PostfixExpression
-| '~' UnaryExpression
- { write_exp_elt_opcode (UNOP_COMPLEMENT); }
-| '!' UnaryExpression
- { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
-| CastExpression
- ;
-
-CastExpression:
- '(' PrimitiveType Dims_opt ')' UnaryExpression
- { write_exp_elt_opcode (UNOP_CAST);
- write_exp_elt_type (java_array_type ($2, $3));
- write_exp_elt_opcode (UNOP_CAST); }
-| '(' Expression ')' UnaryExpressionNotPlusMinus /* FIXME */
-| '(' Name Dims ')' UnaryExpressionNotPlusMinus
- { write_exp_elt_opcode (UNOP_CAST);
- write_exp_elt_type (java_array_type (java_type_from_name ($2), $3));
- write_exp_elt_opcode (UNOP_CAST); }
-;
-
-
-MultiplicativeExpression:
- UnaryExpression
-| MultiplicativeExpression '*' UnaryExpression
- { write_exp_elt_opcode (BINOP_MUL); }
-| MultiplicativeExpression '/' UnaryExpression
- { write_exp_elt_opcode (BINOP_DIV); }
-| MultiplicativeExpression '%' UnaryExpression
- { write_exp_elt_opcode (BINOP_REM); }
-;
-
-AdditiveExpression:
- MultiplicativeExpression
-| AdditiveExpression '+' MultiplicativeExpression
- { write_exp_elt_opcode (BINOP_ADD); }
-| AdditiveExpression '-' MultiplicativeExpression
- { write_exp_elt_opcode (BINOP_SUB); }
-;
-
-ShiftExpression:
- AdditiveExpression
-| ShiftExpression LSH AdditiveExpression
- { write_exp_elt_opcode (BINOP_LSH); }
-| ShiftExpression RSH AdditiveExpression
- { write_exp_elt_opcode (BINOP_RSH); }
-/* | ShiftExpression >>> AdditiveExpression { FIXME } */
-;
-
-RelationalExpression:
- ShiftExpression
-| RelationalExpression '<' ShiftExpression
- { write_exp_elt_opcode (BINOP_LESS); }
-| RelationalExpression '>' ShiftExpression
- { write_exp_elt_opcode (BINOP_GTR); }
-| RelationalExpression LEQ ShiftExpression
- { write_exp_elt_opcode (BINOP_LEQ); }
-| RelationalExpression GEQ ShiftExpression
- { write_exp_elt_opcode (BINOP_GEQ); }
-/* | RelationalExpresion INSTANCEOF ReferenceType { FIXME } */
-;
-
-EqualityExpression:
- RelationalExpression
-| EqualityExpression EQUAL RelationalExpression
- { write_exp_elt_opcode (BINOP_EQUAL); }
-| EqualityExpression NOTEQUAL RelationalExpression
- { write_exp_elt_opcode (BINOP_NOTEQUAL); }
-;
-
-AndExpression:
- EqualityExpression
-| AndExpression '&' EqualityExpression
- { write_exp_elt_opcode (BINOP_BITWISE_AND); }
-;
-
-ExclusiveOrExpression:
- AndExpression
-| ExclusiveOrExpression '^' AndExpression
- { write_exp_elt_opcode (BINOP_BITWISE_XOR); }
-;
-InclusiveOrExpression:
- ExclusiveOrExpression
-| InclusiveOrExpression '|' ExclusiveOrExpression
- { write_exp_elt_opcode (BINOP_BITWISE_IOR); }
-;
-
-ConditionalAndExpression:
- InclusiveOrExpression
-| ConditionalAndExpression ANDAND InclusiveOrExpression
- { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
-;
-
-ConditionalOrExpression:
- ConditionalAndExpression
-| ConditionalOrExpression OROR ConditionalAndExpression
- { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
-;
-
-ConditionalExpression:
- ConditionalOrExpression
-| ConditionalOrExpression '?' Expression ':' ConditionalExpression
- { write_exp_elt_opcode (TERNOP_COND); }
-;
-
-AssignmentExpression:
- ConditionalExpression
-| Assignment
-;
-
-Assignment:
- LeftHandSide '=' ConditionalExpression
- { write_exp_elt_opcode (BINOP_ASSIGN); }
-| LeftHandSide ASSIGN_MODIFY ConditionalExpression
- { write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
- write_exp_elt_opcode ($2);
- write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
-;
-
-LeftHandSide:
- ForcedName
- { push_variable ($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 (p, len, parsed_float, putithere)
- register char *p;
- register int len;
- int parsed_float;
- YYSTYPE *putithere;
-{
- register ULONGEST n = 0;
- ULONGEST limit, limit_div_base;
-
- register int c;
- register int base = input_radix;
-
- struct type *type;
-
- if (parsed_float)
- {
- /* It's a float since it contains a point or an exponent. */
- char c;
- int num = 0; /* number of tokens scanned by scanf */
- 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
- }
- p[len] = saved_char; /* restore the input stream */
- if (num != 1) /* check scanf found ONLY a float ... */
- return ERROR;
- /* See if it has `f' or `d' suffix (float or double). */
-
- c = tolower (p[len - 1]);
-
- if (c == 'f' || c == 'F')
- putithere->typed_val_float.type = builtin_type_float;
- else if (isdigit (c) || c == '.' || c == 'd' || c == 'D')
- putithere->typed_val_float.type = builtin_type_double;
- 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];
- limit = (ULONGEST)0xffffffff;
- if (c == 'l' || c == 'L')
- {
- type = java_long_type;
- len--;
- /* A paranoid calculation of (1<<64)-1. */
- limit = ((limit << 16) << 16) | limit;
- }
- else
- {
- type = java_int_type;
- }
- 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' - 'A';
- if (c >= 'a' && c - 'a' + 10 < base)
- 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;
- }
-
- putithere->typed_val_int.val = n;
- putithere->typed_val_int.type = type;
- return INTEGER_LITERAL;
-}
-
-struct token
-{
- char *operator;
- 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 ()
-{
- int c;
- int namelen;
- unsigned int i;
- char *tokstart;
- char *tokptr;
- int tempbufindex;
- static char *tempbuf;
- static int tempbufsize;
-
- retry:
-
- 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))
- {
- 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 (STREQN (tokstart, tokentab2[i].operator, 2))
- {
- 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 (&lexptr);
- else if (c == '\'')
- error ("Empty character constant.");
-
- yylval.typed_val_int.val = c;
- yylval.typed_val_int.type = builtin_type_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;
- register 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 (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 (&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 (STREQN (tokstart, "boolean", 7))
- return BOOLEAN;
- break;
- case 6:
- if (STREQN (tokstart, "double", 6))
- return DOUBLE;
- break;
- case 5:
- if (STREQN (tokstart, "short", 5))
- return SHORT;
- if (STREQN (tokstart, "false", 5))
- {
- yylval.lval = 0;
- return BOOLEAN_LITERAL;
- }
- if (STREQN (tokstart, "super", 5))
- return SUPER;
- if (STREQN (tokstart, "float", 5))
- return FLOAT;
- break;
- case 4:
- if (STREQN (tokstart, "long", 4))
- return LONG;
- if (STREQN (tokstart, "byte", 4))
- return BYTE;
- if (STREQN (tokstart, "char", 4))
- return CHAR;
- if (STREQN (tokstart, "true", 4))
- {
- 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))
- return INT;
- if (STREQN (tokstart, "new", 3))
- return NEW;
- break;
- default:
- break;
- }
-
- yylval.sval.ptr = tokstart;
- yylval.sval.length = namelen;
-
- if (*tokstart == '$')
- {
- write_dollar_variable (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 (tokstart, namelen, 0, &newlval);
- if (hextype == INTEGER_LITERAL)
- return NAME_OR_INT;
- }
- return IDENTIFIER;
-}
-
-void
-yyerror (msg)
- char *msg;
-{
- error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
-}
-
-static struct type *
-java_type_from_name (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;
-}
-
-static void
-push_variable (name)
- struct stoken name;
-
-{
- char *tmp = copy_name (name);
- int is_a_field_of_this = 0;
- struct symbol *sym;
- struct type *typ;
- sym = lookup_symbol (tmp, expression_context_block, VAR_NAMESPACE,
- &is_a_field_of_this, (struct symtab **) NULL);
- if (sym)
- {
- if (symbol_read_needs_frame (sym))
- {
- if (innermost_block == 0 ||
- contained_in (block_found, innermost_block))
- innermost_block = block_found;
- }
-
- write_exp_elt_opcode (OP_VAR_VALUE);
- /* We want to use the selected frame, not another more inner frame
- which happens to be in the same block. */
- write_exp_elt_block (NULL);
- write_exp_elt_sym (sym);
- write_exp_elt_opcode (OP_VAR_VALUE);
- return;
- }
- if (is_a_field_of_this)
- {
- /* it hangs off of `this'. Must not inadvertently convert from a
- method call to data ref. */
- if (innermost_block == 0 ||
- contained_in (block_found, innermost_block))
- innermost_block = block_found;
- write_exp_elt_opcode (OP_THIS);
- write_exp_elt_opcode (OP_THIS);
- write_exp_elt_opcode (STRUCTOP_PTR);
- write_exp_string (name);
- write_exp_elt_opcode (STRUCTOP_PTR);
- return;
- }
-
- typ = java_lookup_class (tmp);
- if (typ != NULL)
- {
- write_exp_elt_opcode(OP_TYPE);
- write_exp_elt_type(typ);
- write_exp_elt_opcode(OP_TYPE);
- }
- else
- {
- struct minimal_symbol *msymbol;
-
- msymbol = lookup_minimal_symbol (tmp, NULL, NULL);
- if (msymbol != NULL)
- {
- write_exp_msymbol (msymbol,
- lookup_function_type (builtin_type_int),
- builtin_type_int);
- }
- 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);
- }
-
-}
+++ /dev/null
-/* Java language support routines for GDB, the GNU debugger.
- Copyright 1997 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 2 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, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "defs.h"
-#include "symtab.h"
-#include "gdbtypes.h"
-#include "expression.h"
-#include "parser-defs.h"
-#include "language.h"
-#include "gdbtypes.h"
-#include "symtab.h"
-#include "symfile.h"
-#include "objfiles.h"
-#include "gdb_string.h"
-#include "value.h"
-#include "c-lang.h"
-#include "java-lang.h"
-#include "gdbcore.h"
-
-struct type *java_int_type;
-struct type *java_byte_type;
-struct type *java_short_type;
-struct type *java_long_type;
-struct type *java_boolean_type;
-struct type *java_char_type;
-struct type *java_float_type;
-struct type *java_double_type;
-struct type *java_void_type;
-
-struct type *java_object_type;
-
-/* This objfile contains symtabs that have been dynamically created
- to record dynamically loaded Java classes and dynamically
- compiled java methods. */
-struct objfile *dynamics_objfile = NULL;
-
-struct objfile *
-get_dynamics_objfile ()
-{
- if (dynamics_objfile == NULL)
- {
- dynamics_objfile = allocate_objfile (NULL, 0);
- }
- return dynamics_objfile;
-}
-
-#if 1
-/* symtab contains classes read from the inferior. */
-
-static struct symtab *class_symtab = NULL;
-
-/* Maximum number of class in class_symtab before relocation is needed. */
-
-static int class_symtab_space;
-
-struct symtab *
-get_java_class_symtab ()
-{
- if (class_symtab == NULL)
- {
- struct objfile *objfile = get_dynamics_objfile();
- struct blockvector *bv;
- struct block *bl;
- class_symtab = allocate_symtab ("<java-classes>", objfile);
- class_symtab->language = language_java;
- bv = (struct blockvector *)
- obstack_alloc (&objfile->symbol_obstack, sizeof (struct blockvector));
- BLOCKVECTOR_NBLOCKS (bv) = 1;
- BLOCKVECTOR (class_symtab) = bv;
-
- /* Allocate dummy STATIC_BLOCK. */
- bl = (struct block *)
- obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
- BLOCK_NSYMS (bl) = 0;
- BLOCK_START (bl) = 0;
- BLOCK_END (bl) = 0;
- BLOCK_FUNCTION (bl) = NULL;
- BLOCK_SUPERBLOCK (bl) = NULL;
- BLOCK_GCC_COMPILED (bl) = 0;
- BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
-
- /* Allocate GLOBAL_BLOCK. This has to be relocatable. */
- class_symtab_space = 128;
- bl = (struct block *)
- mmalloc (objfile->md,
- sizeof (struct block)
- + ((class_symtab_space - 1) * sizeof (struct symbol *)));
- *bl = *BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
- class_symtab->free_ptr = (char *) bl;
- }
- return class_symtab;
-}
-
-static void
-add_class_symtab_symbol (sym)
- struct symbol *sym;
-{
- struct symtab *symtab = get_java_class_symtab ();
- struct blockvector *bv = BLOCKVECTOR (symtab);
- struct block *bl = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- if (BLOCK_NSYMS (bl) >= class_symtab_space)
- {
- /* Need to re-allocate. */
- class_symtab_space *= 2;
- bl = (struct block *)
- mrealloc (symtab->objfile->md, bl,
- sizeof (struct block)
- + ((class_symtab_space - 1) * sizeof (struct symbol *)));
- class_symtab->free_ptr = (char *) bl;
- BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
- }
-
- BLOCK_SYM (bl, BLOCK_NSYMS (bl)) = sym;
- BLOCK_NSYMS (bl) = BLOCK_NSYMS (bl) + 1;
-}
-
-struct symbol *
-add_class_symbol (type, addr)
- struct type *type;
- CORE_ADDR addr;
-{
- struct symbol *sym;
- sym = (struct symbol *)
- obstack_alloc (&dynamics_objfile->symbol_obstack, sizeof (struct symbol));
- memset (sym, 0, sizeof (struct symbol));
- SYMBOL_LANGUAGE (sym) = language_java;
- SYMBOL_NAME (sym) = TYPE_NAME (type);
- SYMBOL_CLASS (sym) = LOC_TYPEDEF;
- /* SYMBOL_VALUE (sym) = valu;*/
- SYMBOL_TYPE (sym) = type;
- SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
- SYMBOL_VALUE_ADDRESS (sym) = addr;
- return sym;
-}
-#endif
-
-struct type *
-java_lookup_class (name)
- char *name;
-{
- struct symbol *sym;
- sym = lookup_symbol (name, expression_context_block, STRUCT_NAMESPACE,
- (int *) 0, (struct symtab **) NULL);
- if (sym == NULL)
- {
- /* FIXME - should search inferior's symbol table. */
- return NULL;
- }
- return SYMBOL_TYPE (sym);
-}
-
-/* Return a nul-terminated string (allocated on OBSTACK) for
- a name given by NAME (which has type Utf8Const*). */
-
-char *
-get_java_utf8_name (obstack, name)
- struct obstack *obstack;
- value_ptr name;
-{
- char *chrs;
- value_ptr temp = name;
- int name_length = (int) value_as_long
- (value_struct_elt (&temp, NULL, "length", NULL, "structure"));
- temp = name;
- temp = value_struct_elt (&temp, NULL, "data", NULL, "structure");
- chrs = obstack_alloc (obstack, name_length+1);
- chrs [name_length] = '\0';
- read_memory_section (VALUE_ADDRESS (temp) + VALUE_OFFSET (temp),
- chrs, name_length, NULL);
- return chrs;
-}
-
-value_ptr
-java_class_from_object (obj_val)
- value_ptr obj_val;
-{
- value_ptr dtable_val = value_struct_elt (&obj_val, NULL, "dtable", NULL, "structure");
- return value_struct_elt (&dtable_val, NULL, "class", NULL, "structure");
-}
-
-/* Check if CLASS_IS_PRIMITIVE(value of clas): */
-int
-java_class_is_primitive (clas)
- value_ptr clas;
-{
- value_ptr dtable = value_struct_elt (&clas, NULL, "dtable", NULL, "struct");
- CORE_ADDR i = value_as_pointer (dtable);
- return (int) (i & 0x7fffffff) == (int) 0x7fffffff;
-}
-
-/* Read a Kaffe Class object, and generated a gdb (TYPE_CODE_STRUCT) type. */
-
-struct type *
-type_from_class (clas)
- value_ptr clas;
-{
- struct type *type;
- struct type *tsuper;
- int ninterfaces, nfields;
- char *name;
- value_ptr temp;
- struct objfile *objfile = get_dynamics_objfile();
- value_ptr utf8_name, fields, field, method, methods;
- char *nptr;
- CORE_ADDR addr;
- struct block *bl;
- int i, j;
- int type_is_object = 0;
- int is_array = 0;
- int nmethods;
- struct fn_field *fn_fields;
- struct fn_fieldlist *fn_fieldlists;
- char *unqualified_name;
-
- type = check_typedef (VALUE_TYPE (clas));
- if (TYPE_CODE (type) == TYPE_CODE_PTR)
- {
- if (value_logical_not (clas))
- return NULL;
- clas = value_ind (clas);
- }
- addr = VALUE_ADDRESS (clas) + VALUE_OFFSET (clas);
-
- get_java_class_symtab ();
- bl = BLOCKVECTOR_BLOCK (BLOCKVECTOR (class_symtab), GLOBAL_BLOCK);
- for (i = BLOCK_NSYMS (bl); --i >= 0; )
- {
- struct symbol *sym = BLOCK_SYM (bl, i);
- if (SYMBOL_VALUE_ADDRESS (sym) == addr)
- return SYMBOL_TYPE (sym);
- }
-
- if (java_class_is_primitive (clas))
- {
- value_ptr sig;
- temp = clas;
- sig = value_struct_elt (&temp, NULL, "msize", NULL, "structure");
- return java_primitive_type (value_as_long (sig));
- }
-
- /* Get Class name. */
- /* if clasloader non-null, prepend loader address. FIXME */
- temp = clas;
- utf8_name = value_struct_elt (&temp, NULL, "name", NULL, "structure");
- name = get_java_utf8_name (&objfile->type_obstack, utf8_name);
-
- type = alloc_type (objfile);
- TYPE_CODE (type) = TYPE_CODE_STRUCT;
- INIT_CPLUS_SPECIFIC (type);
-
- if (name[0] == '[')
- {
- is_array = 1;
- temp = clas;
- /* Set array element type. */
- temp = value_struct_elt (&temp, NULL, "methods", NULL, "structure");
- VALUE_TYPE (temp) = lookup_pointer_type (VALUE_TYPE (clas));
- TYPE_TARGET_TYPE (type) = type_from_class (temp);
- }
- unqualified_name = name;
- for (nptr = name; *nptr != 0; nptr++)
- {
- if (*nptr == '/')
- {
- *nptr = '.';
- unqualified_name = nptr+1;
- }
- }
-
- ALLOCATE_CPLUS_STRUCT_TYPE (type);
- TYPE_NAME (type) = name;
-
- add_class_symtab_symbol (add_class_symbol (type, addr));
-
- temp = clas;
- temp = value_struct_elt (&temp, NULL, "superclass", NULL, "structure");
- if (name != NULL && strcmp (name, "java.lang.Object") == 0)
- {
- tsuper = get_java_object_type ();
- if (tsuper && TYPE_CODE (tsuper) == TYPE_CODE_PTR)
- tsuper = TYPE_TARGET_TYPE (tsuper);
- type_is_object = 1;
- }
- else
- tsuper = type_from_class (temp);
-
-#if 1
- ninterfaces = 0;
-#else
- temp = clas;
- ninterfaces = value_as_long (value_struct_elt (&temp, NULL, "interface_len", NULL, "structure"));
-#endif
- TYPE_N_BASECLASSES (type) = (tsuper == NULL ? 0 : 1) + ninterfaces;
- temp = clas;
- nfields = value_as_long (value_struct_elt (&temp, NULL, "nfields", NULL, "structure"));
- nfields += TYPE_N_BASECLASSES (type);
- TYPE_NFIELDS (type) = nfields;
- TYPE_FIELDS (type) = (struct field *)
- TYPE_ALLOC (type, sizeof (struct field) * nfields);
-
- memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
-
- TYPE_FIELD_PRIVATE_BITS (type) =
- (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
- B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
-
- TYPE_FIELD_PROTECTED_BITS (type) =
- (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
- B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
-
- TYPE_FIELD_IGNORE_BITS (type) =
- (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
- B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
-
- TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *)
- TYPE_ALLOC (type, B_BYTES (TYPE_N_BASECLASSES (type)));
- B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), TYPE_N_BASECLASSES (type));
-
- if (tsuper != NULL)
- {
- TYPE_BASECLASS (type, 0) = tsuper;
- if (type_is_object)
- SET_TYPE_FIELD_PRIVATE (type, 0);
- }
-
-
- temp = clas;
- temp = value_struct_elt (&temp, NULL, "bfsize", NULL, "structure");
- TYPE_LENGTH (type) = JAVA_OBJECT_SIZE + value_as_long (temp);
-
- fields = NULL;
- for (i = TYPE_N_BASECLASSES (type); i < nfields; i++)
- {
- int accflags;
- int boffset;
- if (fields == NULL)
- {
- temp = clas;
- fields = value_struct_elt (&temp, NULL, "fields", NULL, "structure");
- field = value_ind (fields);
- }
- else
- { /* Re-use field value for next field. */
- VALUE_ADDRESS (field) += TYPE_LENGTH (VALUE_TYPE (field));
- VALUE_LAZY (field) = 1;
- }
- temp = field;
- temp = value_struct_elt (&temp, NULL, "name", NULL, "structure");
- TYPE_FIELD_NAME (type, i) =
- get_java_utf8_name (&objfile->type_obstack, temp);
- temp = field;
- accflags = value_as_long (value_struct_elt (&temp, NULL, "accflags",
- NULL, "structure"));
- boffset = value_as_long (value_struct_elt (&temp, NULL, "boffset",
- NULL, "structure"));
- if (accflags & 0x0001) /* public access */
- {
- /* ??? */
- }
- if (accflags & 0x0002) /* private access */
- {
- SET_TYPE_FIELD_PRIVATE (type, i);
- }
- if (accflags & 0x0004) /* protected access */
- {
- SET_TYPE_FIELD_PROTECTED (type, i);
- }
- if (accflags & 0x0008) /* ACC_STATIC */
- {
- TYPE_FIELD_BITPOS (type, i) = -1;
- /* Hack for TYPE_FIELD_STATIC_PHYSNAME to prevent a crash. FIXME. */
- type->fields[i].bitsize = (long) "???";
- }
- else
- TYPE_FIELD_BITPOS (type, i) = 8 * (JAVA_OBJECT_SIZE + boffset);
- if (accflags & 0x8000) /* FIELD_UNRESOLVED_FLAG */
- {
- TYPE_FIELD_TYPE (type, i) = get_java_object_type (); /* FIXME */
- }
- else
- {
- struct type *ftype;
- temp = field;
- temp = value_struct_elt (&temp, NULL, "type", NULL, "structure");
- ftype = type_from_class (temp);
- if (TYPE_CODE (ftype) == TYPE_CODE_STRUCT)
- ftype = lookup_pointer_type (ftype);
- TYPE_FIELD_TYPE (type, i) = ftype;
- }
- }
-
- temp = clas;
- nmethods = value_as_long (value_struct_elt (&temp, NULL, "nmethods",
- NULL, "structure"));
- TYPE_NFN_FIELDS_TOTAL (type) = nmethods;
- j = nmethods * sizeof (struct fn_field);
- fn_fields = (struct fn_field*)
- obstack_alloc (&dynamics_objfile->symbol_obstack, j);
- memset (fn_fields, 0, j);
- fn_fieldlists = (struct fn_fieldlist*)
- alloca (nmethods * sizeof (struct fn_fieldlist));
-
- methods = NULL;
- for (i = 0; i < nmethods; i++)
- {
- char *mname;
- int k;
- if (methods == NULL)
- {
- temp = clas;
- methods = value_struct_elt (&temp, NULL, "methods", NULL, "structure");
- method = value_ind (methods);
- }
- else
- { /* Re-use method value for next method. */
- VALUE_ADDRESS (method) += TYPE_LENGTH (VALUE_TYPE (method));
- VALUE_LAZY (method) = 1;
- }
-
- /* Get method name. */
- temp = method;
- temp = value_struct_elt (&temp, NULL, "name", NULL, "structure");
- mname = get_java_utf8_name (&objfile->type_obstack, temp);
- if (strcmp (mname, "<init>") == 0)
- mname = unqualified_name;
-
- /* Check for an existing method with the same name.
- * This makes building the fn_fieldslists an O(nmethods**2)
- * operation. That could be using hashing, but I doubt it
- * is worth it. Note that we do maintain the order of methods
- * in the inferior's Method table (as long as that is grouped
- * by method name), which I think is desirable. --PB */
- for (k = 0, j = TYPE_NFN_FIELDS (type); ; )
- {
- if (--j < 0)
- { /* No match - new method name. */
- j = TYPE_NFN_FIELDS(type)++;
- fn_fieldlists[j].name = mname;
- fn_fieldlists[j].length = 1;
- fn_fieldlists[j].fn_fields = &fn_fields[i];
- k = i;
- break;
- }
- if (strcmp (mname, fn_fieldlists[j].name) == 0)
- { /* Found an existing method with the same name. */
- int l;
- if (mname != unqualified_name)
- obstack_free (&objfile->type_obstack, mname);
- mname = fn_fieldlists[j].name;
- fn_fieldlists[j].length++;
- k = i - k; /* Index of new slot. */
- /* Shift intervening fn_fields (between k and i) down. */
- for (l = i; l > k; l--) fn_fields[l] = fn_fields[l-1];
- for (l = TYPE_NFN_FIELDS (type); --l > j; )
- fn_fieldlists[l].fn_fields++;
- break;
- }
- k += fn_fieldlists[j].length;
- }
- fn_fields[k].physname = "";
- fn_fields[k].is_stub = 1;
- fn_fields[k].type = make_function_type (java_void_type, NULL); /* FIXME*/
- TYPE_CODE (fn_fields[k].type) = TYPE_CODE_METHOD;
- }
-
- j = TYPE_NFN_FIELDS(type) * sizeof (struct fn_fieldlist);
- TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist*)
- obstack_alloc (&dynamics_objfile->symbol_obstack, j);
- memcpy (TYPE_FN_FIELDLISTS (type), fn_fieldlists, j);
-
- return type;
-}
-
-struct type*
-get_java_object_type ()
-{
- return java_object_type;
-}
-
-int
-is_object_type (type)
- struct type *type;
-{
- CHECK_TYPEDEF (type);
- if (TYPE_CODE (type) == TYPE_CODE_PTR)
- {
- struct type *ttype = check_typedef (TYPE_TARGET_TYPE (type));
- char *name;
- if (TYPE_CODE (ttype) != TYPE_CODE_STRUCT)
- return 0;
- while (TYPE_N_BASECLASSES (ttype) > 0)
- ttype = TYPE_BASECLASS (ttype, 0);
- name = TYPE_NAME (ttype);
- if (name != NULL && strcmp (name, "java.lang.Object") == 0)
- return 1;
- name = TYPE_NFIELDS (ttype) > 0 ? TYPE_FIELD_NAME (ttype, 0) : (char*)0;
- if (name != NULL && strcmp (name, "dtable") == 0)
- {
- if (java_object_type == NULL)
- java_object_type = type;
- return 1;
- }
- }
- return 0;
-}
-
-struct type*
-java_primitive_type (signature)
- int signature;
-{
- switch (signature)
- {
- case 'B': return java_byte_type;
- case 'S': return java_short_type;
- case 'I': return java_int_type;
- case 'J': return java_long_type;
- case 'Z': return java_boolean_type;
- case 'C': return java_char_type;
- case 'F': return java_float_type;
- case 'D': return java_double_type;
- case 'V': return java_void_type;
- }
- error ("unknown signature '%c' for primitive type", (char) signature);
-}
-
-/* Return the type of TYPE followed by DIMS pairs of [ ].
- If DIMS == 0, TYPE is returned. */
-
-struct type *
-java_array_type (type, dims)
- struct type *type;
- int dims;
-{
- if (dims == 0)
- return type;
- error ("array types not implemented");
-}
-
-/* Create a Java string in the inferior from a (Utf8) literal. */
-
-value_ptr
-java_value_string (ptr, len)
- char *ptr;
- int len;
-{
- error ("not implemented - java_value_string"); /* FIXME */
-}
-
-static value_ptr
-evaluate_subexp_java (expect_type, exp, pos, noside)
- struct type *expect_type;
- register struct expression *exp;
- register int *pos;
- enum noside noside;
-{
- int pc = *pos;
- int i;
- enum exp_opcode op = exp->elts[*pos].opcode;
- value_ptr arg1;
- switch (op)
- {
- case UNOP_IND:
- if (noside == EVAL_SKIP)
- goto standard;
- (*pos)++;
- arg1 = evaluate_subexp_standard (expect_type, exp, pos, EVAL_NORMAL);
- if (is_object_type (VALUE_TYPE (arg1)))
- {
- struct type *type = type_from_class (java_class_from_object (arg1));
- arg1 = value_cast (lookup_pointer_type (type), arg1);
- }
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_ind (arg1);
- case OP_STRING:
- (*pos)++;
- i = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (i + 1);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return java_value_string (&exp->elts[pc + 2].string, i);
- default:
- break;
- }
-standard:
- return evaluate_subexp_standard (expect_type, exp, pos, noside);
- nosideret:
- return value_from_longest (builtin_type_long, (LONGEST) 1);
-}
-
-static struct type *
-java_create_fundamental_type (objfile, typeid)
- struct objfile *objfile;
- int typeid;
-{
- switch (typeid)
- {
- case FT_VOID: return java_void_type;
- case FT_BOOLEAN: return java_boolean_type;
- case FT_CHAR: return java_char_type;
- case FT_FLOAT: return java_float_type;
- case FT_DBL_PREC_FLOAT: return java_double_type;
- case FT_BYTE: case FT_SIGNED_CHAR: return java_byte_type;
- case FT_SHORT: case FT_SIGNED_SHORT: return java_short_type;
- case FT_INTEGER: case FT_SIGNED_INTEGER: return java_int_type;
- case FT_LONG: case FT_SIGNED_LONG: return java_long_type;
- }
- return c_create_fundamental_type (objfile, typeid);
-}
-
-/* Table mapping opcodes into strings for printing operators
- and precedences of the operators. */
-
-const struct op_print java_op_print_tab[] =
- {
- {",", BINOP_COMMA, PREC_COMMA, 0},
- {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
- {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
- {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
- {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
- {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
- {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
- {"==", BINOP_EQUAL, PREC_EQUAL, 0},
- {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
- {"<=", BINOP_LEQ, PREC_ORDER, 0},
- {">=", BINOP_GEQ, PREC_ORDER, 0},
- {">", BINOP_GTR, PREC_ORDER, 0},
- {"<", BINOP_LESS, PREC_ORDER, 0},
- {">>", BINOP_RSH, PREC_SHIFT, 0},
- {"<<", BINOP_LSH, PREC_SHIFT, 0},
-#if 0
- {">>>", BINOP_???, PREC_SHIFT, 0},
-#endif
- {"+", BINOP_ADD, PREC_ADD, 0},
- {"-", BINOP_SUB, PREC_ADD, 0},
- {"*", BINOP_MUL, PREC_MUL, 0},
- {"/", BINOP_DIV, PREC_MUL, 0},
- {"%", BINOP_REM, PREC_MUL, 0},
- {"-", UNOP_NEG, PREC_PREFIX, 0},
- {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
- {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
- {"*", UNOP_IND, PREC_PREFIX, 0},
-#if 0
- {"instanceof", ???, ???, 0},
-#endif
- {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
- {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
- {NULL, 0, 0, 0}
-};
-
-const struct language_defn java_language_defn = {
- "java", /* Language name */
- language_java,
- c_builtin_types,
- range_check_off,
- type_check_off,
- java_parse,
- java_error,
- evaluate_subexp_java,
- c_printchar, /* Print a character constant */
- c_printstr, /* Function to print string constant */
- java_create_fundamental_type, /* Create fundamental type in this language */
- c_print_type, /* Print a type using appropriate syntax */
- java_val_print, /* Print a value using appropriate syntax */
- java_value_print, /* Print a top-level value */
- {"", "", "", ""}, /* Binary format info */
- {"0%lo", "0", "o", ""}, /* Octal format info */
- {"%ld", "", "d", ""}, /* Decimal format info */
- {"0x%lx", "0x", "x", ""}, /* Hex format info */
- java_op_print_tab, /* expression operators for printing */
- 1, /* c-style arrays */
- 0, /* String lower bound */
- &builtin_type_char, /* Type of string elements */
- LANG_MAGIC
-};
-
-void
-_initialize_jave_language ()
-{
-
- java_int_type = init_type (TYPE_CODE_INT, 4, 0, "int", NULL);
- java_short_type = init_type (TYPE_CODE_INT, 2, 0, "short", NULL);
- java_long_type = init_type (TYPE_CODE_INT, 8, 0, "long", NULL);
- java_byte_type = init_type (TYPE_CODE_INT, 1, 0, "byte", NULL);
- java_boolean_type= init_type (TYPE_CODE_BOOL, 1, 0, "boolean", NULL);
- java_char_type = init_type (TYPE_CODE_CHAR, 2, 0, "char", NULL);
- java_float_type = init_type (TYPE_CODE_FLT, 4, 0, "float", NULL);
- java_double_type = init_type (TYPE_CODE_FLT, 8, 0, "double", NULL);
- java_void_type = init_type (TYPE_CODE_VOID, 1, 0, "void", NULL);
-
- add_language (&java_language_defn);
-}
-
-/* Cleanup code that should be urn on every "run".
- We need some hook to have this actually be called ... FIXME */
-
-void java_rerun_cleanup ()
-{
- if (class_symtab != NULL)
- {
- free_symtab (class_symtab); /* ??? */
- class_symtab = NULL;
- }
- if (dynamics_objfile != NULL)
- {
- free_objfile (dynamics_objfile);
- dynamics_objfile = NULL;
- }
-
- java_object_type = NULL;
-}
+++ /dev/null
-/* Java language support definitions for GDB, the GNU debugger.
- Copyright 1997 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 2 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, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-extern int
-java_parse PARAMS ((void)); /* Defined in java-exp.y */
-
-extern void
-java_error PARAMS ((char *)); /* Defined in java-exp.y */
-
-#define JAVA_OBJECT_SIZE (6 * 4) /* sizeof (struct Object) FIXME ! */
-
-extern struct type *java_int_type;
-extern struct type *java_byte_type;
-extern struct type *java_short_type;
-extern struct type *java_long_type;
-extern struct type *java_boolean_type;
-extern struct type *java_char_type;
-extern struct type *java_float_type;
-extern struct type *java_double_type;
-extern struct type *java_void_type;
-
-/* This objfile contains symtabs that have been dynamically created
- to record dynamically loaded Java classes and dynamically
- compiled java methods. */
-extern struct objfile *dynamics_objfile;
-
-extern int
-java_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int,
- int, enum val_prettyprint));
-
-extern int
-java_value_print PARAMS ((struct value *, GDB_FILE *, int,
- enum val_prettyprint));
-
-extern value_ptr java_class_from_object PARAMS ((value_ptr));
-
-extern struct type *type_from_class PARAMS ((struct value*));
-
-extern struct type *java_primitive_type PARAMS ((int));
-
-extern struct type *java_array_type PARAMS ((struct type*, int));
-
-extern struct type *get_java_object_type ();
-
-extern struct type * java_lookup_class PARAMS((char *));
-
-extern int is_object_type PARAMS ((struct type*));
+++ /dev/null
-/* Support for printing Java values for GDB, the GNU debugger.
- Copyright 1997 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 2 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, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "defs.h"
-#include "symtab.h"
-#include "gdbtypes.h"
-#include "expression.h"
-#include "value.h"
-#include "demangle.h"
-#include "valprint.h"
-#include "language.h"
-#include "java-lang.h"
-#include "c-lang.h"
-
-int
-java_value_print (val, stream, format, pretty)
- value_ptr val;
- GDB_FILE *stream;
- int format;
- enum val_prettyprint pretty;
-{
- struct type *type = VALUE_TYPE (val);
- if (TYPE_CODE (type) == TYPE_CODE_PTR)
- {
- fprintf_filtered (stream, "(");
- type_print (TYPE_TARGET_TYPE (type), "", stream, -1);
- fprintf_filtered (stream, ") ");
- }
- return (val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
- VALUE_ADDRESS (val) + VALUE_OFFSET (val),
- stream, format, 1, 0, pretty));
-}
-
-int
-java_val_print (type, valaddr, address, stream, format, deref_ref, recurse,
- pretty)
- struct type *type;
- char *valaddr;
- CORE_ADDR address;
- GDB_FILE *stream;
- int format;
- int deref_ref;
- int recurse;
- enum val_prettyprint pretty;
-{
- if (is_object_type (type))
- {
- CORE_ADDR obj_addr = unpack_pointer (type, valaddr);
- if (obj_addr != 0)
- {
- value_ptr obj_val
- = value_at (TYPE_TARGET_TYPE (type), obj_addr, NULL);
- type = type_from_class (java_class_from_object (obj_val));
- type = lookup_pointer_type (type);
- }
- }
- return c_val_print (type, valaddr, address, stream, format,
- deref_ref, recurse, pretty);
-}
--- /dev/null
+/* YACC parser for Java expressions, for GDB.
+ Copyright (C) 1997.
+ 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 2 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, write to the Free Software
+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.
+ 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.
+
+ 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 "gdb_string.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 */
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+ as well as gratuitiously global symbol names, so we can have multiple
+ yacc generated parsers in gdb. Note that these are only the variables
+ produced by yacc. If other parser generators (bison, byacc, etc) produce
+ additional global names that conflict at link time, then those parser
+ generators need to be fixed instead of adding those names to this list. */
+
+#define yymaxdepth java_maxdepth
+#define yyparse java_parse
+#define yylex java_lex
+#define yyerror java_error
+#define yylval java_lval
+#define yychar java_char
+#define yydebug java_debug
+#define yypact java_pact
+#define yyr1 java_r1
+#define yyr2 java_r2
+#define yydef java_def
+#define yychk java_chk
+#define yypgo java_pgo
+#define yyact java_act
+#define yyexca java_exca
+#define yyerrflag java_errflag
+#define yynerrs java_nerrs
+#define yyps java_ps
+#define yypv java_pv
+#define yys java_s
+#define yy_yys java_yys
+#define yystate java_state
+#define yytmp java_tmp
+#define yyv java_v
+#define yy_yyv java_yyv
+#define yyval java_val
+#define yylloc java_lloc
+#define yyreds java_reds /* With YYDEBUG defined */
+#define yytoks java_toks /* With YYDEBUG defined */
+#define yylhs java_yylhs
+#define yylen java_yylen
+#define yydefred java_yydefred
+#define yydgoto java_yydgoto
+#define yysindex java_yysindex
+#define yyrindex java_yyrindex
+#define yygindex java_yygindex
+#define yytable java_yytable
+#define yycheck java_yycheck
+
+#ifndef YYDEBUG
+#define YYDEBUG 0 /* Default to no yydebug support */
+#endif
+
+int
+yyparse PARAMS ((void));
+
+static int
+yylex PARAMS ((void));
+
+void
+yyerror PARAMS ((char *));
+
+static struct type * java_type_from_name PARAMS ((struct stoken));
+static void push_variable PARAMS ((struct stoken));
+
+%}
+
+/* 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 PARAMS ((char *, int, int, YYSTYPE *));
+%}
+
+%type <lval> rcurly Dims Dims_opt
+%type <tval> ClassOrInterfaceType ClassType /* ReferenceType Type ArrayType */
+%type <tval> IntegralType FloatingPointType NumericType PrimitiveType
+
+%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 THIS 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 '.' '[' '('
+
+\f
+%%
+
+start : exp1
+/* | type_exp FIXME */
+ ;
+
+StringLiteral:
+ STRING_LITERAL
+ {
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_STRING);
+ }
+;
+
+Literal :
+ INTEGER_LITERAL
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_longcst ((LONGEST)($1.val));
+ write_exp_elt_opcode (OP_LONG); }
+| NAME_OR_INT
+ { YYSTYPE val;
+ parse_number ($1.ptr, $1.length, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (val.typed_val_int.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
+ write_exp_elt_opcode (OP_LONG);
+ }
+| FLOATING_POINT_LITERAL
+ { write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_dblcst ($1.dval);
+ write_exp_elt_opcode (OP_DOUBLE); }
+| BOOLEAN_LITERAL
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (java_boolean_type);
+ write_exp_elt_longcst ((LONGEST)$1);
+ write_exp_elt_opcode (OP_LONG); }
+| StringLiteral
+ ;
+
+/* UNUSED:
+Type:
+ PrimitiveType
+| ReferenceType
+;
+*/
+
+PrimitiveType:
+ NumericType
+| BOOLEAN
+ { $$ = java_boolean_type; }
+;
+
+NumericType:
+ IntegralType
+| FloatingPointType
+;
+
+IntegralType:
+ BYTE
+ { $$ = java_byte_type; }
+| SHORT
+ { $$ = java_short_type; }
+| INT
+ { $$ = java_int_type; }
+| LONG
+ { $$ = java_long_type; }
+| CHAR
+ { $$ = java_char_type; }
+;
+
+FloatingPointType:
+ FLOAT
+ { $$ = java_float_type; }
+| DOUBLE
+ { $$ = java_double_type; }
+;
+
+/* UNUSED:
+ReferenceType:
+ ClassOrInterfaceType
+| ArrayType
+;
+*/
+
+ClassOrInterfaceType:
+ Name
+ { $$ = java_type_from_name ($1); }
+;
+
+ClassType:
+ ClassOrInterfaceType
+;
+
+/* UNUSED:
+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
+ {
+ $$.ptr = (char *) malloc ($$.length + 1);
+ make_cleanup (free, $$.ptr);
+ sprintf ($$.ptr, "%.*s.%.*s",
+ $1.length, $1.ptr, $3.length, $3.ptr);
+ } }
+;
+
+/*
+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 (BINOP_COMMA); }
+ ;
+
+Primary:
+ PrimaryNoNewArray
+| ArrayCreationExpression
+;
+
+PrimaryNoNewArray:
+ Literal
+| THIS
+ { write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS); }
+| '(' Expression ')'
+| ClassInstanceCreationExpression
+| FieldAccess
+| MethodInvocation
+| ArrayAccess
+| lcurly ArgumentList rcurly
+ { write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) $3);
+ write_exp_elt_opcode (OP_ARRAY); }
+;
+
+lcurly:
+ '{'
+ { start_arglist (); }
+;
+
+rcurly:
+ '}'
+ { $$ = end_arglist () - 1; }
+;
+
+ClassInstanceCreationExpression:
+ NEW ClassType '(' ArgumentList_opt ')'
+ { error ("FIXME - ClassInstanceCreationExpression"); }
+;
+
+ArgumentList:
+ Expression
+ { arglist_len = 1; }
+| ArgumentList ',' Expression
+ { arglist_len++; }
+;
+
+ArgumentList_opt:
+ /* EMPTY */
+ { arglist_len = 0; }
+| ArgumentList
+;
+
+ArrayCreationExpression:
+ NEW PrimitiveType DimExprs Dims_opt
+ { error ("FIXME - ArrayCreatiionExpression"); }
+| NEW ClassOrInterfaceType DimExprs Dims_opt
+ { error ("FIXME - ArrayCreatiionExpression"); }
+;
+
+DimExprs:
+ DimExpr
+| DimExprs DimExpr
+;
+
+DimExpr:
+ '[' Expression ']'
+;
+
+Dims:
+ '[' ']'
+ { $$ = 1; }
+| Dims '[' ']'
+ { $$ = $1 + 1; }
+;
+
+Dims_opt:
+ Dims
+| /* EMPTY */
+ { $$ = 0; }
+;
+
+FieldAccess:
+ Primary '.' SimpleName
+ { write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string ($3);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); }
+/*| SUPER '.' SimpleName { FIXME } */
+;
+
+MethodInvocation:
+ Name '(' ArgumentList_opt ')'
+ { error ("method invocation not implemented"); }
+| Primary '.' SimpleName '(' ArgumentList_opt ')'
+ { error ("method invocation not implemented"); }
+| SUPER '.' SimpleName '(' ArgumentList_opt ')'
+ { error ("method invocation not implemented"); }
+;
+
+ArrayAccess:
+ Name '[' Expression ']'
+ { error ("ArrayAccess"); } /* FIXME - NASTY */
+| PrimaryNoNewArray '[' Expression ']'
+ { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
+;
+
+PostfixExpression:
+ Primary
+| Name
+ { push_variable ($1); }
+| VARIABLE
+ /* Already written by write_dollar_variable. */
+| PostIncrementExpression
+| PostDecrementExpression
+;
+
+PostIncrementExpression:
+ PostfixExpression INCREMENT
+ { write_exp_elt_opcode (UNOP_POSTINCREMENT); }
+;
+
+PostDecrementExpression:
+ PostfixExpression DECREMENT
+ { write_exp_elt_opcode (UNOP_POSTDECREMENT); }
+;
+
+UnaryExpression:
+ PreIncrementExpression
+| PreDecrementExpression
+| '+' UnaryExpression
+| '-' UnaryExpression
+ { write_exp_elt_opcode (UNOP_NEG); }
+| '*' UnaryExpression
+ { write_exp_elt_opcode (UNOP_IND); } /*FIXME not in Java */
+| UnaryExpressionNotPlusMinus
+;
+
+PreIncrementExpression:
+ INCREMENT UnaryExpression
+ { write_exp_elt_opcode (UNOP_PREINCREMENT); }
+;
+
+PreDecrementExpression:
+ DECREMENT UnaryExpression
+ { write_exp_elt_opcode (UNOP_PREDECREMENT); }
+;
+
+UnaryExpressionNotPlusMinus:
+ PostfixExpression
+| '~' UnaryExpression
+ { write_exp_elt_opcode (UNOP_COMPLEMENT); }
+| '!' UnaryExpression
+ { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
+| CastExpression
+ ;
+
+CastExpression:
+ '(' PrimitiveType Dims_opt ')' UnaryExpression
+ { write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (java_array_type ($2, $3));
+ write_exp_elt_opcode (UNOP_CAST); }
+| '(' Expression ')' UnaryExpressionNotPlusMinus /* FIXME */
+| '(' Name Dims ')' UnaryExpressionNotPlusMinus
+ { write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (java_array_type (java_type_from_name ($2), $3));
+ write_exp_elt_opcode (UNOP_CAST); }
+;
+
+
+MultiplicativeExpression:
+ UnaryExpression
+| MultiplicativeExpression '*' UnaryExpression
+ { write_exp_elt_opcode (BINOP_MUL); }
+| MultiplicativeExpression '/' UnaryExpression
+ { write_exp_elt_opcode (BINOP_DIV); }
+| MultiplicativeExpression '%' UnaryExpression
+ { write_exp_elt_opcode (BINOP_REM); }
+;
+
+AdditiveExpression:
+ MultiplicativeExpression
+| AdditiveExpression '+' MultiplicativeExpression
+ { write_exp_elt_opcode (BINOP_ADD); }
+| AdditiveExpression '-' MultiplicativeExpression
+ { write_exp_elt_opcode (BINOP_SUB); }
+;
+
+ShiftExpression:
+ AdditiveExpression
+| ShiftExpression LSH AdditiveExpression
+ { write_exp_elt_opcode (BINOP_LSH); }
+| ShiftExpression RSH AdditiveExpression
+ { write_exp_elt_opcode (BINOP_RSH); }
+/* | ShiftExpression >>> AdditiveExpression { FIXME } */
+;
+
+RelationalExpression:
+ ShiftExpression
+| RelationalExpression '<' ShiftExpression
+ { write_exp_elt_opcode (BINOP_LESS); }
+| RelationalExpression '>' ShiftExpression
+ { write_exp_elt_opcode (BINOP_GTR); }
+| RelationalExpression LEQ ShiftExpression
+ { write_exp_elt_opcode (BINOP_LEQ); }
+| RelationalExpression GEQ ShiftExpression
+ { write_exp_elt_opcode (BINOP_GEQ); }
+/* | RelationalExpresion INSTANCEOF ReferenceType { FIXME } */
+;
+
+EqualityExpression:
+ RelationalExpression
+| EqualityExpression EQUAL RelationalExpression
+ { write_exp_elt_opcode (BINOP_EQUAL); }
+| EqualityExpression NOTEQUAL RelationalExpression
+ { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+;
+
+AndExpression:
+ EqualityExpression
+| AndExpression '&' EqualityExpression
+ { write_exp_elt_opcode (BINOP_BITWISE_AND); }
+;
+
+ExclusiveOrExpression:
+ AndExpression
+| ExclusiveOrExpression '^' AndExpression
+ { write_exp_elt_opcode (BINOP_BITWISE_XOR); }
+;
+InclusiveOrExpression:
+ ExclusiveOrExpression
+| InclusiveOrExpression '|' ExclusiveOrExpression
+ { write_exp_elt_opcode (BINOP_BITWISE_IOR); }
+;
+
+ConditionalAndExpression:
+ InclusiveOrExpression
+| ConditionalAndExpression ANDAND InclusiveOrExpression
+ { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+;
+
+ConditionalOrExpression:
+ ConditionalAndExpression
+| ConditionalOrExpression OROR ConditionalAndExpression
+ { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
+;
+
+ConditionalExpression:
+ ConditionalOrExpression
+| ConditionalOrExpression '?' Expression ':' ConditionalExpression
+ { write_exp_elt_opcode (TERNOP_COND); }
+;
+
+AssignmentExpression:
+ ConditionalExpression
+| Assignment
+;
+
+Assignment:
+ LeftHandSide '=' ConditionalExpression
+ { write_exp_elt_opcode (BINOP_ASSIGN); }
+| LeftHandSide ASSIGN_MODIFY ConditionalExpression
+ { write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode ($2);
+ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
+;
+
+LeftHandSide:
+ ForcedName
+ { push_variable ($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 (p, len, parsed_float, putithere)
+ register char *p;
+ register int len;
+ int parsed_float;
+ YYSTYPE *putithere;
+{
+ register ULONGEST n = 0;
+ ULONGEST limit, limit_div_base;
+
+ register int c;
+ register int base = input_radix;
+
+ struct type *type;
+
+ if (parsed_float)
+ {
+ /* It's a float since it contains a point or an exponent. */
+ char c;
+ int num = 0; /* number of tokens scanned by scanf */
+ 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
+ }
+ p[len] = saved_char; /* restore the input stream */
+ if (num != 1) /* check scanf found ONLY a float ... */
+ return ERROR;
+ /* See if it has `f' or `d' suffix (float or double). */
+
+ c = tolower (p[len - 1]);
+
+ if (c == 'f' || c == 'F')
+ putithere->typed_val_float.type = builtin_type_float;
+ else if (isdigit (c) || c == '.' || c == 'd' || c == 'D')
+ putithere->typed_val_float.type = builtin_type_double;
+ 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];
+ limit = (ULONGEST)0xffffffff;
+ if (c == 'l' || c == 'L')
+ {
+ type = java_long_type;
+ len--;
+ /* A paranoid calculation of (1<<64)-1. */
+ limit = ((limit << 16) << 16) | limit;
+ }
+ else
+ {
+ type = java_int_type;
+ }
+ 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' - 'A';
+ if (c >= 'a' && c - 'a' + 10 < base)
+ 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;
+ }
+
+ putithere->typed_val_int.val = n;
+ putithere->typed_val_int.type = type;
+ return INTEGER_LITERAL;
+}
+
+struct token
+{
+ char *operator;
+ 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 ()
+{
+ int c;
+ int namelen;
+ unsigned int i;
+ char *tokstart;
+ char *tokptr;
+ int tempbufindex;
+ static char *tempbuf;
+ static int tempbufsize;
+
+ retry:
+
+ 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))
+ {
+ 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 (STREQN (tokstart, tokentab2[i].operator, 2))
+ {
+ 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 (&lexptr);
+ else if (c == '\'')
+ error ("Empty character constant.");
+
+ yylval.typed_val_int.val = c;
+ yylval.typed_val_int.type = builtin_type_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;
+ register 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 (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 (&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 (STREQN (tokstart, "boolean", 7))
+ return BOOLEAN;
+ break;
+ case 6:
+ if (STREQN (tokstart, "double", 6))
+ return DOUBLE;
+ break;
+ case 5:
+ if (STREQN (tokstart, "short", 5))
+ return SHORT;
+ if (STREQN (tokstart, "false", 5))
+ {
+ yylval.lval = 0;
+ return BOOLEAN_LITERAL;
+ }
+ if (STREQN (tokstart, "super", 5))
+ return SUPER;
+ if (STREQN (tokstart, "float", 5))
+ return FLOAT;
+ break;
+ case 4:
+ if (STREQN (tokstart, "long", 4))
+ return LONG;
+ if (STREQN (tokstart, "byte", 4))
+ return BYTE;
+ if (STREQN (tokstart, "char", 4))
+ return CHAR;
+ if (STREQN (tokstart, "true", 4))
+ {
+ 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))
+ return INT;
+ if (STREQN (tokstart, "new", 3))
+ return NEW;
+ break;
+ default:
+ break;
+ }
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ if (*tokstart == '$')
+ {
+ write_dollar_variable (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 (tokstart, namelen, 0, &newlval);
+ if (hextype == INTEGER_LITERAL)
+ return NAME_OR_INT;
+ }
+ return IDENTIFIER;
+}
+
+void
+yyerror (msg)
+ char *msg;
+{
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
+
+static struct type *
+java_type_from_name (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;
+}
+
+static void
+push_variable (name)
+ struct stoken name;
+
+{
+ char *tmp = copy_name (name);
+ int is_a_field_of_this = 0;
+ struct symbol *sym;
+ struct type *typ;
+ sym = lookup_symbol (tmp, expression_context_block, VAR_NAMESPACE,
+ &is_a_field_of_this, (struct symtab **) NULL);
+ if (sym)
+ {
+ if (symbol_read_needs_frame (sym))
+ {
+ if (innermost_block == 0 ||
+ contained_in (block_found, innermost_block))
+ innermost_block = block_found;
+ }
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* We want to use the selected frame, not another more inner frame
+ which happens to be in the same block. */
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ return;
+ }
+ if (is_a_field_of_this)
+ {
+ /* it hangs off of `this'. Must not inadvertently convert from a
+ method call to data ref. */
+ if (innermost_block == 0 ||
+ contained_in (block_found, innermost_block))
+ innermost_block = block_found;
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ write_exp_string (name);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ return;
+ }
+
+ typ = java_lookup_class (tmp);
+ if (typ != NULL)
+ {
+ write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type(typ);
+ write_exp_elt_opcode(OP_TYPE);
+ }
+ else
+ {
+ struct minimal_symbol *msymbol;
+
+ msymbol = lookup_minimal_symbol (tmp, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ 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);
+ }
+
+}
--- /dev/null
+/* Java language support routines for GDB, the GNU debugger.
+ Copyright 1997 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 2 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, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "gdbtypes.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb_string.h"
+#include "value.h"
+#include "c-lang.h"
+#include "jv-lang.h"
+#include "gdbcore.h"
+
+struct type *java_int_type;
+struct type *java_byte_type;
+struct type *java_short_type;
+struct type *java_long_type;
+struct type *java_boolean_type;
+struct type *java_char_type;
+struct type *java_float_type;
+struct type *java_double_type;
+struct type *java_void_type;
+
+struct type *java_object_type;
+
+/* This objfile contains symtabs that have been dynamically created
+ to record dynamically loaded Java classes and dynamically
+ compiled java methods. */
+struct objfile *dynamics_objfile = NULL;
+
+struct type *java_link_class_type PARAMS((struct type*, value_ptr));
+
+struct objfile *
+get_dynamics_objfile ()
+{
+ if (dynamics_objfile == NULL)
+ {
+ dynamics_objfile = allocate_objfile (NULL, 0);
+ }
+ return dynamics_objfile;
+}
+
+#if 1
+/* symtab contains classes read from the inferior. */
+
+static struct symtab *class_symtab = NULL;
+
+/* Maximum number of class in class_symtab before relocation is needed. */
+
+static int class_symtab_space;
+
+struct symtab *
+get_java_class_symtab ()
+{
+ if (class_symtab == NULL)
+ {
+ struct objfile *objfile = get_dynamics_objfile();
+ struct blockvector *bv;
+ struct block *bl;
+ class_symtab = allocate_symtab ("<java-classes>", objfile);
+ class_symtab->language = language_java;
+ bv = (struct blockvector *)
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct blockvector));
+ BLOCKVECTOR_NBLOCKS (bv) = 1;
+ BLOCKVECTOR (class_symtab) = bv;
+
+ /* Allocate dummy STATIC_BLOCK. */
+ bl = (struct block *)
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
+ BLOCK_NSYMS (bl) = 0;
+ BLOCK_START (bl) = 0;
+ BLOCK_END (bl) = 0;
+ BLOCK_FUNCTION (bl) = NULL;
+ BLOCK_SUPERBLOCK (bl) = NULL;
+ BLOCK_GCC_COMPILED (bl) = 0;
+ BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
+
+ /* Allocate GLOBAL_BLOCK. This has to be relocatable. */
+ class_symtab_space = 128;
+ bl = (struct block *)
+ mmalloc (objfile->md,
+ sizeof (struct block)
+ + ((class_symtab_space - 1) * sizeof (struct symbol *)));
+ *bl = *BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
+ class_symtab->free_ptr = (char *) bl;
+ }
+ return class_symtab;
+}
+
+static void
+add_class_symtab_symbol (sym)
+ struct symbol *sym;
+{
+ struct symtab *symtab = get_java_class_symtab ();
+ struct blockvector *bv = BLOCKVECTOR (symtab);
+ struct block *bl = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ if (BLOCK_NSYMS (bl) >= class_symtab_space)
+ {
+ /* Need to re-allocate. */
+ class_symtab_space *= 2;
+ bl = (struct block *)
+ mrealloc (symtab->objfile->md, bl,
+ sizeof (struct block)
+ + ((class_symtab_space - 1) * sizeof (struct symbol *)));
+ class_symtab->free_ptr = (char *) bl;
+ BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
+ }
+
+ BLOCK_SYM (bl, BLOCK_NSYMS (bl)) = sym;
+ BLOCK_NSYMS (bl) = BLOCK_NSYMS (bl) + 1;
+}
+
+struct symbol *
+add_class_symbol (type, addr)
+ struct type *type;
+ CORE_ADDR addr;
+{
+ struct symbol *sym;
+ sym = (struct symbol *)
+ obstack_alloc (&dynamics_objfile->symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_LANGUAGE (sym) = language_java;
+ SYMBOL_NAME (sym) = TYPE_NAME (type);
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ /* SYMBOL_VALUE (sym) = valu;*/
+ SYMBOL_TYPE (sym) = type;
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ SYMBOL_VALUE_ADDRESS (sym) = addr;
+ return sym;
+}
+#endif
+
+struct type *
+java_lookup_class (name)
+ char *name;
+{
+ struct symbol *sym;
+ sym = lookup_symbol (name, expression_context_block, STRUCT_NAMESPACE,
+ (int *) 0, (struct symtab **) NULL);
+ if (sym != NULL)
+ return SYMBOL_TYPE (sym);
+#if 0
+ CORE_ADDR addr;
+ if (called from parser)
+ {
+ call lookup_class (or similar) in inferior;
+ if not found:
+ return NULL;
+ addr = found in inferior;
+ }
+ else
+ addr = 0;
+ struct type *type;
+ type = alloc_type (objfile);
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ INIT_CPLUS_SPECIFIC (type);
+ TYPE_NAME (type) = obsavestring (name, strlen(name), &objfile->type_obstack);
+ TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+ TYPE ? = addr;
+ return type;
+#else
+ /* FIXME - should search inferior's symbol table. */
+ return NULL;
+#endif
+}
+
+/* Return a nul-terminated string (allocated on OBSTACK) for
+ a name given by NAME (which has type Utf8Const*). */
+
+char *
+get_java_utf8_name (obstack, name)
+ struct obstack *obstack;
+ value_ptr name;
+{
+ char *chrs;
+ value_ptr temp = name;
+ int name_length = (int) value_as_long
+ (value_struct_elt (&temp, NULL, "length", NULL, "structure"));
+ temp = name;
+ temp = value_struct_elt (&temp, NULL, "data", NULL, "structure");
+ chrs = obstack_alloc (obstack, name_length+1);
+ chrs [name_length] = '\0';
+ read_memory_section (VALUE_ADDRESS (temp) + VALUE_OFFSET (temp),
+ chrs, name_length, NULL);
+ return chrs;
+}
+
+value_ptr
+java_class_from_object (obj_val)
+ value_ptr obj_val;
+{
+ value_ptr dtable_val = value_struct_elt (&obj_val, NULL, "dtable", NULL, "structure");
+ return value_struct_elt (&dtable_val, NULL, "class", NULL, "structure");
+}
+
+/* Check if CLASS_IS_PRIMITIVE(value of clas): */
+int
+java_class_is_primitive (clas)
+ value_ptr clas;
+{
+ value_ptr dtable = value_struct_elt (&clas, NULL, "dtable", NULL, "struct");
+ CORE_ADDR i = value_as_pointer (dtable);
+ return (int) (i & 0x7fffffff) == (int) 0x7fffffff;
+}
+
+/* Read a Kaffe Class object, and generated a gdb (TYPE_CODE_STRUCT) type. */
+
+struct type *
+type_from_class (clas)
+ value_ptr clas;
+{
+ struct type *type;
+ char *name;
+ value_ptr temp;
+ struct objfile *objfile = get_dynamics_objfile();
+ value_ptr utf8_name;
+ char *nptr;
+ CORE_ADDR addr;
+ struct block *bl;
+ int i;
+ int is_array = 0;
+
+ type = check_typedef (VALUE_TYPE (clas));
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ {
+ if (value_logical_not (clas))
+ return NULL;
+ clas = value_ind (clas);
+ }
+ addr = VALUE_ADDRESS (clas) + VALUE_OFFSET (clas);
+
+ get_java_class_symtab ();
+ bl = BLOCKVECTOR_BLOCK (BLOCKVECTOR (class_symtab), GLOBAL_BLOCK);
+ for (i = BLOCK_NSYMS (bl); --i >= 0; )
+ {
+ struct symbol *sym = BLOCK_SYM (bl, i);
+ if (SYMBOL_VALUE_ADDRESS (sym) == addr)
+ return SYMBOL_TYPE (sym);
+ }
+
+ if (java_class_is_primitive (clas))
+ {
+ value_ptr sig;
+ temp = clas;
+ sig = value_struct_elt (&temp, NULL, "msize", NULL, "structure");
+ return java_primitive_type (value_as_long (sig));
+ }
+
+ /* Get Class name. */
+ /* if clasloader non-null, prepend loader address. FIXME */
+ temp = clas;
+ utf8_name = value_struct_elt (&temp, NULL, "name", NULL, "structure");
+ name = get_java_utf8_name (&objfile->type_obstack, utf8_name);
+
+ type = alloc_type (objfile);
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ INIT_CPLUS_SPECIFIC (type);
+
+ if (name[0] == '[')
+ {
+ is_array = 1;
+ temp = clas;
+ /* Set array element type. */
+ temp = value_struct_elt (&temp, NULL, "methods", NULL, "structure");
+ VALUE_TYPE (temp) = lookup_pointer_type (VALUE_TYPE (clas));
+ TYPE_TARGET_TYPE (type) = type_from_class (temp);
+ }
+ for (nptr = name; *nptr != 0; nptr++)
+ {
+ if (*nptr == '/')
+ *nptr = '.';
+ }
+
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ TYPE_NAME (type) = name;
+
+ add_class_symtab_symbol (add_class_symbol (type, addr));
+ return java_link_class_type (type, clas);
+}
+
+/* Fill in class TYPE with data from the CLAS value. */
+
+struct type *
+java_link_class_type (type, clas)
+ struct type *type;
+ value_ptr clas;
+{
+ value_ptr temp;
+ char *unqualified_name;
+ char *name = TYPE_NAME (type);
+ int ninterfaces, nfields, nmethods;
+ int type_is_object = 0;
+ struct fn_field *fn_fields;
+ struct fn_fieldlist *fn_fieldlists;
+ value_ptr fields, field, method, methods;
+ int i, j;
+ struct objfile *objfile = get_dynamics_objfile();
+ struct type *tsuper;
+
+ unqualified_name = strrchr (name, '.');
+ if (unqualified_name == NULL)
+ unqualified_name = name;
+
+ temp = clas;
+ temp = value_struct_elt (&temp, NULL, "superclass", NULL, "structure");
+ if (name != NULL && strcmp (name, "java.lang.Object") == 0)
+ {
+ tsuper = get_java_object_type ();
+ if (tsuper && TYPE_CODE (tsuper) == TYPE_CODE_PTR)
+ tsuper = TYPE_TARGET_TYPE (tsuper);
+ type_is_object = 1;
+ }
+ else
+ tsuper = type_from_class (temp);
+
+#if 1
+ ninterfaces = 0;
+#else
+ temp = clas;
+ ninterfaces = value_as_long (value_struct_elt (&temp, NULL, "interface_len", NULL, "structure"));
+#endif
+ TYPE_N_BASECLASSES (type) = (tsuper == NULL ? 0 : 1) + ninterfaces;
+ temp = clas;
+ nfields = value_as_long (value_struct_elt (&temp, NULL, "nfields", NULL, "structure"));
+ nfields += TYPE_N_BASECLASSES (type);
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, sizeof (struct field) * nfields);
+
+ memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
+
+ TYPE_FIELD_PRIVATE_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
+
+ TYPE_FIELD_PROTECTED_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
+
+ TYPE_FIELD_IGNORE_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
+
+ TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *)
+ TYPE_ALLOC (type, B_BYTES (TYPE_N_BASECLASSES (type)));
+ B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), TYPE_N_BASECLASSES (type));
+
+ if (tsuper != NULL)
+ {
+ TYPE_BASECLASS (type, 0) = tsuper;
+ if (type_is_object)
+ SET_TYPE_FIELD_PRIVATE (type, 0);
+ }
+
+
+ temp = clas;
+ temp = value_struct_elt (&temp, NULL, "bfsize", NULL, "structure");
+ TYPE_LENGTH (type) = JAVA_OBJECT_SIZE + value_as_long (temp);
+
+ fields = NULL;
+ for (i = TYPE_N_BASECLASSES (type); i < nfields; i++)
+ {
+ int accflags;
+ int boffset;
+ if (fields == NULL)
+ {
+ temp = clas;
+ fields = value_struct_elt (&temp, NULL, "fields", NULL, "structure");
+ field = value_ind (fields);
+ }
+ else
+ { /* Re-use field value for next field. */
+ VALUE_ADDRESS (field) += TYPE_LENGTH (VALUE_TYPE (field));
+ VALUE_LAZY (field) = 1;
+ }
+ temp = field;
+ temp = value_struct_elt (&temp, NULL, "name", NULL, "structure");
+ TYPE_FIELD_NAME (type, i) =
+ get_java_utf8_name (&objfile->type_obstack, temp);
+ temp = field;
+ accflags = value_as_long (value_struct_elt (&temp, NULL, "accflags",
+ NULL, "structure"));
+ boffset = value_as_long (value_struct_elt (&temp, NULL, "boffset",
+ NULL, "structure"));
+ if (accflags & 0x0001) /* public access */
+ {
+ /* ??? */
+ }
+ if (accflags & 0x0002) /* private access */
+ {
+ SET_TYPE_FIELD_PRIVATE (type, i);
+ }
+ if (accflags & 0x0004) /* protected access */
+ {
+ SET_TYPE_FIELD_PROTECTED (type, i);
+ }
+ if (accflags & 0x0008) /* ACC_STATIC */
+ {
+ TYPE_FIELD_BITPOS (type, i) = -1;
+ /* Hack for TYPE_FIELD_STATIC_PHYSNAME to prevent a crash. FIXME. */
+ type->fields[i].bitsize = (long) "???";
+ }
+ else
+ TYPE_FIELD_BITPOS (type, i) = 8 * (JAVA_OBJECT_SIZE + boffset);
+ if (accflags & 0x8000) /* FIELD_UNRESOLVED_FLAG */
+ {
+ TYPE_FIELD_TYPE (type, i) = get_java_object_type (); /* FIXME */
+ }
+ else
+ {
+ struct type *ftype;
+ temp = field;
+ temp = value_struct_elt (&temp, NULL, "type", NULL, "structure");
+ ftype = type_from_class (temp);
+ if (TYPE_CODE (ftype) == TYPE_CODE_STRUCT)
+ ftype = lookup_pointer_type (ftype);
+ TYPE_FIELD_TYPE (type, i) = ftype;
+ }
+ }
+
+ temp = clas;
+ nmethods = value_as_long (value_struct_elt (&temp, NULL, "nmethods",
+ NULL, "structure"));
+ TYPE_NFN_FIELDS_TOTAL (type) = nmethods;
+ j = nmethods * sizeof (struct fn_field);
+ fn_fields = (struct fn_field*)
+ obstack_alloc (&dynamics_objfile->symbol_obstack, j);
+ memset (fn_fields, 0, j);
+ fn_fieldlists = (struct fn_fieldlist*)
+ alloca (nmethods * sizeof (struct fn_fieldlist));
+
+ methods = NULL;
+ for (i = 0; i < nmethods; i++)
+ {
+ char *mname;
+ int k;
+ if (methods == NULL)
+ {
+ temp = clas;
+ methods = value_struct_elt (&temp, NULL, "methods", NULL, "structure");
+ method = value_ind (methods);
+ }
+ else
+ { /* Re-use method value for next method. */
+ VALUE_ADDRESS (method) += TYPE_LENGTH (VALUE_TYPE (method));
+ VALUE_LAZY (method) = 1;
+ }
+
+ /* Get method name. */
+ temp = method;
+ temp = value_struct_elt (&temp, NULL, "name", NULL, "structure");
+ mname = get_java_utf8_name (&objfile->type_obstack, temp);
+ if (strcmp (mname, "<init>") == 0)
+ mname = unqualified_name;
+
+ /* Check for an existing method with the same name.
+ * This makes building the fn_fieldslists an O(nmethods**2)
+ * operation. That could be using hashing, but I doubt it
+ * is worth it. Note that we do maintain the order of methods
+ * in the inferior's Method table (as long as that is grouped
+ * by method name), which I think is desirable. --PB */
+ for (k = 0, j = TYPE_NFN_FIELDS (type); ; )
+ {
+ if (--j < 0)
+ { /* No match - new method name. */
+ j = TYPE_NFN_FIELDS(type)++;
+ fn_fieldlists[j].name = mname;
+ fn_fieldlists[j].length = 1;
+ fn_fieldlists[j].fn_fields = &fn_fields[i];
+ k = i;
+ break;
+ }
+ if (strcmp (mname, fn_fieldlists[j].name) == 0)
+ { /* Found an existing method with the same name. */
+ int l;
+ if (mname != unqualified_name)
+ obstack_free (&objfile->type_obstack, mname);
+ mname = fn_fieldlists[j].name;
+ fn_fieldlists[j].length++;
+ k = i - k; /* Index of new slot. */
+ /* Shift intervening fn_fields (between k and i) down. */
+ for (l = i; l > k; l--) fn_fields[l] = fn_fields[l-1];
+ for (l = TYPE_NFN_FIELDS (type); --l > j; )
+ fn_fieldlists[l].fn_fields++;
+ break;
+ }
+ k += fn_fieldlists[j].length;
+ }
+ fn_fields[k].physname = "";
+ fn_fields[k].is_stub = 1;
+ fn_fields[k].type = make_function_type (java_void_type, NULL); /* FIXME*/
+ TYPE_CODE (fn_fields[k].type) = TYPE_CODE_METHOD;
+ }
+
+ j = TYPE_NFN_FIELDS(type) * sizeof (struct fn_fieldlist);
+ TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist*)
+ obstack_alloc (&dynamics_objfile->symbol_obstack, j);
+ memcpy (TYPE_FN_FIELDLISTS (type), fn_fieldlists, j);
+
+ return type;
+}
+
+struct type*
+get_java_object_type ()
+{
+ return java_object_type;
+}
+
+int
+is_object_type (type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ {
+ struct type *ttype = check_typedef (TYPE_TARGET_TYPE (type));
+ char *name;
+ if (TYPE_CODE (ttype) != TYPE_CODE_STRUCT)
+ return 0;
+ while (TYPE_N_BASECLASSES (ttype) > 0)
+ ttype = TYPE_BASECLASS (ttype, 0);
+ name = TYPE_NAME (ttype);
+ if (name != NULL && strcmp (name, "java.lang.Object") == 0)
+ return 1;
+ name = TYPE_NFIELDS (ttype) > 0 ? TYPE_FIELD_NAME (ttype, 0) : (char*)0;
+ if (name != NULL && strcmp (name, "dtable") == 0)
+ {
+ if (java_object_type == NULL)
+ java_object_type = type;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+struct type*
+java_primitive_type (signature)
+ int signature;
+{
+ switch (signature)
+ {
+ case 'B': return java_byte_type;
+ case 'S': return java_short_type;
+ case 'I': return java_int_type;
+ case 'J': return java_long_type;
+ case 'Z': return java_boolean_type;
+ case 'C': return java_char_type;
+ case 'F': return java_float_type;
+ case 'D': return java_double_type;
+ case 'V': return java_void_type;
+ }
+ error ("unknown signature '%c' for primitive type", (char) signature);
+}
+
+/* Return the type of TYPE followed by DIMS pairs of [ ].
+ If DIMS == 0, TYPE is returned. */
+
+struct type *
+java_array_type (type, dims)
+ struct type *type;
+ int dims;
+{
+ if (dims == 0)
+ return type;
+ error ("array types not implemented");
+}
+
+/* Create a Java string in the inferior from a (Utf8) literal. */
+
+value_ptr
+java_value_string (ptr, len)
+ char *ptr;
+ int len;
+{
+ error ("not implemented - java_value_string"); /* FIXME */
+}
+
+static value_ptr
+evaluate_subexp_java (expect_type, exp, pos, noside)
+ struct type *expect_type;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ int pc = *pos;
+ int i;
+ enum exp_opcode op = exp->elts[*pos].opcode;
+ value_ptr arg1;
+ switch (op)
+ {
+ case UNOP_IND:
+ if (noside == EVAL_SKIP)
+ goto standard;
+ (*pos)++;
+ arg1 = evaluate_subexp_standard (expect_type, exp, pos, EVAL_NORMAL);
+ if (is_object_type (VALUE_TYPE (arg1)))
+ {
+ struct type *type = type_from_class (java_class_from_object (arg1));
+ arg1 = value_cast (lookup_pointer_type (type), arg1);
+ }
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_ind (arg1);
+ case OP_STRING:
+ (*pos)++;
+ i = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (i + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return java_value_string (&exp->elts[pc + 2].string, i);
+ default:
+ break;
+ }
+standard:
+ return evaluate_subexp_standard (expect_type, exp, pos, noside);
+ nosideret:
+ return value_from_longest (builtin_type_long, (LONGEST) 1);
+}
+
+static struct type *
+java_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ switch (typeid)
+ {
+ case FT_VOID: return java_void_type;
+ case FT_BOOLEAN: return java_boolean_type;
+ case FT_CHAR: return java_char_type;
+ case FT_FLOAT: return java_float_type;
+ case FT_DBL_PREC_FLOAT: return java_double_type;
+ case FT_BYTE: case FT_SIGNED_CHAR: return java_byte_type;
+ case FT_SHORT: case FT_SIGNED_SHORT: return java_short_type;
+ case FT_INTEGER: case FT_SIGNED_INTEGER: return java_int_type;
+ case FT_LONG: case FT_SIGNED_LONG: return java_long_type;
+ }
+ return c_create_fundamental_type (objfile, typeid);
+}
+
+/* Table mapping opcodes into strings for printing operators
+ and precedences of the operators. */
+
+const struct op_print java_op_print_tab[] =
+ {
+ {",", BINOP_COMMA, PREC_COMMA, 0},
+ {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+ {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+ {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+ {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+ {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+ {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+ {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+ {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+ {"<=", BINOP_LEQ, PREC_ORDER, 0},
+ {">=", BINOP_GEQ, PREC_ORDER, 0},
+ {">", BINOP_GTR, PREC_ORDER, 0},
+ {"<", BINOP_LESS, PREC_ORDER, 0},
+ {">>", BINOP_RSH, PREC_SHIFT, 0},
+ {"<<", BINOP_LSH, PREC_SHIFT, 0},
+#if 0
+ {">>>", BINOP_???, PREC_SHIFT, 0},
+#endif
+ {"+", BINOP_ADD, PREC_ADD, 0},
+ {"-", BINOP_SUB, PREC_ADD, 0},
+ {"*", BINOP_MUL, PREC_MUL, 0},
+ {"/", BINOP_DIV, PREC_MUL, 0},
+ {"%", BINOP_REM, PREC_MUL, 0},
+ {"-", UNOP_NEG, PREC_PREFIX, 0},
+ {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+ {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+ {"*", UNOP_IND, PREC_PREFIX, 0},
+#if 0
+ {"instanceof", ???, ???, 0},
+#endif
+ {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+ {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+ {NULL, 0, 0, 0}
+};
+
+const struct language_defn java_language_defn = {
+ "java", /* Language name */
+ language_java,
+ c_builtin_types,
+ range_check_off,
+ type_check_off,
+ java_parse,
+ java_error,
+ evaluate_subexp_java,
+ c_printchar, /* Print a character constant */
+ c_printstr, /* Function to print string constant */
+ java_create_fundamental_type, /* Create fundamental type in this language */
+ java_print_type, /* Print a type using appropriate syntax */
+ java_val_print, /* Print a value using appropriate syntax */
+ java_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* Binary format info */
+ {"0%lo", "0", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0x%lx", "0x", "x", ""}, /* Hex format info */
+ java_op_print_tab, /* expression operators for printing */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+void
+_initialize_jave_language ()
+{
+
+ java_int_type = init_type (TYPE_CODE_INT, 4, 0, "int", NULL);
+ java_short_type = init_type (TYPE_CODE_INT, 2, 0, "short", NULL);
+ java_long_type = init_type (TYPE_CODE_INT, 8, 0, "long", NULL);
+ java_byte_type = init_type (TYPE_CODE_INT, 1, 0, "byte", NULL);
+ java_boolean_type= init_type (TYPE_CODE_BOOL, 1, 0, "boolean", NULL);
+ java_char_type = init_type (TYPE_CODE_CHAR, 2, 0, "char", NULL);
+ java_float_type = init_type (TYPE_CODE_FLT, 4, 0, "float", NULL);
+ java_double_type = init_type (TYPE_CODE_FLT, 8, 0, "double", NULL);
+ java_void_type = init_type (TYPE_CODE_VOID, 1, 0, "void", NULL);
+
+ add_language (&java_language_defn);
+}
+
+/* Cleanup code that should be urn on every "run".
+ We need some hook to have this actually be called ... FIXME */
+
+void java_rerun_cleanup ()
+{
+ if (class_symtab != NULL)
+ {
+ free_symtab (class_symtab); /* ??? */
+ class_symtab = NULL;
+ }
+ if (dynamics_objfile != NULL)
+ {
+ free_objfile (dynamics_objfile);
+ dynamics_objfile = NULL;
+ }
+
+ java_object_type = NULL;
+}
--- /dev/null
+/* Java language support definitions for GDB, the GNU debugger.
+ Copyright 1997 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 2 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, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern int
+java_parse PARAMS ((void)); /* Defined in jv-exp.y */
+
+extern void
+java_error PARAMS ((char *)); /* Defined in jv-exp.y */
+
+#define JAVA_OBJECT_SIZE (6 * 4) /* sizeof (struct Object) FIXME ! */
+
+extern struct type *java_int_type;
+extern struct type *java_byte_type;
+extern struct type *java_short_type;
+extern struct type *java_long_type;
+extern struct type *java_boolean_type;
+extern struct type *java_char_type;
+extern struct type *java_float_type;
+extern struct type *java_double_type;
+extern struct type *java_void_type;
+
+/* This objfile contains symtabs that have been dynamically created
+ to record dynamically loaded Java classes and dynamically
+ compiled java methods. */
+extern struct objfile *dynamics_objfile;
+
+extern int
+java_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int,
+ int, enum val_prettyprint));
+
+extern int
+java_value_print PARAMS ((struct value *, GDB_FILE *, int,
+ enum val_prettyprint));
+
+extern value_ptr java_class_from_object PARAMS ((value_ptr));
+
+extern struct type *type_from_class PARAMS ((struct value*));
+
+extern struct type *java_primitive_type PARAMS ((int));
+
+extern struct type *java_array_type PARAMS ((struct type*, int));
+
+extern struct type *get_java_object_type ();
+
+extern struct type * java_lookup_class PARAMS((char *));
+
+extern int is_object_type PARAMS ((struct type*));
+
+extern void /* Defined in jv-typeprint.c */
+java_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int));
--- /dev/null
+/* Support for printing Java types for GDB, the GNU debugger.
+ Copyright 1997 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 2 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, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+
+/* LEVEL is the depth to indent lines by. */
+
+void
+java_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ c_print_type (type, varstring, stream, show, level);
+}
--- /dev/null
+/* Support for printing Java values for GDB, the GNU debugger.
+ Copyright 1997 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 2 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, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "demangle.h"
+#include "valprint.h"
+#include "language.h"
+#include "jv-lang.h"
+#include "c-lang.h"
+
+int
+java_value_print (val, stream, format, pretty)
+ value_ptr val;
+ GDB_FILE *stream;
+ int format;
+ enum val_prettyprint pretty;
+{
+ struct type *type = VALUE_TYPE (val);
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ {
+ fprintf_filtered (stream, "(");
+ type_print (TYPE_TARGET_TYPE (type), "", stream, -1);
+ fprintf_filtered (stream, ") ");
+ }
+ return (val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
+ VALUE_ADDRESS (val) + VALUE_OFFSET (val),
+ stream, format, 1, 0, pretty));
+}
+
+int
+java_val_print (type, valaddr, address, stream, format, deref_ref, recurse,
+ pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ if (is_object_type (type))
+ {
+ CORE_ADDR obj_addr = unpack_pointer (type, valaddr);
+ if (obj_addr != 0)
+ {
+ value_ptr obj_val
+ = value_at (TYPE_TARGET_TYPE (type), obj_addr, NULL);
+ type = type_from_class (java_class_from_object (obj_val));
+ type = lookup_pointer_type (type);
+ }
+ }
+ return c_val_print (type, valaddr, address, stream, format,
+ deref_ref, recurse, pretty);
+}