Initial revision
From-SVN: r22299
This commit is contained in:
parent
fc08e32958
commit
e04a16fbee
43 changed files with 39504 additions and 0 deletions
209
gcc/java/Make-lang.in
Normal file
209
gcc/java/Make-lang.in
Normal file
|
@ -0,0 +1,209 @@
|
|||
# Top level makefile fragment for the GNU compiler for the Java(TM)
|
||||
# language.
|
||||
# Copyright (C) 1996, 1998 Free Software Foundation, Inc.
|
||||
|
||||
#This file is part of GNU CC.
|
||||
|
||||
#GNU CC 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, or (at your option)
|
||||
#any later version.
|
||||
|
||||
#GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
#the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
#Boston, MA 02111-1307, USA.
|
||||
|
||||
#Java and all Java-based marks are trademarks or registered trademarks
|
||||
#of Sun Microsystems, Inc. in the United States and other countries.
|
||||
#The Free Software Foundation is independent of Sun Microsystems, Inc.
|
||||
|
||||
# This file provides the language dependent support in the main Makefile.
|
||||
# Each language makefile fragment must provide the following targets:
|
||||
#
|
||||
# foo.all.build, foo.all.cross, foo.start.encap, foo.rest.encap,
|
||||
# foo.info, foo.dvi,
|
||||
# foo.install-normal, foo.install-common, foo.install-info, foo.install-man,
|
||||
# foo.uninstall, foo.distdir,
|
||||
# foo.mostlyclean, foo.clean, foo.distclean, foo.extraclean,
|
||||
# foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
|
||||
#
|
||||
# where `foo' is the name of the language.
|
||||
#
|
||||
# It should also provide rules for:
|
||||
#
|
||||
# - making any compiler driver (eg: g++)
|
||||
# - the compiler proper (eg: jc1)
|
||||
# - define the names for selecting the language in LANGUAGES.
|
||||
|
||||
# Extra flags to pass to recursive makes.
|
||||
JAVA_FLAGS_TO_PASS = \
|
||||
"JAVA_FOR_BUILD=$(JAVA_FOR_BUILD)" \
|
||||
"JAVAFLAGS=$(JAVAFLAGS)" \
|
||||
"JAVA_FOR_TARGET=$(JAVA_FOR_TARGET)"
|
||||
|
||||
# Actual names to use when installing a native compiler.
|
||||
JAVA_INSTALL_NAME = `t='$(program_transform_name)'; echo gcj | sed $$t`
|
||||
|
||||
# Actual names to use when installing a cross-compiler.
|
||||
JAVA_CROSS_NAME = `t='$(program_transform_cross_name)'; echo gcj | sed $$t`
|
||||
|
||||
|
||||
# Define the names for selecting java in LANGUAGES.
|
||||
java: jc1$(exeext) $(GCJ)$(exeext) jvgenmain$(exeext) gcjh$(exeext)
|
||||
|
||||
# Define the name of target independant tools to be installed in $(bindir)
|
||||
# Names are subject to changes
|
||||
JAVA_TARGET_INDEPENDENT_BIN_TOOLS = gcjh jv-scan jcf-dump
|
||||
|
||||
# Tell GNU make to ignore these if they exist.
|
||||
.PHONY: java
|
||||
|
||||
GCJ = gcj
|
||||
|
||||
# Remember to keep this list in sync with JAVA_OBJS in Makefile.in!!!
|
||||
#
|
||||
JAVA_SRCS = $(srcdir)/java/parse.y $(srcdir)/java/class.c \
|
||||
$(srcdir)/java/decl.c $(srcdir)/java/expr.c $(srcdir)/java/constants.c \
|
||||
$(srcdir)/java/lang.c $(srcdir)/java/typeck.c $(srcdir)/java/except.c \
|
||||
$(srcdir)/java/verify.c $(srcdir)/java/zextract.c $(srcdir)/java/jcf-io.c \
|
||||
$(srcdir)/java/jcf-parse.c $(srcdir)/java/mangle.c \
|
||||
$(srcdir)/java/jcf-write.c $(srcdir)/java/buffer.c
|
||||
|
||||
jc1$(exeext): $(P) $(JAVA_SRCS) $(LIBDEPS) stamp-objlist
|
||||
cd java; $(MAKE) $(FLAGS_TO_PASS) $(JAVA_FLAGS_TO_PASS) ../jc1$(exeext)
|
||||
|
||||
$(GCJ).c: $(srcdir)/gcc.c
|
||||
-rm -f $@
|
||||
$(LN_S) $(srcdir)/gcc.c $@
|
||||
|
||||
jvspec.o: $(srcdir)/java/jvspec.c
|
||||
$(CC) -c -DWITH_THREAD_$(GCC_THREAD_FILE) \
|
||||
$(ALL_CFLAGS) $(ALL_CPPFLAGS) \
|
||||
$(INCLUDES) $(srcdir)/java/jvspec.c
|
||||
|
||||
# N.B.: This is a copy of the gcc.o rule, with -DLANG_SPECIFIC_DRIVER added.
|
||||
# It'd be nice if we could find an easier way to do this---rather than have
|
||||
# to track changes to the toplevel gcc Makefile as well.
|
||||
# We depend on $(GCJ).c last, to make it obvious where it came from.
|
||||
$(GCJ).o: $(CONFIG_H) multilib.h config.status $(lang_specs_files) $(GCJ).c \
|
||||
system.h
|
||||
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
|
||||
$(DRIVER_DEFINES) \
|
||||
-DLANG_SPECIFIC_DRIVER \
|
||||
-c $(GCJ).c
|
||||
|
||||
# Create the compiler driver for $(GCJ).
|
||||
$(GCJ)$(exeext): $(GCJ).o jvspec.o version.o choose-temp.o\
|
||||
pexecute.o prefix.o mkstemp.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
|
||||
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCJ).o jvspec.o prefix.o \
|
||||
version.o choose-temp.o pexecute.o mkstemp.o $(EXTRA_GCC_OBJS) $(LIBS)
|
||||
|
||||
# Create a version of the $(GCJ) driver which calls the cross-compiler.
|
||||
$(GCJ)-cross$(exeext): $(GCJ)$(exeext)
|
||||
-rm -f $(GCJ)-cross$(exeext)
|
||||
cp $(GCJ)$(exeext) $(GCJ)-cross$(exeext)
|
||||
|
||||
# Dependencies here must be kept in sync with dependencies in Makefile.in.
|
||||
jvgenmain$(exeext): $(srcdir)/java/jvgenmain.c $(srcdir)/java/mangle.c \
|
||||
$(OBSTACK)
|
||||
cd java && $(MAKE) $(FLAGS_TO_PASS) $(JAVA_FLAGS_TO_PASS) ../jvgenmain$(exeext)
|
||||
|
||||
# This must be kept in sync with dependencies in Makefile.in.
|
||||
GCJH_SOURCES = $(srcdir)/java/gjavah.c $(srcdir)/java/jcf-io.c \
|
||||
$(srcdir)/java/zextract.c $(srcdir)/java/jcf-reader.c \
|
||||
$(srcdir)/java/jcf.h $(srcdir)/java/javaop.h \
|
||||
$(srcdir)/java/javaop.def
|
||||
|
||||
gcjh$(exeext): $(GCJH_SOURCES)
|
||||
cd java && $(MAKE) $(FLAGS_TO_PASS) $(JAVA_FLAGS_TO_PASS) ../gcjh$(exeext)
|
||||
|
||||
|
||||
|
||||
# Build hooks:
|
||||
|
||||
java.all.build: $(GCJ)$(exeext) jvgenmain$(exeext) gcjh$(exeext)
|
||||
java.all.cross: $(GCJ)-cross$(exeext) jvgenmain$(exeext) gcjh$(exeext)
|
||||
java.start.encap: $(GCJ)$(exeext)
|
||||
java.rest.encap: jvgenmain$(exeext) gcjh$(exeext)
|
||||
|
||||
java.info:
|
||||
|
||||
# Install hooks:
|
||||
# jc1, gcj, jvgenmain, and gcjh are installed elsewhere as part
|
||||
# of $(COMPILERS).
|
||||
|
||||
# Nothing to do here.
|
||||
java.install-normal:
|
||||
|
||||
java.install-common:
|
||||
-if [ -f $(GCJ)$(exeext) ]; then \
|
||||
if [ -f $(GCJ)-cross$(exeext) ]; then \
|
||||
rm -f $(bindir)/$(JAVA_CROSS_NAME)$(exeext); \
|
||||
$(INSTALL_PROGRAM) $(GCJ)-cross$(exeext) $(bindir)/$(JAVA_CROSS_NAME)$(exeext); \
|
||||
chmod a+x $(bindir)/$(JAVA_CROSS_NAME)$(exeext); \
|
||||
else \
|
||||
rm -f $(bindir)/$(JAVA_INSTALL_NAME)$(exeext); \
|
||||
$(INSTALL_PROGRAM) $(GCJ)$(exeext) $(bindir)/$(JAVA_INSTALL_NAME)$(exeext); \
|
||||
chmod a+x $(bindir)/$(JAVA_INSTALL_NAME)$(exeext); \
|
||||
fi ; \
|
||||
fi ; \
|
||||
for tool in $(JAVA_TARGET_INDEPENDENT_BIN_TOOLS); do \
|
||||
if [ -f $$tool$(exeext) ]; then \
|
||||
rm -f $(bindir)/$$tool$(exeext); \
|
||||
$(INSTALL_PROGRAM) $$tool$(exeext) $(bindir)/$$tool$(exeext); \
|
||||
chmod a+x $(bindir)/$$tool$(exeext); \
|
||||
fi ; \
|
||||
done
|
||||
|
||||
java.install-man:
|
||||
|
||||
java.uninstall:
|
||||
-rm -rf $(bindir)/$(JAVA_INSTALL_NAME)$(exeext)
|
||||
-rm -rf $(bindir)/$(JAVA_CROSS_NAME)$(exeext)
|
||||
|
||||
java.install-info:
|
||||
|
||||
|
||||
# Clean hooks:
|
||||
# A lot of the ancillary files are deleted by the main makefile.
|
||||
# We just have to delete files specific to us.
|
||||
|
||||
java.mostlyclean:
|
||||
-rm -f java/*$(objext) $(DEMANGLER_PROG)
|
||||
java.clean:
|
||||
java.distclean:
|
||||
-rm -f java/config.status java/Makefile
|
||||
-rm -f java/parse.output
|
||||
java.extraclean:
|
||||
java.maintainer-clean:
|
||||
-rm -f java/parse.h
|
||||
|
||||
# Stage hooks:
|
||||
# The main makefile has already created stage?/java.
|
||||
|
||||
java.stage1:
|
||||
-mv java/*$(objext) stage1/java
|
||||
java.stage2:
|
||||
-mv java/*$(objext) stage2/java
|
||||
java.stage3:
|
||||
-mv java/*$(objext) stage3/java
|
||||
java.stage4:
|
||||
-mv java/*$(objext) stage4/java
|
||||
|
||||
# Maintenance hooks:
|
||||
|
||||
# This target creates the files that can be rebuilt, but go in the
|
||||
# distribution anyway. It then copies the files to the distdir directory.
|
||||
java.distdir:
|
||||
mkdir tmp/java
|
||||
cd java ; $(MAKE) $(FLAGS_TO_PASS) $(JAVA_FLAGS_TO_PASS) parse.c hash.h
|
||||
cd java; \
|
||||
for file in *[0-9a-zA-Z+]; do \
|
||||
ln $$file ../tmp/java >/dev/null 2>&1 || cp $$file ../tmp/java; \
|
||||
done
|
258
gcc/java/Makefile.in
Normal file
258
gcc/java/Makefile.in
Normal file
|
@ -0,0 +1,258 @@
|
|||
# Makefile for GNU compiler for the Java(TM) language.
|
||||
# Copyright (C) 1987, 88, 90-4, 1995, 1998 Free Software Foundation, Inc.
|
||||
|
||||
#This file is part of GNU CC.
|
||||
|
||||
#GNU CC 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, or (at your option)
|
||||
#any later version.
|
||||
|
||||
#GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
#the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
#Boston, MA 02111-1307, USA.
|
||||
|
||||
#Java and all Java-based marks are trademarks or registered trademarks
|
||||
#of Sun Microsystems, Inc. in the United States and other countries.
|
||||
#The Free Software Foundation is independent of Sun Microsystems, Inc.
|
||||
|
||||
# The makefile built from this file lives in the language subdirectory.
|
||||
# Its purpose is to provide support for:
|
||||
#
|
||||
# 1) recursion where necessary, and only then (building .o's), and
|
||||
# 2) building and debugging cc1 from the language subdirectory, and
|
||||
# 3) nothing else.
|
||||
#
|
||||
# The parent makefile handles all other chores, with help from the
|
||||
# language makefile fragment, of course.
|
||||
#
|
||||
# The targets for external use are:
|
||||
# all, TAGS, ???mostlyclean, ???clean.
|
||||
|
||||
# Suppress smart makes who think they know how to automake Yacc files
|
||||
.y.c:
|
||||
|
||||
# Variables that exist for you to override.
|
||||
# See below for how to change them for certain systems.
|
||||
|
||||
ALLOCA =
|
||||
|
||||
# Various ways of specifying flags for compilations:
|
||||
# CFLAGS is for the user to override to, e.g., do a bootstrap with -O2.
|
||||
# BOOT_CFLAGS is the value of CFLAGS to pass
|
||||
# to the stage2 and stage3 compilations
|
||||
# XCFLAGS is used for most compilations but not when using the GCC just built.
|
||||
XCFLAGS =
|
||||
CFLAGS = -g
|
||||
BOOT_CFLAGS = -O $(CFLAGS)
|
||||
# These exists to be overridden by the x-* and t-* files, respectively.
|
||||
X_CFLAGS =
|
||||
T_CFLAGS =
|
||||
|
||||
X_CPPFLAGS =
|
||||
T_CPPFLAGS =
|
||||
|
||||
CC = @CC@
|
||||
BISON = `if [ -f ../../bison/bison ] ; then echo ../../bison/bison -L $(srcdir)/../../bison/ ; else echo bison ; fi`
|
||||
BISONFLAGS =
|
||||
JAVABISONFLAGS = --name-prefix=java_
|
||||
LEX = `if [ -f ../../flex/flex ] ; then echo ../../flex/flex ; else echo flex ; fi`
|
||||
LEXFLAGS =
|
||||
AR = ar
|
||||
AR_FLAGS = rc
|
||||
SHELL = /bin/sh
|
||||
MAKEINFO = makeinfo
|
||||
TEXI2DVI = texi2dvi
|
||||
|
||||
# Define this as & to perform parallel make on a Sequent.
|
||||
# Note that this has some bugs, and it seems currently necessary
|
||||
# to compile all the gen* files first by hand to avoid erroneous results.
|
||||
P =
|
||||
|
||||
# This is used in the definition of SUBDIR_USE_ALLOCA.
|
||||
# ??? Perhaps it would be better if it just looked for *gcc*.
|
||||
OLDCC = cc
|
||||
|
||||
# This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET.
|
||||
# It omits XCFLAGS, and specifies -B./.
|
||||
# It also specifies -B$(tooldir)/ to find as and ld for a cross compiler.
|
||||
GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS)
|
||||
|
||||
# Tools to use when building a cross-compiler.
|
||||
# These are used because `configure' appends `cross-make'
|
||||
# to the makefile when making a cross-compiler.
|
||||
|
||||
# We don't use cross-make. Instead we use the tools
|
||||
# from the build tree, if they are available.
|
||||
# program_transform_name and objdir are set by configure.in.
|
||||
program_transform_name =
|
||||
objdir = .
|
||||
|
||||
+target=@target@
|
||||
+xmake_file=@dep_host_xmake_file@
|
||||
+tmake_file=@dep_tmake_file@
|
||||
#version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < $(srcdir)/version.c`
|
||||
#mainversion=`sed -e 's/.*\"\([0-9]*\.[0-9]*\).*/\1/' < $(srcdir)/version.c`
|
||||
|
||||
# Directory where sources are, from where we are.
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
# Additional system libraries to link with.
|
||||
CLIB=
|
||||
|
||||
# Change this to a null string if obstacks are installed in the
|
||||
# system library.
|
||||
OBSTACK=obstack.o
|
||||
|
||||
# Choose the real default target.
|
||||
ALL=all
|
||||
|
||||
# End of variables for you to override.
|
||||
|
||||
# Definition of `all' is here so that new rules inserted by sed
|
||||
# do not specify the default target.
|
||||
all: all.indirect
|
||||
|
||||
# This tells GNU Make version 3 not to put all variables in the environment.
|
||||
.NOEXPORT:
|
||||
|
||||
# sed inserts variable overrides after the following line.
|
||||
####target overrides
|
||||
@target_overrides@
|
||||
####host overrides
|
||||
@host_overrides@
|
||||
####cross overrides
|
||||
@cross_overrides@
|
||||
####build overrides
|
||||
@build_overrides@
|
||||
####site overrides
|
||||
|
||||
# Now figure out from those variables how to compile and link.
|
||||
|
||||
all.indirect: Makefile ../jc1$(exeext) ../jcf-dump$(exeext) \
|
||||
../jvgenmain$(exeext) ../gcjh$(exeext) ../jv-scan$(exeext)
|
||||
|
||||
# IN_GCC tells obstack.h that we are using gcc's <stddef.h> file.
|
||||
INTERNAL_CFLAGS = $(CROSS) -DIN_GCC @extra_c_flags@
|
||||
|
||||
# This is the variable actually used when we compile.
|
||||
ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS)
|
||||
|
||||
# Likewise.
|
||||
ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS)
|
||||
|
||||
# Even if ALLOCA is set, don't use it if compiling with GCC.
|
||||
|
||||
SUBDIR_OBSTACK = `if [ x$(OBSTACK) != x ]; then echo ../$(OBSTACK); else true; fi`
|
||||
SUBDIR_USE_ALLOCA = `case "${CC}" in "${OLDCC}") if [ x$(ALLOCA) != x ]; then echo ../$(ALLOCA); else true; fi ;; esac`
|
||||
SUBDIR_MALLOC = `if [ x$(MALLOC) != x ]; then echo ../$(MALLOC); else true; fi`
|
||||
|
||||
# How to link with both our special library facilities
|
||||
# and the system's installed libraries.
|
||||
LIBS = $(SUBDIR_OBSTACK) $(SUBDIR_USE_ALLOCA) $(SUBDIR_MALLOC) $(CLIB)
|
||||
|
||||
# Specify the directories to be searched for header files.
|
||||
# Both . and srcdir are used, in that order,
|
||||
# so that tm.h and config.h will be found in the compilation
|
||||
# subdirectory rather than in the source directory.
|
||||
INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
|
||||
|
||||
# Always use -I$(srcdir)/config when compiling.
|
||||
.c.o:
|
||||
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
|
||||
|
||||
# This tells GNU make version 3 not to export all the variables
|
||||
# defined in this file into the environment.
|
||||
.NOEXPORT:
|
||||
|
||||
# Lists of files for various purposes.
|
||||
|
||||
# Language-specific object files for Gcc/Java:
|
||||
|
||||
# Remember to keep this list in sync with JAVA_SRCS in Make-lang.in!!!
|
||||
#
|
||||
JAVA_OBJS = parse.o class.o decl.o expr.o constants.o lang.o typeck.o \
|
||||
except.o verify.o zextract.o jcf-io.o jcf-parse.o mangle.o jcf-write.o \
|
||||
buffer.o
|
||||
|
||||
JAVA_OBJS_LITE = parse-scan.o jv-scan.o
|
||||
|
||||
# Language-independent object files.
|
||||
OBJS = `cat ../stamp-objlist`
|
||||
OBJDEPS = ../stamp-objlist
|
||||
|
||||
compiler: ../jc1$(exeext) ../jv-scan$(exeext)
|
||||
../jc1$(exeext): $(P) $(JAVA_OBJS) $(OBJDEPS) $(LIBDEPS)
|
||||
rm -f ../jc1$(exeext)
|
||||
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
|
||||
$(JAVA_OBJS) $(OBJS) $(LIBS)
|
||||
../jv-scan$(exeext): $(P) $(JAVA_OBJS_LITE) $(OBJDEPS) $(LIBDEPS)
|
||||
rm -f ../jv-scan$(exeext)
|
||||
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
|
||||
$(JAVA_OBJS_LITE) $(LIBS)
|
||||
|
||||
../jcf-dump$(exeext): jcf-dump.o jcf-io.o zextract.o
|
||||
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ jcf-dump.o jcf-io.o zextract.o
|
||||
|
||||
# Dependencies here must be kept in sync with dependencies in Make-lang.in.
|
||||
../jvgenmain$(exeext): jvgenmain.o mangle.o
|
||||
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ jvgenmain.o mangle.o ../obstack.o
|
||||
|
||||
../gcjh$(exeext): gjavah.o jcf-io.o zextract.o
|
||||
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gjavah.o jcf-io.o zextract.o
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure
|
||||
cd ..; $(SHELL) config.status
|
||||
|
||||
native: config.status ../jc1$(exeext)
|
||||
|
||||
# Compiling object files from source files.
|
||||
|
||||
PARSE_H = $(srcdir)/parse.h
|
||||
PARSE_C = $(srcdir)/parse.c
|
||||
PARSE_SCAN_C = $(srcdir)/parse-scan.c
|
||||
|
||||
$(PARSE_H): $(PARSE_C)
|
||||
$(PARSE_C): $(srcdir)/parse.y $(srcdir)/lex.c $(PARSE_H) $(srcdir)/lex.h
|
||||
$(BISON) -t -v $(BISONFLAGS) $(JAVABISONFLAGS) -o $(PARSE_C) \
|
||||
$(srcdir)/parse.y
|
||||
$(PARSE_SCAN_C): $(srcdir)/parse-scan.y $(srcdir)/lex.c $(PARSE_H) \
|
||||
$(srcdir)/lex.h
|
||||
$(BISON) -t -v $(BISONFLAGS) -o $(PARSE_SCAN_C) $(srcdir)/parse-scan.y
|
||||
|
||||
lex.c: keyword.h lex.h
|
||||
|
||||
keyword.h: keyword.gperf
|
||||
gperf -p -t -j1 -i 1 -g -o -N java_keyword -k1,3,$$ \
|
||||
keyword.gperf > keyword.h
|
||||
|
||||
# These exist for maintenance purposes.
|
||||
|
||||
# Update the tags table.
|
||||
TAGS: force
|
||||
cd $(srcdir) ; \
|
||||
etags *.c *.h ; \
|
||||
echo 'l' | tr 'l' '\f' >> TAGS ; \
|
||||
echo 'parse.y,0' >> TAGS ; \
|
||||
etags -a ../*.h ../*.c;
|
||||
|
||||
.PHONY: TAGS
|
||||
|
||||
mostlyclean:
|
||||
rm -f *.o
|
||||
|
||||
clean: mostlyclean
|
||||
rm -f parse.c
|
||||
|
||||
force:
|
||||
|
||||
parse.o: $(PARSE_C) jcf-reader.c
|
||||
jcf-dump.o: jcf-reader.c jcf.h javaop.h javaop.def
|
||||
gjavah.o: jcf-reader.c jcf.h javaop.h
|
50
gcc/java/buffer.c
Normal file
50
gcc/java/buffer.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* A "buffer" utility type.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Per Bothner <bothner@cygnus.com>, July 1998. */
|
||||
|
||||
#include "gansidecl.h"
|
||||
#include "buffer.h"
|
||||
|
||||
/* Grow BUFP so there is room for at least SIZE more bytes. */
|
||||
|
||||
void
|
||||
buffer_grow (bufp, size)
|
||||
struct buffer *bufp;
|
||||
int size;
|
||||
{
|
||||
if (bufp->limit - bufp->ptr >= size)
|
||||
return;
|
||||
if (bufp->data == 0)
|
||||
{
|
||||
if (size < 120)
|
||||
size = 120;
|
||||
bufp->data = (unsigned char*) xmalloc (size);
|
||||
bufp->ptr = bufp->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = bufp->ptr - bufp->data;
|
||||
size += 2 * (bufp->limit - bufp->data);
|
||||
bufp->data = (unsigned char *) xrealloc (bufp->data, size);
|
||||
bufp->ptr = bufp->data + index;
|
||||
}
|
||||
bufp->limit = bufp->data + size;
|
||||
}
|
43
gcc/java/buffer.h
Normal file
43
gcc/java/buffer.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* A "buffer" utility type.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Per Bothner <bothner@cygnus.com>, July 1998. */
|
||||
|
||||
/* A simple data structure for an expandable buffer. */
|
||||
|
||||
struct buffer
|
||||
{
|
||||
/* The start of the actual data buffer. */
|
||||
unsigned char *data;
|
||||
|
||||
/* Where to write next in the buffer. */
|
||||
unsigned char *ptr;
|
||||
|
||||
/* The end of the allocated data buffer. */
|
||||
unsigned char *limit;
|
||||
};
|
||||
|
||||
#define NULL_BUFFER { (void*) 0, (void*) 0, (void*) 0 }
|
||||
|
||||
#define BUFFER_LENGTH(BUFP) ((BUFP)->ptr - (BUFP)->data)
|
||||
|
||||
#define BUFFER_RESET(BUFP) ((BUFP)->ptr = (BUFP)->data)
|
||||
|
||||
extern void buffer_grow PROTO ((struct buffer*, int));
|
1601
gcc/java/class.c
Normal file
1601
gcc/java/class.c
Normal file
File diff suppressed because it is too large
Load diff
40
gcc/java/config-lang.in
Normal file
40
gcc/java/config-lang.in
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Top level configure fragment for the GNU compiler for the Java(TM)
|
||||
# language.
|
||||
# Copyright (C) 1994, 1995 Free Software Foundation, Inc.
|
||||
|
||||
#This file is part of GNU CC.
|
||||
|
||||
#GNU CC 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, or (at your option)
|
||||
#any later version.
|
||||
|
||||
#GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
#the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
#Boston, MA 02111-1307, USA.
|
||||
|
||||
#Java and all Java-based marks are trademarks or registered trademarks
|
||||
#of Sun Microsystems, Inc. in the United States and other countries.
|
||||
#The Free Software Foundation is independent of Sun Microsystems, Inc.
|
||||
|
||||
# Configure looks for the existence of this file to auto-config each language.
|
||||
# We define several parameters used by configure:
|
||||
#
|
||||
# language - name of language as it would appear in $(LANGUAGES)
|
||||
# compilers - value to add to $(COMPILERS)
|
||||
# stagestuff - files to add to $(STAGESTUFF)
|
||||
# diff_excludes - files to ignore when building diffs between two versions.
|
||||
|
||||
language="java"
|
||||
|
||||
compilers="jc1\$(exeext) jvgenmain\$(exeext)"
|
||||
|
||||
stagestuff="jc1\$(exeext) gcj\$(exeext) jvgenmain\$(exeext) gcjh\$(exeext)"
|
||||
|
||||
outputs=java/Makefile
|
453
gcc/java/constants.c
Normal file
453
gcc/java/constants.c
Normal file
|
@ -0,0 +1,453 @@
|
|||
/* Handle the constant pool of the Java(TM) Virtual Machine.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
#include "config.h"
|
||||
#include "tree.h"
|
||||
#include "java-tree.h"
|
||||
#include "jcf.h"
|
||||
#include "system.h"
|
||||
|
||||
extern struct obstack permanent_obstack;
|
||||
|
||||
/* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */
|
||||
|
||||
void
|
||||
set_constant_entry (cpool, index, tag, value)
|
||||
CPool *cpool;
|
||||
int index;
|
||||
int tag;
|
||||
jword value;
|
||||
{
|
||||
if (cpool->data == NULL)
|
||||
{
|
||||
cpool->capacity = 100;
|
||||
cpool->tags = (uint8*) xmalloc (sizeof(uint8) * cpool->capacity);
|
||||
cpool->data = (jword*) xmalloc (sizeof(jword) * cpool->capacity);
|
||||
cpool->count = 1;
|
||||
}
|
||||
if (index >= cpool->capacity)
|
||||
{
|
||||
cpool->capacity *= 2;
|
||||
if (index >= cpool->capacity)
|
||||
cpool->capacity = index + 10;
|
||||
cpool->tags = (uint8*) xrealloc (cpool->tags,
|
||||
sizeof(uint8) * cpool->capacity);
|
||||
cpool->data = (jword*) xrealloc (cpool->data,
|
||||
sizeof(jword) * cpool->capacity);
|
||||
}
|
||||
if (index >= cpool->count)
|
||||
cpool->count = index + 1;
|
||||
cpool->tags[index] = tag;
|
||||
cpool->data[index] = value;
|
||||
}
|
||||
|
||||
/* Find (or create) a constant pool entry matching TAG and VALUE. */
|
||||
|
||||
int
|
||||
find_constant1 (cpool, tag, value)
|
||||
CPool *cpool;
|
||||
int tag;
|
||||
jword value;
|
||||
{
|
||||
int i;
|
||||
for (i = cpool->count; --i > 0; )
|
||||
{
|
||||
if (cpool->tags[i] == tag && cpool->data[i] == value)
|
||||
return i;
|
||||
}
|
||||
i = cpool->count == 0 ? 1 : cpool->count;
|
||||
set_constant_entry (cpool, i, tag, value);
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Find a double-word constant pool entry matching TAG and WORD1/WORD2. */
|
||||
|
||||
int
|
||||
find_constant2 (cpool, tag, word1, word2)
|
||||
CPool *cpool;
|
||||
int tag;
|
||||
jword word1, word2;
|
||||
{
|
||||
int i;
|
||||
for (i = cpool->count - 1; --i > 0; )
|
||||
{
|
||||
if (cpool->tags[i] == tag
|
||||
&& cpool->data[i] == word1
|
||||
&& cpool->data[i+1] == word2)
|
||||
return i;
|
||||
}
|
||||
i = cpool->count == 0 ? 1 : cpool->count;
|
||||
set_constant_entry (cpool, i, tag, word1);
|
||||
set_constant_entry (cpool, i+1, 0, word2);
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
find_utf8_constant (cpool, name)
|
||||
CPool *cpool;
|
||||
tree name;
|
||||
{
|
||||
if (name == NULL_TREE)
|
||||
return 0;
|
||||
return find_constant1 (cpool, CONSTANT_Utf8, (jword) name);
|
||||
}
|
||||
|
||||
int
|
||||
find_class_or_string_constant (cpool, tag, name)
|
||||
CPool *cpool;
|
||||
int tag;
|
||||
tree name;
|
||||
{
|
||||
int j = find_utf8_constant (cpool, name);
|
||||
int i;
|
||||
for (i = cpool->count; --i > 0; )
|
||||
{
|
||||
if (cpool->tags[i] == tag && cpool->data[i] == j)
|
||||
return i;
|
||||
}
|
||||
i = cpool->count;
|
||||
set_constant_entry (cpool, i, tag, (jword) j);
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
find_class_constant (cpool, type)
|
||||
CPool *cpool;
|
||||
tree type;
|
||||
{
|
||||
return find_class_or_string_constant (cpool, CONSTANT_Class,
|
||||
build_internal_class_name (type));
|
||||
}
|
||||
|
||||
/* Find (or create) a CONSTANT_NameAndType matching NAME and TYPE.
|
||||
Return its index in the constant pool CPOOL. */
|
||||
|
||||
int
|
||||
find_name_and_type_constant (cpool, name, type)
|
||||
CPool *cpool;
|
||||
tree name;
|
||||
tree type;
|
||||
{
|
||||
int name_index = find_utf8_constant (cpool, name);
|
||||
int type_index = find_utf8_constant (cpool, build_java_signature (type));
|
||||
return find_constant1 (cpool, CONSTANT_NameAndType,
|
||||
(name_index << 16) | type_index);
|
||||
}
|
||||
|
||||
/* Find (or create) a CONSTANT_Fieldref for DECL (a FIELD_DECL or VAR_DECL).
|
||||
Return its index in the constant pool CPOOL. */
|
||||
|
||||
int
|
||||
find_fieldref_index (cpool, decl)
|
||||
CPool *cpool;
|
||||
tree decl;
|
||||
{
|
||||
int class_index = find_class_constant (cpool, DECL_CONTEXT (decl));
|
||||
int name_type_index
|
||||
= find_name_and_type_constant (cpool, DECL_NAME (decl), TREE_TYPE (decl));
|
||||
return find_constant1 (cpool, CONSTANT_Fieldref,
|
||||
(class_index << 16) | name_type_index);
|
||||
}
|
||||
|
||||
/* Find (or create) a CONSTANT_Methodref for DECL (a FUNCTION_DECL).
|
||||
Return its index in the constant pool CPOOL. */
|
||||
|
||||
int
|
||||
find_methodref_index (cpool, decl)
|
||||
CPool *cpool;
|
||||
tree decl;
|
||||
{
|
||||
int class_index = find_class_constant (cpool, DECL_CONTEXT (decl));
|
||||
tree name = DECL_CONSTRUCTOR_P (decl) ? init_identifier_node
|
||||
: DECL_NAME (decl);
|
||||
int name_type_index
|
||||
= find_name_and_type_constant (cpool, name, TREE_TYPE (decl));
|
||||
/* Methodref or INterfacemethodRef - FIXME */
|
||||
return find_constant1 (cpool, CONSTANT_Methodref,
|
||||
(class_index << 16) | name_type_index);
|
||||
}
|
||||
|
||||
#define PUT1(X) (*ptr++ = (X))
|
||||
#define PUT2(X) (PUT1((X) >> 8), PUT1(X))
|
||||
#define PUT4(X) (PUT2((X) >> 16), PUT2(X))
|
||||
#define PUTN(P, N) (bcopy(P, ptr, N), ptr += (N))
|
||||
|
||||
/* Give the number of bytes needed in a .class file for the CPOOL
|
||||
constant pool. Includes the 2-byte constant_pool_count. */
|
||||
|
||||
int
|
||||
count_constant_pool_bytes (cpool)
|
||||
CPool *cpool;
|
||||
{
|
||||
int size = 2;
|
||||
int i = 1;
|
||||
jword *datap = &cpool->data[1];;
|
||||
for ( ; i < cpool->count; i++, datap++)
|
||||
{
|
||||
size++;
|
||||
switch (cpool->tags[i])
|
||||
{
|
||||
case CONSTANT_NameAndType:
|
||||
case CONSTANT_Fieldref:
|
||||
case CONSTANT_Methodref:
|
||||
case CONSTANT_InterfaceMethodref:
|
||||
case CONSTANT_Float:
|
||||
case CONSTANT_Integer:
|
||||
size += 4;
|
||||
break;
|
||||
case CONSTANT_Class:
|
||||
case CONSTANT_String:
|
||||
size += 2;
|
||||
break;
|
||||
case CONSTANT_Long:
|
||||
case CONSTANT_Double:
|
||||
size += 4;
|
||||
break;
|
||||
case CONSTANT_Utf8:
|
||||
{
|
||||
tree t = (tree) *datap;
|
||||
int len = IDENTIFIER_LENGTH (t);
|
||||
size += len + 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Write the constant pool CPOOL into BUFFER.
|
||||
The length of BUFFER is LENGTH, which must match the needed length. */
|
||||
|
||||
void
|
||||
write_constant_pool (cpool, buffer, length)
|
||||
CPool *cpool;
|
||||
unsigned char* buffer;
|
||||
int length;
|
||||
{
|
||||
unsigned char* ptr = buffer;
|
||||
int i = 1;
|
||||
jword *datap = &cpool->data[1];
|
||||
PUT2 (cpool->count);
|
||||
for ( ; i < cpool->count; i++, datap++)
|
||||
{
|
||||
int tag = cpool->tags[i];
|
||||
PUT1 (tag);
|
||||
switch (tag)
|
||||
{
|
||||
case CONSTANT_NameAndType:
|
||||
case CONSTANT_Fieldref:
|
||||
case CONSTANT_Methodref:
|
||||
case CONSTANT_InterfaceMethodref:
|
||||
case CONSTANT_Float:
|
||||
case CONSTANT_Integer:
|
||||
PUT4 (*datap);
|
||||
break;
|
||||
case CONSTANT_Class:
|
||||
case CONSTANT_String:
|
||||
PUT2 (*datap);
|
||||
break;
|
||||
break;
|
||||
case CONSTANT_Long:
|
||||
case CONSTANT_Double:
|
||||
PUT4(*datap);
|
||||
i++;
|
||||
datap++;
|
||||
PUT4 (*datap);
|
||||
break;
|
||||
case CONSTANT_Utf8:
|
||||
{
|
||||
tree t = (tree) *datap;
|
||||
int len = IDENTIFIER_LENGTH (t);
|
||||
PUT2 (len);
|
||||
PUTN (IDENTIFIER_POINTER (t), len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ptr != buffer + length)
|
||||
fatal("internal error - incorrect constant pool");
|
||||
}
|
||||
|
||||
CPool *outgoing_cpool;
|
||||
|
||||
/* If non-NULL, an ADDR_EXPR referencing a VAR_DECL containing
|
||||
the constant data array for the current class. */
|
||||
tree current_constant_pool_data_ref;
|
||||
|
||||
/* A Cache for build_int_2 (CONSTANT_XXX, 0). */
|
||||
static tree tag_nodes[13];
|
||||
|
||||
tree
|
||||
get_tag_node (tag)
|
||||
int tag;
|
||||
{
|
||||
if (tag_nodes[tag] == NULL_TREE)
|
||||
{
|
||||
push_obstacks (&permanent_obstack, &permanent_obstack);
|
||||
tag_nodes[tag] = build_int_2 (tag, 0);
|
||||
pop_obstacks ();
|
||||
}
|
||||
return tag_nodes[tag];
|
||||
}
|
||||
|
||||
/* Look for a constant pool entry that matches TAG and NAME.
|
||||
Creates a new entry if not found.
|
||||
TAG is one of CONSTANT_Utf8, CONSTANT_String or CONSTANT_Class.
|
||||
NAME is an IDENTIFIER_NODE naming the Utf8 constant, string, or class.
|
||||
Returns the index of the entry. */
|
||||
|
||||
int
|
||||
alloc_name_constant (tag, name)
|
||||
int tag;
|
||||
tree name;
|
||||
{
|
||||
return find_constant1 (outgoing_cpool, tag, (jword) name);
|
||||
}
|
||||
|
||||
/* Build an identifier for the internal name of reference type TYPE. */
|
||||
|
||||
tree
|
||||
build_internal_class_name (type)
|
||||
tree type;
|
||||
{
|
||||
tree name;
|
||||
if (TYPE_ARRAY_P (type))
|
||||
name = build_java_signature (type);
|
||||
else
|
||||
{
|
||||
name = TYPE_NAME (type);
|
||||
if (TREE_CODE (name) != IDENTIFIER_NODE)
|
||||
name = DECL_NAME (name);
|
||||
name = identifier_subst (name, "", '.', '/', "");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/* Look for a CONSTANT_Class entry for CLAS, creating a new one if needed. */
|
||||
|
||||
int
|
||||
alloc_class_constant (clas)
|
||||
tree clas;
|
||||
{
|
||||
|
||||
return alloc_name_constant (CONSTANT_Class,
|
||||
build_internal_class_name (clas));
|
||||
}
|
||||
|
||||
/* Return a reference to the data array of the current constant pool. */
|
||||
|
||||
tree
|
||||
build_constant_data_ref ()
|
||||
{
|
||||
if (current_constant_pool_data_ref == NULL_TREE)
|
||||
{
|
||||
tree decl;
|
||||
tree decl_name = mangled_classname ("_CD_", current_class);
|
||||
push_obstacks (&permanent_obstack, &permanent_obstack);
|
||||
decl = build_decl (VAR_DECL, decl_name,
|
||||
build_array_type (ptr_type_node,
|
||||
one_elt_array_domain_type));
|
||||
TREE_STATIC (decl) = 1;
|
||||
make_decl_rtl (decl, NULL, 1);
|
||||
pop_obstacks ();
|
||||
current_constant_pool_data_ref
|
||||
= build1 (ADDR_EXPR, ptr_type_node, decl);
|
||||
}
|
||||
return current_constant_pool_data_ref;
|
||||
}
|
||||
|
||||
/* Get the pointer value at the INDEX'th element of the constant pool. */
|
||||
|
||||
tree
|
||||
build_ref_from_constant_pool (index)
|
||||
int index;
|
||||
{
|
||||
tree t = build_constant_data_ref ();
|
||||
index *= int_size_in_bytes (ptr_type_node);
|
||||
t = fold (build (PLUS_EXPR, ptr_type_node,
|
||||
t, build_int_2 (index, 0)));
|
||||
return build1 (INDIRECT_REF, ptr_type_node, t);
|
||||
}
|
||||
|
||||
/* Build an initializer for the constants field of the current constal pool.
|
||||
Should only be called at top-level, since it may emit declarations. */
|
||||
|
||||
tree
|
||||
build_constants_constructor ()
|
||||
{
|
||||
tree tags_value, data_value;
|
||||
tree cons;
|
||||
tree tags_list = NULL_TREE;
|
||||
tree data_list = NULL_TREE;
|
||||
int i;
|
||||
for (i = outgoing_cpool->count; --i > 0; )
|
||||
{
|
||||
tags_list
|
||||
= tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
|
||||
tags_list);
|
||||
data_list
|
||||
= tree_cons (NULL_TREE, build_utf8_ref ((tree)outgoing_cpool->data[i]),
|
||||
data_list);
|
||||
}
|
||||
if (outgoing_cpool->count > 0)
|
||||
{
|
||||
tree index_type;
|
||||
tree data_decl, tags_decl, tags_type;
|
||||
tree max_index = build_int_2 (outgoing_cpool->count - 1, 0);
|
||||
TREE_TYPE (max_index) = sizetype;
|
||||
index_type = build_index_type (max_index);
|
||||
|
||||
/* Add dummy 0'th element of constant pool. */
|
||||
tags_list = tree_cons (NULL_TREE, get_tag_node (0), tags_list);
|
||||
data_list = tree_cons (NULL_TREE, null_pointer_node, data_list);
|
||||
|
||||
data_decl = TREE_OPERAND (build_constant_data_ref (), 0);
|
||||
TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type),
|
||||
DECL_INITIAL (data_decl) = build (CONSTRUCTOR, TREE_TYPE (data_decl),
|
||||
NULL_TREE, data_list);
|
||||
DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
|
||||
rest_of_decl_compilation (data_decl, (char*) 0, 1, 0);
|
||||
data_value = build_address_of (data_decl);
|
||||
|
||||
tags_type = build_array_type (unsigned_byte_type_node, index_type);
|
||||
tags_decl = build_decl (VAR_DECL, mangled_classname ("_CT_",
|
||||
current_class),
|
||||
tags_type);
|
||||
TREE_STATIC (tags_decl) = 1;
|
||||
DECL_INITIAL (tags_decl) = build (CONSTRUCTOR, tags_type,
|
||||
NULL_TREE, tags_list);
|
||||
rest_of_decl_compilation (tags_decl, (char*) 0, 1, 0);
|
||||
tags_value = build_address_of (tags_decl);
|
||||
}
|
||||
else
|
||||
{
|
||||
data_value = null_pointer_node;
|
||||
tags_value = null_pointer_node;
|
||||
}
|
||||
START_RECORD_CONSTRUCTOR (cons, constants_type_node);
|
||||
PUSH_FIELD_VALUE (cons, "size", build_int_2 (outgoing_cpool->count, 0));
|
||||
PUSH_FIELD_VALUE (cons, "tags", tags_value);
|
||||
PUSH_FIELD_VALUE (cons, "data", data_value);
|
||||
FINISH_RECORD_CONSTRUCTOR (cons);
|
||||
return cons;
|
||||
}
|
24
gcc/java/convert.h
Normal file
24
gcc/java/convert.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* Definition of conversion functions.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Jeffrey Hsu <hsu@cygnus.com> */
|
||||
|
||||
extern tree convert_to_boolean PROTO ((tree, tree));
|
||||
extern tree convert_to_char PROTO ((tree, tree));
|
1561
gcc/java/decl.c
Normal file
1561
gcc/java/decl.c
Normal file
File diff suppressed because it is too large
Load diff
278
gcc/java/except.c
Normal file
278
gcc/java/except.c
Normal file
|
@ -0,0 +1,278 @@
|
|||
/* Handle exceptions for GNU compiler for the Java(TM) language.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#include "tree.h"
|
||||
#include "real.h"
|
||||
#include "rtl.h"
|
||||
#include "java-tree.h"
|
||||
#include "javaop.h"
|
||||
#include "java-opcodes.h"
|
||||
#include "jcf.h"
|
||||
#include "except.h"
|
||||
#include "java-except.h"
|
||||
#include "eh-common.h"
|
||||
|
||||
extern struct obstack permanent_obstack;
|
||||
|
||||
struct eh_range *current_method_handlers;
|
||||
|
||||
struct eh_range *current_try_block = NULL;
|
||||
|
||||
struct eh_range *eh_range_freelist = NULL;
|
||||
|
||||
/* These variables are used to speed up find_handler. */
|
||||
|
||||
static int cache_range_start, cache_range_end;
|
||||
static struct eh_range *cache_range;
|
||||
static struct eh_range *cache_next_child;
|
||||
|
||||
/* A dummy range that represents the entire method. */
|
||||
|
||||
struct eh_range whole_range;
|
||||
|
||||
/* Search for the most specific eh_range containing PC.
|
||||
Assume PC is within RANGE.
|
||||
CHILD is a list of children of RANGE such that any
|
||||
previous children have end_pc values that are too low. */
|
||||
|
||||
static struct eh_range *
|
||||
find_handler_in_range (pc, range, child)
|
||||
int pc;
|
||||
struct eh_range *range;
|
||||
register struct eh_range *child;
|
||||
{
|
||||
for (; child != NULL; child = child->next_sibling)
|
||||
{
|
||||
if (pc < child->start_pc)
|
||||
break;
|
||||
if (pc <= child->end_pc)
|
||||
return find_handler_in_range (pc, child, child->first_child);
|
||||
}
|
||||
cache_range = range;
|
||||
cache_range_start = pc;
|
||||
cache_next_child = child;
|
||||
cache_range_end = child == NULL ? range->end_pc : child->start_pc;
|
||||
return range;
|
||||
}
|
||||
|
||||
/* Find the inner-most handler that contains PC. */
|
||||
|
||||
struct eh_range *
|
||||
find_handler (pc)
|
||||
int pc;
|
||||
{
|
||||
struct eh_range *h;
|
||||
if (pc >= cache_range_start)
|
||||
{
|
||||
h = cache_range;
|
||||
if (pc < cache_range_end)
|
||||
return h;
|
||||
while (pc >= h->end_pc)
|
||||
{
|
||||
cache_next_child = h->next_sibling;
|
||||
h = h->outer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
h = &whole_range;
|
||||
cache_next_child = h->first_child;
|
||||
}
|
||||
return find_handler_in_range (pc, h, cache_next_child);
|
||||
}
|
||||
|
||||
#if 0
|
||||
first_child;
|
||||
next_sibling;
|
||||
outer;
|
||||
#endif
|
||||
|
||||
/* Recursive helper routine for add_handler. */
|
||||
|
||||
static int
|
||||
link_handler (start_pc, end_pc, handler, type, outer)
|
||||
int start_pc, end_pc;
|
||||
tree handler;
|
||||
tree type;
|
||||
struct eh_range *outer;
|
||||
{
|
||||
struct eh_range **ptr;
|
||||
if (start_pc < outer->start_pc || end_pc > outer->end_pc)
|
||||
return 0; /* invalid or non-nested exception range */
|
||||
if (start_pc == outer->start_pc && end_pc == outer->end_pc)
|
||||
{
|
||||
outer->handlers = tree_cons (type, handler, outer->handlers);
|
||||
return 1;
|
||||
}
|
||||
ptr = &outer->first_child;
|
||||
for (;; ptr = &(*ptr)->next_sibling)
|
||||
{
|
||||
if (*ptr == NULL || end_pc <= (*ptr)->start_pc)
|
||||
{
|
||||
struct eh_range *h = (struct eh_range *)
|
||||
oballoc (sizeof (struct eh_range));
|
||||
h->start_pc = start_pc;
|
||||
h->end_pc = end_pc;
|
||||
h->next_sibling = *ptr;
|
||||
h->first_child = NULL;
|
||||
h->outer = outer;
|
||||
h->handlers = build_tree_list (type, handler);
|
||||
*ptr = h;
|
||||
return 1;
|
||||
}
|
||||
else if (start_pc < (*ptr)->end_pc)
|
||||
return link_handler (start_pc, end_pc, handler, type, *ptr);
|
||||
/* end_pc > (*ptr)->start_pc && start_pc >= (*ptr)->end_pc. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Called to re-initialize the exception machinery for a new method. */
|
||||
|
||||
void
|
||||
method_init_exceptions ()
|
||||
{
|
||||
whole_range.start_pc = 0;
|
||||
whole_range.end_pc = DECL_CODE_LENGTH (current_function_decl) + 1;
|
||||
whole_range.outer = NULL;
|
||||
whole_range.first_child = NULL;
|
||||
whole_range.next_sibling = NULL;
|
||||
cache_range_start = 0xFFFFFF;
|
||||
set_exception_lang_code (EH_LANG_Java);
|
||||
set_exception_version_code (1);
|
||||
}
|
||||
|
||||
int
|
||||
add_handler (start_pc, end_pc, handler, type)
|
||||
int start_pc, end_pc;
|
||||
tree handler;
|
||||
tree type;
|
||||
{
|
||||
return link_handler (start_pc, end_pc, handler, type, &whole_range);
|
||||
}
|
||||
|
||||
|
||||
/* if there are any handlers for this range, issue start of region */
|
||||
void
|
||||
expand_start_java_handler (range)
|
||||
struct eh_range *range;
|
||||
{
|
||||
expand_eh_region_start ();
|
||||
}
|
||||
|
||||
/* if there are any handlers for this range, isssue end of range,
|
||||
and then all handler blocks */
|
||||
void
|
||||
expand_end_java_handler (range)
|
||||
struct eh_range *range;
|
||||
{
|
||||
tree handler = range->handlers;
|
||||
expand_start_all_catch ();
|
||||
for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler))
|
||||
{
|
||||
tree type = TREE_PURPOSE (handler);
|
||||
tree exp;
|
||||
/* The "type" (metch_info) in a (Java) exception table is one:
|
||||
* a) NULL - meaning match any type in a try-finally.
|
||||
* b) a pointer to a (ccmpiled) class (low-order bit 0).
|
||||
* c) a pointer to the Utf8Const name of the class, plus one
|
||||
* (which yields a value with low-order bit 1). */
|
||||
push_obstacks (&permanent_obstack, &permanent_obstack);
|
||||
if (type == NULL_TREE)
|
||||
exp = null_pointer_node;
|
||||
else if (is_compiled_class (type))
|
||||
exp = build_class_ref (type);
|
||||
else
|
||||
exp = fold (build (PLUS_EXPR, ptr_type_node,
|
||||
build_utf8_ref (build_internal_class_name (type)),
|
||||
size_one_node));
|
||||
pop_obstacks ();
|
||||
start_catch_handler (exp);
|
||||
expand_goto (TREE_VALUE (handler));
|
||||
}
|
||||
expand_end_all_catch ();
|
||||
}
|
||||
|
||||
/* Recursive helper routine for maybe_start_handlers. */
|
||||
|
||||
static void
|
||||
check_start_handlers (range, pc)
|
||||
struct eh_range *range;
|
||||
int pc;
|
||||
{
|
||||
if (range != NULL_EH_RANGE && range->start_pc == pc)
|
||||
{
|
||||
check_start_handlers (range->outer, pc);
|
||||
expand_start_java_handler (range);
|
||||
}
|
||||
}
|
||||
|
||||
struct eh_range *current_range;
|
||||
|
||||
/* Emit any start-of-try-range start at PC. */
|
||||
|
||||
void
|
||||
maybe_start_try (pc)
|
||||
int pc;
|
||||
{
|
||||
if (! doing_eh (1))
|
||||
return;
|
||||
|
||||
current_range = find_handler (pc);
|
||||
check_start_handlers (current_range, pc);
|
||||
}
|
||||
|
||||
/* Emit any end-of-try-range end at PC. */
|
||||
|
||||
void
|
||||
maybe_end_try (pc)
|
||||
int pc;
|
||||
{
|
||||
if (! doing_eh (1))
|
||||
return;
|
||||
|
||||
while (current_range != NULL_EH_RANGE && current_range->end_pc <= pc)
|
||||
{
|
||||
expand_end_java_handler (current_range);
|
||||
current_range = current_range->outer;
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit the handler labels and their code */
|
||||
|
||||
void
|
||||
emit_handlers ()
|
||||
{
|
||||
if (catch_clauses)
|
||||
{
|
||||
rtx funcend = gen_label_rtx ();
|
||||
emit_jump (funcend);
|
||||
|
||||
emit_insns (catch_clauses);
|
||||
expand_leftover_cleanups ();
|
||||
|
||||
emit_label (funcend);
|
||||
}
|
||||
}
|
2283
gcc/java/expr.c
Normal file
2283
gcc/java/expr.c
Normal file
File diff suppressed because it is too large
Load diff
959
gcc/java/gjavah.c
Normal file
959
gcc/java/gjavah.c
Normal file
|
@ -0,0 +1,959 @@
|
|||
/* Program to write C++-suitable header files from a Java(TM) .class
|
||||
file. This is similar to SUN's javah.
|
||||
|
||||
Copyright (C) 1996, 1998 Free Software Foundation, Inc.
|
||||
|
||||
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, 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "jcf.h"
|
||||
#ifdef __STDC__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
/* The output file. */
|
||||
FILE *out = NULL;
|
||||
|
||||
/* Nonzero on failure. */
|
||||
static int found_error = 0;
|
||||
|
||||
/* Directory to place resulting files in. Set by -d option. */
|
||||
char *output_directory = "";
|
||||
|
||||
char *output_file = NULL;
|
||||
|
||||
/* Directory to place temporary file. Set by -td option. Currently unused. */
|
||||
char *temp_directory = "/tmp";
|
||||
|
||||
/* Number of friend functions we have to declare. */
|
||||
static int friend_count;
|
||||
|
||||
/* A class can optionally have a `friend' function declared. If
|
||||
non-NULL, this is that function. */
|
||||
static char **friend_specs = NULL;
|
||||
|
||||
/* Number of lines we are prepending before the class. */
|
||||
static int prepend_count;
|
||||
|
||||
/* We can prepend extra lines before the class's start. */
|
||||
static char **prepend_specs = NULL;
|
||||
|
||||
/* Number of lines we are appending at the end of the class. */
|
||||
static int add_count;
|
||||
|
||||
/* We can append extra lines just before the class's end. */
|
||||
static char **add_specs = NULL;
|
||||
|
||||
/* Number of lines we are appending after the class. */
|
||||
static int append_count;
|
||||
|
||||
/* We can append extra lines after the class's end. */
|
||||
static char **append_specs = NULL;
|
||||
|
||||
int verbose = 0;
|
||||
|
||||
int stubs = 0;
|
||||
|
||||
struct JCF *current_jcf;
|
||||
struct JCF *main_jcf;
|
||||
|
||||
/* This holds access information for the last field we examined. They
|
||||
let us generate "private:", "public:", and "protected:" properly.
|
||||
If 0 then we haven't previously examined any field. */
|
||||
static JCF_u2 last_access;
|
||||
|
||||
#define ACC_VISIBILITY (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)
|
||||
|
||||
int seen_fields = 0;
|
||||
|
||||
static void print_field_info PROTO ((FILE *, JCF*, int, int, JCF_u2));
|
||||
static void print_method_info PROTO ((FILE *, JCF*, int, int, JCF_u2));
|
||||
static void print_c_decl PROTO ((FILE*, JCF*, int, int, JCF_u2, int));
|
||||
|
||||
JCF_u2 current_field_name;
|
||||
JCF_u2 current_field_value;
|
||||
JCF_u2 current_field_signature;
|
||||
JCF_u2 current_field_flags;
|
||||
|
||||
#define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
|
||||
( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
|
||||
current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
|
||||
|
||||
#define HANDLE_END_FIELD() \
|
||||
print_field_info (out, jcf, current_field_name, current_field_signature, \
|
||||
current_field_flags);
|
||||
|
||||
#define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
|
||||
|
||||
#define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
|
||||
print_method_info (out, jcf, NAME, SIGNATURE, ACCESS_FLAGS)
|
||||
|
||||
#include "jcf-reader.c"
|
||||
|
||||
/* Some useful constants. */
|
||||
#define F_NAN_MASK 0x7f800000
|
||||
#define D_NAN_MASK 0x7ff0000000000000LL
|
||||
|
||||
/* Return 1 if F is not Inf or NaN. */
|
||||
static int
|
||||
java_float_finite (f)
|
||||
jfloat f;
|
||||
{
|
||||
int32 *ip = (int32 *) &f;
|
||||
|
||||
/* We happen to know that F_NAN_MASK will match all NaN values, and
|
||||
also positive and negative infinity. That's why we only need one
|
||||
test here. See The Java Language Specification, section 20.9. */
|
||||
return (*ip & F_NAN_MASK) != F_NAN_MASK;
|
||||
}
|
||||
|
||||
/* Return 1 if D is not Inf or NaN. */
|
||||
static int
|
||||
java_double_finite (d)
|
||||
jdouble d;
|
||||
{
|
||||
int64 *ip = (int64 *) &d;
|
||||
|
||||
/* Now check for all NaNs. */
|
||||
return (*ip & D_NAN_MASK) != D_NAN_MASK;
|
||||
}
|
||||
|
||||
void
|
||||
DEFUN(print_name, (stream, jcf, name_index),
|
||||
FILE* stream AND JCF* jcf AND int name_index)
|
||||
{
|
||||
if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
|
||||
fprintf (stream, "<not a UTF8 constant>");
|
||||
else
|
||||
jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
|
||||
JPOOL_UTF_LENGTH (jcf, name_index));
|
||||
}
|
||||
|
||||
/* Print base name of class. The base name is everything after the
|
||||
final separator. */
|
||||
|
||||
static void
|
||||
print_base_classname (stream, jcf, index)
|
||||
FILE *stream;
|
||||
JCF *jcf;
|
||||
int index;
|
||||
{
|
||||
int name_index = JPOOL_USHORT1 (jcf, index);
|
||||
int i, len;
|
||||
unsigned char *s, *p, *limit;
|
||||
|
||||
s = JPOOL_UTF_DATA (jcf, name_index);
|
||||
len = JPOOL_UTF_LENGTH (jcf, name_index);
|
||||
limit = s + len;
|
||||
p = s;
|
||||
while (s < limit)
|
||||
{
|
||||
int c = UTF8_GET (s, limit);
|
||||
if (c == '/')
|
||||
p = s;
|
||||
}
|
||||
|
||||
while (p < limit)
|
||||
{
|
||||
int ch = UTF8_GET (p, limit);
|
||||
if (ch == '/')
|
||||
fputs ("::", stream);
|
||||
else
|
||||
jcf_print_char (stream, ch);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 0 if NAME is equal to STR, nonzero otherwise. */
|
||||
|
||||
static int
|
||||
utf8_cmp (str, length, name)
|
||||
unsigned char *str;
|
||||
int length;
|
||||
char *name;
|
||||
{
|
||||
unsigned char *limit = str + length;
|
||||
int i;
|
||||
|
||||
for (i = 0; name[i]; ++i)
|
||||
{
|
||||
int ch = UTF8_GET (str, limit);
|
||||
if (ch != name[i])
|
||||
return 1;
|
||||
}
|
||||
|
||||
return str != limit;
|
||||
}
|
||||
|
||||
/* Generate an access control keyword based on FLAGS. Returns 0 if
|
||||
FLAGS matches the saved access information, nonzero otherwise. */
|
||||
|
||||
static void
|
||||
generate_access (stream, flags)
|
||||
FILE *stream;
|
||||
JCF_u2 flags;
|
||||
{
|
||||
/* FIXME: Java's "protected" and "no access specifier" modes don't
|
||||
actually map to C++ "protected". That's how we map them for now,
|
||||
though. */
|
||||
|
||||
if (! (flags & ACC_VISIBILITY))
|
||||
flags = ACC_PROTECTED;
|
||||
|
||||
if ((flags & ACC_VISIBILITY) == last_access)
|
||||
return;
|
||||
last_access = (flags & ACC_VISIBILITY);
|
||||
|
||||
switch (last_access)
|
||||
{
|
||||
case ACC_PUBLIC:
|
||||
fputs ("public:\n", stream);
|
||||
break;
|
||||
case ACC_PRIVATE:
|
||||
fputs ("private:\n", stream);
|
||||
break;
|
||||
case ACC_PROTECTED:
|
||||
fputs ("protected:\n", stream);
|
||||
break;
|
||||
default:
|
||||
found_error = 1;
|
||||
fprintf (stream, "#error unrecognized visibility %d\n",
|
||||
(flags & ACC_VISIBILITY));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags),
|
||||
FILE *stream AND JCF* jcf
|
||||
AND int name_index AND int sig_index AND JCF_u2 flags)
|
||||
{
|
||||
if (flags & ACC_FINAL)
|
||||
{
|
||||
if (current_field_value > 0)
|
||||
{
|
||||
jlong num;
|
||||
char buffer[25];
|
||||
|
||||
generate_access (stream, flags);
|
||||
switch (JPOOL_TAG (jcf, current_field_value))
|
||||
{
|
||||
case CONSTANT_Integer:
|
||||
fputs (" static const jint ", out);
|
||||
print_name (out, jcf, name_index);
|
||||
fputs (" = ", out);
|
||||
num = JPOOL_INT (jcf, current_field_value);
|
||||
format_int (buffer, num, 10);
|
||||
fprintf (out, "%sL;\n", buffer);
|
||||
break;
|
||||
case CONSTANT_Long:
|
||||
fputs (" static const jlong ", out);
|
||||
print_name (out, jcf, name_index);
|
||||
fputs (" = ", out);
|
||||
num = JPOOL_LONG (jcf, current_field_value);
|
||||
format_int (buffer, num, 10);
|
||||
fprintf (out, "%sLL;\n", buffer);
|
||||
break;
|
||||
case CONSTANT_Float:
|
||||
{
|
||||
jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
|
||||
fputs (" static const jfloat ", out);
|
||||
print_name (out, jcf, name_index);
|
||||
if (! java_float_finite (fnum))
|
||||
fputs (";\n", out);
|
||||
else
|
||||
fprintf (out, " = %.10g;\n", fnum);
|
||||
}
|
||||
break;
|
||||
case CONSTANT_Double:
|
||||
{
|
||||
jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
|
||||
fputs (" static const jdouble ", out);
|
||||
print_name (out, jcf, name_index);
|
||||
if (! java_double_finite (dnum))
|
||||
fputs (";\n", out);
|
||||
else
|
||||
fprintf (out, " = %.17g;\n", dnum);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(out, " <<inappropriate constant type>>\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
generate_access (stream, flags);
|
||||
fputs (" ", out);
|
||||
if (flags & ACC_STATIC)
|
||||
fputs ("static ", out);
|
||||
print_c_decl (out, jcf, name_index, sig_index, flags, 0);
|
||||
fputs (";\n", out);
|
||||
if (! (flags & ACC_STATIC))
|
||||
seen_fields++;
|
||||
}
|
||||
|
||||
static void
|
||||
DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
|
||||
FILE *stream AND JCF* jcf
|
||||
AND int name_index AND int sig_index AND JCF_u2 flags)
|
||||
{
|
||||
unsigned char *str;
|
||||
int length, is_init = 0;
|
||||
|
||||
if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
|
||||
fprintf (stream, "<not a UTF8 constant>");
|
||||
str = JPOOL_UTF_DATA (jcf, name_index);
|
||||
length = JPOOL_UTF_LENGTH (jcf, name_index);
|
||||
if (str[0] == '<')
|
||||
{
|
||||
/* Ignore internally generated methods like <clinit>. However,
|
||||
treat <init> as a constructor. */
|
||||
if (! utf8_cmp (str, length, "<init>"))
|
||||
is_init = 1;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
/* We can't generate a method whose name is a C++ reserved word.
|
||||
For now the only problem has been `delete'; add more here as
|
||||
required. FIXME: we need a better solution than just ignoring
|
||||
the method. */
|
||||
if (! utf8_cmp (str, length, "delete"))
|
||||
return;
|
||||
|
||||
generate_access (stream, flags);
|
||||
|
||||
fputs (" ", out);
|
||||
if ((flags & ACC_STATIC))
|
||||
fputs ("static ", out);
|
||||
else if (! (flags & ACC_FINAL) && ! (jcf->access_flags & ACC_FINAL))
|
||||
{
|
||||
/* Don't print `virtual' if we have a constructor. */
|
||||
if (! is_init)
|
||||
fputs ("virtual ", out);
|
||||
}
|
||||
print_c_decl (out, jcf, name_index, sig_index, flags, is_init);
|
||||
|
||||
/* FIXME: it would be nice to decompile small methods here. That
|
||||
would allow for inlining. */
|
||||
|
||||
fprintf(out, ";\n");
|
||||
}
|
||||
|
||||
static void
|
||||
DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, flags, is_init),
|
||||
FILE* stream AND JCF* jcf
|
||||
AND int name_index AND int signature_index AND JCF_u2 flags
|
||||
AND int is_init)
|
||||
{
|
||||
if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
|
||||
fprintf (stream, "<not a UTF8 constant>");
|
||||
else
|
||||
{
|
||||
int length = JPOOL_UTF_LENGTH (jcf, signature_index);
|
||||
unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
|
||||
register unsigned char *str = str0;
|
||||
unsigned char *limit = str + length;
|
||||
int j;
|
||||
char *ctype;
|
||||
int need_space = 0;
|
||||
int is_method = str[0] == '(';
|
||||
|
||||
if (is_method)
|
||||
{
|
||||
/* Skip to the return signature, and print that first.
|
||||
However, don't do this is we are printing a construtcor.
|
||||
*/
|
||||
if (is_init)
|
||||
{
|
||||
str = str0 + 1;
|
||||
/* FIXME: Most programmers love Celtic knots because
|
||||
they see their own code in the interconnected loops.
|
||||
That is, this is spaghetti. */
|
||||
goto have_constructor;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (str < limit)
|
||||
{
|
||||
int ch = *str++;
|
||||
if (ch == ')')
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
again:
|
||||
while (str < limit)
|
||||
{
|
||||
switch (str[0])
|
||||
{
|
||||
case '[':
|
||||
for (str++; str < limit && *str >= '0' && *str <= '9'; str++)
|
||||
;
|
||||
switch (*str)
|
||||
{
|
||||
case 'B': ctype = "jbyteArray"; goto printit;
|
||||
case 'C': ctype = "jcharArray"; goto printit;
|
||||
case 'D': ctype = "jdoubleArray"; goto printit;
|
||||
case 'F': ctype = "jfloatArray"; goto printit;
|
||||
case 'I': ctype = "jintArray"; goto printit;
|
||||
case 'S': ctype = "jshortArray"; goto printit;
|
||||
case 'J': ctype = "jlongArray"; goto printit;
|
||||
case 'Z': ctype = "jbooleanArray"; goto printit;
|
||||
case '[': ctype = "jobjectArray"; goto printit;
|
||||
case 'L':
|
||||
/* We have to generate a reference to JArray here,
|
||||
so that our output matches what the compiler
|
||||
does. */
|
||||
++str;
|
||||
fputs ("JArray<", out);
|
||||
while (str < limit && *str != ';')
|
||||
{
|
||||
int ch = UTF8_GET (str, limit);
|
||||
if (ch == '/')
|
||||
fputs ("::", stream);
|
||||
else
|
||||
jcf_print_char (stream, ch);
|
||||
}
|
||||
fputs (" *> *", out);
|
||||
need_space = 0;
|
||||
++str;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "unparseable signature `%s'\n", str0);
|
||||
found_error = 1;
|
||||
ctype = "???"; goto printit;
|
||||
}
|
||||
break;
|
||||
case '(':
|
||||
fputc (*str++, stream);
|
||||
continue;
|
||||
case ')':
|
||||
fputc (*str++, stream);
|
||||
/* the return signature was printed in the first pass. */
|
||||
return;
|
||||
case 'B': ctype = "jbyte"; goto printit;
|
||||
case 'C': ctype = "jchar"; goto printit;
|
||||
case 'D': ctype = "jdouble"; goto printit;
|
||||
case 'F': ctype = "jfloat"; goto printit;
|
||||
case 'I': ctype = "jint"; goto printit;
|
||||
case 'J': ctype = "jlong"; goto printit;
|
||||
case 'S': ctype = "jshort"; goto printit;
|
||||
case 'Z': ctype = "jboolean"; goto printit;
|
||||
case 'V': ctype = "void"; goto printit;
|
||||
case 'L':
|
||||
++str;
|
||||
while (*str && *str != ';')
|
||||
{
|
||||
int ch = UTF8_GET (str, limit);
|
||||
if (ch == '/')
|
||||
fputs ("::", stream);
|
||||
else
|
||||
jcf_print_char (stream, ch);
|
||||
}
|
||||
fputs (" *", stream);
|
||||
if (*str == ';')
|
||||
str++;
|
||||
need_space = 0;
|
||||
break;
|
||||
default:
|
||||
need_space = 1;
|
||||
jcf_print_char (stream, *str++);
|
||||
break;
|
||||
printit:
|
||||
str++;
|
||||
need_space = 1;
|
||||
fputs (ctype, stream);
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_method && str < limit && *str != ')')
|
||||
fputs (", ", stream);
|
||||
}
|
||||
have_constructor:
|
||||
if (name_index)
|
||||
{
|
||||
if (need_space)
|
||||
fprintf (stream, " ");
|
||||
/* Declare constructors specially. */
|
||||
if (is_init)
|
||||
print_base_classname (stream, jcf, jcf->this_class);
|
||||
else
|
||||
print_name (stream, jcf, name_index);
|
||||
}
|
||||
if (is_method)
|
||||
{
|
||||
fputs (" (", stream);
|
||||
/* Go to beginning, skipping '('. */
|
||||
str = str0 + 1;
|
||||
goto again; /* To handle argument signatures. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
DEFUN(print_mangled_classname, (stream, jcf, prefix, index),
|
||||
FILE *stream AND JCF *jcf AND char *prefix AND int index)
|
||||
{
|
||||
int name_index = JPOOL_USHORT1 (jcf, index);
|
||||
fputs (prefix, stream);
|
||||
jcf_print_utf8_replace (out,
|
||||
JPOOL_UTF_DATA (jcf, name_index),
|
||||
JPOOL_UTF_LENGTH (jcf, name_index),
|
||||
'/', '_');
|
||||
}
|
||||
|
||||
/* Print PREFIX, then a class name in C++ format. If the name refers
|
||||
to an array, ignore it and don't print PREFIX. Returns 1 if
|
||||
something was printed, 0 otherwise. */
|
||||
static int
|
||||
print_cxx_classname (stream, prefix, jcf, index)
|
||||
FILE *stream;
|
||||
char *prefix;
|
||||
JCF *jcf;
|
||||
int index;
|
||||
{
|
||||
int name_index = JPOOL_USHORT1 (jcf, index);
|
||||
int i, len, c;
|
||||
unsigned char *s, *p, *limit;
|
||||
|
||||
s = JPOOL_UTF_DATA (jcf, name_index);
|
||||
len = JPOOL_UTF_LENGTH (jcf, name_index);
|
||||
limit = s + len;
|
||||
|
||||
/* Explicitly omit arrays here. */
|
||||
p = s;
|
||||
c = UTF8_GET (p, limit);
|
||||
if (c == '[')
|
||||
return 0;
|
||||
|
||||
fputs (prefix, stream);
|
||||
while (s < limit)
|
||||
{
|
||||
c = UTF8_GET (s, limit);
|
||||
if (c == '/')
|
||||
fputs ("::", stream);
|
||||
else
|
||||
jcf_print_char (stream, c);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int written_class_count = 0;
|
||||
|
||||
/* Return name of superclass. If LEN is not NULL, fill it with length
|
||||
of name. */
|
||||
static unsigned char *
|
||||
super_class_name (derived_jcf, len)
|
||||
JCF *derived_jcf;
|
||||
int *len;
|
||||
{
|
||||
int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
|
||||
int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
|
||||
unsigned char *supername = JPOOL_UTF_DATA (derived_jcf, supername_index);
|
||||
|
||||
if (len)
|
||||
*len = supername_length;
|
||||
|
||||
return supername;
|
||||
}
|
||||
|
||||
/* Print declarations for all classes required by this class. FIXME:
|
||||
the current implementation just prints every class name from the
|
||||
constant pool. This is too much. We really only need to print a
|
||||
declaration for each class which is the type of a return value, a
|
||||
field, or an argument. */
|
||||
static void
|
||||
print_class_decls (out, jcf)
|
||||
FILE *out;
|
||||
JCF *jcf;
|
||||
{
|
||||
int i, seen_one = 0;
|
||||
|
||||
for (i = 1; i < JPOOL_SIZE (jcf); ++i)
|
||||
{
|
||||
int kind = JPOOL_TAG (jcf, i);
|
||||
if (kind == CONSTANT_Class)
|
||||
{
|
||||
if (print_cxx_classname (out, "class ", jcf, i))
|
||||
fputs (";\n", out);
|
||||
seen_one = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (seen_one)
|
||||
fputs ("\n", out);
|
||||
}
|
||||
|
||||
static void
|
||||
DEFUN(process_file, (file, out),
|
||||
JCF *jcf AND FILE *out)
|
||||
{
|
||||
int code, i;
|
||||
|
||||
current_jcf = main_jcf = jcf;
|
||||
|
||||
last_access = 0;
|
||||
|
||||
if (jcf_parse_preamble (jcf) != 0)
|
||||
{
|
||||
fprintf (stderr, "Not a valid Java .class file.\n");
|
||||
found_error = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parse and possibly print constant pool */
|
||||
code = jcf_parse_constant_pool (jcf);
|
||||
if (code != 0)
|
||||
{
|
||||
fprintf (stderr, "error while parsing constant pool\n");
|
||||
found_error = 1;
|
||||
return;
|
||||
}
|
||||
code = verify_constant_pool (jcf);
|
||||
if (code > 0)
|
||||
{
|
||||
fprintf (stderr, "error in constant pool entry #%d\n", code);
|
||||
found_error = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
jcf_parse_class (jcf);
|
||||
|
||||
if (written_class_count++ == 0)
|
||||
fputs ("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-\n\n",
|
||||
out);
|
||||
|
||||
print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
|
||||
fprintf (out, "__\n");
|
||||
|
||||
print_mangled_classname (out, jcf, "#define __", jcf->this_class);
|
||||
fprintf (out, "__\n\n");
|
||||
|
||||
if (jcf->super_class)
|
||||
{
|
||||
int super_length;
|
||||
unsigned char *supername = super_class_name (jcf, &super_length);
|
||||
|
||||
fputs ("#include <", out);
|
||||
jcf_print_utf8 (out, supername, super_length);
|
||||
fputs (".h>\n", out);
|
||||
|
||||
/* FIXME: If our superclass is Object, then we include
|
||||
java-array.h. The right thing to do here is look at all the
|
||||
methods and fields and see if an array is in use. Only then
|
||||
would we need to include java-array.h. */
|
||||
if (! utf8_cmp (supername, super_length, "java/lang/Object"))
|
||||
fputs ("#include <java-array.h>\n", out);
|
||||
|
||||
fputs ("\n", out);
|
||||
}
|
||||
|
||||
print_class_decls (out, jcf);
|
||||
|
||||
for (i = 0; i < prepend_count; ++i)
|
||||
fprintf (out, "%s\n", prepend_specs[i]);
|
||||
if (prepend_count > 0)
|
||||
fputc ('\n', out);
|
||||
|
||||
if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
|
||||
{
|
||||
fprintf (stderr, "class is of array type\n");
|
||||
found_error = 1;
|
||||
return;
|
||||
}
|
||||
if (jcf->super_class)
|
||||
{
|
||||
if (! print_cxx_classname (out, " : public ", jcf, jcf->super_class))
|
||||
{
|
||||
fprintf (stderr, "base class is of array type\n");
|
||||
found_error = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
fputs ("\n{\n", out);
|
||||
|
||||
/* We make a single pass over the file, printing methods and fields
|
||||
as we see them. We have to list the methods in the same order
|
||||
that they appear in the class file, so that the Java and C++
|
||||
vtables have the same layout. */
|
||||
jcf_parse_fields (jcf);
|
||||
jcf_parse_methods (jcf);
|
||||
jcf_parse_final_attributes (jcf);
|
||||
|
||||
/* Generate friend decl if we still must. */
|
||||
for (i = 0; i < friend_count; ++i)
|
||||
fprintf (out, " friend %s\n", friend_specs[i]);
|
||||
|
||||
/* Generate extra declarations. */
|
||||
if (add_count > 0)
|
||||
fputc ('\n', out);
|
||||
for (i = 0; i < add_count; ++i)
|
||||
fprintf (out, " %s\n", add_specs[i]);
|
||||
|
||||
fputs ("};\n", out);
|
||||
|
||||
if (append_count > 0)
|
||||
fputc ('\n', out);
|
||||
for (i = 0; i < append_count; ++i)
|
||||
fprintf (out, "%s\n", append_specs[i]);
|
||||
|
||||
print_mangled_classname (out, jcf, "\n#endif /* __", jcf->this_class);
|
||||
fprintf (out, "__ */\n");
|
||||
}
|
||||
|
||||
static void
|
||||
usage ()
|
||||
{
|
||||
fprintf (stderr, "gjavah: no classes specified\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
static void
|
||||
help ()
|
||||
{
|
||||
printf ("Usage: gjavah [OPTION]... CLASS...\n\n");
|
||||
printf ("Generate C++ header files from .class files\n\n");
|
||||
printf (" --classpath PATH Set path to find .class files\n");
|
||||
printf (" -d DIRECTORY Set output directory name\n");
|
||||
printf (" --help Print this help, then exit\n");
|
||||
printf (" -o FILE Set output file name\n");
|
||||
printf (" -td DIRECTORY Set temporary directory name\n");
|
||||
printf (" -v, --verbose Print extra information while running\n");
|
||||
printf (" --version Print version number, then exit\n");
|
||||
/* FIXME: print bug-report information. */
|
||||
exit (0);
|
||||
}
|
||||
|
||||
static void
|
||||
no_argument (opt)
|
||||
char *opt;
|
||||
{
|
||||
fprintf (stderr, "gjavah: no argument given for option `%s'\n", opt);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
static void
|
||||
version ()
|
||||
{
|
||||
/* FIXME: use version.c? */
|
||||
printf ("gjavah (GNU gcc) 0.0\n\n");
|
||||
printf ("Copyright (C) 1998 Free Software Foundation, Inc.\n");
|
||||
printf ("This is free software; see the source for copying conditions. There is NO\n");
|
||||
printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
|
||||
exit (0);
|
||||
}
|
||||
|
||||
int
|
||||
DEFUN(main, (argc, argv),
|
||||
int argc AND char** argv)
|
||||
{
|
||||
JCF jcf;
|
||||
int argi;
|
||||
|
||||
if (argc <= 1)
|
||||
usage ();
|
||||
|
||||
for (argi = 1; argi < argc; argi++)
|
||||
{
|
||||
char *arg = argv[argi];
|
||||
|
||||
if (arg[0] != '-' || ! strcmp (arg, "--"))
|
||||
break;
|
||||
|
||||
/* Just let all arguments be given in either "-" or "--" form. */
|
||||
if (arg[1] == '-')
|
||||
++arg;
|
||||
|
||||
if (strcmp (arg, "-o") == 0)
|
||||
{
|
||||
if (argi + 1 < argc)
|
||||
output_file = argv[++argi];
|
||||
else
|
||||
no_argument (argv[argi]);
|
||||
}
|
||||
else if (strcmp (arg, "-d") == 0)
|
||||
{
|
||||
if (argi + 1 < argc)
|
||||
output_directory = argv[++argi];
|
||||
else
|
||||
no_argument (argv[argi]);
|
||||
}
|
||||
else if (strcmp (arg, "-td") == 0)
|
||||
{
|
||||
if (argi + 1 < argc)
|
||||
temp_directory = argv[++argi];
|
||||
else
|
||||
no_argument (argv[argi]);
|
||||
}
|
||||
else if (strcmp (arg, "-prepend") == 0)
|
||||
{
|
||||
if (argi + 1 < argc)
|
||||
{
|
||||
if (prepend_count == 0)
|
||||
prepend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
|
||||
prepend_specs[prepend_count++] = argv[++argi];
|
||||
}
|
||||
else
|
||||
no_argument (argv[argi]);
|
||||
}
|
||||
else if (strcmp (arg, "-friend") == 0)
|
||||
{
|
||||
if (argi + 1 < argc)
|
||||
{
|
||||
if (friend_count == 0)
|
||||
friend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
|
||||
friend_specs[friend_count++] = argv[++argi];
|
||||
}
|
||||
else
|
||||
no_argument (argv[argi]);
|
||||
}
|
||||
else if (strcmp (arg, "-add") == 0)
|
||||
{
|
||||
if (argi + 1 < argc)
|
||||
{
|
||||
if (add_count == 0)
|
||||
add_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
|
||||
add_specs[add_count++] = argv[++argi];
|
||||
}
|
||||
else
|
||||
no_argument (argv[argi]);
|
||||
}
|
||||
else if (strcmp (arg, "-append") == 0)
|
||||
{
|
||||
if (argi + 1 < argc)
|
||||
{
|
||||
if (append_count == 0)
|
||||
append_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
|
||||
append_specs[append_count++] = argv[++argi];
|
||||
}
|
||||
else
|
||||
no_argument (argv[argi]);
|
||||
}
|
||||
else if (strcmp (arg, "-classpath") == 0)
|
||||
{
|
||||
if (argi + 1 < argc)
|
||||
classpath = argv[++argi];
|
||||
else
|
||||
no_argument (argv[argi]);
|
||||
}
|
||||
else if (strcmp (arg, "-verbose") == 0 || strcmp (arg, "-v") == 0)
|
||||
verbose++;
|
||||
else if (strcmp (arg, "-stubs") == 0)
|
||||
stubs++;
|
||||
else if (strcmp (arg, "-help") == 0)
|
||||
help ();
|
||||
else if (strcmp (arg, "-version") == 0)
|
||||
version ();
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "%s: illegal argument\n", argv[argi]);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (argi == argc)
|
||||
usage ();
|
||||
|
||||
if (classpath == NULL)
|
||||
{
|
||||
classpath = (char *) getenv ("CLASSPATH");
|
||||
if (classpath == NULL)
|
||||
classpath = "";
|
||||
}
|
||||
|
||||
for (; argi < argc; argi++)
|
||||
{
|
||||
char *classname = argv[argi];
|
||||
char *classfile_name, *current_output_file;
|
||||
|
||||
if (verbose)
|
||||
fprintf (stderr, "Processing %s\n", classname);
|
||||
classfile_name = find_class (classname, strlen (classname), &jcf, 1);
|
||||
if (classfile_name == NULL)
|
||||
{
|
||||
fprintf (stderr, "%s: no such class\n", classname);
|
||||
exit (1);
|
||||
}
|
||||
if (verbose)
|
||||
fprintf (stderr, "Found in %s\n", classfile_name);
|
||||
if (output_file)
|
||||
{
|
||||
if (strcmp (output_file, "-") == 0)
|
||||
out = stdout;
|
||||
else if (out == NULL)
|
||||
out = fopen (output_file, "w");
|
||||
if (out == NULL)
|
||||
{
|
||||
perror (output_file);
|
||||
exit (1);
|
||||
}
|
||||
current_output_file = output_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
int dir_len = strlen (output_directory);
|
||||
int i, classname_length = strlen (classname);
|
||||
current_output_file = (char*) ALLOC (dir_len + classname_length + 4);
|
||||
strcpy (current_output_file, output_directory);
|
||||
if (dir_len > 0 && output_directory[dir_len-1] != '/')
|
||||
current_output_file[dir_len++] = '/';
|
||||
for (i = 0; classname[i] != '\0'; i++)
|
||||
{
|
||||
char ch = classname[i];
|
||||
if (ch == '.')
|
||||
ch = '/';
|
||||
current_output_file[dir_len++] = ch;
|
||||
}
|
||||
strcpy (current_output_file+dir_len, ".h");
|
||||
out = fopen (current_output_file, "w");
|
||||
if (out == NULL)
|
||||
{
|
||||
perror (current_output_file);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
process_file (&jcf, out);
|
||||
JCF_FINISH (&jcf);
|
||||
if (current_output_file != output_file)
|
||||
free (current_output_file);
|
||||
}
|
||||
|
||||
if (out != NULL && out != stdout)
|
||||
fclose (out);
|
||||
|
||||
return found_error;
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
|
||||
* Do whatever the javah -stubs flag does.
|
||||
|
||||
* Emit "structure forward declarations" when needed.
|
||||
|
||||
* Generate C headers, like javah
|
||||
|
||||
*/
|
67
gcc/java/java-except.h
Normal file
67
gcc/java/java-except.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/* Definitions for exception handling for use by the GNU compiler
|
||||
for the Java(TM) language compiler.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
struct eh_range
|
||||
{
|
||||
/* The (byte-code PC) range of the handled block. */
|
||||
int start_pc;
|
||||
int end_pc;
|
||||
|
||||
/* A list of handlers. For each element in the list,
|
||||
the TREE_PURPOSE is the handled class (NULL_EXPR for a finally block),
|
||||
and the TREE_VALUE is the LABEL_DECL of the handler. */
|
||||
tree handlers;
|
||||
|
||||
/* Surrunding handler, if any. */
|
||||
struct eh_range *outer;
|
||||
|
||||
/* The first child range. It is is nested inside this range
|
||||
(i.e. this.start_pc <= first_child.end_pc
|
||||
&& this.end_pc >= first_child.end_pc).
|
||||
The children are linked together using next_sibling, and are sorted
|
||||
by increasing start_pc and end_pc (we do not support non-nested
|
||||
overlapping ranges). */
|
||||
struct eh_range *first_child;
|
||||
|
||||
/* The next child of outer, in address order. */
|
||||
struct eh_range *next_sibling;
|
||||
|
||||
#if 0
|
||||
/* Next handler, sorted by ascending start_pc then descending end_pc. */
|
||||
tree next;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* A dummy range that represents the entire method. */
|
||||
extern struct eh_range whole_range;
|
||||
|
||||
#define NULL_EH_RANGE (&whole_range)
|
||||
|
||||
extern struct eh_range * find_handler PROTO ((int));
|
||||
|
||||
extern void method_init_exceptions PROTO ((void));
|
||||
|
||||
extern void emit_handlers PROTO ((void));
|
||||
|
5
gcc/java/java-opcodes.h
Normal file
5
gcc/java/java-opcodes.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
enum java_opcode {
|
||||
#define JAVAOP(NAME, CODE, KIND, TYPE, VALUE) OPCODE_##NAME = CODE,
|
||||
#include "javaop.def"
|
||||
#undef JAVAOP
|
||||
};
|
12
gcc/java/java-tree.def
Normal file
12
gcc/java/java-tree.def
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* Shift right, logical. */
|
||||
|
||||
DEFTREECODE (URSHIFT_EXPR, "urshift_expr", "2", 2)
|
||||
|
||||
/* Return -1, 0, 1 depending on whether the first argument is
|
||||
less, equal, or greater to the second argument. */
|
||||
DEFTREECODE (COMPARE_EXPR, "compare_expr", "2", 2)
|
||||
|
||||
/* Same as COMPARE_EXPR, but if either value is NaN, the result is -1. */
|
||||
DEFTREECODE (COMPARE_L_EXPR, "compare_l_expr", "2", 2)
|
||||
/* Same as COMPARE_EXPR, but if either value is NaN, the result is 1. */
|
||||
DEFTREECODE (COMPARE_G_EXPR, "compare_g_expr", "2", 2)
|
720
gcc/java/java-tree.h
Normal file
720
gcc/java/java-tree.h
Normal file
|
@ -0,0 +1,720 @@
|
|||
/* Definitions for parsing and type checking for the GNU compiler for
|
||||
the Java(TM) language.
|
||||
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* Hacked by Per Bothner <bothner@cygnus.com> February 1996. */
|
||||
|
||||
/* Java language-specific tree codes. */
|
||||
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
|
||||
enum java_tree_code {
|
||||
__DUMMY = LAST_AND_UNUSED_TREE_CODE,
|
||||
#include "java-tree.def"
|
||||
LAST_JAVA_TREE_CODE
|
||||
};
|
||||
#undef DEFTREECODE
|
||||
|
||||
struct JCF;
|
||||
|
||||
/* Usage of TREE_LANG_FLAG_?:
|
||||
0: IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (in IDENTIFIER_NODE)
|
||||
RESOLVE_EXPRESSION_NAME_P (in EXPR_WITH_FILE_LOCATION)
|
||||
IS_FOR_LOOP_P (in LOOP_EXPR)
|
||||
1: CLASS_HAS_SUPER_FLAG (in TREE_VEC).
|
||||
IS_A_CLASSFILE_NAME (in IDENTIFIER_NODE)
|
||||
COMPOUND_ASSIGN_P (in EXPR (binop_*))
|
||||
2: RETURN_MAP_ADJUSTED (in TREE_VEC).
|
||||
QUALIFIED_P (in IDENTIFIER_NODE)
|
||||
PRIMARY_P (in EXPR_WITH_FILE_LOCATION)
|
||||
MODIFY_EXPR_FROM_INITIALIZATION_P (in MODIFY_EXPR)
|
||||
3: IS_AN_IMPORT_ON_DEMAND_P (in IDENTIFIER_NODE)
|
||||
RESOLVE_PACKAGE_NAME_P (in EXPR_WITH_FILE_LOCATION)
|
||||
4: RESOLVE_TYPE_NAME_P (in EXPR_WITH_FILE_LOCATION)
|
||||
5: IS_BREAK_STMT_P (in EXPR_WITH_FILE_LOCATION)
|
||||
|
||||
Usage of TYPE_LANG_FLAG_?:
|
||||
1: TYPE_ARRAY_P (in RECORD_TYPE).
|
||||
2: CLASS_LOADED_P (in RECORD_TYPE).
|
||||
3: CLASS_FROM_SOURCE_P (in RECORD_TYPE).
|
||||
4: CLASS_P (in RECORD_TYPE).
|
||||
|
||||
Usage of DECL_LANG_FLAG_?:
|
||||
1: METHOD_PUBLIC (in FUNCTION_DECL).
|
||||
FIELD_PUBLIC (in FIELD_DECL).
|
||||
CLASS_PUBLIC (in TYPE_DECL).
|
||||
2: METHOD_STATIC (in FUNCTION_DECL).
|
||||
(But note that FIELD_STATIC uses TREE_STATIC!)
|
||||
CLASS_COMPLETE_P (in TYPE_DECL)
|
||||
3: METHOD_FINAL (in FUNCTION_DECL)
|
||||
FIELD_FINAL (in FIELD_DECL)
|
||||
CLASS_FINAL (in TYPE_DECL)
|
||||
4: METHOD_SYNCHRONIZED (in FUNCTION_DECL).
|
||||
LABEL_IN_SUBR (in LABEL_DECL)
|
||||
CLASS_INTERFACE (in TYPE_DECL)
|
||||
FIELD_VOLATILE (int FIELD_DECL)
|
||||
5: METHOD_ABSTRACT (in FUNCTION_DECL).
|
||||
LABEL_IS_SUBR_START (in LABEL_DECL)
|
||||
CLASS_ABSTRACT (in TYPE_DECL)
|
||||
FIELD_TRANSIENT (in FIELD_DECL)
|
||||
6: METHOD_TRANSIENT (in FUNCTION_DECL)
|
||||
LABEL_CHANGED (in LABEL_DECL)
|
||||
CLASS_SUPER (in TYPE_DECL, ACC_SUPER flag)
|
||||
INITIALIZED_P (in FIELD_DECL, VAR_DECL, PARM_DECL)
|
||||
7: DECL_CONSTRUCTOR_P (in FUNCTION_DECL)
|
||||
*/
|
||||
|
||||
/* True if the class whose TYPE_BINFO this is has a superclass.
|
||||
(True of all classes except Object.) */
|
||||
#define CLASS_HAS_SUPER_FLAG(BINFO) TREE_LANG_FLAG_1(BINFO)
|
||||
#define CLASS_HAS_SUPER(TYPE) CLASS_HAS_SUPER_FLAG (TYPE_BINFO (TYPE))
|
||||
|
||||
/* Return the supertype of class TYPE, or NULL_TREE is it has none. */
|
||||
#define CLASSTYPE_SUPER(TYPE) (CLASS_HAS_SUPER (TYPE) ? \
|
||||
BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (TYPE), 0)) : NULL_TREE)
|
||||
|
||||
/* True if the class we are compiling is a .java source file;
|
||||
false if it is a .class bytecode file. */
|
||||
extern int compiling_from_source;
|
||||
|
||||
/* The class defined by the actual (main) file we are compiling. */
|
||||
extern tree main_class;
|
||||
|
||||
/* The class we are currently processing. */
|
||||
extern tree current_class;
|
||||
|
||||
/* Nonzero if we want to automatically do array bounds checking;
|
||||
on by default. Use -fno-bounds-check to disable. */
|
||||
|
||||
extern int flag_bounds_check;
|
||||
|
||||
/* Nonzero if we should make is_compiled_class always return 1 for
|
||||
appropriate classes that we're referencing. */
|
||||
|
||||
extern int flag_assume_compiled;
|
||||
|
||||
extern int flag_emit_class_files;
|
||||
|
||||
/* The Java .class file that provides main_class; the main input file. */
|
||||
extern struct JCF main_jcf[1], *current_jcf;
|
||||
|
||||
typedef struct CPool constant_pool;
|
||||
|
||||
#define CONSTANT_ResolvedFlag 16
|
||||
|
||||
/* The cpool->data[i] for a ResolvedString points to a STRING_CST. */
|
||||
#define CONSTANT_ResolvedString (CONSTANT_String+CONSTANT_ResolvedFlag)
|
||||
|
||||
/* The cpool->data[i] for a ResolvedClass points to a RECORD_TYPE. */
|
||||
#define CONSTANT_ResolvedClass (CONSTANT_Class+CONSTANT_ResolvedFlag)
|
||||
|
||||
#define CPOOL_UTF(CPOOL, INDEX) ((tree) (CPOOL)->data[INDEX])
|
||||
|
||||
/* A NameAndType constant is represented as a TREE_LIST.
|
||||
The type is the signature string (as an IDENTIFIER_NODE). */
|
||||
|
||||
#define NAME_AND_TYPE_NAME(CPOOL, IDX) \
|
||||
CPOOL_UTF(CPOOL, CPOOL_USHORT1(CPOOL, IDX))
|
||||
#define NAME_AND_TYPE_SIGNATURE(CPOOL, IDX) \
|
||||
CPOOL_UTF(CPOOL, CPOOL_USHORT2(CPOOL, IDX))
|
||||
|
||||
/* A FieldRef, MethodRef or InterfaceMethodRef constant
|
||||
is represented as a TREE_LIST. */
|
||||
|
||||
#define COMPONENT_REF_CLASS_INDEX(CPOOL, IDX) CPOOL_USHORT1(CPOOL, IDX)
|
||||
#define COMPONENT_REF_NAME_AND_TYPE(CPOOL, IDX) CPOOL_USHORT2(CPOOL, IDX)
|
||||
#define COMPONENT_REF_NAME(CPOOL, IDX) \
|
||||
NAME_AND_TYPE_NAME (CPOOL, COMPONENT_REF_NAME_AND_TYPE(CPOOL, IDX))
|
||||
#define COMPONENT_REF_SIGNATURE(CPOOL, IDX) \
|
||||
NAME_AND_TYPE_SIGNATURE (CPOOL, COMPONENT_REF_NAME_AND_TYPE(CPOOL, IDX))
|
||||
|
||||
/* "Promoted types" that are used for primitive types smaller
|
||||
than int. We could use int_type_node, but then we would lose
|
||||
type information (such as needed for debugging). */
|
||||
extern tree promoted_byte_type_node;
|
||||
extern tree promoted_short_type_node;
|
||||
extern tree promoted_char_type_node;
|
||||
extern tree promoted_boolean_type_node;
|
||||
|
||||
extern tree byte_type_node;
|
||||
extern tree short_type_node;
|
||||
extern tree int_type_node;
|
||||
extern tree long_type_node;
|
||||
|
||||
extern tree unsigned_byte_type_node;
|
||||
extern tree unsigned_short_type_node;
|
||||
extern tree unsigned_int_type_node;
|
||||
extern tree unsigned_long_type_node;
|
||||
|
||||
extern tree boolean_type_node;
|
||||
extern tree char_type_node;
|
||||
extern tree float_type_node;
|
||||
extern tree double_type_node;
|
||||
|
||||
extern tree object_type_node;
|
||||
extern tree object_ptr_type_node;
|
||||
extern tree string_type_node;
|
||||
extern tree throwable_type_node;
|
||||
|
||||
extern tree byte_array_type_node;
|
||||
extern tree short_array_type_node;
|
||||
extern tree int_array_type_node;
|
||||
extern tree long_array_type_node;
|
||||
extern tree boolean_array_type_node;
|
||||
extern tree char_array_type_node;
|
||||
extern tree double_array_type_node;
|
||||
extern tree float_array_type_node;
|
||||
extern tree array_array_type_node;
|
||||
extern tree object_array_type_node;
|
||||
extern tree string_array_type_node;
|
||||
extern tree TYPE_identifier_node; /* "TYPE" */
|
||||
extern tree init_identifier_node; /* "<init>" */
|
||||
extern tree clinit_identifier_node; /* "<clinit>" */
|
||||
extern tree void_signature_node; /* "()V" */
|
||||
extern tree finalize_identifier_node; /* "finalize" */
|
||||
extern tree length_identifier_node; /* "length" */
|
||||
extern tree this_identifier_node; /* "this" */
|
||||
extern tree super_identifier_node; /* "super" */
|
||||
extern tree one_elt_array_domain_type;
|
||||
extern tree void_type_node;
|
||||
extern tree ptr_type_node;
|
||||
/* The type of the return address of a subroutine. */
|
||||
extern tree return_address_type_node;
|
||||
|
||||
/* Nodes for boolean constants TRUE and FALSE. */
|
||||
extern tree boolean_true_node, boolean_false_node;
|
||||
|
||||
/* Integer constants not declared in tree.h. */
|
||||
extern tree integer_negative_one_node;
|
||||
extern tree integer_two_node;
|
||||
extern tree integer_four_node;
|
||||
|
||||
/* The type for struct methodtable. */
|
||||
extern tree methodtable_type;
|
||||
extern tree methodtable_ptr_type;
|
||||
|
||||
extern tree utf8const_type;
|
||||
extern tree utf8const_ptr_type;
|
||||
|
||||
extern tree class_type_node;
|
||||
extern tree class_ptr_type;
|
||||
extern tree field_type_node;
|
||||
extern tree constants_type_node;
|
||||
extern tree dtable_type, dtable_ptr_type;
|
||||
extern tree field_ptr_type_node;
|
||||
extern tree field_info_union_node;
|
||||
extern tree method_type_node;
|
||||
extern tree method_ptr_type_node;
|
||||
#define nativecode_ptr_type_node ptr_type_node
|
||||
|
||||
/* References to internal libjava functions we use. */
|
||||
extern tree alloc_object_node;
|
||||
extern tree soft_instanceof_node;
|
||||
extern tree soft_checkcast_node;
|
||||
extern tree soft_initclass_node;
|
||||
extern tree soft_newarray_node;
|
||||
extern tree soft_anewarray_node;
|
||||
extern tree soft_multianewarray_node;
|
||||
extern tree soft_badarrayindex_node;
|
||||
extern tree throw_node;
|
||||
extern tree soft_checkarraystore_node;
|
||||
extern tree soft_monitorenter_node;
|
||||
extern tree soft_monitorexit_node;
|
||||
extern tree soft_lookupinterfacemethod_node;
|
||||
extern tree soft_fmod_node;
|
||||
|
||||
extern tree access_flags_type_node;
|
||||
|
||||
extern tree class_dtable_decl;
|
||||
|
||||
/* They need to be reset before processing each class */
|
||||
extern struct CPool *outgoing_cpool;
|
||||
extern tree current_constant_pool_data_ref;
|
||||
|
||||
|
||||
struct lang_identifier
|
||||
{
|
||||
struct tree_identifier ignore;
|
||||
tree global_value, local_value;
|
||||
|
||||
/* If non-NULL: An ADDR_REF to a VAR_DECL that contains
|
||||
* the Utf8Const representation of the identifier. */
|
||||
tree utf8_ref;
|
||||
};
|
||||
|
||||
/* Macros for access to language-specific slots in an identifier. */
|
||||
/* UNless specifide, each of these slots contains a DECL node or null. */
|
||||
|
||||
/* This represents the value which the identifier has in the
|
||||
file-scope namespace. */
|
||||
#define IDENTIFIER_GLOBAL_VALUE(NODE) \
|
||||
(((struct lang_identifier *)(NODE))->global_value)
|
||||
/* This represents the value which the identifier has in the current
|
||||
scope. */
|
||||
#define IDENTIFIER_LOCAL_VALUE(NODE) \
|
||||
(((struct lang_identifier *)(NODE))->local_value)
|
||||
|
||||
/* Given an identifier NODE, get the corresponding (non-handle) class.
|
||||
For get_identifier ("java.lang.Number"), the result is
|
||||
the struct whose DECL_ASSEMBLER_NAME is "Classjava_lang_Number". */
|
||||
#define IDENTIFIER_CLASS_VALUE(NODE) IDENTIFIER_GLOBAL_VALUE(NODE)
|
||||
|
||||
/* Given an identifier NODE, get the corresponding handle class.
|
||||
For get_identifier ("java.lang.Number"), the result is
|
||||
the struct whose DECL_ASSEMBLER_NAME is "Hjava_lang_Number". */
|
||||
#define IDENTIFIER_HANDLECLASS_VALUE(NODE) ???
|
||||
|
||||
/* Given a signature of a reference (or array) type, or a method, return the
|
||||
corresponding type (if one has been allocated).
|
||||
Do not use for primitive types, since they may be ambiguous.
|
||||
(E.g. is "I" a signature or a class name?) */
|
||||
#define IDENTIFIER_SIGNATURE_TYPE(NODE) IDENTIFIER_GLOBAL_VALUE(NODE)
|
||||
|
||||
/* If non-NULL: An ADDR_REF to a VAR_DECL that contains
|
||||
the Utf8Const representation of the identifier. */
|
||||
#define IDENTIFIER_UTF8_REF(NODE) \
|
||||
(((struct lang_identifier *)(NODE))->utf8_ref)
|
||||
|
||||
#define IDENTIFIER_UTF8_DECL(NODE) \
|
||||
TREE_OPERAND((((struct lang_identifier *)(NODE))->utf8_ref), 0)
|
||||
|
||||
/* For a FUNCTION_DECL, if we are compiling a .class file, then this is
|
||||
the position in the .class file of the method code.
|
||||
Specifically, this is the code itself, not the code attribute. */
|
||||
#define DECL_CODE_OFFSET(DECL) (DECL_LANG_SPECIFIC(DECL)->code_offset)
|
||||
/* Similarly, the length of the bytecode. */
|
||||
#define DECL_CODE_LENGTH(DECL) (DECL_LANG_SPECIFIC(DECL)->code_length)
|
||||
/* Similarly, the position of the LineNumberTable attribute. */
|
||||
#define DECL_LINENUMBERS_OFFSET(DECL) \
|
||||
(DECL_LANG_SPECIFIC(DECL)->linenumbers_offset)
|
||||
/* Similarly, the position of the LocalVariableTable attribute
|
||||
(following the standard attribute header). */
|
||||
#define DECL_LOCALVARIABLES_OFFSET(DECL) \
|
||||
(DECL_LANG_SPECIFIC(DECL)->localvariables_offset)
|
||||
|
||||
#define DECL_MAX_LOCALS(DECL) (DECL_LANG_SPECIFIC(DECL)->max_locals)
|
||||
#define DECL_MAX_STACK(DECL) (DECL_LANG_SPECIFIC(DECL)->max_stack)
|
||||
/* Number of local variable slots needed for the arguments of this function. */
|
||||
#define DECL_ARG_SLOT_COUNT(DECL) (DECL_LANG_SPECIFIC(DECL)->arg_slot_count)
|
||||
/* Pointer to the function's COMPOUND_EXPR tree */
|
||||
#define DECL_FUNCTION_BODY(DECL) (DECL_LANG_SPECIFIC(DECL)->function_decl_body)
|
||||
|
||||
/* In a LABEL_DECL, a TREE_VEC that saves the type_map at that point. */
|
||||
#define LABEL_TYPE_STATE(NODE) (DECL_INITIAL (NODE))
|
||||
|
||||
/* In the label of a subroutine, a dummy label that records the
|
||||
state following a merge of all the ret instructions in this subroutine. */
|
||||
#define LABEL_RETURN_LABEL(DECL) DECL_ARGUMENTS(DECL)
|
||||
|
||||
/* In the label of a sub-routine, records the type state at return.
|
||||
* A local may be TYPE_UNUSED, which means that the local is not
|
||||
* used (stored to or loaded from) in this subroutine - at least for
|
||||
* code that we have verified so far. */
|
||||
#define LABEL_RETURN_TYPE_STATE(NODE) LABEL_TYPE_STATE (LABEL_RETURN_LABEL (NODE))
|
||||
|
||||
/* In a TREE_VEC for a LABEL_RETURN_TYPE_STATE, notes that
|
||||
TREE_VEC_LENGTH has been adjust to the correct stack size. */
|
||||
#define RETURN_MAP_ADJUSTED(NODE) TREE_LANG_FLAG_2(NODE)
|
||||
|
||||
/* In the label of a sub-routine, a chain of the return location labels. */
|
||||
#define LABEL_RETURN_LABELS(node) DECL_RESULT (LABEL_RETURN_LABEL(node))
|
||||
|
||||
/* In a LABEL_DECL, the next pending label.
|
||||
See pending_blocks in expr.c. */
|
||||
#define LABEL_PENDING_CHAIN(NODE) DECL_RESULT(NODE)
|
||||
|
||||
/* In a LABEL_DECL, the corresponding bytecode program counter. */
|
||||
#define LABEL_PC(NODE) ((NODE)->decl.saved_insns.i)
|
||||
|
||||
/* Used during verification to mark the label has "changed". (See JVM Spec). */
|
||||
#define LABEL_CHANGED(NODE) DECL_LANG_FLAG_6(NODE)
|
||||
|
||||
/* In a LABEL_DECL, true if we have verified instructions starting here. */
|
||||
#define LABEL_VERIFIED(NODE) (instruction_bits[LABEL_PC(NODE)]&BCODE_VERIFIED)
|
||||
|
||||
/* True if this code is within a subroutine (target of a jsr). */
|
||||
#define LABEL_IN_SUBR(NODE) DECL_LANG_FLAG_4(NODE)
|
||||
/* True if this code is the start of a subroutine (target of a jsr). */
|
||||
#define LABEL_IS_SUBR_START(NODE) DECL_LANG_FLAG_5(NODE)
|
||||
|
||||
/* In a LABEL_DECL, if LABEL_IN_SUBR(NODE), points to start of subroutine. */
|
||||
#define LABEL_SUBR_START(NODE) DECL_ABSTRACT_ORIGIN(NODE)
|
||||
|
||||
/* In a LABEL_DECL that has LABEL_IS_SUBR_START, this points to the start
|
||||
of surrounding subroutine in the case of a nested subroutine,
|
||||
and NULL_TREE otherwise. */
|
||||
#define LABEL_SUBR_CONTEXT(NODE) DECL_CONTEXT (LABEL_RETURN_LABEL (NODE))
|
||||
|
||||
/* The slot number for this local variable. */
|
||||
#define DECL_LOCAL_SLOT_NUMBER(NODE) \
|
||||
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->slot_number)
|
||||
/* The start (bytecode) pc for the valid range of this local variable. */
|
||||
#define DECL_LOCAL_START_PC(NODE) \
|
||||
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->start_pc)
|
||||
/* The end (bytecode) pc for the valid range of this local variable. */
|
||||
#define DECL_LOCAL_END_PC(NODE) \
|
||||
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->end_pc)
|
||||
/* For a VAR_DECLor PARM_DECL, used to chain decls with the same
|
||||
slot_number in decl_map. */
|
||||
#define DECL_LOCAL_SLOT_CHAIN(NODE) \
|
||||
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->slot_chain)
|
||||
|
||||
/* DECL_LANG_SPECIFIC for FUNCTION_DECLs. */
|
||||
struct lang_decl
|
||||
{
|
||||
/* tree chain; not yet used. */
|
||||
long code_offset;
|
||||
int code_length;
|
||||
long linenumbers_offset;
|
||||
long localvariables_offset;
|
||||
int arg_slots;
|
||||
int max_locals, max_stack, arg_slot_count;
|
||||
tree function_decl_body; /* Hold all function's statements */
|
||||
};
|
||||
|
||||
/* DECL_LANG_SPECIFIC for VAR_DECL and PARM_DECL. */
|
||||
struct lang_decl_var
|
||||
{
|
||||
int slot_number;
|
||||
int start_pc;
|
||||
int end_pc;
|
||||
tree slot_chain;
|
||||
};
|
||||
|
||||
struct lang_type
|
||||
{
|
||||
tree signature;
|
||||
struct JCF *jcf;
|
||||
};
|
||||
|
||||
#ifdef JAVA_USE_HANDLES
|
||||
/* TYPE_BINFO_HANDLE points from a handle-class to its corresponding
|
||||
non-handle-class, and vice verse. */
|
||||
|
||||
#define BINFO_HANDLE(NODE) TREE_VEC_ELT ((NODE), 6)
|
||||
|
||||
/* Given a RECORD_TYPE for a handle type, return the corresponding class. */
|
||||
#define HANDLE_TO_CLASS_TYPE(HTYPE) BINFO_HANDLE (TYPE_BINFO (HTYPE))
|
||||
|
||||
/* Given a RECORD_TYPE for a class, return the corresponding handle type. */
|
||||
#define CLASS_TO_HANDLE_TYPE(TYPE) BINFO_HANDLE (TYPE_BINFO (TYPE))
|
||||
#else
|
||||
#define HANDLE_TO_CLASS_TYPE(HTYPE) (HTYPE)
|
||||
#define CLASS_TO_HANDLE_TYPE(TYPE) (TYPE)
|
||||
#endif
|
||||
|
||||
#define JCF_u4 unsigned long
|
||||
#define JCF_u2 unsigned short
|
||||
|
||||
extern tree lookup_class PROTO ((tree));
|
||||
extern tree lookup_java_constructor PROTO ((tree, tree));
|
||||
extern tree lookup_java_method PROTO ((tree, tree, tree));
|
||||
extern tree lookup_argument_method PROTO ((tree, tree, tree));
|
||||
extern tree promote_type PROTO ((tree));
|
||||
extern tree get_constant PROTO ((struct JCF*, int));
|
||||
extern tree get_name_constant PROTO ((struct JCF*, int));
|
||||
extern tree get_class_constant PROTO ((struct JCF*, int));
|
||||
extern tree parse_signature PROTO ((struct JCF *jcf, int sig_index));
|
||||
extern int jcf_parse PROTO ((struct JCF*));
|
||||
extern tree add_field PROTO ((tree, tree, tree, int));
|
||||
extern tree add_method PROTO ((tree, int, tree, tree));
|
||||
extern tree add_method_1 PROTO ((tree, int, tree, tree));
|
||||
extern tree make_class ();
|
||||
extern tree push_class PROTO ((tree, tree));
|
||||
extern tree unmangle_classname PROTO ((const char *name, int name_length));
|
||||
extern tree parse_signature_string PROTO ((const unsigned char *, int));
|
||||
extern tree get_type_from_signature PROTO ((tree));
|
||||
extern void layout_class PROTO ((tree));
|
||||
extern tree make_class ();
|
||||
extern tree build_class_ref PROTO ((tree));
|
||||
extern tree build_dtable_decl PROTO ((tree));
|
||||
extern tree build_internal_class_name PROTO ((tree));
|
||||
extern tree build_constants_constructor ();
|
||||
extern tree build_ref_from_constant_pool PROTO ((int));
|
||||
extern tree build_utf8_ref PROTO ((tree));
|
||||
extern tree ident_subst PROTO ((const char*, int,
|
||||
const char*, int, int, const char*));
|
||||
extern tree identifier_subst PROTO ((const tree,
|
||||
const char *, int, int, const char *));
|
||||
extern tree build_java_signature PROTO ((tree));
|
||||
extern tree build_java_argument_signature PROTO ((tree));
|
||||
extern void set_java_signature PROTO ((tree, tree));
|
||||
extern tree build_static_field_ref PROTO ((tree));
|
||||
extern tree build_address_of PROTO ((tree));
|
||||
extern tree find_local_variable PROTO ((int index, tree type, int pc));
|
||||
extern tree find_stack_slot PROTO ((int index, tree type));
|
||||
extern tree build_prim_array_type PROTO ((tree, HOST_WIDE_INT));
|
||||
extern tree build_java_array_type PROTO ((tree, HOST_WIDE_INT));
|
||||
extern int is_compiled_class PROTO ((tree));
|
||||
extern tree mangled_classname PROTO ((char*, tree));
|
||||
extern tree lookup_label PROTO ((int));
|
||||
extern tree pop_type PROTO ((tree));
|
||||
extern void pop_argument_types PROTO ((tree));
|
||||
extern tree decode_newarray_type PROTO ((int));
|
||||
extern tree lookup_field PROTO ((tree*, tree));
|
||||
extern int is_array_type_p PROTO ((tree));
|
||||
extern HOST_WIDE_INT java_array_type_length PROTO ((tree));
|
||||
extern void load_class PROTO ((tree, int));
|
||||
|
||||
extern tree lookup_name PROTO ((tree));
|
||||
extern tree build_known_method_ref PROTO ((tree, tree, tree, tree, tree));
|
||||
extern tree build_class_init PROTO ((tree, tree));
|
||||
extern tree build_invokevirtual PROTO ((tree, tree));
|
||||
extern tree invoke_build_dtable PROTO ((int, tree));
|
||||
extern tree match_java_method PROTO ((tree, tree, tree));
|
||||
extern tree build_field_ref PROTO ((tree, tree, tree));
|
||||
extern void pushdecl_force_head PROTO ((tree));
|
||||
extern tree build_java_binop PROTO ((enum tree_code, tree, tree, tree));
|
||||
extern tree binary_numeric_promotion PROTO ((tree, tree, tree *, tree *));
|
||||
extern tree build_decl_no_layout PROTO ((enum tree_code, tree, tree));
|
||||
extern tree build_java_arrayaccess PROTO ((tree, tree, tree));
|
||||
extern tree build_newarray PROTO ((int, tree));
|
||||
extern tree build_anewarray PROTO ((tree, tree));
|
||||
extern tree build_java_array_length_access PROTO ((tree));
|
||||
extern tree build_java_arraynull_check PROTO ((tree, tree, tree));
|
||||
extern tree create_label_decl PROTO ((tree));
|
||||
extern void push_labeled_block PROTO ((tree));
|
||||
|
||||
/* Access flags etc for a method (a FUNCTION_DECL): */
|
||||
|
||||
#define METHOD_PUBLIC(DECL) DECL_LANG_FLAG_1 (DECL)
|
||||
#define METHOD_PRIVATE(DECL) TREE_PRIVATE (DECL)
|
||||
#define METHOD_PROTECTED(DECL) TREE_PROTECTED (DECL)
|
||||
#define METHOD_STATIC(DECL) DECL_LANG_FLAG_2 (DECL)
|
||||
#define METHOD_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
|
||||
#define METHOD_SYNCHRONIZED(DECL) DECL_LANG_FLAG_4 (DECL)
|
||||
#define METHOD_NATIVE(DECL) DECL_EXTERNAL(DECL)
|
||||
#define METHOD_ABSTRACT(DECL) DECL_LANG_FLAG_5 (DECL)
|
||||
#define METHOD_TRANSIENT(DECL) DECL_LANG_FLAG_6 (DECL)
|
||||
|
||||
#define DECL_CONSTRUCTOR_P(DECL) DECL_LANG_FLAG_7(DECL)
|
||||
|
||||
/* Access flags etc for a variable/field (a FIELD_DECL): */
|
||||
|
||||
#define FIELD_PRIVATE(DECL) TREE_PRIVATE (DECL)
|
||||
#define FIELD_PROTECTED(DECL) TREE_PROTECTED (DECL)
|
||||
#define FIELD_PUBLIC(DECL) DECL_LANG_FLAG_1 (DECL)
|
||||
#define FIELD_STATIC(DECL) TREE_STATIC (DECL)
|
||||
#define FIELD_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
|
||||
#define FIELD_VOLATILE(DECL) DECL_LANG_FLAG_4 (DECL)
|
||||
#define FIELD_TRANSIENT(DECL) DECL_LANG_FLAG_5 (DECL)
|
||||
|
||||
/* Initialized flag on variable/field/parm decl */
|
||||
|
||||
#define INITIALIZED_P(DECL) DECL_LANG_FLAG_6 (DECL)
|
||||
|
||||
/* Access flags etc for a class (a TYPE_DECL): */
|
||||
|
||||
#define CLASS_PUBLIC(DECL) DECL_LANG_FLAG_1 (DECL)
|
||||
#define CLASS_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
|
||||
#define CLASS_INTERFACE(DECL) DECL_LANG_FLAG_4 (DECL)
|
||||
#define CLASS_ABSTRACT(DECL) DECL_LANG_FLAG_5 (DECL)
|
||||
#define CLASS_SUPER(DECL) DECL_LANG_FLAG_6 (DECL)
|
||||
|
||||
/* The number of virtual methods in this class's dispatch table.
|
||||
Does not include initial two dummy entries (one points to the
|
||||
Class object, and the other is for G++ -fvtable-thunks compatibility). */
|
||||
#define TYPE_NVIRTUALS(TYPE) TYPE_BINFO_VIRTUALS (TYPE)
|
||||
|
||||
/* A TREE_VEC (indexed by DECL_VINDEX) containing this class's
|
||||
virtual methods. */
|
||||
#define TYPE_VTABLE(TYPE) TYPE_BINFO_VTABLE(TYPE)
|
||||
|
||||
/* True of a RECORD_TYPE of a class/interface type (not array type) */
|
||||
#define CLASS_P(TYPE) TYPE_LANG_FLAG_4 (TYPE)
|
||||
/* Use CLASS_LOADED_P? FIXME */
|
||||
#define CLASS_COMPLETE_P(DECL) DECL_LANG_FLAG_2 (DECL)
|
||||
|
||||
/* This maps a bytecode offset (PC) to various flags,
|
||||
listed below (starting with BCODE_). */
|
||||
extern char *instruction_bits;
|
||||
|
||||
/* True iff the byte is the start of an instruction. */
|
||||
#define BCODE_INSTRUCTION_START 1
|
||||
|
||||
/* True iff there is a jump to this location. */
|
||||
#define BCODE_JUMP_TARGET 2
|
||||
|
||||
/* True iff there is a return to this location.
|
||||
(I.e. the preceedng instruction was a call.) */
|
||||
#define BCODE_RETURN_TARGET 4
|
||||
|
||||
/* True iff this is the start of an exception handler. */
|
||||
#define BCODE_EXCEPTION_TARGET 16
|
||||
|
||||
/* True iff there is a jump to this location (and it needs a label). */
|
||||
#define BCODE_TARGET \
|
||||
(BCODE_JUMP_TARGET|BCODE_RETURN_TARGET \
|
||||
| BCODE_EXCEPTION_TARGET)
|
||||
|
||||
/* True iff there is an entry in the linenumber table for this location. */
|
||||
#define BCODE_HAS_LINENUMBER 32
|
||||
|
||||
/* True iff there is more than one entry in the linenumber table for
|
||||
this location. (This probably does not make much sense.) */
|
||||
#define BCODE_HAS_MULTI_LINENUMBERS 64
|
||||
|
||||
/* True if this instruction has been verified. */
|
||||
#define BCODE_VERIFIED 8
|
||||
|
||||
/* A pointer to the line number table of the current method. */
|
||||
extern unsigned char *linenumber_table;
|
||||
/* The length (in items) of the line number table. */
|
||||
extern int linenumber_count;
|
||||
|
||||
/* In type_map, means that slot is uninitialized or otherwise unusable. */
|
||||
#define TYPE_UNKNOWN NULL_TREE
|
||||
|
||||
/* In type_map, means the second half of a 64-bit double or long. */
|
||||
#define TYPE_SECOND void_type_node
|
||||
|
||||
/* In type_map, means the null type (i.e. type of a null reference). */
|
||||
#define TYPE_NULL ptr_type_node
|
||||
|
||||
/* In a type map means the type the address subroutine return address. */
|
||||
#define TYPE_RETURN_ADDR return_address_type_node
|
||||
|
||||
/* In a subroutine's return type map, indicates that the slot was neither
|
||||
used nor set in the subroutine. */
|
||||
#define TYPE_UNUSED error_mark_node
|
||||
|
||||
/* A array mapping variable/stack slot index to the type current
|
||||
in that variable/stack slot.
|
||||
TYPE_UNKNOWN, TYPE_SECOND, and TYPE_NULL are special cases. */
|
||||
extern tree *type_map;
|
||||
|
||||
/* Map a stack index to the type currently in that slot. */
|
||||
#define stack_type_map (type_map+DECL_MAX_LOCALS(current_function_decl))
|
||||
|
||||
/* True iff TYPE takes two variable/stack slots. */
|
||||
#define TYPE_IS_WIDE(TYPE) \
|
||||
((TYPE) == double_type_node || (TYPE) == long_type_node)
|
||||
|
||||
/* True iff TYPE is a Java array type. */
|
||||
#define TYPE_ARRAY_P(TYPE) TYPE_LANG_FLAG_1 (TYPE)
|
||||
|
||||
/* If FUNCTION_TYPE or METHOD_TYPE: cache for build_java_argument_signature. */
|
||||
#define TYPE_ARGUMENT_SIGNATURE(TYPE) TYPE_VFIELD(TYPE)
|
||||
|
||||
/* Given an array type, give the type of the elements. */
|
||||
/* FIXME this use of TREE_TYPE conflicts with something or other. */
|
||||
#define TYPE_ARRAY_ELEMENT(ATYPE) TREE_TYPE(ATYPE)
|
||||
|
||||
/* True if class TYPE has been loaded. */
|
||||
#define CLASS_LOADED_P(TYPE) TYPE_LANG_FLAG_2 (TYPE)
|
||||
|
||||
/* True if class TYPE was defined in Java source code. */
|
||||
#define CLASS_FROM_SOURCE_P(TYPE) TYPE_LANG_FLAG_3 (TYPE)
|
||||
|
||||
/* True if identifier ID was seen while processing a single type import stmt */
|
||||
#define IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P(ID) TREE_LANG_FLAG_0 (ID)
|
||||
|
||||
/* True if identifier ID was seen while processing an import statement */
|
||||
#define IS_A_CLASSFILE_NAME(ID) TREE_LANG_FLAG_1 (ID)
|
||||
|
||||
/* True if ID is a qualified named (contains . or /) */
|
||||
#define QUALIFIED_P(ID) TREE_LANG_FLAG_2 (ID)
|
||||
|
||||
/* True if ID is an already processed import on demand */
|
||||
#define IS_AN_IMPORT_ON_DEMAND_P(ID) TREE_LANG_FLAG_3 (ID)
|
||||
|
||||
/* True if EXPR is RHS sub-tree of a compound assign expression */
|
||||
#define COMPOUND_ASSIGN_P(EXPR) TREE_LANG_FLAG_1 (EXPR)
|
||||
|
||||
/* True if EXPR (a WFL in that case) was created after the
|
||||
reduction of PRIMARY . XXX */
|
||||
#define PRIMARY_P(EXPR) TREE_LANG_FLAG_2 (EXPR)
|
||||
|
||||
/* True if EXPR (a MODIFY_EXPR in that case) is the result of variable
|
||||
initialization during its declaration */
|
||||
#define MODIFY_EXPR_FROM_INITIALIZATION_P(EXPR) TREE_LANG_FLAG_2 (EXPR)
|
||||
|
||||
/* True if EXPR (a WFL in that case) resolves into an expression name */
|
||||
#define RESOLVE_EXPRESSION_NAME_P(WFL) TREE_LANG_FLAG_0 (WFL)
|
||||
|
||||
/* True if EXPR (a LOOP_EXPR in that case) is part of a for statement */
|
||||
#define IS_FOR_LOOP_P(EXPR) TREE_LANG_FLAG_0 (EXPR)
|
||||
|
||||
/* True if EXPR (a WFL in that case) resolves into a package name */
|
||||
#define RESOLVE_PACKAGE_NAME_P(WFL) TREE_LANG_FLAG_3 (WFL)
|
||||
|
||||
/* True if EXPR (a WFL in that case) resolves into a type name */
|
||||
#define RESOLVE_TYPE_NAME_P(WFL) TREE_LANG_FLAG_4 (WFL)
|
||||
|
||||
/* True if STMT (a WFL in that case) holds a BREAK statement */
|
||||
#define IS_BREAK_STMT_P(WFL) TREE_LANG_FLAG_5 (WFL)
|
||||
|
||||
/* Add a FIELD_DECL to RECORD_TYPE RTYPE.
|
||||
The field has name NAME (a char*), and type FTYPE.
|
||||
Unless this is the first field, FIELD most hold the previous field.
|
||||
FIELD is set to the newly created FIELD_DECL.
|
||||
|
||||
We set DECL_ARTIFICIAL so these fields get skipped by make_class_data
|
||||
if compiling java.lang.Object or java.lang.Class. */
|
||||
|
||||
#define PUSH_FIELD(RTYPE, FIELD, NAME, FTYPE) \
|
||||
{ tree tmp_field = build_decl (FIELD_DECL, get_identifier(NAME), FTYPE); \
|
||||
if (TYPE_FIELDS (RTYPE) == NULL_TREE) TYPE_FIELDS (RTYPE) = tmp_field; \
|
||||
else TREE_CHAIN(FIELD) = tmp_field; \
|
||||
DECL_CONTEXT (tmp_field) = RTYPE; \
|
||||
DECL_ARTIFICIAL (tmp_field) = 1; \
|
||||
FIELD = tmp_field; }
|
||||
|
||||
#define FINISH_RECORD(RTYPE) layout_type (RTYPE)
|
||||
|
||||
/* Start building a RECORD_TYPE constructor with a given TYPE in CONS. */
|
||||
#define START_RECORD_CONSTRUCTOR(CONS, CTYPE) { \
|
||||
CONS = build (CONSTRUCTOR, CTYPE, NULL_TREE, NULL_TREE);\
|
||||
TREE_CHAIN(CONS) = TYPE_FIELDS (CTYPE); }
|
||||
|
||||
/* Append a field initializer to CONS for the dummy field for the inherited
|
||||
fields. The dummy field has the given VALUE, and the same type as the
|
||||
super-class. Must be specified before calls to PUSH_FIELD_VALUE. */
|
||||
|
||||
#define PUSH_SUPER_VALUE(CONS, VALUE) {\
|
||||
tree field = TREE_CHAIN(CONS);\
|
||||
if (DECL_NAME (field) != NULL_TREE) abort();\
|
||||
CONSTRUCTOR_ELTS(CONS) = tree_cons (field, VALUE, CONSTRUCTOR_ELTS(CONS));\
|
||||
TREE_CHAIN(CONS) = TREE_CHAIN (field); }
|
||||
|
||||
/* Append a field initializer to CONS for a field with the given VALUE.
|
||||
NAME is a char* string used for error checking;
|
||||
the initializer must be specified in order. */
|
||||
#define PUSH_FIELD_VALUE(CONS, NAME, VALUE) {\
|
||||
tree field = TREE_CHAIN(CONS);\
|
||||
if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), NAME) != 0) abort();\
|
||||
CONSTRUCTOR_ELTS(CONS) = tree_cons (field, VALUE, CONSTRUCTOR_ELTS(CONS));\
|
||||
TREE_CHAIN(CONS) = TREE_CHAIN (field); }
|
||||
|
||||
/* Finish creating a record CONSTRUCTOR CONS. */
|
||||
#define FINISH_RECORD_CONSTRUCTOR(CONS) \
|
||||
CONSTRUCTOR_ELTS(CONS) = nreverse (CONSTRUCTOR_ELTS(CONS))
|
||||
|
||||
/* New tree code for expression, so we can expand then individually. */
|
||||
#define JAVA_UNARY_PLUS_EXPR ((int)LAST_AND_UNUSED_TREE_CODE + 2)
|
||||
#define JAVA_NEW_ARRAY_EXPR ((int)LAST_AND_UNUSED_TREE_CODE + 3)
|
||||
#define JAVA_NEW_CLASS_EXPR ((int)LAST_AND_UNUSED_TREE_CODE + 4)
|
||||
#define JAVA_THIS_EXPR ((int)LAST_AND_UNUSED_TREE_CODE + 5)
|
||||
|
||||
/* Macro(s) using the definitions above */
|
||||
#define CALL_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == JAVA_NEW_CLASS_EXPR)
|
||||
|
314
gcc/java/javaop.def
Normal file
314
gcc/java/javaop.def
Normal file
|
@ -0,0 +1,314 @@
|
|||
/* Table of opcodes for byte codes defined by the Java(TM) virtual
|
||||
machine specification.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc.
|
||||
|
||||
Written by Per Bothner <bothner@cygnus.com>, February 1996.
|
||||
*/
|
||||
|
||||
/* JAVAOP (OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE), where:
|
||||
OPNAME is the name of the opcode.
|
||||
OPCODE is the 1-byte opcode value.
|
||||
OPKIND is the kind of operation.
|
||||
OPERAND_TYPE is the type operands affected.
|
||||
OPERAND_VALUE tells where to get the value. (Its meaning
|
||||
depends on OPKIND.) */
|
||||
|
||||
/* Various macro used in OPERAND_VALUE:
|
||||
IMMEDIATE_s1: An immediate signed 1-byte value in the byte-code stream.
|
||||
IMMEDIATE_s2: An immediate signed 2-byte value in the byte-code stream.
|
||||
IMMEDIATE_u1: An immediate unsigned 1-byte value in the byte-code stream.
|
||||
IMMEDIATE_u2: An immediate unsigned 2-byte value in the byte-code stream.
|
||||
|
||||
CONST_INDEX_1: An immediate unsigned 1-byte index into the constant pool.
|
||||
CONST_INDEX_2: An immediate unsigned 2-byte index into the constant pool.
|
||||
*/
|
||||
|
||||
/* More specifically, this is the meaning of the various OPKINDs:
|
||||
|
||||
BINOP: binary operation
|
||||
OPERAND_TYPE is the argument type.
|
||||
OPERAND_VALUE is PLUS, MINUS, MULT, TRUNC_DIV, RDIV, REM,
|
||||
LSHIFT, RSHIFT, URSHIFT, BIT_AND, BIT_IOR, BIT_XOR,
|
||||
COMPARE, COMPARE_L, or COMPARE_G.
|
||||
|
||||
UNOP: unary operation
|
||||
OPERAND_TYPE is the argument type.
|
||||
OPERAND_VALUE is NEG.
|
||||
|
||||
INVOKE: invoke operations
|
||||
OPERAND_TYPE is VIRTUAL, SPECIAL, STATIC, or INTERFACE.
|
||||
OPERAND_VALUE is 1 if interface, 0 otherwise.
|
||||
|
||||
OBJECT: new, checkcast, instanceof
|
||||
OPERAND_TYPE is PTR.
|
||||
OPERAND_VALUE is NEW, CHECKCAST, or INSTANCEOF.
|
||||
|
||||
BRANCH: branch operations
|
||||
OPERAND_TYPE is GOTO, CALL, or RETURN.
|
||||
OPERAND_VALUE is IMMEDIATE_s2, VAR_INDEX_1, IMMEDIATE_s4,
|
||||
or VAR_INDEX_2.
|
||||
|
||||
STACK: Various stack operations.
|
||||
|
||||
PUSHC: Push a constant onto the operand stack.
|
||||
OPERAND_VALUE maybe be the value to push,
|
||||
or IMMEDIATE_s1 or IMMEDIATE_s2 if the constant is immediate,
|
||||
or CONST_INDEX_1 or CONST_INDEX_2 for a constant pool index.
|
||||
|
||||
LOAD: Push a value from a local variable onto the operand stack.
|
||||
OPERAND_VALUE is the index of the local variable in the current
|
||||
Java frame. It can be a literal, or IMMEDIATE_i2.
|
||||
|
||||
CONVERT: Convert top of stack value from one type to another.
|
||||
OPERAND_TYPE is the argument type.
|
||||
OPERAND_VALUE is the result type.
|
||||
|
||||
TEST: Compares an integer (popped from the stack) against zero.
|
||||
If the test (in OPERAND_VALUE) is true, goto a relative
|
||||
offset given by the next two bytes.
|
||||
|
||||
COND: Compares two values (popped from the stack) againt each other.
|
||||
If the test (in OPERAND_VALUE) is true, goto a relative
|
||||
offset given by the next two bytes.
|
||||
|
||||
SWITCH:
|
||||
OPERAND_VALUE is either TABLE or LOOKUP.
|
||||
|
||||
ARRAY:
|
||||
OPERAND_VALUE is LOAD, STORE, LENGTH, or NEW.
|
||||
|
||||
FIELD: Extracts from or stores into a field.
|
||||
OPERAND_TYPE is 1 for a static field, 0 for a regular field.
|
||||
OPERAND_VALUE is 1 for a put operation, 0 for a get operation.
|
||||
|
||||
SPECIAL:
|
||||
Random bunch of opcodes.
|
||||
|
||||
*/
|
||||
|
||||
JAVAOP (nop, 0, STACK, POP, 0)
|
||||
JAVAOP (aconst_null, 1, PUSHC, PTR, 0)
|
||||
JAVAOP (iconst_m1, 2, PUSHC, INT, -1)
|
||||
JAVAOP (iconst_0, 3, PUSHC, INT, 0)
|
||||
JAVAOP (iconst_1, 4, PUSHC, INT, 1)
|
||||
JAVAOP (iconst_2, 5, PUSHC, INT, 2)
|
||||
JAVAOP (iconst_3, 6, PUSHC, INT, 3)
|
||||
JAVAOP (iconst_4, 7, PUSHC, INT, 4)
|
||||
JAVAOP (iconst_5, 8, PUSHC, INT, 5)
|
||||
JAVAOP (lconst_0, 9, PUSHC, LONG, 0)
|
||||
JAVAOP (lconst_1, 10, PUSHC, LONG, 1)
|
||||
JAVAOP (fconst_0, 11, PUSHC, FLOAT, 0)
|
||||
JAVAOP (fconst_1, 12, PUSHC, FLOAT, 1)
|
||||
JAVAOP (fconst_2, 13, PUSHC, FLOAT, 2)
|
||||
JAVAOP (dconst_0, 14, PUSHC, DOUBLE, 0)
|
||||
JAVAOP (dconst_1, 15, PUSHC, DOUBLE, 1)
|
||||
JAVAOP (bipush, 16, PUSHC, INT, IMMEDIATE_s1)
|
||||
JAVAOP (sipush, 17, PUSHC, INT, IMMEDIATE_s2)
|
||||
JAVAOP (ldc, 18, PUSHC, INT, CONST_INDEX_1)
|
||||
JAVAOP (ldc_w, 19, PUSHC, INT, CONST_INDEX_2)
|
||||
JAVAOP (ldc2_w, 20, PUSHC, LONG, CONST_INDEX_2)
|
||||
JAVAOP (iload, 21, LOAD, INT, IMMEDIATE_u1)
|
||||
JAVAOP (lload, 22, LOAD, LONG, IMMEDIATE_u1)
|
||||
JAVAOP (fload, 23, LOAD, FLOAT, IMMEDIATE_u1)
|
||||
JAVAOP (dload, 24, LOAD, DOUBLE, IMMEDIATE_u1)
|
||||
JAVAOP (aload, 25, LOAD, PTR, IMMEDIATE_u1)
|
||||
JAVAOP (iload_0, 26, LOAD, INT, 0)
|
||||
JAVAOP (iload_1, 27, LOAD, INT, 1)
|
||||
JAVAOP (iload_2, 28, LOAD, INT, 2)
|
||||
JAVAOP (iload_3, 29, LOAD, INT, 3)
|
||||
JAVAOP (lload_0, 30, LOAD, LONG, 0)
|
||||
JAVAOP (lload_1, 31, LOAD, LONG, 1)
|
||||
JAVAOP (lload_2, 32, LOAD, LONG, 2)
|
||||
JAVAOP (lload_3, 33, LOAD, LONG, 3)
|
||||
JAVAOP (fload_0, 34, LOAD, FLOAT, 0)
|
||||
JAVAOP (fload_1, 35, LOAD, FLOAT, 1)
|
||||
JAVAOP (fload_2, 36, LOAD, FLOAT, 2)
|
||||
JAVAOP (fload_3, 37, LOAD, FLOAT, 3)
|
||||
JAVAOP (dload_0, 38, LOAD, DOUBLE, 0)
|
||||
JAVAOP (dload_1, 39, LOAD, DOUBLE, 1)
|
||||
JAVAOP (dload_2, 40, LOAD, DOUBLE, 2)
|
||||
JAVAOP (dload_3, 41, LOAD, DOUBLE, 3)
|
||||
JAVAOP (aload_0, 42, LOAD, PTR, 0)
|
||||
JAVAOP (aload_1, 43, LOAD, PTR, 1)
|
||||
JAVAOP (aload_2, 44, LOAD, PTR, 2)
|
||||
JAVAOP (aload_3, 45, LOAD, PTR, 3)
|
||||
JAVAOP (iaload, 46, ARRAY, INT, LOAD)
|
||||
JAVAOP (laload, 47, ARRAY, LONG, LOAD)
|
||||
JAVAOP (faload, 48, ARRAY, FLOAT, LOAD)
|
||||
JAVAOP (daload, 49, ARRAY, DOUBLE, LOAD)
|
||||
JAVAOP (aaload, 50, ARRAY, PTR, LOAD)
|
||||
JAVAOP (baload, 51, ARRAY, BYTE, LOAD)
|
||||
JAVAOP (caload, 52, ARRAY, CHAR, LOAD)
|
||||
JAVAOP (saload, 53, ARRAY, SHORT, LOAD)
|
||||
JAVAOP (istore, 54, STORE, INT, IMMEDIATE_u1)
|
||||
JAVAOP (lstore, 55, STORE, LONG, IMMEDIATE_u1)
|
||||
JAVAOP (fstore, 56, STORE, FLOAT, IMMEDIATE_u1)
|
||||
JAVAOP (dstore, 57, STORE, DOUBLE, IMMEDIATE_u1)
|
||||
JAVAOP (astore, 58, STORE, PTR, IMMEDIATE_u1)
|
||||
JAVAOP (istore_0, 59, STORE, INT, 0)
|
||||
JAVAOP (istore_1, 60, STORE, INT, 1)
|
||||
JAVAOP (istore_2, 61, STORE, INT, 2)
|
||||
JAVAOP (istore_3, 62, STORE, INT, 3)
|
||||
JAVAOP (lstore_0, 63, STORE, LONG, 0)
|
||||
JAVAOP (lstore_1, 64, STORE, LONG, 1)
|
||||
JAVAOP (lstore_2, 65, STORE, LONG, 2)
|
||||
JAVAOP (lstore_3, 66, STORE, LONG, 3)
|
||||
JAVAOP (fstore_0, 67, STORE, FLOAT, 0)
|
||||
JAVAOP (fstore_1, 68, STORE, FLOAT, 1)
|
||||
JAVAOP (fstore_2, 69, STORE, FLOAT, 2)
|
||||
JAVAOP (fstore_3, 70, STORE, FLOAT, 3)
|
||||
JAVAOP (dstore_0, 71, STORE, DOUBLE, 0)
|
||||
JAVAOP (dstore_1, 72, STORE, DOUBLE, 1)
|
||||
JAVAOP (dstore_2, 73, STORE, DOUBLE, 2)
|
||||
JAVAOP (dstore_3, 74, STORE, DOUBLE, 3)
|
||||
JAVAOP (astore_0, 75, STORE, PTR, 0)
|
||||
JAVAOP (astore_1, 76, STORE, PTR, 1)
|
||||
JAVAOP (astore_2, 77, STORE, PTR, 2)
|
||||
JAVAOP (astore_3, 78, STORE, PTR, 3)
|
||||
JAVAOP (iastore, 79, ARRAY, INT, STORE)
|
||||
JAVAOP (lastore, 80, ARRAY, LONG, STORE)
|
||||
JAVAOP (fastore, 81, ARRAY, FLOAT, STORE)
|
||||
JAVAOP (dastore, 82, ARRAY, DOUBLE, STORE)
|
||||
JAVAOP (aastore, 83, ARRAY, PTR, STORE)
|
||||
JAVAOP (bastore, 84, ARRAY, BYTE, STORE)
|
||||
JAVAOP (castore, 85, ARRAY, CHAR, STORE)
|
||||
JAVAOP (sastore, 86, ARRAY, SHORT, STORE)
|
||||
JAVAOP (pop, 87, STACK, POP, 1)
|
||||
JAVAOP (pop2, 88, STACK, POP, 2)
|
||||
JAVAOP (dup, 89, STACK, DUP, 1)
|
||||
JAVAOP (dup_x1, 90, STACK, DUPx1, 1)
|
||||
JAVAOP (dup_x2, 91, STACK, DUPx2, 1)
|
||||
JAVAOP (dup2, 92, STACK, DUP, 2)
|
||||
JAVAOP (dup2_x1, 93, STACK, DUPx1, 2)
|
||||
JAVAOP (dup2_x2, 94, STACK, DUPx2, 2)
|
||||
JAVAOP (swap, 95, STACK, SWAP, 0)
|
||||
JAVAOP (iadd, 96, BINOP, INT, PLUS)
|
||||
JAVAOP (ladd, 97, BINOP, LONG, PLUS)
|
||||
JAVAOP (fadd, 98, BINOP, FLOAT, PLUS)
|
||||
JAVAOP (dadd, 99, BINOP, DOUBLE, PLUS)
|
||||
JAVAOP (isub, 100, BINOP, INT, MINUS)
|
||||
JAVAOP (lsub, 101, BINOP, LONG, MINUS)
|
||||
JAVAOP (fsub, 102, BINOP, FLOAT, MINUS)
|
||||
JAVAOP (dsub, 103, BINOP, DOUBLE, MINUS)
|
||||
JAVAOP (imul, 104, BINOP, INT, MULT)
|
||||
JAVAOP (lmul, 105, BINOP, LONG, MULT)
|
||||
JAVAOP (fmul, 106, BINOP, FLOAT, MULT)
|
||||
JAVAOP (dmul, 107, BINOP, DOUBLE, MULT)
|
||||
JAVAOP (idiv, 108, BINOP, INT, TRUNC_DIV)
|
||||
JAVAOP (ldiv, 109, BINOP, LONG, TRUNC_DIV)
|
||||
JAVAOP (fdiv, 110, BINOP, FLOAT, RDIV)
|
||||
JAVAOP (ddiv, 111, BINOP, DOUBLE, RDIV)
|
||||
JAVAOP (irem, 112, BINOP, INT, REM)
|
||||
JAVAOP (lrem, 113, BINOP, LONG, REM)
|
||||
JAVAOP (frem, 114, BINOP, FLOAT, REM)
|
||||
JAVAOP (drem, 115, BINOP, DOUBLE, REM)
|
||||
JAVAOP (ineg, 116, UNOP, INT, NEG)
|
||||
JAVAOP (lneg, 117, UNOP, LONG, NEG)
|
||||
JAVAOP (fneg, 118, UNOP, FLOAT, NEG)
|
||||
JAVAOP (dneg, 119, UNOP, DOUBLE, NEG)
|
||||
JAVAOP (ishl, 120, BINOP, INT, LSHIFT)
|
||||
JAVAOP (lshl, 121, BINOP, LONG, LSHIFT)
|
||||
JAVAOP (ishr, 122, BINOP, INT, RSHIFT)
|
||||
JAVAOP (lshr, 123, BINOP, LONG, RSHIFT)
|
||||
JAVAOP (iushr, 124, BINOP, INT, URSHIFT)
|
||||
JAVAOP (lushr, 125, BINOP, LONG, URSHIFT)
|
||||
JAVAOP (iand, 126, BINOP, INT, BIT_AND)
|
||||
JAVAOP (land, 127, BINOP, LONG, BIT_AND)
|
||||
JAVAOP (ior, 128, BINOP, INT, BIT_IOR)
|
||||
JAVAOP (lor, 129, BINOP, LONG, BIT_IOR)
|
||||
JAVAOP (ixor, 130, BINOP, INT, BIT_XOR)
|
||||
JAVAOP (lxor, 131, BINOP, LONG, BIT_XOR)
|
||||
JAVAOP (iinc, 132, SPECIAL, INT, IINC)
|
||||
JAVAOP (i2l, 133, CONVERT, INT, LONG)
|
||||
JAVAOP (i2f, 134, CONVERT, INT, FLOAT)
|
||||
JAVAOP (i2d, 135, CONVERT, INT, DOUBLE)
|
||||
JAVAOP (l2i, 136, CONVERT, LONG, INT)
|
||||
JAVAOP (l2f, 137, CONVERT, LONG, FLOAT)
|
||||
JAVAOP (l2d, 138, CONVERT, LONG, DOUBLE)
|
||||
JAVAOP (f2i, 139, CONVERT, FLOAT, INT)
|
||||
JAVAOP (f2l, 140, CONVERT, FLOAT, LONG)
|
||||
JAVAOP (f2d, 141, CONVERT, FLOAT, DOUBLE)
|
||||
JAVAOP (d2i, 142, CONVERT, DOUBLE, INT)
|
||||
JAVAOP (d2l, 143, CONVERT, DOUBLE, LONG)
|
||||
JAVAOP (d2f, 144, CONVERT, DOUBLE, FLOAT)
|
||||
JAVAOP (i2b, 145, CONVERT2, INT, BYTE)
|
||||
JAVAOP (i2c, 146, CONVERT2, INT, CHAR)
|
||||
JAVAOP (i2s, 147, CONVERT2, INT, SHORT)
|
||||
JAVAOP (lcmp, 148, BINOP, LONG, COMPARE)
|
||||
JAVAOP (fcmpl, 149, BINOP, FLOAT, COMPARE_L)
|
||||
JAVAOP (fcmpg, 150, BINOP, FLOAT, COMPARE_G)
|
||||
JAVAOP (dcmpl, 151, BINOP, DOUBLE, COMPARE_L)
|
||||
JAVAOP (dcmpg, 152, BINOP, DOUBLE, COMPARE_G)
|
||||
JAVAOP (ifeq, 153, TEST, INT, EQ)
|
||||
JAVAOP (ifne, 154, TEST, INT, NE)
|
||||
JAVAOP (iflt, 155, TEST, INT, LT)
|
||||
JAVAOP (ifge, 156, TEST, INT, GE)
|
||||
JAVAOP (ifgt, 157, TEST, INT, GT)
|
||||
JAVAOP (ifle, 158, TEST, INT, LE)
|
||||
JAVAOP (if_icmpeq, 159, COND, INT, EQ)
|
||||
JAVAOP (if_icmpne, 160, COND, INT, NE)
|
||||
JAVAOP (if_icmplt, 161, COND, INT, LT)
|
||||
JAVAOP (if_icmpge, 162, COND, INT, GE)
|
||||
JAVAOP (if_icmpgt, 163, COND, INT, GT)
|
||||
JAVAOP (if_icmple, 164, COND, INT, LE)
|
||||
JAVAOP (if_acmpeq, 165, COND, PTR, EQ)
|
||||
JAVAOP (if_acmpne, 166, COND, PTR, NE)
|
||||
JAVAOP (goto, 167, BRANCH, GOTO, IMMEDIATE_s2)
|
||||
JAVAOP (jsr, 168, JSR, CALL, IMMEDIATE_s2)
|
||||
JAVAOP (ret, 169, RET, RETURN, VAR_INDEX_1)
|
||||
JAVAOP (tableswitch, 170, SWITCH, INT, TABLE)
|
||||
JAVAOP (lookupswitch, 171, SWITCH, INT, LOOKUP)
|
||||
JAVAOP (ireturn, 172, RETURN, INT, 0)
|
||||
JAVAOP (lreturn, 173, RETURN, LONG, 0)
|
||||
JAVAOP (freturn, 174, RETURN, FLOAT, 0)
|
||||
JAVAOP (dreturn, 175, RETURN, DOUBLE, 0)
|
||||
JAVAOP (areturn, 176, RETURN, PTR, 0)
|
||||
JAVAOP (return, 177, RETURN, VOID, 0)
|
||||
JAVAOP (getstatic, 178, FIELD, 1, 0)
|
||||
JAVAOP (putstatic, 179, FIELD, 1, 1)
|
||||
JAVAOP (getfield, 180, FIELD, 0, 0)
|
||||
JAVAOP (putfield, 181, FIELD, 0, 1)
|
||||
JAVAOP (invokevirtual, 182, INVOKE, VIRTUAL,0)
|
||||
JAVAOP (invokespecial, 183, INVOKE, SPECIAL, 0)
|
||||
JAVAOP (invokestatic, 184, INVOKE, STATIC, 0)
|
||||
JAVAOP (invokeinterface,185, INVOKE, INTERFACE, 1)
|
||||
JAVAOP (new, 187, OBJECT, PTR, NEW)
|
||||
JAVAOP (newarray, 188, ARRAY, NUM, NEW)
|
||||
JAVAOP (anewarray, 189, ARRAY, PTR, NEW)
|
||||
JAVAOP (arraylength, 190, ARRAY, INT, LENGTH)
|
||||
JAVAOP (athrow, 191, SPECIAL, ANY, THROW)
|
||||
JAVAOP (checkcast, 192, OBJECT, PTR, CHECKCAST)
|
||||
JAVAOP (instanceof, 193, OBJECT, PTR, INSTANCEOF)
|
||||
JAVAOP (monitorenter, 194, SPECIAL, MONITOR, ENTER)
|
||||
JAVAOP (monitorexit, 195, SPECIAL, MONITOR, EXIT)
|
||||
JAVAOP (wide, 196, SPECIAL, ANY, WIDE)
|
||||
JAVAOP (multianewarray,197, ARRAY, MULTI, NEW)
|
||||
JAVAOP (ifnull, 198, TEST, PTR, EQ)
|
||||
JAVAOP (ifnonnull, 199, TEST, PTR, NE)
|
||||
JAVAOP (goto_w, 200, BRANCH, GOTO, IMMEDIATE_s4)
|
||||
JAVAOP (jsr_w, 201, JSR, CALL, IMMEDIATE_s4)
|
||||
JAVAOP (breakpoint, 202, SPECIAL, ANY, BREAK)
|
||||
JAVAOP (ret_w, 209, RET, RETURN, VAR_INDEX_2)
|
||||
JAVAOP (impdep1, 254, IMPL, ANY, 1)
|
||||
JAVAOP (impdep2, 255, IMPL, ANY, 2)
|
142
gcc/java/javaop.h
Normal file
142
gcc/java/javaop.h
Normal file
|
@ -0,0 +1,142 @@
|
|||
/* Utility macros to handle Java(TM) byte codes.
|
||||
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
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, 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
|
||||
|
||||
#ifndef JAVAOP_H
|
||||
#define JAVAOP_H
|
||||
|
||||
typedef char int8;
|
||||
typedef unsigned char uint8;
|
||||
#ifndef int16
|
||||
#define int16 short
|
||||
#endif
|
||||
typedef unsigned int16 uint16;
|
||||
|
||||
#ifndef int32
|
||||
#define int32 long
|
||||
#endif
|
||||
typedef unsigned int32 uint32;
|
||||
|
||||
/* A signed 64-bit (or more) integral type, suiteable for Java's 'long'. */
|
||||
#ifndef int64
|
||||
#define int64 long long
|
||||
#endif
|
||||
/* An unsigned 64-bit (or more) integral type, same length as int64. */
|
||||
#ifndef uint64
|
||||
#define uint64 unsigned int64
|
||||
#endif
|
||||
|
||||
typedef uint16 jchar;
|
||||
typedef int8 jbyte;
|
||||
typedef int16 jshort;
|
||||
typedef int32 jint;
|
||||
typedef int64 jlong;
|
||||
typedef void* jref;
|
||||
|
||||
/* A 32-bit IEEE single-precision float. */
|
||||
#ifndef jfloat
|
||||
#define jfloat float
|
||||
#endif
|
||||
|
||||
/* A 32-bit IEEE double-precision float. */
|
||||
#ifndef jdouble
|
||||
#define jdouble double
|
||||
#endif
|
||||
|
||||
union Word {
|
||||
jint i;
|
||||
jfloat f;
|
||||
void *p;
|
||||
};
|
||||
|
||||
/* A jword is an unsigned integral type big enough for a 32-bit jint
|
||||
or jfloat *or* a pointer. It is the type appropriate for stack
|
||||
locations and local variables in a Java interpreter. */
|
||||
|
||||
|
||||
#ifndef jword
|
||||
#define jword uint32
|
||||
#endif
|
||||
|
||||
#if !defined(inline) && !defined(__GC__) && !defined(__cplusplus)
|
||||
#define inline static
|
||||
#endif
|
||||
|
||||
#ifndef IMMEDIATE_u1
|
||||
#define IMMEDIATE_u1 (PC++, CHECK_PC_IN_RANGE(PC), BCODE[PC-1])
|
||||
#endif
|
||||
#ifndef IMMEDIATE_s1
|
||||
#define IMMEDIATE_s1 (PC++, CHECK_PC_IN_RANGE(PC), (signed char)BCODE[PC-1])
|
||||
#endif
|
||||
#ifndef IMMEDIATE_s2
|
||||
#define IMMEDIATE_s2 (PC+=2, CHECK_PC_IN_RANGE(PC), \
|
||||
(signed char) BCODE[PC-2] * 256 + BCODE[PC-1])
|
||||
#endif
|
||||
#ifndef IMMEDIATE_u2
|
||||
#define IMMEDIATE_u2 (PC+=2, CHECK_PC_IN_RANGE(PC),\
|
||||
(BCODE[PC-2] * 256 + BCODE[PC-1]))
|
||||
#endif
|
||||
#ifndef IMMEDIATE_s4
|
||||
#define IMMEDIATE_s4 (PC+=4, CHECK_PC_IN_RANGE(PC), \
|
||||
((jint)((BCODE[PC-4] << 24) | (BCODE[PC-3] << 16) \
|
||||
| (BCODE[PC-2] << 8) | (BCODE[PC-1]))))
|
||||
#endif
|
||||
|
||||
inline jfloat
|
||||
WORD_TO_FLOAT(jword w)
|
||||
{ union Word wu;
|
||||
wu.i = w;
|
||||
return wu.f;
|
||||
}
|
||||
|
||||
inline jlong
|
||||
WORDS_TO_LONG(jword hi, jword lo)
|
||||
{
|
||||
return ((jlong) hi << 32) | ((jlong)lo & (((jlong)1 << 32) -1));
|
||||
}
|
||||
|
||||
union DWord {
|
||||
jdouble d;
|
||||
jlong l;
|
||||
jword w[2];
|
||||
};
|
||||
|
||||
inline jdouble
|
||||
WORDS_TO_DOUBLE(jword hi, jword lo)
|
||||
{ union DWord wu;
|
||||
wu.l = WORDS_TO_LONG(hi, lo);
|
||||
return wu.d;
|
||||
}
|
||||
|
||||
/* If PREFIX_CHAR is the first character of the Utf8 encoding of a character,
|
||||
return the number of bytes taken by the encoding.
|
||||
Return -1 for a continuation character. */
|
||||
#define UT8_CHAR_LENGTH(PREFIX_CHAR) \
|
||||
((unsigned char)(PREFIX_CHAR) < 128 ? 1 \
|
||||
: ((PREFIX_CHAR) & 0x40) == 0 ? -1 \
|
||||
: ((PREFIX_CHAR) & 0x20) == 0 ? 2 \
|
||||
: ((PREFIX_CHAR) & 0x10) == 0 ? 3 \
|
||||
: ((PREFIX_CHAR) & 0x08) == 0 ? 4 : 5)
|
||||
|
||||
#endif /* !JAVAOP_H */
|
1072
gcc/java/jcf-dump.c
Normal file
1072
gcc/java/jcf-dump.c
Normal file
File diff suppressed because it is too large
Load diff
574
gcc/java/jcf-io.c
Normal file
574
gcc/java/jcf-io.c
Normal file
|
@ -0,0 +1,574 @@
|
|||
/* Utility routines for finding and reading Java(TM) .class files.
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
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, 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define ENABLE_UNZIP 1
|
||||
|
||||
#include "jcf.h"
|
||||
#ifdef __STDC__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/* DOS brain-damage */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0 /* MS-DOS brain-damage */
|
||||
#endif
|
||||
|
||||
char *classpath;
|
||||
|
||||
int
|
||||
DEFUN(jcf_unexpected_eof, (jcf, count),
|
||||
JCF *jcf AND int count)
|
||||
{
|
||||
if (jcf->filename)
|
||||
fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
|
||||
else
|
||||
fprintf (stderr, "Premature end of .class file <stdin>.\n");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
void
|
||||
DEFUN(jcf_trim_old_input, (jcf),
|
||||
JCF *jcf)
|
||||
{
|
||||
int count = jcf->read_ptr - jcf->buffer;
|
||||
if (count > 0)
|
||||
{
|
||||
memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
|
||||
jcf->read_ptr -= count;
|
||||
jcf->read_end -= count;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
DEFUN(jcf_filbuf_from_stdio, (jcf, count),
|
||||
JCF *jcf AND int count)
|
||||
{
|
||||
FILE *file = (FILE*) (jcf->read_state);
|
||||
if (count > jcf->buffer_end - jcf->read_ptr)
|
||||
{
|
||||
JCF_u4 old_read_ptr = jcf->read_ptr - jcf->buffer;
|
||||
JCF_u4 old_read_end = jcf->read_end - jcf->buffer;
|
||||
JCF_u4 old_size = jcf->buffer_end - jcf->buffer;
|
||||
JCF_u4 new_size = (old_size == 0 ? 2000 : 2 * old_size) + count;
|
||||
unsigned char *new_buffer = jcf->buffer == NULL ? ALLOC (new_size)
|
||||
: REALLOC (jcf->buffer, new_size);
|
||||
jcf->buffer = new_buffer;
|
||||
jcf->buffer_end = new_buffer + new_size;
|
||||
jcf->read_ptr = new_buffer + old_read_ptr;
|
||||
jcf->read_end = new_buffer + old_read_end;
|
||||
}
|
||||
count -= jcf->read_end - jcf->read_ptr;
|
||||
if (count <= 0)
|
||||
return 0;
|
||||
if (fread (jcf->read_end, 1, count, file) != count)
|
||||
jcf_unexpected_eof (jcf, count);
|
||||
jcf->read_end += count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if ENABLE_UNZIP
|
||||
#include "zipfile.h"
|
||||
|
||||
struct ZipFileCache *SeenZipFiles = NULL;
|
||||
|
||||
int
|
||||
DEFUN(open_in_zip, (jcf,
|
||||
zipfile, zipmember),
|
||||
JCF *jcf AND const char *zipfile AND const char *zipmember)
|
||||
{
|
||||
struct ZipFileCache* zipf;
|
||||
ZipDirectory *zipd;
|
||||
int i, len;
|
||||
for (zipf = SeenZipFiles; ; zipf = zipf->next)
|
||||
{
|
||||
if (zipf == NULL)
|
||||
{
|
||||
char magic [4];
|
||||
int fd = open (zipfile, O_RDONLY | O_BINARY);
|
||||
if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
|
||||
return -1;
|
||||
lseek (fd, 0L, SEEK_SET);
|
||||
zipf = ALLOC (sizeof (struct ZipFileCache) + strlen (zipfile) + 1);
|
||||
zipf->next = SeenZipFiles;
|
||||
zipf->name = (char*)(zipf+1);
|
||||
strcpy (zipf->name, zipfile);
|
||||
SeenZipFiles = zipf;
|
||||
zipf->z.fd = fd;
|
||||
if (fd == -1)
|
||||
{
|
||||
/* A missing zip file is not considered an error. */
|
||||
zipf->z.count = 0;
|
||||
zipf->z.dir_size = 0;
|
||||
zipf->z.central_directory = NULL;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (read_zip_archive (&zipf->z) != 0)
|
||||
return -2; /* This however should be an error - FIXME */
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (strcmp (zipf->name, zipfile) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!zipmember)
|
||||
return 0;
|
||||
|
||||
len = strlen (zipmember);
|
||||
|
||||
zipd = (struct ZipDirectory*) zipf->z.central_directory;
|
||||
for (i = 0; i < zipf->z.count; i++, zipd = ZIPDIR_NEXT (zipd))
|
||||
{
|
||||
if (len == zipd->filename_length &&
|
||||
strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
|
||||
{
|
||||
JCF_ZERO (jcf);
|
||||
jcf->buffer = ALLOC (zipd->size);
|
||||
jcf->buffer_end = jcf->buffer + zipd->size;
|
||||
jcf->read_ptr = jcf->buffer;
|
||||
jcf->read_end = jcf->buffer_end;
|
||||
jcf->filbuf = jcf_unexpected_eof;
|
||||
jcf->filename = (char *) strdup (zipfile);
|
||||
jcf->classname = (char *) strdup (zipmember);
|
||||
jcf->zipd = (void *)zipd;
|
||||
if (lseek (zipf->z.fd, zipd->filestart, 0) < 0
|
||||
|| read (zipf->z.fd, jcf->buffer, zipd->size) != zipd->size)
|
||||
return -2;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif /* ENABLE_UNZIP */
|
||||
|
||||
#if JCF_USE_STDIO
|
||||
char*
|
||||
DEFUN(open_class, (filename, jcf, stream),
|
||||
char *filename AND JCF *jcf AND FILE* stream)
|
||||
{
|
||||
if (jcf)
|
||||
{
|
||||
JCF_ZERO (jcf);
|
||||
jcf->buffer = NULL;
|
||||
jcf->buffer_end = NULL;
|
||||
jcf->read_ptr = NULL;
|
||||
jcf->read_end = NULL;
|
||||
jcf->read_state = stream;
|
||||
jcf->filbuf = jcf_filbuf_from_stdio;
|
||||
}
|
||||
else
|
||||
fclose (stream);
|
||||
return filename;
|
||||
}
|
||||
#else
|
||||
char*
|
||||
DEFUN(open_class, (filename, jcf, fd),
|
||||
char *filename AND JCF *jcf AND int fd)
|
||||
{
|
||||
if (jcf)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
if (fstat (fd, &stat_buf) != 0
|
||||
|| ! S_ISREG (stat_buf.st_mode))
|
||||
{
|
||||
perror ("Could not figure length of .class file");
|
||||
return NULL;
|
||||
}
|
||||
JCF_ZERO (jcf);
|
||||
jcf->buffer = ALLOC (stat_buf.st_size);
|
||||
jcf->buffer_end = jcf->buffer + stat_buf.st_size;
|
||||
jcf->read_ptr = jcf->buffer;
|
||||
jcf->read_end = jcf->buffer_end;
|
||||
jcf->read_state = NULL;
|
||||
jcf->filename = filename;
|
||||
if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
|
||||
{
|
||||
perror ("Failed to read .class file");
|
||||
return NULL;
|
||||
}
|
||||
close (fd);
|
||||
jcf->filbuf = jcf_unexpected_eof;
|
||||
}
|
||||
else
|
||||
close (fd);
|
||||
return filename;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
char *
|
||||
DEFUN(find_classfile, (filename_length, jcf),
|
||||
char *filename AND JCF *jcf)
|
||||
{
|
||||
#if JCF_USE_STDIO
|
||||
FILE *stream = fopen (filename, "rb");
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
return open_class (arg, jcf, stream);
|
||||
#else
|
||||
int fd = open (filename, O_RDONLY | O_BINARY);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
return open_class (filename, jcf, fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Returns a freshly malloc'd string with the fully qualified pathname
|
||||
of the .class file for the class CLASSNAME. Returns NULL on
|
||||
failure. If JCF != NULL, it is suitably initialized. With
|
||||
DO_CLASS_FILE set to 1, search a .class/.java file named after
|
||||
CLASSNAME, otherwise, search a ZIP directory entry named after
|
||||
CLASSNAME. */
|
||||
|
||||
char *
|
||||
DEFUN(find_class, (classname, classname_length, jcf, do_class_file),
|
||||
const char *classname AND int classname_length AND JCF *jcf AND int do_class_file)
|
||||
|
||||
{
|
||||
#if JCF_USE_STDIO
|
||||
FILE *stream;
|
||||
#else
|
||||
int fd;
|
||||
#endif
|
||||
int i, j, k, java, class;
|
||||
struct stat java_buf, class_buf;
|
||||
|
||||
/* Allocate and zero out the buffer, since we don't explicitly put a
|
||||
null pointer when we're copying it below. */
|
||||
int buflen = strlen (classpath) + classname_length + 10;
|
||||
char *buffer = (char *) ALLOC (buflen);
|
||||
bzero (buffer, buflen);
|
||||
|
||||
jcf->java_source = jcf->outofsynch = 0;
|
||||
for (j = 0; classpath[j] != '\0'; )
|
||||
{
|
||||
for (i = 0; classpath[j] != ':' && classpath[j] != '\0'; i++, j++)
|
||||
buffer[i] = classpath[j];
|
||||
if (classpath[j] == ':')
|
||||
j++;
|
||||
if (i > 0) /* Empty directory is redundant */
|
||||
{
|
||||
int dir_len;
|
||||
if (buffer[i-1] != '/')
|
||||
buffer[i++] = '/';
|
||||
dir_len = i-1;
|
||||
for (k = 0; k < classname_length; k++, i++)
|
||||
{
|
||||
char ch = classname[k];
|
||||
buffer[i] = ch == '.' ? '/' : ch;
|
||||
}
|
||||
if (do_class_file)
|
||||
strcpy (buffer+i, ".class");
|
||||
#if ENABLE_UNZIP
|
||||
if (dir_len > 4
|
||||
&& buffer[dir_len-4] == '.' && buffer[dir_len-3] == 'z'
|
||||
&& buffer[dir_len-2] == 'i' && buffer[dir_len-1] == 'p')
|
||||
{
|
||||
int err_code;
|
||||
JCF _jcf;
|
||||
if (!do_class_file)
|
||||
strcpy (buffer+i, "/");
|
||||
buffer[dir_len] = '\0';
|
||||
if (do_class_file)
|
||||
SOURCE_FRONTEND_DEBUG
|
||||
(("Trying [...%s]:%s",
|
||||
&buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
|
||||
buffer+dir_len+1));
|
||||
if (jcf == NULL)
|
||||
jcf = &_jcf;
|
||||
err_code = open_in_zip (jcf, buffer, buffer+dir_len+1);
|
||||
if (err_code == 0)
|
||||
{
|
||||
if (!do_class_file)
|
||||
jcf->seen_in_zip = 1;
|
||||
else
|
||||
{
|
||||
buffer[dir_len] = '(';
|
||||
strcpy (buffer+i, ".class)");
|
||||
}
|
||||
if (jcf == &_jcf)
|
||||
JCF_FINISH (jcf);
|
||||
return buffer;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* If we do directories, do them here */
|
||||
if (!do_class_file)
|
||||
{
|
||||
struct stat dir_buff;
|
||||
int dir;
|
||||
buffer[i] = '\0'; /* Was previously unterminated here. */
|
||||
if (!(dir = stat (buffer, &dir_buff)))
|
||||
{
|
||||
jcf->seen_in_zip = 0;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for out of synch .class/.java files */
|
||||
class = stat (buffer, &class_buf);
|
||||
strcpy (buffer+i, ".java");
|
||||
java = stat (buffer, &java_buf);
|
||||
if ((!java && !class) && java_buf.st_mtime >= class_buf.st_mtime)
|
||||
jcf->outofsynch = 1;
|
||||
#if JCF_USE_STDIO
|
||||
if (!class)
|
||||
{
|
||||
strcpy (buffer+i, ".class");
|
||||
SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
|
||||
stream = fopen (buffer, "rb");
|
||||
if (stream)
|
||||
goto found;
|
||||
}
|
||||
/* Give .java a try, if necessary */
|
||||
if (!java)
|
||||
{
|
||||
strcpy (buffer+i, ".java");
|
||||
SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
|
||||
stream = fopen (buffer, "r");
|
||||
if (stream)
|
||||
{
|
||||
jcf->java_source = 1;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!class)
|
||||
{
|
||||
strcpy (buffer+i, ".class");
|
||||
SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
|
||||
fd = open (buffer, O_RDONLY | O_BINARY);
|
||||
if (fd >= 0)
|
||||
goto found;
|
||||
}
|
||||
/* Give .java a try, if necessary */
|
||||
if (!java)
|
||||
{
|
||||
if (do_class_file)
|
||||
strcpy (buffer+i, ".java");
|
||||
SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
|
||||
fd = open (buffer, O_RDONLY | O_BINARY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
jcf->java_source = 1;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
free (buffer);
|
||||
return NULL;
|
||||
found:
|
||||
#if JCF_USE_STDIO
|
||||
if (jcf->java_source)
|
||||
return NULL; /* FIXME */
|
||||
else
|
||||
return open_class (buffer, jcf, stream);
|
||||
#else
|
||||
if (jcf->java_source)
|
||||
{
|
||||
JCF_ZERO (jcf); /* JCF_FINISH relies on this */
|
||||
jcf->java_source = 1;
|
||||
jcf->filename = (char *) strdup (buffer);
|
||||
close (fd); /* We use STDIO for source file */
|
||||
}
|
||||
else if (do_class_file)
|
||||
buffer = open_class (buffer, jcf, fd);
|
||||
jcf->classname = (char *) ALLOC (classname_length + 1);
|
||||
strncpy (jcf->classname, classname, classname_length + 1);
|
||||
jcf->classname = (char *) strdup (classname);
|
||||
return buffer;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DEFUN(jcf_print_char, (stream, ch),
|
||||
FILE *stream AND int ch)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case '\'':
|
||||
case '\\':
|
||||
case '\"':
|
||||
fprintf (stream, "\\%c", ch);
|
||||
break;
|
||||
case '\n':
|
||||
fprintf (stream, "\\n");
|
||||
break;
|
||||
case '\t':
|
||||
fprintf (stream, "\\t");
|
||||
break;
|
||||
case '\r':
|
||||
fprintf (stream, "\\r");
|
||||
break;
|
||||
default:
|
||||
if (ch >= ' ' && ch < 127)
|
||||
putc (ch, stream);
|
||||
else if (ch < 256)
|
||||
fprintf (stream, "\\%03x", ch);
|
||||
else
|
||||
fprintf (stream, "\\u%04x", ch);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
|
||||
|
||||
void
|
||||
DEFUN(jcf_print_utf8, (stream, str, length),
|
||||
FILE *stream AND register unsigned char *str AND int length)
|
||||
{
|
||||
unsigned char* limit = str + length;
|
||||
while (str < limit)
|
||||
{
|
||||
int ch = UTF8_GET (str, limit);
|
||||
if (ch < 0)
|
||||
{
|
||||
fprintf (stream, "\\<invalid>");
|
||||
return;
|
||||
}
|
||||
jcf_print_char (stream, ch);
|
||||
}
|
||||
}
|
||||
|
||||
/* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
|
||||
|
||||
void
|
||||
DEFUN(jcf_print_utf8_replace, (stream, str, length, in_char, out_char),
|
||||
FILE *stream AND unsigned char *str AND int length
|
||||
AND int in_char AND int out_char)
|
||||
{
|
||||
|
||||
int i;/* FIXME - actually handle Unicode! */
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
int ch = str[i];
|
||||
jcf_print_char (stream, ch == in_char ? out_char : ch);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that all the cross-references in the constant pool are
|
||||
valid. Returns 0 on success.
|
||||
Otherwise, returns the index of the (first) invalid entry. */
|
||||
|
||||
int
|
||||
DEFUN(verify_constant_pool, (jcf),
|
||||
JCF *jcf)
|
||||
{
|
||||
int i, n;
|
||||
for (i = 1; i < JPOOL_SIZE (jcf); i++)
|
||||
{
|
||||
switch (JPOOL_TAG (jcf, i))
|
||||
{
|
||||
case CONSTANT_NameAndType:
|
||||
n = JPOOL_USHORT2 (jcf, i);
|
||||
if (n <= 0 || n >= JPOOL_SIZE(jcf)
|
||||
|| JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
|
||||
return i;
|
||||
/* ... fall through ... */
|
||||
case CONSTANT_Class:
|
||||
case CONSTANT_String:
|
||||
n = JPOOL_USHORT1 (jcf, i);
|
||||
if (n <= 0 || n >= JPOOL_SIZE(jcf)
|
||||
|| JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
|
||||
return i;
|
||||
break;
|
||||
case CONSTANT_Fieldref:
|
||||
case CONSTANT_Methodref:
|
||||
case CONSTANT_InterfaceMethodref:
|
||||
n = JPOOL_USHORT1 (jcf, i);
|
||||
if (n <= 0 || n >= JPOOL_SIZE(jcf)
|
||||
|| JPOOL_TAG (jcf, n) != CONSTANT_Class)
|
||||
return i;
|
||||
n = JPOOL_USHORT2 (jcf, i);
|
||||
if (n <= 0 || n >= JPOOL_SIZE(jcf)
|
||||
|| JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
|
||||
return i;
|
||||
break;
|
||||
case CONSTANT_Long:
|
||||
case CONSTANT_Double:
|
||||
i++;
|
||||
break;
|
||||
case CONSTANT_Float:
|
||||
case CONSTANT_Integer:
|
||||
case CONSTANT_Utf8:
|
||||
case CONSTANT_Unicode:
|
||||
break;
|
||||
default:
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
DEFUN(format_uint, (buffer, value, base),
|
||||
char *buffer AND uint64 value AND int base)
|
||||
{
|
||||
#define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
|
||||
char buf[WRITE_BUF_SIZE];
|
||||
register char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
|
||||
int chars_written;
|
||||
int i;
|
||||
|
||||
/* Now do the actual conversion, placing the result at the *end* of buf. */
|
||||
/* Note this code does not pretend to be optimized. */
|
||||
do {
|
||||
int digit = value % base;
|
||||
static char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
*--buf_ptr = digit_chars[digit];
|
||||
value /= base;
|
||||
} while (value != 0);
|
||||
|
||||
chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
|
||||
for (i = 0; i < chars_written; i++)
|
||||
buffer[i] = *buf_ptr++;
|
||||
buffer[i] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
DEFUN(format_int, (buffer, value, base),
|
||||
char *buffer AND jlong value AND int base)
|
||||
{
|
||||
uint64 abs_value;
|
||||
if (value < 0)
|
||||
{
|
||||
abs_value = -(uint64)value;
|
||||
*buffer++ = '-';
|
||||
}
|
||||
else
|
||||
abs_value = (uint64) value;
|
||||
format_uint (buffer, abs_value, base);
|
||||
}
|
917
gcc/java/jcf-parse.c
Normal file
917
gcc/java/jcf-parse.c
Normal file
|
@ -0,0 +1,917 @@
|
|||
/* Parser for Java(TM) .class files.
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* Written by Per Bothner <bothner@cygnus.com> */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "config.h"
|
||||
#include "tree.h"
|
||||
#include "obstack.h"
|
||||
#include "flags.h"
|
||||
#include "java-except.h"
|
||||
#include "input.h"
|
||||
#include "java-tree.h"
|
||||
|
||||
/* A CONSTANT_Utf8 element is converted to an IDENTIFIER_NODE at parse time. */
|
||||
#define JPOOL_UTF(JCF, INDEX) CPOOL_UTF(&(JCF)->cpool, INDEX)
|
||||
#define JPOOL_UTF_LENGTH(JCF, INDEX) IDENTIFIER_LENGTH (JPOOL_UTF (JCF, INDEX))
|
||||
#define JPOOL_UTF_DATA(JCF, INDEX) \
|
||||
((unsigned char*) IDENTIFIER_POINTER (JPOOL_UTF (JCF, INDEX)))
|
||||
#define HANDLE_CONSTANT_Utf8(JCF, INDEX, LENGTH) \
|
||||
do { \
|
||||
unsigned char save; unsigned char *text; \
|
||||
JCF_FILL (JCF, (LENGTH)+1); /* Make sure we read 1 byte beyond string. */ \
|
||||
text = (JCF)->read_ptr; \
|
||||
save = text[LENGTH]; \
|
||||
text[LENGTH] = 0; \
|
||||
(JCF)->cpool.data[INDEX] = (jword) get_identifier (text); \
|
||||
text[LENGTH] = save; \
|
||||
JCF_SKIP (JCF, LENGTH); } while (0)
|
||||
|
||||
#include "jcf.h"
|
||||
#ifdef __STDC__
|
||||
/* For getenv */
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
extern struct obstack *saveable_obstack;
|
||||
extern struct obstack temporary_obstack;
|
||||
extern struct obstack permanent_obstack;
|
||||
|
||||
/* The class we are currently processing. */
|
||||
tree current_class = NULL_TREE;
|
||||
|
||||
/* The class we started with. */
|
||||
tree main_class = NULL_TREE;
|
||||
|
||||
/* The FIELD_DECL for the current field. */
|
||||
static tree current_field = NULL_TREE;
|
||||
|
||||
static tree current_method = NULL_TREE;
|
||||
|
||||
static tree give_name_to_class PROTO ((JCF *jcf, int index));
|
||||
|
||||
void parse_zip_file_entries (void);
|
||||
void process_zip_dir();
|
||||
|
||||
/* Source file compilation declarations */
|
||||
static void parse_source_file ();
|
||||
extern int java_error_count;
|
||||
#define java_parse_abort_on_error() \
|
||||
{ \
|
||||
if (java_error_count) \
|
||||
{ \
|
||||
java_report_errors (); \
|
||||
java_pop_parser_context (); \
|
||||
return; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Handle "SourceFile" attribute. */
|
||||
|
||||
void
|
||||
set_source_filename (jcf, index)
|
||||
JCF *jcf;
|
||||
int index;
|
||||
{
|
||||
tree sfname_id = get_name_constant (jcf, index);
|
||||
char *sfname = IDENTIFIER_POINTER (sfname_id);
|
||||
if (input_filename != NULL)
|
||||
{
|
||||
int old_len = strlen (input_filename);
|
||||
int new_len = IDENTIFIER_LENGTH (sfname_id);
|
||||
/* Use the current input_filename (derived from the class name)
|
||||
if it has a directory prefix, but otherwise matches sfname. */
|
||||
if (old_len > new_len
|
||||
&& strcmp (sfname, input_filename + old_len - new_len) == 0
|
||||
&& (input_filename[old_len - new_len - 1] == '/'
|
||||
|| input_filename[old_len - new_len - 1] == '\\'))
|
||||
return;
|
||||
}
|
||||
input_filename = sfname;
|
||||
DECL_SOURCE_FILE (TYPE_NAME (current_class)) = sfname;
|
||||
if (current_class == main_class) main_input_filename = input_filename;
|
||||
}
|
||||
|
||||
#define HANDLE_SOURCEFILE(INDEX) set_source_filename (jcf, INDEX)
|
||||
|
||||
#define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
|
||||
{ tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \
|
||||
current_class = give_name_to_class (jcf, THIS); \
|
||||
set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}
|
||||
|
||||
#define HANDLE_CLASS_INTERFACE(INDEX) \
|
||||
add_interface (current_class, get_class_constant (jcf, INDEX))
|
||||
|
||||
#define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
|
||||
{ int sig_index = SIGNATURE; \
|
||||
current_field = add_field (current_class, get_name_constant (jcf, NAME), \
|
||||
parse_signature (jcf, sig_index), ACCESS_FLAGS); \
|
||||
set_java_signature (TREE_TYPE (current_field), JPOOL_UTF (jcf, sig_index)); }
|
||||
|
||||
#define HANDLE_END_FIELDS() \
|
||||
(current_field = NULL_TREE)
|
||||
|
||||
#define HANDLE_CONSTANTVALUE(INDEX) \
|
||||
{ tree constant; int index = INDEX; \
|
||||
if (JPOOL_TAG (jcf, index) == CONSTANT_String) { \
|
||||
tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); \
|
||||
constant = build_utf8_ref (name); \
|
||||
} \
|
||||
else \
|
||||
constant = get_constant (jcf, index); \
|
||||
set_constant_value (current_field, constant); }
|
||||
|
||||
#define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
|
||||
(current_method = add_method (current_class, ACCESS_FLAGS, \
|
||||
get_name_constant (jcf, NAME), \
|
||||
get_name_constant (jcf, SIGNATURE)), \
|
||||
DECL_LOCALVARIABLES_OFFSET (current_method) = 0, \
|
||||
DECL_LINENUMBERS_OFFSET (current_method) = 0)
|
||||
|
||||
#define HANDLE_END_METHODS() \
|
||||
{ tree handle_type = CLASS_TO_HANDLE_TYPE (current_class); \
|
||||
if (handle_type != current_class) layout_type (handle_type); }
|
||||
|
||||
#define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
|
||||
{ DECL_MAX_STACK (current_method) = (MAX_STACK); \
|
||||
DECL_MAX_LOCALS (current_method) = (MAX_LOCALS); \
|
||||
DECL_CODE_LENGTH (current_method) = (CODE_LENGTH); \
|
||||
DECL_CODE_OFFSET (current_method) = JCF_TELL (jcf); }
|
||||
|
||||
#define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
|
||||
{ int n = (COUNT); \
|
||||
DECL_LOCALVARIABLES_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
|
||||
JCF_SKIP (jcf, n * 10); }
|
||||
|
||||
#define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
|
||||
{ int n = (COUNT); \
|
||||
DECL_LINENUMBERS_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
|
||||
JCF_SKIP (jcf, n * 4); }
|
||||
|
||||
#include "jcf-reader.c"
|
||||
|
||||
static int yydebug;
|
||||
|
||||
tree
|
||||
parse_signature (jcf, sig_index)
|
||||
JCF *jcf;
|
||||
int sig_index;
|
||||
{
|
||||
if (sig_index <= 0 || sig_index >= JPOOL_SIZE(jcf)
|
||||
|| JPOOL_TAG (jcf, sig_index) != CONSTANT_Utf8)
|
||||
fatal ("invalid field/method signature");
|
||||
else
|
||||
{
|
||||
return parse_signature_string (JPOOL_UTF_DATA (jcf, sig_index),
|
||||
JPOOL_UTF_LENGTH (jcf, sig_index));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
init_lex ()
|
||||
{
|
||||
/* Make identifier nodes long enough for the language-specific slots. */
|
||||
set_identifier_size (sizeof (struct lang_identifier));
|
||||
}
|
||||
|
||||
void
|
||||
set_yydebug (value)
|
||||
int value;
|
||||
{
|
||||
yydebug = value;
|
||||
}
|
||||
|
||||
tree
|
||||
get_constant (jcf, index)
|
||||
JCF *jcf;
|
||||
int index;
|
||||
{
|
||||
tree value;
|
||||
int tag;
|
||||
if (index <= 0 || index >= JPOOL_SIZE(jcf))
|
||||
goto bad;
|
||||
tag = JPOOL_TAG (jcf, index);
|
||||
if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
|
||||
return (tree) jcf->cpool.data[index];
|
||||
push_obstacks (&permanent_obstack, &permanent_obstack);
|
||||
switch (tag)
|
||||
{
|
||||
case CONSTANT_Integer:
|
||||
{
|
||||
jint num = JPOOL_INT(jcf, index);
|
||||
value = build_int_2 (num, num < 0 ? -1 : 0);
|
||||
TREE_TYPE (value) = int_type_node;
|
||||
break;
|
||||
}
|
||||
case CONSTANT_Long:
|
||||
{
|
||||
jint num = JPOOL_INT (jcf, index);
|
||||
HOST_WIDE_INT lo, hi;
|
||||
lshift_double (num, 0, 32, 64, &lo, &hi, 0);
|
||||
num = JPOOL_INT (jcf, index+1);
|
||||
add_double (lo, hi, num, 0, &lo, &hi);
|
||||
value = build_int_2 (lo, hi);
|
||||
TREE_TYPE (value) = long_type_node;
|
||||
force_fit_type (value, 0);
|
||||
break;
|
||||
}
|
||||
#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
|
||||
case CONSTANT_Float:
|
||||
{
|
||||
jint num = JPOOL_INT(jcf, index);
|
||||
REAL_VALUE_TYPE d;
|
||||
#ifdef REAL_ARITHMETIC
|
||||
d = REAL_VALUE_FROM_TARGET_SINGLE (num);
|
||||
#else
|
||||
union { float f; jint i; } u;
|
||||
u.i = num;
|
||||
d = u.f;
|
||||
#endif
|
||||
value = build_real (float_type_node, d);
|
||||
break;
|
||||
}
|
||||
case CONSTANT_Double:
|
||||
{
|
||||
HOST_WIDE_INT num[2];
|
||||
REAL_VALUE_TYPE d;
|
||||
HOST_WIDE_INT lo, hi;
|
||||
num[0] = JPOOL_INT (jcf, index);
|
||||
lshift_double (num[0], 0, 32, 64, &lo, &hi, 0);
|
||||
num[0] = JPOOL_INT (jcf, index+1);
|
||||
add_double (lo, hi, num[0], 0, &lo, &hi);
|
||||
if (FLOAT_WORDS_BIG_ENDIAN)
|
||||
{
|
||||
num[0] = hi;
|
||||
num[1] = lo;
|
||||
}
|
||||
else
|
||||
{
|
||||
num[0] = lo;
|
||||
num[1] = hi;
|
||||
}
|
||||
#ifdef REAL_ARITHMETIC
|
||||
d = REAL_VALUE_FROM_TARGET_DOUBLE (num);
|
||||
#else
|
||||
union { double d; jint i[2]; } u;
|
||||
u.i[0] = (jint) num[0];
|
||||
u.i[1] = (jint) num[1];
|
||||
d = u.d;
|
||||
#endif
|
||||
value = build_real (double_type_node, d);
|
||||
break;
|
||||
}
|
||||
#endif /* TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT */
|
||||
case CONSTANT_String:
|
||||
{
|
||||
extern struct obstack *expression_obstack;
|
||||
tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
|
||||
char *utf8_ptr = IDENTIFIER_POINTER (name);
|
||||
unsigned char *str_ptr;
|
||||
int utf8_len = IDENTIFIER_LENGTH (name);
|
||||
unsigned char *str = (unsigned char*)utf8_ptr;
|
||||
int i = utf8_len;
|
||||
int str_len;
|
||||
|
||||
/* Count the number of Unicode characters in the string,
|
||||
while checking for a malformed Utf8 string. */
|
||||
for (str_len = 0; i > 0; str_len++)
|
||||
{
|
||||
int char_len = UT8_CHAR_LENGTH (*str);
|
||||
if (char_len < 0 || char_len > 2 || char_len > i)
|
||||
fatal ("bad string constant");
|
||||
str += char_len;
|
||||
i -= char_len;
|
||||
}
|
||||
|
||||
value = make_node (STRING_CST);
|
||||
TREE_STRING_LENGTH (value) = 2 * str_len;
|
||||
TREE_STRING_POINTER (value)
|
||||
= obstack_alloc (expression_obstack, 2 * str_len);
|
||||
str_ptr = (unsigned char *) TREE_STRING_POINTER (value);
|
||||
str = (unsigned char*)utf8_ptr;
|
||||
for (i = 0; i < str_len; i++)
|
||||
{
|
||||
int char_value;
|
||||
int char_len = UT8_CHAR_LENGTH (*str);
|
||||
switch (char_len)
|
||||
{
|
||||
case 1:
|
||||
char_value = *str++;
|
||||
break;
|
||||
case 2:
|
||||
char_value = *str++ & 0x1F;
|
||||
char_value = (char_value << 6) | (*str++ & 0x3F);
|
||||
break;
|
||||
case 3:
|
||||
char_value = *str_ptr++ & 0x0F;
|
||||
char_value = (char_value << 6) | (*str++ & 0x3F);
|
||||
char_value = (char_value << 6) | (*str++ & 0x3F);
|
||||
break;
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
if (BYTES_BIG_ENDIAN)
|
||||
{
|
||||
*str_ptr++ = char_value >> 8;
|
||||
*str_ptr++ = char_value & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
*str_ptr++ = char_value & 0xFF;
|
||||
*str_ptr++ = char_value >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
pop_obstacks ();
|
||||
JPOOL_TAG(jcf, index) = tag | CONSTANT_ResolvedFlag;
|
||||
jcf->cpool.data [index] = (jword) value;
|
||||
return value;
|
||||
bad:
|
||||
fatal ("bad value constant type %d, index %d",
|
||||
JPOOL_TAG( jcf, index ), index);
|
||||
}
|
||||
|
||||
tree
|
||||
get_name_constant (jcf, index)
|
||||
JCF *jcf;
|
||||
int index;
|
||||
{
|
||||
tree name = get_constant (jcf, index);
|
||||
if (TREE_CODE (name) != IDENTIFIER_NODE)
|
||||
fatal ("bad nameandtype index %d", index);
|
||||
return name;
|
||||
}
|
||||
|
||||
static tree
|
||||
give_name_to_class (jcf, i)
|
||||
JCF *jcf;
|
||||
int i;
|
||||
{
|
||||
if (i <= 0 || i >= JPOOL_SIZE(jcf)
|
||||
|| JPOOL_TAG (jcf, i) != CONSTANT_Class)
|
||||
fatal ("bad class index %d", i);
|
||||
else
|
||||
{
|
||||
tree this_class;
|
||||
int j = JPOOL_USHORT1 (jcf, i);
|
||||
/* verify_constant_pool confirmed that j is a CONSTANT_Utf8. */
|
||||
tree class_name = unmangle_classname (JPOOL_UTF_DATA (jcf, j),
|
||||
JPOOL_UTF_LENGTH (jcf, j));
|
||||
this_class = lookup_class (class_name);
|
||||
input_filename = DECL_SOURCE_FILE (TYPE_NAME (this_class));
|
||||
lineno = 0;
|
||||
if (main_input_filename == NULL && jcf == main_jcf)
|
||||
main_input_filename = input_filename;
|
||||
|
||||
jcf->cpool.data[i] = (jword) this_class;
|
||||
JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
|
||||
return this_class;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the class of the CONSTANT_Class whose constant pool index is I. */
|
||||
|
||||
tree
|
||||
get_class_constant (JCF *jcf , int i)
|
||||
{
|
||||
tree type;
|
||||
if (i <= 0 || i >= JPOOL_SIZE(jcf)
|
||||
|| (JPOOL_TAG (jcf, i) & ~CONSTANT_ResolvedFlag) != CONSTANT_Class)
|
||||
fatal ("bad class index %d", i);
|
||||
|
||||
if (JPOOL_TAG (jcf, i) != CONSTANT_ResolvedClass)
|
||||
{
|
||||
int name_index = JPOOL_USHORT1 (jcf, i);
|
||||
/* verify_constant_pool confirmed that name_index is a CONSTANT_Utf8. */
|
||||
char *name = JPOOL_UTF_DATA (jcf, name_index);
|
||||
int nlength = JPOOL_UTF_LENGTH (jcf, name_index);
|
||||
if (name[0] == '[') /* Handle array "classes". */
|
||||
type = parse_signature_string (name, nlength);
|
||||
else
|
||||
{
|
||||
tree cname = unmangle_classname (name, nlength);
|
||||
type = lookup_class (cname);
|
||||
}
|
||||
jcf->cpool.data[i] = (jword) type;
|
||||
JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
|
||||
}
|
||||
else
|
||||
type = (tree) jcf->cpool.data[i];
|
||||
return type;
|
||||
}
|
||||
|
||||
void
|
||||
fix_classpath ()
|
||||
{
|
||||
static char default_path[] = DEFAULT_CLASS_PATH;
|
||||
|
||||
if (classpath == NULL)
|
||||
{
|
||||
classpath = (char *) getenv ("CLASSPATH");
|
||||
if (classpath == NULL)
|
||||
{
|
||||
warning ("CLASSPATH not set");
|
||||
classpath = default_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DEFUN(jcf_out_of_synch, (jcf),
|
||||
JCF *jcf)
|
||||
{
|
||||
char *source = strdup (jcf->filename);
|
||||
int i = strlen (source);
|
||||
|
||||
while (source[i] != '.')
|
||||
i--;
|
||||
|
||||
source [i] = '\0';
|
||||
warning ("Class file `%s' out of synch with `%s.java'",
|
||||
jcf->filename, source);
|
||||
free (source);
|
||||
}
|
||||
|
||||
/* Load CLASS_OR_NAME. CLASS_OR_NAME can be a mere identifier if
|
||||
called from the parser, otherwise it's a RECORD_TYPE node. If
|
||||
VERBOSE is 1, print error message on failure to load a class. */
|
||||
|
||||
void
|
||||
load_class (class_or_name, verbose)
|
||||
tree class_or_name;
|
||||
int verbose;
|
||||
{
|
||||
JCF this_jcf, *jcf;
|
||||
tree name = (TREE_CODE (class_or_name) == IDENTIFIER_NODE ?
|
||||
class_or_name : DECL_NAME (TYPE_NAME (class_or_name)));
|
||||
tree save_current_class = current_class;
|
||||
char *save_input_filename = input_filename;
|
||||
JCF *save_current_jcf = current_jcf;
|
||||
long saved_pos;
|
||||
if (current_jcf->read_state)
|
||||
saved_pos = ftell (current_jcf->read_state);
|
||||
|
||||
push_obstacks (&permanent_obstack, &permanent_obstack);
|
||||
|
||||
if (!classpath)
|
||||
fix_classpath ();
|
||||
/* Search in current zip first. */
|
||||
if (find_in_current_zip (IDENTIFIER_POINTER (name),
|
||||
IDENTIFIER_LENGTH (name), &jcf) == 0)
|
||||
if (find_class (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name),
|
||||
&this_jcf, 1) == 0)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
error ("Cannot find class file class %s.",
|
||||
IDENTIFIER_POINTER (name));
|
||||
TYPE_SIZE (class_or_name) = error_mark_node;
|
||||
if (!strcmp (classpath, DEFAULT_CLASS_PATH))
|
||||
fatal ("giving up");
|
||||
pop_obstacks (); /* FIXME: one pop_obstack() per function */
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_jcf.seen_in_zip = 0;
|
||||
current_jcf = &this_jcf;
|
||||
if (this_jcf.outofsynch)
|
||||
jcf_out_of_synch (current_jcf);
|
||||
}
|
||||
else
|
||||
current_jcf = jcf;
|
||||
|
||||
if (current_jcf->java_source)
|
||||
jcf_parse_source (current_jcf);
|
||||
else {
|
||||
int saved_lineno = lineno;
|
||||
input_filename = current_jcf->filename;
|
||||
jcf_parse (current_jcf);
|
||||
lineno = saved_lineno;
|
||||
}
|
||||
|
||||
if (!current_jcf->seen_in_zip)
|
||||
JCF_FINISH (current_jcf);
|
||||
/* DECL_IGNORED_P (TYPE_NAME (class_or_name)) = 1;*/
|
||||
pop_obstacks ();
|
||||
|
||||
current_class = save_current_class;
|
||||
input_filename = save_input_filename;
|
||||
current_jcf = save_current_jcf;
|
||||
if (current_jcf->read_state)
|
||||
fseek (current_jcf->read_state, saved_pos, SEEK_SET);
|
||||
}
|
||||
|
||||
/* Parse a source file when JCF refers to a source file. This piece
|
||||
needs further work as far as error handling and report. */
|
||||
|
||||
int
|
||||
jcf_parse_source (jcf)
|
||||
JCF *jcf;
|
||||
{
|
||||
java_parser_context_save_global ();
|
||||
|
||||
input_filename = current_jcf->filename;
|
||||
if (!(finput = fopen (input_filename, "r")))
|
||||
fatal ("input file `%s' just disappeared - jcf_parse_source",
|
||||
input_filename);
|
||||
|
||||
parse_source_file (1); /* Parse only */
|
||||
if (current_class && TREE_TYPE (current_class))
|
||||
CLASS_FROM_SOURCE_P (TREE_TYPE (current_class)) = 1;
|
||||
|
||||
fclose (finput);
|
||||
java_parser_context_restore_global ();
|
||||
}
|
||||
|
||||
/* Parse the .class file JCF. */
|
||||
|
||||
int
|
||||
jcf_parse (jcf)
|
||||
JCF* jcf;
|
||||
{
|
||||
int i, code;
|
||||
|
||||
if (jcf_parse_preamble (jcf) != 0)
|
||||
fatal ("Not a valid Java .class file.\n");
|
||||
code = jcf_parse_constant_pool (jcf);
|
||||
if (code != 0)
|
||||
fatal ("error while parsing constant pool");
|
||||
code = verify_constant_pool (jcf);
|
||||
if (code > 0)
|
||||
fatal ("error in constant pool entry #%d\n", code);
|
||||
|
||||
jcf_parse_class (jcf);
|
||||
if (main_class == NULL_TREE)
|
||||
main_class = current_class;
|
||||
if (! quiet_flag && TYPE_NAME (current_class))
|
||||
fprintf (stderr, " class %s",
|
||||
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
|
||||
CLASS_LOADED_P (current_class) = 1;
|
||||
|
||||
for (i = 1; i < JPOOL_SIZE(jcf); i++)
|
||||
{
|
||||
switch (JPOOL_TAG (jcf, i))
|
||||
{
|
||||
case CONSTANT_Class:
|
||||
get_class_constant (jcf, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
code = jcf_parse_fields (jcf);
|
||||
if (code != 0)
|
||||
fatal ("error while parsing fields");
|
||||
code = jcf_parse_methods (jcf);
|
||||
if (code != 0)
|
||||
fatal ("error while parsing methods");
|
||||
code = jcf_parse_final_attributes (jcf);
|
||||
if (code != 0)
|
||||
fatal ("error while parsing final attributes");
|
||||
|
||||
/* The fields of class_type_node are already in correct order. */
|
||||
if (current_class != class_type_node && current_class != object_type_node)
|
||||
TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class));
|
||||
|
||||
push_obstacks (&permanent_obstack, &permanent_obstack);
|
||||
layout_class (current_class);
|
||||
pop_obstacks ();
|
||||
}
|
||||
|
||||
void
|
||||
init_outgoing_cpool ()
|
||||
{
|
||||
current_constant_pool_data_ref = NULL_TREE;
|
||||
if (outgoing_cpool == NULL)
|
||||
{
|
||||
static CPool outgoing_cpool_buffer;
|
||||
outgoing_cpool = &outgoing_cpool_buffer;
|
||||
CPOOL_INIT(outgoing_cpool);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPOOL_REINIT(outgoing_cpool);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parse_class_file ()
|
||||
{
|
||||
tree method;
|
||||
char *save_input_filename = input_filename;
|
||||
int save_lineno = lineno;
|
||||
|
||||
input_filename = DECL_SOURCE_FILE (TYPE_NAME (current_class));
|
||||
lineno = 0;
|
||||
debug_start_source_file (input_filename);
|
||||
init_outgoing_cpool ();
|
||||
|
||||
for ( method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class));
|
||||
method != NULL_TREE; method = TREE_CHAIN (method))
|
||||
{
|
||||
JCF *jcf = current_jcf;
|
||||
|
||||
if (METHOD_NATIVE (method) || METHOD_ABSTRACT (method))
|
||||
continue;
|
||||
|
||||
if (DECL_CODE_OFFSET (method) == 0)
|
||||
{
|
||||
error ("missing Code attribute");
|
||||
continue;
|
||||
}
|
||||
|
||||
lineno = 0;
|
||||
if (DECL_LINENUMBERS_OFFSET (method))
|
||||
{
|
||||
register int i;
|
||||
register unsigned char *ptr;
|
||||
JCF_SEEK (jcf, DECL_LINENUMBERS_OFFSET (method));
|
||||
linenumber_count = i = JCF_readu2 (jcf);
|
||||
linenumber_table = ptr = jcf->read_ptr;
|
||||
|
||||
for (ptr += 2; --i >= 0; ptr += 4)
|
||||
{
|
||||
int line = GET_u2 (ptr);
|
||||
/* Set initial lineno lineno to smallest linenumber.
|
||||
* Needs to be set before init_function_start. */
|
||||
if (lineno == 0 || line < lineno)
|
||||
lineno = line;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
linenumber_table = NULL;
|
||||
linenumber_count = 0;
|
||||
}
|
||||
|
||||
start_java_method (method);
|
||||
|
||||
give_name_to_locals (jcf);
|
||||
|
||||
/* Actually generate code. */
|
||||
expand_byte_code (jcf, method);
|
||||
|
||||
end_java_method ();
|
||||
}
|
||||
|
||||
if (flag_emit_class_files)
|
||||
write_classfile (current_class);
|
||||
make_class_data (current_class);
|
||||
register_class ();
|
||||
rest_of_decl_compilation (TYPE_NAME (current_class), (char*) 0, 1, 0);
|
||||
|
||||
debug_end_source_file (save_lineno);
|
||||
input_filename = save_input_filename;
|
||||
lineno = save_lineno;
|
||||
}
|
||||
|
||||
/* Parse a source file, as pointed by the current JCF. If PARSE_ONLY
|
||||
is non zero, we're not parsing a file found on the command line and
|
||||
we skip things related to code generation. */
|
||||
|
||||
static void
|
||||
parse_source_file (parse_only)
|
||||
int parse_only;
|
||||
{
|
||||
lang_init_source (1); /* Error msgs have no method prototypes */
|
||||
java_push_parser_context ();
|
||||
java_init_lex (); /* Initialize the parser */
|
||||
java_parse_abort_on_error ();
|
||||
java_parse (); /* Parse and build partial tree nodes. */
|
||||
java_parse_abort_on_error ();
|
||||
java_complete_class (); /* Parse unsatisfied class decl. */
|
||||
java_parse_abort_on_error ();
|
||||
java_check_circular_reference (); /* Check on circular references */
|
||||
java_parse_abort_on_error ();
|
||||
java_check_methods (); /* Check the methods */
|
||||
java_parse_abort_on_error ();
|
||||
java_layout_classes ();
|
||||
java_parse_abort_on_error ();
|
||||
if (!parse_only)
|
||||
{
|
||||
lang_init_source (2); /* Error msgs have method prototypes */
|
||||
java_complete_expand_methods (); /* Complete and expand method bodies */
|
||||
java_parse_abort_on_error ();
|
||||
java_expand_finals (); /* Expand and check the finals */
|
||||
java_parse_abort_on_error ();
|
||||
java_check_final (); /* Check unitialized final */
|
||||
java_parse_abort_on_error ();
|
||||
if (! flag_emit_class_files)
|
||||
emit_register_class ();
|
||||
java_report_errors (); /* Final step for this file */
|
||||
}
|
||||
if (flag_emit_class_files)
|
||||
write_classfile (current_class);
|
||||
java_pop_parser_context ();
|
||||
}
|
||||
|
||||
int
|
||||
yyparse ()
|
||||
{
|
||||
/* Everything migh be enclosed within a loop processing each file after
|
||||
the other one. */
|
||||
|
||||
switch (jcf_figure_file_type (current_jcf))
|
||||
{
|
||||
case JCF_ZIP:
|
||||
parse_zip_file_entries ();
|
||||
emit_register_class ();
|
||||
break;
|
||||
case JCF_CLASS:
|
||||
jcf_parse (current_jcf);
|
||||
parse_class_file ();
|
||||
emit_register_class ();
|
||||
break;
|
||||
case JCF_SOURCE:
|
||||
parse_source_file (0); /* Parse and generate */
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ZipFileCache *localToFile;
|
||||
|
||||
/* Process all class entries found in the zip file. */
|
||||
void
|
||||
parse_zip_file_entries (void)
|
||||
{
|
||||
struct ZipDirectory *zdir;
|
||||
int i;
|
||||
|
||||
for (i = 0, zdir = (ZipDirectory *)localToFile->z.central_directory;
|
||||
i < localToFile->z.count; i++, zdir = ZIPDIR_NEXT (zdir))
|
||||
{
|
||||
tree class;
|
||||
|
||||
/* We don't need to consider those files. */
|
||||
if (!zdir->size || !zdir->filename_offset)
|
||||
continue;
|
||||
|
||||
class = lookup_class (get_identifier (ZIPDIR_FILENAME (zdir)));
|
||||
current_jcf = TYPE_LANG_SPECIFIC (class)->jcf;
|
||||
current_class = class;
|
||||
|
||||
if ( !CLASS_LOADED_P (class))
|
||||
{
|
||||
fseek (current_jcf->read_state, current_jcf->zip_offset, SEEK_SET);
|
||||
jcf_parse (current_jcf);
|
||||
}
|
||||
|
||||
input_filename = current_jcf->filename;
|
||||
|
||||
parse_class_file ();
|
||||
FREE (current_jcf->buffer); /* No longer necessary */
|
||||
/* Note: there is a way to free this buffer right after a class seen
|
||||
in a zip file has been parsed. The idea is the set its jcf in such
|
||||
a way that buffer will be reallocated the time the code for the class
|
||||
will be generated. FIXME. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Read all the entries of the zip file, creates a class and a JCF. Sets the
|
||||
jcf up for further processing and link it to the created class. */
|
||||
|
||||
void process_zip_dir()
|
||||
{
|
||||
int i;
|
||||
ZipDirectory *zdir;
|
||||
|
||||
for (i = 0, zdir = (ZipDirectory *)localToFile->z.central_directory;
|
||||
i < localToFile->z.count; i++, zdir = ZIPDIR_NEXT (zdir))
|
||||
{
|
||||
char *class_name, *file_name, *class_name_in_zip_dir;
|
||||
tree class;
|
||||
JCF *jcf;
|
||||
int j;
|
||||
|
||||
class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
|
||||
|
||||
/* We choose to not to process entries with a zero size or entries
|
||||
not bearing the .class extention. */
|
||||
if (!zdir->size || !zdir->filename_offset ||
|
||||
strncmp (&class_name_in_zip_dir[zdir->filename_length-6],
|
||||
".class", 6))
|
||||
{
|
||||
/* So it will be skipped in parse_zip_file_entries */
|
||||
zdir->size = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
class_name = ALLOC (zdir->filename_length+1-6);
|
||||
file_name = ALLOC (zdir->filename_length+1);
|
||||
jcf = ALLOC (sizeof (JCF));
|
||||
JCF_ZERO (jcf);
|
||||
|
||||
strncpy (class_name, class_name_in_zip_dir, zdir->filename_length-6);
|
||||
class_name [zdir->filename_length-6] = '\0';
|
||||
strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
|
||||
file_name [zdir->filename_length] = '\0';
|
||||
|
||||
for (j=0; class_name[j]; j++)
|
||||
class_name [j] = (class_name [j] == '/' ? '.' : class_name [j]);
|
||||
|
||||
/* Yes, we write back the true class name into the zip directory. */
|
||||
strcpy (class_name_in_zip_dir, class_name);
|
||||
zdir->filename_length = j;
|
||||
class = lookup_class (get_identifier (class_name));
|
||||
|
||||
jcf->read_state = finput;
|
||||
jcf->filbuf = jcf_filbuf_from_stdio;
|
||||
jcf->seen_in_zip = 1;
|
||||
jcf->java_source = 0;
|
||||
jcf->zip_offset = zdir->filestart;
|
||||
jcf->classname = class_name;
|
||||
jcf->filename = file_name;
|
||||
|
||||
TYPE_LANG_SPECIFIC (class) =
|
||||
(struct lang_type *) perm_calloc (1, sizeof (struct lang_type));
|
||||
TYPE_LANG_SPECIFIC (class)->jcf = jcf;
|
||||
}
|
||||
}
|
||||
|
||||
/* Lookup class NAME and figure whether is a class already found in the current
|
||||
zip file. */
|
||||
int
|
||||
DEFUN(find_in_current_zip, (name, length, jcf),
|
||||
char *name AND int length AND JCF **jcf)
|
||||
{
|
||||
JCF *local_jcf;
|
||||
tree class_name = maybe_get_identifier (name), class, icv;
|
||||
|
||||
if (!class_name)
|
||||
return 0;
|
||||
|
||||
if (!(icv = IDENTIFIER_CLASS_VALUE (class_name)))
|
||||
return 0;
|
||||
|
||||
class = TREE_TYPE (icv);
|
||||
|
||||
/* Doesn't have jcf specific info ? It's not ours */
|
||||
if (!TYPE_LANG_SPECIFIC (class) || !TYPE_LANG_SPECIFIC (class)->jcf)
|
||||
return 0;
|
||||
|
||||
*jcf = local_jcf = TYPE_LANG_SPECIFIC (class)->jcf;
|
||||
fseek (local_jcf->read_state, local_jcf->zip_offset, SEEK_SET);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Figure what kind of file we're dealing with */
|
||||
int
|
||||
DEFUN(jcf_figure_file_type, (jcf),
|
||||
JCF *jcf)
|
||||
{
|
||||
unsigned char magic_string[4];
|
||||
uint32 magic;
|
||||
|
||||
if (fread (magic_string, 1, 4, jcf->read_state) != 4)
|
||||
jcf_unexpected_eof (jcf, 4);
|
||||
|
||||
fseek (jcf->read_state, 0L, SEEK_SET);
|
||||
magic = GET_u4 (magic_string);
|
||||
|
||||
if (magic == 0xcafebabe)
|
||||
return JCF_CLASS;
|
||||
|
||||
if (!open_in_zip (jcf, input_filename, NULL))
|
||||
{
|
||||
localToFile = ALLOC (sizeof (struct ZipFileCache));
|
||||
bcopy (SeenZipFiles, localToFile, sizeof (struct ZipFileCache));
|
||||
process_zip_dir (); /* Register all the class defined there */
|
||||
return JCF_ZIP;
|
||||
}
|
||||
|
||||
return JCF_SOURCE;
|
||||
}
|
||||
|
352
gcc/java/jcf-reader.c
Normal file
352
gcc/java/jcf-reader.c
Normal file
|
@ -0,0 +1,352 @@
|
|||
/* This file read a Java(TM) .class file.
|
||||
It is not stand-alone: It depends on tons of macros, and the
|
||||
intent is you #include this file after you've defined the macros.
|
||||
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
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, 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
#include "jcf.h"
|
||||
#include "zipfile.h"
|
||||
|
||||
int
|
||||
DEFUN(get_attribute, (jcf),
|
||||
JCF *jcf)
|
||||
{
|
||||
uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf));
|
||||
uint32 attribute_length = JCF_readu4 (jcf);
|
||||
uint32 start_pos = JCF_TELL(jcf);
|
||||
int name_length;
|
||||
unsigned char *name_data;
|
||||
JCF_FILL (jcf, attribute_length);
|
||||
if (attribute_name <= 0 || attribute_name >= JPOOL_SIZE(jcf))
|
||||
return -2;
|
||||
if (JPOOL_TAG (jcf, attribute_name) != CONSTANT_Utf8)
|
||||
return -2;
|
||||
name_length = JPOOL_UTF_LENGTH (jcf, attribute_name);
|
||||
name_data = JPOOL_UTF_DATA (jcf, attribute_name);
|
||||
|
||||
#ifdef IGNORE_ATTRIBUTE
|
||||
if (IGNORE_ATTRIBUTE (jcf, attribute_name, attribute_length))
|
||||
{
|
||||
JCF_SKIP (jcf, attribute_length);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef HANDLE_SOURCEFILE
|
||||
if (name_length == 10 && memcmp (name_data, "SourceFile", 10) == 0)
|
||||
{
|
||||
uint16 sourcefile_index = JCF_readu2 (jcf);
|
||||
HANDLE_SOURCEFILE(sourcefile_index);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef HANDLE_CONSTANTVALUE
|
||||
if (name_length == 13 && memcmp (name_data, "ConstantValue", 13) == 0)
|
||||
{
|
||||
uint16 constantvalue_index = JCF_readu2 (jcf);
|
||||
if (constantvalue_index <= 0 || constantvalue_index >= JPOOL_SIZE(jcf))
|
||||
return -2;
|
||||
HANDLE_CONSTANTVALUE(constantvalue_index);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef HANDLE_CODE_ATTRIBUTE
|
||||
if (name_length == 4 && memcmp (name_data, "Code", 4) == 0)
|
||||
{
|
||||
uint16 j;
|
||||
uint16 max_stack = JCF_readu2 (jcf);
|
||||
uint16 max_locals = JCF_readu2 (jcf);
|
||||
uint32 code_length = JCF_readu4 (jcf);
|
||||
uint16 exception_table_length, attributes_count;
|
||||
if (code_length + 12 > attribute_length)
|
||||
return -1;
|
||||
HANDLE_CODE_ATTRIBUTE(max_stack, max_locals, code_length);
|
||||
JCF_SKIP (jcf, code_length);
|
||||
exception_table_length = JCF_readu2 (jcf);
|
||||
if (code_length + 8 * exception_table_length + 12 > attribute_length)
|
||||
return -1;
|
||||
JCF_SKIP (jcf, 2 * 4 * exception_table_length);
|
||||
attributes_count = JCF_readu2 (jcf);
|
||||
for (j = 0; j < attributes_count; j++)
|
||||
{
|
||||
int code = get_attribute (jcf);
|
||||
if (code != 0)
|
||||
return code;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* HANDLE_CODE_ATTRIBUTE */
|
||||
#ifdef HANDLE_EXCEPTIONS_ATTRIBUTE
|
||||
if (name_length == 10 && memcmp (name_data, "Exceptions", 10) == 0)
|
||||
{
|
||||
uint16 count = JCF_readu2 (jcf);
|
||||
HANDLE_EXCEPTIONS_ATTRIBUTE (count);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef HANDLE_LINENUMBERTABLE_ATTRIBUTE
|
||||
if (name_length == 15 && memcmp (name_data, "LineNumberTable", 15) == 0)
|
||||
{
|
||||
uint16 count = JCF_readu2 (jcf);
|
||||
HANDLE_LINENUMBERTABLE_ATTRIBUTE (count);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef HANDLE_LOCALVARIABLETABLE_ATTRIBUTE
|
||||
if (name_length == 18 && memcmp (name_data, "LocalVariableTable", 18) == 0)
|
||||
{
|
||||
uint16 count = JCF_readu2 (jcf);
|
||||
HANDLE_LOCALVARIABLETABLE_ATTRIBUTE (count);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef PROCESS_OTHER_ATTRIBUTE
|
||||
PROCESS_OTHER_ATTRIBUTE(jcf, attribute_name, attribute_length);
|
||||
#else
|
||||
JCF_SKIP (jcf, attribute_length);
|
||||
#endif
|
||||
}
|
||||
if (start_pos + attribute_length != JCF_TELL(jcf))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read and handle the pre-amble. */
|
||||
int
|
||||
DEFUN(jcf_parse_preamble, (jcf),
|
||||
JCF* jcf)
|
||||
{
|
||||
uint32 magic = (JCF_FILL (jcf, 8), JCF_readu4 (jcf));
|
||||
uint16 minor_version = JCF_readu2 (jcf);
|
||||
uint16 major_version = JCF_readu2 (jcf);
|
||||
#ifdef HANDLE_MAGIC
|
||||
HANDLE_MAGIC (magic, minor_version, major_version);
|
||||
#endif
|
||||
if (magic != 0xcafebabe)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read and handle the constant pool.
|
||||
|
||||
Return 0 if OK.
|
||||
Return -2 if a bad cross-reference (index of other constant) was seen.
|
||||
*/
|
||||
int
|
||||
DEFUN(jcf_parse_constant_pool, (jcf),
|
||||
JCF* jcf)
|
||||
{
|
||||
int i, n;
|
||||
JPOOL_SIZE (jcf) = (JCF_FILL (jcf, 2), JCF_readu2 (jcf));
|
||||
jcf->cpool.tags = ALLOC (JPOOL_SIZE (jcf));
|
||||
jcf->cpool.data = ALLOC (sizeof (jword) * JPOOL_SIZE (jcf));
|
||||
jcf->cpool.tags[0] = 0;
|
||||
#ifdef HANDLE_START_CONSTANT_POOL
|
||||
HANDLE_START_CONSTANT_POOL (JPOOL_SIZE (jcf));
|
||||
#endif
|
||||
for (i = 1; i < (int) JPOOL_SIZE (jcf); i++)
|
||||
{
|
||||
int constant_kind;
|
||||
|
||||
/* Make sure at least 9 bytes are available. This is enough
|
||||
for all fixed-sized constant pool entries (so we don't need many
|
||||
more JCF_FILL calls below), but is is small enough that
|
||||
we are guaranteed to not hit EOF (in a valid .class file). */
|
||||
JCF_FILL (jcf, 9);
|
||||
constant_kind = JCF_readu (jcf);
|
||||
jcf->cpool.tags[i] = constant_kind;
|
||||
switch (constant_kind)
|
||||
{
|
||||
case CONSTANT_String:
|
||||
case CONSTANT_Class:
|
||||
jcf->cpool.data[i] = JCF_readu2 (jcf);
|
||||
break;
|
||||
case CONSTANT_Fieldref:
|
||||
case CONSTANT_Methodref:
|
||||
case CONSTANT_InterfaceMethodref:
|
||||
case CONSTANT_NameAndType:
|
||||
jcf->cpool.data[i] = JCF_readu2 (jcf);
|
||||
jcf->cpool.data[i] |= JCF_readu2 (jcf) << 16;
|
||||
break;
|
||||
case CONSTANT_Integer:
|
||||
case CONSTANT_Float:
|
||||
jcf->cpool.data[i] = JCF_readu4 (jcf);
|
||||
break;
|
||||
case CONSTANT_Long:
|
||||
case CONSTANT_Double:
|
||||
jcf->cpool.data[i] = JCF_readu4 (jcf);
|
||||
i++; /* These take up two spots in the constant pool */
|
||||
jcf->cpool.tags[i] = 0;
|
||||
jcf->cpool.data[i] = JCF_readu4 (jcf);
|
||||
break;
|
||||
case CONSTANT_Utf8:
|
||||
n = JCF_readu2 (jcf);
|
||||
JCF_FILL (jcf, n);
|
||||
#ifdef HANDLE_CONSTANT_Utf8
|
||||
HANDLE_CONSTANT_Utf8(jcf, i, n);
|
||||
#else
|
||||
jcf->cpool.data[i] = JCF_TELL(jcf) - 2;
|
||||
JCF_SKIP (jcf, n);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read various class flags and numbers. */
|
||||
|
||||
void
|
||||
DEFUN(jcf_parse_class, (jcf),
|
||||
JCF* jcf)
|
||||
{
|
||||
int i;
|
||||
uint16 interfaces_count;
|
||||
JCF_FILL (jcf, 8);
|
||||
jcf->access_flags = JCF_readu2 (jcf);
|
||||
jcf->this_class = JCF_readu2 (jcf);
|
||||
jcf->super_class = JCF_readu2 (jcf);
|
||||
interfaces_count = JCF_readu2 (jcf);
|
||||
|
||||
#ifdef HANDLE_CLASS_INFO
|
||||
HANDLE_CLASS_INFO(jcf->access_flags, jcf->this_class, jcf->super_class, interfaces_count);
|
||||
#endif
|
||||
|
||||
JCF_FILL (jcf, 2 * interfaces_count);
|
||||
|
||||
/* Read interfaces. */
|
||||
for (i = 0; i < interfaces_count; i++)
|
||||
{
|
||||
uint16 index = JCF_readu2 (jcf);
|
||||
#ifdef HANDLE_CLASS_INTERFACE
|
||||
HANDLE_CLASS_INTERFACE (index);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Read fields. */
|
||||
int
|
||||
DEFUN(jcf_parse_fields, (jcf),
|
||||
JCF* jcf)
|
||||
{
|
||||
int i, j;
|
||||
uint16 fields_count;
|
||||
JCF_FILL (jcf, 2);
|
||||
fields_count = JCF_readu2 (jcf);
|
||||
|
||||
#ifdef HANDLE_START_FIELDS
|
||||
HANDLE_START_FIELDS (fields_count);
|
||||
#endif
|
||||
for (i = 0; i < fields_count; i++)
|
||||
{
|
||||
uint16 access_flags = (JCF_FILL (jcf, 8), JCF_readu2 (jcf));
|
||||
uint16 name_index = JCF_readu2 (jcf);
|
||||
uint16 signature_index = JCF_readu2 (jcf);
|
||||
uint16 attribute_count = JCF_readu2 (jcf);
|
||||
#ifdef HANDLE_START_FIELD
|
||||
HANDLE_START_FIELD (access_flags, name_index, signature_index,
|
||||
attribute_count);
|
||||
#endif
|
||||
for (j = 0; j < attribute_count; j++)
|
||||
{
|
||||
int code = get_attribute (jcf);
|
||||
if (code != 0)
|
||||
return code;
|
||||
}
|
||||
#ifdef HANDLE_END_FIELD
|
||||
HANDLE_END_FIELD ();
|
||||
#endif
|
||||
}
|
||||
#ifdef HANDLE_END_FIELDS
|
||||
HANDLE_END_FIELDS ();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read methods. */
|
||||
|
||||
int
|
||||
DEFUN(jcf_parse_one_method, (jcf),
|
||||
JCF* jcf)
|
||||
{
|
||||
int i;
|
||||
uint16 access_flags = (JCF_FILL (jcf, 8), JCF_readu2 (jcf));
|
||||
uint16 name_index = JCF_readu2 (jcf);
|
||||
uint16 signature_index = JCF_readu2 (jcf);
|
||||
uint16 attribute_count = JCF_readu2 (jcf);
|
||||
#ifdef HANDLE_METHOD
|
||||
HANDLE_METHOD(access_flags, name_index, signature_index, attribute_count);
|
||||
#endif
|
||||
for (i = 0; i < attribute_count; i++)
|
||||
{
|
||||
int code = get_attribute (jcf);
|
||||
if (code != 0)
|
||||
return code;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
DEFUN(jcf_parse_methods, (jcf),
|
||||
JCF* jcf)
|
||||
{
|
||||
int i;
|
||||
uint16 methods_count;
|
||||
JCF_FILL (jcf, 2);
|
||||
methods_count = JCF_readu2 (jcf);
|
||||
#ifdef HANDLE_START_METHODS
|
||||
HANDLE_START_METHODS (methods_count);
|
||||
#endif
|
||||
for (i = 0; i < methods_count; i++)
|
||||
{
|
||||
int code = jcf_parse_one_method (jcf);
|
||||
if (code != 0)
|
||||
return code;
|
||||
}
|
||||
#ifdef HANDLE_END_METHODS
|
||||
HANDLE_END_METHODS ();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read attributes. */
|
||||
int
|
||||
DEFUN(jcf_parse_final_attributes, (jcf),
|
||||
JCF *jcf)
|
||||
{
|
||||
int i;
|
||||
uint16 attributes_count = (JCF_FILL (jcf, 2), JCF_readu2 (jcf));
|
||||
#ifdef START_FINAL_ATTRIBUTES
|
||||
START_FINAL_ATTRIBUTES (attributes_count)
|
||||
#endif
|
||||
for (i = 0; i < attributes_count; i++)
|
||||
{
|
||||
int code = get_attribute (jcf);
|
||||
if (code != 0)
|
||||
return code;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
964
gcc/java/jcf-write.c
Normal file
964
gcc/java/jcf-write.c
Normal file
|
@ -0,0 +1,964 @@
|
|||
/* Write out a Java(TM) class file.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
#include "config.h"
|
||||
#include "tree.h"
|
||||
#include "java-tree.h"
|
||||
#include "jcf.h"
|
||||
#include <stdio.h>
|
||||
#include "obstack.h"
|
||||
#undef AND
|
||||
#include "rtl.h"
|
||||
#include "java-opcodes.h"
|
||||
#include "parse.h" /* for BLOCK_EXPR_BODY */
|
||||
#include "buffer.h"
|
||||
|
||||
extern struct obstack temporary_obstack;
|
||||
|
||||
/* The buffer allocated for bytecode for the current method. */
|
||||
|
||||
struct buffer bytecode = NULL_BUFFER;
|
||||
|
||||
/* Make sure bytecode.data is big enough for at least N more bytes. */
|
||||
|
||||
#define RESERVE(N) \
|
||||
do { if (bytecode.ptr + (N) > bytecode.limit) buffer_grow (&bytecode, N); } while (0)
|
||||
|
||||
/* Add a 1-byte instruction/operand I to bytecode.data,
|
||||
assuming space has already been RESERVE'd. */
|
||||
|
||||
#define OP1(I) (*bytecode.ptr++ = (I))
|
||||
|
||||
/* Like OP1, but I is a 2-byte big endian integer. */
|
||||
|
||||
#define OP2(I) \
|
||||
do { int _I = (I); OP1 (_I >> 8); OP1 (_I); } while (0)
|
||||
|
||||
/* Like OP1, but I is a 4-byte big endian integer. */
|
||||
|
||||
#define OP4(I) \
|
||||
do { int _I = (I); OP1 (_I >> 24); OP1 (_I >> 16); \
|
||||
OP1 (_I >> 8); OP1 (_I); } while (0)
|
||||
|
||||
/* The current stack size (stack pointer) in the current method. */
|
||||
|
||||
int code_SP = 0;
|
||||
|
||||
/* The largest extent of stack size (stack pointer) in the current method. */
|
||||
|
||||
int code_SP_max = 0;
|
||||
|
||||
CPool *code_cpool;
|
||||
|
||||
/* Macro to call each time we push I words on the JVM stack. */
|
||||
|
||||
#define NOTE_PUSH(I) \
|
||||
do { code_SP += (I); if (code_SP > code_SP_max) code_SP_max = code_SP; } while (0)
|
||||
|
||||
/* Macro to call each time we pop I words from the JVM stack. */
|
||||
|
||||
#define NOTE_POP(I) \
|
||||
do { code_SP -= (I); if (code_SP < 0) abort(); } while (0)
|
||||
|
||||
/* A chunk or segment of a .class file. */
|
||||
|
||||
struct chunk
|
||||
{
|
||||
/* The next segment of this .class file. */
|
||||
struct chunk *next;
|
||||
|
||||
/* The actual data in this segment to be written to the .class file. */
|
||||
unsigned char *data;
|
||||
|
||||
/* The size of the segment to be written to the .class file. */
|
||||
int size;
|
||||
};
|
||||
|
||||
/* Utility macros for appending (big-endian) data to a buffer.
|
||||
We assume a local variable 'ptr' points into where we want to
|
||||
write next, and we assume enoygh space has been allocated. */
|
||||
|
||||
#define PUT1(X) (*ptr++ = (X))
|
||||
#define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
|
||||
#define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
|
||||
#define PUTN(P, N) (bcopy(P, ptr, N), ptr += (N))
|
||||
|
||||
|
||||
/* A buffer for storing line number entries for the current method. */
|
||||
struct buffer linenumbers = NULL_BUFFER;
|
||||
|
||||
/* Append a line number entry for the given PC and LINE into
|
||||
linenumbers.data. This will later before a LineNumberTable attribute. */
|
||||
|
||||
void
|
||||
put_linenumber (pc, line)
|
||||
int pc, line;
|
||||
{
|
||||
register unsigned char *ptr;
|
||||
if (linenumbers.ptr == linenumbers.limit)
|
||||
buffer_grow (&linenumbers, 4);
|
||||
ptr = linenumbers.ptr;
|
||||
PUT2 (pc);
|
||||
PUT2 (line);
|
||||
linenumbers.ptr = ptr;
|
||||
}
|
||||
|
||||
/* The index of jvm local variable allocated for this DECL.
|
||||
This is assign when generating .class files;
|
||||
contrast DECL_LOCAL_SLOT_NUMBER whcih is set when *reading* a .class file.
|
||||
(We don't allocate DECL_LANG_SPECIFIC for locals from Java sourc code.) */
|
||||
|
||||
#define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
|
||||
|
||||
struct localvar_info
|
||||
{
|
||||
tree decl;
|
||||
|
||||
int start_pc;
|
||||
|
||||
/* Offset in LocalVariableTable. */
|
||||
int debug_offset;
|
||||
};
|
||||
|
||||
struct buffer localvars = NULL_BUFFER;
|
||||
|
||||
#define localvar_buffer ((struct localvar_info*) localvars.data)
|
||||
#define localvar_max ((struct localvar_info*) localvars.ptr - localvar_buffer)
|
||||
|
||||
/* A buffer for storing LocalVariableTable entries entries. */
|
||||
|
||||
struct buffer localvartable = NULL_BUFFER;
|
||||
|
||||
int
|
||||
localvar_alloc (decl, start_pc)
|
||||
tree decl;
|
||||
int start_pc;
|
||||
{
|
||||
int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
|
||||
int index;
|
||||
register struct localvar_info *info = (struct localvar_info*)localvars.data;
|
||||
register struct localvar_info *limit = (struct localvar_info*)localvars.ptr;
|
||||
for (index = 0; info < limit; index++, info++)
|
||||
{
|
||||
if (info->decl == NULL_TREE
|
||||
&& (! wide || (info+1)->decl == NULL_TREE))
|
||||
break;
|
||||
}
|
||||
if (info == limit)
|
||||
{
|
||||
buffer_grow (&localvars, sizeof (struct localvar_info));
|
||||
info = (struct localvar_info*)localvars.data + index;
|
||||
localvars.ptr = (unsigned char *) (info + 1 + wide);
|
||||
}
|
||||
info->decl = decl;
|
||||
if (wide)
|
||||
(info+1)->decl = TYPE_SECOND;
|
||||
DECL_LOCAL_INDEX (decl) = index;
|
||||
info->start_pc = start_pc;
|
||||
|
||||
if (DECL_NAME (decl) != NULL_TREE)
|
||||
{
|
||||
/* Generate debugging info. */
|
||||
int i;
|
||||
register unsigned char *ptr;
|
||||
buffer_grow (&localvartable, 10);
|
||||
ptr = localvartable.ptr;
|
||||
info->debug_offset = ptr - localvartable.data;
|
||||
PUT2 (start_pc);
|
||||
PUT2 (0); /* length - fill in later */
|
||||
i = find_utf8_constant (code_cpool, DECL_NAME (decl));
|
||||
PUT2 (i); /* name_index*/
|
||||
i = find_utf8_constant (code_cpool,
|
||||
build_java_signature (TREE_TYPE (decl)));
|
||||
PUT2 (i); /* descriptor_index */
|
||||
PUT2 (index);
|
||||
localvartable.ptr = ptr;
|
||||
}
|
||||
else
|
||||
info->debug_offset = -1;
|
||||
}
|
||||
|
||||
int
|
||||
localvar_free (decl, end_pc)
|
||||
tree decl;
|
||||
int end_pc;
|
||||
{
|
||||
register unsigned char *ptr;
|
||||
int index = DECL_LOCAL_INDEX (decl);
|
||||
register struct localvar_info *info = &localvar_buffer [index];
|
||||
int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
|
||||
int i;
|
||||
|
||||
i = info->debug_offset;
|
||||
if (i >= 0)
|
||||
{
|
||||
register unsigned char *ptr;
|
||||
/* Point to length field of local_variable_table. */
|
||||
ptr = localvartable.data + i + 2;
|
||||
i = end_pc - info->start_pc;
|
||||
PUT2 (i);
|
||||
}
|
||||
|
||||
if (info->decl != decl)
|
||||
abort ();
|
||||
info->decl = NULL_TREE;
|
||||
if (wide)
|
||||
{
|
||||
info++;
|
||||
if (info->decl != TYPE_SECOND)
|
||||
abort ();
|
||||
info->decl = NULL_TREE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#define STACK_TARGET 1
|
||||
#define IGNORE_TARGET 2
|
||||
|
||||
/* Allocate a new chunk on obstack WORK, and link it in after LAST.
|
||||
Set the data and size fields to DATA and SIZE, respectively.
|
||||
However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
|
||||
|
||||
struct chunk *
|
||||
alloc_chunk (last, data, size, work)
|
||||
struct chunk *last;
|
||||
unsigned char *data;
|
||||
int size;
|
||||
struct obstack *work;
|
||||
{
|
||||
struct chunk *chunk = (struct chunk *)
|
||||
obstack_alloc (work, sizeof(struct chunk));
|
||||
|
||||
if (data == NULL && size > 0)
|
||||
data = obstack_alloc (work, size);
|
||||
|
||||
chunk->next = NULL;
|
||||
chunk->data = data;
|
||||
chunk->size = size;
|
||||
last->next = chunk;
|
||||
return chunk;
|
||||
}
|
||||
|
||||
/* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
|
||||
a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
|
||||
|
||||
int
|
||||
get_access_flags (decl)
|
||||
tree decl;
|
||||
{
|
||||
int flags = 0;
|
||||
int isfield = TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL;
|
||||
if (CLASS_PUBLIC (decl)) /* same as FIELD_PUBLIC and METHOD_PUBLIC */
|
||||
flags |= ACC_PUBLIC;
|
||||
if (CLASS_FINAL (decl)) /* same as FIELD_FINAL and METHOD_FINAL */
|
||||
flags |= ACC_PUBLIC;
|
||||
if (isfield || TREE_CODE (decl) == FUNCTION_DECL)
|
||||
{
|
||||
if (TREE_PROTECTED (decl))
|
||||
flags |= ACC_PROTECTED;
|
||||
if (TREE_PRIVATE (decl))
|
||||
flags |= ACC_PRIVATE;
|
||||
}
|
||||
else if (TREE_CODE (decl) == TYPE_DECL)
|
||||
{
|
||||
if (CLASS_SUPER (decl))
|
||||
flags |= ACC_SUPER;
|
||||
if (CLASS_ABSTRACT (decl))
|
||||
flags |= ACC_ABSTRACT;
|
||||
if (CLASS_INTERFACE (decl))
|
||||
flags |= ACC_INTERFACE;
|
||||
}
|
||||
else
|
||||
fatal ("internal error - bad argument to get_access_flags");
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||
{
|
||||
if (METHOD_NATIVE (decl))
|
||||
flags |= ACC_NATIVE;
|
||||
if (METHOD_STATIC (decl))
|
||||
flags |= ACC_STATIC;
|
||||
if (METHOD_FINAL (decl))
|
||||
flags |= ACC_FINAL;
|
||||
if (METHOD_SYNCHRONIZED (decl))
|
||||
flags |= ACC_SYNCHRONIZED;
|
||||
if (METHOD_ABSTRACT (decl))
|
||||
flags |= ACC_ABSTRACT;
|
||||
}
|
||||
if (isfield)
|
||||
{
|
||||
if (FIELD_STATIC (decl))
|
||||
flags |= ACC_STATIC;
|
||||
if (FIELD_VOLATILE (decl))
|
||||
flags |= ACC_VOLATILE;
|
||||
if (FIELD_TRANSIENT (decl))
|
||||
flags |= ACC_TRANSIENT;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* Write the list of segments starting at CHUNKS to STREAM. */
|
||||
|
||||
void
|
||||
write_chunks (stream, chunks)
|
||||
FILE* stream;
|
||||
struct chunk *chunks;
|
||||
{
|
||||
for (; chunks != NULL; chunks = chunks->next)
|
||||
fwrite (chunks->data, chunks->size, 1, stream);
|
||||
}
|
||||
|
||||
void
|
||||
push_constant1 (index)
|
||||
int index;
|
||||
{
|
||||
if (index < 256)
|
||||
{
|
||||
OP1 (OPCODE_ldc);
|
||||
OP1 (index);
|
||||
}
|
||||
else
|
||||
{
|
||||
OP1 (OPCODE_ldc_w);
|
||||
OP2 (index);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
push_constant2 (index)
|
||||
int index;
|
||||
{
|
||||
RESERVE (3);
|
||||
OP1 (OPCODE_ldc2_w);
|
||||
OP2 (index);
|
||||
}
|
||||
|
||||
void
|
||||
push_int_const (i)
|
||||
HOST_WIDE_INT i;
|
||||
{
|
||||
RESERVE(3);
|
||||
if (i >= -1 && i <= 5)
|
||||
OP1(OPCODE_iconst_0 + i);
|
||||
else if (i >= -128 && i < 128)
|
||||
{
|
||||
OP1(OPCODE_bipush);
|
||||
OP1(i);
|
||||
}
|
||||
else if (i >= -32768 && i < 32768)
|
||||
{
|
||||
OP1(OPCODE_sipush);
|
||||
OP2(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = find_constant1 (code_cpool, CONSTANT_Integer, i & 0xFFFFFFFF);
|
||||
push_constant1 (i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
push_long_const (lo, hi)
|
||||
HOST_WIDE_INT lo, hi;
|
||||
{
|
||||
if (hi == 0 && lo >= 0 && lo <= 1)
|
||||
{
|
||||
RESERVE(1);
|
||||
OP1(OPCODE_lconst_0 + lo);
|
||||
}
|
||||
#if 0
|
||||
else if ((jlong) (jint) i == i)
|
||||
{
|
||||
push_int_const ((jint) i);
|
||||
RESERVE (1);
|
||||
OP1 (OPCODE_i2l);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
HOST_WIDE_INT w1, w2;
|
||||
lshift_double (lo, hi, -32, 64, &w1, &w2, 1);
|
||||
hi = find_constant1 (code_cpool, CONSTANT_Long,
|
||||
w1 & 0xFFFFFFFF, lo & 0xFFFFFFFF);
|
||||
push_constant2 (hi);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
field_op (field, opcode)
|
||||
tree field;
|
||||
int opcode;
|
||||
{
|
||||
int index = find_fieldref_index (code_cpool, field);
|
||||
RESERVE (3);
|
||||
OP1 (opcode);
|
||||
OP2 (index);
|
||||
}
|
||||
|
||||
/* Returns an integer in the range 0 (for 'int') through 4 (for object
|
||||
reference) to 7 (for 'short') which matches the pattern of how JVM
|
||||
opcodes typically depend on the operand type. */
|
||||
|
||||
int
|
||||
adjust_typed_op (type)
|
||||
tree type;
|
||||
{
|
||||
switch (TREE_CODE (type))
|
||||
{
|
||||
case BOOLEAN_TYPE: return 5;
|
||||
case CHAR_TYPE: return 6;
|
||||
case POINTER_TYPE:
|
||||
case RECORD_TYPE: return 4;
|
||||
case INTEGER_TYPE:
|
||||
switch (TYPE_PRECISION (type))
|
||||
{
|
||||
case 8: return 5;
|
||||
case 16: return 7;
|
||||
case 32: return 0;
|
||||
case 64: return 1;
|
||||
}
|
||||
break;
|
||||
case REAL_TYPE:
|
||||
switch (TYPE_PRECISION (type))
|
||||
{
|
||||
case 32: return 2;
|
||||
case 64: return 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
abort ();
|
||||
}
|
||||
|
||||
void
|
||||
maybe_wide (opcode, index)
|
||||
int opcode, index;
|
||||
{
|
||||
if (index >= 256)
|
||||
{
|
||||
RESERVE (4);
|
||||
OP1 (196); /* wide */
|
||||
OP1 (opcode);
|
||||
OP2 (index);
|
||||
}
|
||||
else
|
||||
{
|
||||
RESERVE (2);
|
||||
OP1 (opcode);
|
||||
OP1 (index);
|
||||
}
|
||||
}
|
||||
|
||||
#define PC BUFFER_LENGTH(&bytecode)
|
||||
|
||||
/* Generate byetcode for sub-expression EXP of METHOD.
|
||||
TARGET is one of STACK_TARGET or IGNORE_TARGET. */
|
||||
|
||||
void
|
||||
generate_bytecode_insns (method, exp, target)
|
||||
tree method;
|
||||
tree exp;
|
||||
int target;
|
||||
{
|
||||
rtx value;
|
||||
tree type = TREE_TYPE (exp);
|
||||
enum java_opcode jopcode;
|
||||
int op;
|
||||
switch (TREE_CODE (exp))
|
||||
{
|
||||
case BLOCK:
|
||||
if (BLOCK_EXPR_BODY (exp))
|
||||
{
|
||||
tree local;
|
||||
for (local = BLOCK_EXPR_DECLS (exp); local; )
|
||||
{
|
||||
tree next = TREE_CHAIN (local);
|
||||
localvar_alloc (local, PC);
|
||||
local = next;
|
||||
}
|
||||
generate_bytecode_insns (method, BLOCK_EXPR_BODY (exp), target);
|
||||
for (local = BLOCK_EXPR_DECLS (exp); local; )
|
||||
{
|
||||
tree next = TREE_CHAIN (local);
|
||||
localvar_free (local, PC);
|
||||
local = next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case COMPOUND_EXPR:
|
||||
generate_bytecode_insns (method, TREE_OPERAND (exp, 0), IGNORE_TARGET);
|
||||
generate_bytecode_insns (method, TREE_OPERAND (exp, 1), target);
|
||||
break;
|
||||
case EXPR_WITH_FILE_LOCATION:
|
||||
{
|
||||
char *saved_input_filename = input_filename;
|
||||
int saved_lineno = lineno;
|
||||
input_filename = EXPR_WFL_FILENAME (exp);
|
||||
lineno = EXPR_WFL_LINENO (exp);
|
||||
if (EXPR_WFL_EMIT_LINE_NOTE (exp))
|
||||
put_linenumber (PC, EXPR_WFL_LINENO (exp));
|
||||
generate_bytecode_insns (method, EXPR_WFL_NODE (exp), target);
|
||||
input_filename = saved_input_filename;
|
||||
lineno = saved_lineno;
|
||||
}
|
||||
break;
|
||||
case INTEGER_CST:
|
||||
if (target == IGNORE_TARGET) ; /* do nothing */
|
||||
else if (TREE_CODE (type) == POINTER_TYPE)
|
||||
{
|
||||
if (! integer_zerop (exp))
|
||||
abort();
|
||||
RESERVE(1);
|
||||
OP1 (OPCODE_aconst_null);
|
||||
NOTE_PUSH (1);
|
||||
}
|
||||
else if (TYPE_PRECISION (type) <= 32)
|
||||
{
|
||||
push_int_const (TREE_INT_CST_LOW (exp));
|
||||
NOTE_PUSH (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
push_long_const (TREE_INT_CST_LOW (exp), TREE_INT_CST_HIGH (exp));
|
||||
NOTE_PUSH (2);
|
||||
}
|
||||
break;
|
||||
case VAR_DECL:
|
||||
if (TREE_STATIC (exp))
|
||||
{
|
||||
field_op (exp, OPCODE_getstatic);
|
||||
break;
|
||||
}
|
||||
/* ... fall through ... */
|
||||
case PARM_DECL:
|
||||
{
|
||||
int kind = adjust_typed_op (type);
|
||||
int index = DECL_LOCAL_INDEX (exp);
|
||||
if (index <= 3)
|
||||
{
|
||||
RESERVE (1);
|
||||
OP1 (26 + 4 * kind + index); /* [ilfda]load_[0123] */
|
||||
}
|
||||
else
|
||||
maybe_wide (21 + kind, index); /* [ilfda]load */
|
||||
}
|
||||
break;
|
||||
case INDIRECT_REF:
|
||||
generate_bytecode_insns (method, TREE_OPERAND (exp, 0), target);
|
||||
break;
|
||||
case ARRAY_REF:
|
||||
generate_bytecode_insns (method, TREE_OPERAND (exp, 0), target);
|
||||
generate_bytecode_insns (method, TREE_OPERAND (exp, 1), target);
|
||||
if (target != IGNORE_TARGET)
|
||||
{
|
||||
jopcode = OPCODE_iaload + adjust_typed_op (type);
|
||||
RESERVE(1);
|
||||
OP1 (jopcode);
|
||||
}
|
||||
break;
|
||||
case COMPONENT_REF:
|
||||
{
|
||||
tree obj = TREE_OPERAND (exp, 0);
|
||||
tree field = TREE_OPERAND (exp, 1);
|
||||
int is_static = FIELD_STATIC (field);
|
||||
generate_bytecode_insns (method, obj,
|
||||
is_static ? IGNORE_TARGET : target);
|
||||
if (target != IGNORE_TARGET)
|
||||
{
|
||||
if (DECL_NAME (field) == length_identifier_node && !is_static
|
||||
&& TYPE_ARRAY_P (TREE_TYPE (obj)))
|
||||
{
|
||||
RESERVE (1);
|
||||
OP1 (OPCODE_arraylength);
|
||||
}
|
||||
else
|
||||
field_op (field, is_static ? OPCODE_getstatic : OPCODE_getfield);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RETURN_EXPR:
|
||||
if (!TREE_OPERAND (exp, 0))
|
||||
op = OPCODE_return;
|
||||
else
|
||||
{
|
||||
exp = TREE_OPERAND (exp, 0);
|
||||
if (TREE_CODE (exp) != MODIFY_EXPR)
|
||||
abort ();
|
||||
exp = TREE_OPERAND (exp, 1);
|
||||
op = OPCODE_ireturn + adjust_typed_op (TREE_TYPE (exp));
|
||||
generate_bytecode_insns (method, exp, STACK_TARGET);
|
||||
}
|
||||
RESERVE (1);
|
||||
OP1 (op);
|
||||
break;
|
||||
case MODIFY_EXPR:
|
||||
{
|
||||
tree lhs = TREE_OPERAND (exp, 0);
|
||||
tree rhs = TREE_OPERAND (exp, 1);
|
||||
HOST_WIDE_INT value;
|
||||
#if 0
|
||||
if (TREE_CODE (rhs) == PLUS_EXPR
|
||||
&& TREE_CODE (lhs) == VAR_DECL
|
||||
/* && FIXME lhs is a local variable */
|
||||
&& TYPE_MODE (TREE)TYPE (lhs) == SImode /* ??? */
|
||||
&& TREE_OPERAND (rhs, 0) == lhs
|
||||
&& TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST
|
||||
/* or vice versa FIXME */
|
||||
&& (value = TREE_INT_CST_LOW (TREE_OPERAND (rhs, 1)),
|
||||
(value >= -32768 && value <= 32767)))
|
||||
{
|
||||
emit_insn (gen_rtx (SET, SImode,
|
||||
DECL_RTL (lhs),
|
||||
gen_rtx (PLUS, SImode,
|
||||
DECL_RTL (lhs),
|
||||
gen_rtx_CONST_INT (SImode, value))));
|
||||
return DECL_RTL (lhs);
|
||||
}
|
||||
#endif
|
||||
if (TREE_CODE (lhs) == COMPONENT_REF)
|
||||
generate_bytecode_insns (method, TREE_OPERAND (lhs, 0), STACK_TARGET);
|
||||
else if (TREE_CODE (lhs) == ARRAY_REF)
|
||||
{
|
||||
generate_bytecode_insns (method,
|
||||
TREE_OPERAND (lhs, 0), STACK_TARGET);
|
||||
generate_bytecode_insns (method,
|
||||
TREE_OPERAND (lhs, 1), STACK_TARGET);
|
||||
}
|
||||
generate_bytecode_insns (method, rhs, STACK_TARGET);
|
||||
if (target != IGNORE_TARGET)
|
||||
{
|
||||
RESERVE (1);
|
||||
OP1 (TYPE_IS_WIDE (type) ? OPCODE_dup2_x1 : OPCODE_dup_x1);
|
||||
}
|
||||
if (TREE_CODE (lhs) == COMPONENT_REF)
|
||||
{
|
||||
tree field = TREE_OPERAND (lhs, 1);
|
||||
field_op (field,
|
||||
FIELD_STATIC (field) ? OPCODE_putstatic
|
||||
: OPCODE_putfield);
|
||||
}
|
||||
else if (TREE_CODE (lhs) == VAR_DECL
|
||||
|| TREE_CODE (lhs) == PARM_DECL)
|
||||
{
|
||||
if (FIELD_STATIC (lhs))
|
||||
{
|
||||
field_op (lhs, OPCODE_putstatic);
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = DECL_LOCAL_INDEX (lhs);
|
||||
int opcode = adjust_typed_op (TREE_TYPE (lhs));
|
||||
if (index <= 3)
|
||||
{
|
||||
RESERVE (1);
|
||||
opcode = 59 + 4 * opcode + index;
|
||||
OP1 (opcode); /* [ilfda]store_[0123] */
|
||||
}
|
||||
else
|
||||
{
|
||||
maybe_wide (54 + opcode, index); /* [ilfda]store */
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (lhs) == ARRAY_REF)
|
||||
{
|
||||
jopcode = OPCODE_iastore + adjust_typed_op (TREE_TYPE (lhs));
|
||||
RESERVE(1);
|
||||
OP1 (jopcode);
|
||||
}
|
||||
else
|
||||
fatal ("internal error (bad lhs to MODIFY_EXPR)");
|
||||
}
|
||||
break;
|
||||
case PLUS_EXPR:
|
||||
jopcode = OPCODE_iadd + adjust_typed_op (type);
|
||||
goto binop;
|
||||
case MINUS_EXPR:
|
||||
jopcode = OPCODE_isub + adjust_typed_op (type);
|
||||
goto binop;
|
||||
case MULT_EXPR:
|
||||
jopcode = OPCODE_imul + adjust_typed_op (type);
|
||||
goto binop;
|
||||
case TRUNC_DIV_EXPR:
|
||||
case RDIV_EXPR:
|
||||
jopcode = OPCODE_idiv + adjust_typed_op (type);
|
||||
goto binop;
|
||||
binop:
|
||||
generate_bytecode_insns (method, TREE_OPERAND (exp, 0), target);
|
||||
generate_bytecode_insns (method, TREE_OPERAND (exp, 1), target);
|
||||
if (target == STACK_TARGET)
|
||||
{
|
||||
RESERVE(1);
|
||||
OP1 (jopcode);
|
||||
}
|
||||
break;
|
||||
case CALL_EXPR:
|
||||
{
|
||||
tree t;
|
||||
for (t = TREE_OPERAND (exp, 1); t != NULL_TREE; t = TREE_CHAIN (t))
|
||||
{
|
||||
generate_bytecode_insns (method, TREE_VALUE (t), STACK_TARGET);
|
||||
}
|
||||
t = TREE_OPERAND (exp, 0);
|
||||
if (TREE_CODE (t) == FUNCTION_DECL)
|
||||
{
|
||||
int index = find_methodref_index (code_cpool, t);
|
||||
RESERVE (3);
|
||||
if (DECL_CONSTRUCTOR_P (t))
|
||||
OP1 (OPCODE_invokespecial);
|
||||
else if (METHOD_STATIC (t))
|
||||
OP1 (OPCODE_invokestatic);
|
||||
else
|
||||
OP1 (OPCODE_invokevirtual);
|
||||
OP2 (index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
error("internal error - tree code not implemented: ", TREE_CODE (exp));
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate and return a list of chunks containing the class CLAS
|
||||
in the .class file representation. The list can be written to a
|
||||
.class file using write_chunks. Allocate chunks from obstack WORK. */
|
||||
|
||||
/* Currently does not write any attributes i.e. no code. */
|
||||
|
||||
struct chunk *
|
||||
generate_classfile (clas, work)
|
||||
tree clas;
|
||||
struct obstack *work;
|
||||
{
|
||||
CPool cpool;
|
||||
struct chunk head;
|
||||
struct chunk *chunk;
|
||||
struct chunk *cpool_chunk;
|
||||
char *ptr;
|
||||
int i;
|
||||
char *fields_count_ptr;
|
||||
int fields_count = 0;
|
||||
char *methods_count_ptr;
|
||||
int methods_count = 0;
|
||||
tree part;
|
||||
int total_supers
|
||||
= clas == object_type_node ? 0
|
||||
: TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas));
|
||||
|
||||
chunk = alloc_chunk (&head, NULL, 8, work);
|
||||
ptr = chunk->data;
|
||||
PUT4 (0xCafeBabe); /* Magic number */
|
||||
PUT2 (3); /* Minor version */
|
||||
PUT2 (45); /* Major version */
|
||||
|
||||
CPOOL_INIT(&cpool);
|
||||
cpool_chunk = chunk = alloc_chunk (chunk, NULL, 0, work);
|
||||
|
||||
/* Next allocate the chunk containing acces_flags through fields_counr. */
|
||||
if (clas == object_type_node)
|
||||
i = 10;
|
||||
else
|
||||
i = 8 + 2 * total_supers;
|
||||
chunk = alloc_chunk (chunk, NULL, i, work);
|
||||
ptr = chunk->data;
|
||||
i = get_access_flags (TYPE_NAME (clas)); PUT2 (i); /* acces_flags */
|
||||
i = find_class_constant (&cpool, clas); PUT2 (i); /* this_class */
|
||||
if (clas == object_type_node)
|
||||
{
|
||||
PUT2(0); /* super_class */
|
||||
PUT2(0); /* interfaces_count */
|
||||
}
|
||||
else
|
||||
{
|
||||
tree basetypes = TYPE_BINFO_BASETYPES (clas);
|
||||
tree base = BINFO_TYPE (TREE_VEC_ELT (basetypes, 0));
|
||||
int j = find_class_constant (&cpool, base); PUT2 (j); /* super_class */
|
||||
PUT2 (total_supers - 1); /* interfaces_count */
|
||||
for (i = 1; i < total_supers; i++)
|
||||
{
|
||||
base = BINFO_TYPE (TREE_VEC_ELT (basetypes, i));
|
||||
j = find_class_constant (&cpool, base);
|
||||
PUT2 (j);
|
||||
}
|
||||
}
|
||||
fields_count_ptr = ptr;
|
||||
|
||||
for (part = TYPE_FIELDS (clas); part; part = TREE_CHAIN (part))
|
||||
{
|
||||
if (DECL_NAME (part) == NULL_TREE)
|
||||
continue;
|
||||
chunk = alloc_chunk (chunk, NULL, 8, work);
|
||||
ptr = chunk->data;
|
||||
i = get_access_flags (part); PUT2 (i);
|
||||
i = find_utf8_constant (&cpool, DECL_NAME (part)); PUT2 (i);
|
||||
i = find_utf8_constant (&cpool, build_java_signature (TREE_TYPE (part)));
|
||||
PUT2(i);
|
||||
PUT2 (0); /* attributes_count */
|
||||
/* FIXME - emit ConstantValue attribute when appropriate */
|
||||
fields_count++;
|
||||
}
|
||||
ptr = fields_count_ptr; PUT2 (fields_count);
|
||||
|
||||
chunk = alloc_chunk (chunk, NULL, 2, work);
|
||||
ptr = methods_count_ptr = chunk->data;
|
||||
PUT2 (0);
|
||||
|
||||
for (part = TYPE_METHODS (clas); part; part = TREE_CHAIN (part))
|
||||
{
|
||||
tree body = BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (part));
|
||||
int linenumber_size; /* 4 * number of line number entries */
|
||||
chunk = alloc_chunk (chunk, NULL, 8, work);
|
||||
ptr = chunk->data;
|
||||
i = get_access_flags (part); PUT2 (i);
|
||||
i = find_utf8_constant (&cpool, DECL_NAME (part)); PUT2 (i);
|
||||
i = find_utf8_constant (&cpool, build_java_signature (TREE_TYPE (part)));
|
||||
PUT2 (i);
|
||||
PUT2 (body != NULL_TREE ? 1 : 0); /* attributes_count */
|
||||
if (body != NULL_TREE)
|
||||
{
|
||||
int code_attributes_count = 0;
|
||||
int linenumber_size; /* 4 * number of line number entries */
|
||||
int localvartable_size; /* 10 * number of local variable entries */
|
||||
static tree Code_node = NULL_TREE;
|
||||
tree t;
|
||||
char *attr_len_ptr;
|
||||
int code_length;
|
||||
if (Code_node == NULL_TREE)
|
||||
Code_node = get_identifier ("Code");
|
||||
chunk = alloc_chunk (chunk, NULL, 14, work);
|
||||
ptr = chunk->data;
|
||||
i = find_utf8_constant (&cpool, Code_node); PUT2 (i);
|
||||
attr_len_ptr = ptr;
|
||||
BUFFER_RESET (&bytecode);
|
||||
BUFFER_RESET (&localvartable);
|
||||
BUFFER_RESET (&linenumbers);
|
||||
BUFFER_RESET (&localvars);
|
||||
code_SP = 0;
|
||||
code_SP_max = 0;
|
||||
code_cpool = &cpool;
|
||||
for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
|
||||
localvar_alloc (t, 0);
|
||||
generate_bytecode_insns (part, body, IGNORE_TARGET);
|
||||
code_length = PC;
|
||||
for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
|
||||
localvar_free (t, code_length);
|
||||
linenumber_size = BUFFER_LENGTH (&linenumbers);
|
||||
localvartable_size = BUFFER_LENGTH (&localvartable);
|
||||
chunk = alloc_chunk (chunk, NULL, code_length, work);
|
||||
bcopy (bytecode.data, chunk->data, code_length);
|
||||
ptr = attr_len_ptr;
|
||||
i = 8 + code_length + 4;
|
||||
if (linenumber_size > 0)
|
||||
{
|
||||
code_attributes_count++;
|
||||
i += 8 + linenumber_size;
|
||||
}
|
||||
if (localvartable_size > 0)
|
||||
{
|
||||
code_attributes_count++;
|
||||
i += 8 + localvartable_size;
|
||||
}
|
||||
PUT4 (i); /* attribute_length */
|
||||
PUT2 (code_SP_max); /* max_stack */
|
||||
PUT2 (localvar_max); /* max_locals */
|
||||
PUT4 (code_length);
|
||||
chunk = alloc_chunk (chunk, NULL, 4, work);
|
||||
ptr = chunk->data;
|
||||
PUT2 (0); /* exception_table_length */
|
||||
PUT2 (code_attributes_count);
|
||||
|
||||
/* Write the LineNumberTable attribute. */
|
||||
if (linenumber_size > 0)
|
||||
{
|
||||
static tree LineNumberTable_node = NULL_TREE;
|
||||
chunk = alloc_chunk (chunk, NULL, 8 + linenumber_size, work);
|
||||
ptr = chunk->data;
|
||||
if (LineNumberTable_node == NULL_TREE)
|
||||
LineNumberTable_node = get_identifier ("LineNumberTable");
|
||||
i = find_utf8_constant (&cpool, LineNumberTable_node);
|
||||
PUT2 (i); /* attribute_name_index */
|
||||
i = 2 + linenumber_size; PUT4 (i); /* attribute_length */
|
||||
i = linenumber_size >> 2; PUT2 (i);
|
||||
PUTN (linenumbers.data, linenumber_size);
|
||||
}
|
||||
|
||||
/* Write the LocalVariableTable attribute. */
|
||||
if (localvartable_size > 0)
|
||||
{
|
||||
static tree LocalVariableTable_node = NULL_TREE;
|
||||
chunk = alloc_chunk (chunk, NULL, 8 + localvartable_size, work);
|
||||
ptr = chunk->data;
|
||||
if (LocalVariableTable_node == NULL_TREE)
|
||||
LocalVariableTable_node = get_identifier("LocalVariableTable");
|
||||
i = find_utf8_constant (&cpool, LocalVariableTable_node);
|
||||
PUT2 (i); /* attribute_name_index */
|
||||
i = 2 + localvartable_size; PUT4 (i); /* attribute_length */
|
||||
i = localvartable_size / 10; PUT2 (i);
|
||||
PUTN (localvartable.data, localvartable_size);
|
||||
}
|
||||
}
|
||||
methods_count++;
|
||||
}
|
||||
ptr = methods_count_ptr; PUT2 (methods_count);
|
||||
|
||||
chunk = alloc_chunk (chunk, NULL, 2, work);
|
||||
ptr = chunk->data;
|
||||
PUT2 (0); /* attributes_count */
|
||||
|
||||
/* New finally generate the contents of the constant pool chunk. */
|
||||
i = count_constant_pool_bytes (&cpool);
|
||||
ptr = obstack_alloc (work, i);
|
||||
cpool_chunk->data = ptr;
|
||||
cpool_chunk->size = i;
|
||||
write_constant_pool (&cpool, ptr, i);
|
||||
CPOOL_FINISH (&cpool);
|
||||
return head.next;
|
||||
}
|
||||
|
||||
char*
|
||||
make_class_file_name (clas)
|
||||
tree clas;
|
||||
{
|
||||
/* Should prepend an output directly, but need an option to specify it. */
|
||||
return IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
|
||||
"", '.', '/', ".class"));
|
||||
}
|
||||
|
||||
/* Write out the contens of a class (RECORD_TYPE) CLAS, as a .class file.
|
||||
The output .class file name is make_class_file_name(CLAS). */
|
||||
|
||||
void
|
||||
write_classfile (clas)
|
||||
tree clas;
|
||||
{
|
||||
struct obstack *work = &temporary_obstack;
|
||||
char *class_file_name = make_class_file_name (clas);
|
||||
struct chunk *chunks;
|
||||
FILE* stream = fopen (class_file_name, "wb");
|
||||
if (stream == NULL)
|
||||
fatal ("failed to open `%s' for writing", class_file_name);
|
||||
chunks = generate_classfile (clas, work);
|
||||
write_chunks (stream, chunks);
|
||||
if (fclose (stream))
|
||||
fatal ("failed to close after writing `%s'", class_file_name);
|
||||
obstack_free (work, chunks);
|
||||
}
|
260
gcc/java/jcf.h
Normal file
260
gcc/java/jcf.h
Normal file
|
@ -0,0 +1,260 @@
|
|||
/* Utility macros to read Java(TM) .class files and byte codes.
|
||||
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
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, 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
|
||||
|
||||
#ifndef JCF_H
|
||||
#define JCF_H
|
||||
#include "javaop.h"
|
||||
#ifndef DEFUN
|
||||
#if defined (__STDC__)
|
||||
#define AND ,
|
||||
#define PTR void *
|
||||
#define DEFUN(name, arglist, args) name(args)
|
||||
#else
|
||||
#define PTR char *
|
||||
#define AND ;
|
||||
#define DEFUN(name, arglist, args) name arglist args;
|
||||
#define inline static
|
||||
#endif
|
||||
#endif /* !DEFUN */
|
||||
|
||||
#ifndef PROTO
|
||||
#if defined (__STDC__)
|
||||
#define PROTO(paramlist) paramlist
|
||||
#else
|
||||
#define PROTO(paramlist) ()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef JCF_u4
|
||||
#define JCF_u4 unsigned long
|
||||
#endif
|
||||
#ifndef JCF_u2
|
||||
#define JCF_u2 unsigned short
|
||||
#endif
|
||||
|
||||
#define ALLOC (void*)malloc
|
||||
#define REALLOC (void*)realloc
|
||||
#ifndef FREE
|
||||
#define FREE(PTR) free(PTR)
|
||||
#endif
|
||||
|
||||
#ifdef JCF_word
|
||||
#define JCF_word JCF_u4
|
||||
#endif
|
||||
|
||||
#define JCF_ZIP 1
|
||||
#define JCF_CLASS 2
|
||||
#define JCF_SOURCE 3
|
||||
|
||||
struct JCF;
|
||||
typedef int (*jcf_filbuf_t) PROTO ((struct JCF*, int needed));
|
||||
|
||||
typedef struct CPool {
|
||||
/* Available number of elements in the constants array, before it
|
||||
must be re-allocated. */
|
||||
int capacity;
|
||||
|
||||
/* The constant_pool_count. */
|
||||
int count;
|
||||
|
||||
uint8* tags;
|
||||
|
||||
jword* data;
|
||||
} CPool;
|
||||
|
||||
/* JCF encapsulates the state of reading a Java Class File. */
|
||||
|
||||
typedef struct JCF {
|
||||
unsigned char *buffer;
|
||||
unsigned char *buffer_end;
|
||||
unsigned char *read_ptr;
|
||||
unsigned char *read_end;
|
||||
int seen_in_zip;
|
||||
int java_source;
|
||||
int outofsynch; /* Found a class file out of synch
|
||||
with the matching source file. */
|
||||
long zip_offset;
|
||||
jcf_filbuf_t filbuf;
|
||||
void *read_state;
|
||||
char *filename;
|
||||
char *classname;
|
||||
void *zipd; /* Directory entry where it was found */
|
||||
JCF_u2 access_flags, this_class, super_class;
|
||||
CPool cpool;
|
||||
} JCF;
|
||||
/*typedef JCF* JCF_FILE;*/
|
||||
|
||||
/* The CPOOL macros take a (pointer to a) CPool.
|
||||
The JPOOL macros take a (pointer to a) JCF.
|
||||
Some of the latter should perhaps be deprecated or removed. */
|
||||
|
||||
#define CPOOL_COUNT(CPOOL) ((CPOOL)->count)
|
||||
#define JPOOL_SIZE(JCF) CPOOL_COUNT(&(JCF)->cpool)
|
||||
#define JPOOL_TAG(JCF, INDEX) ((JCF)->cpool.tags[INDEX])
|
||||
/* The INDEX'th constant pool entry as a JCF_u4. */
|
||||
#define CPOOL_UINT(CPOOL, INDEX) ((CPOOL)->data[INDEX])
|
||||
#define JPOOL_UINT(JCF, INDEX) CPOOL_UINT(&(JCF)->cpool, INDEX) /*deprecated*/
|
||||
/* The first uint16 of the INDEX'th constant pool entry. */
|
||||
#define CPOOL_USHORT1(CPOOL, INDEX) ((CPOOL)->data[INDEX] & 0xFFFF)
|
||||
#define JPOOL_USHORT1(JCF, INDEX) CPOOL_USHORT1(&(JCF)->cpool, INDEX)
|
||||
/* The second uint16 of the INDEX'th constant pool entry. */
|
||||
#define CPOOL_USHORT2(CPOOL, INDEX) ((CPOOL)->data[INDEX] >> 16)
|
||||
#define JPOOL_USHORT2(JCF, INDEX) CPOOL_USHORT2(&(JCF)->cpool, INDEX)
|
||||
#define JPOOL_LONG(JCF, INDEX) \
|
||||
WORDS_TO_LONG (JPOOL_UINT(JCF, INDEX), JPOOL_UINT(JCF, (INDEX)+1))
|
||||
#define JPOOL_DOUBLE(JCF, INDEX) \
|
||||
WORDS_TO_DOUBLE (JPOOL_UINT(JCF, INDEX), JPOOL_UINT(JCF, (INDEX)+1))
|
||||
#ifndef JPOOL_UTF_LENGTH
|
||||
#define JPOOL_UTF_LENGTH(JCF, INDEX) \
|
||||
GET_u2 ((JCF)->buffer+JPOOL_UINT(JCF, INDEX))
|
||||
#endif
|
||||
#ifndef JPOOL_UTF_DATA
|
||||
#define JPOOL_UTF_DATA(JCF, INDEX) \
|
||||
((JCF)->buffer+JPOOL_UINT(JCF, INDEX)+2)
|
||||
#endif
|
||||
#define JPOOL_INT(JCF, INDEX) ((jint) JPOOL_UINT (JCF, INDEX))
|
||||
#define JPOOL_FLOAT(JCF, INDEX) WORD_TO_FLOAT (JPOOL_UINT (JCF, INDEX))
|
||||
|
||||
#define CPOOL_INDEX_IN_RANGE(CPOOL, INDEX) \
|
||||
((INDEX) > 0 && (INDEX) < CPOOL_COUNT(CPOOL))
|
||||
|
||||
#define CPOOL_FINISH(CPOOL) { \
|
||||
if ((CPOOL)->tags) FREE ((CPOOL)->tags); \
|
||||
if ((CPOOL)->data) FREE ((CPOOL)->data); }
|
||||
|
||||
#define JCF_FINISH(JCF) { \
|
||||
CPOOL_FINISH(&(JCF)->cpool); \
|
||||
if ((JCF)->buffer) FREE ((JCF)->buffer); \
|
||||
if ((JCF)->filename) FREE ((JCF)->filename); \
|
||||
if ((JCF)->classname) FREE ((JCF)->classname); }
|
||||
|
||||
#define CPOOL_INIT(CPOOL) \
|
||||
((CPOOL)->capacity = 0, (CPOOL)->count = 0, (CPOOL)->tags = 0, (CPOOL)->data = 0)
|
||||
|
||||
#define CPOOL_REINIT(CPOOL) ((CPOOL)->count = 0)
|
||||
|
||||
#define JCF_ZERO(JCF) \
|
||||
((JCF)->buffer = (JCF)->buffer_end = (JCF)->read_ptr = (JCF)->read_end = 0,\
|
||||
(JCF)->read_state = 0, (JCF)->filename = (JCF)->classname = 0, \
|
||||
CPOOL_INIT(&(JCF)->cpool), (JCF)->java_source = 0)
|
||||
|
||||
/* Given that PTR points to a 2-byte unsigned integer in network
|
||||
(big-endian) byte-order, return that integer. */
|
||||
#define GET_u2(PTR) (((PTR)[0] << 8) | ((PTR)[1]))
|
||||
/* Like GET_u2, but for little-endian format. */
|
||||
#define GET_u2_le(PTR) (((PTR)[1] << 8) | ((PTR)[0]))
|
||||
|
||||
/* Given that PTR points to a 4-byte unsigned integer in network
|
||||
(big-endian) byte-order, return that integer. */
|
||||
#define GET_u4(PTR) (((JCF_u4)(PTR)[0] << 24) | ((JCF_u4)(PTR)[1] << 16) \
|
||||
| ((JCF_u4)(PTR)[2] << 8) | ((JCF_u4)(PTR)[3]))
|
||||
/* Like GET_u4, but for little-endian order. */
|
||||
#define GET_u4_le(PTR) (((JCF_u4)(PTR)[3] << 24) | ((JCF_u4)(PTR)[2] << 16) \
|
||||
| ((JCF_u4)(PTR)[1] << 8) | ((JCF_u4)(PTR)[0]))
|
||||
|
||||
/* Make sure there are COUNT bytes readable. */
|
||||
#define JCF_FILL(JCF, COUNT) \
|
||||
((JCF)->read_end-(JCF)->read_ptr >= (COUNT) ? 0 : (*(JCF)->filbuf)(JCF, COUNT))
|
||||
#define JCF_GETC(JCF) (JCF_FILL(JCF, 1) ? -1 : *(JCF)->read_ptr++)
|
||||
#define JCF_READ(JCF, BUFFER, N) \
|
||||
(memcpy (BUFFER, (JCF)->read_ptr, N), (JCF)->read_ptr += (N))
|
||||
#define JCF_SKIP(JCF,N) ((JCF)->read_ptr += (N))
|
||||
#define JCF_readu(JCF) (*(JCF)->read_ptr++)
|
||||
|
||||
/* Reads an unsigned 2-byte integer in network (big-endian) byte-order
|
||||
from JCF. Returns that integer.
|
||||
Does not check for EOF (make sure to call JCF_FILL before-hand). */
|
||||
#define JCF_readu2(JCF) ((JCF)->read_ptr += 2, GET_u2 ((JCF)->read_ptr-2))
|
||||
#define JCF_readu2_le(JCF) ((JCF)->read_ptr += 2, GET_u2_le((JCF)->read_ptr-2))
|
||||
|
||||
/* Like JCF_readu2, but read a 4-byte unsigned integer. */
|
||||
#define JCF_readu4(JCF) ((JCF)->read_ptr += 4, GET_u4 ((JCF)->read_ptr-4))
|
||||
#define JCF_readu4_le(JCF) ((JCF)->read_ptr += 4, GET_u4_le((JCF)->read_ptr-4))
|
||||
|
||||
#define JCF_TELL(JCF) ((JCF)->read_ptr - (JCF)->buffer)
|
||||
#define JCF_SEEK(JCF, POS) ((JCF)->read_ptr = (JCF)->buffer + (POS))
|
||||
|
||||
#define ACC_PUBLIC 0x0001
|
||||
#define ACC_PRIVATE 0x0002
|
||||
#define ACC_PROTECTED 0x0004
|
||||
#define ACC_STATIC 0x0008
|
||||
#define ACC_FINAL 0x0010
|
||||
#define ACC_SYNCHRONIZED 0x0020
|
||||
#define ACC_SUPER 0x0020
|
||||
#define ACC_VOLATILE 0x0040
|
||||
#define ACC_TRANSIENT 0x0080
|
||||
#define ACC_NATIVE 0x0100
|
||||
#define ACC_INTERFACE 0x0200
|
||||
#define ACC_ABSTRACT 0x0400
|
||||
|
||||
#define CONSTANT_Class 7
|
||||
#define CONSTANT_Fieldref 9
|
||||
#define CONSTANT_Methodref 10
|
||||
#define CONSTANT_InterfaceMethodref 11
|
||||
#define CONSTANT_String 8
|
||||
#define CONSTANT_Integer 3
|
||||
#define CONSTANT_Float 4
|
||||
#define CONSTANT_Long 5
|
||||
#define CONSTANT_Double 6
|
||||
#define CONSTANT_NameAndType 12
|
||||
#define CONSTANT_Utf8 1
|
||||
#define CONSTANT_Unicode 2
|
||||
|
||||
extern char *classpath;
|
||||
#define DEFAULT_CLASS_PATH "."
|
||||
|
||||
extern char *find_class PROTO ((const char *, int, JCF*, int));
|
||||
extern char *find_classfile PROTO ((char *, JCF*));
|
||||
extern int jcf_filbuf_from_stdio PROTO ((JCF *jcf, int count));
|
||||
extern void jcf_out_of_synch PROTO((JCF *));
|
||||
extern int jcf_unexpected_eof PROTO ((JCF*, int));
|
||||
|
||||
/* Extract a character from a Java-style Utf8 string.
|
||||
* PTR points to the current character.
|
||||
* LIMIT points to the end of the Utf8 string.
|
||||
* PTR is incremented to point after the character thta gets returns.
|
||||
* On an error, -1 is returned. */
|
||||
#define UTF8_GET(PTR, LIMIT) \
|
||||
((PTR) >= (LIMIT) ? -1 \
|
||||
: *(PTR) < 128 ? *(PTR)++ \
|
||||
: (*(PTR)&0xE0) == 0xC0 && ((PTR)+=2)<=(LIMIT) && ((PTR)[-1]&0xC0) == 0x80 \
|
||||
? (((PTR)[-2] & 0x1F) << 6) + ((PTR)[-1] & 0x3F) \
|
||||
: (*(PTR) & 0xF0) == 0xE0 && ((PTR) += 3) <= (LIMIT) \
|
||||
&& ((PTR)[-2] & 0xC0) == 0x80 && ((PTR)[-1] & 0xC0) == 0x80 \
|
||||
? (((PTR)[-3]&0x1F) << 12) + (((PTR)[-2]&0x3F) << 6) + ((PTR)[-1]&0x3F) \
|
||||
: ((PTR)++, -1))
|
||||
|
||||
/* Debug macros, for the front end */
|
||||
|
||||
extern int quiet_flag;
|
||||
#ifdef SOURCE_FRONTEND_DEBUG
|
||||
#undef SOURCE_FRONTEND_DEBUG
|
||||
#define SOURCE_FRONTEND_DEBUG(X) \
|
||||
{if (!quiet_flag) {printf ("* "); printf X; putchar ('\n');} }
|
||||
#else
|
||||
#define SOURCE_FRONTEND_DEBUG(X)
|
||||
#endif
|
||||
|
||||
#endif
|
235
gcc/java/jv-scan.c
Normal file
235
gcc/java/jv-scan.c
Normal file
|
@ -0,0 +1,235 @@
|
|||
/* Main for jv-scan
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "gansidecl.h" /* Definitions of PROTO and VPROTO */
|
||||
#include "obstack.h" /* We use obstacks in lex.c */
|
||||
|
||||
void fatal VPROTO((char *s, ...));
|
||||
void warning VPROTO((char *s, ...));
|
||||
void gcc_obstack_init PROTO ((struct obstack *obstack));
|
||||
extern void reset_report PROTO ((void));
|
||||
|
||||
#define JC1_LITE
|
||||
#include "parse.h"
|
||||
|
||||
/* Current input file and output file IO streams. */
|
||||
FILE *finput, *out;
|
||||
|
||||
/* Current input filename. */
|
||||
char *input_filename;
|
||||
|
||||
/* Executable name. */
|
||||
char *exec_name;
|
||||
|
||||
/* Flags matching command line options. */
|
||||
int flag_find_main = 0;
|
||||
int flag_dump_class = 0;
|
||||
int flag_list_filename = 0;
|
||||
|
||||
/* jc1-lite main entry point */
|
||||
int
|
||||
main (argc, argv, envp)
|
||||
int argc;
|
||||
char **argv;
|
||||
char **envp;
|
||||
{
|
||||
int i = 1;
|
||||
char *output_file = NULL;
|
||||
long ft;
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
/* Default for output */
|
||||
out = stdout;
|
||||
|
||||
/* Process options first */
|
||||
while (argv [i])
|
||||
{
|
||||
if (argv [i][0] == '-')
|
||||
{
|
||||
/* Dump result into a file */
|
||||
if (!strcmp (argv [i], "-o") && i+1 < argc)
|
||||
{
|
||||
argv [i] = NULL;
|
||||
output_file = argv [++i];
|
||||
argv [i] = NULL;
|
||||
}
|
||||
|
||||
/* Print the name of the class that contains main */
|
||||
else if (!strcmp (argv [i], "--print-main"))
|
||||
flag_find_main = 1;
|
||||
|
||||
else if (!strcmp (argv [i], "--list-filename"))
|
||||
flag_list_filename = 1;
|
||||
|
||||
/* List all the classes found in a source file */
|
||||
else if (!strcmp (argv [i], "--list-class"))
|
||||
flag_dump_class = 1;
|
||||
|
||||
else
|
||||
warning ("Unrecognized argument `%s'", argv[i]);
|
||||
|
||||
/* non recognized argument ignored silently */
|
||||
argv [i] = NULL; /* Nullify so it's not considered a file */
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
/* No flags? Do nothing */
|
||||
if (!flag_find_main && !flag_dump_class)
|
||||
exit (0);
|
||||
|
||||
/* Check on bad usage */
|
||||
if (flag_find_main && flag_dump_class)
|
||||
fatal ("Options `--print-main' and `--list-class' can't be turned on "
|
||||
"at the same time", argv [0]);
|
||||
|
||||
if (output_file && !(out = fopen (output_file, "w")))
|
||||
fatal ("Can't open output file `%s'", argv [0], output_file);
|
||||
|
||||
ft = ftell (out);
|
||||
|
||||
gcc_obstack_init (&temporary_obstack);
|
||||
java_push_parser_context ();
|
||||
|
||||
for ( i = 1; i < argc; i++ )
|
||||
if (argv [i])
|
||||
{
|
||||
input_filename = argv [i];
|
||||
if ( (finput = fopen (argv [i], "r")) )
|
||||
{
|
||||
java_init_lex ();
|
||||
yyparse ();
|
||||
if (ftell (out) != ft)
|
||||
fputc ('\n', out);
|
||||
ft = ftell (out);
|
||||
fclose (finput);
|
||||
reset_report ();
|
||||
}
|
||||
else
|
||||
fatal ("File not found `%s'", argv [0], argv [i]);
|
||||
}
|
||||
|
||||
/* Flush and close */
|
||||
if (ftell (out) != ft)
|
||||
fputc ('\n', out);
|
||||
if (!output_file)
|
||||
fclose (out);
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/* Error report, memory, obstack initialization and other utility
|
||||
functions */
|
||||
|
||||
void
|
||||
fatal VPROTO((char *s, ...))
|
||||
{
|
||||
#ifndef __STDC__
|
||||
char *s;
|
||||
#endif
|
||||
va_list ap;
|
||||
|
||||
VA_START (ap, s);
|
||||
|
||||
#ifndef __STDC__
|
||||
s = va_arg (ap, char *);
|
||||
#endif
|
||||
|
||||
fprintf (stderr, "%s: error: ", exec_name);
|
||||
vfprintf (stderr, s, ap);
|
||||
fputc ('\n', stderr);
|
||||
va_end (ap);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
char *
|
||||
xmalloc (size)
|
||||
unsigned size;
|
||||
{
|
||||
register char *value;
|
||||
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
|
||||
value = (char *) malloc (size);
|
||||
if (value == 0)
|
||||
fatal ("virtual memory exhausted");
|
||||
return value;
|
||||
}
|
||||
|
||||
char *
|
||||
xstrdup (string)
|
||||
char *string;
|
||||
{
|
||||
int length = strlen (string)+1;
|
||||
char *to_return = xmalloc (length);
|
||||
strcpy (to_return, string);
|
||||
return to_return;
|
||||
}
|
||||
|
||||
void
|
||||
warning VPROTO((char *s, ...))
|
||||
{
|
||||
#ifndef __STDC__
|
||||
char *s;
|
||||
#endif
|
||||
va_list ap;
|
||||
|
||||
VA_START (ap, s);
|
||||
|
||||
#ifndef __STDC__
|
||||
s = va_arg (ap, char *);
|
||||
#endif
|
||||
|
||||
fprintf (stderr, "%s: warning: ", exec_name);
|
||||
vfprintf (stderr, s, ap);
|
||||
fputc ('\n', stderr);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
void
|
||||
gcc_obstack_init (obstack)
|
||||
struct obstack *obstack;
|
||||
{
|
||||
/* Let particular systems override the size of a chunk. */
|
||||
#ifndef OBSTACK_CHUNK_SIZE
|
||||
#define OBSTACK_CHUNK_SIZE 0
|
||||
#endif
|
||||
/* Let them override the alloc and free routines too. */
|
||||
#ifndef OBSTACK_CHUNK_ALLOC
|
||||
#define OBSTACK_CHUNK_ALLOC xmalloc
|
||||
#endif
|
||||
#ifndef OBSTACK_CHUNK_FREE
|
||||
#define OBSTACK_CHUNK_FREE free
|
||||
#endif
|
||||
_obstack_begin (obstack, OBSTACK_CHUNK_SIZE, 0,
|
||||
(void *(*) ()) OBSTACK_CHUNK_ALLOC,
|
||||
(void (*) ()) OBSTACK_CHUNK_FREE);
|
||||
}
|
124
gcc/java/jvgenmain.c
Normal file
124
gcc/java/jvgenmain.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/* Program to generate "main" a Java(TM) class containing a main method.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* Written by Per Bothner <bothner@cygnus.com> */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include "obstack.h"
|
||||
|
||||
const char main_method_prefix[] = "main__";
|
||||
const char main_method_suffix[] = "Pt6JArray1ZPQ34java4lang6String";
|
||||
const char class_mangling_prefix[] = "_CL_";
|
||||
|
||||
struct obstack name_obstack;
|
||||
|
||||
void
|
||||
error (const char *str)
|
||||
{
|
||||
fprintf (stderr, "%s\n", str);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
void *
|
||||
xmalloc (size)
|
||||
size_t size;
|
||||
{
|
||||
void *ptr = malloc (size);
|
||||
if (ptr == NULL)
|
||||
{
|
||||
fprintf (stderr, "Not enough memory!\n");
|
||||
exit (-1);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void
|
||||
gcc_obstack_init (obstack)
|
||||
struct obstack *obstack;
|
||||
{
|
||||
/* Let particular systems override the size of a chunk. */
|
||||
#ifndef OBSTACK_CHUNK_SIZE
|
||||
#define OBSTACK_CHUNK_SIZE 0
|
||||
#endif
|
||||
/* Let them override the alloc and free routines too. */
|
||||
#ifndef OBSTACK_CHUNK_ALLOC
|
||||
#define OBSTACK_CHUNK_ALLOC xmalloc
|
||||
#endif
|
||||
#ifndef OBSTACK_CHUNK_FREE
|
||||
#define OBSTACK_CHUNK_FREE free
|
||||
#endif
|
||||
_obstack_begin (obstack, OBSTACK_CHUNK_SIZE, 0,
|
||||
(void *(*) ()) OBSTACK_CHUNK_ALLOC,
|
||||
(void (*) ()) OBSTACK_CHUNK_FREE);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, const char **argv)
|
||||
{
|
||||
const char *classname;
|
||||
FILE *stream;
|
||||
char *mangled_classname;
|
||||
|
||||
if (argc < 2 || argc > 3)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s CLASSNAME [OUTFILE]\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
classname = argv[1];
|
||||
|
||||
gcc_obstack_init (&name_obstack);
|
||||
append_gpp_mangled_classtype (&name_obstack, classname);
|
||||
mangled_classname = obstack_finish (&name_obstack);
|
||||
|
||||
if (argc > 2 && strcmp (argv[2], "-") != 0)
|
||||
{
|
||||
const char *outfile = argv[2];
|
||||
stream = fopen (outfile, "w");
|
||||
if (stream == NULL)
|
||||
{
|
||||
fprintf (stderr, "%s: Cannot open output file: %s\n",
|
||||
argv[0], outfile);
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
stream = stdout;
|
||||
fprintf (stream, "extern struct Class %s%s;\n",
|
||||
class_mangling_prefix, mangled_classname);
|
||||
fprintf (stream, "int main (int argc, const char **argv)\n");
|
||||
fprintf (stream, "{\n");
|
||||
fprintf (stream, " JvRunMain (&%s%s, argc, argv);\n",
|
||||
class_mangling_prefix, mangled_classname);
|
||||
fprintf (stream, "}\n");
|
||||
if (stream != stdout && fclose (stream) != 0)
|
||||
{
|
||||
fprintf (stderr, "%s: Failed to close output file %s\n",
|
||||
argv[0], argv[2]);
|
||||
exit (-1);
|
||||
}
|
||||
return 0;
|
||||
}
|
357
gcc/java/jvspec.c
Normal file
357
gcc/java/jvspec.c
Normal file
|
@ -0,0 +1,357 @@
|
|||
/* Specific flags and argument handling of the front-end of the
|
||||
GNU compiler for the Java(TM) language.
|
||||
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include "gansidecl.h"
|
||||
|
||||
#if defined (WITH_THREAD_posix) || defined (WITH_THREAD_pthreads)
|
||||
#define THREAD_NAME "-lpthread"
|
||||
#elif defined (WITH_THREAD_qt)
|
||||
#define THREAD_NAME "-lqthreads"
|
||||
#endif
|
||||
|
||||
/* This bit is set if we saw a `-xfoo' language specification. */
|
||||
#define LANGSPEC (1<<1)
|
||||
/* This bit is set if they did `-lm' or `-lmath'. */
|
||||
#define MATHLIB (1<<2)
|
||||
/* This bit is set if they did `-lc'. */
|
||||
#define WITHLIBC (1<<3)
|
||||
/* This bit is set if they did `-lgc'. */
|
||||
#define GCLIB (1<<4)
|
||||
/* This bit is set if they did `-lpthread' (or added some other thread
|
||||
library). */
|
||||
#define THREADLIB (1<<5)
|
||||
|
||||
#ifndef MATH_LIBRARY
|
||||
#define MATH_LIBRARY "-lm"
|
||||
#endif
|
||||
|
||||
extern char *xmalloc PROTO((size_t));
|
||||
extern int do_spec PROTO((char *));
|
||||
extern char *input_filename;
|
||||
extern size_t input_filename_length;
|
||||
|
||||
char *main_class_name = NULL;
|
||||
int lang_specific_extra_outfiles = 0;
|
||||
|
||||
char jvgenmain_spec[] =
|
||||
"jvgenmain %i %{!pipe:%g.i} |\n\
|
||||
cc1 %{!pipe:%g.i} %1 \
|
||||
%{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
|
||||
%{g*} %{O*} \
|
||||
%{v:-version} %{pg:-p} %{p} %{f*}\
|
||||
%{aux-info*}\
|
||||
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
|
||||
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
|
||||
%{!S:as %a %Y -o %w%b%O %{!pipe:%g.s} %A\n }";
|
||||
|
||||
void
|
||||
lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
|
||||
void (*fn)();
|
||||
int *in_argc;
|
||||
char ***in_argv;
|
||||
int *in_added_libraries;
|
||||
{
|
||||
int i, j;
|
||||
|
||||
/* If non-zero, the user gave us the `-v' flag. */
|
||||
int saw_verbose_flag = 0;
|
||||
|
||||
/* This will be 0 if we encounter a situation where we should not
|
||||
link in libjava. */
|
||||
int library = 1;
|
||||
|
||||
/* The number of arguments being added to what's in argv, other than
|
||||
libraries. We use this to track the number of times we've inserted
|
||||
-xc++/-xnone. */
|
||||
int added = 2;
|
||||
|
||||
/* Used to track options that take arguments, so we don't go wrapping
|
||||
those with -xc++/-xnone. */
|
||||
char *quote = NULL;
|
||||
|
||||
/* The new argument list will be contained in this. */
|
||||
char **arglist;
|
||||
|
||||
/* Non-zero if we saw a `-xfoo' language specification on the
|
||||
command line. Used to avoid adding our own -xc++ if the user
|
||||
already gave a language for the file. */
|
||||
int saw_speclang = 0;
|
||||
|
||||
/* "-lm" or "-lmath" if it appears on the command line. */
|
||||
char *saw_math = 0;
|
||||
|
||||
/* "-lc" if it appears on the command line. */
|
||||
char *saw_libc = 0;
|
||||
|
||||
/* "-lgc" if it appears on the command line. */
|
||||
char *saw_gc = 0;
|
||||
|
||||
/* Saw `-l' option for the thread library. */
|
||||
char *saw_threadlib = 0;
|
||||
|
||||
/* Saw `-ljava' on command line. */
|
||||
int saw_libjava = 0;
|
||||
|
||||
/* An array used to flag each argument that needs a bit set for
|
||||
LANGSPEC, MATHLIB, WITHLIBC, or GCLIB. */
|
||||
int *args;
|
||||
|
||||
/* By default, we throw on the math library. */
|
||||
int need_math = 1;
|
||||
|
||||
/* By default, we throw in the thread library (if one is required).
|
||||
*/
|
||||
int need_thread = 1;
|
||||
|
||||
/* The total number of arguments with the new stuff. */
|
||||
int argc;
|
||||
|
||||
/* The argument list. */
|
||||
char **argv;
|
||||
|
||||
/* The number of libraries added in. */
|
||||
int added_libraries;
|
||||
|
||||
/* The total number of arguments with the new stuff. */
|
||||
int num_args = 1;
|
||||
|
||||
argc = *in_argc;
|
||||
argv = *in_argv;
|
||||
added_libraries = *in_added_libraries;
|
||||
|
||||
args = (int *) xmalloc (argc * sizeof (int));
|
||||
bzero ((char *) args, argc * sizeof (int));
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
/* If the previous option took an argument, we swallow it here. */
|
||||
if (quote)
|
||||
{
|
||||
quote = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We don't do this anymore, since we don't get them with minus
|
||||
signs on them. */
|
||||
if (argv[i][0] == '\0' || argv[i][1] == '\0')
|
||||
continue;
|
||||
|
||||
if (argv[i][0] == '-')
|
||||
{
|
||||
if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0
|
||||
|| strcmp (argv[i], "-nodefaultlibs") == 0))
|
||||
{
|
||||
library = 0;
|
||||
}
|
||||
else if (strcmp (argv[i], "-lm") == 0
|
||||
|| strcmp (argv[i], "-lmath") == 0
|
||||
#ifdef ALT_LIBM
|
||||
|| strcmp (argv[i], ALT_LIBM) == 0
|
||||
#endif
|
||||
)
|
||||
{
|
||||
args[i] |= MATHLIB;
|
||||
need_math = 0;
|
||||
}
|
||||
else if (strncmp (argv[i], "-fmain=", 7) == 0)
|
||||
main_class_name = argv[i] + 7;
|
||||
else if (strcmp (argv[i], "-ljava") == 0)
|
||||
saw_libjava = 1;
|
||||
else if (strcmp (argv[i], "-lc") == 0)
|
||||
args[i] |= WITHLIBC;
|
||||
else if (strcmp (argv[i], "-lgc") == 0)
|
||||
args[i] |= GCLIB;
|
||||
#ifdef THREAD_NAME
|
||||
else if (strcmp (argv[i], THREAD_NAME) == 0)
|
||||
{
|
||||
args[i] |= THREADLIB;
|
||||
need_thread = 0;
|
||||
}
|
||||
#endif
|
||||
else if (strcmp (argv[i], "-v") == 0)
|
||||
{
|
||||
saw_verbose_flag = 1;
|
||||
if (argc == 2)
|
||||
{
|
||||
/* If they only gave us `-v', don't try to link
|
||||
in libjava. */
|
||||
library = 0;
|
||||
}
|
||||
}
|
||||
else if (strncmp (argv[i], "-x", 2) == 0)
|
||||
saw_speclang = 1;
|
||||
else if (((argv[i][2] == '\0'
|
||||
&& (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
|
||||
|| strcmp (argv[i], "-Tdata") == 0))
|
||||
quote = argv[i];
|
||||
else if (library != 0 && ((argv[i][2] == '\0'
|
||||
&& (char *) strchr ("cSEM", argv[i][1]) != NULL)
|
||||
|| strcmp (argv[i], "-MM") == 0))
|
||||
{
|
||||
/* Don't specify libraries if we won't link, since that would
|
||||
cause a warning. */
|
||||
library = 0;
|
||||
added -= 2;
|
||||
}
|
||||
else
|
||||
/* Pass other options through. */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
int len;
|
||||
|
||||
if (saw_speclang)
|
||||
{
|
||||
saw_speclang = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the filename ends in .c or .i, put options around it.
|
||||
But not if a specified -x option is currently active. */
|
||||
len = strlen (argv[i]);
|
||||
if (len > 2
|
||||
&& (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i')
|
||||
&& argv[i][len - 2] == '.')
|
||||
{
|
||||
args[i] |= LANGSPEC;
|
||||
added += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (quote)
|
||||
(*fn) ("argument to `%s' missing\n", quote);
|
||||
|
||||
/* If we know we don't have to do anything, bail now. */
|
||||
if (! added && ! library && main_class_name == NULL)
|
||||
{
|
||||
free (args);
|
||||
return;
|
||||
}
|
||||
|
||||
num_args = argc + added + need_math + need_thread;
|
||||
if (main_class_name)
|
||||
{
|
||||
lang_specific_extra_outfiles++;
|
||||
}
|
||||
arglist = (char **) xmalloc (num_args * sizeof (char *));
|
||||
|
||||
/* NOTE: We start at 1 now, not 0. */
|
||||
for (i = 0, j = 0; i < argc; i++, j++)
|
||||
{
|
||||
arglist[j] = argv[i];
|
||||
|
||||
if (strncmp (argv[i], "-fmain=", 7) == 0)
|
||||
{
|
||||
--j;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Make sure -ljava is before the math library, since libjava
|
||||
itself uses those math routines. */
|
||||
if (!saw_math && (args[i] & MATHLIB) && library)
|
||||
{
|
||||
--j;
|
||||
saw_math = argv[i];
|
||||
}
|
||||
|
||||
/* Likewise -ljava must come before -lc. */
|
||||
if (!saw_libc && (args[i] & WITHLIBC) && library)
|
||||
{
|
||||
--j;
|
||||
saw_libc = argv[i];
|
||||
}
|
||||
|
||||
/* And -ljava must come before -lgc. */
|
||||
if (!saw_gc && (args[i] & GCLIB) && library)
|
||||
{
|
||||
--j;
|
||||
saw_gc = argv[i];
|
||||
}
|
||||
|
||||
/* And -ljava must come before thread library. */
|
||||
if (!saw_threadlib && (args[i] & THREADLIB) && library)
|
||||
{
|
||||
--j;
|
||||
saw_threadlib = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Add `-ljava' if we haven't already done so. */
|
||||
if (library && ! saw_libjava)
|
||||
{
|
||||
arglist[j++] = "-ljava";
|
||||
added_libraries++;
|
||||
}
|
||||
|
||||
if (saw_math)
|
||||
arglist[j++] = saw_math;
|
||||
else if (library)
|
||||
{
|
||||
arglist[j++] = MATH_LIBRARY;
|
||||
added_libraries++;
|
||||
}
|
||||
|
||||
/* FIXME: we need a way to know when the GC library should be
|
||||
added. Then we can add it if the user hasn't already. */
|
||||
if (saw_gc)
|
||||
arglist[j++] = saw_gc;
|
||||
|
||||
/* Thread library must come after GC library as well as after
|
||||
-ljava. */
|
||||
if (saw_threadlib)
|
||||
arglist[j++] = saw_threadlib;
|
||||
#ifdef THREAD_NAME
|
||||
else if (library)
|
||||
{
|
||||
arglist[j++] = THREAD_NAME;
|
||||
added_libraries++;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (saw_libc)
|
||||
arglist[j++] = saw_libc;
|
||||
|
||||
arglist[j] = NULL;
|
||||
|
||||
*in_argc = j;
|
||||
*in_argv = arglist;
|
||||
*in_added_libraries = added_libraries;
|
||||
}
|
||||
|
||||
int
|
||||
lang_specific_pre_link ()
|
||||
{
|
||||
if (main_class_name == NULL)
|
||||
return 0;
|
||||
input_filename = main_class_name;
|
||||
input_filename_length = strlen (main_class_name);
|
||||
return do_spec (jvgenmain_spec);
|
||||
}
|
80
gcc/java/keyword.gperf
Normal file
80
gcc/java/keyword.gperf
Normal file
|
@ -0,0 +1,80 @@
|
|||
%{
|
||||
/* Keyword definition for the GNU compiler for the Java(TM) language.
|
||||
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
%}
|
||||
struct java_keyword { char *name; int token; };
|
||||
%%
|
||||
abstract, ABSTRACT_TK
|
||||
default, DEFAULT_TK
|
||||
if, IF_TK
|
||||
private, PRIVATE_TK
|
||||
throw, THROW_TK
|
||||
boolean, BOOLEAN_TK
|
||||
do, DO_TK
|
||||
implements, IMPLEMENTS_TK
|
||||
protected, PROTECTED_TK
|
||||
throws, THROWS_TK
|
||||
break, BREAK_TK
|
||||
double, DOUBLE_TK
|
||||
import, IMPORT_TK
|
||||
public, PUBLIC_TK
|
||||
transient, TRANSIENT_TK
|
||||
byte, BYTE_TK
|
||||
else, ELSE_TK
|
||||
instanceof, INSTANCEOF_TK
|
||||
return, RETURN_TK
|
||||
try, TRY_TK
|
||||
case, CASE_TK
|
||||
extends, EXTENDS_TK
|
||||
int, INT_TK
|
||||
short, SHORT_TK
|
||||
void, VOID_TK
|
||||
catch, CATCH_TK
|
||||
final, FINAL_TK
|
||||
interface, INTERFACE_TK
|
||||
static, STATIC_TK
|
||||
volatile, VOLATILE_TK
|
||||
char, CHAR_TK
|
||||
finally, FINALLY_TK
|
||||
long, LONG_TK
|
||||
super, SUPER_TK
|
||||
while, WHILE_TK
|
||||
class, CLASS_TK
|
||||
float, FLOAT_TK
|
||||
native, NATIVE_TK
|
||||
switch, SWITCH_TK
|
||||
const, CONST_TK
|
||||
for, FOR_TK
|
||||
new, NEW_TK
|
||||
synchronized, SYNCHRONIZED_TK
|
||||
continue, CONTINUE_TK
|
||||
goto, GOTO_TK
|
||||
package, PACKAGE_TK
|
||||
this, THIS_TK
|
||||
# true, false and null aren't keyword. But we match them easily this way
|
||||
true, TRUE_TK
|
||||
false, FALSE_TK
|
||||
null, NULL_TK
|
165
gcc/java/keyword.h
Normal file
165
gcc/java/keyword.h
Normal file
|
@ -0,0 +1,165 @@
|
|||
/* C code produced by gperf version 2.5 (GNU C++ version) */
|
||||
/* Command-line: gperf -p -t -j1 -i 1 -g -o -N java_keyword -k1,3,$ keyword.gperf */
|
||||
/* Keyword definitions for the GNU compiler for the Java(TM) language.
|
||||
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
struct java_keyword { char *name; int token; };
|
||||
|
||||
#define TOTAL_KEYWORDS 50
|
||||
#define MIN_WORD_LENGTH 2
|
||||
#define MAX_WORD_LENGTH 12
|
||||
#define MIN_HASH_VALUE 6
|
||||
#define MAX_HASH_VALUE 86
|
||||
/* maximum key range = 81, duplicates = 0 */
|
||||
|
||||
#ifdef __GNUC__
|
||||
inline
|
||||
#endif
|
||||
static unsigned int
|
||||
hash (str, len)
|
||||
register char *str;
|
||||
register int unsigned len;
|
||||
{
|
||||
static unsigned char asso_values[] =
|
||||
{
|
||||
87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
|
||||
87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
|
||||
87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
|
||||
87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
|
||||
87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
|
||||
87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
|
||||
87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
|
||||
87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
|
||||
87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
|
||||
87, 87, 87, 87, 87, 87, 87, 18, 37, 38,
|
||||
27, 1, 30, 3, 12, 8, 87, 2, 11, 87,
|
||||
8, 1, 5, 87, 24, 1, 1, 30, 2, 36,
|
||||
87, 1, 87, 87, 87, 87, 87, 87,
|
||||
};
|
||||
register int hval = len;
|
||||
|
||||
switch (hval)
|
||||
{
|
||||
default:
|
||||
case 3:
|
||||
hval += asso_values[str[2]];
|
||||
case 2:
|
||||
case 1:
|
||||
hval += asso_values[str[0]];
|
||||
break;
|
||||
}
|
||||
return hval + asso_values[str[len - 1]];
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
inline
|
||||
#endif
|
||||
struct java_keyword *
|
||||
java_keyword (str, len)
|
||||
register char *str;
|
||||
register unsigned int len;
|
||||
{
|
||||
static struct java_keyword wordlist[] =
|
||||
{
|
||||
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
|
||||
{"try", TRY_TK},
|
||||
{"else", ELSE_TK},
|
||||
{"short", SHORT_TK},
|
||||
{"goto", GOTO_TK},
|
||||
{"extends", EXTENDS_TK},
|
||||
{"",}, {"",},
|
||||
{"int", INT_TK},
|
||||
{"this", THIS_TK},
|
||||
{"",},
|
||||
{"native", NATIVE_TK},
|
||||
{"",}, {"",},
|
||||
{"interface", INTERFACE_TK},
|
||||
{"import", IMPORT_TK},
|
||||
{"private", PRIVATE_TK},
|
||||
{"volatile", VOLATILE_TK},
|
||||
{"",},
|
||||
{"implements", IMPLEMENTS_TK},
|
||||
{"",},
|
||||
{"long", LONG_TK},
|
||||
{"switch", SWITCH_TK},
|
||||
{"abstract", ABSTRACT_TK},
|
||||
{"transient", TRANSIENT_TK},
|
||||
{"do", DO_TK},
|
||||
{"",},
|
||||
{"throws", THROWS_TK},
|
||||
{"",},
|
||||
{"null", NULL_TK},
|
||||
{"super", SUPER_TK},
|
||||
{"true", TRUE_TK},
|
||||
{"float", FLOAT_TK},
|
||||
{"",},
|
||||
{"return", RETURN_TK},
|
||||
{"if", IF_TK},
|
||||
{"void", VOID_TK},
|
||||
{"protected", PROTECTED_TK},
|
||||
{"byte", BYTE_TK},
|
||||
{"case", CASE_TK},
|
||||
{"break", BREAK_TK},
|
||||
{"finally", FINALLY_TK},
|
||||
{"false", FALSE_TK},
|
||||
{"synchronized", SYNCHRONIZED_TK},
|
||||
{"instanceof", INSTANCEOF_TK},
|
||||
{"while", WHILE_TK},
|
||||
{"package", PACKAGE_TK},
|
||||
{"const", CONST_TK},
|
||||
{"boolean", BOOLEAN_TK},
|
||||
{"final", FINAL_TK},
|
||||
{"continue", CONTINUE_TK},
|
||||
{"catch", CATCH_TK},
|
||||
{"",}, {"",}, {"",}, {"",}, {"",},
|
||||
{"class", CLASS_TK},
|
||||
{"static", STATIC_TK},
|
||||
{"double", DOUBLE_TK},
|
||||
{"default", DEFAULT_TK},
|
||||
{"throw", THROW_TK},
|
||||
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
|
||||
{"",}, {"",}, {"",}, {"",}, {"",},
|
||||
{"for", FOR_TK},
|
||||
{"",},
|
||||
{"new", NEW_TK},
|
||||
{"char", CHAR_TK},
|
||||
{"",},
|
||||
{"public", PUBLIC_TK},
|
||||
};
|
||||
|
||||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
||||
{
|
||||
register int key = hash (str, len);
|
||||
|
||||
if (key <= MAX_HASH_VALUE && key >= 0)
|
||||
{
|
||||
register char *s = wordlist[key].name;
|
||||
|
||||
if (*s == *str && !strcmp (str + 1, s + 1))
|
||||
return &wordlist[key];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
35
gcc/java/lang-options.h
Normal file
35
gcc/java/lang-options.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* Switch definitions for the GNU compiler for the Java(TM) language.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* This is the contribution to the `lang_options' array in gcc.c for
|
||||
java. */
|
||||
|
||||
DEFINE_LANG_NAME ("Java")
|
||||
|
||||
{ "-fbounds-check", "" },
|
||||
{ "-fno-bounds-check", "Disable automatic array bounds checking" },
|
||||
{ "-fassume-compiled", "Make is_compiled_class return 1"},
|
||||
{ "-fno-assume-compiled", "" },
|
||||
{ "-femit-class-file", "" },
|
||||
{ "-femit-class-files", "Dump class files to <name>.class" },
|
38
gcc/java/lang-specs.h
Normal file
38
gcc/java/lang-specs.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* Definitions for specs for the GNU compiler for the Java(TM) language.
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* This is the contribution to the `default_compilers' array in gcc.c for
|
||||
Java. */
|
||||
|
||||
{".java", "@java" },
|
||||
{".class", "@java" },
|
||||
{"@java",
|
||||
"%{!M:%{!MM:%{!E:jc1 %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\
|
||||
%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
|
||||
%{traditional} %{v:-version} %{pg:-p} %{p}\
|
||||
%{f*} %{+e*} %{aux-info*}\
|
||||
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
|
||||
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
|
||||
%{!S:as %a %Y\
|
||||
%{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
|
||||
%{!pipe:%g.s} %A\n }}}}"},
|
406
gcc/java/lang.c
Normal file
406
gcc/java/lang.c
Normal file
|
@ -0,0 +1,406 @@
|
|||
/* Java(TM) language-specific utility routines.
|
||||
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* Hacked by Per Bothner <bothner@cygnus.com> February 1996. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#include "tree.h"
|
||||
#include "input.h"
|
||||
#include "java-tree.h"
|
||||
#include "jcf.h"
|
||||
|
||||
int compiling_from_source;
|
||||
|
||||
char *language_string = "GNU Java";
|
||||
|
||||
/* Nonzero if we want to automatically do array bounds checking;
|
||||
on by default. Use -fno-bounds-check to disable. */
|
||||
|
||||
int flag_bounds_check = 1;
|
||||
|
||||
/* Nonzero if we should make is_compiled_class always return 1 for
|
||||
appropriate classes that we're referencing. */
|
||||
|
||||
int flag_assume_compiled = 1;
|
||||
|
||||
int flag_emit_class_files = 0;
|
||||
|
||||
/* From gcc/flags.h, and idicates if exceptions are turned on or not. */
|
||||
|
||||
extern int flag_new_exceptions;
|
||||
extern int flag_exceptions;
|
||||
|
||||
/* Table of language-dependent -f options.
|
||||
STRING is the option name. VARIABLE is the address of the variable.
|
||||
ON_VALUE is the value to store in VARIABLE
|
||||
if `-fSTRING' is seen as an option.
|
||||
(If `-fno-STRING' is seen as an option, the opposite value is stored.) */
|
||||
|
||||
static struct { char *string; int *variable; int on_value;} lang_f_options[] =
|
||||
{
|
||||
{"bounds-check", &flag_bounds_check, 1},
|
||||
{"assume-compiled", &flag_assume_compiled, 1},
|
||||
{"emit-class-file", &flag_emit_class_files, 1},
|
||||
{"emit-class-files", &flag_emit_class_files, 1},
|
||||
};
|
||||
|
||||
JCF main_jcf[1];
|
||||
JCF *current_jcf;
|
||||
|
||||
/*
|
||||
* process java-specific compiler command-line options
|
||||
*/
|
||||
int
|
||||
lang_decode_option (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *p = argv[0];
|
||||
if (p[0] == '-' && p[1] == 'f')
|
||||
{
|
||||
/* Some kind of -f option.
|
||||
P's value is the option sans `-f'.
|
||||
Search for it in the table of options. */
|
||||
int found = 0, j;
|
||||
|
||||
p += 2;
|
||||
|
||||
for (j = 0;
|
||||
!found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]);
|
||||
j++)
|
||||
{
|
||||
if (!strcmp (p, lang_f_options[j].string))
|
||||
{
|
||||
*lang_f_options[j].variable = lang_f_options[j].on_value;
|
||||
/* A goto here would be cleaner,
|
||||
but breaks the vax pcc. */
|
||||
found = 1;
|
||||
}
|
||||
if (p[0] == 'n' && p[1] == 'o' && p[2] == '-'
|
||||
&& ! strcmp (p+3, lang_f_options[j].string))
|
||||
{
|
||||
*lang_f_options[j].variable = ! lang_f_options[j].on_value;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE *finput;
|
||||
char *
|
||||
init_parse (filename)
|
||||
char *filename;
|
||||
{
|
||||
/* Open input file. */
|
||||
|
||||
if (filename == 0 || !strcmp (filename, "-"))
|
||||
{
|
||||
finput = stdin;
|
||||
filename = "stdin";
|
||||
}
|
||||
else
|
||||
finput = fopen (filename, "r");
|
||||
if (finput == 0)
|
||||
pfatal_with_name (filename);
|
||||
|
||||
#ifdef IO_BUFFER_SIZE
|
||||
setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
|
||||
#endif
|
||||
init_lex ();
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
void
|
||||
finish_parse ()
|
||||
{
|
||||
fclose (finput);
|
||||
}
|
||||
|
||||
/* Buffer used by lang_printable_name. */
|
||||
static char *decl_buf = NULL;
|
||||
|
||||
/* Allocated size of decl_buf. */
|
||||
static int decl_buflen = 0;
|
||||
|
||||
/* Length of used part of decl_buf; position for next character. */
|
||||
static int decl_bufpos = 0;
|
||||
|
||||
/* Append the string STR to decl_buf.
|
||||
It length is given by LEN; -1 means the string is nul-terminated. */
|
||||
|
||||
static void
|
||||
put_decl_string (str, len)
|
||||
char *str;
|
||||
int len;
|
||||
{
|
||||
if (len < 0)
|
||||
len = strlen (str);
|
||||
if (decl_bufpos + len >= decl_buflen)
|
||||
{
|
||||
if (decl_buf == NULL)
|
||||
{
|
||||
decl_buflen = len + 100;
|
||||
decl_buf = (char *) xmalloc (decl_buflen);
|
||||
}
|
||||
else
|
||||
{
|
||||
decl_buflen *= 2;
|
||||
decl_buf = (char *) xrealloc (decl_buf, decl_buflen);
|
||||
}
|
||||
}
|
||||
strcpy (decl_buf + decl_bufpos, str);
|
||||
decl_bufpos += len;
|
||||
}
|
||||
|
||||
/* Append to decl_buf a printable name for NODE. */
|
||||
|
||||
static void
|
||||
put_decl_node (node)
|
||||
tree node;
|
||||
{
|
||||
int was_pointer = 0;
|
||||
if (TREE_CODE (node) == POINTER_TYPE)
|
||||
{
|
||||
node = TREE_TYPE (node);
|
||||
was_pointer = 1;
|
||||
}
|
||||
if (TREE_CODE_CLASS (TREE_CODE (node)) == 'd'
|
||||
&& DECL_NAME (node) != NULL_TREE)
|
||||
{
|
||||
#if 0
|
||||
if (DECL_CONTEXT (node) != NULL_TREE)
|
||||
{
|
||||
put_decl_node (DECL_CONTEXT (node));
|
||||
put_decl_string (".", 1);
|
||||
}
|
||||
#endif
|
||||
put_decl_node (DECL_NAME (node));
|
||||
if (TREE_CODE (node) == FUNCTION_DECL && TREE_TYPE (node) != NULL_TREE)
|
||||
{
|
||||
int i = 0;
|
||||
tree args = TYPE_ARG_TYPES (TREE_TYPE (node));
|
||||
if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE)
|
||||
args = TREE_CHAIN (args);
|
||||
put_decl_string ("(", 1);
|
||||
for ( ; args != NULL_TREE; args = TREE_CHAIN (args), i++)
|
||||
{
|
||||
if (i > 0)
|
||||
put_decl_string (",", 1);
|
||||
put_decl_node (TREE_VALUE (args));
|
||||
}
|
||||
put_decl_string (")", 1);
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE_CLASS (TREE_CODE (node)) == 't'
|
||||
&& TYPE_NAME (node) != NULL_TREE)
|
||||
{
|
||||
if (TREE_CODE (node) == RECORD_TYPE && TYPE_ARRAY_P (node))
|
||||
{
|
||||
put_decl_node (TYPE_ARRAY_ELEMENT (node));
|
||||
put_decl_string("[]", 2);
|
||||
}
|
||||
else if (node == promoted_byte_type_node)
|
||||
put_decl_string ("byte", 4);
|
||||
else if (node == promoted_short_type_node)
|
||||
put_decl_string ("short", 5);
|
||||
else if (node == promoted_char_type_node)
|
||||
put_decl_string ("char", 4);
|
||||
else if (node == promoted_boolean_type_node)
|
||||
put_decl_string ("boolean", 7);
|
||||
else if (node == void_type_node && was_pointer)
|
||||
put_decl_string ("null", 4);
|
||||
else
|
||||
put_decl_node (TYPE_NAME (node));
|
||||
}
|
||||
else if (TREE_CODE (node) == IDENTIFIER_NODE)
|
||||
put_decl_string (IDENTIFIER_POINTER (node), IDENTIFIER_LENGTH (node));
|
||||
else
|
||||
put_decl_string ("<unknown>", -1);
|
||||
}
|
||||
|
||||
/* Return a user-friendly name for DECL.
|
||||
The resulting string is only valid until the next call.
|
||||
The value of the hook decl_printable_name is this function,
|
||||
which is also called directly by lang_print_error. */
|
||||
|
||||
char *
|
||||
lang_printable_name (decl, v)
|
||||
tree decl;
|
||||
int v;
|
||||
{
|
||||
decl_bufpos = 0;
|
||||
put_decl_node (decl);
|
||||
put_decl_string ("", 1);
|
||||
return decl_buf;
|
||||
}
|
||||
|
||||
/* Print on stderr the current class and method context. This function
|
||||
is the value of the hook print_error_function, called from toplev.c. */
|
||||
|
||||
void
|
||||
lang_print_error (file)
|
||||
char *file;
|
||||
{
|
||||
static tree last_error_function_context = NULL_TREE;
|
||||
static tree last_error_function = NULL;
|
||||
|
||||
if (current_function_decl != NULL
|
||||
&& DECL_CONTEXT (current_function_decl) != last_error_function_context)
|
||||
{
|
||||
if (file)
|
||||
fprintf (stderr, "%s: ", file);
|
||||
|
||||
last_error_function_context = DECL_CONTEXT (current_function_decl);
|
||||
fprintf (stderr, "In class `%s':\n",
|
||||
lang_printable_name (last_error_function_context));
|
||||
}
|
||||
if (last_error_function != current_function_decl)
|
||||
{
|
||||
if (file)
|
||||
fprintf (stderr, "%s: ", file);
|
||||
|
||||
if (current_function_decl == NULL)
|
||||
fprintf (stderr, "At top level:\n");
|
||||
else
|
||||
{
|
||||
char *name = lang_printable_name (current_function_decl, 2);
|
||||
fprintf (stderr, "In method `%s':\n", name);
|
||||
}
|
||||
|
||||
last_error_function = current_function_decl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
lang_init ()
|
||||
{
|
||||
extern struct rtx_def * java_lang_expand_expr ();
|
||||
extern struct rtx_def * (*lang_expand_expr) ();
|
||||
extern void (*print_error_function) PROTO((char *));
|
||||
#if 0
|
||||
extern int flag_minimal_debug;
|
||||
flag_minimal_debug = 0;
|
||||
#endif
|
||||
|
||||
decl_printable_name = lang_printable_name;
|
||||
print_error_function = lang_print_error;
|
||||
lang_expand_expr = java_lang_expand_expr;
|
||||
|
||||
JCF_ZERO (main_jcf);
|
||||
main_jcf->read_state = finput;
|
||||
main_jcf->filbuf = jcf_filbuf_from_stdio;
|
||||
current_jcf = main_jcf;
|
||||
|
||||
flag_exceptions = 1;
|
||||
}
|
||||
|
||||
/* This doesn't do anything on purpose. It's used to satisfy the
|
||||
print_error_function hook we don't print error messages with bogus
|
||||
function prototypes. */
|
||||
|
||||
void java_dummy_print (s)
|
||||
char *s;
|
||||
{
|
||||
}
|
||||
|
||||
/* Called to install the PRINT_ERROR_FUNCTION hook differently
|
||||
according to LEVEL. LEVEL is 1 during early parsing, when function
|
||||
prototypes aren't fully resolved. print_error_function is set so it
|
||||
doesn't print incomplete function prototypes. When LEVEL is 2,
|
||||
function prototypes are fully resolved and can be printed when
|
||||
reporting errors. */
|
||||
|
||||
void lang_init_source (level)
|
||||
int level;
|
||||
{
|
||||
extern void (*print_error_function) PROTO((char *));
|
||||
if (level == 1)
|
||||
print_error_function = java_dummy_print;
|
||||
else
|
||||
print_error_function = lang_print_error;
|
||||
}
|
||||
|
||||
void
|
||||
lang_init_options ()
|
||||
{
|
||||
flag_new_exceptions = 1;
|
||||
}
|
||||
|
||||
void
|
||||
lang_finish ()
|
||||
{
|
||||
}
|
||||
|
||||
char*
|
||||
lang_identify ()
|
||||
{
|
||||
return "Java";
|
||||
}
|
||||
|
||||
/* Hooks for print_node. */
|
||||
|
||||
void
|
||||
print_lang_decl (file, node, indent)
|
||||
FILE *file;
|
||||
tree node;
|
||||
int indent;
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
print_lang_type (file, node, indent)
|
||||
FILE *file;
|
||||
tree node;
|
||||
int indent;
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
print_lang_identifier (file, node, indent)
|
||||
FILE *file;
|
||||
tree node;
|
||||
int indent;
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
print_lang_statistics ()
|
||||
{
|
||||
}
|
||||
|
||||
/* used by print-tree.c */
|
||||
|
||||
void
|
||||
lang_print_xnode (file, node, indent)
|
||||
FILE *file;
|
||||
tree node;
|
||||
int indent;
|
||||
{
|
||||
}
|
1355
gcc/java/lex.c
Normal file
1355
gcc/java/lex.c
Normal file
File diff suppressed because it is too large
Load diff
512
gcc/java/lex.h
Normal file
512
gcc/java/lex.h
Normal file
|
@ -0,0 +1,512 @@
|
|||
/* Language lexer definitions for the GNU compiler for the Java(TM) language.
|
||||
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
#ifndef JV_LEX_H
|
||||
#define JV_LEX_H
|
||||
|
||||
/* Extern global variables declarations */
|
||||
extern FILE *finput;
|
||||
extern int lineno;
|
||||
extern char *classpath;
|
||||
|
||||
/* A Unicode character, as read from the input file */
|
||||
typedef unsigned short unicode_t;
|
||||
|
||||
/* Function declaration */
|
||||
static int java_lineterminator ();
|
||||
static char *java_sprint_unicode ();
|
||||
static void java_unicode_2_utf8 ();
|
||||
static void java_lex_error ();
|
||||
static void java_store_unicode ();
|
||||
|
||||
/* Debug macro to print-out what we match */
|
||||
#ifdef JAVA_LEX_DEBUG
|
||||
#ifdef JAVA_LEX_DEBUG_CHAR
|
||||
#define JAVA_LEX_CHAR(c) printf ("java_lex:%d: char '%c'.%d\n", \
|
||||
lineno, (c < 128 ? c : '.'), c);
|
||||
#else
|
||||
#define JAVA_LEX_CHAR(c)
|
||||
#endif
|
||||
#define JAVA_LEX_KW(c) printf ("java_lex:%d: keyword: '%s'\n", lineno,c)
|
||||
#define JAVA_LEX_ID(s) printf ("java_lex:%d: ID: '%s'\n", \
|
||||
lineno, \
|
||||
(all_ascii ? s : "<U>"))
|
||||
#define JAVA_LEX_LIT(s, r) printf ("java_lex:%d: literal '%s'_%d\n", \
|
||||
lineno, s, r)
|
||||
#define JAVA_LEX_CHAR_LIT(s) printf ("java_lex:%d: literal '%d'\n", lineno, s)
|
||||
#define JAVA_LEX_STR_LIT(s) { \
|
||||
int i; \
|
||||
printf ("java_lex:%d: literal '%s'\n", \
|
||||
lineno, s); \
|
||||
}
|
||||
#define JAVA_LEX_SEP(c) printf ("java_lex:%d: separator '%c'\n",lineno,c)
|
||||
#define JAVA_LEX_OP(c) printf ("java_lex:%d: operator '%s'\n", lineno,c)
|
||||
#else
|
||||
#define JAVA_LEX_CHAR(c)
|
||||
#define JAVA_LEX_KW(c)
|
||||
#define JAVA_LEX_ID(s)
|
||||
#define JAVA_LEX_LIT(s,r)
|
||||
#define JAVA_LEX_CHAR_LIT(s)
|
||||
#define JAVA_LEX_STR_LIT(s)
|
||||
#define JAVA_LEX_SEP(c)
|
||||
#define JAVA_LEX_OP(s)
|
||||
#endif
|
||||
|
||||
/* Line information containers */
|
||||
struct java_line {
|
||||
unicode_t *line; /* The line's unicode */
|
||||
char *unicode_escape_p; /* The maching char was a unicode escape */
|
||||
unicode_t ahead[1]; /* Character ahead */
|
||||
char unicode_escape_ahead_p; /* Character ahead is a unicode escape */
|
||||
int max; /* buffer's max size */
|
||||
int size; /* number of unicodes */
|
||||
int current; /* Current position, unicode based */
|
||||
int char_col; /* Current position, input char based */
|
||||
int lineno; /* Its line number */
|
||||
int white_space_only; /* If it contains only white spaces */
|
||||
};
|
||||
#define JAVA_COLUMN_DELTA(p) \
|
||||
(ctxp->c_line->unicode_escape_p [ctxp->c_line->current+(p)] ? 6 : \
|
||||
(ctxp->c_line->line [ctxp->c_line->current+(p)] == '\t' ? 8 : 1))
|
||||
|
||||
struct java_error {
|
||||
struct java_line *line;
|
||||
int error;
|
||||
};
|
||||
|
||||
typedef struct _java_lc {
|
||||
int line;
|
||||
int col;
|
||||
} java_lc;
|
||||
|
||||
|
||||
#define JAVA_LINE_MAX 80
|
||||
|
||||
/* Macro to read and unread chars */
|
||||
#define UNGETC(c) ctxp->unget_utf8_value = (c);
|
||||
#define GETC() getc(finput)
|
||||
|
||||
/* Build a location compound integer */
|
||||
#define BUILD_LOCATION() ((ctxp->elc.line << 12) | (ctxp->elc.col & 0xfff))
|
||||
|
||||
/* Those macros are defined differently if we compile jc1-lite
|
||||
(JC1_LITE defined) or jc1. */
|
||||
#ifdef JC1_LITE
|
||||
|
||||
#define DCONST0 0
|
||||
#define HOST_WIDE_INT long
|
||||
#define HOST_BITS_PER_WIDE_INT 64
|
||||
#define HOST_BITS_PER_CHAR 8
|
||||
#define REAL_VALUE_TYPE int
|
||||
#define SET_FLOAT_HANDLER(H)
|
||||
#define GET_IDENTIFIER(S) xstrdup ((S))
|
||||
#define REAL_VALUE_ATOF(LIT,MODE) 0
|
||||
#define REAL_VALUE_ISINF(VALUE) 0
|
||||
#define REAL_VALUE_ISNAN(VALUE) 0
|
||||
#define SET_REAL_VALUE_ATOF(TARGET,SOURCE)
|
||||
#define FLOAT_TYPE_NODE 0
|
||||
#define DOUBLE_TYPE_NODE 0
|
||||
#define SET_MODIFIER_CTX(TOKEN) java_lval->value = (TOKEN)
|
||||
#define GET_TYPE_PRECISION(NODE) 4
|
||||
#define BUILD_OPERATOR(TOKEN) return TOKEN
|
||||
#define BUILD_OPERATOR2(TOKEN) return TOKEN
|
||||
#define SET_LVAL_NODE(NODE)
|
||||
#define SET_LVAL_NODE_TYPE(NODE, TYPE)
|
||||
#define BUILD_ID_WFL(EXP) (EXP)
|
||||
#define JAVA_FLOAT_RANGE_ERROR(S) {}
|
||||
#define JAVA_INTEGRAL_RANGE_ERROR(S) {}
|
||||
|
||||
#else
|
||||
|
||||
static tree build_wfl_node ();
|
||||
#define SET_FLOAT_HANDLER(H) set_float_handler ((H))
|
||||
#define DCONST0 dconst0
|
||||
#define GET_IDENTIFIER(S) get_identifier ((S))
|
||||
#define SET_REAL_VALUE_ATOF(TARGET,SOURCE) (TARGET) = (SOURCE)
|
||||
#define FLOAT_TYPE_NODE float_type_node
|
||||
#define DOUBLE_TYPE_NODE double_type_node
|
||||
/* Set modifier_ctx according to TOKEN */
|
||||
#define SET_MODIFIER_CTX(TOKEN) \
|
||||
{ \
|
||||
ctxp->modifier_ctx [(TOKEN)-PUBLIC_TK] = build_wfl_node (NULL_TREE); \
|
||||
java_lval->value = (TOKEN)-PUBLIC_TK; \
|
||||
}
|
||||
/* Type precision for long */
|
||||
#define GET_TYPE_PRECISION(NODE) TYPE_PRECISION (long_type_node) / 8;
|
||||
/* Build an operator tree node and return TOKEN */
|
||||
#define BUILD_OPERATOR(TOKEN) \
|
||||
{ \
|
||||
java_lval->operator.token = (TOKEN); \
|
||||
java_lval->operator.location = BUILD_LOCATION(); \
|
||||
return (TOKEN); \
|
||||
}
|
||||
|
||||
/* Build an operator tree node but return ASSIGN_ANY_TK */
|
||||
#define BUILD_OPERATOR2(TOKEN) \
|
||||
{ \
|
||||
java_lval->operator.token = (TOKEN); \
|
||||
java_lval->operator.location = BUILD_LOCATION(); \
|
||||
return ASSIGN_ANY_TK; \
|
||||
}
|
||||
/* Set java_lval->node and TREE_TYPE(java_lval->node) in macros */
|
||||
#define SET_LVAL_NODE(NODE) java_lval->node = (NODE)
|
||||
#define SET_LVAL_NODE_TYPE(NODE,TYPE) \
|
||||
{ \
|
||||
java_lval->node = (NODE); \
|
||||
TREE_TYPE (java_lval->node) = (TYPE); \
|
||||
}
|
||||
/* Wrap identifier around a wfl */
|
||||
#define BUILD_ID_WFL(EXP) build_wfl_node ((EXP))
|
||||
/* Special ways to report error on numeric literals */
|
||||
#define JAVA_FLOAT_RANGE_ERROR(m) \
|
||||
{ \
|
||||
char msg [1024]; \
|
||||
int i = ctxp->c_line->current; \
|
||||
ctxp->c_line->current = number_beginning; \
|
||||
sprintf (msg, "Floating pointer literal exceeds range of `%s'", (m)); \
|
||||
java_lex_error (msg, 0); \
|
||||
ctxp->c_line->current = i; \
|
||||
value = dconst0; \
|
||||
}
|
||||
#define JAVA_INTEGRAL_RANGE_ERROR(m) \
|
||||
{ \
|
||||
int i = ctxp->c_line->current; \
|
||||
ctxp->c_line->current = number_beginning; \
|
||||
java_lex_error (m, 0); \
|
||||
ctxp->c_line->current = i; \
|
||||
}
|
||||
|
||||
#endif /* Definitions for jc1 compilation only */
|
||||
|
||||
/* Macros to decode character ranges */
|
||||
#define RANGE(c, l, h) (((c) >= l && (c) <= h))
|
||||
#define JAVA_WHITE_SPACE_P(c) (c == ' ' || c == '\t' || c == '\f')
|
||||
#define JAVA_ID_CHAR_P(c) ((c < 128 && (RANGE (c, 'A', 'Z') || \
|
||||
RANGE (c, 'a', 'z') || \
|
||||
RANGE (c, '0', '9') || \
|
||||
c == '_' || \
|
||||
c == '$')) || \
|
||||
(c > 127 && java_letter_or_digit_p (c)))
|
||||
#define JAVA_ASCII_DIGIT(c) RANGE(c,'0', '9')
|
||||
#define JAVA_ASCII_OCTDIGIT(c) RANGE(c,'0', '7')
|
||||
#define JAVA_ASCII_HEXDIGIT(c) (RANGE(c,'0', '9') || \
|
||||
RANGE(c,'a', 'f') || \
|
||||
RANGE(c,'A', 'F'))
|
||||
#define JAVA_ASCII_FPCHAR(c) (RANGE(c,'d', 'f') || RANGE(c,'D', 'F') || \
|
||||
c == '.' || JAVA_ASCII_DIGIT (c))
|
||||
#define JAVA_FP_SUFFIX(c) (c == 'D' || c == 'd' || c == 'f' || c == 'F')
|
||||
#define JAVA_FP_EXP(c) (c == 'E' || c == 'F')
|
||||
#define JAVA_FP_PM(c) (c == '-' || c == '+')
|
||||
#define JAVA_ASCII_LETTER(c) (RANGE(c,'a', 'z') || RANGE(c,'A', 'Z'))
|
||||
#define JAVA_DIGIT_P(c) \
|
||||
(RANGE (c, 0x030, 0x039) || /* ISO-Latin-1 (and ASCII) digits ('0'-'9') */ \
|
||||
RANGE (c, 0x660, 0x669) || /* Arabic-Indic digits */ \
|
||||
RANGE (c, 0x6F0, 0x6F9) || /* Eastern Arabic-Indic digits */ \
|
||||
RANGE (c, 0x966, 0x96F) || /* Devanagari digits */ \
|
||||
RANGE (c, 0x9E6, 0x9EF) || /* Bengali digits */ \
|
||||
RANGE (c, 0xA66, 0xA6F) || /* Gurmukhi digits */ \
|
||||
RANGE (c, 0xAE6, 0xAEF) || /* Gujarati digits */ \
|
||||
RANGE (c, 0xB66, 0xB6F) || /* Oriya digits */ \
|
||||
RANGE (c, 0xBE7, 0xBEF) || /* Tamil digits */ \
|
||||
RANGE (c, 0xC66, 0xC6F) || /* Telugu digits */ \
|
||||
RANGE (c, 0xCE6, 0xCEF) || /* Kannada digits */ \
|
||||
RANGE (c, 0xD66, 0xD6F) || /* Malayalam digits */ \
|
||||
RANGE (c, 0xE50, 0xE59) || /* Thai digits */ \
|
||||
RANGE (c, 0xED0, 0xED9)) /* Lao digits */
|
||||
|
||||
/* This is not to be used as a stand alone macro. Use JAVA_ID_CHAR_P()
|
||||
or the forcoming JAVA_LETTER_OR_DIGIT_P() instead.
|
||||
It need to be split by region. FIXME. */
|
||||
#define _JAVA_LETTER_OR_DIGIT_P(c) \
|
||||
(RANGE (c, 0x00C0, 0x00D6) || \
|
||||
RANGE (c, 0x00D8, 0x00F6) || \
|
||||
RANGE (c, 0x00F8, 0x01F5) || \
|
||||
RANGE (c, 0x01FA, 0x0217) || \
|
||||
RANGE (c, 0x0250, 0x02A8) || \
|
||||
RANGE (c, 0x02B0, 0x02DE) || \
|
||||
RANGE (c, 0x02E0, 0x02E9) || \
|
||||
RANGE (c, 0x0300, 0x0345) || \
|
||||
RANGE (c, 0x0360, 0x0361) || \
|
||||
RANGE (c, 0x0374, 0x0375) || \
|
||||
c == 0x037A || \
|
||||
c == 0x037E || \
|
||||
RANGE (c, 0x0384, 0x038A) || \
|
||||
c == 0x038C || \
|
||||
c == 0x038E || \
|
||||
RANGE (c, 0x038F, 0x03A1) || \
|
||||
RANGE (c, 0x03A3, 0x03CE) || \
|
||||
RANGE (c, 0x03D0, 0x03D6) || \
|
||||
RANGE (c, 0x03DA, 0x03E2) || \
|
||||
c == 0x03DA || \
|
||||
c == 0x03DC || \
|
||||
c == 0x03DE || \
|
||||
c == 0x03E0 || \
|
||||
RANGE (c, 0x03E2, 0x03F3) || \
|
||||
RANGE (c, 0x0401, 0x040C) || \
|
||||
RANGE (c, 0x040E, 0x044F) || \
|
||||
RANGE (c, 0x0451, 0x045C) || \
|
||||
RANGE (c, 0x045E, 0x0486) || \
|
||||
RANGE (c, 0x0490, 0x04C4) || \
|
||||
RANGE (c, 0x04C7, 0x04C8) || \
|
||||
RANGE (c, 0x04CB, 0x04CC) || \
|
||||
RANGE (c, 0x04D0, 0x04EB) || \
|
||||
RANGE (c, 0x04EE, 0x04F5) || \
|
||||
RANGE (c, 0x04F8, 0x04F9) || \
|
||||
RANGE (c, 0x0531, 0x0556) || \
|
||||
RANGE (c, 0x0559, 0x055F) || \
|
||||
RANGE (c, 0x0561, 0x0587) || \
|
||||
c == 0x0589 || \
|
||||
RANGE (c, 0x05B0, 0x05B9) || \
|
||||
RANGE (c, 0x05BB, 0x05C3) || \
|
||||
RANGE (c, 0x05D0, 0x05EA) || \
|
||||
RANGE (c, 0x05F0, 0x05F4) || \
|
||||
c == 0x060C || \
|
||||
c == 0x061B || \
|
||||
c == 0x061F || \
|
||||
c == 0x0621 || \
|
||||
RANGE (c, 0x0622, 0x063A) || \
|
||||
RANGE (c, 0x0640, 0x0652) || \
|
||||
RANGE (c, 0x0660, 0x066D) || \
|
||||
RANGE (c, 0x0670, 0x06B7) || \
|
||||
RANGE (c, 0x06BA, 0x06BE) || \
|
||||
RANGE (c, 0x06C0, 0x06CE) || \
|
||||
RANGE (c, 0x06D0, 0x06ED) || \
|
||||
RANGE (c, 0x06F0, 0x06F9) || \
|
||||
RANGE (c, 0x0901, 0x0903) || \
|
||||
RANGE (c, 0x0905, 0x0939) || \
|
||||
RANGE (c, 0x093C, 0x094D) || \
|
||||
RANGE (c, 0x0950, 0x0954) || \
|
||||
RANGE (c, 0x0958, 0x0970) || \
|
||||
RANGE (c, 0x0981, 0x0983) || \
|
||||
RANGE (c, 0x0985, 0x098C) || \
|
||||
RANGE (c, 0x098F, 0x0990) || \
|
||||
RANGE (c, 0x0993, 0x09A8) || \
|
||||
RANGE (c, 0x09AA, 0x09B0) || \
|
||||
c == 0x09B2 || \
|
||||
RANGE (c, 0x09B6, 0x09B9) || \
|
||||
c == 0x09BC || \
|
||||
c == 0x09BE || \
|
||||
RANGE (c, 0x09BF, 0x09C4) || \
|
||||
RANGE (c, 0x09C7, 0x09C8) || \
|
||||
RANGE (c, 0x09CB, 0x09CD) || \
|
||||
c == 0x09D7 || \
|
||||
RANGE (c, 0x09DC, 0x09DD) || \
|
||||
RANGE (c, 0x09DF, 0x09E3) || \
|
||||
RANGE (c, 0x09E6, 0x09FA) || \
|
||||
c == 0x0A02 || \
|
||||
RANGE (c, 0x0A05, 0x0A0A) || \
|
||||
RANGE (c, 0x0A0F, 0x0A10) || \
|
||||
RANGE (c, 0x0A13, 0x0A28) || \
|
||||
RANGE (c, 0x0A2A, 0x0A30) || \
|
||||
RANGE (c, 0x0A32, 0x0A33) || \
|
||||
RANGE (c, 0x0A35, 0x0A36) || \
|
||||
RANGE (c, 0x0A38, 0x0A39) || \
|
||||
c == 0x0A3C || \
|
||||
c == 0x0A3E || \
|
||||
RANGE (c, 0x0A3F, 0x0A42) || \
|
||||
RANGE (c, 0x0A47, 0x0A48) || \
|
||||
RANGE (c, 0x0A4B, 0x0A4D) || \
|
||||
RANGE (c, 0x0A59, 0x0A5C) || \
|
||||
c == 0x0A5E || \
|
||||
RANGE (c, 0x0A66, 0x0A74) || \
|
||||
RANGE (c, 0x0A81, 0x0A83) || \
|
||||
RANGE (c, 0x0A85, 0x0A8B) || \
|
||||
c == 0x0A8D || \
|
||||
c == 0x0A8F || \
|
||||
RANGE (c, 0x0A90, 0x0A91) || \
|
||||
RANGE (c, 0x0A93, 0x0AA8) || \
|
||||
RANGE (c, 0x0AAA, 0x0AB0) || \
|
||||
RANGE (c, 0x0AB2, 0x0AB3) || \
|
||||
RANGE (c, 0x0AB5, 0x0AB9) || \
|
||||
RANGE (c, 0x0ABC, 0x0AC5) || \
|
||||
RANGE (c, 0x0AC7, 0x0AC9) || \
|
||||
RANGE (c, 0x0ACB, 0x0ACD) || \
|
||||
c == 0x0AD0 || \
|
||||
c == 0x0AE0 || \
|
||||
RANGE (c, 0x0AE6, 0x0AEF) || \
|
||||
RANGE (c, 0x0B01, 0x0B03) || \
|
||||
RANGE (c, 0x0B05, 0x0B0C) || \
|
||||
RANGE (c, 0x0B0F, 0x0B10) || \
|
||||
RANGE (c, 0x0B13, 0x0B28) || \
|
||||
RANGE (c, 0x0B2A, 0x0B30) || \
|
||||
RANGE (c, 0x0B32, 0x0B33) || \
|
||||
RANGE (c, 0x0B36, 0x0B39) || \
|
||||
RANGE (c, 0x0B3C, 0x0B43) || \
|
||||
RANGE (c, 0x0B47, 0x0B48) || \
|
||||
RANGE (c, 0x0B4B, 0x0B4D) || \
|
||||
RANGE (c, 0x0B56, 0x0B57) || \
|
||||
RANGE (c, 0x0B5C, 0x0B5D) || \
|
||||
RANGE (c, 0x0B5F, 0x0B61) || \
|
||||
RANGE (c, 0x0B66, 0x0B70) || \
|
||||
RANGE (c, 0x0B82, 0x0B83) || \
|
||||
RANGE (c, 0x0B85, 0x0B8A) || \
|
||||
RANGE (c, 0x0B8E, 0x0B90) || \
|
||||
RANGE (c, 0x0B92, 0x0B95) || \
|
||||
RANGE (c, 0x0B99, 0x0B9A) || \
|
||||
c == 0x0B9C || \
|
||||
c == 0x0B9E || \
|
||||
c == 0x0B9F || \
|
||||
RANGE (c, 0x0BA3, 0x0BA4) || \
|
||||
RANGE (c, 0x0BA8, 0x0BAA) || \
|
||||
RANGE (c, 0x0BAE, 0x0BB5) || \
|
||||
RANGE (c, 0x0BB7, 0x0BB9) || \
|
||||
RANGE (c, 0x0BBE, 0x0BC2) || \
|
||||
RANGE (c, 0x0BC6, 0x0BC8) || \
|
||||
RANGE (c, 0x0BCA, 0x0BCD) || \
|
||||
c == 0x0BD7 || \
|
||||
RANGE (c, 0x0BE7, 0x0BF2) || \
|
||||
RANGE (c, 0x0C01, 0x0C03) || \
|
||||
RANGE (c, 0x0C05, 0x0C0C) || \
|
||||
RANGE (c, 0x0C0E, 0x0C10) || \
|
||||
RANGE (c, 0x0C12, 0x0C28) || \
|
||||
RANGE (c, 0x0C2A, 0x0C33) || \
|
||||
RANGE (c, 0x0C35, 0x0C39) || \
|
||||
RANGE (c, 0x0C3E, 0x0C44) || \
|
||||
RANGE (c, 0x0C46, 0x0C48) || \
|
||||
RANGE (c, 0x0C4A, 0x0C4D) || \
|
||||
RANGE (c, 0x0C55, 0x0C56) || \
|
||||
RANGE (c, 0x0C60, 0x0C61) || \
|
||||
RANGE (c, 0x0C66, 0x0C6F) || \
|
||||
RANGE (c, 0x0C82, 0x0C83) || \
|
||||
RANGE (c, 0x0C85, 0x0C8C) || \
|
||||
RANGE (c, 0x0C8E, 0x0C90) || \
|
||||
RANGE (c, 0x0C92, 0x0CA8) || \
|
||||
RANGE (c, 0x0CAA, 0x0CB3) || \
|
||||
RANGE (c, 0x0CB5, 0x0CB9) || \
|
||||
RANGE (c, 0x0CBE, 0x0CC4) || \
|
||||
RANGE (c, 0x0CC6, 0x0CC8) || \
|
||||
RANGE (c, 0x0CCA, 0x0CCD) || \
|
||||
RANGE (c, 0x0CD5, 0x0CD6) || \
|
||||
c == 0x0CDE || \
|
||||
c == 0x0CE0 || \
|
||||
c == 0x0CE1 || \
|
||||
RANGE (c, 0x0CE6, 0x0CEF) || \
|
||||
RANGE (c, 0x0D02, 0x0D03) || \
|
||||
RANGE (c, 0x0D05, 0x0D0C) || \
|
||||
RANGE (c, 0x0D0E, 0x0D10) || \
|
||||
RANGE (c, 0x0D12, 0x0D28) || \
|
||||
RANGE (c, 0x0D2A, 0x0D39) || \
|
||||
RANGE (c, 0x0D3E, 0x0D43) || \
|
||||
RANGE (c, 0x0D46, 0x0D48) || \
|
||||
RANGE (c, 0x0D4A, 0x0D4D) || \
|
||||
c == 0x0D57 || \
|
||||
RANGE (c, 0x0D60, 0x0D61) || \
|
||||
RANGE (c, 0x0D66, 0x0D6F) || \
|
||||
RANGE (c, 0x0E01, 0x0E3A) || \
|
||||
RANGE (c, 0x0E3F, 0x0E5B) || \
|
||||
RANGE (c, 0x0E81, 0x0E82) || \
|
||||
c == 0x0E84 || \
|
||||
RANGE (c, 0x0E87, 0x0E88) || \
|
||||
c == 0x0E8A || \
|
||||
c == 0x0E8D || \
|
||||
RANGE (c, 0x0E94, 0x0E97) || \
|
||||
RANGE (c, 0x0E99, 0x0E9F) || \
|
||||
RANGE (c, 0x0EA1, 0x0EA3) || \
|
||||
c == 0x0EA5 || \
|
||||
c == 0x0EA7 || \
|
||||
RANGE (c, 0x0EAA, 0x0EAB) || \
|
||||
RANGE (c, 0x0EAD, 0x0EB9) || \
|
||||
RANGE (c, 0x0EBB, 0x0EBD) || \
|
||||
RANGE (c, 0x0EC0, 0x0EC4) || \
|
||||
c == 0x0EC6 || \
|
||||
c == 0x0EC8 || \
|
||||
RANGE (c, 0x0EC9, 0x0ECD) || \
|
||||
RANGE (c, 0x0ED0, 0x0ED9) || \
|
||||
RANGE (c, 0x0EDC, 0x0EDD) || \
|
||||
RANGE (c, 0x10A0, 0x10C5) || \
|
||||
RANGE (c, 0x10D0, 0x10F6) || \
|
||||
c == 0x10FB || \
|
||||
RANGE (c, 0x1100, 0x1159) || \
|
||||
RANGE (c, 0x115F, 0x11A2) || \
|
||||
RANGE (c, 0x11A8, 0x11F9) || \
|
||||
RANGE (c, 0x1E00, 0x1E9A) || \
|
||||
RANGE (c, 0x1EA0, 0x1EF9) || \
|
||||
RANGE (c, 0x1F00, 0x1F15) || \
|
||||
RANGE (c, 0x1F18, 0x1F1D) || \
|
||||
RANGE (c, 0x1F20, 0x1F45) || \
|
||||
RANGE (c, 0x1F48, 0x1F4D) || \
|
||||
RANGE (c, 0x1F50, 0x1F57) || \
|
||||
c == 0x1F59 || \
|
||||
c == 0x1F5B || \
|
||||
c == 0x1F5D || \
|
||||
RANGE (c, 0x1F5F, 0x1F7D) || \
|
||||
RANGE (c, 0x1F80, 0x1FB4) || \
|
||||
RANGE (c, 0x1FB6, 0x1FC4) || \
|
||||
RANGE (c, 0x1FC6, 0x1FD3) || \
|
||||
RANGE (c, 0x1FD6, 0x1FDB) || \
|
||||
RANGE (c, 0x1FDD, 0x1FEF) || \
|
||||
RANGE (c, 0x1FF2, 0x1FF4) || \
|
||||
RANGE (c, 0x1FF6, 0x1FFE) || \
|
||||
RANGE (c, 0x3041, 0x3094) || \
|
||||
RANGE (c, 0x3099, 0x309E) || \
|
||||
RANGE (c, 0x30A1, 0x30FE) || \
|
||||
RANGE (c, 0x3105, 0x312C) || \
|
||||
RANGE (c, 0x3131, 0x318E) || \
|
||||
RANGE (c, 0x3190, 0x319F) || \
|
||||
RANGE (c, 0x3200, 0x321C) || \
|
||||
RANGE (c, 0x3220, 0x3243) || \
|
||||
RANGE (c, 0x3260, 0x327B) || \
|
||||
RANGE (c, 0x327F, 0x32B0) || \
|
||||
RANGE (c, 0x32C0, 0x32CB) || \
|
||||
RANGE (c, 0x32D0, 0x32FE) || \
|
||||
RANGE (c, 0x3300, 0x3376) || \
|
||||
RANGE (c, 0x337B, 0x33DD) || \
|
||||
RANGE (c, 0x33E0, 0x33FE) || \
|
||||
RANGE (c, 0x3400, 0x9FA5) || \
|
||||
RANGE (c, 0xF900, 0xFA2D) || \
|
||||
RANGE (c, 0xFB00, 0xFB06) || \
|
||||
RANGE (c, 0xFB13, 0xFB17) || \
|
||||
RANGE (c, 0xFB1E, 0xFB36) || \
|
||||
RANGE (c, 0xFB38, 0xFB3C) || \
|
||||
c == 0xFB3E || \
|
||||
c == 0xFB40 || \
|
||||
c == 0xFB41 || \
|
||||
c == 0xFB43 || \
|
||||
c == 0xFB44 || \
|
||||
c == 0xFB46 || \
|
||||
RANGE (c, 0xFB47, 0xFBB1) || \
|
||||
RANGE (c, 0xFBD3, 0xFD3F) || \
|
||||
RANGE (c, 0xFD50, 0xFD8F) || \
|
||||
RANGE (c, 0xFD92, 0xFDC7) || \
|
||||
RANGE (c, 0xFDF0, 0xFDFB) || \
|
||||
RANGE (c, 0xFE70, 0xFE72) || \
|
||||
c == 0xFE74 || \
|
||||
c == 0xFE76 || \
|
||||
RANGE (c, 0xFE77, 0xFEFC) || \
|
||||
RANGE (c, 0xFF10, 0xFF19) || \
|
||||
RANGE (c, 0xFF21, 0xFF3A) || \
|
||||
RANGE (c, 0xFF41, 0xFF5A) || \
|
||||
RANGE (c, 0xFF66, 0xFFBE) || \
|
||||
RANGE (c, 0xFFC2, 0xFFC7) || \
|
||||
RANGE (c, 0xFFCA, 0xFFCF) || \
|
||||
RANGE (c, 0xFFD2, 0xFFD7) || \
|
||||
RANGE (c, 0xFFDA, 0xFFDC))
|
||||
|
||||
/* Constants */
|
||||
#define JAVA_CHAR_ERROR 0xFFC1 /* This is an illegal unicode!?! FIXME */
|
||||
#define JAVA_READ_BUFFER 256
|
||||
#define UEOF (unicode_t)0xffff
|
||||
|
||||
#endif
|
163
gcc/java/mangle.c
Normal file
163
gcc/java/mangle.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/* Functions related to mangling class names for the GNU compiler
|
||||
for the Java(TM) language.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* Written by Per Bothner <bothner@cygnus.com> */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
#include "jcf.h"
|
||||
#include "obstack.h"
|
||||
|
||||
/* Assuming (NAME, LEN) is a Utf8-encoding string, calculate
|
||||
the length of the string as mangled (a la g++) including Unicode escapes.
|
||||
If no escapes are needed, return 0. */
|
||||
|
||||
int
|
||||
unicode_mangling_length (name, len)
|
||||
char *name;
|
||||
int len;
|
||||
{
|
||||
unsigned char *ptr;
|
||||
unsigned char *limit = (unsigned char *)name + len;
|
||||
int need_escapes = 0;
|
||||
int num_chars = 0;
|
||||
int underscores = 0;
|
||||
for (ptr = (unsigned char *) name; ptr < limit; )
|
||||
{
|
||||
int ch = UTF8_GET(ptr, limit);
|
||||
if (ch < 0)
|
||||
error ("internal error - invalid Utf8 name");
|
||||
if (ch >= '0' && ch <= '9')
|
||||
need_escapes += num_chars == 0;
|
||||
else if (ch == '_')
|
||||
underscores++;
|
||||
else if ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z'))
|
||||
need_escapes++;
|
||||
num_chars++;
|
||||
}
|
||||
if (need_escapes)
|
||||
return num_chars + 4 * (need_escapes + underscores);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assuming (NAME, LEN) is a Utf8-encoding string, emit the string
|
||||
appropriately mangled (with Unicode escapes) to OBSTACK. */
|
||||
|
||||
void
|
||||
emit_unicode_mangled_name (obstack, name, len)
|
||||
struct obstack *obstack;
|
||||
char *name;
|
||||
{
|
||||
unsigned char *ptr;
|
||||
unsigned char *limit = (unsigned char *)name + len;
|
||||
for (ptr = (unsigned char *) name; ptr < limit; )
|
||||
{
|
||||
int ch = UTF8_GET(ptr, limit);
|
||||
int emit_escape;
|
||||
if (ch < 0)
|
||||
{
|
||||
error ("internal error - bad Utf8 string");
|
||||
break;
|
||||
}
|
||||
if (ch >= '0' && ch <= '9')
|
||||
emit_escape = (ptr == (unsigned char*) name);
|
||||
else
|
||||
emit_escape = (ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z');
|
||||
if (emit_escape)
|
||||
{
|
||||
char buf[6];
|
||||
sprintf (buf, "_%04x", ch);
|
||||
obstack_grow (obstack, buf, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
obstack_1grow (obstack, ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Assuming (NAME, LEN) is a Utf8-encoding string, emit the string
|
||||
appropriately mangled (with Unicode escapes if needed) to OBSTACK. */
|
||||
|
||||
void
|
||||
append_gpp_mangled_name (obstack, name, len)
|
||||
struct obstack *obstack;
|
||||
char *name;
|
||||
int len;
|
||||
{
|
||||
int encoded_len = unicode_mangling_length (name, len);
|
||||
int needs_escapes = encoded_len > 0;
|
||||
char buf[6];
|
||||
if (needs_escapes)
|
||||
{
|
||||
sprintf (buf, "U%d", encoded_len);
|
||||
obstack_grow (obstack, buf, strlen(buf));
|
||||
emit_unicode_mangled_name (obstack, name, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf (buf, "%d", len);
|
||||
obstack_grow (obstack, buf, strlen(buf));
|
||||
obstack_grow (obstack, name, len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Append the mangled name of a class named CLASSNAME onto OBSTACK. */
|
||||
|
||||
void
|
||||
append_gpp_mangled_classtype (obstack, class_name)
|
||||
struct obstack *obstack;
|
||||
char *class_name;
|
||||
{
|
||||
char *ptr;
|
||||
int qualifications = 0;
|
||||
|
||||
for (ptr = class_name; *ptr != '\0'; ptr++)
|
||||
{
|
||||
if (*ptr == '.')
|
||||
qualifications++;
|
||||
}
|
||||
if (qualifications)
|
||||
{
|
||||
char buf[8];
|
||||
if (qualifications >= 9)
|
||||
sprintf (buf, "Q_%d_", qualifications + 1);
|
||||
else
|
||||
sprintf (buf, "Q%d", qualifications + 1);
|
||||
obstack_grow (obstack, buf, strlen (buf));
|
||||
}
|
||||
for (ptr = class_name; ; ptr++)
|
||||
{
|
||||
if (ptr[0] == '.' || ptr[0] == '\0')
|
||||
{
|
||||
append_gpp_mangled_name (obstack, class_name, ptr - class_name);
|
||||
if (ptr[0] == '\0')
|
||||
break;
|
||||
class_name = ptr + 1;
|
||||
}
|
||||
}
|
||||
}
|
1162
gcc/java/parse-scan.y
Normal file
1162
gcc/java/parse-scan.y
Normal file
File diff suppressed because it is too large
Load diff
10648
gcc/java/parse.c
Normal file
10648
gcc/java/parse.c
Normal file
File diff suppressed because it is too large
Load diff
599
gcc/java/parse.h
Normal file
599
gcc/java/parse.h
Normal file
|
@ -0,0 +1,599 @@
|
|||
/* Language parser definitions for the GNU compiler for the Java(TM) language.
|
||||
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
#ifndef JV_LANG_H
|
||||
#define JV_LANG_H
|
||||
|
||||
#include "lex.h"
|
||||
|
||||
/* Extern global variable declarations */
|
||||
extern int java_error_count;
|
||||
extern struct obstack temporary_obstack;
|
||||
extern struct obstack permanent_obstack;
|
||||
extern int quiet_flag;
|
||||
|
||||
#ifndef JC1_LITE
|
||||
/* Function extern to java/ */
|
||||
extern int int_fits_type_p PROTO ((tree, tree));
|
||||
extern tree stabilize_reference PROTO ((tree));
|
||||
#endif
|
||||
|
||||
/* Macros for verbose debug info */
|
||||
#ifdef VERBOSE_SKELETON
|
||||
#define RULE( rule ) printf ( "jv_yacc:%d: rule %s\n", lineno, rule )
|
||||
#else
|
||||
#define RULE( rule )
|
||||
#endif
|
||||
|
||||
#ifdef SOURCE_FRONTEND_DEBUG
|
||||
#undef SOURCE_FRONTEND_DEBUG
|
||||
#define SOURCE_FRONTEND_DEBUG(X) \
|
||||
{if (!quiet_flag) {printf ("* "); printf X; putchar ('\n');} }
|
||||
#else
|
||||
#define SOURCE_FRONTEND_DEBUG(X)
|
||||
#endif
|
||||
|
||||
/* Macro for error recovering */
|
||||
#ifdef YYDEBUG
|
||||
#define RECOVERED \
|
||||
{ if (!quiet_flag) {printf ("** Recovered\n");} }
|
||||
#define DRECOVERED(s) \
|
||||
{ if (!quiet_flag) {printf ("** Recovered (%s)\n", #s);}}
|
||||
#else
|
||||
#define RECOVERED
|
||||
#define DRECOVERED(s)
|
||||
#endif
|
||||
|
||||
#define DRECOVER(s) {yyerrok; DRECOVERED(s)}
|
||||
#define RECOVER {yyerrok; RECOVERED}
|
||||
|
||||
#define YYERROR_NOW ctxp->java_error_flag = 1
|
||||
#define YYNOT_TWICE if (ctxp->prevent_ese != lineno)
|
||||
|
||||
/* Accepted modifiers */
|
||||
#define CLASS_MODIFIERS ACC_PUBLIC|ACC_ABSTRACT|ACC_FINAL
|
||||
#define FIELD_MODIFIERS ACC_PUBLIC|ACC_PROTECTED|ACC_PRIVATE|ACC_FINAL| \
|
||||
ACC_STATIC|ACC_TRANSIENT|ACC_VOLATILE
|
||||
#define METHOD_MODIFIERS ACC_PUBLIC|ACC_PROTECTED|ACC_PRIVATE|ACC_ABSTRACT| \
|
||||
ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE
|
||||
#define INTERFACE_MODIFIERS ACC_PUBLIC|ACC_ABSTRACT
|
||||
#define INTERFACE_METHOD_MODIFIERS ACC_PUBLIC|ACC_ABSTRACT
|
||||
#define INTERFACE_FIELD_MODIFIERS ACC_PUBLIC|ACC_STATIC|ACC_FINAL
|
||||
|
||||
/* Getting a modifier WFL */
|
||||
#define MODIFIER_WFL(M) (ctxp->modifier_ctx [(M) - PUBLIC_TK])
|
||||
|
||||
/* Check on modifiers */
|
||||
#define THIS_MODIFIER_ONLY(f, m, v, count, l) \
|
||||
if ((f) & (m)) \
|
||||
{ \
|
||||
tree node = ctxp->modifier_ctx [v]; \
|
||||
if ((l) \
|
||||
&& ((EXPR_WFL_COLNO (node) > EXPR_WFL_COLNO (l)) \
|
||||
|| (EXPR_WFL_LINENO (node) > EXPR_WFL_LINENO (l)))) \
|
||||
l = node; \
|
||||
else if (!(l)) \
|
||||
l = node; \
|
||||
count++; \
|
||||
}
|
||||
|
||||
#define ABSTRACT_CHECK(flag, v, cl, s) \
|
||||
if ((flag) & (v)) \
|
||||
parse_error_context (cl, s " method can't be abstract");
|
||||
|
||||
/* Misc. */
|
||||
#define exit_java_complete_class() \
|
||||
{ \
|
||||
pop_obstacks (); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define CLASS_OR_INTERFACE(decl, s1, s2) \
|
||||
(decl ? \
|
||||
((get_access_flags_from_decl (TYPE_NAME (TREE_TYPE (decl))) \
|
||||
& ACC_INTERFACE) ? \
|
||||
s2 : s1) : ((s1 [0]=='S'|| s1 [0]=='s') ? \
|
||||
(s1 [0]=='S' ? "Supertype" : "supertype") : \
|
||||
(s1 [0] > 'A' ? "Type" : "type")))
|
||||
|
||||
/* Pedantic warning on obsolete modifiers. Note: when cl is NULL,
|
||||
flags was set artificially, such as for a interface method */
|
||||
#define OBSOLETE_MODIFIER_WARNING(cl, flags, modifier, format, arg) \
|
||||
{ \
|
||||
if ((cl) && ((flags) & (modifier))) \
|
||||
parse_warning_context (cl, \
|
||||
"Discouraged redundant use of `%s' modifier " \
|
||||
"in declaration of " format, \
|
||||
java_accstring_lookup (modifier), arg); \
|
||||
}
|
||||
|
||||
/* Quickly build a temporary pointer on hypothetical type NAME. */
|
||||
#define BUILD_PTR_FROM_NAME(ptr, name) \
|
||||
{ \
|
||||
ptr = build (POINTER_TYPE, NULL_TREE); \
|
||||
TYPE_NAME (ptr) = name; \
|
||||
}
|
||||
|
||||
#define INCOMPLETE_TYPE_P(NODE) \
|
||||
((TREE_CODE (NODE) == TREE_LIST) \
|
||||
&& (TREE_CODE (TREE_PURPOSE (NODE)) == POINTER_TYPE) \
|
||||
&& (TREE_TYPE (TREE_PURPOSE (NODE)) == NULL_TREE))
|
||||
|
||||
/* Set the EMIT_LINE_NOTE flag of a EXPR_WLF to 1 if debug information
|
||||
are requested. Works in the context of a parser rule. */
|
||||
#define JAVA_MAYBE_GENERATE_DEBUG_INFO(node) \
|
||||
(debug_info_level != DINFO_LEVEL_NONE ? \
|
||||
EXPR_WFL_EMIT_LINE_NOTE (node) = 1, node : node)
|
||||
|
||||
/* Types classification, according to the JLS, section 4.2 */
|
||||
#define JFLOAT_TYPE_P(TYPE) (TREE_CODE ((TYPE)) == REAL_TYPE)
|
||||
#define JINTEGRAL_TYPE_P(TYPE) ((TREE_CODE ((TYPE)) == INTEGER_TYPE) \
|
||||
|| (TREE_CODE ((TYPE)) == CHAR_TYPE))
|
||||
#define JNUMERIC_TYPE_P(TYPE) (JFLOAT_TYPE_P ((TYPE)) \
|
||||
|| JINTEGRAL_TYPE_P ((TYPE)))
|
||||
#define JPRIMITIVE_TYPE_P(TYPE) (JNUMERIC_TYPE_P ((TYPE)) \
|
||||
|| (TREE_CODE ((TYPE)) == BOOLEAN_TYPE))
|
||||
|
||||
/* Not defined in the LRM */
|
||||
#define JSTRING_TYPE_P(TYPE) ((TYPE) == string_type_node || \
|
||||
(TREE_CODE (TYPE) == POINTER_TYPE && \
|
||||
TREE_TYPE (op1_type) == string_type_node))
|
||||
|
||||
#define JREFERENCE_TYPE_P(TYPE) (TREE_CODE (TYPE) == RECORD_TYPE || \
|
||||
(TREE_CODE (TYPE) == POINTER_TYPE && \
|
||||
TREE_CODE (TREE_TYPE (TYPE)) == RECORD_TYPE))
|
||||
|
||||
/* Other predicate */
|
||||
#define DECL_P(NODE) (NODE && (TREE_CODE (NODE) == PARM_DECL \
|
||||
|| TREE_CODE (NODE) == VAR_DECL \
|
||||
|| TREE_CODE (NODE) == FIELD_DECL))
|
||||
|
||||
#define TYPE_INTERFACE_P(TYPE) \
|
||||
(CLASS_P (TYPE) && CLASS_INTERFACE (TYPE_NAME (TYPE)))
|
||||
|
||||
#define TYPE_CLASS_P(TYPE) (CLASS_P (TYPE) \
|
||||
&& !CLASS_INTERFACE (TYPE_NAME (TYPE)) \
|
||||
&& !TYPE_ARRAY_P (TYPE))
|
||||
|
||||
/* Standard error messages */
|
||||
#define ERROR_CANT_CONVERT_TO_BOOLEAN(OPERATOR, NODE, TYPE) \
|
||||
parse_error_context \
|
||||
((OPERATOR), "Incompatible type for `%s'. Can't convert `%s' to " \
|
||||
"boolean", operator_string ((NODE)), lang_printable_name ((TYPE)))
|
||||
|
||||
#define ERROR_CANT_CONVERT_TO_NUMERIC(OPERATOR, NODE, TYPE) \
|
||||
parse_error_context \
|
||||
((OPERATOR), "Incompatible type for `%s'. Can't convert `%s' to " \
|
||||
"numeric type", operator_string ((NODE)), lang_printable_name ((TYPE)))
|
||||
|
||||
#define ERROR_CAST_NEEDED_TO_INTEGRAL(OPERATOR, NODE, TYPE) \
|
||||
parse_error_context \
|
||||
((OPERATOR), (JPRIMITIVE_TYPE_P (TYPE) ? \
|
||||
"Incompatible type for `%s'. Explicit cast needed to convert " \
|
||||
"`%s' to integral" : "Incompatible type for `%s'. Can't convert " \
|
||||
"`%s' to integral"), operator_string ((NODE)), \
|
||||
lang_printable_name ((TYPE)))
|
||||
|
||||
#define ERROR_VARIABLE_NOT_INITIALIZED(WFL, V) \
|
||||
parse_error_context \
|
||||
((WFL), "Variable `%s' may not have been initialized", \
|
||||
IDENTIFIER_POINTER (V))
|
||||
|
||||
/* Definition for loop handling. This Java's own definition of a loop
|
||||
body. See parse.y for documentation. It's valid once you hold a
|
||||
loop's body (LOOP_EXPR_BODY) */
|
||||
|
||||
/* The loop main block is the one hold the condition and the loop body */
|
||||
#define LOOP_EXPR_BODY_MAIN_BLOCK(NODE) TREE_OPERAND (NODE, 0)
|
||||
/* And then there is the loop update block */
|
||||
#define LOOP_EXPR_BODY_UPDATE_BLOCK(NODE) TREE_OPERAND (NODE, 1)
|
||||
|
||||
/* Inside the loop main block, there is the loop condition and the
|
||||
loop body. They may be reversed if the loop being described is a
|
||||
do-while loop. NOTE: if you use a WFL around the EXIT_EXPR so you
|
||||
can issue debug info for it, the EXIT_EXPR will be one operand
|
||||
further. */
|
||||
#define LOOP_EXPR_BODY_CONDITION_EXPR(NODE, R) \
|
||||
TREE_OPERAND (LOOP_EXPR_BODY_MAIN_BLOCK (NODE), (R ? 1 : 0))
|
||||
|
||||
/* Here is the labeled block the loop real body is encapsulated in */
|
||||
#define LOOP_EXPR_BODY_LABELED_BODY(NODE, R) \
|
||||
TREE_OPERAND (LOOP_EXPR_BODY_MAIN_BLOCK (NODE), (R ? 0 : 1))
|
||||
/* And here is the loop's real body */
|
||||
#define LOOP_EXPR_BODY_BODY_EXPR(NODE, R) \
|
||||
LABELED_BLOCK_BODY (LOOP_EXPR_BODY_LABELED_BODY(NODE, R))
|
||||
|
||||
/* Does a loop have a label ? */
|
||||
#define LOOP_HAS_LABEL_P(LOOP) \
|
||||
(ctxp->current_labeled_block \
|
||||
&& LABELED_BLOCK_BODY (ctxp->current_labeled_block) == (LOOP))
|
||||
|
||||
/* Same operation than the one performed above, but considering the
|
||||
previous labeled block */
|
||||
#define LOOP_HAS_LABEL_SKIP_P(LOOP) \
|
||||
(ctxp->current_labeled_block \
|
||||
&& TREE_CHAIN (ctxp->current_labeled_block) \
|
||||
&& LABELED_BLOCK_BODY (TREE_CHAIN (ctxp->current_labeled_block)) == (LOOP))
|
||||
|
||||
#define PUSH_LABELED_BLOCK(B) \
|
||||
{ \
|
||||
TREE_CHAIN (B) = ctxp->current_labeled_block; \
|
||||
ctxp->current_labeled_block = (B); \
|
||||
}
|
||||
#define POP_LABELED_BLOCK() \
|
||||
ctxp->current_labeled_block = TREE_CHAIN (ctxp->current_labeled_block)
|
||||
|
||||
#define PUSH_LOOP(L) \
|
||||
{ \
|
||||
TREE_CHAIN (L) = ctxp->current_loop; \
|
||||
ctxp->current_loop = (L); \
|
||||
}
|
||||
#define POP_LOOP() ctxp->current_loop = TREE_CHAIN (ctxp->current_loop)
|
||||
|
||||
|
||||
/* Invocation modes, as returned by invocation_mode (). */
|
||||
enum {
|
||||
INVOKE_STATIC,
|
||||
INVOKE_NONVIRTUAL,
|
||||
INVOKE_SUPER,
|
||||
INVOKE_INTERFACE,
|
||||
INVOKE_VIRTUAL,
|
||||
};
|
||||
|
||||
/* We need the resolution stuff only if we compile jc1 */
|
||||
#ifndef JC1_LITE
|
||||
|
||||
/* Unresolved type identifiers handling. When we process the source
|
||||
code, we blindly accept an unknown type identifier and try to
|
||||
resolve it later. When an unknown type identifier is encountered
|
||||
and used, we record in a struct jdep element what the incomplete
|
||||
type is and what it should patch. Later, java_complete_class will
|
||||
process all classes known to have unresolved type
|
||||
dependencies. Within each of these classes, this routine will
|
||||
process unresolved type dependencies (JDEP_TO_RESOLVE), patch what
|
||||
needs to be patched in the dependent tree node (JDEP_GET_PATCH,
|
||||
JDEP_APPLY_PATCH) and perform other actions dictated by the context
|
||||
of the patch (JDEP_KIND). The ideas are: we patch only what needs
|
||||
to be patched, and with java_complete_class called at the right
|
||||
time, we will start processing incomplete function bodies tree
|
||||
nodes with everything external to function's bodies already
|
||||
completed, it makes things much simpler. */
|
||||
|
||||
enum jdep_code {
|
||||
JDEP_NO_PATCH, /* Must be first */
|
||||
JDEP_SUPER, /* Patch the type of one type
|
||||
supertype. Requires some check
|
||||
before it's done */
|
||||
JDEP_FIELD, /* Patch the type of a class field */
|
||||
|
||||
/* JDEP_{METHOD,METHOD_RETURN,METHOD_END} to be kept in order */
|
||||
JDEP_METHOD, /* Mark the beginning of the patching
|
||||
of a method declaration, including
|
||||
it's arguments */
|
||||
JDEP_METHOD_RETURN, /* Mark the beginning of the patching
|
||||
of a method declaration. Arguments
|
||||
aren't patched, only the returned
|
||||
type is */
|
||||
JDEP_METHOD_END, /* Mark the end of the patching of a
|
||||
method declaration. It indicates
|
||||
that it's time to compute and
|
||||
install a new signature */
|
||||
|
||||
JDEP_INTERFACE, /* Patch the type of a Class/interface
|
||||
extension */
|
||||
JDEP_VARIABLE, /* Patch the type of a variable declaration */
|
||||
JDEP_PARM, /* Patch the type of a parm declaration */
|
||||
JDEP_TYPE, /* Patch a random tree node type,
|
||||
without the need for any specific
|
||||
actions */
|
||||
};
|
||||
|
||||
typedef struct _jdep {
|
||||
#ifdef ONLY_INT_FIELDS
|
||||
int kind : 8; /* Type of patch */
|
||||
#else
|
||||
enum jdep_code kind : 8;
|
||||
#endif
|
||||
|
||||
int flag0 : 1; /* Some flags */
|
||||
tree decl; /* Tied decl/or WFL */
|
||||
tree solv; /* What to solve */
|
||||
tree wfl; /* Where thing to resolve where found */
|
||||
tree misc; /* Miscellaneous info (optional). */
|
||||
tree *patch; /* Address of a location to patch */
|
||||
struct _jdep *next; /* Linked list */
|
||||
} jdep;
|
||||
|
||||
|
||||
#define JDEP_DECL(J) ((J)->decl)
|
||||
#define JDEP_DECL_WFL(J) ((J)->decl)
|
||||
#define JDEP_KIND(J) ((J)->kind)
|
||||
#define JDEP_SOLV(J) ((J)->solv)
|
||||
#define JDEP_WFL(J) ((J)->wfl)
|
||||
#define JDEP_MISC(J) ((J)->misc)
|
||||
#define JDEP_CLASS(J) ((J)->class)
|
||||
#define JDEP_APPLY_PATCH(J,P) (*(J)->patch = (P))
|
||||
#define JDEP_GET_PATCH(J) ((J)->patch)
|
||||
#define JDEP_CHAIN(J) ((J)->next)
|
||||
#define JDEP_TO_RESOLVE(J) (TREE_PURPOSE ((J)->solv))
|
||||
#define JDEP_RESOLVED_DECL(J) ((J)->solv ? TREE_PURPOSE ((J)->solv):NULL_TREE)
|
||||
#define JDEP_RESOLVED(J, D) \
|
||||
{ \
|
||||
TREE_PURPOSE ((J)->solv) = D; \
|
||||
TREE_VALUE ((J)->solv) = (J)->solv; \
|
||||
}
|
||||
#define JDEP_RESOLVED_P(J) (!(J)->solv || \
|
||||
TREE_VALUE ((J)->solv) == (J)->solv)
|
||||
|
||||
typedef struct _jdeplist {
|
||||
jdep *first;
|
||||
jdep *last;
|
||||
struct _jdeplist *next;
|
||||
} jdeplist;
|
||||
static jdeplist *reverse_jdep_list ();
|
||||
|
||||
#endif /* JC1_LITE */
|
||||
|
||||
#define CLASSD_FIRST(CD) ((CD)->first)
|
||||
#define CLASSD_LAST(CD) ((CD)->last)
|
||||
#define CLASSD_CHAIN(CD) ((CD)->next)
|
||||
|
||||
#define JDEP_INSERT(L,J) \
|
||||
{ \
|
||||
if (!(L)->first) \
|
||||
(L)->last = (L)->first = (J); \
|
||||
else \
|
||||
{ \
|
||||
JDEP_CHAIN ((L)->last) = (J); \
|
||||
(L)->last = (J); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Insert a DECL in the current block */
|
||||
#define BLOCK_CHAIN_DECL(NODE) \
|
||||
{ \
|
||||
TREE_CHAIN ((NODE)) = \
|
||||
BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (current_function_decl)); \
|
||||
BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (current_function_decl)) = (NODE); \
|
||||
}
|
||||
|
||||
#define BLOCK_EXPR_DECLS(NODE) BLOCK_VARS(NODE)
|
||||
#define BLOCK_EXPR_BODY(NODE) BLOCK_SUBBLOCKS(NODE)
|
||||
#define BLOCK_EXPR_ORIGIN(NODE) BLOCK_ABSTRACT_ORIGIN(NODE)
|
||||
|
||||
/* Merge an other line to the source line number of a decl. Used to
|
||||
remember function's end. */
|
||||
#define DECL_SOURCE_LINE_MERGE(DECL,NO) DECL_SOURCE_LINE(DECL) |= (NO << 16)
|
||||
|
||||
/* Retrieve those two info separately. */
|
||||
#define DECL_SOURCE_LINE_FIRST(DECL) (DECL_SOURCE_LINE(DECL) & 0x0000ffff)
|
||||
#define DECL_SOURCE_LINE_LAST(DECL) (DECL_SOURCE_LINE(DECL) >> 16)
|
||||
|
||||
/* Build a WFL for expression nodes */
|
||||
#define BUILD_EXPR_WFL(NODE, WFL) \
|
||||
build_expr_wfl ((NODE), input_filename, EXPR_WFL_LINENO ((WFL)), \
|
||||
EXPR_WFL_COLNO ((WFL)))
|
||||
|
||||
#define EXPR_WFL_QUALIFICATION(WFL) TREE_OPERAND ((WFL), 1)
|
||||
#define QUAL_WFL(NODE) TREE_PURPOSE (NODE)
|
||||
#define QUAL_RESOLUTION(NODE) TREE_VALUE (NODE)
|
||||
#define QUAL_DECL_TYPE(NODE) \
|
||||
(TREE_CODE (TREE_TYPE (NODE)) == POINTER_TYPE ? \
|
||||
TREE_TYPE (TREE_TYPE (NODE)) : TREE_TYPE (NODE))
|
||||
|
||||
/* Handy macros for the walk operation */
|
||||
#define COMPLETE_CHECK_OP(NODE, N) \
|
||||
{ \
|
||||
TREE_OPERAND ((NODE), (N)) = \
|
||||
java_complete_tree (TREE_OPERAND ((NODE), (N))); \
|
||||
if (TREE_OPERAND ((NODE), (N)) == error_mark_node) \
|
||||
return error_mark_node; \
|
||||
}
|
||||
#define COMPLETE_CHECK_OP_0(NODE) COMPLETE_CHECK_OP(NODE, 0)
|
||||
#define COMPLETE_CHECK_OP_1(NODE) COMPLETE_CHECK_OP(NODE, 1)
|
||||
|
||||
/* Parser context data structure. */
|
||||
struct parser_ctxt {
|
||||
|
||||
char *filename; /* Current filename */
|
||||
FILE *finput; /* Current file input stream */
|
||||
struct parser_ctxt *next;
|
||||
|
||||
struct java_line *p_line, *c_line; /* Previous and current line */
|
||||
java_lc elc; /* Error's line column info */
|
||||
unicode_t unget_utf8_value; /* An unget utf8 value */
|
||||
int ccb_indent; /* Keep track of {} indent, lexer */
|
||||
int first_ccb_indent1; /* First { at ident level 1 */
|
||||
int last_ccb_indent1; /* Last } at ident level 1 */
|
||||
int parser_ccb_indent; /* Keep track of {} indent, parser */
|
||||
int osb_number; /* Keep track of ['s */
|
||||
int minus_seen; /* Integral literal overflow */
|
||||
int lineno; /* Current lineno */
|
||||
int java_error_flag; /* Report error when true */
|
||||
|
||||
/* This section is defined only if we compile jc1 */
|
||||
#ifndef JC1_LITE
|
||||
tree modifier_ctx [11]; /* WFL of modifiers */
|
||||
tree current_class; /* Current class */
|
||||
tree current_function_decl; /* Current function decl, save/restore */
|
||||
|
||||
JCF *current_jcf; /* CU jcf */
|
||||
|
||||
int prevent_ese; /* Prevent expression statement error */
|
||||
int class_err; /* Flag to report certain errors */
|
||||
|
||||
int formal_parameter_number; /* Number of parameters found */
|
||||
int interface_number; /* # itfs declared to extend an itf def */
|
||||
|
||||
tree package; /* Defined package ID */
|
||||
|
||||
tree incomplete_class; /* List of non-complete classes */
|
||||
tree current_parsed_class; /* Class currently parsed */
|
||||
tree class_list; /* List of classes in a CU */
|
||||
jdeplist *classd_list; /* Classe dependencies in a CU */
|
||||
|
||||
tree non_static_initialized; /* List of non static initialized fields */
|
||||
tree static_initialized; /* List of static non final initialized */
|
||||
|
||||
tree import_list; /* List of import */
|
||||
tree import_demand_list; /* List of import on demand */
|
||||
|
||||
tree current_loop; /* List of the currently nested loops */
|
||||
tree current_labeled_block; /* List of currently nested
|
||||
labeled blocks. */
|
||||
|
||||
int pending_block; /* Pending block to close */
|
||||
#endif /* JC1_LITE */
|
||||
};
|
||||
|
||||
/* Functions declarations */
|
||||
#ifndef JC1_LITE
|
||||
static char *java_accstring_lookup PROTO ((int));
|
||||
static void parse_error PROTO ((char *));
|
||||
static void redefinition_error PROTO ((char *,tree, tree, tree));
|
||||
static void check_modifiers PROTO ((char *, int, int));
|
||||
static tree create_class PROTO ((int, tree, tree, tree));
|
||||
static tree create_interface PROTO ((int, tree, tree));
|
||||
static tree find_field PROTO ((tree, tree));
|
||||
static tree lookup_field_wrapper PROTO ((tree, tree));
|
||||
static int duplicate_declaration_error PROTO ((tree, tree, tree, tree));
|
||||
static void register_fields PROTO ((int, tree, tree));
|
||||
static tree parser_qualified_classname PROTO ((tree));
|
||||
static int parser_check_super PROTO ((tree, tree, tree));
|
||||
static int parser_check_super_interface PROTO ((tree, tree, tree));
|
||||
static void check_modifiers_consistency PROTO ((int));
|
||||
static tree lookup_cl PROTO ((tree));
|
||||
static tree lookup_java_method2 PROTO ((tree, tree, int));
|
||||
static tree method_header PROTO ((int, tree, tree, tree));
|
||||
static tree method_declarator PROTO ((tree, tree));
|
||||
static void parse_error_context VPROTO ((tree cl, char *msg, ...));
|
||||
static void parse_warning_context VPROTO ((tree cl, char *msg, ...));
|
||||
static void complete_class_report_errors PROTO ((jdep *));
|
||||
static int process_imports PROTO ((void));
|
||||
static void read_import_dir PROTO ((tree));
|
||||
static int find_in_imports_on_demand PROTO ((tree));
|
||||
static int find_in_imports PROTO ((tree));
|
||||
static int check_pkg_class_access PROTO ((tree, tree));
|
||||
static tree resolve_class PROTO ((tree, tree, tree));
|
||||
static tree do_resolve_class PROTO ((tree, tree, tree));
|
||||
static void declare_local_variables PROTO ((int, tree, tree));
|
||||
static void source_start_java_method PROTO ((tree));
|
||||
static void source_end_java_method PROTO ((void));
|
||||
static void expand_start_java_method PROTO ((tree));
|
||||
static tree find_name_in_single_imports PROTO ((tree));
|
||||
static void check_abstract_method_header PROTO ((tree));
|
||||
static tree lookup_java_interface_method2 PROTO ((tree, tree));
|
||||
static tree resolve_expression_name PROTO ((tree));
|
||||
static tree maybe_create_class_interface_decl PROTO ((tree, tree, tree));
|
||||
static int check_class_interface_creation PROTO ((int, int, tree, tree, tree, tree));
|
||||
static tree patch_method_invocation_stmt PROTO ((tree, tree, tree, int *));
|
||||
static int breakdown_qualified PROTO ((tree *, tree *, tree));
|
||||
static tree resolve_and_layout PROTO ((tree, tree));
|
||||
static tree resolve_no_layout PROTO ((tree, tree));
|
||||
static int identical_subpath_p PROTO ((tree, tree));
|
||||
static int invocation_mode PROTO ((tree, int));
|
||||
static tree refine_accessible_methods_list PROTO ((int, tree));
|
||||
static tree patch_invoke PROTO ((tree, tree, tree, tree));
|
||||
static tree lookup_method_invoke PROTO ((int, tree, tree, tree, tree));
|
||||
static tree register_incomplete_type PROTO ((int, tree, tree, tree));
|
||||
static tree obtain_incomplete_type PROTO ((tree));
|
||||
static tree java_complete_tree PROTO ((tree));
|
||||
static void java_complete_expand_method PROTO ((tree));
|
||||
static int unresolved_type_p PROTO ((tree, tree *));
|
||||
static void create_jdep_list PROTO ((struct parser_ctxt *));
|
||||
static tree build_expr_block PROTO ((tree, tree));
|
||||
static tree enter_block PROTO ((void));
|
||||
static tree exit_block PROTO ((void));
|
||||
static tree lookup_name_in_blocks PROTO ((tree));
|
||||
static void maybe_absorb_scoping_blocks PROTO ((void));
|
||||
static tree build_method_invocation PROTO ((tree, tree));
|
||||
static tree build_assignment PROTO ((int, int, tree, tree));
|
||||
static tree build_binop PROTO ((enum tree_code, int, tree, tree));
|
||||
static tree patch_assignment PROTO ((tree, tree, tree ));
|
||||
static tree patch_binop PROTO ((tree, tree, tree));
|
||||
static tree build_unaryop PROTO ((int, int, tree));
|
||||
static tree build_incdec PROTO ((int, int, tree, int));
|
||||
static tree patch_unaryop PROTO ((tree, tree));
|
||||
static tree build_cast PROTO ((int, tree, tree));
|
||||
static tree patch_cast PROTO ((tree, tree, tree));
|
||||
static int valid_ref_assignconv_cast_p PROTO ((tree, tree, int));
|
||||
static int can_cast_to_p PROTO ((tree, tree));
|
||||
static tree build_unresolved_array_type PROTO ((tree));
|
||||
static tree build_array_ref PROTO ((int, tree, tree));
|
||||
static tree patch_array_ref PROTO ((tree, tree, tree));
|
||||
static tree make_qualified_name PROTO ((tree, tree, int));
|
||||
static tree merge_qualified_name PROTO ((tree, tree));
|
||||
static tree make_qualified_primary PROTO ((tree, tree, int));
|
||||
static int resolve_qualified_expression_name PROTO ((tree, tree *, tree *, tree *));
|
||||
static void qualify_ambiguous_name PROTO ((tree));
|
||||
static void maybe_generate_clinit PROTO ((void));
|
||||
static tree resolve_field_access PROTO ((tree, tree *, tree *));
|
||||
static tree build_newarray_node PROTO ((tree, tree, int));
|
||||
static tree patch_newarray PROTO ((tree));
|
||||
static tree resolve_type_during_patch PROTO ((tree));
|
||||
static int not_initialized_as_it_should_p PROTO ((tree));
|
||||
static tree build_this PROTO ((int));
|
||||
static tree build_return PROTO ((int, tree));
|
||||
static tree patch_return PROTO ((tree));
|
||||
static tree maybe_access_field PROTO ((tree, tree, tree));
|
||||
static int complete_function_arguments PROTO ((tree));
|
||||
static int check_for_static_method_reference PROTO ((tree, tree, tree, tree, tree));
|
||||
static int not_accessible_p PROTO ((tree, tree, int));
|
||||
static int class_in_current_package PROTO ((tree));
|
||||
static tree build_if_else_statement PROTO ((int, tree, tree, tree));
|
||||
static tree patch_if_else_statement PROTO ((tree));
|
||||
static tree add_stmt_to_compound PROTO ((tree, tree, tree));
|
||||
static tree patch_exit_expr PROTO ((tree));
|
||||
static tree build_labeled_block PROTO ((int, tree, tree));
|
||||
static tree generate_labeled_block PROTO (());
|
||||
static tree complete_labeled_statement PROTO ((tree, tree));
|
||||
static tree build_bc_statement PROTO ((int, int, tree));
|
||||
static tree patch_bc_statement PROTO ((tree));
|
||||
static tree patch_loop_statement PROTO ((tree));
|
||||
static tree build_new_loop PROTO ((tree));
|
||||
static tree build_loop_body PROTO ((int, tree, int));
|
||||
static tree complete_loop_body PROTO ((int, tree, tree, int));
|
||||
static tree build_debugable_stmt PROTO ((int, tree));
|
||||
static tree complete_for_loop PROTO ((int, tree, tree, tree));
|
||||
|
||||
void safe_layout_class PROTO ((tree));
|
||||
void java_complete_class PROTO ((void));
|
||||
void java_check_circular_reference PROTO ((void));
|
||||
void java_check_final PROTO ((void));
|
||||
void java_check_methods PROTO ((void));
|
||||
void java_layout_classes PROTO ((void));
|
||||
tree java_method_add_stmt PROTO ((tree, tree));
|
||||
char *java_get_line_col PROTO ((char *, int, int));
|
||||
#endif /* JC1_LITE */
|
||||
|
||||
/* Always in use, no matter what you compile */
|
||||
|
||||
void java_push_parser_context PROTO ((void));
|
||||
void java_init_lex PROTO ((void));
|
||||
int yyparse PROTO ((void));
|
||||
int yylex ();
|
||||
void yyerror PROTO ((char *));
|
||||
|
||||
#endif
|
8035
gcc/java/parse.y
Normal file
8035
gcc/java/parse.y
Normal file
File diff suppressed because it is too large
Load diff
785
gcc/java/typeck.c
Normal file
785
gcc/java/typeck.c
Normal file
|
@ -0,0 +1,785 @@
|
|||
/* Handle types for the GNU compiler for the Java(TM) language.
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* Written by Per Bothner <bothner@cygnus.com> */
|
||||
|
||||
#include "config.h"
|
||||
#include "tree.h"
|
||||
#include "obstack.h"
|
||||
#include "java-tree.h"
|
||||
#include "jcf.h"
|
||||
#include "convert.h"
|
||||
|
||||
tree * type_map;
|
||||
extern struct obstack permanent_obstack;
|
||||
|
||||
/* Set the type of the local variable with index SLOT to TYPE. */
|
||||
|
||||
void
|
||||
set_local_type (slot, type)
|
||||
int slot;
|
||||
tree type;
|
||||
{
|
||||
int max_locals = DECL_MAX_LOCALS(current_function_decl);
|
||||
int nslots = TYPE_IS_WIDE (type) ? 2 : 1;
|
||||
if (slot < 0 || slot + nslots - 1 >= max_locals)
|
||||
fatal ("invalid local variable index");
|
||||
type_map[slot] = type;
|
||||
while (--nslots > 0)
|
||||
type_map[++slot] = void_type_node;
|
||||
}
|
||||
|
||||
extern tree convert_to_integer (tree type, tree expr);
|
||||
extern tree convert_to_real (tree type, tree expr);
|
||||
extern tree convert_to_pointer (tree type, tree expr);
|
||||
|
||||
/* Create an expression whose value is that of EXPR,
|
||||
converted to type TYPE. The TREE_TYPE of the value
|
||||
is always TYPE. This function implements all reasonable
|
||||
conversions; callers should filter out those that are
|
||||
not permitted by the language being compiled. */
|
||||
|
||||
tree
|
||||
convert (type, expr)
|
||||
tree type, expr;
|
||||
{
|
||||
register enum tree_code code = TREE_CODE (type);
|
||||
|
||||
if (type == TREE_TYPE (expr)
|
||||
|| TREE_CODE (expr) == ERROR_MARK)
|
||||
return expr;
|
||||
if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
|
||||
return error_mark_node;
|
||||
if (code == BOOLEAN_TYPE)
|
||||
return fold (convert_to_boolean (type, expr));
|
||||
if (code == INTEGER_TYPE)
|
||||
return fold (convert_to_integer (type, expr));
|
||||
if (code == REAL_TYPE)
|
||||
return fold (convert_to_real (type, expr));
|
||||
if (code == CHAR_TYPE)
|
||||
return fold (convert_to_char (type, expr));
|
||||
if (code == POINTER_TYPE)
|
||||
return fold (convert_to_pointer (type, expr));
|
||||
error ("conversion to non-scalar type requested");
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
tree
|
||||
convert_to_char (type, expr)
|
||||
tree type, expr;
|
||||
{
|
||||
return build1 (NOP_EXPR, type, expr);
|
||||
}
|
||||
|
||||
tree
|
||||
convert_to_boolean (type, expr)
|
||||
tree type, expr;
|
||||
{
|
||||
return build1 (NOP_EXPR, type, expr);
|
||||
}
|
||||
|
||||
/* Print an error message for invalid use of an incomplete type.
|
||||
VALUE is the expression that was used (or 0 if that isn't known)
|
||||
and TYPE is the type that was invalid. */
|
||||
|
||||
void
|
||||
incomplete_type_error (value, type)
|
||||
tree value;
|
||||
tree type;
|
||||
{
|
||||
error ("internal error - use of undefined type");
|
||||
}
|
||||
|
||||
/* Return a data type that has machine mode MODE.
|
||||
If the mode is an integer,
|
||||
then UNSIGNEDP selects between signed and unsigned types. */
|
||||
|
||||
tree
|
||||
type_for_mode (mode, unsignedp)
|
||||
enum machine_mode mode;
|
||||
int unsignedp;
|
||||
{
|
||||
if (mode == TYPE_MODE (int_type_node))
|
||||
return unsignedp ? unsigned_int_type_node : int_type_node;
|
||||
if (mode == TYPE_MODE (long_type_node))
|
||||
return unsignedp ? unsigned_long_type_node : long_type_node;
|
||||
if (mode == TYPE_MODE (short_type_node))
|
||||
return unsignedp ? unsigned_short_type_node : short_type_node;
|
||||
if (mode == TYPE_MODE (byte_type_node))
|
||||
return unsignedp ? unsigned_byte_type_node : byte_type_node;
|
||||
if (mode == TYPE_MODE (float_type_node))
|
||||
return float_type_node;
|
||||
if (mode == TYPE_MODE (double_type_node))
|
||||
return double_type_node;
|
||||
|
||||
#if 0
|
||||
if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
|
||||
return build_pointer_type (char_type_node);
|
||||
|
||||
if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
|
||||
return build_pointer_type (integer_type_node);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return an integer type with BITS bits of precision,
|
||||
that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */
|
||||
|
||||
tree
|
||||
type_for_size (bits, unsignedp)
|
||||
unsigned bits;
|
||||
int unsignedp;
|
||||
{
|
||||
if (bits <= TYPE_PRECISION (byte_type_node))
|
||||
return unsignedp ? unsigned_byte_type_node : byte_type_node;
|
||||
if (bits <= TYPE_PRECISION (short_type_node))
|
||||
return unsignedp ? unsigned_short_type_node : short_type_node;
|
||||
if (bits <= TYPE_PRECISION (int_type_node))
|
||||
return unsignedp ? unsigned_int_type_node : int_type_node;
|
||||
if (bits <= TYPE_PRECISION (long_type_node))
|
||||
return unsignedp ? unsigned_long_type_node : long_type_node;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return a type the same as TYPE except unsigned or
|
||||
signed according to UNSIGNEDP. */
|
||||
|
||||
tree
|
||||
signed_or_unsigned_type (unsignedp, type)
|
||||
int unsignedp;
|
||||
tree type;
|
||||
{
|
||||
if (! INTEGRAL_TYPE_P (type))
|
||||
return type;
|
||||
if (TYPE_PRECISION (type) == TYPE_PRECISION (int_type_node))
|
||||
return unsignedp ? unsigned_int_type_node : int_type_node;
|
||||
if (TYPE_PRECISION (type) == TYPE_PRECISION (byte_type_node))
|
||||
return unsignedp ? unsigned_byte_type_node : byte_type_node;
|
||||
if (TYPE_PRECISION (type) == TYPE_PRECISION (short_type_node))
|
||||
return unsignedp ? unsigned_short_type_node : short_type_node;
|
||||
if (TYPE_PRECISION (type) == TYPE_PRECISION (long_type_node))
|
||||
return unsignedp ? unsigned_long_type_node : long_type_node;
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Return a signed type the same as TYPE in other respects. */
|
||||
|
||||
tree
|
||||
signed_type (type)
|
||||
tree type;
|
||||
{
|
||||
return signed_or_unsigned_type (0, type);
|
||||
}
|
||||
|
||||
/* Return an unsigned type the same as TYPE in other respects. */
|
||||
|
||||
tree
|
||||
unsigned_type (type)
|
||||
tree type;
|
||||
{
|
||||
return signed_or_unsigned_type (1, type);
|
||||
|
||||
}
|
||||
|
||||
/* Mark EXP saying that we need to be able to take the
|
||||
address of it; it should not be allocated in a register.
|
||||
Value is 1 if successful. */
|
||||
|
||||
int
|
||||
mark_addressable (exp)
|
||||
tree exp;
|
||||
{
|
||||
register tree x = exp;
|
||||
while (1)
|
||||
switch (TREE_CODE (x))
|
||||
{
|
||||
case ADDR_EXPR:
|
||||
case COMPONENT_REF:
|
||||
case ARRAY_REF:
|
||||
case REALPART_EXPR:
|
||||
case IMAGPART_EXPR:
|
||||
x = TREE_OPERAND (x, 0);
|
||||
break;
|
||||
|
||||
case TRUTH_ANDIF_EXPR:
|
||||
case TRUTH_ORIF_EXPR:
|
||||
case COMPOUND_EXPR:
|
||||
x = TREE_OPERAND (x, 1);
|
||||
break;
|
||||
|
||||
case COND_EXPR:
|
||||
return mark_addressable (TREE_OPERAND (x, 1))
|
||||
& mark_addressable (TREE_OPERAND (x, 2));
|
||||
|
||||
case CONSTRUCTOR:
|
||||
TREE_ADDRESSABLE (x) = 1;
|
||||
return 1;
|
||||
|
||||
case INDIRECT_REF:
|
||||
/* We sometimes add a cast *(TYPE*)&FOO to handle type and mode
|
||||
incompatibility problems. Handle this case by marking FOO. */
|
||||
if (TREE_CODE (TREE_OPERAND (x, 0)) == NOP_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (x, 0), 0)) == ADDR_EXPR)
|
||||
{
|
||||
x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
|
||||
break;
|
||||
}
|
||||
if (TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
|
||||
{
|
||||
x = TREE_OPERAND (x, 0);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case VAR_DECL:
|
||||
case CONST_DECL:
|
||||
case PARM_DECL:
|
||||
case RESULT_DECL:
|
||||
case FUNCTION_DECL:
|
||||
TREE_ADDRESSABLE (x) = 1;
|
||||
#if 0 /* poplevel deals with this now. */
|
||||
if (DECL_CONTEXT (x) == 0)
|
||||
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
|
||||
#endif
|
||||
/* drops through */
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Thorough checking of the arrayness of TYPE. */
|
||||
|
||||
int
|
||||
is_array_type_p (type)
|
||||
tree type;
|
||||
{
|
||||
return TREE_CODE (type) == POINTER_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
|
||||
&& TYPE_ARRAY_P (TREE_TYPE (type));
|
||||
}
|
||||
|
||||
/* Return the length of a Java array type.
|
||||
Return -1 if the length is unknown or non-constant. */
|
||||
|
||||
HOST_WIDE_INT
|
||||
java_array_type_length (array_type)
|
||||
tree array_type;
|
||||
{
|
||||
tree arfld;
|
||||
if (TREE_CODE (array_type) == POINTER_TYPE)
|
||||
array_type = TREE_TYPE (array_type);
|
||||
arfld = TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (array_type)));
|
||||
if (arfld != NULL_TREE)
|
||||
{
|
||||
tree index_type = TYPE_DOMAIN (TREE_TYPE (arfld));
|
||||
tree high = TYPE_MAX_VALUE (index_type);
|
||||
if (TREE_CODE (high) == INTEGER_CST)
|
||||
return TREE_INT_CST_LOW (high) + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
tree
|
||||
build_prim_array_type (element_type, length)
|
||||
tree element_type;
|
||||
HOST_WIDE_INT length;
|
||||
{
|
||||
tree max_index = build_int_2 (length - 1, 0);
|
||||
TREE_TYPE (max_index) = sizetype;
|
||||
return build_array_type (element_type, build_index_type (max_index));
|
||||
}
|
||||
|
||||
/* Return a Java array type with a given ELEMENT_TYPE and LENGTH.
|
||||
These are hashed (shared) using IDENTIFIER_SIGNATURE_TYPE.
|
||||
The LENGTH is -1 if the length is unknown. */
|
||||
|
||||
tree
|
||||
build_java_array_type (element_type, length)
|
||||
tree element_type;
|
||||
HOST_WIDE_INT length;
|
||||
{
|
||||
tree sig, t, fld;
|
||||
char buf[12];
|
||||
tree elsig = build_java_signature (element_type);
|
||||
tree el_name = element_type;
|
||||
sprintf (buf, length >= 0 ? "[%d" : "[", length);
|
||||
sig = ident_subst (IDENTIFIER_POINTER (elsig), IDENTIFIER_LENGTH (elsig),
|
||||
buf, 0, 0, "");
|
||||
t = IDENTIFIER_SIGNATURE_TYPE (sig);
|
||||
if (t != NULL_TREE)
|
||||
return t;
|
||||
t = make_class ();
|
||||
IDENTIFIER_SIGNATURE_TYPE (sig) = t;
|
||||
TYPE_ARRAY_P (t) = 1;
|
||||
|
||||
if (TREE_CODE (el_name) == POINTER_TYPE)
|
||||
el_name = TREE_TYPE (el_name);
|
||||
el_name = TYPE_NAME (el_name);
|
||||
if (TREE_CODE (el_name) == TYPE_DECL)
|
||||
el_name = DECL_NAME (el_name);
|
||||
TYPE_NAME (t) = identifier_subst (el_name, "", '.', '.', "[]");
|
||||
|
||||
set_java_signature (t, sig);
|
||||
set_super_info (0, t, object_type_node, 0);
|
||||
TYPE_ARRAY_ELEMENT (t) = element_type;
|
||||
|
||||
/* Add length pseudo-field. */
|
||||
push_obstacks (&permanent_obstack, &permanent_obstack);
|
||||
fld = build_decl (FIELD_DECL, get_identifier ("length"), int_type_node);
|
||||
TYPE_FIELDS (t) = fld;
|
||||
DECL_CONTEXT (fld) = t;
|
||||
FIELD_PUBLIC (fld) = 1;
|
||||
FIELD_FINAL (fld) = 1;
|
||||
|
||||
if (length >= 0)
|
||||
{
|
||||
tree atype = build_prim_array_type (element_type, length);
|
||||
tree arfld = build_decl (FIELD_DECL, get_identifier ("data"), atype);
|
||||
DECL_CONTEXT (arfld) = t;
|
||||
TREE_CHAIN (fld) = arfld;
|
||||
}
|
||||
else
|
||||
TYPE_ALIGN (t) = TYPE_ALIGN (element_type);
|
||||
pop_obstacks ();
|
||||
|
||||
layout_class (t);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Promote TYPE to the type actually used for fields and parameters. */
|
||||
|
||||
tree
|
||||
promote_type (type)
|
||||
tree type;
|
||||
{
|
||||
switch (TREE_CODE (type))
|
||||
{
|
||||
case RECORD_TYPE:
|
||||
return build_pointer_type (CLASS_TO_HANDLE_TYPE (type));
|
||||
case BOOLEAN_TYPE:
|
||||
if (type == boolean_type_node)
|
||||
return promoted_boolean_type_node;
|
||||
goto handle_int;
|
||||
case CHAR_TYPE:
|
||||
if (type == char_type_node)
|
||||
return promoted_char_type_node;
|
||||
goto handle_int;
|
||||
case INTEGER_TYPE:
|
||||
handle_int:
|
||||
if (TYPE_PRECISION (type) < TYPE_PRECISION (int_type_node))
|
||||
{
|
||||
if (type == short_type_node)
|
||||
return promoted_short_type_node;
|
||||
if (type == byte_type_node)
|
||||
return promoted_byte_type_node;
|
||||
return int_type_node;
|
||||
}
|
||||
/* ... else fall through ... */
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse a signature string, starting at *PTR and ending at LIMIT.
|
||||
Return the seen TREE_TYPE, updating *PTR. */
|
||||
|
||||
static tree
|
||||
parse_signature_type (ptr, limit)
|
||||
const unsigned char **ptr, *limit;
|
||||
{
|
||||
if ((*ptr) >= limit)
|
||||
fatal ("bad signature string");
|
||||
switch (*(*ptr))
|
||||
{
|
||||
case 'B': (*ptr)++; return byte_type_node;
|
||||
case 'C': (*ptr)++; return char_type_node;
|
||||
case 'D': (*ptr)++; return double_type_node;
|
||||
case 'F': (*ptr)++; return float_type_node;
|
||||
case 'S': (*ptr)++; return short_type_node;
|
||||
case 'I': (*ptr)++; return int_type_node;
|
||||
case 'J': (*ptr)++; return long_type_node;
|
||||
case 'Z': (*ptr)++; return boolean_type_node;
|
||||
case 'V': (*ptr)++; return void_type_node;
|
||||
case '[':
|
||||
for ((*ptr)++; (*ptr) < limit && isdigit (**ptr); ) (*ptr)++;
|
||||
{
|
||||
tree element_type = parse_signature_type (ptr, limit);
|
||||
if (TREE_CODE (element_type) == RECORD_TYPE)
|
||||
element_type = promote_type (element_type);
|
||||
return build_java_array_type (element_type, -1);
|
||||
}
|
||||
case 'L':
|
||||
{
|
||||
const unsigned char *start = ++(*ptr);
|
||||
register const unsigned char *str = start;
|
||||
for ( ; ; str++)
|
||||
{
|
||||
if (str >= limit)
|
||||
fatal ("bad signature string");
|
||||
if (*str == ';')
|
||||
break;
|
||||
}
|
||||
*ptr = str+1;
|
||||
return lookup_class (unmangle_classname (start, str - start));
|
||||
}
|
||||
default:
|
||||
fatal ("unrecognized signature string");
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse a Java "mangled" signature string, starting at SIG_STRING,
|
||||
and SIG_LENGTH bytes long.
|
||||
Return a gcc type node. */
|
||||
|
||||
tree
|
||||
parse_signature_string (sig_string, sig_length)
|
||||
const unsigned char *sig_string;
|
||||
int sig_length;
|
||||
{
|
||||
tree result_type;
|
||||
const unsigned char *str = sig_string;
|
||||
const unsigned char *limit = str + sig_length;
|
||||
|
||||
push_obstacks (&permanent_obstack, &permanent_obstack);
|
||||
if (str < limit && str[0] == '(')
|
||||
{
|
||||
tree argtype_list = NULL_TREE;
|
||||
str++;
|
||||
while (str < limit && str[0] != ')')
|
||||
{
|
||||
tree argtype = promote_type (parse_signature_type (&str, limit));
|
||||
argtype_list = tree_cons (NULL_TREE, argtype, argtype_list);
|
||||
}
|
||||
if (str++, str >= limit)
|
||||
fatal ("bad signature string");
|
||||
result_type = promote_type (parse_signature_type (&str, limit));
|
||||
result_type = build_function_type (result_type,
|
||||
nreverse (argtype_list));
|
||||
}
|
||||
else
|
||||
result_type = parse_signature_type (&str, limit);
|
||||
if (str != limit)
|
||||
error ("junk at end of signature string");
|
||||
pop_obstacks ();
|
||||
return result_type;
|
||||
}
|
||||
|
||||
/* Convert a signature to its type.
|
||||
* Uses IDENTIFIER_SIGNATURE_TYPE as a cache (except for primitive types).
|
||||
*/
|
||||
|
||||
tree
|
||||
get_type_from_signature (tree signature)
|
||||
{
|
||||
unsigned char *sig = (unsigned char *) IDENTIFIER_POINTER (signature);
|
||||
int len = IDENTIFIER_LENGTH (signature);
|
||||
tree type;
|
||||
/* Primitive types aren't cached. */
|
||||
if (len <= 1)
|
||||
return parse_signature_string (sig, len);
|
||||
type = IDENTIFIER_SIGNATURE_TYPE (signature);
|
||||
if (type == NULL_TREE)
|
||||
{
|
||||
type = parse_signature_string (sig, len);
|
||||
IDENTIFIER_SIGNATURE_TYPE (signature) = type;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Return the signature string for the arguments of method type TYPE. */
|
||||
|
||||
tree
|
||||
build_java_argument_signature (type)
|
||||
tree type;
|
||||
{
|
||||
extern struct obstack temporary_obstack;
|
||||
tree sig = TYPE_ARGUMENT_SIGNATURE (type);
|
||||
if (sig == NULL_TREE)
|
||||
{
|
||||
tree args = TYPE_ARG_TYPES (type);
|
||||
if (TREE_CODE (type) == METHOD_TYPE)
|
||||
args = TREE_CHAIN (args); /* Skip "this" argument. */
|
||||
for (; args != NULL_TREE; args = TREE_CHAIN (args))
|
||||
{
|
||||
tree t = build_java_signature (TREE_VALUE (args));
|
||||
obstack_grow (&temporary_obstack,
|
||||
IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t));
|
||||
}
|
||||
obstack_1grow (&temporary_obstack, '\0');
|
||||
|
||||
sig = get_identifier (obstack_base (&temporary_obstack));
|
||||
TYPE_ARGUMENT_SIGNATURE (type) = sig;
|
||||
obstack_free (&temporary_obstack, obstack_base (&temporary_obstack));
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
/* Return the signature of the given TYPE. */
|
||||
|
||||
tree
|
||||
build_java_signature (type)
|
||||
tree type;
|
||||
{
|
||||
tree sig, t;
|
||||
push_obstacks (&permanent_obstack, &permanent_obstack);
|
||||
while (TREE_CODE (type) == POINTER_TYPE)
|
||||
type = TREE_TYPE (type);
|
||||
if (TYPE_LANG_SPECIFIC (type) == NULL)
|
||||
{
|
||||
TYPE_LANG_SPECIFIC (type) = (struct lang_type *)
|
||||
perm_calloc (1, sizeof (struct lang_type));
|
||||
|
||||
}
|
||||
sig = TYPE_LANG_SPECIFIC (type)->signature;
|
||||
if (sig == NULL_TREE)
|
||||
{
|
||||
char sg[2];
|
||||
switch (TREE_CODE (type))
|
||||
{
|
||||
case BOOLEAN_TYPE: sg[0] = 'Z'; goto native;
|
||||
case CHAR_TYPE: sg[0] = 'C'; goto native;
|
||||
case VOID_TYPE: sg[0] = 'V'; goto native;
|
||||
case INTEGER_TYPE:
|
||||
switch (TYPE_PRECISION (type))
|
||||
{
|
||||
case 8: sg[0] = 'B'; goto native;
|
||||
case 16: sg[0] = 'S'; goto native;
|
||||
case 32: sg[0] = 'I'; goto native;
|
||||
case 64: sg[0] = 'J'; goto native;
|
||||
default: goto bad_type;
|
||||
}
|
||||
case REAL_TYPE:
|
||||
switch (TYPE_PRECISION (type))
|
||||
{
|
||||
case 32: sg[0] = 'F'; goto native;
|
||||
case 64: sg[0] = 'D'; goto native;
|
||||
default: goto bad_type;
|
||||
}
|
||||
native:
|
||||
sg[1] = 0;
|
||||
sig = get_identifier (sg);
|
||||
break;
|
||||
case RECORD_TYPE:
|
||||
if (TYPE_ARRAY_P (type))
|
||||
{
|
||||
t = build_java_signature (TYPE_ARRAY_ELEMENT (type));
|
||||
sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t),
|
||||
"[", 0, 0, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
t = DECL_NAME (TYPE_NAME (type));
|
||||
sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t),
|
||||
"L", '.', '/', ";");
|
||||
}
|
||||
break;
|
||||
case METHOD_TYPE:
|
||||
case FUNCTION_TYPE:
|
||||
{
|
||||
extern struct obstack temporary_obstack;
|
||||
sig = build_java_argument_signature (type);
|
||||
obstack_1grow (&temporary_obstack, '(');
|
||||
obstack_grow (&temporary_obstack,
|
||||
IDENTIFIER_POINTER (sig), IDENTIFIER_LENGTH (sig));
|
||||
obstack_1grow (&temporary_obstack, ')');
|
||||
|
||||
t = build_java_signature (TREE_TYPE (type));
|
||||
obstack_grow0 (&temporary_obstack,
|
||||
IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t));
|
||||
|
||||
sig = get_identifier (obstack_base (&temporary_obstack));
|
||||
obstack_free (&temporary_obstack,
|
||||
obstack_base (&temporary_obstack));
|
||||
}
|
||||
break;
|
||||
bad_type:
|
||||
default:
|
||||
fatal ("internal error - build_java_signature passed invalid type");
|
||||
}
|
||||
TYPE_LANG_SPECIFIC (type)->signature = sig;
|
||||
}
|
||||
pop_obstacks ();
|
||||
return sig;
|
||||
}
|
||||
|
||||
/* Save signature string SIG (an IDENTIFIER_NODE) in TYPE for future use. */
|
||||
|
||||
void
|
||||
set_java_signature (type, sig)
|
||||
tree type;
|
||||
tree sig;
|
||||
{
|
||||
tree old_sig;
|
||||
while (TREE_CODE (type) == POINTER_TYPE)
|
||||
type = TREE_TYPE (type);
|
||||
if (TYPE_LANG_SPECIFIC (type) == NULL)
|
||||
{
|
||||
TYPE_LANG_SPECIFIC (type) = (struct lang_type *)
|
||||
perm_calloc (1, sizeof (struct lang_type));
|
||||
|
||||
}
|
||||
old_sig = TYPE_LANG_SPECIFIC (type)->signature;
|
||||
if (old_sig != NULL_TREE && old_sig != sig)
|
||||
fatal ("internal error - set_java_signature");
|
||||
TYPE_LANG_SPECIFIC (type)->signature = sig;
|
||||
#if 0 /* careful about METHOD_TYPE */
|
||||
if (IDENTIFIER_SIGNATURE_TYPE (sig) == NULL_TREE && TREE_PERMANENT (type))
|
||||
IDENTIFIER_SIGNATURE_TYPE (sig) = type;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Search in class CLAS (and its superclasses) for a method
|
||||
matching METHOD_NAME and argument signature METHOD_SIGNATURE.
|
||||
Return a FUNCTION_DECL on success, or NULL_TREE if none found.
|
||||
(Contrast lookup_java_method, which takes into account return type.) */
|
||||
|
||||
tree
|
||||
lookup_argument_method (clas, method_name, method_signature)
|
||||
tree clas, method_name, method_signature;
|
||||
{
|
||||
tree method;
|
||||
while (clas != NULL_TREE)
|
||||
{
|
||||
for (method = TYPE_METHODS (clas);
|
||||
method != NULL_TREE; method = TREE_CHAIN (method))
|
||||
{
|
||||
tree method_sig = build_java_argument_signature (TREE_TYPE (method));
|
||||
if (DECL_NAME (method) == method_name && method_sig == method_signature)
|
||||
return method;
|
||||
}
|
||||
clas = CLASSTYPE_SUPER (clas);
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Search in class CLAS (and its superclasses) for a method
|
||||
matching METHOD_NAME and signature METHOD_SIGNATURE.
|
||||
Return a FUNCTION_DECL on success, or NULL_TREE if none found.
|
||||
(Contrast lookup_argument_method, which ignores return type.) */
|
||||
|
||||
tree
|
||||
lookup_java_method (clas, method_name, method_signature)
|
||||
tree clas, method_name, method_signature;
|
||||
{
|
||||
tree method;
|
||||
while (clas != NULL_TREE)
|
||||
{
|
||||
for (method = TYPE_METHODS (clas);
|
||||
method != NULL_TREE; method = TREE_CHAIN (method))
|
||||
{
|
||||
tree method_sig = build_java_signature (TREE_TYPE (method));
|
||||
if (DECL_NAME (method) == method_name && method_sig == method_signature)
|
||||
return method;
|
||||
}
|
||||
clas = CLASSTYPE_SUPER (clas);
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Search in class CLAS (and its superclasses) for methods matching
|
||||
METHOD_NAME and METHOD_SIGNATURE. Return a list of FUNCTION_DECLs.
|
||||
When called from here, build_java_signature doesn't take the
|
||||
returned type into account. */
|
||||
|
||||
tree
|
||||
match_java_method (clas, method_name, method_signature)
|
||||
tree clas, method_name, method_signature;
|
||||
{
|
||||
tree method;
|
||||
tree list = NULL_TREE;
|
||||
while (clas != NULL_TREE)
|
||||
{
|
||||
for (method = TYPE_METHODS (clas);
|
||||
method != NULL_TREE; method = TREE_CHAIN (method))
|
||||
{
|
||||
tree method_sig = build_java_argument_signature (TREE_TYPE (method));
|
||||
if (DECL_NAME (method) == method_name
|
||||
&& method_sig == method_signature)
|
||||
list = tree_cons (NULL_TREE, method, list);
|
||||
}
|
||||
clas = CLASSTYPE_SUPER (clas);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/* Search in class CLAS for a constructor matching METHOD_SIGNATURE.
|
||||
Return a FUNCTION_DECL on success, or NULL_TREE if none found. */
|
||||
|
||||
tree
|
||||
lookup_java_constructor (clas, method_signature)
|
||||
tree clas, method_signature;
|
||||
{
|
||||
tree method = TYPE_METHODS (clas);
|
||||
for ( ; method != NULL_TREE; method = TREE_CHAIN (method))
|
||||
{
|
||||
tree method_sig = build_java_signature (TREE_TYPE (method));
|
||||
if (DECL_CONSTRUCTOR_P (method) && method_sig == method_signature)
|
||||
return method;
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Return a type which is the Binary Numeric Promotion of the pair T1,
|
||||
T2 and convert EXP1 and/or EXP2. See 5.6.2 Binary Numeric
|
||||
Promotion. It assumes that both T1 and T2 are elligible to BNP. */
|
||||
|
||||
tree
|
||||
binary_numeric_promotion (t1, t2, exp1, exp2)
|
||||
tree t1;
|
||||
tree t2;
|
||||
tree *exp1;
|
||||
tree *exp2;
|
||||
{
|
||||
if (t1 == double_type_node || t2 == double_type_node)
|
||||
{
|
||||
if (t1 != double_type_node)
|
||||
*exp1 = convert (double_type_node, *exp1);
|
||||
if (t2 != double_type_node)
|
||||
*exp2 = convert (double_type_node, *exp2);
|
||||
return double_type_node;
|
||||
}
|
||||
if (t1 == float_type_node || t2 == float_type_node)
|
||||
{
|
||||
if (t1 != float_type_node)
|
||||
*exp1 = convert (float_type_node, *exp1);
|
||||
if (t2 != float_type_node)
|
||||
*exp2 = convert (float_type_node, *exp2);
|
||||
return float_type_node;
|
||||
}
|
||||
if (t1 == long_type_node || t2 == long_type_node)
|
||||
{
|
||||
if (t1 != long_type_node)
|
||||
*exp1 = convert (long_type_node, *exp1);
|
||||
if (t2 != long_type_node)
|
||||
*exp2 = convert (long_type_node, *exp2);
|
||||
return long_type_node;
|
||||
}
|
||||
|
||||
if (t1 != int_type_node)
|
||||
*exp1 = convert (int_type_node, *exp1);
|
||||
if (t2 != int_type_node)
|
||||
*exp2 = convert (int_type_node, *exp2);
|
||||
return int_type_node;
|
||||
}
|
1239
gcc/java/verify.c
Normal file
1239
gcc/java/verify.c
Normal file
File diff suppressed because it is too large
Load diff
350
gcc/java/zextract.c
Normal file
350
gcc/java/zextract.c
Normal file
|
@ -0,0 +1,350 @@
|
|||
/* Handle a .class file embedded in a .zip archive.
|
||||
This extracts a member from a .zip file, but does not handle
|
||||
uncompression (since that is not needed for classes.zip).
|
||||
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
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, 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
/* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
|
||||
|
||||
#include "zipfile.h"
|
||||
|
||||
|
||||
/* This stuff is partly based on the 28 August 1994 public release of the
|
||||
Info-ZIP group's portable UnZip zipfile-extraction program (and related
|
||||
utilities). */
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef __STDC__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <errno.h> /* used in mapname() */
|
||||
|
||||
/*************/
|
||||
/* Defines */
|
||||
/*************/
|
||||
|
||||
#define UNZIP
|
||||
#define UNZIP_VERSION 20 /* compatible with PKUNZIP 2.0 */
|
||||
#define VMS_UNZIP_VERSION 42 /* if OS-needed-to-extract is VMS: can do */
|
||||
|
||||
|
||||
#define ZSUFX ".zip"
|
||||
#define CENTRAL_HDR_SIG "\113\001\002" /* the infamous "PK" signature */
|
||||
#define LOCAL_HDR_SIG "\113\003\004" /* bytes, sans "P" (so unzip */
|
||||
#define END_CENTRAL_SIG "\113\005\006" /* executable not mistaken for */
|
||||
#define EXTD_LOCAL_SIG "\113\007\010" /* zipfile itself) */
|
||||
|
||||
#define STORED 0 /* compression methods */
|
||||
#define SHRUNK 1
|
||||
#define REDUCED1 2
|
||||
#define REDUCED2 3
|
||||
#define REDUCED3 4
|
||||
#define REDUCED4 5
|
||||
#define IMPLODED 6
|
||||
#define TOKENIZED 7
|
||||
#define DEFLATED 8
|
||||
#define NUM_METHODS 9 /* index of last method + 1 */
|
||||
/* don't forget to update list_files() appropriately if NUM_METHODS changes */
|
||||
|
||||
#define PK_OK 0 /* no error */
|
||||
#define PK_COOL 0 /* no error */
|
||||
#define PK_GNARLY 0 /* no error */
|
||||
#define PK_WARN 1 /* warning error */
|
||||
#define PK_ERR 2 /* error in zipfile */
|
||||
#define PK_BADERR 3 /* severe error in zipfile */
|
||||
#define PK_MEM 4 /* insufficient memory */
|
||||
#define PK_MEM2 5 /* insufficient memory */
|
||||
#define PK_MEM3 6 /* insufficient memory */
|
||||
#define PK_MEM4 7 /* insufficient memory */
|
||||
#define PK_MEM5 8 /* insufficient memory */
|
||||
#define PK_NOZIP 9 /* zipfile not found */
|
||||
#define PK_PARAM 10 /* bad or illegal parameters specified */
|
||||
#define PK_FIND 11 /* no files found */
|
||||
#define PK_DISK 50 /* disk full */
|
||||
#define PK_EOF 51 /* unexpected EOF */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
True sizes of the various headers, as defined by PKWARE--so it is not
|
||||
likely that these will ever change. But if they do, make sure both these
|
||||
defines AND the typedefs below get updated accordingly.
|
||||
---------------------------------------------------------------------------*/
|
||||
#define LREC_SIZE 26 /* lengths of local file headers, central */
|
||||
#define CREC_SIZE 42 /* directory headers, and the end-of- */
|
||||
#define ECREC_SIZE 18 /* central-dir record, respectively */
|
||||
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0
|
||||
# define SEEK_CUR 1
|
||||
# define SEEK_END 2
|
||||
#endif
|
||||
|
||||
/**************/
|
||||
/* Typedefs */
|
||||
/**************/
|
||||
|
||||
typedef char boolean;
|
||||
typedef unsigned char uch; /* code assumes unsigned bytes; these type- */
|
||||
typedef unsigned short ush; /* defs replace byte/UWORD/ULONG (which are */
|
||||
typedef unsigned long ulg; /* predefined on some systems) & match zip */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Zipfile layout declarations. If these headers ever change, make sure the
|
||||
xxREC_SIZE defines (above) change with them!
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
typedef uch local_byte_hdr[ LREC_SIZE ];
|
||||
# define L_VERSION_NEEDED_TO_EXTRACT_0 0
|
||||
# define L_VERSION_NEEDED_TO_EXTRACT_1 1
|
||||
# define L_GENERAL_PURPOSE_BIT_FLAG 2
|
||||
# define L_COMPRESSION_METHOD 4
|
||||
# define L_LAST_MOD_FILE_TIME 6
|
||||
# define L_LAST_MOD_FILE_DATE 8
|
||||
# define L_CRC32 10
|
||||
# define L_COMPRESSED_SIZE 14
|
||||
# define L_UNCOMPRESSED_SIZE 18
|
||||
# define L_FILENAME_LENGTH 22
|
||||
# define L_EXTRA_FIELD_LENGTH 24
|
||||
|
||||
typedef uch cdir_byte_hdr[ CREC_SIZE ];
|
||||
# define C_VERSION_MADE_BY_0 0
|
||||
# define C_VERSION_MADE_BY_1 1
|
||||
# define C_VERSION_NEEDED_TO_EXTRACT_0 2
|
||||
# define C_VERSION_NEEDED_TO_EXTRACT_1 3
|
||||
# define C_GENERAL_PURPOSE_BIT_FLAG 4
|
||||
# define C_COMPRESSION_METHOD 6
|
||||
# define C_LAST_MOD_FILE_TIME 8
|
||||
# define C_LAST_MOD_FILE_DATE 10
|
||||
# define C_CRC32 12
|
||||
# define C_COMPRESSED_SIZE 16
|
||||
# define C_UNCOMPRESSED_SIZE 20
|
||||
# define C_FILENAME_LENGTH 24
|
||||
# define C_EXTRA_FIELD_LENGTH 26
|
||||
# define C_FILE_COMMENT_LENGTH 28
|
||||
# define C_DISK_NUMBER_START 30
|
||||
# define C_INTERNAL_FILE_ATTRIBUTES 32
|
||||
# define C_EXTERNAL_FILE_ATTRIBUTES 34
|
||||
# define C_RELATIVE_OFFSET_LOCAL_HEADER 38
|
||||
|
||||
typedef uch ec_byte_rec[ ECREC_SIZE+4 ];
|
||||
/* define SIGNATURE 0 space-holder only */
|
||||
# define NUMBER_THIS_DISK 4
|
||||
# define NUM_DISK_WITH_START_CENTRAL_DIR 6
|
||||
# define NUM_ENTRIES_CENTRL_DIR_THS_DISK 8
|
||||
# define TOTAL_ENTRIES_CENTRAL_DIR 10
|
||||
# define SIZE_CENTRAL_DIRECTORY 12
|
||||
# define OFFSET_START_CENTRAL_DIRECTORY 16
|
||||
# define ZIPFILE_COMMENT_LENGTH 20
|
||||
|
||||
|
||||
typedef struct local_file_header { /* LOCAL */
|
||||
uch version_needed_to_extract[2];
|
||||
ush general_purpose_bit_flag;
|
||||
ush compression_method;
|
||||
ush last_mod_file_time;
|
||||
ush last_mod_file_date;
|
||||
ulg crc32;
|
||||
ulg csize;
|
||||
ulg ucsize;
|
||||
ush filename_length;
|
||||
ush extra_field_length;
|
||||
} local_file_hdr;
|
||||
|
||||
typedef struct central_directory_file_header { /* CENTRAL */
|
||||
uch version_made_by[2];
|
||||
uch version_needed_to_extract[2];
|
||||
ush general_purpose_bit_flag;
|
||||
ush compression_method;
|
||||
ush last_mod_file_time;
|
||||
ush last_mod_file_date;
|
||||
ulg crc32;
|
||||
ulg csize;
|
||||
ulg ucsize;
|
||||
ush filename_length;
|
||||
ush extra_field_length;
|
||||
ush file_comment_length;
|
||||
ush disk_number_start;
|
||||
ush internal_file_attributes;
|
||||
ulg external_file_attributes;
|
||||
ulg relative_offset_local_header;
|
||||
} cdir_file_hdr;
|
||||
|
||||
typedef struct end_central_dir_record { /* END CENTRAL */
|
||||
ush number_this_disk;
|
||||
ush num_disk_with_start_central_dir;
|
||||
ush num_entries_centrl_dir_ths_disk;
|
||||
ush total_entries_central_dir;
|
||||
ulg size_central_directory;
|
||||
ulg offset_start_central_directory;
|
||||
ush zipfile_comment_length;
|
||||
} ecdir_rec;
|
||||
|
||||
|
||||
/************/
|
||||
/* Macros */
|
||||
/************/
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
|
||||
/***********************/
|
||||
/* Function makeword() */
|
||||
/***********************/
|
||||
|
||||
static ush makeword(b)
|
||||
uch *b;
|
||||
{
|
||||
/*
|
||||
* Convert Intel style 'short' integer to non-Intel non-16-bit
|
||||
* host format. This routine also takes care of byte-ordering.
|
||||
*/
|
||||
return (ush)((b[1] << 8) | b[0]);
|
||||
}
|
||||
|
||||
|
||||
/***********************/
|
||||
/* Function makelong() */
|
||||
/***********************/
|
||||
|
||||
static ulg makelong(sig)
|
||||
uch *sig;
|
||||
{
|
||||
/*
|
||||
* Convert intel style 'long' variable to non-Intel non-16-bit
|
||||
* host format. This routine also takes care of byte-ordering.
|
||||
*/
|
||||
return (((ulg)sig[3]) << 24)
|
||||
+ (((ulg)sig[2]) << 16)
|
||||
+ (((ulg)sig[1]) << 8)
|
||||
+ ((ulg)sig[0]);
|
||||
}
|
||||
|
||||
int
|
||||
read_zip_archive (zipf)
|
||||
register ZipFile *zipf;
|
||||
{
|
||||
int i;
|
||||
int dir_last_pad;
|
||||
char *dir_ptr;
|
||||
char buffer[100];
|
||||
|
||||
zipf->size = lseek (zipf->fd, 0L, SEEK_END);
|
||||
|
||||
if (zipf->size < (ECREC_SIZE+4) || lseek (zipf->fd, (long)(-(ECREC_SIZE+4)), SEEK_CUR) <= 0)
|
||||
return -1;
|
||||
if (read (zipf->fd, buffer, ECREC_SIZE+4) != ECREC_SIZE+4)
|
||||
return -2;
|
||||
zipf->count = makeword(&buffer[TOTAL_ENTRIES_CENTRAL_DIR]);
|
||||
zipf->dir_size = makelong(&buffer[SIZE_CENTRAL_DIRECTORY]);
|
||||
#define ALLOC malloc
|
||||
/* Allocate 1 more to allow appending '\0' to last filename. */
|
||||
zipf->central_directory = ALLOC (zipf->dir_size+1);
|
||||
if (lseek (zipf->fd, -(zipf->dir_size+ECREC_SIZE+4), SEEK_CUR) < 0)
|
||||
return -2;
|
||||
if (read (zipf->fd, zipf->central_directory, zipf->dir_size) < 0)
|
||||
return -2;
|
||||
|
||||
#ifdef TEST
|
||||
printf ("number_this_disk = %d\n", makeword(&buffer[NUMBER_THIS_DISK]));
|
||||
printf ("num_disk_with_start_central_dir = %d\n", makeword(&buffer[NUM_DISK_WITH_START_CENTRAL_DIR]));
|
||||
|
||||
printf ("num_entries_centrl_dir_ths_disk = %d\n",
|
||||
makeword(&buffer[NUM_ENTRIES_CENTRL_DIR_THS_DISK]));
|
||||
printf ("total_entries_central_dir = %d\n",
|
||||
makeword(&buffer[TOTAL_ENTRIES_CENTRAL_DIR]));
|
||||
printf ("size_central_directory = %d\n",
|
||||
makelong(&buffer[SIZE_CENTRAL_DIRECTORY]));
|
||||
printf ("offset_start_central_directory = %d\n",
|
||||
makelong(&buffer[OFFSET_START_CENTRAL_DIRECTORY]));
|
||||
printf ("zipfile_comment_length = %d\n",
|
||||
makeword(&buffer[ZIPFILE_COMMENT_LENGTH]));
|
||||
#endif
|
||||
|
||||
dir_last_pad = 0;
|
||||
dir_ptr = zipf->central_directory;
|
||||
for (i = 0; i < zipf->count; i++)
|
||||
{
|
||||
ZipDirectory *zipd = (ZipDirectory*)(dir_ptr + dir_last_pad);
|
||||
long uncompressed_size = makelong (&dir_ptr[4+C_UNCOMPRESSED_SIZE]);
|
||||
long filename_length = makeword (&dir_ptr[4+C_FILENAME_LENGTH]);
|
||||
long extra_field_length = makeword (&dir_ptr[4+C_EXTRA_FIELD_LENGTH]);
|
||||
long file_comment_length = makeword (&dir_ptr[4+C_FILE_COMMENT_LENGTH]);
|
||||
int unpadded_direntry_length;
|
||||
if ((dir_ptr-zipf->central_directory)+filename_length+CREC_SIZE+4>zipf->dir_size)
|
||||
return -1;
|
||||
|
||||
zipd->filename_length = filename_length;
|
||||
zipd->size = uncompressed_size;
|
||||
#ifdef __GNUC__
|
||||
#define DIR_ALIGN __alignof__(ZipDirectory)
|
||||
#else
|
||||
#define DIR_ALIGN sizeof(long)
|
||||
#endif
|
||||
zipd->filestart = makelong (&dir_ptr[4+C_RELATIVE_OFFSET_LOCAL_HEADER])
|
||||
+ (LREC_SIZE+4) + filename_length + file_comment_length +
|
||||
+ (extra_field_length ? extra_field_length+4 : 0);
|
||||
/* About the last term of the expression above. Should the same
|
||||
apply if file_comment_length is not zero ? I've never seen
|
||||
the comment field uses so far. FIXME. */
|
||||
zipd->filename_offset = CREC_SIZE+4 - dir_last_pad;
|
||||
unpadded_direntry_length
|
||||
= zipd->filename_offset + zipd->filename_length + extra_field_length;
|
||||
zipd->direntry_size =
|
||||
((unpadded_direntry_length + DIR_ALIGN) / DIR_ALIGN) * DIR_ALIGN;
|
||||
dir_last_pad = zipd->direntry_size - unpadded_direntry_length;
|
||||
dir_ptr = (char*)zipd + unpadded_direntry_length;
|
||||
*dir_ptr = '\0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
main ()
|
||||
{
|
||||
ZipFile zipf[1];
|
||||
ZipDirectory *zipd;
|
||||
int i;
|
||||
|
||||
zipf->fd = 0;
|
||||
|
||||
i = read_zip_archive (zipf);
|
||||
if (i)
|
||||
{
|
||||
fprintf (stderr, "Bad zip file.\n");
|
||||
exit (i);
|
||||
}
|
||||
|
||||
zipd = (ZipDirectory*) zipf->central_directory;
|
||||
for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
|
||||
{
|
||||
printf ("%d: size:%d, name(#%d)%s, offset:%d\n",
|
||||
i, zipd->size, zipd->filename_length,
|
||||
ZIPDIR_FILENAME (zipd),
|
||||
zipd->filestart);
|
||||
}
|
||||
}
|
||||
#endif
|
58
gcc/java/zipfile.h
Normal file
58
gcc/java/zipfile.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Definitions for using a zipped' archive.
|
||||
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
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, 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
Java and all Java-based marks are trademarks or registered trademarks
|
||||
of Sun Microsystems, Inc. in the United States and other countries.
|
||||
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
||||
|
||||
struct ZipFile {
|
||||
int fd;
|
||||
long size;
|
||||
long count;
|
||||
long dir_size;
|
||||
char *central_directory;
|
||||
};
|
||||
|
||||
typedef struct ZipFile ZipFile;
|
||||
|
||||
struct ZipDirectory {
|
||||
int direntry_size;
|
||||
int filename_offset;
|
||||
long size; /* length of file */
|
||||
long filestart; /* start of file in archive */
|
||||
long filename_length;
|
||||
/* char mid_padding[...]; */
|
||||
/* char filename[filename_length]; */
|
||||
/* char end_padding[...]; */
|
||||
};
|
||||
|
||||
typedef struct ZipDirectory ZipDirectory;
|
||||
|
||||
struct ZipFileCache {
|
||||
struct ZipFile z;
|
||||
struct ZipFileCache *next;
|
||||
char *name;
|
||||
};
|
||||
|
||||
extern struct ZipFileCache *SeenZipFiles;
|
||||
|
||||
#define ZIPDIR_FILENAME(ZIPD) ((char*)(ZIPD)+(ZIPD)->filename_offset)
|
||||
#define ZIPDIR_NEXT(ZIPD) \
|
||||
((ZipDirectory*)((char*)(ZIPD)+(ZIPD)->direntry_size))
|
||||
#define ZIPMAGIC 0x504b0304
|
Loading…
Add table
Reference in a new issue