first commit
This commit is contained in:
commit
063194f8be
349 changed files with 36508 additions and 0 deletions
BIN
jasmin/jasmin-2.4.zip
Normal file
BIN
jasmin/jasmin-2.4.zip
Normal file
Binary file not shown.
116
jasmin/jasmin-2.4/Readme.txt
Normal file
116
jasmin/jasmin-2.4/Readme.txt
Normal file
|
@ -0,0 +1,116 @@
|
|||
Jasmin README file 1 March 1997, Jonathan Meyer
|
||||
Last updated October 2004
|
||||
|
||||
Introduction
|
||||
------------
|
||||
Welcome to Jasmin version 1.1.
|
||||
|
||||
Jasmin is a Java Assembler Interface. It takes ASCII descriptions for Java
|
||||
classes, written in a simple assembler-like syntax, using the Java
|
||||
Virtual Machine instruction set. It converts them into binary Java class
|
||||
files suitable for loading into a Java interpreter.
|
||||
|
||||
Jasmin was originally written as the companion to the
|
||||
book "Java Virtual Machine", published by O'Reilly, written by
|
||||
Jon Meyer and Troy Downing. (See http://www.ora.com/catalog/javavm/).
|
||||
The book is now out of print. However, the Jasmin assembler retains its
|
||||
usefulness as a utility, and continues its life as an OpenSource project.
|
||||
|
||||
Background
|
||||
----------
|
||||
Jasmin is today a little long in the tooth. It was originally coded in
|
||||
1996 as a stop-gap until Sun released their own assembler. It has seen
|
||||
no major upgrades since 1997. By 2004 Sun still has not released an
|
||||
official assembler, so I decided to release Jasmin as a sourceforge
|
||||
project. Hopefully this will inject some fresh life into the project...
|
||||
|
||||
Home Page
|
||||
---------
|
||||
Check out the Jasmin home page at:
|
||||
|
||||
http://jasmin.sourceforge.net
|
||||
|
||||
Requirements
|
||||
------------
|
||||
Jasmin is written in Java, and should work with most Java 1.1 environments.
|
||||
|
||||
To run Jasmin you need to have a Java 2 Runtime Environment available (e.g. JDK 1.4).
|
||||
This can be downloaded from "http://www.javasoft.com/j2se/".
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
The Jasmin distribution contains a jasmin.jar file holding the Jasmin assembler.
|
||||
To run Jasmin, execute the Jarfile, specifying any files to assemble
|
||||
as command-line parameters, e.g. to assemble the "HelloWorld.j" file in examples,
|
||||
first use cd to change into the Jasmin directory:
|
||||
|
||||
cd c:\jasmin-1.1 [Windows]
|
||||
or
|
||||
cd ~/jasmin-1.1 [Unix]
|
||||
|
||||
Then, to run Jasmin, use:
|
||||
|
||||
java -jar jasmin.jar examples\HelloWorld.j [Windows]
|
||||
or
|
||||
java -jar jasmin.jar examples/HelloWorld.j [Unix/MacOsX]
|
||||
|
||||
|
||||
After running Jasmin as above, it generates a compiled HelloWorld.class file
|
||||
in the examples directory.
|
||||
|
||||
You can then run the HelloWorld program by doing:
|
||||
|
||||
java examples.HelloWorld
|
||||
|
||||
Build Instructions
|
||||
------------------
|
||||
Jasmin uses Ant as its build mechanism. See build.xml for instructions on how
|
||||
to build Jasmin. In brief, you need to:
|
||||
|
||||
1. Start a Terminal or Command window.
|
||||
2. Change (cd) into the Jasmin directory
|
||||
3. Make sure that java, javac etc. are on your path
|
||||
4. Run build.bat (Windows) or build.sh (Unix).
|
||||
|
||||
For example, on Windows, this might look something like:
|
||||
|
||||
cd c:\jasmin-1.1 # change to Jasmin directory
|
||||
build all
|
||||
|
||||
Or, for Unix, it might be like:
|
||||
|
||||
cd ~/jasmin-1.1 # change to Jasmin directory
|
||||
./build.sh all
|
||||
|
||||
These scripts use the build.xml configuration file to specify build parameters.
|
||||
|
||||
Where Next
|
||||
----------
|
||||
After trying Jasmin out, have a look at the HelloWorld.j source in the examples directory,
|
||||
try compiling and running the other examples.
|
||||
|
||||
There is documentation for Jasmin in the doc directory. You should probably
|
||||
start with the 'guide.html' document.
|
||||
|
||||
Files
|
||||
-----
|
||||
The following files are included in this distribution:
|
||||
|
||||
README.txt - this file
|
||||
jasmin.jar - executable Jar file containing Jasmin assembler
|
||||
examples/ - directory containing example files written for Jasmin
|
||||
src/ - the Java source code and for the jasmin package
|
||||
lib/ - Contains Java sources for the java_cup and jas packages
|
||||
docs/ - various documentation files.
|
||||
|
||||
Copyright
|
||||
---------
|
||||
Jasmin is Copyright (1997-2004) Jonathan Meyer, under the terms of
|
||||
the GNU General Public License. See license-jasmin.txt for more.
|
||||
|
||||
Jasmin uses the JAS package which has its own copyright - see lib/jas/README.
|
||||
[sbktech.org no longer seem to be in existence, but the code lives
|
||||
on in this project].
|
||||
|
||||
Jasmin utilizes Scott E. Hudson's Java Cup package v0.9e, which is also in
|
||||
the lib directory. See http://www.cs.princeton.edu/~appel/modern/java/CUP/
|
107
jasmin/jasmin-2.4/build.bat
Normal file
107
jasmin/jasmin-2.4/build.bat
Normal file
|
@ -0,0 +1,107 @@
|
|||
@echo off
|
||||
|
||||
REM Copyright 2001,2004 The Apache Software Foundation
|
||||
REM
|
||||
REM Licensed under the Apache License, Version 2.0 (the "License");
|
||||
REM you may not use this file except in compliance with the License.
|
||||
REM You may obtain a copy of the License at
|
||||
REM
|
||||
REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
REM
|
||||
REM Unless required by applicable law or agreed to in writing, software
|
||||
REM distributed under the License is distributed on an "AS IS" BASIS,
|
||||
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
REM See the License for the specific language governing permissions and
|
||||
REM limitations under the License.
|
||||
|
||||
if exist "%HOME%\antrc_pre.bat" call "%HOME%\antrc_pre.bat"
|
||||
|
||||
if "%OS%"=="Windows_NT" @setlocal
|
||||
|
||||
rem %~dp0 is expanded pathname of the current script under NT
|
||||
set ANT_HOME=.
|
||||
rem set DEFAULT_ANT_HOME=%~dp0..
|
||||
|
||||
if "%ANT_HOME%"=="" set ANT_HOME=%DEFAULT_ANT_HOME%
|
||||
set DEFAULT_ANT_HOME=
|
||||
|
||||
rem Slurp the command line arguments. This loop allows for an unlimited number
|
||||
rem of arguments (up to the command line limit, anyway).
|
||||
set ANT_CMD_LINE_ARGS=%1
|
||||
if ""%1""=="""" goto doneStart
|
||||
shift
|
||||
:setupArgs
|
||||
if ""%1""=="""" goto doneStart
|
||||
set ANT_CMD_LINE_ARGS=%ANT_CMD_LINE_ARGS% %1
|
||||
shift
|
||||
goto setupArgs
|
||||
rem This label provides a place for the argument list loop to break out
|
||||
rem and for NT handling to skip to.
|
||||
|
||||
:doneStart
|
||||
rem find ANT_HOME if it does not exist due to either an invalid value passed
|
||||
rem by the user or the %0 problem on Windows 9x
|
||||
if exist "%ANT_HOME%\lib\ant.jar" goto checkJava
|
||||
|
||||
rem check for ant in Program Files
|
||||
if not exist "%ProgramFiles%\ant" goto checkSystemDrive
|
||||
set ANT_HOME=%ProgramFiles%\ant
|
||||
goto checkJava
|
||||
|
||||
:checkSystemDrive
|
||||
rem check for ant in root directory of system drive
|
||||
if not exist %SystemDrive%\ant\lib\ant.jar goto checkCDrive
|
||||
set ANT_HOME=%SystemDrive%\ant
|
||||
goto checkJava
|
||||
|
||||
:checkCDrive
|
||||
rem check for ant in C:\ant for Win9X users
|
||||
if not exist C:\ant\lib\ant.jar goto noAntHome
|
||||
set ANT_HOME=C:\ant
|
||||
goto checkJava
|
||||
|
||||
:noAntHome
|
||||
echo ANT_HOME is set incorrectly or ant could not be located. Please set ANT_HOME.
|
||||
goto end
|
||||
|
||||
:checkJava
|
||||
set _JAVACMD=%JAVACMD%
|
||||
|
||||
if "%JAVA_HOME%" == "" goto noJavaHome
|
||||
if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
|
||||
if "%_JAVACMD%" == "" set _JAVACMD=%JAVA_HOME%\bin\java.exe
|
||||
goto checkJikes
|
||||
|
||||
:noJavaHome
|
||||
if "%_JAVACMD%" == "" set _JAVACMD=java.exe
|
||||
|
||||
:checkJikes
|
||||
if not "%JIKESPATH%"=="" goto runAntWithJikes
|
||||
|
||||
:runAnt
|
||||
if not "%CLASSPATH%"=="" goto runAntWithClasspath
|
||||
"%_JAVACMD%" %ANT_OPTS% -classpath "%ANT_HOME%\lib\ant-launcher.jar" "-Dant.home=%ANT_HOME%" org.apache.tools.ant.launch.Launcher %ANT_ARGS% %ANT_CMD_LINE_ARGS%
|
||||
goto end
|
||||
|
||||
:runAntWithClasspath
|
||||
"%_JAVACMD%" %ANT_OPTS% -classpath "%ANT_HOME%\lib\ant-launcher.jar" "-Dant.home=%ANT_HOME%" org.apache.tools.ant.launch.Launcher %ANT_ARGS% -lib "%CLASSPATH%" %ANT_CMD_LINE_ARGS%
|
||||
goto end
|
||||
|
||||
:runAntWithJikes
|
||||
if not "%CLASSPATH%"=="" goto runAntWithJikesAndClasspath
|
||||
"%_JAVACMD%" %ANT_OPTS% -classpath "%ANT_HOME%\lib\ant-launcher.jar" "-Dant.home=%ANT_HOME%" "-Djikes.class.path=%JIKESPATH%" org.apache.tools.ant.launch.Launcher %ANT_ARGS% %ANT_CMD_LINE_ARGS%
|
||||
goto end
|
||||
|
||||
:runAntWithJikesAndClasspath
|
||||
"%_JAVACMD%" %ANT_OPTS% -classpath "%ANT_HOME%\lib\ant-launcher.jar" "-Dant.home=%ANT_HOME%" "-Djikes.class.path=%JIKESPATH%" org.apache.tools.ant.launch.Launcher %ANT_ARGS% -lib "%CLASSPATH%" %ANT_CMD_LINE_ARGS%
|
||||
goto end
|
||||
|
||||
:end
|
||||
set _JAVACMD=
|
||||
set ANT_CMD_LINE_ARGS=
|
||||
|
||||
if "%OS%"=="Windows_NT" @endlocal
|
||||
|
||||
:mainEnd
|
||||
if exist "%HOME%\antrc_post.bat" call "%HOME%\antrc_post.bat"
|
||||
|
305
jasmin/jasmin-2.4/build.sh
Normal file
305
jasmin/jasmin-2.4/build.sh
Normal file
|
@ -0,0 +1,305 @@
|
|||
#! /bin/sh
|
||||
|
||||
# Copyright 2001-2004 The Apache Software Foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ANT_HOME=.
|
||||
export ANT_HOME
|
||||
|
||||
# Extract launch and ant arguments, (see details below).
|
||||
ant_exec_args=
|
||||
no_config=false
|
||||
use_jikes_default=false
|
||||
ant_exec_debug=false
|
||||
show_help=false
|
||||
for arg in "$@" ; do
|
||||
if [ "$arg" = "--noconfig" ] ; then
|
||||
no_config=true
|
||||
elif [ "$arg" = "--usejikes" ] ; then
|
||||
use_jikes_default=true
|
||||
elif [ "$arg" = "--execdebug" ] ; then
|
||||
ant_exec_debug=true
|
||||
elif [ my"$arg" = my"--h" -o my"$arg" = my"--help" ] ; then
|
||||
show_help=true
|
||||
ant_exec_args="$ant_exec_args -h"
|
||||
else
|
||||
if [ my"$arg" = my"-h" -o my"$arg" = my"-help" ] ; then
|
||||
show_help=true
|
||||
fi
|
||||
ant_exec_args="$ant_exec_args \"$arg\""
|
||||
fi
|
||||
done
|
||||
|
||||
# Source/default ant configuration
|
||||
if $no_config ; then
|
||||
rpm_mode=false
|
||||
usejikes=$use_jikes_default
|
||||
else
|
||||
# load system-wide ant configuration
|
||||
if [ -f "/etc/ant.conf" ] ; then
|
||||
. /etc/ant.conf
|
||||
fi
|
||||
|
||||
# load user ant configuration
|
||||
if [ -f "$HOME/.ant/ant.conf" ] ; then
|
||||
. $HOME/.ant/ant.conf
|
||||
fi
|
||||
if [ -f "$HOME/.antrc" ] ; then
|
||||
. "$HOME/.antrc"
|
||||
fi
|
||||
|
||||
# provide default configuration values
|
||||
if [ -z "$rpm_mode" ] ; then
|
||||
rpm_mode=false
|
||||
fi
|
||||
if [ -z "$usejikes" ] ; then
|
||||
usejikes=$use_jikes_default
|
||||
fi
|
||||
fi
|
||||
|
||||
# Setup Java environment in rpm mode
|
||||
if $rpm_mode ; then
|
||||
if [ -f /usr/share/java-utils/java-functions ] ; then
|
||||
. /usr/share/java-utils/java-functions
|
||||
set_jvm
|
||||
set_javacmd
|
||||
fi
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
Darwin*) darwin=true
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$ANT_HOME" -o ! -d "$ANT_HOME" ] ; then
|
||||
# try to find ANT
|
||||
if [ -d /opt/ant ] ; then
|
||||
ANT_HOME=/opt/ant
|
||||
fi
|
||||
|
||||
if [ -d "${HOME}/opt/ant" ] ; then
|
||||
ANT_HOME="${HOME}/opt/ant"
|
||||
fi
|
||||
|
||||
## resolve links - $0 may be a link to ant's home
|
||||
PRG="$0"
|
||||
progname=`basename "$0"`
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
ANT_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
ANT_HOME=`cd "$ANT_HOME" && pwd`
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$ANT_HOME" ] &&
|
||||
ANT_HOME=`cygpath --unix "$ANT_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# set ANT_LIB location
|
||||
ANT_LIB="${ANT_HOME}/lib"
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD=`which java 2> /dev/null `
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
JAVACMD=java
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly."
|
||||
echo " We cannot execute $JAVACMD"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build local classpath using just the launcher in non-rpm mode or
|
||||
# use the Jpackage helper in rpm mode with basic and default jars
|
||||
# specified in the ant.conf configuration. Because the launcher is
|
||||
# used, libraries linked in ANT_HOME will also be include, but this
|
||||
# is discouraged as it is not java-version safe. A user should
|
||||
# request optional jars and their dependencies via the OPT_JAR_LIST
|
||||
# variable
|
||||
if $rpm_mode && [ -f /usr/bin/build-classpath ] ; then
|
||||
LOCALCLASSPATH="$(/usr/bin/build-classpath ant ant-launcher jaxp_parser_impl xml-commons-apis)"
|
||||
# If the user requested to try to add some other jars to the classpath
|
||||
if [ -n "$OPT_JAR_LIST" ] ; then
|
||||
_OPTCLASSPATH="$(/usr/bin/build-classpath $OPT_JAR_LIST 2> /dev/null)"
|
||||
if [ -n "$_OPTCLASSPATH" ] ; then
|
||||
LOCALCLASSPATH="$LOCALCLASSPATH:$_OPTCLASSPATH"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Explicitly add javac path to classpath, assume JAVA_HOME set
|
||||
# properly in rpm mode
|
||||
if [ -f "$JAVA_HOME/lib/tools.jar" ] ; then
|
||||
LOCALCLASSPATH="$LOCALCLASSPATH:$JAVA_HOME/lib/tools.jar"
|
||||
fi
|
||||
if [ -f "$JAVA_HOME/lib/classes.zip" ] ; then
|
||||
LOCALCLASSPATH="$LOCALCLASSPATH:$JAVA_HOME/lib/classes.zip"
|
||||
fi
|
||||
|
||||
# if CLASSPATH_OVERRIDE env var is set, LOCALCLASSPATH will be
|
||||
# user CLASSPATH first and ant-found jars after.
|
||||
# In that case, the user CLASSPATH will override ant-found jars
|
||||
#
|
||||
# if CLASSPATH_OVERRIDE is not set, we'll have the normal behaviour
|
||||
# with ant-found jars first and user CLASSPATH after
|
||||
if [ -n "$CLASSPATH" ] ; then
|
||||
# merge local and specified classpath
|
||||
if [ -z "$LOCALCLASSPATH" ] ; then
|
||||
LOCALCLASSPATH="$CLASSPATH"
|
||||
elif [ -n "$CLASSPATH_OVERRIDE" ] ; then
|
||||
LOCALCLASSPATH="$CLASSPATH:$LOCALCLASSPATH"
|
||||
else
|
||||
LOCALCLASSPATH="$LOCALCLASSPATH:$CLASSPATH"
|
||||
fi
|
||||
|
||||
# remove class path from launcher -lib option
|
||||
CLASSPATH=""
|
||||
fi
|
||||
else
|
||||
# not using rpm_mode; use launcher to determine classpaths
|
||||
if [ -z "$LOCALCLASSPATH" ] ; then
|
||||
LOCALCLASSPATH=$ANT_LIB/ant-launcher.jar
|
||||
else
|
||||
LOCALCLASSPATH=$ANT_LIB/ant-launcher.jar:$LOCALCLASSPATH
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
# OSX hack to make Ant work with jikes
|
||||
if $darwin ; then
|
||||
OSXHACK="${JAVA_HOME}/../Classes"
|
||||
if [ -d "${OSXHACK}" ] ; then
|
||||
for i in "${OSXHACK}"/*.jar
|
||||
do
|
||||
JIKESPATH="$JIKESPATH:$i"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Allow Jikes support (off by default)
|
||||
if $usejikes; then
|
||||
ANT_OPTS="$ANT_OPTS -Dbuild.compiler=jikes"
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to appropriate format before running java
|
||||
if $cygwin; then
|
||||
if [ "$OS" = "Windows_NT" ] && cygpath -m .>/dev/null 2>/dev/null ; then
|
||||
format=mixed
|
||||
else
|
||||
format=windows
|
||||
fi
|
||||
ANT_HOME=`cygpath --$format "$ANT_HOME"`
|
||||
ANT_LIB=`cygpath --$format "$ANT_LIB"`
|
||||
JAVA_HOME=`cygpath --$format "$JAVA_HOME"`
|
||||
LOCALCLASSPATH=`cygpath --path --$format "$LOCALCLASSPATH"`
|
||||
if [ -n "$CLASSPATH" ] ; then
|
||||
CLASSPATH=`cygpath --path --$format "$CLASSPATH"`
|
||||
fi
|
||||
CYGHOME=`cygpath --$format "$HOME"`
|
||||
fi
|
||||
|
||||
# Show script help if requested
|
||||
if $show_help ; then
|
||||
echo $0 '[script options] [options] [target [target2 [target3] ..]]'
|
||||
echo 'Script Options:'
|
||||
echo ' --help, --h print this message and ant help'
|
||||
echo ' --noconfig suppress sourcing of /etc/ant.conf,'
|
||||
echo ' $HOME/.ant/ant.conf, and $HOME/.antrc'
|
||||
echo ' configuration files'
|
||||
echo ' --usejikes enable use of jikes by default, unless'
|
||||
echo ' set explicitly in configuration files'
|
||||
echo ' --execdebug print ant exec line generated by this'
|
||||
echo ' launch script'
|
||||
echo ' '
|
||||
fi
|
||||
# add a second backslash to variables terminated by a backslash under cygwin
|
||||
if $cygwin; then
|
||||
case "$ANT_HOME" in
|
||||
*\\ )
|
||||
ANT_HOME="$ANT_HOME\\"
|
||||
;;
|
||||
esac
|
||||
case "$CYGHOME" in
|
||||
*\\ )
|
||||
CYGHOME="$CYGHOME\\"
|
||||
;;
|
||||
esac
|
||||
case "$JIKESPATH" in
|
||||
*\\ )
|
||||
JIKESPATH="$JIKESPATH\\"
|
||||
;;
|
||||
esac
|
||||
case "$LOCALCLASSPATH" in
|
||||
*\\ )
|
||||
LOCALCLASSPATH="$LOCALCLASSPATH\\"
|
||||
;;
|
||||
esac
|
||||
case "$CLASSPATH" in
|
||||
*\\ )
|
||||
CLASSPATH="$CLASSPATH\\"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
# Execute ant using eval/exec to preserve spaces in paths,
|
||||
# java options, and ant args
|
||||
ant_sys_opts=
|
||||
if [ -n "$CYGHOME" ]; then
|
||||
if [ -n "$JIKESPATH" ]; then
|
||||
ant_sys_opts="-Djikes.class.path=\"$JIKESPATH\" -Dcygwin.user.home=\"$CYGHOME\""
|
||||
else
|
||||
ant_sys_opts="-Dcygwin.user.home=\"$CYGHOME\""
|
||||
fi
|
||||
else
|
||||
if [ -n "$JIKESPATH" ]; then
|
||||
ant_sys_opts="-Djikes.class.path=\"$JIKESPATH\""
|
||||
fi
|
||||
fi
|
||||
ant_exec_command="exec \"$JAVACMD\" $ANT_OPTS -classpath \"$LOCALCLASSPATH\" -Dant.home=\"$ANT_HOME\" -Dant.library.dir=\"$ANT_LIB\" $ant_sys_opts org.apache.tools.ant.launch.Launcher $ANT_ARGS -lib \"$CLASSPATH\" $ant_exec_args"
|
||||
if $ant_exec_debug ; then
|
||||
echo $ant_exec_command
|
||||
fi
|
||||
eval $ant_exec_command
|
297
jasmin/jasmin-2.4/build.xml
Normal file
297
jasmin/jasmin-2.4/build.xml
Normal file
|
@ -0,0 +1,297 @@
|
|||
<!-- ===========================================================================
|
||||
|
||||
Installing the build tools
|
||||
==========================
|
||||
|
||||
The Jasmin build system is based on Jakarta Ant, which is a Java building tool
|
||||
originally developed for the Jakarta Tomcat project but now used in many other
|
||||
Apache projects and extended by many developers.
|
||||
|
||||
Ant is a little but very handy tool that uses a build file written in XML
|
||||
(this file) as building instructions. For more information refer to
|
||||
"http://jakarta.apache.org/ant/".
|
||||
|
||||
Jasmin includes its own copy of the ant library in the lib directory.
|
||||
|
||||
The only other thing that you have to make sure of is that the
|
||||
"JAVA_HOME" environment property is set to match the top level directory
|
||||
containing the JVM you want to use. For example:
|
||||
|
||||
C:\> set JAVA_HOME=C:\jdk1.4
|
||||
|
||||
or on Unix:
|
||||
|
||||
% setenv JAVA_HOME /usr/local/java
|
||||
(csh)
|
||||
> JAVA_HOME=/usr/java; export JAVA_HOME
|
||||
(ksh, bash)
|
||||
|
||||
That's it!
|
||||
|
||||
Building instructions
|
||||
=====================
|
||||
|
||||
First, make sure your current working directory is
|
||||
where this very file is located. Then type:
|
||||
|
||||
./build.sh all (unix)
|
||||
build.bat all (win32)
|
||||
|
||||
To build the framework, examples, and tests or:
|
||||
|
||||
./build.sh (unix)
|
||||
build.bat (win32)
|
||||
|
||||
To list all the possible build targets.
|
||||
|
||||
If everything is right (see *) and all the required packages are visible, this action
|
||||
will generate a build directory ./build, containing the jar file:
|
||||
|
||||
jasmin.jar - This jar contains the Jasmin assembler
|
||||
|
||||
This jar file can be run by the command
|
||||
|
||||
java -jar jasmin.jar <filenames>
|
||||
|
||||
from within the ./build directory.
|
||||
|
||||
* On Win/98 you may get an "Out of Environment Space" error message. This happens if
|
||||
Windows provides too small a space for environment variables. To work around this
|
||||
limitation:
|
||||
Close the DOS window (the error can corrupt its CLASSPATH variable).
|
||||
Open a new DOS window. Click on the MS-DOS icon at the top left of the window.
|
||||
Select the Properties option.
|
||||
Click on the Memory tab.
|
||||
Adjust the "Initial Environment" drop-down box from "Auto" to "2816".
|
||||
Click OK.
|
||||
Then try building.
|
||||
|
||||
-->
|
||||
|
||||
<project name="Jasmin" default="usage" basedir=".">
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Initialization target -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="init">
|
||||
<tstamp/>
|
||||
<property name="Name" value="Jasmin"/>
|
||||
<property name="name" value="jasmin"/>
|
||||
<property name="version" value="2.1"/>
|
||||
<property name="year" value="2006"/>
|
||||
|
||||
<echo message="----------- ${Name} ${version} [${year}] ------------"/>
|
||||
|
||||
<property name="build.compiler" value="modern"/>
|
||||
<property name="debug" value="on"/>
|
||||
<property name="optimize" value="on"/>
|
||||
<property name="deprecation" value="on"/>
|
||||
<property name="packages" value="jasmin.*,jas.*,scm.*"/>
|
||||
|
||||
<!-- Define the source directories -->
|
||||
<property name="root.dir" value="./"/>
|
||||
<property name="docs.dir" value="${root.dir}/docs"/>
|
||||
<property name="lib.dir" value="${root.dir}/lib"/>
|
||||
<property name="src.dir" value="${root.dir}/src"/>
|
||||
|
||||
<!-- Define the source build directories -->
|
||||
<property name="build.dir" value="${root.dir}/build"/>
|
||||
<property name="build.lib" value="${build.dir}/lib"/>
|
||||
<property name="build.jasmin.src" value="${build.dir}/jasmin/src"/>
|
||||
<property name="build.jasmin.dest" value="${build.dir}/jasmin/classes"/>
|
||||
<property name="apidocs.dir" value="${docs.dir}/api"/>
|
||||
|
||||
<!-- Define the distribution directories -->
|
||||
<property name="dist.root" value="${root.dir}/dist"/>
|
||||
<property name="sourcedist.dir" value="${dist.root}/${name}-${version}/${name}-${version}"/>
|
||||
<property name="compiledist.dir" value="${dist.root}/${name}-${version}/${name}-${version}"/>
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Help on usage -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="usage">
|
||||
<echo message=""/>
|
||||
<echo message=""/>
|
||||
<echo message="Jasmin Build file"/>
|
||||
<echo message="-------------------------------------------------------------"/>
|
||||
<echo message=""/>
|
||||
<echo message=" available targets are:"/>
|
||||
<echo message=""/>
|
||||
<echo message=" all --> builds all the jars in ./build"/>
|
||||
<echo message=" parser --> regenerates parser.java from parser.cup "/>
|
||||
<echo message=" docs --> builds the documentation in ./docs/api"/>
|
||||
<echo message=" clean --> restores distribution to original state"/>
|
||||
<echo message=" sourcedist --> builds and zips the source distribution"/>
|
||||
<echo message=" usage --> (default) displays build menu"/>
|
||||
<echo message=""/>
|
||||
<echo message=" See the comments inside the build.xml file for more details."/>
|
||||
<echo message="-------------------------------------------------------------"/>
|
||||
<echo message=""/>
|
||||
<echo message=""/>
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Prepares the build directory -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="prepare" depends="init">
|
||||
<mkdir dir="${build.dir}"/>
|
||||
<mkdir dir="${build.lib}"/>
|
||||
|
||||
<copy todir="${build.lib}">
|
||||
<fileset dir="${lib.dir}"/>
|
||||
</copy>
|
||||
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Prepares the jasmin source code -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="prepare-jasmin" depends="prepare">
|
||||
<mkdir dir="${build.jasmin.src}"/>
|
||||
<mkdir dir="${build.jasmin.dest}"/>
|
||||
|
||||
<copy todir="${build.jasmin.src}">
|
||||
<fileset dir="${src.dir}"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Compiles the jasmin source code -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="compile-jasmin" depends="prepare-jasmin">
|
||||
<javac srcdir="${build.jasmin.src}"
|
||||
source="1.4"
|
||||
destdir="${build.jasmin.dest}"
|
||||
debug="${debug}"
|
||||
deprecation="${deprecation}"
|
||||
optimize="${optimize}"/>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Creates the jasmin.jar in ./build -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="jasmin" depends="compile-jasmin">
|
||||
<jar jarfile="${root.dir}/${name}.jar"
|
||||
basedir="${build.jasmin.dest}"
|
||||
manifest="${build.jasmin.src}/jasmin.mf"
|
||||
includes="jasmin/*.class,jas/*.class,java_cup/runtime/*.class"/>
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Compiles the JavaCup library -->
|
||||
<!-- =================================================================== -->
|
||||
|
||||
<target name="compile-java_cup" depends="prepare-jasmin">
|
||||
<mkdir dir="${build.jasmin.dest}/java_cup"/>
|
||||
<javac srcdir="${build.jasmin.src}/java_cup"
|
||||
source="1.4"
|
||||
destdir="${build.jasmin.dest}/java_cup"
|
||||
debug="${debug}"
|
||||
deprecation="${deprecation}"
|
||||
optimize="${optimize}"/>
|
||||
</target>
|
||||
|
||||
<target name="java_cup" depends="compile-java_cup">
|
||||
<jar jarfile="${root.dir}/lib/java_cup.jar"
|
||||
basedir="${build.jasmin.dest}"
|
||||
includes="java_cup/*.class,java_cup/runtime/*.class"/>
|
||||
</target>
|
||||
|
||||
<!--
|
||||
This task runs Java Cup to generate the Jasmin Parser (parser.java)
|
||||
from the CUP file (parser.cup) in the Jasmin src directory. You only need to
|
||||
run this task if you edit parser.cup.
|
||||
-->
|
||||
<target name="parser" depends="java_cup">
|
||||
<java classname="java_cup.Main" output="test.java" input="src/jasmin/parser.cup">
|
||||
<classpath>
|
||||
<pathelement location="${root.dir}/lib/java_cup.jar"/>
|
||||
</classpath>
|
||||
</java>
|
||||
<move file="parser.java" tofile="src/jasmin/parser.java"/>
|
||||
<move file="sym.java" tofile="src/jasmin/sym.java"/>
|
||||
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Build all jars in ./build -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="all" depends="jasmin,docs"/>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Creates the API documentation in ./docs/api/ -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="docs">
|
||||
<mkdir dir="${apidocs.dir}"/>
|
||||
<javadoc packagenames="${packages}"
|
||||
link="http://java.sun.com/j2se/1.4/docs/api"
|
||||
sourcepath="${src.dir}"
|
||||
destdir="${apidocs.dir}"
|
||||
author="true"
|
||||
additionalparam="-source 1.4"
|
||||
version="true"
|
||||
use="true"
|
||||
splitindex="true"
|
||||
noindex="false"
|
||||
windowtitle="${Name} API"
|
||||
doctitle="${Name}"
|
||||
bottom="Copyright © ${year} Jonathan Meyer, USA All rights reserved."
|
||||
/>
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Build source distribution in ./dist -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="sourcedist" depends="clean">
|
||||
<mkdir dir="${dist.root}"/>
|
||||
<mkdir dir="${sourcedist.dir}"/>
|
||||
|
||||
<copy todir="${sourcedist.dir}">
|
||||
<fileset dir="${root.dir}"/>
|
||||
</copy>
|
||||
|
||||
<!-- Now delete what we dont want, probably a better way to do this -->
|
||||
<delete dir="${sourcedist.dir}/dist"/>
|
||||
<delete dir="${sourcedist.dir}/classes"/>
|
||||
|
||||
<zip zipfile="${dist.root}/${name}-${version}.zip"
|
||||
basedir="${dist.root}/${name}-${version}"
|
||||
whenempty="create"
|
||||
/>
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Build compiled distribution in ./dist -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="compiledist" depends="clean, all">
|
||||
<mkdir dir="${dist.root}"/>
|
||||
<mkdir dir="${compiledist.dir}"/>
|
||||
|
||||
<copy todir="${compiledist.dir}">
|
||||
<fileset dir="${root.dir}"/>
|
||||
</copy>
|
||||
|
||||
<!-- Now delete what we dont want, probably a better way to do this -->
|
||||
<delete dir="${compiledist.dir}/dist"/>
|
||||
<delete dir="${compiledist.dir}/build"/>
|
||||
|
||||
|
||||
<zip zipfile="${dist.root}/${name}-${version}.zip"
|
||||
basedir="${dist.root}/${name}-${version}"
|
||||
whenempty="create"
|
||||
/>
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Clean restores distribution to original state -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="clean" depends="init">
|
||||
<delete dir="${build.dir}"/>
|
||||
<delete dir="${dist.root}"/>
|
||||
<delete dir="${apidocs.dir}"/>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
<!-- End of file -->
|
114
jasmin/jasmin-2.4/changes.txt
Normal file
114
jasmin/jasmin-2.4/changes.txt
Normal file
|
@ -0,0 +1,114 @@
|
|||
Jasmin Revision History Jonathan Meyer
|
||||
|
||||
15 Oct 2004 - Release 1.1
|
||||
|
||||
* Switched to Ant Build System
|
||||
|
||||
* Moved java_cup and jas sources into src directory
|
||||
|
||||
* Updated documentation to use style sheets
|
||||
|
||||
* Changed docs to reflect using jar files rather than class files
|
||||
|
||||
* Uploaded to SourceForge
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
11 Apr 97 - Release 1.06.
|
||||
|
||||
11 Apr 97
|
||||
|
||||
* Fixed bug which prevented the source name from being written out
|
||||
in the class file
|
||||
|
||||
* Improved README file
|
||||
|
||||
2 Mar 97 - Release 1.05.
|
||||
|
||||
1 Mar 97
|
||||
|
||||
* Moved scripts into a bin directory.
|
||||
|
||||
* Added support for Visual J++.
|
||||
|
||||
Added vjasmin.bat, for running Jasmin using Visual J++.
|
||||
|
||||
Converted JAS/Jasmin to use its own internal RuntimeConstants, so that
|
||||
there is no longer any dependency on Sun's version (needed by J++).
|
||||
|
||||
* Tidied API:
|
||||
|
||||
Renamed "Jasmin" class "ClassFile" (sorry to those of you using the API
|
||||
from 1.04). The ClassFile class is documented in the doc/api directory.
|
||||
|
||||
* Mods for Java 1.1:
|
||||
|
||||
Classes now set the ACC_SUPER bit in their access flags.
|
||||
i2b/i2s/i2c are now synonyms for int2byte, int2short, int2char.
|
||||
invokespecial is now a synonym for invokenonvirtual.
|
||||
|
||||
* Mods to pick up documentation in book:
|
||||
|
||||
"wide" is now a recognized instruction in Jasmin files - although the assembler
|
||||
just ignores it!
|
||||
|
||||
Added the optional <high> parameter to tableswitch.
|
||||
|
||||
* Fixed bug in .catch all
|
||||
|
||||
10 Feb 96 - Release 1.04.
|
||||
|
||||
8 Feb 97
|
||||
* Updated to use latest version of JAS. This fixes some bugs in the
|
||||
earlier release (including handling of _w instructions)
|
||||
|
||||
* Split several of the internal classes into smaller pieces.
|
||||
|
||||
* Restructured internal sources so that Jasmin, Scanner and parser
|
||||
no longer rely on static data structures. Now there is a public API
|
||||
to Jasmin, for people that want to assemble classes using their own
|
||||
data input/output streams.
|
||||
|
||||
30 Oct 96
|
||||
|
||||
* Added support for more \ escapes in quoted strings. In
|
||||
particular, you can now use \nnn to specify a character using
|
||||
octal.
|
||||
|
||||
2 Oct 96 - Release 1.03.
|
||||
|
||||
1 Oct 96
|
||||
|
||||
* Added better support for interfaces: added the .interface
|
||||
directive (an alternative to the .class directive), and also a
|
||||
.implements directive. Updates guide.html to mention these new
|
||||
features.
|
||||
|
||||
24 Sept 96
|
||||
|
||||
* Fixed several problems with guide.html - thanks to feedback from
|
||||
Shawn Silverman (umsilve1@cc.umanitoba.ca).
|
||||
|
||||
23 Aug 96
|
||||
|
||||
* Tidied up documentation and implementation for wide instructions.
|
||||
|
||||
Now ldc and ldc_w are used for single-word items, whereas
|
||||
ldc2_w is used for two word items (previously, I had ldc_w as
|
||||
a synonym for ldc2_w - oops).
|
||||
|
||||
25 July 96
|
||||
|
||||
* Added documentation for .var directive.
|
||||
|
||||
* Fixed line numbering produced by -g flag (I hope).
|
||||
|
||||
* Improved error reporting slightly.
|
||||
|
||||
24 July 96
|
||||
|
||||
* Added fix to scanner to handle Ctrl-M characters,
|
||||
for DOS/NT Systems. (Thanks sbk!)
|
||||
|
||||
18 July 96 - Release 1.0.
|
182
jasmin/jasmin-2.4/docs/about.html
Normal file
182
jasmin/jasmin-2.4/docs/about.html
Normal file
|
@ -0,0 +1,182 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>About Jasmin</title>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr><td width=550>
|
||||
<center>
|
||||
<p><img src=jasmin_icon.jpg></p>
|
||||
<p>
|
||||
<div class="h1">ABOUT JASMIN</div>
|
||||
Jonathan Meyer, July 1996
|
||||
</p>
|
||||
</center>
|
||||
|
||||
<h1>Introduction</h1>
|
||||
|
||||
This document tries to answer some questions you might have
|
||||
about Jasmin. In particular, several people have asked me what
|
||||
Jasmin is, why they might use Jasmin, and why I wrote it in the
|
||||
first place. I've tried to give some answers to these questions
|
||||
below.<p>
|
||||
|
||||
<h1>Jasmin Assembler</h1>
|
||||
|
||||
Jasmin is a Java Assembler Interface. It takes ASCII descriptions for Java
|
||||
classes, written in a simple assembler-like syntax using the Java Virtual
|
||||
Machine instructions set. It converts them into binary Java class files
|
||||
suitable for loading into a Java interpreter.<p>
|
||||
|
||||
To give you a flavor, here is the Jasmin assembly code for HelloWorld:<p>
|
||||
|
||||
<pre>
|
||||
.class public HelloWorld
|
||||
.super java/lang/Object
|
||||
|
||||
;
|
||||
; standard initializer (calls java.lang.Object's initializer)
|
||||
;
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
;
|
||||
; main() - prints out Hello World
|
||||
;
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
.limit stack 2 ; up to two items can be pushed
|
||||
|
||||
; push System.out onto the stack
|
||||
getstatic java/lang/System/out Ljava/io/PrintStream;
|
||||
|
||||
; push a string onto the stack
|
||||
ldc "Hello World!"
|
||||
|
||||
; call the PrintStream.println() method.
|
||||
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
|
||||
|
||||
; done
|
||||
return
|
||||
.end method
|
||||
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Jasmin was originally created as a companion to the book "Java Virtual Machine",
|
||||
written by Jon Meyer and Troy Downing and published by O'Reilly Associates. The
|
||||
book is now out of print. Jasmin survives as a SourceForge Open Source project.
|
||||
</p>
|
||||
|
||||
<h1>Motivation for Jasmin</h1>
|
||||
|
||||
<p>
|
||||
Jasmin was written because, at the time that we wrote the Java Virtual Machine
|
||||
book for O'Reilly, Sun had not published an assembler format for the
|
||||
Java virtual machine.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Generating a binary Java .class file is pretty fiddly. Its like
|
||||
creating an a.out (or .exe) file by hand. Even using a Java package like
|
||||
JAS (a Java API for creating class files, used internally by Jasmin and written by KB Sriram), you
|
||||
need to know a lot about the philosophy of the Java Virtual
|
||||
Machine before you can write something at the Virtual
|
||||
Machine level and generate a Java class. <p>
|
||||
|
||||
We wanted something that made it very easy for a student or programmer
|
||||
to explore the Java Virtual Machine, or write a new language
|
||||
which targets the VM, without getting into the details of constant
|
||||
pool indices, attribute tables, and so on.<p>
|
||||
|
||||
<p>
|
||||
Creating a Java assembler seemed like a good solution.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Unfortunately, Sun has not seen the need to define a standard Java
|
||||
assembler format, and has not released tools perform Java assembly.
|
||||
</p>
|
||||
|
||||
<p>Sun does provide a javap program which can print the assembly code
|
||||
in a class file. However, the javap output is inappropriate for
|
||||
use as an assembler format. It is designed to be read by a person,
|
||||
not to be parsed by an assembler, so it has a number of
|
||||
omissions and drawbacks. </p>
|
||||
|
||||
<p>
|
||||
Internally, Sun has a Java assembler tool. In hindsight, the syntax used by their internal tool is nicer than
|
||||
the Jasmin syntax. However, to my knowledge, their tool is still not widely available, nor is it a formally
|
||||
supported part of the Sun JDK.
|
||||
</p>
|
||||
|
||||
<h1>Update on Jasmin Today (2004) </h1>
|
||||
|
||||
Since Jasmin was written, it has become the de-facto standard assembly format for Java. It is used in dozens of compiler classes throughout the world, and has
|
||||
been ported and cloned multiple times. For better or worse, Jasmin remains the original Java assembler.
|
||||
<p>
|
||||
[As an interesting comparison, Microsoft .NET shipped out-of-box with an
|
||||
assembler, a disassembler, a standard IL assembly format, and built-in libraries
|
||||
for code-genning (generating classes on the fly). It would be great if Sun was
|
||||
as comprehensive in their support of the JVM].
|
||||
</p>
|
||||
|
||||
<h1>What can I do with Jasmin?</h1>
|
||||
|
||||
To give you some ideas, below are some theoretical Jasmin users/uses.<p>
|
||||
|
||||
<h3>Teachers</h3>
|
||||
|
||||
If you are teaching a compilers course, you could have students
|
||||
write a compiler which generates Jasmin assembly files,
|
||||
and then assembles those files into Java class files. Then you
|
||||
can integrate the advantages of the Virtual Machine (portability,
|
||||
the verifier, an object model...) into your courseware.<p>
|
||||
|
||||
<h3>Hobbyists</h3>
|
||||
|
||||
Jasmin lets you poke around in Java at the VM level, so that
|
||||
you can gain a real understanding of how Java works and
|
||||
what the Virtual Machine is like.<p>
|
||||
|
||||
<h3>System Implementors</h3>
|
||||
|
||||
If you are implementing a Java runtime system, Jasmin is
|
||||
an essential tool for generating test classes.<p>
|
||||
|
||||
<h3>Advanced Programmers</h3>
|
||||
|
||||
You could use Jasmin to write a critical class or method by
|
||||
hand (e.g. if you think that Java isn't doing things
|
||||
as well as it could). <p>
|
||||
|
||||
Alternatively, you could create a syntax extension to the
|
||||
Java language which uses Jasmin (or JAS). <p>
|
||||
|
||||
<h3>Language Implementors</h3>
|
||||
|
||||
If you want to create an implementation of your
|
||||
favorite programming language which targets the
|
||||
Virtual Machine, Jasmin may be a simpler approach than
|
||||
writing a Java class file generator. This is especially
|
||||
true if your compiler is implemented in something other
|
||||
than Java, since you can create Java class files easily
|
||||
without having to get involved in the details of the
|
||||
binary file format.<p>
|
||||
|
||||
<h3>Security Wizards</h3>
|
||||
|
||||
Sun's claim that the Java class verifier protects you from
|
||||
hostile programs is a pretty strong one. Jasmin lets you create
|
||||
'hostile' class files and see if a Java implementation is really as
|
||||
secure as it should be. <p>
|
||||
|
||||
<hr><address>Copyright (c) Jonathan Meyer, July 1996</address>
|
||||
|
||||
<hr>
|
||||
<a href="http://jasmin.sourceforge.net">Jasmin Home</a> |
|
||||
<a href="http://www.cybergrain.com/">Jon Meyer's Home</a>
|
||||
|
689
jasmin/jasmin-2.4/docs/guide.html
Normal file
689
jasmin/jasmin-2.4/docs/guide.html
Normal file
|
@ -0,0 +1,689 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Jasmin User Guide</title>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr><td width=550>
|
||||
<center>
|
||||
<p><img src=jasmin_icon.jpg></p>
|
||||
<p>
|
||||
<div class="h1">JASMIN USER GUIDE</div>
|
||||
Jonathan Meyer, July 1996
|
||||
</p>
|
||||
</center>
|
||||
|
||||
<h1>About This Document</h1>
|
||||
|
||||
This guide describes the rules and syntax used in Jasmin, and
|
||||
how to run Jasmin. Note that this document doesn't
|
||||
explain the Java Virtual Machine itself, or give syntax notes for
|
||||
every instruction known to Jasmin. See the Java Virtual Machine specification
|
||||
for more information on the JVM.<p>
|
||||
|
||||
<h1>What is Jasmin?</h1>
|
||||
|
||||
<p>
|
||||
Jasmin is an assembler for the Java Virtual Machine. It takes
|
||||
ASCII descriptions of Java classes, written in a simple
|
||||
assembler-like syntax using the Java Virtual
|
||||
Machine instruction set. It converts them into binary Java class files,
|
||||
suitable for loading by a Java runtime system.<p>
|
||||
</p>
|
||||
<p>
|
||||
Jasmin was originally created as a companion to the book "Java Virtual Machine",
|
||||
written by Jon Meyer and Troy Downing and published by O'Reilly Associates. The
|
||||
book is now out of print. Jasmin survives as a SourceForge Open Source project.
|
||||
</p>
|
||||
|
||||
<h1>Jasmin Design</h1>
|
||||
|
||||
<p>
|
||||
Jasmin is designed as a simple assembler. It has a clean easy-to-learn
|
||||
syntax with few bells and whistles. Where possible, Jasmin adopts a
|
||||
one-to-one mapping between its syntax and the conventions followed by Java class files.
|
||||
For example, package names in Jasmin are delimited with the '/' character
|
||||
(e.g. "java/lang/String") used by the class file format, instead
|
||||
of the '.' character (java.lang.String) used in the Java language.</p>
|
||||
|
||||
<p>
|
||||
The Jasmin assembler does little compile-time processing or
|
||||
checking of the input code. For example, it doesn't check that
|
||||
classes you reference actually exist, or that your type descriptors are
|
||||
well formed. Jasmin also lacks many of the feautures
|
||||
found in full macro assemblers. For example, it doesn't
|
||||
inline mathematical expressions, perform variable
|
||||
substitutions, or support macros.</p>
|
||||
|
||||
<p>
|
||||
On the other hand, using Jasmin you can quickly try out nearly
|
||||
all of the features of the Java Virtual Machine, including
|
||||
methods, fields, subroutines, exception handlers, and so on.
|
||||
The Jasmin syntax is also readable and compact.</p>
|
||||
|
||||
<h1>Running Jasmin</h1>
|
||||
<p>
|
||||
The <code>jasmin.jar</code> file is an executable JAR file that runs Jasmin.
|
||||
For example:</p>
|
||||
|
||||
<pre><strong> java -jar jasmin.jar myfile.j</strong></pre>
|
||||
|
||||
<p>assembles the file "myfile.j". Jasmin looks at the
|
||||
<code>.class</code> directive contained in the file to
|
||||
decide where to place the output class file. So if myfile.j starts
|
||||
with:</p>
|
||||
|
||||
<pre>
|
||||
.class mypackage/MyClass
|
||||
</pre>
|
||||
|
||||
<p>then Jasmin will place the output class file "MyClass.class" in the
|
||||
subdirectory "mypackage" of the current directory. It will create the
|
||||
mypackage directory if it doesn't exist.</p>
|
||||
|
||||
<p>You can use the "-d" option to tell jasmin to place the output
|
||||
in an alternative directory. For example,</p>
|
||||
|
||||
<pre><strong> java -jar jasmin.jar -d /tmp myfile.j </strong></pre>
|
||||
|
||||
<p>will place the output in /tmp/mypackage/MyClass.class.</p>
|
||||
|
||||
<p>Finally, you can use the "-g" option to tell Jasmin to include
|
||||
line number information (used by debuggers) in the resulting
|
||||
.class file. Jasmin will number the lines in the Jasmin source
|
||||
file that JVM instructions appear on. Then, if an error occurs,
|
||||
you can see what instruction in the Jasmin source caused the error.
|
||||
Note that specifying "-g" causes any .line directives within the
|
||||
Jasmin file to be ignored.
|
||||
</p>
|
||||
|
||||
<h1>Statements</h1>
|
||||
|
||||
<p>Jasmin source files consists of a sequence of newline-separated statements.
|
||||
There are three types of statement: </p>
|
||||
|
||||
<ul>
|
||||
<li>directives
|
||||
<li>instructions
|
||||
<li>labels
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Directives and instructions can take <i>parameters</i>. These parameters
|
||||
are placed on the same line as the directive or instruction,
|
||||
separated by spaces.</p>
|
||||
|
||||
<h3>Directives</h3>
|
||||
|
||||
<p>
|
||||
Directive statements are used to give Jasmin meta-level information.
|
||||
Directive statements consist of a directive name, and then zero or more
|
||||
parameters separated by spaces, then a newline.</p>
|
||||
|
||||
<p>
|
||||
All directive names start with a "." character. The directives in Jasmin are:</p>
|
||||
|
||||
<pre>
|
||||
.catch .class .end .field .implements .interface .limit .line
|
||||
.method .source .super .throws .var
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Some example directive statements are:</p>
|
||||
|
||||
<pre>
|
||||
.limit stack 10
|
||||
|
||||
.method public myMethod()V
|
||||
|
||||
.class Foo
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The parameters used by each directive are described in more detail
|
||||
later in the document.</p>
|
||||
|
||||
<h3>Instructions</h3>
|
||||
|
||||
<p>
|
||||
An instruction statement consists of an instruction name, zero or
|
||||
more parameters separated by spaces, and a newline.</p>
|
||||
|
||||
<p>
|
||||
Jasmin uses the standard mnemonics for JVM opcodes as instruction names.
|
||||
For example, aload_1, bipush and iinc are all Jasmin instruction names.</p>
|
||||
|
||||
<p>
|
||||
Here are some examples of instruction statements:</p>
|
||||
|
||||
<pre>
|
||||
ldc "Hello World"
|
||||
iinc 1 -1
|
||||
bipush 10
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
</p>See <a href="instructions.html">Jasmin Instructions</a> for more details on
|
||||
the syntax of instructions in Jasmin.</p>
|
||||
|
||||
|
||||
<h3>Labels</h3>
|
||||
|
||||
<p>
|
||||
</p>A Jasmin label statement consists of a name followed by a ':', and a newline.
|
||||
For example:</p>
|
||||
|
||||
<pre>
|
||||
Foo:
|
||||
|
||||
Label:
|
||||
</pre>
|
||||
|
||||
<p>Label names cannot start with a numeric digit, and cannot contain
|
||||
any of the special characters:</p>
|
||||
|
||||
<pre>
|
||||
= : . " -
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
You cannot use directive names or instruction names as labels. Other
|
||||
than that, there are few restrictions on label names.
|
||||
For example, you could use the label:</p>
|
||||
|
||||
<pre>
|
||||
#_1:
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Labels can only be used within method definitions. The names are
|
||||
local to that method.</p>
|
||||
|
||||
<h1>The Jasmin Tokenizer</h1>
|
||||
|
||||
<p>
|
||||
Jasmin tokenizes its input stream, splitting the stream into tokens
|
||||
by looking for whitespace characters (spaces, tabs and newlines).
|
||||
The tokenizer looks for:</p>
|
||||
|
||||
<ul>
|
||||
<li>directive names
|
||||
<li>instruction names
|
||||
<li>labels
|
||||
<li>comments
|
||||
<li>type descriptor names
|
||||
<li>class names
|
||||
<li>numbers and quoted strings
|
||||
<li>etc.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The rules used by the tokenizer are described below:</p>
|
||||
|
||||
<h3>Comments</h3>
|
||||
|
||||
<p>
|
||||
A comment is a token that starts with a ';' character, and
|
||||
terminates with the newline character at the end of the line. </p>
|
||||
|
||||
<p>
|
||||
Note that the semicolon must be preceded by a whitespace character (a space, tab, newline), i.e.
|
||||
embedded semicolons are ignored. For example,</p>
|
||||
|
||||
<pre>
|
||||
abc;def
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
is treated as a single token "abc;def", and</p>
|
||||
|
||||
<pre>
|
||||
Ljava/lang/String;
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
is the token "Ljava/lang/String;", whereas</p>
|
||||
|
||||
<pre>
|
||||
foo ; baz ding
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
is the token "foo" followed by a comment "baz ding".</p>
|
||||
|
||||
<h3>Numbers and Strings</h3>
|
||||
|
||||
<p>
|
||||
In Jasmin, only simple decimal and integer numeric formats are
|
||||
recognized. Floats in scientific or exponent format are not yet
|
||||
supported. Character codes and octal aren't currently supported either. This
|
||||
means you can have:</p>
|
||||
|
||||
<pre>
|
||||
1, 123, .25, 0.03, 0xA
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
but not</p>
|
||||
|
||||
<pre>
|
||||
1e-10, 'a', '\u123'
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Quoted strings are also very basic. The full range of
|
||||
backslash escape sequences are not supported yet, although "\n" and "\t"
|
||||
are.</p>
|
||||
|
||||
<h3>Class Names</h3>
|
||||
|
||||
<p></p>Class names in Jasmin should be written using the Java class file format
|
||||
conventions, so java.lang.String becomes java/lang/String.</p>
|
||||
|
||||
|
||||
<h3>Type Descriptors</h3>
|
||||
|
||||
<p>
|
||||
Type information is also written as they appear in class files (e.g.
|
||||
the descriptor I speficies an integer, [Ljava/lang/Thread; is an
|
||||
array of Threads, etc.).</p>
|
||||
|
||||
<h3>Methods</h3>
|
||||
|
||||
<p>
|
||||
Method names are specified using a single token, e.g.</p>
|
||||
|
||||
<pre>
|
||||
java/io/PrintStream/println(Ljava/lang/String;)V
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
is the method called "println" in the class java.io.PrintStream, which
|
||||
has the type descriptor "(Ljava/lang/String;)V" (i.e. it takes a String
|
||||
and returns no result). In general, a method specification
|
||||
is formed of three parts: the characters before the last '/' form the class
|
||||
name. The characters between the last '/' and '(' are the method name. The
|
||||
rest of the string is the type descriptor for the method.</p>
|
||||
|
||||
<pre>
|
||||
foo/baz/Myclass/myMethod(Ljava/lang/String;)V
|
||||
--------------- ---------------------
|
||||
| -------- |
|
||||
| | |
|
||||
class method descriptor
|
||||
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
As another example, you would call the Java method: </p>
|
||||
|
||||
<pre>
|
||||
class mypackage.MyClass {
|
||||
int foo(Object a, int b[]) { ... }
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
using:</p>
|
||||
|
||||
<pre>
|
||||
invokevirtual mypackage/MyClass/foo(Ljava/lang/Object;[I)I
|
||||
</pre>
|
||||
|
||||
<h3>Fields</h3>
|
||||
|
||||
<p>
|
||||
Field names are specified in Jasmin using two tokens, one giving the name
|
||||
and class of the field, the other giving its descriptor. For example:</p>
|
||||
|
||||
<pre>
|
||||
getstatic mypackage/MyClass/my_font Ljava/lang/Font;
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
gets the value of the field called "my_font" in the class mypackage.MyClass.
|
||||
The type of the field is "Ljava/lang/Font;" (i.e. a Font object).</p>
|
||||
|
||||
<h1>FILES</h1>
|
||||
|
||||
<p>
|
||||
Jasmin files start by giving information on the class
|
||||
being defined in the file - such as the name of the
|
||||
class, the name of the source file that the class originated from,
|
||||
the name of the superclass, etc.</p>
|
||||
|
||||
<p>
|
||||
Typically, a Jasmin file starts with the three directives:</p>
|
||||
|
||||
<pre>
|
||||
.source <source-file>
|
||||
.class <access-spec> <class-name>
|
||||
.super <class-name>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
For example, the file defining MyClass might start with the directives:</p>
|
||||
|
||||
<pre>
|
||||
.source MyClass.j
|
||||
.class public MyClass
|
||||
.super java/lang/Object
|
||||
</pre>
|
||||
|
||||
<h3>.source directive</h3>
|
||||
|
||||
<p>
|
||||
The .source directive is optional. It specifies the
|
||||
value of the "SourceFile" attribute for the class
|
||||
file. (This is used by Java to print out debugging info
|
||||
if something goes wrong in one of the methods in the class).
|
||||
If you generated the Jasmin file automatically (e.g. as the result of
|
||||
compiling a file written in another syntax) you should use the .source
|
||||
directive to tell Java the name of the originating file. Note that
|
||||
the source file name should not include any pathname. Use "foo.src"
|
||||
but not "/home/user/foo.src".</p>
|
||||
|
||||
<p>
|
||||
If no .source directive is given, the name of the Jasmin
|
||||
file you are compiling is used instead as the SourceFile attribute
|
||||
instead.</p>
|
||||
|
||||
<h3>.class and .super directives</h3>
|
||||
|
||||
<p>
|
||||
The .class and .super directive tell the JVM the name of this
|
||||
class and its superclass. These directives take parameters as
|
||||
follows:
|
||||
</p>
|
||||
|
||||
<dl>
|
||||
<dt><class-name></dt>
|
||||
<dd>is the full name of the class, including
|
||||
any package names. For example foo/baz/MyClass.<p>
|
||||
</dd>
|
||||
|
||||
<dt><access-spec></dt>
|
||||
<dd>defines access permissions and other attributes for
|
||||
the class. This is a list of zero or more of the following
|
||||
keywords:<p>
|
||||
<dl><dd>
|
||||
public, final, super, interface, abstract
|
||||
</dl>
|
||||
</dl>
|
||||
|
||||
<h3>.interface directive</h3>
|
||||
|
||||
<p>
|
||||
Note that, instead of using the directive .class,
|
||||
you can alternatively use the directive .interface. This has
|
||||
the same syntax as the .class directive, but indicates that the Jasmin file
|
||||
is defining a Java interface. e.g.</p>
|
||||
|
||||
<pre>
|
||||
.interface public foo
|
||||
</pre>
|
||||
|
||||
<h3>.implements directive</h3>
|
||||
|
||||
<p>
|
||||
After .source, .class and .super, you can list the
|
||||
interfaces that are implemented by the class you are defining, using
|
||||
the .implements directive. The syntax of .implements is:</p>
|
||||
|
||||
<pre>
|
||||
.implements <class-name>
|
||||
</pre>
|
||||
<p>
|
||||
where <class-name> has the same format as was used by .class and .super.
|
||||
For example:</p>
|
||||
|
||||
<pre>
|
||||
.class foo
|
||||
.super java/lang/Object
|
||||
.implements Edible
|
||||
.implements java/lang/Throwable
|
||||
</pre>
|
||||
|
||||
<h1>Field Definitions</h1>
|
||||
|
||||
<p>
|
||||
After the header information, the next section of the Jasmin file
|
||||
is a list of field definitions.</p>
|
||||
|
||||
<p>
|
||||
A field is defined using the .field directive:</p>
|
||||
|
||||
<pre>
|
||||
.field <access-spec> <field-name> <descriptor> [ = <value> ]
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
where:</p>
|
||||
|
||||
<dl>
|
||||
<dt><access-spec>
|
||||
<dd>is one of the keywords:
|
||||
<dl><dd>
|
||||
public, private, protected, static, final,
|
||||
volatile, transient
|
||||
</dl>
|
||||
</dl><p>
|
||||
|
||||
<dt><field-name>
|
||||
<dd>is the name of the field.<p>
|
||||
|
||||
<dt><descriptor>
|
||||
<dd>is its type descriptor.<p>
|
||||
|
||||
<dt><value>
|
||||
<dd>is an integer, a quoted string or a decimal number, giving the
|
||||
initial value of the field (for final fields).<p>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
For example, the Java field definition:</p>
|
||||
|
||||
<pre>
|
||||
public int foo;
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
becomes</p>
|
||||
|
||||
<pre>
|
||||
.field public foo I
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
whereas the constant:</p>
|
||||
|
||||
<pre>
|
||||
public static final float PI = 3.14;
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
becomes</p>
|
||||
|
||||
<pre>
|
||||
.field public static final PI F = 3.14
|
||||
</pre>
|
||||
|
||||
<h1>Method Definitions</h1>
|
||||
|
||||
<p>
|
||||
After listing the fields of the class, the rest of the Jasmin file lists
|
||||
methods defined by the class.</p>
|
||||
|
||||
<p>
|
||||
A method is defined using the basic form:</p>
|
||||
|
||||
<pre>
|
||||
.method <access-spec> <method-spec>
|
||||
<statements>
|
||||
.end method
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
where:</p>
|
||||
|
||||
<dl>
|
||||
<dt><access-spec>
|
||||
<dd>is one of the keywords: public, private, protected, static, final,
|
||||
synchronized, native, abstract<p>
|
||||
|
||||
<dt><method-spec>
|
||||
<dd>is the name and type descriptor of the method.<p>
|
||||
|
||||
<dt><statements>
|
||||
<dd>is the code defining the body of the method.<p>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
Method definitions cannot be nested. Also, Jasmin does not
|
||||
insert an implicit 'return' instruction at the end of a method. It is
|
||||
up to you to ensure that your methods return cleanly. So
|
||||
the most basic Jasmin method is something like:</p>
|
||||
|
||||
<pre>
|
||||
.method foo()V
|
||||
return ; must give a return statement
|
||||
.end method
|
||||
</pre>
|
||||
|
||||
<h3>Method Directives</h3>
|
||||
|
||||
<p>
|
||||
The following directives can be used only within method definitions:</p>
|
||||
|
||||
<dl>
|
||||
<dt><pre>.limit stack <integer></pre><p>
|
||||
<dd>Sets the maximum size of the operand stack
|
||||
required by the method.
|
||||
|
||||
<dt><pre>.limit locals <integer></pre><p>
|
||||
<dd>Sets the number of local variables
|
||||
required by the method.
|
||||
|
||||
<dt><pre>.line <integer></pre><p>
|
||||
<dd>This is used to tag the subsequent
|
||||
instruction(s) with a line number. Debuggers use this information,
|
||||
together with the name of the source file (see .source above)
|
||||
to show at what line in a method things went wrong. If you are
|
||||
generating Jasmin files by compiling a source file,
|
||||
this directive lets you indicate what line
|
||||
numbers in the source file produced corrosponding Jasmin
|
||||
instructions. For example:
|
||||
|
||||
<pre>
|
||||
.method foo()V
|
||||
.line 5
|
||||
bipush 10 // these instructions generated from line 5
|
||||
istore_2 // of the source file.
|
||||
.line 6
|
||||
...
|
||||
</pre>
|
||||
|
||||
<dt><pre>.var <var-number> is <name> <descriptor> from <label1> to <label2></pre><p>
|
||||
<dd>The .var directive is used to define the name, type descriptor and scope of
|
||||
a local variable number. This information is used by debuggers
|
||||
so that they can be more helpful when printing out the values of local
|
||||
variables (rather than printing just a local variable number, the
|
||||
debugger can actually print out the name of the variable). For example:
|
||||
|
||||
<pre>
|
||||
.method foo()V
|
||||
.limit locals 1
|
||||
|
||||
; declare variable 0 as an "int Count;"
|
||||
; whose scope is the code between Label1 and Label2
|
||||
;
|
||||
.var 0 is Count I from Label1 to Label2
|
||||
|
||||
Label1:
|
||||
bipush 10
|
||||
istore_0
|
||||
Label2:
|
||||
|
||||
return
|
||||
.end method
|
||||
</pre>
|
||||
|
||||
<dt><pre>.throws <classname></pre><p>
|
||||
<dd>Indicates that this method can throw
|
||||
exceptions of the type indicated by <classname>.
|
||||
e.g.
|
||||
<pre>
|
||||
.throws java/io/IOException
|
||||
</pre>
|
||||
|
||||
This information isn't required by Java runtime systems,
|
||||
but it is used by the Java compiler to check that methods
|
||||
either catch exceptions they can cause, or declare
|
||||
that they throw them.
|
||||
|
||||
<dt><pre>.catch <classname> from <label1> to <label2> using <label3></pre><p>
|
||||
<dd>Appends an entry to the end of the exceptions table for the
|
||||
method. The entry indicates that when an exception which is
|
||||
an instance of <classname> or one of its subclasses is thrown
|
||||
while executing the code between <label1> and <label2>, then
|
||||
the runtime system should jump to <label3>. e.g.<p>
|
||||
<pre>
|
||||
.catch java/io/IOException from L1 to L2 using IO_Handler
|
||||
</pre>
|
||||
|
||||
If classname is the keyword "all", then exceptions of any
|
||||
class are caught by the handler.<p>
|
||||
|
||||
</dl>
|
||||
|
||||
<h3>Abstract Methods</h3>
|
||||
|
||||
<p>
|
||||
To declare an abstract method, write a method with no body. e.g.</p>
|
||||
|
||||
<pre>
|
||||
.method abstract myAbstract()V
|
||||
.end method
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
note that abstract methods can have .throws directives, e.g.</p>
|
||||
|
||||
<pre>
|
||||
.method abstract anotherAbstract()V
|
||||
.throws java/io/IOException
|
||||
.end method
|
||||
</pre>
|
||||
|
||||
<h1>Instructions</h1>
|
||||
|
||||
<p>
|
||||
JVM instructions are placed between the <code>.method</code> and
|
||||
<code>.end method</code> directives. VM instructions can take zero or more
|
||||
parameters, depending on the type of instruction used. Some example
|
||||
instructions are shown below:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
iinc 1 -3 ; decrement local variable 1 by 3
|
||||
|
||||
bipush 10 ; push the integer 10 onto the stack
|
||||
|
||||
pop ; remove the top item from the stack.
|
||||
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="instructions.html">Jasmin Instructions</a> for more details on the syntax
|
||||
of instructions in Jasmin.
|
||||
</p>
|
||||
|
||||
<hr><address>Copyright (c) Jonathan Meyer, July 1996</address>
|
||||
<hr>
|
||||
<a href="http://jasmin.sourceforge.net">Jasmin Home</a> |
|
||||
<a href="http://www.cybergrain.com">Jon Meyer's Home</a>
|
||||
|
||||
</td></tr></table>
|
||||
</body>
|
||||
</html>
|
65
jasmin/jasmin-2.4/docs/index.html
Normal file
65
jasmin/jasmin-2.4/docs/index.html
Normal file
|
@ -0,0 +1,65 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Jasmin Home Page</title>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr><td width=550>
|
||||
<center>
|
||||
<p><img src=jasmin_icon.jpg></p>
|
||||
<p>
|
||||
<div class="h1">JASMIN HOME PAGE</div>
|
||||
Jonathan Meyer, Oct 2004
|
||||
</p>
|
||||
</center>
|
||||
|
||||
<h1>Introduction</h1>
|
||||
|
||||
<p>
|
||||
Jasmin is an assembler for the Java Virtual Machine. It takes
|
||||
ASCII descriptions of Java classes, written in a simple
|
||||
assembler-like syntax using the Java Virtual
|
||||
Machine instruction set. It converts them into binary Java class files,
|
||||
suitable for loading by a Java runtime system.<p>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Jasmin was originally created as a companion to the book "Java Virtual Machine",
|
||||
written by Jon Meyer and Troy Downing and published by O'Reilly Associates.
|
||||
Since then, it has become the de-facto standard assembly format for Java. It is used in dozens of compiler classes throughout the world, and has
|
||||
been ported and cloned multiple times. For better or worse, Jasmin remains the oldest and the original Java assembler.
|
||||
</p>
|
||||
<p>
|
||||
The O'Reilly JVM book is now out of print. Jasmin continues to survive as a SourceForge Open Source project.
|
||||
</p>
|
||||
|
||||
<h1>Documentation</h1>
|
||||
<dl>
|
||||
<dt>
|
||||
<a href = "http://jasmin.sourceforge.net">Jasmin Home Page</a>
|
||||
<dd>this file (on SourceForge.net).<p>
|
||||
|
||||
<dt>
|
||||
<a href = "guide.html">Jasmin User Guide</a>
|
||||
<dd>a brief user guide for using Jasmin.<p>
|
||||
|
||||
<dt><a href = "instructions.html">Jasmin Instructions</a>
|
||||
<dd>the syntax of JVM instructions in Jasmin.<p>
|
||||
|
||||
<dt>
|
||||
<a href = "about.html">About Jasmin</a>
|
||||
<dd>describes the background to Jasmin, who might find it interesting, etc.
|
||||
Includes an example piece of Jasmin assembler to look at.<p>
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
<hr><address>Copyright (c) Jonathan Meyer, 2004</address>
|
||||
<hr>
|
||||
<a href="http://jasmin.sourceforge.net">Jasmin Home</a> |
|
||||
<a href="http://www.cybergrain.com">Jon Meyer's Home</a>
|
||||
|
||||
</td></tr></table>
|
||||
</body>
|
||||
</html>
|
505
jasmin/jasmin-2.4/docs/instructions.html
Normal file
505
jasmin/jasmin-2.4/docs/instructions.html
Normal file
|
@ -0,0 +1,505 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Jasmin Instructions</title>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<table ID="Table1">
|
||||
<tr><td width=550>
|
||||
<center>
|
||||
<p><img src=jasmin_icon.jpg></p>
|
||||
<p>
|
||||
<div class="h1">JASMIN INSTRUCTIONS</div>
|
||||
Jonathan Meyer, July 1996
|
||||
</p>
|
||||
</center>
|
||||
|
||||
<h1>Introduction</h1>
|
||||
|
||||
This document shows the syntax and the types of parameters required by
|
||||
each Java VM instruction in Jasmin. It also shows brief illustrative
|
||||
examples.<p>
|
||||
|
||||
See <a href="guide.html">The Jasmin User Guide</a> for a description
|
||||
of other aspects of the Jasmin syntax.<p>
|
||||
|
||||
<h1>Local variable instructions</h1>
|
||||
|
||||
The following instructions use local variables:<p>
|
||||
|
||||
<pre>
|
||||
ret <var-num>
|
||||
aload <var-num>
|
||||
astore <var-num>
|
||||
dload <var-num>
|
||||
dstore <var-num>
|
||||
fload <var-num>
|
||||
fstore <var-num>
|
||||
iload <var-num>
|
||||
istore <var-num>
|
||||
lload <var-num>
|
||||
lstore <var-num>
|
||||
</pre>
|
||||
|
||||
for example:<p>
|
||||
|
||||
<pre>
|
||||
aload 1 ; push local variable 1 onto the stack
|
||||
ret 2 ; return to the address held in local variable 2
|
||||
</pre>
|
||||
|
||||
<h1>The bipush, sipush and iinc instructions</h1>
|
||||
|
||||
The bipush and sipush instructions take an integer as a
|
||||
parameter:<p>
|
||||
|
||||
<pre>
|
||||
bipush <int>
|
||||
sipush <int>
|
||||
</pre>
|
||||
|
||||
for example:<p>
|
||||
|
||||
<pre>
|
||||
bipush 100 ; push 100 onto the stack
|
||||
</pre>
|
||||
|
||||
The iinc instruction takes two integer parameters:<p>
|
||||
|
||||
<pre>
|
||||
iinc <var-num> <amount>
|
||||
</pre>
|
||||
|
||||
for example:<p>
|
||||
|
||||
<pre>
|
||||
iinc 3 -10 ; subtract 10 from local variable 3
|
||||
</pre>
|
||||
|
||||
<h1>Branch instructions</h1>
|
||||
|
||||
The following instructions take a label as a parameter:
|
||||
|
||||
<pre>
|
||||
goto <label>
|
||||
goto_w <label>
|
||||
if_acmpeq <label>
|
||||
if_acmpne <label>
|
||||
if_icmpeq <label>
|
||||
if_icmpge <label>
|
||||
if_icmpgt <label>
|
||||
if_icmple <label>
|
||||
if_icmplt <label>
|
||||
if_icmpne <label>
|
||||
ifeq <label>
|
||||
ifge <label>
|
||||
ifgt <label>
|
||||
ifle <label>
|
||||
iflt <label>
|
||||
ifne <label>
|
||||
ifnonnull <label>
|
||||
ifnull <label>
|
||||
jsr <label>
|
||||
jsr_w <label>
|
||||
</pre>
|
||||
|
||||
For example:<p>
|
||||
|
||||
<pre>
|
||||
|
||||
Label1:
|
||||
goto Label1 ; jump to the code at Label1
|
||||
; (an infinite loop!)
|
||||
|
||||
</pre>
|
||||
|
||||
<h1>Class and object operations</h1>
|
||||
|
||||
The following instructions take a class name
|
||||
as a parameter:
|
||||
|
||||
<pre>
|
||||
anewarray <class>
|
||||
checkcast <class>
|
||||
instanceof <class>
|
||||
new <class>
|
||||
</pre>
|
||||
|
||||
For example:<p>
|
||||
|
||||
<pre>
|
||||
new java/lang/String ; create a new String object
|
||||
</pre>
|
||||
|
||||
<h1>Method invokation</h1>
|
||||
|
||||
The following instructions are used to invoke methods:<p>
|
||||
|
||||
<pre>
|
||||
invokenonvirtual <method-spec>
|
||||
invokestatic <method-spec>
|
||||
invokevirtual <method-spec>
|
||||
</pre>
|
||||
|
||||
for example:<p>
|
||||
|
||||
<pre>
|
||||
|
||||
; invokes java.io.PrintStream.println(String);
|
||||
|
||||
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
|
||||
|
||||
</pre>
|
||||
|
||||
A method specification is formed of three parts: the characters before the
|
||||
last '/' form the class name. The characters between the last '/' and '(' are
|
||||
the method name. The rest of the string is the descriptor.<p>
|
||||
|
||||
<pre>
|
||||
foo/baz/Myclass/myMethod(Ljava/lang/String;)V
|
||||
--------------- ---------------------
|
||||
| -------- |
|
||||
| | |
|
||||
class method descriptor
|
||||
</pre>
|
||||
|
||||
|
||||
A special case is invokeinterface, which takes a <method-spec> and
|
||||
an integer indicating how many arguments the method takes:<p>
|
||||
|
||||
<pre>
|
||||
invokeinterface <method-spec> <num-args>
|
||||
</pre>
|
||||
|
||||
for example:<p>
|
||||
|
||||
<pre>
|
||||
invokeinterface foo/Baz/myMethod(I)V 1
|
||||
</pre>
|
||||
|
||||
<h1>Field manipulation instructions</h1>
|
||||
|
||||
The four instructions getfield, getstatic, putfield and
|
||||
putstatic have the form:<p>
|
||||
|
||||
<pre>
|
||||
getfield <field-spec> <descriptor>
|
||||
getstatic <field-spec> <descriptor>
|
||||
putfield <field-spec> <descriptor>
|
||||
putstatic <field-spec> <descriptor>
|
||||
</pre>
|
||||
|
||||
for example:
|
||||
|
||||
<pre>
|
||||
; get java.lang.System.out, which is a PrintStream
|
||||
getstatic java/lang/System/out Ljava/io/PrintStream;
|
||||
</pre>
|
||||
|
||||
<field-spec> is composed of two parts, a classname and a fieldname. The
|
||||
classname is all of the characters in the <field-spec> up to the last
|
||||
'/' character, and the fieldname is the rest of the characters after the last
|
||||
'/'. For example: <p>
|
||||
|
||||
<pre>
|
||||
foo/baz/AnotherClass/anotherFunField
|
||||
-- class name ------ --field name --
|
||||
</pre>
|
||||
|
||||
<descriptor> is the Java type descriptor of the field.
|
||||
For example:<p>
|
||||
|
||||
<pre>
|
||||
Ljava/io/PrintStream;
|
||||
</pre>
|
||||
|
||||
|
||||
<h1>The newarray instruction</h1>
|
||||
|
||||
The newarray instruction is followed by the type of the array,<p>
|
||||
|
||||
<pre>
|
||||
newarray <array-type>
|
||||
</pre>
|
||||
|
||||
for example:<p>
|
||||
|
||||
<pre>
|
||||
newarray int
|
||||
newarray short
|
||||
newarray float
|
||||
etc.
|
||||
</pre>
|
||||
|
||||
<h1>The multianewarray instruction</h1>
|
||||
|
||||
The multianewarray instruction takes two parameters,
|
||||
the type descriptor for the array and the number of
|
||||
dimensions to allocate:<p>
|
||||
|
||||
<pre>
|
||||
multianewarray <array-descriptor> <num-dimensions>
|
||||
</pre>
|
||||
|
||||
for example:<p>
|
||||
|
||||
<pre>
|
||||
multianewarray [[[I 2
|
||||
</pre>
|
||||
|
||||
<h1>The ldc and ldc_w instructions</h1>
|
||||
|
||||
The ldc and ldc_w instructions are followed by a constant:<p>
|
||||
|
||||
<pre>
|
||||
ldc <constant>
|
||||
ldc_w <constant>
|
||||
</pre>
|
||||
|
||||
<constant> is either an integer, a floating point number, or a
|
||||
quoted string. For example:<p>
|
||||
|
||||
<pre>
|
||||
ldc 1.2 ; push a float
|
||||
ldc 10 ; push an int
|
||||
ldc "Hello World" ; push a String
|
||||
ldc_w 3.141592654 ; push PI as a double
|
||||
</pre>
|
||||
|
||||
<h1>The lookupswitch instruction</h1>
|
||||
|
||||
The lookupswitch instruction has the syntax:<p>
|
||||
|
||||
<pre>
|
||||
<lookupswitch> ::=
|
||||
lookupswitch
|
||||
<int1> : <label1>
|
||||
<int2> : <label2>
|
||||
...
|
||||
default : <default-label>
|
||||
</pre>
|
||||
|
||||
For example:<p>
|
||||
|
||||
<pre>
|
||||
; If the int on the stack is 3, jump to Label1.
|
||||
; If it is 5, jump to Label2.
|
||||
; Otherwise jump to DefaultLabel.
|
||||
|
||||
lookupswitch
|
||||
3 : Label1
|
||||
5 : Label2
|
||||
default : DefaultLabel
|
||||
|
||||
Label1:
|
||||
... got 3
|
||||
|
||||
Label2:
|
||||
... got 5
|
||||
|
||||
DefaultLabel:
|
||||
... got something else
|
||||
</pre>
|
||||
|
||||
<h1>The tableswitch instruction</h1>
|
||||
|
||||
The tableswitch instruction has the syntax:<p>
|
||||
|
||||
<pre>
|
||||
<tableswitch> ::=
|
||||
tableswitch <low>
|
||||
<label1>
|
||||
<label2>
|
||||
...
|
||||
default : <default-label>
|
||||
</pre>
|
||||
|
||||
For example:<p>
|
||||
|
||||
<pre>
|
||||
; If the int on the stack is 0, jump to Label1.
|
||||
; If it is 1, jump to Label2.
|
||||
; Otherwise jump to DefaultLabel.
|
||||
|
||||
tableswitch 0
|
||||
Label1
|
||||
Label2
|
||||
default : DefaultLabel
|
||||
|
||||
Label1:
|
||||
... got 0
|
||||
|
||||
Label2:
|
||||
... got 1
|
||||
|
||||
DefaultLabel:
|
||||
... got something else
|
||||
</pre>
|
||||
|
||||
<h1>No parameter</h1>
|
||||
|
||||
The following instructions (the majority) take no parameters:<p>
|
||||
|
||||
<dl><dd>
|
||||
aaload
|
||||
aastore
|
||||
aconst_null
|
||||
aload_0
|
||||
aload_1
|
||||
aload_2
|
||||
aload_3
|
||||
areturn
|
||||
arraylength
|
||||
astore_0
|
||||
astore_1
|
||||
astore_2
|
||||
astore_3
|
||||
athrow
|
||||
baload
|
||||
bastore
|
||||
breakpoint
|
||||
caload
|
||||
castore
|
||||
d2f
|
||||
d2i
|
||||
d2l
|
||||
dadd
|
||||
daload
|
||||
dastore
|
||||
dcmpg
|
||||
dcmpl
|
||||
dconst_0
|
||||
dconst_1
|
||||
ddiv
|
||||
dload_0
|
||||
dload_1
|
||||
dload_2
|
||||
dload_3
|
||||
dmul
|
||||
dneg
|
||||
drem
|
||||
dreturn
|
||||
dstore_0
|
||||
dstore_1
|
||||
dstore_2
|
||||
dstore_3
|
||||
dsub
|
||||
dup
|
||||
dup2
|
||||
dup2_x1
|
||||
dup2_x2
|
||||
dup_x1
|
||||
dup_x2
|
||||
f2d
|
||||
f2i
|
||||
f2l
|
||||
fadd
|
||||
faload
|
||||
fastore
|
||||
fcmpg
|
||||
fcmpl
|
||||
fconst_0
|
||||
fconst_1
|
||||
fconst_2
|
||||
fdiv
|
||||
fload_0
|
||||
fload_1
|
||||
fload_2
|
||||
fload_3
|
||||
fmul
|
||||
fneg
|
||||
frem
|
||||
freturn
|
||||
fstore_0
|
||||
fstore_1
|
||||
fstore_2
|
||||
fstore_3
|
||||
fsub
|
||||
i2d
|
||||
i2f
|
||||
i2l
|
||||
iadd
|
||||
iaload
|
||||
iand
|
||||
iastore
|
||||
iconst_0
|
||||
iconst_1
|
||||
iconst_2
|
||||
iconst_3
|
||||
iconst_4
|
||||
iconst_5
|
||||
iconst_m1
|
||||
idiv
|
||||
iload_0
|
||||
iload_1
|
||||
iload_2
|
||||
iload_3
|
||||
imul
|
||||
ineg
|
||||
int2byte
|
||||
int2char
|
||||
int2short
|
||||
ior
|
||||
irem
|
||||
ireturn
|
||||
ishl
|
||||
ishr
|
||||
istore_0
|
||||
istore_1
|
||||
istore_2
|
||||
istore_3
|
||||
isub
|
||||
iushr
|
||||
ixor
|
||||
l2d
|
||||
l2f
|
||||
l2i
|
||||
ladd
|
||||
laload
|
||||
land
|
||||
lastore
|
||||
lcmp
|
||||
lconst_0
|
||||
lconst_1
|
||||
ldiv
|
||||
lload_0
|
||||
lload_1
|
||||
lload_2
|
||||
lload_3
|
||||
lmul
|
||||
lneg
|
||||
lor
|
||||
lrem
|
||||
lreturn
|
||||
lshl
|
||||
lshr
|
||||
lstore_0
|
||||
lstore_1
|
||||
lstore_2
|
||||
lstore_3
|
||||
lsub
|
||||
lushr
|
||||
lxor
|
||||
monitorenter
|
||||
monitorexit
|
||||
nop
|
||||
pop
|
||||
pop2
|
||||
return
|
||||
saload
|
||||
sastore
|
||||
swap
|
||||
</dl>
|
||||
|
||||
for example:
|
||||
|
||||
<pre>
|
||||
pop ; remove the top item from the stack
|
||||
iconst_1 ; push 1 onto the stack
|
||||
swap ; swap the top two items on the stack
|
||||
</pre>
|
||||
|
||||
<hr><address>Copyright (c) Jonathan Meyer, July 1996</address>
|
||||
<hr>
|
||||
<a href="http://mrl.nyu.edu/meyer/jvm/jasmin.html">Jasmin Home</a> |
|
||||
<a href="http://mrl.nyu.edu/meyer/">Jon Meyer's Home</a>
|
BIN
jasmin/jasmin-2.4/docs/jasmin_icon.jpg
Normal file
BIN
jasmin/jasmin-2.4/docs/jasmin_icon.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
BIN
jasmin/jasmin-2.4/docs/javavm.gif
Normal file
BIN
jasmin/jasmin-2.4/docs/javavm.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
16
jasmin/jasmin-2.4/docs/style.css
Normal file
16
jasmin/jasmin-2.4/docs/style.css
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
td { font-family: Verdana,Arial,Helvetica,sans-serif; color: #000000; font-size: 12px; line-height: 16px; }
|
||||
td h1 { font-family: Tahoma; padding: 1px; padding-left: 4px; color: white; background-color: #303030; font-size: 20px; line-height: 24px; font-weight: bold; }
|
||||
td h2{ font-family: Tahoma; color: #000000; font-size: 14px; line-height: 16px; font-weight: bold; }
|
||||
td h3 { font-family: Tahoma; color: #000000; font-size: 12px; line-height: 16px; font-weight: bold; }
|
||||
|
||||
.h1 { font-family: Times; color: #000000; font-size: 18px; line-height: 20px; font-weight: bold; }
|
||||
|
||||
/* main text hyperlinks */
|
||||
a { color: #b11; TEXT-DECORATION: underline; }
|
||||
a:visited {color: #b11}
|
||||
a:hover {color: #f88}
|
||||
|
||||
pre.code{ font-family: courier new; color: #202060; font-size: 12px; line-height: 14px;}
|
||||
font.code{ font-family: courier new; color: #202060; font-size: 12px; line-height: 14px;}
|
||||
|
88
jasmin/jasmin-2.4/docs/syntax.bnf
Normal file
88
jasmin/jasmin-2.4/docs/syntax.bnf
Normal file
|
@ -0,0 +1,88 @@
|
|||
Jasmin Syntax Jonathan Meyer, April 1996
|
||||
|
||||
This file contains a simplified BNF version of the Jasmin syntax.
|
||||
|
||||
jasmin_file ::=
|
||||
'.class' [ <access> ] <name> <break>
|
||||
'.super' <name> <break>
|
||||
[ <fields> ]
|
||||
[ <methods> ]
|
||||
|
||||
|
||||
<fields> ::= <field> [ <field> ... ]
|
||||
|
||||
<field> ::=
|
||||
'.field' <access> <name> <signature> [ = <default> ] <break>
|
||||
|
||||
<default> ::= <int> | <quoted_string> | <float>
|
||||
|
||||
|
||||
<methods> ::= <method> [ <method> ... ]
|
||||
|
||||
<method> ::=
|
||||
'.method' <access> <name> <break>
|
||||
[ <statements> ]
|
||||
'.end' 'method' <break>
|
||||
|
||||
<statements> ::= <statement> [ <statement> ... ]
|
||||
|
||||
<statement> ::=
|
||||
<directive> <break>
|
||||
|
|
||||
<instruction> <break>
|
||||
|
|
||||
<label> ':' <break>
|
||||
|
||||
<directive> ::=
|
||||
'.limit' 'stack' <val>
|
||||
|
|
||||
'.limit' 'locals' <val>
|
||||
|
|
||||
'.throws' <classname>
|
||||
|
|
||||
'.catch' <classname> 'from' <label1> 'to' <label2> 'using' <label3>
|
||||
|
||||
<instruction> ::= <simple_instruction> | <complex_instruction>
|
||||
|
||||
<simple_instruction> ::=
|
||||
<insn>
|
||||
|
|
||||
<insn> <int> <int>
|
||||
|
|
||||
<insn> <int>
|
||||
|
|
||||
<insn> <num>
|
||||
|
|
||||
<insn> <word>
|
||||
|
|
||||
<insn> <word> <int>
|
||||
|
|
||||
<insn> <word> <word>
|
||||
|
|
||||
<insn> <quoted_string>
|
||||
|
||||
<complex_instruction> ::=
|
||||
<lookupswitch>
|
||||
|
|
||||
<tableswitch>
|
||||
|
||||
<lookupswitch> ::=
|
||||
lookupswitch <nl>
|
||||
<int> : <label> <nl>
|
||||
<int> : <label> <nl>
|
||||
...
|
||||
default : <label>
|
||||
|
||||
<tableswitch> ::=
|
||||
tableswitch <low> <nl>
|
||||
<label> <nl>
|
||||
<label> <nl>
|
||||
...
|
||||
default : <label>
|
||||
|
||||
<access> ::= <access_item> [ <access_item> ... ]
|
||||
|
||||
<access_item> ::=
|
||||
'public' | 'private' | 'protected' | 'static' | 'final' |
|
||||
'synchronized' | 'volatile' | 'transient' | 'native' |
|
||||
'interface' | 'abstract'
|
52
jasmin/jasmin-2.4/examples/ANewArray.j
Normal file
52
jasmin/jasmin-2.4/examples/ANewArray.j
Normal file
|
@ -0,0 +1,52 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/ANewArray.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Shows how to use anewarray instruction
|
||||
; -------------------------------------------------------------------------
|
||||
;
|
||||
; This class demonstrates how to allocate a multidimensional
|
||||
; array using anewarray.
|
||||
;
|
||||
|
||||
.class public examples/ANewArray
|
||||
.super java/lang/Object
|
||||
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
.limit stack 4
|
||||
.limit locals 2
|
||||
|
||||
;
|
||||
; Allocates an array like:
|
||||
; String x[][] = new String[2][5]
|
||||
;
|
||||
|
||||
; Allocate spine for array and store it in local var 1
|
||||
; (i.e. String[2][])
|
||||
|
||||
iconst_2
|
||||
anewarray [Ljava/lang/String;
|
||||
astore_1
|
||||
|
||||
; allocate first array of String[5] and store it in index 0
|
||||
aload_1
|
||||
iconst_0
|
||||
bipush 5
|
||||
anewarray java/lang/String
|
||||
aastore
|
||||
|
||||
; allocate second array of String[5] and store it in index 1
|
||||
aload_1
|
||||
iconst_1
|
||||
bipush 5
|
||||
anewarray java/lang/String
|
||||
aastore
|
||||
|
||||
; done ...
|
||||
return
|
||||
.end method
|
31
jasmin/jasmin-2.4/examples/AnInterface.j
Normal file
31
jasmin/jasmin-2.4/examples/AnInterface.j
Normal file
|
@ -0,0 +1,31 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/AnInterface.j
|
||||
; Author: Jonathan Meyer, 1 Oct 1996
|
||||
; Purpose: A Java interface written in Jasmin
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
;
|
||||
; This file shows how to use Jasmin to define an interface. It
|
||||
; is like the Java code:
|
||||
;
|
||||
; interface public examples.AnInterface {
|
||||
; void foo();
|
||||
; }
|
||||
;
|
||||
; See examples.Implementor for an example of a class that implements
|
||||
; this interface.
|
||||
;
|
||||
|
||||
.interface public examples/AnInterface
|
||||
.super java/lang/Object
|
||||
|
||||
; (Interfaces should either inherit from Object, or from
|
||||
; another interface.)
|
||||
|
||||
;
|
||||
; declare abstract method foo() - note that the method body is empty.
|
||||
;
|
||||
.method abstract foo()V
|
||||
.end method
|
||||
|
||||
|
53
jasmin/jasmin-2.4/examples/Arrays.j
Normal file
53
jasmin/jasmin-2.4/examples/Arrays.j
Normal file
|
@ -0,0 +1,53 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/Arrays.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Example using JVM's anewarray and aaload/aastore
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
;
|
||||
; This illustrates how to use the various JVM array instructions - though
|
||||
; it doesn't actually do anything very interesting with the arrays.
|
||||
;
|
||||
|
||||
.class public examples/Arrays
|
||||
.super java/lang/Object
|
||||
|
||||
; standard initializer
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
.limit locals 2
|
||||
.limit stack 4
|
||||
|
||||
; creates a new array of strings,
|
||||
; like:
|
||||
; String[] myarray = new String[2];
|
||||
iconst_2
|
||||
anewarray java/lang/String
|
||||
astore_1 ; stores this in local variable 1
|
||||
|
||||
; this is like the code:
|
||||
; myarray[0] = args[0];
|
||||
|
||||
aload_1 ; push my array on the stack
|
||||
iconst_0
|
||||
aload_0 ; push the array argument to main() on the stack
|
||||
iconst_0
|
||||
aaload ; get its zero'th entry
|
||||
aastore ; and store it in my zero'th entry
|
||||
|
||||
; now print out myarray[0]
|
||||
|
||||
getstatic java/lang/System/out Ljava/io/PrintStream;
|
||||
aload_1
|
||||
iconst_0
|
||||
aaload
|
||||
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
|
||||
|
||||
; done
|
||||
return
|
||||
.end method
|
79
jasmin/jasmin-2.4/examples/Catch.j
Normal file
79
jasmin/jasmin-2.4/examples/Catch.j
Normal file
|
@ -0,0 +1,79 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/Catch.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Catching and throwing exceptions
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
;
|
||||
; This hows how to throw and catch Exceptions in Jasmin
|
||||
;
|
||||
|
||||
.class public examples/Catch
|
||||
.super java/lang/Object
|
||||
|
||||
; standard initializer
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object.<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
|
||||
.limit locals 3
|
||||
.limit stack 5
|
||||
|
||||
; set up a handler to catch subclasses of java.lang.Exception
|
||||
.catch java/lang/Exception from Label1 to Label2 using Handler
|
||||
|
||||
; store System.out in local variable 1
|
||||
getstatic java/lang/System/out Ljava/io/PrintStream;
|
||||
astore_1
|
||||
|
||||
; print out a message
|
||||
aload_1
|
||||
ldc " -- Before exception"
|
||||
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
|
||||
|
||||
; construct an instance of Exception, initialize it with a string,
|
||||
; throw it. This is like the Java statement :
|
||||
;
|
||||
; throw new Exception("My exception");
|
||||
;
|
||||
|
||||
Label1:
|
||||
new java/lang/Exception
|
||||
dup
|
||||
ldc "<my exception>"
|
||||
invokenonvirtual java/lang/Exception/<init>(Ljava/lang/String;)V
|
||||
athrow
|
||||
|
||||
Label2:
|
||||
aload_1
|
||||
ldc " -- After exception"
|
||||
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
|
||||
|
||||
return
|
||||
|
||||
; This is the handler for the exception
|
||||
|
||||
Handler:
|
||||
; store the exception in local variable 2
|
||||
astore_2
|
||||
|
||||
; print out a message
|
||||
aload_1
|
||||
ldc " -- Caught exception: "
|
||||
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
|
||||
|
||||
; call getMessage() to retrieve the message from the Exception...
|
||||
aload_1
|
||||
aload_2
|
||||
invokevirtual java/lang/Throwable/getMessage()Ljava/lang/String;
|
||||
; ... now print it
|
||||
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
|
||||
|
||||
; return to the code
|
||||
goto Label2
|
||||
|
||||
.end method
|
35
jasmin/jasmin-2.4/examples/Checkcast.j
Normal file
35
jasmin/jasmin-2.4/examples/Checkcast.j
Normal file
|
@ -0,0 +1,35 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/Checkcast.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Catching and throwing exceptions
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
;
|
||||
; Simple test for checkcast instruction
|
||||
;
|
||||
|
||||
.class examples/Checkcast
|
||||
.super java/lang/Object
|
||||
|
||||
;
|
||||
; standard initializer
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
.limit stack 2
|
||||
|
||||
; push System.out onto the stack
|
||||
getstatic java/lang/System/out Ljava/io/PrintStream;
|
||||
|
||||
; check that it is a PrintStream
|
||||
checkcast java/io/PrintStream
|
||||
|
||||
; done
|
||||
return
|
||||
.end method
|
56
jasmin/jasmin-2.4/examples/Count.j
Normal file
56
jasmin/jasmin-2.4/examples/Count.j
Normal file
|
@ -0,0 +1,56 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/Count.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Counts from 0 to 9, printing out the value
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
.class public examples/Count
|
||||
.super java/lang/Object
|
||||
|
||||
;
|
||||
; standard initializer
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
; set limits used by this method
|
||||
.limit locals 4
|
||||
.limit stack 3
|
||||
|
||||
; setup local variables:
|
||||
|
||||
; 1 - the PrintStream object held in java.lang.System.out
|
||||
getstatic java/lang/System/out Ljava/io/PrintStream;
|
||||
astore_1
|
||||
|
||||
; 2 - the integer 10 - the counter used in the loop
|
||||
bipush 10
|
||||
istore_2
|
||||
|
||||
; now loop 10 times printing out a number
|
||||
|
||||
Loop:
|
||||
|
||||
; compute 10 - <local variable 2> ...
|
||||
bipush 10
|
||||
iload_2
|
||||
isub
|
||||
invokestatic java/lang/String/valueOf(I)Ljava/lang/String;
|
||||
astore_3
|
||||
; ... and print it
|
||||
aload_1 ; push the PrintStream object
|
||||
aload_3 ; push the string we just created - then ...
|
||||
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
|
||||
|
||||
; decrement the counter and loop
|
||||
iinc 2 -1
|
||||
iload_2
|
||||
ifne Loop
|
||||
|
||||
; done
|
||||
return
|
||||
|
||||
.end method
|
5
jasmin/jasmin-2.4/examples/HelloWeb.html
Normal file
5
jasmin/jasmin-2.4/examples/HelloWeb.html
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
This shows how to run HelloApplet:<p>
|
||||
|
||||
<applet code="HelloWeb.class" width=350 height=75>
|
||||
</applet>
|
91
jasmin/jasmin-2.4/examples/HelloWeb.j
Normal file
91
jasmin/jasmin-2.4/examples/HelloWeb.j
Normal file
|
@ -0,0 +1,91 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/HelloWeb.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Demonstration of a Jasmin-created applet
|
||||
; -------------------------------------------------------------------------
|
||||
; HelloWeb.j
|
||||
|
||||
; This demonstrates how you can use Jasmin to create an applet.
|
||||
|
||||
; The code below is like the Java code:
|
||||
;
|
||||
; import java.applet.*;
|
||||
; import java.awt.*;
|
||||
;
|
||||
; public class HelloWeb extends Applet {
|
||||
; private Font font;
|
||||
;
|
||||
; public void init() {
|
||||
; font = new Font("Helvetica", Font.BOLD, 48);
|
||||
; }
|
||||
;
|
||||
; public void paint(Graphics g) {
|
||||
; g.setFont(font);
|
||||
; g.drawString("Hello World!", 25, 50);
|
||||
; }
|
||||
; }
|
||||
|
||||
|
||||
.class public HelloWeb
|
||||
.super java/applet/Applet
|
||||
|
||||
.field private font Ljava/awt/Font;
|
||||
|
||||
|
||||
; my init() method - allocate a font and assign it to this.font.
|
||||
|
||||
.method public init()V
|
||||
.limit stack 5
|
||||
|
||||
; Create a new Font and call its constructor with
|
||||
; "Helvetica", 1 (i.e. Font.BOLD), and 48.
|
||||
|
||||
new java/awt/Font
|
||||
dup
|
||||
ldc "Helvetica"
|
||||
iconst_1
|
||||
bipush 48
|
||||
invokenonvirtual java/awt/Font/<init>(Ljava/lang/String;II)V
|
||||
|
||||
; now store the Font on the stack in this.font
|
||||
aload_0
|
||||
swap
|
||||
putfield HelloWeb/font Ljava/awt/Font;
|
||||
|
||||
; done
|
||||
return
|
||||
.end method
|
||||
|
||||
; my paint() method - draws the string "Hello World!" using this.font.
|
||||
|
||||
.method public paint(Ljava/awt/Graphics;)V
|
||||
.limit stack 4
|
||||
.limit locals 2
|
||||
|
||||
; local variable 0 holds <this>
|
||||
; local variable 1 holds the java.awt.Graphics instance ('g').
|
||||
|
||||
; g.setFont(this.font);
|
||||
aload_1
|
||||
aload_0
|
||||
getfield HelloWeb/font Ljava/awt/Font;
|
||||
invokevirtual java/awt/Graphics/setFont(Ljava/awt/Font;)V
|
||||
|
||||
; g.drawString("Hello Web!", 25, 50);
|
||||
aload_1
|
||||
ldc "Hello Web!"
|
||||
bipush 25
|
||||
bipush 50
|
||||
invokevirtual java/awt/Graphics/drawString(Ljava/lang/String;II)V
|
||||
|
||||
; done
|
||||
return
|
||||
.end method
|
||||
|
||||
|
||||
; standard constructor
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/applet/Applet/<init>()V
|
||||
return
|
||||
.end method
|
BIN
jasmin/jasmin-2.4/examples/HelloWorld.class
Normal file
BIN
jasmin/jasmin-2.4/examples/HelloWorld.class
Normal file
Binary file not shown.
35
jasmin/jasmin-2.4/examples/HelloWorld.j
Normal file
35
jasmin/jasmin-2.4/examples/HelloWorld.j
Normal file
|
@ -0,0 +1,35 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/HelloWorld.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Prints out "Hello World!"
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
|
||||
.class public NoJad.j
|
||||
.super java/lang/Object
|
||||
|
||||
;
|
||||
; standard initializer
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
.limit stack 2
|
||||
.limit locals 2
|
||||
|
||||
bipush 2
|
||||
astore 0
|
||||
bipush 3
|
||||
astore 1
|
||||
|
||||
aload 0
|
||||
aload 1
|
||||
astore 0
|
||||
astore 1
|
||||
|
||||
return
|
||||
.end method
|
53
jasmin/jasmin-2.4/examples/Implementor.j
Normal file
53
jasmin/jasmin-2.4/examples/Implementor.j
Normal file
|
@ -0,0 +1,53 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/HelloWorld.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Shows how to define a class that implements an interface
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
;
|
||||
; This class implements the examples.AnInterface interface - see
|
||||
; AnInterface.j
|
||||
;
|
||||
.class public examples/Implementor
|
||||
.super java/lang/Object
|
||||
.implements examples/AnInterface
|
||||
|
||||
;
|
||||
; standard initializer
|
||||
;
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
;
|
||||
; implement the foo()V method - this is an interface method
|
||||
;
|
||||
.method public foo()V
|
||||
.limit stack 2
|
||||
|
||||
; print a simple message
|
||||
getstatic java/lang/System/out Ljava/io/PrintStream;
|
||||
ldc "Hello Interface"
|
||||
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
|
||||
|
||||
; done
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
.limit stack 2
|
||||
|
||||
; create a new one of me
|
||||
new examples/Implementor
|
||||
dup
|
||||
invokenonvirtual examples/Implementor/<init>()V
|
||||
|
||||
; now call my interface method foo()
|
||||
invokeinterface examples/AnInterface/foo()V 1
|
||||
|
||||
return
|
||||
.end method
|
||||
|
45
jasmin/jasmin-2.4/examples/InvokeInterface.j
Normal file
45
jasmin/jasmin-2.4/examples/InvokeInterface.j
Normal file
|
@ -0,0 +1,45 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/InvokeInterface.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Example of using invokeinterface
|
||||
; -------------------------------------------------------------------------
|
||||
;
|
||||
; Demonstrates invoking an interface method
|
||||
;
|
||||
|
||||
.class public examples/InvokeInterface
|
||||
.super java/lang/Object
|
||||
|
||||
; standard initializer
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
;
|
||||
; This is a rather silly example - since the result of calling the
|
||||
; interface method isn't actually used. But it does illustrate how to
|
||||
; use invokeinterface.
|
||||
;
|
||||
|
||||
.method public example(Ljava/util/Enumeration;)V
|
||||
.limit stack 1
|
||||
.limit locals 3
|
||||
|
||||
; push local variable 1 (the Enumeration object)
|
||||
aload_1
|
||||
|
||||
; now call the hasMoreElements() interface method.
|
||||
invokeinterface java/util/Enumeration/hasMoreElements()Z 1
|
||||
|
||||
; store the integer result in local variable 2
|
||||
istore_2
|
||||
|
||||
; done
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
return
|
||||
.end method
|
37
jasmin/jasmin-2.4/examples/MultiANewArray.j
Normal file
37
jasmin/jasmin-2.4/examples/MultiANewArray.j
Normal file
|
@ -0,0 +1,37 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/MultiANewArray.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Example of multanewarray instruction
|
||||
; -------------------------------------------------------------------------
|
||||
;
|
||||
; This illustrates how to use multianewarray to allocate
|
||||
; an array.
|
||||
;
|
||||
|
||||
.class public examples/MultiANewArray
|
||||
.super java/lang/Object
|
||||
|
||||
; standard initializer
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
|
||||
.limit locals 4
|
||||
.limit stack 2
|
||||
|
||||
;
|
||||
; This allocates an array like:
|
||||
;
|
||||
; String s[][] = new String[2][5];
|
||||
;
|
||||
iconst_2
|
||||
iconst_5
|
||||
multianewarray [[Ljava/lang/String; 2
|
||||
astore_1
|
||||
|
||||
return
|
||||
.end method
|
55
jasmin/jasmin-2.4/examples/MultiArrays.j
Normal file
55
jasmin/jasmin-2.4/examples/MultiArrays.j
Normal file
|
@ -0,0 +1,55 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/MultiArrays.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Examples involving multi-dimensional arrays
|
||||
; -------------------------------------------------------------------------
|
||||
;
|
||||
; This illustrates how to use multi-dimensional arrays in the Java VM
|
||||
; (though it doesn't actually do anything very interesting with the arrays.)
|
||||
;
|
||||
|
||||
.class public examples/MultiArrays
|
||||
.super java/lang/Object
|
||||
|
||||
; standard initializer
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
|
||||
.limit locals 4
|
||||
.limit stack 5
|
||||
|
||||
; this is like:
|
||||
; new int[2][5][]
|
||||
iconst_2
|
||||
iconst_5
|
||||
multianewarray [[[I 2
|
||||
|
||||
; store the result in local variable 1
|
||||
astore_1
|
||||
|
||||
aload_1
|
||||
iconst_1
|
||||
aaload ; stack now contains x[0]
|
||||
astore_2 ; store the array in local variable 2
|
||||
|
||||
; create a new array of 50 ints and store it in x[1][1]
|
||||
aload_2
|
||||
iconst_1
|
||||
bipush 50
|
||||
newarray int
|
||||
aastore
|
||||
|
||||
; create a new array of 60 ints and store it in x[1][2]
|
||||
aload_2
|
||||
iconst_2
|
||||
bipush 60
|
||||
newarray int
|
||||
aastore
|
||||
|
||||
return
|
||||
.end method
|
41
jasmin/jasmin-2.4/examples/NewArray.j
Normal file
41
jasmin/jasmin-2.4/examples/NewArray.j
Normal file
|
@ -0,0 +1,41 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/NewArray.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Example of newarray
|
||||
; -------------------------------------------------------------------------
|
||||
;
|
||||
; Example showing how to allocate an array using
|
||||
; newarray.
|
||||
;
|
||||
|
||||
.class public examples/NewArray
|
||||
.super java/lang/Object
|
||||
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
.limit stack 4
|
||||
.limit locals 2
|
||||
|
||||
; create an array like:
|
||||
;
|
||||
; boolean b[] = new boolean[2]
|
||||
;
|
||||
; (stores it in local var 1)
|
||||
|
||||
iconst_2
|
||||
newarray boolean
|
||||
astore_1
|
||||
|
||||
; b[0] = true;
|
||||
aload_1
|
||||
iconst_0
|
||||
iconst_1
|
||||
bastore
|
||||
|
||||
return
|
||||
.end method
|
41
jasmin/jasmin-2.4/examples/Switch.j
Normal file
41
jasmin/jasmin-2.4/examples/Switch.j
Normal file
|
@ -0,0 +1,41 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/Switch.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Shows usage of lookupswitch and tableswitch
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
;
|
||||
; Illustrates lookupswitch and tableswitch syntax for Jasmin
|
||||
;
|
||||
|
||||
.class public examples/Switch
|
||||
.super java/lang/Object
|
||||
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
.limit stack 3
|
||||
|
||||
iconst_1
|
||||
lookupswitch
|
||||
1 : Hello
|
||||
2 : Goodbye
|
||||
default : Foo
|
||||
|
||||
iconst_1
|
||||
tableswitch 0
|
||||
Hello
|
||||
Goodbye
|
||||
default : Foo
|
||||
|
||||
Hello:
|
||||
Goodbye:
|
||||
Foo:
|
||||
|
||||
return
|
||||
|
||||
.end method
|
36
jasmin/jasmin-2.4/examples/Uncaught.j
Normal file
36
jasmin/jasmin-2.4/examples/Uncaught.j
Normal file
|
@ -0,0 +1,36 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/Uncaught.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Throws an exception - doesn't catch it
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
;
|
||||
; This example class contains a main() method that throws
|
||||
; an exception but doesn't catch it -
|
||||
;
|
||||
.source Uncaught.j
|
||||
.class public examples/Uncaught
|
||||
.super java/lang/Object
|
||||
|
||||
; specify the initializer method (as for HelloWorld)
|
||||
|
||||
.method public <init>()V
|
||||
; just call Object's initializer
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
; specify the "main" method - this throws an uncaught exception
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
.limit stack 2
|
||||
|
||||
new java/lang/Exception
|
||||
dup
|
||||
invokenonvirtual java/lang/Exception/<init>()V
|
||||
athrow
|
||||
|
||||
; without this the verifier might complain ...
|
||||
return
|
||||
.end method
|
41
jasmin/jasmin-2.4/examples/VerifyTest.j
Normal file
41
jasmin/jasmin-2.4/examples/VerifyTest.j
Normal file
|
@ -0,0 +1,41 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/VerifyTest.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Treats an int as an object - should alert the Verifier
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
;
|
||||
; This code demonstrates the verifier at work. See also VerifyTest1.j.
|
||||
;
|
||||
; The main() method below tries to clone the integer 100 - this
|
||||
; is clearly an error since clone() expects an Object, not an integer.
|
||||
;
|
||||
; If you run this with no verification on, it is likely to crash the
|
||||
; interpreter. Running this with the -verify option produces a
|
||||
; Verifier error.
|
||||
;
|
||||
|
||||
; This is similar to the Java code:
|
||||
;
|
||||
; class VerifyTest {
|
||||
; public static void main(String args[]) {
|
||||
; int x = 100;
|
||||
; x.clone();
|
||||
; }
|
||||
; }
|
||||
|
||||
|
||||
.class public examples/VerifyTest
|
||||
.super java/lang/Object
|
||||
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
bipush 100
|
||||
invokevirtual java/lang/Object/clone()Ljava/lang/Object;
|
||||
return
|
||||
.end method
|
62
jasmin/jasmin-2.4/examples/VerifyTest1.j
Normal file
62
jasmin/jasmin-2.4/examples/VerifyTest1.j
Normal file
|
@ -0,0 +1,62 @@
|
|||
; --- Copyright Jonathan Meyer 1996. All rights reserved. -----------------
|
||||
; File: jasmin/examples/VerifyTest1.j
|
||||
; Author: Jonathan Meyer, 10 July 1996
|
||||
; Purpose: Trys to pull one on the verifier
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
; This file illustrates the bytecode verifier at work - the
|
||||
; code in the example() method below seems reasonable, but
|
||||
; Java's bytecode verifier will fail the code because the two points leading
|
||||
; to the Loop label (from the top of the method and from the ifne
|
||||
; statement) have different stack states. Instead, a different approach
|
||||
; must be adopted - e.g. by allocating an array, or simply writing:
|
||||
;
|
||||
; aconst_null
|
||||
; aconst_null
|
||||
; aconst_null
|
||||
; aconst_null
|
||||
|
||||
; Note that many interpreters will run this code OK if you don't use
|
||||
; a verifier. The code itself is well behaved (it doesn't trash the
|
||||
; interpreter), but the approach it uses is disallowed by the verifier.
|
||||
;
|
||||
|
||||
; Compile the example, then run it using:
|
||||
;
|
||||
; % java -verify VerifyTest1
|
||||
; VERIFIER ERROR VerifyTest1.example()V:
|
||||
; Inconsistent stack height 1 != 0
|
||||
;
|
||||
|
||||
.class public examples/VerifyTest1
|
||||
.super java/lang/Object
|
||||
|
||||
.method public <init>()V
|
||||
aload_0
|
||||
invokenonvirtual java/lang/Object/<init>()V
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public example()V
|
||||
.limit locals 2
|
||||
.limit stack 10
|
||||
|
||||
; this tries to push four nulls onto the stack
|
||||
; using a loop - Java's verifier will fail this program
|
||||
|
||||
iconst_4 ; store 4 in local variable 1 (used as a counter)
|
||||
istore_1
|
||||
|
||||
Loop:
|
||||
aconst_null ; push null onto the stack
|
||||
iinc 1 -1 ; decrement local variable 4 (the counter variable)
|
||||
iload_1
|
||||
ifne Loop ; jump back to Loop unless the variable has reached 0
|
||||
|
||||
return
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
; - do nothing : this is only to illustrate the bytecode verifier at work.
|
||||
return
|
||||
.end method
|
BIN
jasmin/jasmin-2.4/html2x/jasmin_icon.jpg
Normal file
BIN
jasmin/jasmin-2.4/html2x/jasmin_icon.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
16
jasmin/jasmin-2.4/html2x/style.css
Normal file
16
jasmin/jasmin-2.4/html2x/style.css
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
td { font-family: Verdana,Arial,Helvetica,sans-serif; color: #000000; font-size: 12px; line-height: 16px; }
|
||||
td h1 { font-family: Tahoma; padding: 1px; padding-left: 4px; color: white; background-color: #303030; font-size: 20px; line-height: 24px; font-weight: bold; }
|
||||
td h2{ font-family: Tahoma; color: #000000; font-size: 14px; line-height: 16px; font-weight: bold; }
|
||||
td h3 { font-family: Tahoma; color: #000000; font-size: 12px; line-height: 16px; font-weight: bold; }
|
||||
|
||||
.h1 { font-family: Times; color: #000000; font-size: 18px; line-height: 20px; font-weight: bold; }
|
||||
|
||||
/* main text hyperlinks */
|
||||
a { color: #b11; TEXT-DECORATION: underline; }
|
||||
a:visited {color: #b11}
|
||||
a:hover {color: #f88}
|
||||
|
||||
pre.code{ font-family: courier new; color: #202060; font-size: 12px; line-height: 14px;}
|
||||
font.code{ font-family: courier new; color: #202060; font-size: 12px; line-height: 14px;}
|
||||
|
414
jasmin/jasmin-2.4/html2x/xt.html
Normal file
414
jasmin/jasmin-2.4/html2x/xt.html
Normal file
|
@ -0,0 +1,414 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Jasmin User Guide</title>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr><td width=550>
|
||||
<center>
|
||||
<p><img src=jasmin_icon.jpg></p>
|
||||
<p>
|
||||
<div class="h1">JasminXT Syntax</div>
|
||||
Daniel Reynaud, Mart 2006
|
||||
</p>
|
||||
</center>
|
||||
|
||||
<h1>About This Document</h1>
|
||||
|
||||
This guide describes the rules and syntax used in JasminXT, the extension of
|
||||
the Jasmin language in version 2.0. If you are new to Jasmin, you should
|
||||
refer to the Jasmin user guide. Note that this document doesn't
|
||||
explain the Java Virtual Machine itself, or give syntax notes for
|
||||
every instruction known to Jasmin. See the Java Virtual Machine specification
|
||||
for more information on the JVM.<p>
|
||||
|
||||
|
||||
<h1>Why a new Jasmin language ?</h1>
|
||||
|
||||
<p>
|
||||
Jasmin is the de-facto standard Java assembly language. It is useful to explore
|
||||
the possibilities of bytecode, but it does not offer a real low level control
|
||||
over the produced output. Therefore it is not suitable to generate test cases
|
||||
for virtual machines or bytecode verifier. This new version of the Jasmin
|
||||
language, called JasminXT, provides optional directives and other syntax
|
||||
updates to have more control over the output and to stick with the latest
|
||||
changes of the Java language.</p>
|
||||
|
||||
<p>JasminXT has been defined for the tinapoc project. The purpose of the tinapoc
|
||||
project is to create a reliable Java reverse engineering toolkit. See the tinapoc
|
||||
homepage for more information : <a href="http://tinapoc.sourceforge.net/">http://tinapoc.sourceforge.net/</a></p>
|
||||
|
||||
<h1>Summary of the new features</h1>
|
||||
<p>
|
||||
<b>Since 2.4 :</b><br>
|
||||
<li> accept 'd'-suffix in float constant (no attempt cast to float)
|
||||
<li> redesign to dynamic compiler class creation
|
||||
<li> some cosmetic bugfixes
|
||||
<br><br>
|
||||
<b>Since 2.3 :</b><br>
|
||||
<li> added 'wide'-aliases to two-face instructions
|
||||
<br><br>
|
||||
<b>Since 2.2 :</b><br>
|
||||
<li> some bug fixes in the diagnostic
|
||||
<li> added support for attribute StackMapTable (directive .stack) described in JDK1.6
|
||||
<li> added keyword 'use' to directive .stack
|
||||
<li> added support for \uXXXX escape sequence in the names (just as in the Java)
|
||||
<li> instruction ldc_w always generates wide index
|
||||
<li> changed syntaxes of the non-standard identifiers (or overloaded keywords), now it hasto be signgle quoted and can't be empty
|
||||
<br><br>
|
||||
<b>Since 2.1 :</b><br>
|
||||
<li> some bug fixes with string and number parsing
|
||||
<li> added support for \uXXXX escape sequences
|
||||
<li> added support for access flags ACC_STRICT (fpstrict) and ACC_SYNTHETIC (synthetic)
|
||||
<li> added signatures for local variables support
|
||||
<li> several .debug directives are permitted
|
||||
<li> added the invokedynamic instruction
|
||||
<li> improved the syntax of the StackMap attribute (.stack directive)
|
||||
<li> new command-line option -e to support different encodings
|
||||
<li> added support for non-standard identifiers in double-quotes
|
||||
<li> fields can now be defined on multiple lines
|
||||
<li> new directives have been included : .inner, .attribute, .deprecated, .annotation
|
||||
<br><br>
|
||||
<b>Since 2.0 :</b><br><br>
|
||||
<li>use of offsets for branch targets, local variable visibility and exception handlers. The offsets can either be absolute or relative :<br>
|
||||
<pre>
|
||||
goto 12 ; absolute offset : go to bytecode at offset 12
|
||||
goto +5 ; relative offset : go 12 bytes forward
|
||||
goto -8 ; relative offset : go 8 bytes backwards
|
||||
</pre>
|
||||
|
||||
<li>the following access flags are now supported : ACC_ENUM, ACC_ANNOTATION, ACC_BRIDGE and ACC_VARARGS<br>
|
||||
|
||||
<li>the .bytecode directive has been added, to set the bytecode version in the class file.<br>
|
||||
Example : <pre>.bytecode 49.0</pre><br>
|
||||
|
||||
<li>it is now possible to add a SourceDebugExtension attribute to the class with the following directive :<br>
|
||||
<pre>.debug "some string here"</pre><br>
|
||||
|
||||
<li>same thing for the EnclosingMethod attribute :<br>
|
||||
<pre>.enclosing method "some/package/Foo/someMethod(I)V"</pre><br>
|
||||
|
||||
<li>support for the Signature attribute (in the classes, methods and fields) :<br>
|
||||
<pre>.signature "<my::own>Signature()"
|
||||
.field myField Ljava/lang/String; signature "<my::own>Signature()"</pre><br>
|
||||
|
||||
<li>support for the StackMap attribute, using the .stack directive in a method definition<br>
|
||||
|
||||
<li>it is now possible to give the offset of an instruction before the instruction itself, like in the following code snippet :<br>
|
||||
<pre>
|
||||
0: aload_0
|
||||
1: invokespecial java/lang/Object/<init>()V
|
||||
4: aload_0
|
||||
5: ldc2_w 3.14159
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
<h1>JasminXT File Format</h1>
|
||||
<p>
|
||||
This new version is an extension of the existing Jasmin language, therefore old
|
||||
Jasmin files should still compile correctly with newer versions of Jasmin.
|
||||
JasminXT is supported by Jasmin 2.0 or higher. <b>Changes in Jasmin 2.4 are in bold.</b></p>
|
||||
|
||||
<p>
|
||||
In the rest of this document, words between '[' and ']' are optional. The
|
||||
syntax of a JasminXT file is the following :</p>
|
||||
|
||||
<pre>
|
||||
<jas_file> {
|
||||
<jasmin_header>
|
||||
[<field>]*
|
||||
[<method>]*
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h1>JasminXT Header</h1>
|
||||
<pre>
|
||||
<jasmin_header> {
|
||||
[.bytecode <x.y>]
|
||||
[.source <sourcefile>]
|
||||
<class_spec>
|
||||
<super_spec>
|
||||
<implements>
|
||||
[.signature "<signature>"]
|
||||
[.enclosing method <method_name>]
|
||||
[.debug "<debug_source_extension>"]*
|
||||
[.inner class [<access>] [<name>] [inner <classname>] [outer <name>]]*
|
||||
[.inner interface [<access>] [<name>] [inner <classname>] [outer <name>]]*
|
||||
}
|
||||
|
||||
example :
|
||||
.bytecode 49.0
|
||||
.source hello.j
|
||||
.class hello
|
||||
.super java/lang/Object
|
||||
.signature "<my::own>Signature()"
|
||||
.enclosing method foo/bar/Whatever/someMethod()</pre>
|
||||
.debug "this string will be included in the SourceDebugExtension attribute"
|
||||
.debug "this string too"
|
||||
|
||||
<p>The .bytecode directive sets the version of the bytecode in the class file.</p>
|
||||
|
||||
<p>The .signature directive, when used in the header of the Jasmin file, sets the
|
||||
Signature attribute for the class (the argument is a string between double
|
||||
quotes)</p>
|
||||
|
||||
<p>The .enclosing directive sets the EnclosingMethod attribute for the class. The
|
||||
argument is a supposed to be a method name, but it can be any string between
|
||||
double quotes.</p>
|
||||
|
||||
<p>The .debug directive sets the SourceDebugExtension attribute for the class (the
|
||||
argument is also a string between double quotes)</p>
|
||||
|
||||
|
||||
|
||||
<h1>JasminXT Class, Super Class and Interfaces Definition</h1>
|
||||
<pre>
|
||||
<class_spec> {
|
||||
.class <access_spec> <class_name>
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>where <access_spec> is any number of words taken from this list : public,
|
||||
private, protected, static, final, synchronized, native, final, super,
|
||||
interface, abstract, annotation, enum, bridge/volatile, transient/varargs</p>
|
||||
|
||||
<p>and <class_name> is the fully qualified internal form of the class, such as
|
||||
my/package/MyClass</p><br>
|
||||
|
||||
|
||||
<pre>
|
||||
<super_spec> {
|
||||
.super <class_name>
|
||||
}
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
<implements> {
|
||||
.implements <class_name>*
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
The .super and .implements directives have not been modified in JasminXT<br>
|
||||
The .implements directive can be repeated in order to implement multiple interfaces</p><br>
|
||||
|
||||
|
||||
|
||||
<h1>JasminXT Field Definition</h1>
|
||||
<pre>
|
||||
<field> {
|
||||
.field <access_spec> <field_name> <descriptor> [signature <signature>]
|
||||
[ = <value> ]
|
||||
|
|
||||
.field <access_spec> <field_name> <descriptor> [signature <signature>]
|
||||
[ = <value> ]
|
||||
[<field_attribute>]*
|
||||
.end field
|
||||
(...)
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
If present, the Signature attribute will be set in the class file for this field with the given
|
||||
quoted string as an argument.</p>
|
||||
|
||||
|
||||
<pre>
|
||||
<field_attribute> {
|
||||
.deprecated
|
||||
| .attribute <name> <file_name>
|
||||
| .signature <signature>
|
||||
| .annotation (...)
|
||||
}
|
||||
</pre>
|
||||
|
||||
(see below for the definition of the annotation and the attribute directives)
|
||||
|
||||
|
||||
|
||||
<p>examples :
|
||||
<pre>.field enum myField Ljava/lang/String; signature "<my::own>Signature()" = "val"</pre>
|
||||
<pre>.field static hello_string Ljava/lang/String;
|
||||
.signature "mySignature"
|
||||
.deprecated
|
||||
.end field</pre>
|
||||
</p>
|
||||
|
||||
|
||||
<h1>JasminXT Method Definition</h1>
|
||||
The general format of a method definition has not changed in JasminXT.
|
||||
|
||||
<pre>
|
||||
<method> {
|
||||
.method <access_spec> <method_name> <descriptor>
|
||||
<statement>*
|
||||
.end method
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<h1>JasminXT Method Statements</h1>
|
||||
<pre>
|
||||
<statement> {
|
||||
.limit stack <integer>
|
||||
| .limit locals <integer>
|
||||
| .line <integer>
|
||||
| .var <var_number> is <var_name> <descriptor> [signature <sign>] from <label1> to <label2>
|
||||
| .var <var_number> is <var_name> <descriptor> [signature <sign>] from <offset1> to <offset2>
|
||||
| .throws <classname>
|
||||
| .catch <classname> from <label1> to <label2> using <label3>
|
||||
| .catch <classname> from <offset1> to <offset2> using <offset3>
|
||||
| .signature "<signature>"
|
||||
| .stack
|
||||
[offset {<pc> | <label>}]
|
||||
[locals <verification_type> [<verification_arg>]]
|
||||
(...)
|
||||
[stack <verification_type> [<verification_arg>]]
|
||||
(...)
|
||||
.end stack
|
||||
| .stack use [n] locals
|
||||
(...)
|
||||
.end stack
|
||||
| <instruction> [<instruction_args>]
|
||||
| <Label>:
|
||||
| .deprecated
|
||||
| <generic> ; see below for the use of generic attributes
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
In Jasmin XT you can now use offsets instead of labels for the local variable
|
||||
definitions and for the exception handlers definitions.</p>
|
||||
|
||||
<p>The .signature sets the Signature attribute for this method with the given
|
||||
quoted string.<p>
|
||||
|
||||
<p>You can now also define StackMap (or StackMapTable) attributes using
|
||||
the .stack directive. <pc> is an offset in the local bytecode array.
|
||||
<verification_type> is one of the following keywords : Top, Integer,
|
||||
Float, Long, Double, Null, UninitializedThis, Object or Uninitialized. Object
|
||||
takes a <classname> as a parameter. Uninitialized takes an integer or a
|
||||
label as a parameter. Also, jasmin allows to use "short" notation. The
|
||||
'.stack use [n] locals' directive results in copy first <n> values from
|
||||
previous .stack directive. If <n> is omitted, all values are copied.</p>
|
||||
|
||||
<p>NOTE: If bytecode version is 50 or above jasmin generates StackMapTable
|
||||
attribute in accordance with specification of the new 'ClassFile Format'
|
||||
edition. If bytecode version is 49 or below jasmin generate StakMap attribute
|
||||
in accordance with CLDC specification.<p>
|
||||
|
||||
examples :
|
||||
<pre>
|
||||
.stack
|
||||
offset 16
|
||||
locals Null
|
||||
locals Top
|
||||
locals Object allo
|
||||
stack Uninitialized 12
|
||||
.end stack
|
||||
|
||||
.stack
|
||||
; offset is not specified, the offset of the current opcode will be used
|
||||
locals Null
|
||||
locals Top
|
||||
locals Object allo
|
||||
stack Uninitialized Label0
|
||||
.end stack
|
||||
</pre>
|
||||
<p>
|
||||
This statement defines a single stack map frame. All the stack map frames
|
||||
defined in a method are then aggregated and form the StackMap attribute for the
|
||||
method. The last example my be wrote at the short notation as:</p>
|
||||
|
||||
<pre>
|
||||
.stack use locals
|
||||
stack Uninitialized Label0
|
||||
.end stack
|
||||
</pre>
|
||||
<p>
|
||||
|
||||
|
||||
|
||||
<h1>JasminXT Instructions</h1>
|
||||
<pre>
|
||||
<instruction> {
|
||||
[<pc>:] <opcode> [<instruction_args>]
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The main change in JasminXT is that it is now possible to put the offset of the
|
||||
instruction before the opcode (the <pc>: statement). The pc is processed as a
|
||||
label, therefore you can virtually put any number as the pc but it won't change
|
||||
the actual pc of the bytecode.</p>
|
||||
|
||||
<p>
|
||||
Another update is that it is now possible to use offsets (both relative and
|
||||
absolute) as branch targets instead of labels. The offset is considered to be
|
||||
relative if it begins with '$+' or '$-'.</p>
|
||||
|
||||
example :
|
||||
<pre>
|
||||
goto n ; absolute offset : go to the bytecode labelled n
|
||||
goto $+n ; relative offset : go n bytes forward (from the offset of this goto)
|
||||
goto $-n ; relative offset : go n bytes backwards
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If something hasn't been documented here, it means that it hasn't changed, so
|
||||
you can still refer to the Jasmin <a href="guide.html">user guide</a></p>
|
||||
|
||||
<p>
|
||||
<b>Added '_w' aliase to [adfli]-load/store, iinc and ret instructions (e.g. aload - aload_w).
|
||||
Using '_w' postfix guarantees wide-form of byte-code generation</b></p>
|
||||
|
||||
<h1>Generic Attributes</h1>
|
||||
Generic attributes are supported in class/field/method definitions as follows :
|
||||
<pre><generic> = {
|
||||
.attribute <name> <file_name>
|
||||
}</pre>
|
||||
|
||||
<name> is the name of the attribute and <file_name> is the name of the file containing the data of the attribute (between double quotes). If the generic attribute is in the body of the method, the following logic is used : if it is the first statement in the method, the attribute will be added as a method attribute, otherwise it will be added as a Code attribute.
|
||||
|
||||
<h1>Annotations</h1>
|
||||
Thanks to Iouri Kharon for implementing this. Here are his explanations :<br>
|
||||
|
||||
<p>Added a new directive .annotation to create the AnnotationDefault,
|
||||
RuntimeVisibleAnnotation, RuntimeInvisibleAnnotation,
|
||||
RuntimeVisibeParameterAnnotation, RuntimeInvisibleParameterAnnotation
|
||||
attributes. The directive arguments are verified to have valid values
|
||||
and correct signatures.<br>
|
||||
Complex (nested) annotations are supported as well as arrays of them.<br>
|
||||
The generic format is:
|
||||
<pre>
|
||||
<annotation> = {
|
||||
.annotation visible <classname>
|
||||
| .annotation invisible <classname>>
|
||||
| .annotation visibleparam <paramnum> <classname>
|
||||
| .annotation invisibleparam <paramnum> <classname>
|
||||
| .annotation default
|
||||
........
|
||||
.end annotation
|
||||
|
||||
Field format (except AnnotationDefault):
|
||||
|
||||
<name> <signchar> = <value>*
|
||||
| <name> @ = .annotation
|
||||
........
|
||||
.end annotation
|
||||
}
|
||||
</pre>
|
||||
|
||||
AnnotationDefault supports only one field and the <name> tag is not used.
|
||||
Nested annotations must be with the <name> tag and can have any number
|
||||
of fields. Besides, 'empty annotation' is forbidden for AnnotationDefault.
|
||||
Lastly, AnnotationDefault can be used only once for each method.
|
||||
Other annotation types can be used many times and will accumulate information.</p>
|
||||
|
||||
<hr><address>Copyright (c) Daniel Reynaud, Mart 2006</address>
|
||||
<hr>
|
||||
<a href="http://jasmin.sourceforge.net">Jasmin Home</a>
|
||||
</td></tr></table>
|
||||
</body>
|
||||
</html>
|
BIN
jasmin/jasmin-2.4/jasmin.jar
Normal file
BIN
jasmin/jasmin-2.4/jasmin.jar
Normal file
Binary file not shown.
BIN
jasmin/jasmin-2.4/lib/ant-launcher.jar
Normal file
BIN
jasmin/jasmin-2.4/lib/ant-launcher.jar
Normal file
Binary file not shown.
BIN
jasmin/jasmin-2.4/lib/ant.jar
Normal file
BIN
jasmin/jasmin-2.4/lib/ant.jar
Normal file
Binary file not shown.
13
jasmin/jasmin-2.4/lib/jas/JASMIN_NOTES.txt
Normal file
13
jasmin/jasmin-2.4/lib/jas/JASMIN_NOTES.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
10 October 2004, Jon Meyer
|
||||
|
||||
* Moved the jas src code into ../src/jas.
|
||||
|
||||
|
||||
1 March 1997, Jon Meyer
|
||||
|
||||
* Modified JAS to use self-contained RuntimeConstants interface.
|
||||
|
||||
* Moved JAS classes into the Jasmin classes directory.
|
||||
|
||||
* Fixed bug in CatchEntry.
|
||||
|
109
jasmin/jasmin-2.4/lib/jas/README.txt
Normal file
109
jasmin/jasmin-2.4/lib/jas/README.txt
Normal file
|
@ -0,0 +1,109 @@
|
|||
This is v0.3 of a simple Java bytecode assembler.
|
||||
|
||||
|
||||
Quick Info:
|
||||
-----------
|
||||
If you want to just quickly check out things, do the following.
|
||||
|
||||
% java scm.driver examples/hworld.jas
|
||||
|
||||
This compiles an assembler script to bytecode.
|
||||
|
||||
% java out
|
||||
|
||||
This runs the resultant bytecode, which should print the
|
||||
string "Hello World" 5 times.
|
||||
|
||||
|
||||
Then read the online documentation at
|
||||
|
||||
http://www.blackdown.org/~kbs/jas.html
|
||||
|
||||
More Details:
|
||||
-------------
|
||||
|
||||
* What is available:
|
||||
|
||||
A simple java bytecode assembler that can be used either as a
|
||||
standalone scripting program or directly from java (through the jas
|
||||
package)
|
||||
|
||||
* What is not available in this version:
|
||||
|
||||
- Error recovery in the scripting interface
|
||||
- defining a tableswitch or lookupswitch instruction from the scripting
|
||||
interface
|
||||
|
||||
* Documentation
|
||||
|
||||
You can leaf through the jas API in reference/jas You can look at
|
||||
the list of available scripting functions from reference/scm. The
|
||||
bulk of what documentation exists is online from
|
||||
|
||||
http://www.blackdown.org/~kbs/jas.html
|
||||
|
||||
UTSL, ofcourse ;-) And documentation is mostly demand-driven,
|
||||
if there is interest I'll continue to expand it.
|
||||
|
||||
* Examples
|
||||
|
||||
The examples directory contains a few examples of using the
|
||||
assembler with the script and directly from java. Look at the
|
||||
README in this directory to see how to run them. Online
|
||||
documentation contains more details.
|
||||
|
||||
simple.java
|
||||
simple.jas
|
||||
These are simple programs that create classes which
|
||||
don't do anything but get initialized.
|
||||
|
||||
hworld.java
|
||||
hworld.jas
|
||||
These create bytecode that can be run standalone,
|
||||
which print a string a few times.
|
||||
|
||||
exprcomp.java
|
||||
This is a primitive compiler that does runtime
|
||||
codegeneration and execution of arithmetic expressions.
|
||||
exprcomp.jas
|
||||
This is a primitive compiler written in jas to translate
|
||||
jas arithmetic expressions to bytecode.
|
||||
|
||||
* Recompiling
|
||||
|
||||
You can recompile all classes if you wish. First remove the
|
||||
jas/ and the scm/ directories under this directory. Then run the
|
||||
script compile.sh in this directory.
|
||||
|
||||
You will probably want to then run the tests in the test directory
|
||||
to make sure the basic api is functional. Look at the README in this
|
||||
directory for details.
|
||||
|
||||
|
||||
Running the scripting driver:
|
||||
-----------------------------
|
||||
|
||||
If you are going to use the scripting language, the driver for it is
|
||||
located in the class scm.driver. The magic incantation is
|
||||
|
||||
% java scm.driver [path to file]
|
||||
|
||||
If you don't give it a file name, it will try to read from stdin.
|
||||
|
||||
|
||||
Using code from this distribution:
|
||||
----------------------------------
|
||||
|
||||
There is exactly one class that I *use* from the sun/* package, which
|
||||
is sun.tools.java.RuntimeConstants. I know of no other reasonable way
|
||||
to keep in sync with the VM.
|
||||
|
||||
Outside of this class, (which is not present in this distribution) you
|
||||
can freely use/modify/sell/dance on with hobnailed boots any or all of
|
||||
this code. If you do end up using derived code and feel disinclined to
|
||||
buy me a snowboard :) all I ask is that you add me to the list of
|
||||
credits.
|
||||
|
||||
-KB-
|
||||
kbs@sbktech.org
|
||||
Version created: Tue Aug 21 09:50:23 PDT 1996
|
52
jasmin/jasmin-2.4/lib/jas/examples/README
Normal file
52
jasmin/jasmin-2.4/lib/jas/examples/README
Normal file
|
@ -0,0 +1,52 @@
|
|||
This contains three examples of using the assembler
|
||||
from java and from the script
|
||||
|
||||
Look up http://www.blackdown.org/~kbs/jas.html for more
|
||||
documentation. This only tells you how to run the examples. The
|
||||
documentation is very Unix centric, I apologize.... I have not had
|
||||
time to set this up on the PC's yet.
|
||||
|
||||
|
||||
simple.java:
|
||||
simple.jas:
|
||||
|
||||
Unexciting program that generates a do nothing class.
|
||||
|
||||
Go up a directory and compile simple.java. Run the program,
|
||||
which generates the bytecode. Disassemble the bytecode
|
||||
|
||||
% (cd ..; javac -d . examples/simple.java; java simple; javap -p -c out)
|
||||
|
||||
Same thing, but using the script instead of java directly.
|
||||
|
||||
% (cd ..; java scm.driver examples/simple.jas; javap -p -c out)
|
||||
|
||||
|
||||
hworld.java:
|
||||
hworld.jas:
|
||||
|
||||
Print a string in a loop.
|
||||
|
||||
% (cd ..; javac -d . examples/hworld.java; java hworld; java out)
|
||||
|
||||
As before, but use script instead.
|
||||
|
||||
% (cd ..; java scm.driver examples/hworld.jas; java out)
|
||||
|
||||
exprcomp.java:
|
||||
|
||||
Primitive runtime expression compiler. It translates arithmetic
|
||||
expressions into bytecode and loads it on the fly as a class, which
|
||||
is run to get the answer. test.inp is an example of the sort of
|
||||
arithmetic expressions it translates.
|
||||
|
||||
% (cd ..; javac -d . examples/exprcomp.java; java exprcomp examples/test.inp)
|
||||
|
||||
exprcomp.jas:
|
||||
|
||||
Primitive compiler for jas arithmetic expressions (in jas).
|
||||
jas is fairly expressive, thats about the only point of this
|
||||
exercise ;-) Unlike the java version, this gets written out
|
||||
into a file which you'll have to run to get the results.
|
||||
|
||||
% (cd ..; java scm.driver examples/exprcomp.jas; java results)
|
116
jasmin/jasmin-2.4/lib/jas/examples/exprcomp.jas
Normal file
116
jasmin/jasmin-2.4/lib/jas/examples/exprcomp.jas
Normal file
|
@ -0,0 +1,116 @@
|
|||
;;; Simple arithmetic expression compiler for jas in jas.
|
||||
;;;
|
||||
;;; The compiler is defined in the function
|
||||
;;; compile-expression
|
||||
;;;
|
||||
;;; use as (for instance)
|
||||
;;; (compile-expression (quote (+ (* 2 (+ 1 3)) 1)))
|
||||
;;;
|
||||
;;; This will generate a standalone program called results.class
|
||||
;;; Run the bytecode interpreter on it as:
|
||||
;;;
|
||||
;;; % java results
|
||||
;;;
|
||||
;;; which will print the result of the expression
|
||||
|
||||
(define compile-expression
|
||||
(lambda (expr)
|
||||
(real-compile-expression expr)
|
||||
(dump-code)))
|
||||
|
||||
;; The fun part...
|
||||
|
||||
(define real-compile-expression
|
||||
(lambda (expr)
|
||||
(cond
|
||||
|
||||
((num? expr)
|
||||
(compile-number expr))
|
||||
|
||||
(1 (progn
|
||||
(real-compile-expression (get-op1 expr))
|
||||
(real-compile-expression (get-op2 expr))
|
||||
(compile-op (get-op expr))
|
||||
(set! cur-stack-height (- cur-stack-height 1)))))))
|
||||
|
||||
;; Ah well. Back to boring bookkeeping.
|
||||
|
||||
|
||||
(define compile-number
|
||||
(lambda (num)
|
||||
(append-insn (bipush num))
|
||||
(set! cur-stack-height (+ 1 cur-stack-height))
|
||||
(cond
|
||||
((< max-stack-height cur-stack-height)
|
||||
(set! max-stack-height cur-stack-height)))))
|
||||
|
||||
(define compile-op
|
||||
(lambda (op)
|
||||
(cond
|
||||
((eq? op (quote +)) (append-insn (iadd)))
|
||||
((eq? op (quote -)) (append-insn (isub)))
|
||||
((eq? op (quote *)) (append-insn (imul)))
|
||||
((eq? op (quote /)) (append-insn (idiv))))))
|
||||
|
||||
(define get-op1
|
||||
(lambda (expr) (car (cdr expr))))
|
||||
(define get-op2
|
||||
(lambda (expr) (car (cdr (cdr expr)))))
|
||||
(define get-op
|
||||
(lambda (expr) (car expr)))
|
||||
|
||||
(define append-insn
|
||||
(lambda (insn)
|
||||
(jas-code-addinsn my-code insn)))
|
||||
|
||||
(define cur-stack-height 1)
|
||||
(define max-stack-height 1)
|
||||
|
||||
(define my-code (make-code))
|
||||
(define my-init-code (make-code))
|
||||
|
||||
; define the main() portion,
|
||||
; and the call to print out the
|
||||
; results.
|
||||
(define append-sequence
|
||||
(lambda (code-part insn-list)
|
||||
(mapcar (lambda (insn) (jas-code-addinsn code-part insn))
|
||||
insn-list)))
|
||||
|
||||
(append-sequence
|
||||
my-init-code
|
||||
(quote
|
||||
((aload_0)
|
||||
(invokenonvirtual (make-method-cpe "java/lang/Object" "<init>" "()V"))
|
||||
(return))))
|
||||
|
||||
(define dump-code
|
||||
(lambda ()
|
||||
(define my-env (make-class-env))
|
||||
(jas-class-setclass my-env (make-class-cpe "results"))
|
||||
(jas-class-setsuperclass my-env (make-class-cpe "java/lang/Object"))
|
||||
(jas-class-addmethod my-env acc-public "<init>" "()V" my-init-code ())
|
||||
(append-sequence
|
||||
my-code
|
||||
(quote
|
||||
((getstatic
|
||||
(make-field-cpe "java/lang/System" "out" "Ljava/io/PrintStream;"))
|
||||
(swap)
|
||||
(invokevirtual (make-method-cpe
|
||||
"java/io/PrintStream" "println" "(I)V"))
|
||||
(return))))
|
||||
(jas-code-stack-size my-code max-stack-height)
|
||||
(jas-class-addmethod my-env
|
||||
(| acc-public acc-static)
|
||||
"main" "([Ljava/lang/String;)V" my-code ())
|
||||
(jas-class-write my-env
|
||||
(make-outputstream "results.class"))))
|
||||
|
||||
;;;
|
||||
;;; example usage of compiler.
|
||||
;;;
|
||||
;;; run the compiled class with
|
||||
;;; % java results
|
||||
;;; to get the answer.
|
||||
|
||||
(compile-expression (quote (+ (* 2 (+ 1 3)) 1)))
|
242
jasmin/jasmin-2.4/lib/jas/examples/exprcomp.java
Normal file
242
jasmin/jasmin-2.4/lib/jas/examples/exprcomp.java
Normal file
|
@ -0,0 +1,242 @@
|
|||
// Primitive runtime code generation of expressions. This is a jas
|
||||
// implementation of the example in Aho Sethi Ullman.
|
||||
//
|
||||
// You pass to it statements of the form
|
||||
// a = 1*2 + 3*5;
|
||||
// Only integer operations are allowed, and variables
|
||||
// are magically created by using them in the LHS of a statement.
|
||||
//
|
||||
// You can print out the value of expressions with the println keyword:
|
||||
// println(a + 10);
|
||||
//
|
||||
// It compiles this into a bytearray, and then loads it as
|
||||
// a new class.
|
||||
//
|
||||
// Unfortunately, this trick cannot be used in an applet --- security
|
||||
// restrictions prevent ClassLoaders from being placed on the
|
||||
// stack. So much for writing regexp compilers that can do codegen instead of
|
||||
// state tables.
|
||||
//
|
||||
// The grammar is simple, so code generation is part of the parsing
|
||||
// step. Operator precedence is directly handled by the grammar.
|
||||
//
|
||||
// Grammar + production rules:
|
||||
//
|
||||
// start -> list EOF
|
||||
// list -> id = expr ; { emit(istore, id.index); } list
|
||||
// | println expr ; { emit(<println sequence>); } list
|
||||
// | lambda
|
||||
// expr -> term moreterms
|
||||
// moreterms -> + term { emit(iadd) } moreterms
|
||||
// | - term { emit(isub) } moreterms
|
||||
// | lambda
|
||||
// term -> factor morefactors
|
||||
// morefactors -> * factor { emit(imul) } morefactors
|
||||
// | / factor { emit(idiv) } morefactors
|
||||
// | lambda
|
||||
// factor -> ( expr )
|
||||
// | number { emit(iconst, number.value) }
|
||||
// | id { emit(iload, id.index); }
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import jas.*;
|
||||
import sun.tools.java.RuntimeConstants;
|
||||
|
||||
public class exprcomp implements RuntimeConstants
|
||||
{
|
||||
StreamTokenizer inp;
|
||||
CodeAttr myCode;
|
||||
short cur_stack_height;
|
||||
short max_stack_height;
|
||||
short max_vars;
|
||||
Hashtable vars;
|
||||
|
||||
public exprcomp(StreamTokenizer inp)
|
||||
throws jasError
|
||||
{
|
||||
inp.eolIsSignificant(false);
|
||||
this.inp = inp;
|
||||
myCode = new CodeAttr();
|
||||
// Add initializations
|
||||
myCode.addInsn(new Insn(opc_aload_0));
|
||||
myCode.addInsn(new Insn(opc_invokenonvirtual,
|
||||
new MethodCP("java/lang/Object",
|
||||
"<init>", "()V")));
|
||||
cur_stack_height = max_stack_height = 1;
|
||||
vars = new Hashtable();
|
||||
max_vars = 1;
|
||||
}
|
||||
public void write(DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
ClassEnv clazz = new ClassEnv();
|
||||
myCode.setStackSize(max_stack_height);
|
||||
myCode.setVarSize(max_vars);
|
||||
// add initializer to class
|
||||
clazz.addMethod
|
||||
((short) ACC_PUBLIC, "<init>", "()V", myCode, null);
|
||||
clazz.setClassAccess((short) ACC_PUBLIC);
|
||||
clazz.setClass(new ClassCP("results"));
|
||||
clazz.setSuperClass(new ClassCP("java/lang/Object"));
|
||||
clazz.write(out);
|
||||
}
|
||||
|
||||
public void parse()
|
||||
throws IOException, parseError, jasError
|
||||
{
|
||||
inp.nextToken();
|
||||
while(inp.ttype != inp.TT_EOF)
|
||||
{
|
||||
if (inp.ttype != inp.TT_WORD)
|
||||
{
|
||||
throw new parseError("Expected an id at line " + inp.lineno());
|
||||
}
|
||||
if (inp.sval.equals("println"))
|
||||
{
|
||||
match(inp.TT_WORD);
|
||||
expr();
|
||||
match(';');
|
||||
emit(new Insn(opc_getstatic,
|
||||
new FieldCP("java/lang/System",
|
||||
"out", "Ljava/io/PrintStream;")));
|
||||
emit(new Insn(opc_swap));
|
||||
emit(new Insn(opc_invokevirtual,
|
||||
new MethodCP("java/io/PrintStream",
|
||||
"println", "(I)V")));
|
||||
}
|
||||
else
|
||||
{ // search, maybe add into var list
|
||||
Integer idx;
|
||||
if ((idx = (Integer) vars.get(inp.sval)) == null)
|
||||
{
|
||||
idx = new Integer(max_vars++);
|
||||
vars.put(inp.sval.intern(), idx);
|
||||
}
|
||||
match(inp.TT_WORD); match('='); expr(); match(';');
|
||||
emit(new Insn(opc_istore, idx.intValue()));
|
||||
}
|
||||
}
|
||||
emit(new Insn(opc_return));
|
||||
}
|
||||
|
||||
void expr()
|
||||
throws IOException, parseError, jasError
|
||||
{
|
||||
term();
|
||||
while (true)
|
||||
{
|
||||
switch(inp.ttype)
|
||||
{
|
||||
case '+':
|
||||
match('+'); term(); emit(new Insn(opc_iadd)); break;
|
||||
case '-':
|
||||
match('-'); term(); emit(new Insn(opc_isub)); break;
|
||||
default: return;
|
||||
}
|
||||
cur_stack_height--;
|
||||
}
|
||||
}
|
||||
|
||||
void term()
|
||||
throws IOException, parseError, jasError
|
||||
{
|
||||
factor();
|
||||
while (true)
|
||||
{
|
||||
switch(inp.ttype)
|
||||
{
|
||||
case '*': match('*'); factor(); emit(new Insn(opc_imul)); break;
|
||||
case '/': match('/'); factor(); emit(new Insn(opc_idiv)); break;
|
||||
default: return;
|
||||
}
|
||||
cur_stack_height --;
|
||||
}
|
||||
}
|
||||
void factor()
|
||||
throws IOException, parseError, jasError
|
||||
{
|
||||
switch(inp.ttype)
|
||||
{
|
||||
case '(': match('('); expr(); match(')'); break;
|
||||
case inp.TT_NUMBER:
|
||||
int val = (int)(inp.nval);
|
||||
emit(new Insn(opc_bipush, (short)val));
|
||||
match(inp.TT_NUMBER);
|
||||
break;
|
||||
case inp.TT_WORD:
|
||||
Integer idx;
|
||||
if ((idx = (Integer) vars.get(inp.sval)) == null)
|
||||
{
|
||||
throw new parseError
|
||||
("Unknown variable " + inp.sval + " at line " + inp.lineno());
|
||||
}
|
||||
emit(new Insn(opc_iload, idx.intValue()));
|
||||
match(inp.TT_WORD);
|
||||
break;
|
||||
default:
|
||||
throw new parseError("Syntax error at line " + inp.lineno());
|
||||
}
|
||||
cur_stack_height++;
|
||||
if (max_stack_height < cur_stack_height)
|
||||
max_stack_height = cur_stack_height;
|
||||
}
|
||||
void match(int val)
|
||||
throws IOException, parseError
|
||||
{
|
||||
if (inp.ttype != val)
|
||||
{ throw new parseError
|
||||
("line " + inp.lineno() + ": expected " + val + " but got " + inp); }
|
||||
inp.nextToken();
|
||||
}
|
||||
|
||||
void emit(Insn insn)
|
||||
{
|
||||
myCode.addInsn(insn);
|
||||
}
|
||||
|
||||
public static void main(String argv[])
|
||||
throws Exception
|
||||
{
|
||||
exprcomp compiler =
|
||||
new exprcomp(new StreamTokenizer(new FileInputStream(argv[0])));
|
||||
compiler.parse();
|
||||
ByteArrayOutputStream data = new ByteArrayOutputStream();
|
||||
compiler.write(new DataOutputStream(data));
|
||||
dynaloader dl = new dynaloader(data.toByteArray());
|
||||
dl.exec();
|
||||
}
|
||||
}
|
||||
|
||||
class dynaloader extends ClassLoader
|
||||
{
|
||||
Hashtable cache;
|
||||
Class ex;
|
||||
|
||||
dynaloader(byte[] data)
|
||||
throws ClassFormatError
|
||||
{
|
||||
cache = new Hashtable();
|
||||
ex = defineClass(data, 0, data.length);
|
||||
cache.put("results", ex);
|
||||
resolveClass(ex);
|
||||
}
|
||||
|
||||
void exec() throws Exception { ex.newInstance(); }
|
||||
public synchronized Class loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
Class c = (Class) cache.get(name);
|
||||
if (c == null)
|
||||
{
|
||||
c = findSystemClass(name);
|
||||
cache.put(name, c);
|
||||
}
|
||||
if (resolve) resolveClass(c);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class parseError extends Exception
|
||||
{ parseError(String s) { super(s); } }
|
87
jasmin/jasmin-2.4/lib/jas/examples/hworld.jas
Normal file
87
jasmin/jasmin-2.4/lib/jas/examples/hworld.jas
Normal file
|
@ -0,0 +1,87 @@
|
|||
;; create a container
|
||||
|
||||
(define my-class (make-class-env))
|
||||
|
||||
|
||||
;; specify class hierarchy
|
||||
|
||||
(jas-class-setaccess my-class acc-public)
|
||||
(jas-class-setclass my-class (make-class-cpe "out"))
|
||||
(jas-class-setsuperclass my-class (make-class-cpe "java/lang/Object"))
|
||||
|
||||
|
||||
;; write a convenience function to append insns as a list.
|
||||
(define append-code
|
||||
(lambda (code-part insn-list)
|
||||
(mapcar (lambda (insn) (jas-code-addinsn code-part insn))
|
||||
insn-list)))
|
||||
|
||||
;; Define code for initializer
|
||||
;;
|
||||
(define init-it (make-code))
|
||||
(append-code
|
||||
init-it
|
||||
(quote
|
||||
((aload_0)
|
||||
(invokenonvirtual (make-method-cpe "java/lang/Object" "<init>" "()V"))
|
||||
(return))))
|
||||
|
||||
;; this is the code that comprises
|
||||
;; the actual task, ie the code for
|
||||
;; main(String argv[]).
|
||||
;; print a string 5 times
|
||||
|
||||
(define doit (make-code))
|
||||
(append-code
|
||||
doit
|
||||
(quote
|
||||
(
|
||||
|
||||
; store references in local
|
||||
; variables to avoid field/cp
|
||||
; lookup
|
||||
(getstatic
|
||||
(make-field-cpe "java/lang/System" "out" "Ljava/io/PrintStream;"))
|
||||
(astore_1)
|
||||
(ldc (make-string-cpe "Hello World"))
|
||||
(astore_2)
|
||||
(bipush 5)
|
||||
(istore_3) ; store loop index in var reg 3
|
||||
|
||||
; loop 5 times, printing out
|
||||
; the string.
|
||||
|
||||
(make-label "loop")
|
||||
; push arguments to function
|
||||
; on stack and call it
|
||||
|
||||
(aload_1) (aload_2)
|
||||
(invokevirtual
|
||||
(make-method-cpe "java/io/PrintStream" "println" "(Ljava/lang/String;)V"))
|
||||
|
||||
; decrement loop index
|
||||
|
||||
(iinc 3 -1)
|
||||
(iload_3)
|
||||
(ifne (make-label "loop"))
|
||||
(return))))
|
||||
|
||||
;; set stack/var size
|
||||
|
||||
(jas-code-stack-size doit 3)
|
||||
(jas-code-var-size doit 4)
|
||||
|
||||
;; fill up the class with the methods
|
||||
|
||||
;; first the initializer.
|
||||
(jas-class-addmethod my-class acc-public "<init>" "()V" init-it ())
|
||||
|
||||
;; define the printing code as a static main(String argv[]) method
|
||||
|
||||
(jas-class-addmethod my-class
|
||||
(| acc-static acc-public)
|
||||
"main" "([Ljava/lang/String;)V" doit ())
|
||||
|
||||
;; write it out.
|
||||
|
||||
(jas-class-write my-class (make-outputstream "out.class"))
|
78
jasmin/jasmin-2.4/lib/jas/examples/hworld.java
Normal file
78
jasmin/jasmin-2.4/lib/jas/examples/hworld.java
Normal file
|
@ -0,0 +1,78 @@
|
|||
import jas.*;
|
||||
import java.io.*;
|
||||
import sun.tools.java.RuntimeConstants;
|
||||
|
||||
//
|
||||
// This is program that makes calls into the jas package
|
||||
// to generate a class that prints a string afew times.
|
||||
//
|
||||
|
||||
class hworld implements RuntimeConstants
|
||||
{
|
||||
public static void main(String argv[])
|
||||
throws jasError, IOException
|
||||
{
|
||||
|
||||
// class hierarchy
|
||||
ClassEnv nclass = new ClassEnv();
|
||||
nclass.setClass(new ClassCP("out"));
|
||||
nclass.setSuperClass(new ClassCP("java/lang/Object"));
|
||||
nclass.setClassAccess((short)ACC_PUBLIC);
|
||||
|
||||
// Initialization code
|
||||
|
||||
CodeAttr init = new CodeAttr();
|
||||
init.addInsn(new Insn(opc_aload_0));
|
||||
init.addInsn(new Insn(opc_invokenonvirtual,
|
||||
new MethodCP("java/lang/Object", "<init>", "()V")));
|
||||
init.addInsn(new Insn(opc_return));
|
||||
|
||||
|
||||
// Actual code to print string
|
||||
CodeAttr doit = new CodeAttr();
|
||||
|
||||
// store refs in local variables
|
||||
doit.addInsn(new Insn(opc_getstatic,
|
||||
new FieldCP("java/lang/System",
|
||||
"out",
|
||||
"Ljava/io/PrintStream;")));
|
||||
doit.addInsn(new Insn(opc_astore_1));
|
||||
doit.addInsn(new Insn(opc_ldc,
|
||||
new StringCP("Hello World")));
|
||||
doit.addInsn(new Insn(opc_astore_2));
|
||||
|
||||
// Loop index in var reg 3
|
||||
doit.addInsn(new Insn(opc_bipush, 5));
|
||||
doit.addInsn(new Insn(opc_istore_3));
|
||||
|
||||
// Start the loop
|
||||
Label loop = new Label("loop");
|
||||
doit.addInsn(loop);
|
||||
doit.addInsn(new Insn(opc_aload_1));
|
||||
doit.addInsn(new Insn(opc_aload_2));
|
||||
doit.addInsn(new Insn(opc_invokevirtual,
|
||||
new MethodCP("java/io/PrintStream",
|
||||
"println",
|
||||
"(Ljava/lang/String;)V")));
|
||||
doit.addInsn(new IincInsn(3, -1));
|
||||
doit.addInsn(new Insn(opc_iload_3));
|
||||
doit.addInsn(new Insn(opc_ifne, loop));
|
||||
doit.addInsn(new Insn(opc_return));
|
||||
|
||||
// set the right sizes for code
|
||||
doit.setStackSize((short)3); doit.setVarSize((short)4);
|
||||
|
||||
// Add the init code to the class.
|
||||
nclass.addMethod((short)ACC_PUBLIC, "<init>", "()V", init, null);
|
||||
|
||||
// Add the printing code
|
||||
nclass.addMethod((short)(ACC_PUBLIC|ACC_STATIC), "main",
|
||||
"([Ljava/lang/String;)V", doit, null);
|
||||
|
||||
// write it all out
|
||||
nclass.write(new DataOutputStream
|
||||
(new FileOutputStream("out.class")));
|
||||
}
|
||||
}
|
||||
|
||||
|
30
jasmin/jasmin-2.4/lib/jas/examples/simple.jas
Normal file
30
jasmin/jasmin-2.4/lib/jas/examples/simple.jas
Normal file
|
@ -0,0 +1,30 @@
|
|||
;; script to create a class that does nothing.
|
||||
|
||||
|
||||
; make-class-env creates
|
||||
; a ClassEnv object which is
|
||||
; used to store information about
|
||||
; an object.
|
||||
(define my-class (make-class-env))
|
||||
|
||||
; make-code creates a code object
|
||||
; which contains the body of a
|
||||
; method.
|
||||
|
||||
(define init-code (make-code))
|
||||
(jas-code-addinsn init-code
|
||||
(aload_0))
|
||||
(jas-code-addinsn init-code
|
||||
(invokenonvirtual
|
||||
(make-method-cpe "java/lang/Object" "<init>" "()V")))
|
||||
(jas-code-addinsn init-code
|
||||
(return))
|
||||
|
||||
; fill up the class with goodies
|
||||
(jas-class-setsuperclass my-class (make-class-cpe "java/lang/Object"))
|
||||
(jas-class-setclass my-class (make-class-cpe "out"))
|
||||
(jas-class-setaccess my-class acc-public)
|
||||
(jas-class-addmethod my-class acc-public "<init>" "()V" init-code ())
|
||||
|
||||
; and write it all out
|
||||
(jas-class-write my-class (make-outputstream "out.class"))
|
45
jasmin/jasmin-2.4/lib/jas/examples/simple.java
Normal file
45
jasmin/jasmin-2.4/lib/jas/examples/simple.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
import jas.*;
|
||||
import java.io.*;
|
||||
import sun.tools.java.RuntimeConstants;
|
||||
|
||||
//
|
||||
// This is program that makes calls into the jas package
|
||||
// to generate a class that does nothing at all.
|
||||
//
|
||||
|
||||
class simple implements RuntimeConstants
|
||||
{
|
||||
public static void main(String argv[])
|
||||
throws jasError, IOException
|
||||
{
|
||||
|
||||
// CodeAttr's contain the body of
|
||||
// a method.
|
||||
|
||||
CodeAttr init = new CodeAttr();
|
||||
init.addInsn(new Insn(opc_aload_0));
|
||||
init.addInsn(new Insn(opc_invokenonvirtual,
|
||||
new MethodCP("java/lang/Object", "<init>", "()V")));
|
||||
init.addInsn(new Insn(opc_return));
|
||||
|
||||
|
||||
// ClassEnv's are used as a container
|
||||
// to hold all information about a class.
|
||||
|
||||
ClassEnv nclass = new ClassEnv();
|
||||
nclass.setClass(new ClassCP("out"));
|
||||
nclass.setSuperClass(new ClassCP("java/lang/Object"));
|
||||
|
||||
|
||||
|
||||
// Add the init code to the class.
|
||||
nclass.addMethod((short)ACC_PUBLIC, "<init>", "()V", init, null);
|
||||
|
||||
|
||||
// write it all out
|
||||
nclass.write(new DataOutputStream
|
||||
(new FileOutputStream("out.class")));
|
||||
}
|
||||
}
|
||||
|
||||
|
8
jasmin/jasmin-2.4/lib/jas/examples/test.inp
Normal file
8
jasmin/jasmin-2.4/lib/jas/examples/test.inp
Normal file
|
@ -0,0 +1,8 @@
|
|||
a = 10;
|
||||
println a;
|
||||
|
||||
b = a + 5;
|
||||
|
||||
println (b);
|
||||
println(a*b +2);
|
||||
|
16
jasmin/jasmin-2.4/lib/jas/tests/README
Normal file
16
jasmin/jasmin-2.4/lib/jas/tests/README
Normal file
|
@ -0,0 +1,16 @@
|
|||
This is a start of a basic set of tests intended to exercise the API
|
||||
functions available in the jas and scm packages. It is not complete by
|
||||
any means.
|
||||
|
||||
all.java tries to touch as much of the jas API as it can, generating a
|
||||
non functional class called regress.class. all.jas does
|
||||
something similar, but for the scm package.
|
||||
|
||||
Once the jas and scm packages are compiled, do this:
|
||||
|
||||
% (cd ..; javac -d . tests/all.java; java all; cmp regress.class tests/regress.class)
|
||||
% (cd ..; java scm.driver tests/all.jas; cmp scmregress.class tests/scmregress.class)
|
||||
|
||||
|
||||
If both these complete silently, you are in good shape. Otherwise,
|
||||
mail me a bug report and enough details for me to replicate it :)
|
72
jasmin/jasmin-2.4/lib/jas/tests/all.jas
Normal file
72
jasmin/jasmin-2.4/lib/jas/tests/all.jas
Normal file
|
@ -0,0 +1,72 @@
|
|||
(define my-env (make-class-env))
|
||||
|
||||
(jas-class-addcpe my-env (make-ascii-cpe "fubar"))
|
||||
(jas-class-addcpe my-env (make-class-cpe "java/lang/Number"))
|
||||
(jas-class-addcpe my-env (make-double-cpe 2.0))
|
||||
(jas-class-addcpe my-env
|
||||
(make-field-cpe "java/lang/System" "out" "Ljava/io/PrintStream;"))
|
||||
(jas-class-addcpe my-env (make-float-cpe 2.0))
|
||||
(jas-class-addcpe my-env (make-integer-cpe 2))
|
||||
(jas-class-addcpe my-env
|
||||
(make-interface-cpe "java/lang/Runnable" "run" "()V"))
|
||||
(jas-class-addcpe my-env (make-long-cpe 2))
|
||||
(jas-class-addcpe my-env
|
||||
(make-method-cpe "java/lang/Thread" "run" "()V"))
|
||||
(jas-class-addcpe my-env
|
||||
(make-name-type-cpe "sdfsdf" "Ljava/lang/Object;"))
|
||||
(jas-class-addcpe my-env (make-string-cpe "sdf"))
|
||||
(jas-class-addfield my-env
|
||||
(make-field
|
||||
acc-public (make-ascii-cpe "someIntVar") (make-ascii-cpe "I") ()))
|
||||
(jas-class-addfield my-env
|
||||
(make-field
|
||||
(| acc-public acc-static) (make-ascii-cpe "finalInt")
|
||||
(make-ascii-cpe "I") (make-const (make-integer-cpe 10.2))))
|
||||
(jas-class-addinterface my-env (make-class-cpe "java/lang/Runnable"))
|
||||
(jas-class-setclass my-env (make-class-cpe "scmregress"))
|
||||
(jas-class-setsuperclass my-env (make-class-cpe "java/lang/Object"))
|
||||
(jas-class-setaccess my-env acc-public)
|
||||
|
||||
|
||||
(define my-code (make-code))
|
||||
(jas-code-addinsn my-code (return))
|
||||
(jas-code-addinsn my-code (astore 5))
|
||||
(jas-code-addinsn my-code (make-label "First label"))
|
||||
(jas-code-addinsn my-code (jsr (make-label "First label")))
|
||||
(define saved-label (make-label "second_label"))
|
||||
(jas-code-addinsn my-code saved-label)
|
||||
(jas-code-addinsn my-code (ldc_w (make-string-cpe "sdfsdf")))
|
||||
(jas-code-addinsn my-code (iinc 2 -2))
|
||||
(jas-code-addinsn my-code
|
||||
(invokeinterface
|
||||
(make-class-cpe "java/lang/Number") 1))
|
||||
|
||||
(jas-code-addinsn my-code (multianewarray (make-class-cpe "java/lang/Double")
|
||||
3))
|
||||
(define ctb (make-catchtable))
|
||||
(jas-add-catch-entry ctb (make-catch-entry
|
||||
(make-label "First label")
|
||||
saved-label
|
||||
saved-label
|
||||
(make-class-cpe "java/lang/Exception")))
|
||||
(jas-add-catch-entry ctb (make-catch-entry
|
||||
(make-label "First label")
|
||||
saved-label
|
||||
saved-label
|
||||
(make-class-cpe "java/lang/Error")))
|
||||
(jas-set-catchtable my-code ctb)
|
||||
(jas-code-stack-size my-code 100)
|
||||
(jas-code-var-size my-code 100)
|
||||
(define my-except (make-exception))
|
||||
(jas-exception-add my-except (make-class-cpe "java/io/IOException"))
|
||||
(jas-exception-add my-except (make-class-cpe "java/lang/Error"))
|
||||
|
||||
(jas-class-addmethod my-env
|
||||
acc-public
|
||||
"somemethod"
|
||||
"(I)V"
|
||||
my-code
|
||||
my-except)
|
||||
(jas-class-write my-env (make-outputstream "scmregress.class"))
|
||||
|
||||
|
155
jasmin/jasmin-2.4/lib/jas/tests/all.java
Normal file
155
jasmin/jasmin-2.4/lib/jas/tests/all.java
Normal file
|
@ -0,0 +1,155 @@
|
|||
// Simply try
|
||||
// to access as much of
|
||||
// the API as possible.
|
||||
|
||||
import jas.*;
|
||||
|
||||
import java.io.*;
|
||||
import sun.tools.java.RuntimeConstants;
|
||||
|
||||
public class all implements RuntimeConstants
|
||||
{
|
||||
public static void main(String argv[])
|
||||
throws Exception
|
||||
{
|
||||
ClassEnv c = new ClassEnv();
|
||||
|
||||
// Adding CP Items directly
|
||||
|
||||
c.addCPItem(new AsciiCP("fubar"));
|
||||
c.addCPItem(new ClassCP("java/lang/Number"));
|
||||
c.addCPItem(new DoubleCP(2.0));
|
||||
c.addCPItem(new FieldCP("java/lang/System",
|
||||
"out",
|
||||
"Ljava/io/PrintStream;"));
|
||||
c.addCPItem(new FloatCP((float)(2.0)));
|
||||
c.addCPItem(new IntegerCP(2));
|
||||
c.addCPItem(new InterfaceCP("java/lang/Runnable",
|
||||
"run",
|
||||
"()V"));
|
||||
c.addCPItem(new LongCP(2));
|
||||
c.addCPItem(new MethodCP("java/lang/Thread",
|
||||
"run",
|
||||
"()V"));
|
||||
|
||||
c.addCPItem(new NameTypeCP("sdfsdf", "Ljava/lang/Object;"));
|
||||
c.addCPItem(new StringCP("sdf"));
|
||||
|
||||
|
||||
// Add fields, creating variables
|
||||
c.addField(new Var((short) ACC_PUBLIC,
|
||||
new AsciiCP("someIntvar"),
|
||||
new AsciiCP("I"),
|
||||
null));
|
||||
c.addField(new Var((short)(ACC_PUBLIC|ACC_STATIC|ACC_FINAL),
|
||||
new AsciiCP("finalInt"),
|
||||
new AsciiCP("I"),
|
||||
new ConstAttr(new IntegerCP(10))));
|
||||
|
||||
// Check if I can add interfaces
|
||||
c.addInterface(new ClassCP("java/lang/Runnable"));
|
||||
|
||||
c.setClass(new ClassCP("regress"));
|
||||
c.setSuperClass(new ClassCP("java/lang/Object"));
|
||||
c.setClassAccess((short) ACC_PUBLIC);
|
||||
|
||||
// Creating code.
|
||||
|
||||
CodeAttr code = new CodeAttr();
|
||||
// add instructions of various
|
||||
// operand types.
|
||||
|
||||
// No operands
|
||||
code.addInsn(new Insn(opc_return));
|
||||
// one arg operands
|
||||
code.addInsn(new Insn(opc_astore, 5));
|
||||
// one arg arguments with wide operand
|
||||
code.addInsn(new Insn(opc_dstore, 256));
|
||||
code.addInsn(new Insn(opc_istore, 2576));
|
||||
|
||||
// Add a label
|
||||
code.addInsn(new Label("First label"));
|
||||
// refer back to it
|
||||
code.addInsn(new Insn(opc_jsr,
|
||||
new Label("First label")));
|
||||
// add another label
|
||||
code.addInsn(new Label("second_label"));
|
||||
// insn with CP argument
|
||||
code.addInsn(new Insn(opc_ldc_w, new StringCP("sdfsdf")));
|
||||
|
||||
// the "special" instructions
|
||||
code.addInsn(new IincInsn(2, -2));
|
||||
// wider version check
|
||||
code.addInsn(new IincInsn(1234, 2));
|
||||
code.addInsn(new IincInsn(3, -200));
|
||||
code.addInsn(new InvokeinterfaceInsn(new ClassCP("java/lang/Number"), 1));
|
||||
code.addInsn(new MultiarrayInsn(new ClassCP("java/lang/Double"), 3));
|
||||
Label woo[] = new Label[3];
|
||||
woo[0] = new Label("First label");
|
||||
woo[1] = new Label("second_label");
|
||||
woo[2] = new Label("second_label");
|
||||
code.addInsn(new TableswitchInsn(0, 2, woo[0], woo));
|
||||
|
||||
int m[] = new int[3];
|
||||
m[0] = 11;
|
||||
m[1] = 15;
|
||||
m[2] = -1;
|
||||
code.addInsn(new LookupswitchInsn(woo[0], m, woo));
|
||||
|
||||
|
||||
// make a catchtable
|
||||
Catchtable ctb = new Catchtable();
|
||||
// add a couple of entries
|
||||
ctb.addEntry(new Label("First label"),
|
||||
new Label("second_label"),
|
||||
new Label("second_label"),
|
||||
new ClassCP("java/lang/Exception"));
|
||||
ctb.addEntry(new Label("First label"),
|
||||
new Label("second_label"),
|
||||
new Label("second_label"),
|
||||
new ClassCP("java/lang/Error"));
|
||||
code.setCatchtable(ctb);
|
||||
code.setStackSize((short)100);
|
||||
code.setVarSize((short)500);
|
||||
// Add some line table info
|
||||
LineTableAttr ln = new LineTableAttr();
|
||||
ln.addEntry(woo[0], 234);
|
||||
ln.addEntry(woo[1], 245);
|
||||
ln.addEntry(woo[2], 22);
|
||||
code.setLineTable(ln);
|
||||
// Add a generic attr to a method
|
||||
String foo = "sldkfj sdlfkj";
|
||||
byte dat[] = new byte[foo.length()];
|
||||
foo.getBytes(0, dat.length, dat, 0);
|
||||
code.addGenericAttr(new GenericAttr("strangeAttr", dat));
|
||||
|
||||
// Also adding local varinfo
|
||||
LocalVarTableAttr lv = new LocalVarTableAttr();
|
||||
lv.addEntry(new LocalVarEntry(woo[0], woo[2], "fakevar", "I", 22));
|
||||
lv.addEntry(new LocalVarEntry(woo[1], woo[1], "morefa", "()V", 10));
|
||||
code.setLocalVarTable(lv);
|
||||
|
||||
// check out add method, also
|
||||
// adding a throws exception for
|
||||
// good measure
|
||||
ExceptAttr ex = new ExceptAttr();
|
||||
ex.addException(new ClassCP("java/io/IOException"));
|
||||
ex.addException(new ClassCP("java/lang/Error"));
|
||||
c.addMethod((short) ACC_PUBLIC,
|
||||
"fubarmethod",
|
||||
"()V",
|
||||
code,
|
||||
ex);
|
||||
|
||||
|
||||
|
||||
|
||||
// Add a source file attribute
|
||||
c.setSource(new SourceAttr("all.java"));
|
||||
// Add some more generic attribute
|
||||
c.addGenericAttr(new GenericAttr("blahAttr", dat));
|
||||
c.write(new DataOutputStream(new FileOutputStream("regress.class")));
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
jasmin/jasmin-2.4/lib/jas/tests/regress.class
Normal file
BIN
jasmin/jasmin-2.4/lib/jas/tests/regress.class
Normal file
Binary file not shown.
BIN
jasmin/jasmin-2.4/lib/jas/tests/scmregress.class
Normal file
BIN
jasmin/jasmin-2.4/lib/jas/tests/scmregress.class
Normal file
Binary file not shown.
BIN
jasmin/jasmin-2.4/lib/java_cup.jar
Normal file
BIN
jasmin/jasmin-2.4/lib/java_cup.jar
Normal file
Binary file not shown.
100
jasmin/jasmin-2.4/lib/java_cup/INSTALL
Normal file
100
jasmin/jasmin-2.4/lib/java_cup/INSTALL
Normal file
|
@ -0,0 +1,100 @@
|
|||
#!/bin/csh
|
||||
#
|
||||
# JavaCup install and test script
|
||||
# Scott Hudson 8/31/95
|
||||
#
|
||||
# Last revision 1/7/96 (for v0.9d)
|
||||
#
|
||||
echo
|
||||
echo "===================================="
|
||||
echo "Installing and testing JavaCup v0.9d"
|
||||
echo "===================================="
|
||||
echo
|
||||
|
||||
# check for this directory in CLASSPATH
|
||||
#
|
||||
set cwd = `pwd`
|
||||
if ($CLASSPATH !~ "*$cwd*") then
|
||||
echo " "
|
||||
echo "WARNING:"
|
||||
echo "WARNING: The current directory does not appear in your CLASSPATH"
|
||||
echo "WARNING: it will be added for this install/test only"
|
||||
echo "WARNING:"
|
||||
echo " "
|
||||
set CLASSPATH = $CLASSPATH':'$cwd
|
||||
echo "CLASSPATH now set to "
|
||||
echo $CLASSPATH
|
||||
endif
|
||||
|
||||
# change to the demo directory
|
||||
#
|
||||
echo " "
|
||||
echo "changing to simple_calc subdirectory..."
|
||||
echo "cd simple_calc"
|
||||
cd simple_calc
|
||||
|
||||
# remove old copies of parser.java and sym.java
|
||||
#
|
||||
echo " "
|
||||
echo "removing any old copies of parser.java and sym.java..."
|
||||
echo "rm -f parser.java sym.java"
|
||||
rm -f parser.java sym.java
|
||||
|
||||
# compile java_cup and run it against the demo program
|
||||
# the -cs (for "checksource") option here will force the
|
||||
# java_cup and java_cup.runtime source to be compiled prior
|
||||
# to running it.
|
||||
#
|
||||
echo " "
|
||||
echo "compiling java_cup then generating demo program..."
|
||||
echo "java -cs java_cup.Main < parser.cup"
|
||||
java -cs java_cup.Main < parser.cup
|
||||
|
||||
# make sure parser.java and sym.java now exist
|
||||
#
|
||||
if ( ! -e parser.java) then
|
||||
echo " "
|
||||
echo "ERROR: for some reason parser.java was not created"
|
||||
echo "ERROR: install was not successful"
|
||||
exit 1
|
||||
endif
|
||||
if ( ! -e sym.java) then
|
||||
echo " "
|
||||
echo "ERROR: for some reason sym.java was not created"
|
||||
echo "ERROR: install was not successful"
|
||||
exit 1
|
||||
endif
|
||||
|
||||
# run the demo
|
||||
# again, the -cs option will cause compilation of all the parts
|
||||
# of the demo program (including parser.java and sym.java that
|
||||
# should have been generated in the previous step).
|
||||
#
|
||||
echo "removing old test results..."
|
||||
echo "rm -f test_results"
|
||||
rm -f test_results
|
||||
echo " "
|
||||
echo "executing the demo program..."
|
||||
echo "echo '2+2;' | java -cs Main >& test_results"
|
||||
echo '2+2;' | java -cs Main >& test_results
|
||||
|
||||
# compare with standard results
|
||||
#
|
||||
set res = `tail -1 test_results`
|
||||
if ("$res" !~ "= 4") then
|
||||
echo "ERROR: test program produced the wrong results"
|
||||
echo "ERROR: output was:"
|
||||
cat test_results
|
||||
echo "ERROR: install was not successful"
|
||||
rm -f test_results
|
||||
exit 2
|
||||
endif
|
||||
|
||||
# all is well
|
||||
#
|
||||
rm -f test_results
|
||||
echo " "
|
||||
echo "=============================="
|
||||
echo "Install and test was successful"
|
||||
echo "=============================="
|
||||
exit 0
|
5
jasmin/jasmin-2.4/lib/java_cup/JASMIN_NOTES.txt
Normal file
5
jasmin/jasmin-2.4/lib/java_cup/JASMIN_NOTES.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
Jasmin use of Java Cup
|
||||
|
||||
The source code for JavaCup, as it is used in the Jasmin distribution, has been moved to ../src/java_cup.
|
||||
|
||||
|
44
jasmin/jasmin-2.4/lib/java_cup/README.txt
Normal file
44
jasmin/jasmin-2.4/lib/java_cup/README.txt
Normal file
|
@ -0,0 +1,44 @@
|
|||
|
||||
This directory contains the Java CUP v0.9d release in source form. You should
|
||||
find the following files and subdirectories in this release:
|
||||
|
||||
README This file.
|
||||
java_cup A subdirectory containing Java CUP and runtime sources.
|
||||
javacup.logo.gif A logo image used by the manual.
|
||||
manual.html A user's manual in HTML format.
|
||||
simple_calc A subdirectory containing a small demo and test application.
|
||||
INSTALL A shell script to install and test the system
|
||||
|
||||
To install the release, copy the contents of this directory (if you haven't
|
||||
done so already) into a "classes" directory accessible to the java interpreter
|
||||
(i.e., a directory that is listed in the colon separated list of directories
|
||||
in your CLASSPATH environment variable).
|
||||
|
||||
Once files have been copied to an appropriate location, you should be able to
|
||||
both compile and test the system by executing the INSTALL shell script
|
||||
(sorry, but non Unix users are still on their own for this release
|
||||
-- zip archive and directions for Win95 users coming soon).
|
||||
Again, be sure that you have placed these sources in a directory listed in
|
||||
your CLASSPATH environment variable (or changed your CLASSPATH to include
|
||||
this directory). The INSTALL script will warn you if this is not the case.
|
||||
|
||||
A manual page that explains the operation and use of the system can be found
|
||||
in manual.html and from the Java CUP home page mentioned below.
|
||||
|
||||
This is an alpha-test release of the Java CUP system and is designed to run
|
||||
under the JDK-beta2 Java compiler. Bug reports regarding the installation
|
||||
process or the system as a whole can be sent to java-cup@cc.gatech.edu.
|
||||
|
||||
The Java CUP home page where the latest information regarding Java CUP can be
|
||||
found (e.g., new releases) is:
|
||||
|
||||
http://www.cc.gatech.edu/gvu/people/Faculty/hudson/java_cup/home.html
|
||||
|
||||
Enjoy,
|
||||
|
||||
Scott Hudson
|
||||
Graphics, Visualization, and Usability Center
|
||||
Georgia Institute of Technology
|
||||
|
||||
Last updated: 1/7/96 [SEH]
|
||||
|
BIN
jasmin/jasmin-2.4/lib/java_cup/Thumbs.db
Normal file
BIN
jasmin/jasmin-2.4/lib/java_cup/Thumbs.db
Normal file
Binary file not shown.
BIN
jasmin/jasmin-2.4/lib/java_cup/java_cup.logo.new.gif
Normal file
BIN
jasmin/jasmin-2.4/lib/java_cup/java_cup.logo.new.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
883
jasmin/jasmin-2.4/lib/java_cup/manual.html
Normal file
883
jasmin/jasmin-2.4/lib/java_cup/manual.html
Normal file
|
@ -0,0 +1,883 @@
|
|||
<html><head>
|
||||
<title>Java(tm) CUP User's Manual</title>
|
||||
</head><body>
|
||||
|
||||
<hr>
|
||||
<img src="java_cup.logo.new.gif" alt="Java CUP Logo Image">
|
||||
<hr>
|
||||
<h1>Java(tm) CUP User's Manual</h1>
|
||||
<h3><a href="http://www.cc.gatech.edu/gvu/people/Faculty/Scott.E.Hudson.html">
|
||||
Scott E. Hudson</a><br>
|
||||
<a href="http://www.cc.gatech.edu/gvu/gvutop.html">
|
||||
Graphics Visualization and Usability Center</a><br>
|
||||
<a href="http://www.gatech.edu/TechHome.html">
|
||||
Georgia Institute of Technology</a><br>
|
||||
<i>January 1996</i> (v0.9d release)</h3>
|
||||
<hr>
|
||||
|
||||
<h3>Table of Contents</h3>
|
||||
<dl compact>
|
||||
<dt> 1. <dd> <a href="#intro">Introduction and Example</a>
|
||||
<dt> 2. <dd> <a href="#spec">Specification Syntax</a>
|
||||
<dt> 3. <dd> <a href="#running">Running Java CUP</a>
|
||||
<dt> 4. <dd> <a href="#parser">Customizing the Parser</a>
|
||||
<dt> 5. <dd> <a href="#errors">Error Recovery</a>
|
||||
<dt> 6. <dd> <a href="#conclusion">Conclusion</a>
|
||||
<dt> <dd> <a href="#refs">References</a>
|
||||
<dt> A. <dd> <a href="#appendixa">Grammar for Java CUP Specification Files</a>
|
||||
<dt> B. <dd> <a href="#appendixb">A Very Simple Example Scanner</a>
|
||||
</dl>
|
||||
|
||||
<a name=intro>
|
||||
<h3>1. Introduction and Example</h3></a>
|
||||
|
||||
This manual describes the basic operation and use of the
|
||||
Java<a href="#trademark">(tm)</a>
|
||||
Based Constructor of Useful Parsers (Java CUP for short).
|
||||
Java CUP is a system for generating LALR parsers from simple specifications.
|
||||
It serves the same role as the widely used program YACC
|
||||
<a href="#YACCref">[1]</a> and in fact offers most of the features of YACC.
|
||||
However, Java CUP is written in Java, uses specifications including embedded
|
||||
Java code, and produces parsers which are implemented in Java.<p>
|
||||
|
||||
Although covering all aspect of the Java CUP system, this manual is relatively
|
||||
brief, assumes you have at least a little bit of knowledge of LR parsing,
|
||||
and preferably have a bit of experience with a program such as YACC.
|
||||
A number of compiler construction textbooks (such as
|
||||
<a href="#dragonbook">[2</a>,<a href="#crafting">3]</a>) cover this material,
|
||||
and discuss the YACC system (which is quite similar to this one) as a
|
||||
specific example. <p>
|
||||
|
||||
Using Java CUP involves creating a simple specifications based on the
|
||||
grammar for which a parser is needed, along with construction of a
|
||||
scanner capable of breaking characters up into meaningful tokens (such
|
||||
as keywords, numbers, and special symbols).<p>
|
||||
|
||||
As a simple example, consider a
|
||||
system for evaluating simple arithmetic expressions over integers.
|
||||
This system would read expressions from standard input (each terminated
|
||||
with a semicolon), evaluate them, and print the result on standard output.
|
||||
A grammar for the input to such a system might look like: <pre>
|
||||
expr_list ::= expr_list expr_part | expr_part
|
||||
expr_part ::= expr ';'
|
||||
expr ::= expr '+' term | expr '-' term | term
|
||||
term ::= term '*' factor | term '/' factor | term '%' factor | factor
|
||||
factor ::= number | '-' expr | '(' expr ')'
|
||||
</pre>
|
||||
To specify a parser based on this grammar, our first step is to identify and
|
||||
name the set of terminal symbols that will appear on input, and the set of
|
||||
non terminal symbols. In this case, the non terminals are:
|
||||
|
||||
<pre><tt> expr_list, expr_part, expr, term,</tt> and <tt>factor</tt>.</pre>
|
||||
|
||||
For terminal names we might choose:
|
||||
|
||||
<pre><tt> SEMI, PLUS, MINUS, TIMES, DIVIDE, MOD, NUMBER, LPAREN,</tt> and <tt>RPAREN</tt></pre>
|
||||
|
||||
Based on these namings we can construct a small Java CUP specification
|
||||
as follows:<br>
|
||||
<hr>
|
||||
<pre><tt>// Java CUP specification for a simple expression evaluator (no actions)
|
||||
|
||||
import java_cup.runtime.*;
|
||||
|
||||
/* Preliminaries to set up and use the scanner. */
|
||||
init with {: scanner.init(); :};
|
||||
scan with {: return scanner.next_token(); :};
|
||||
|
||||
/* Terminals (tokens returned by the scanner). */
|
||||
terminal token SEMI, PLUS, MINUS, TIMES, DIVIDE, MOD, LPAREN, RPAREN;
|
||||
terminal int_token NUMBER;
|
||||
|
||||
/* Non terminals */
|
||||
non terminal symbol expr_list, expr_part;
|
||||
non terminal int_token expr, term, factor;
|
||||
|
||||
/* The grammar */
|
||||
expr_list ::= expr_list expr_part |
|
||||
expr_part;
|
||||
expr_part ::= expr SEMI;
|
||||
expr ::= expr PLUS term |
|
||||
expr MINUS term |
|
||||
term;
|
||||
term ::= term TIMES factor |
|
||||
term DIVIDE factor |
|
||||
term MOD factor |
|
||||
factor;
|
||||
factor ::= NUMBER |
|
||||
MINUS factor |
|
||||
LPAREN expr LPAREN;
|
||||
</tt></pre>
|
||||
<hr><br>
|
||||
We will consider each part of the specification syntax in detail later.
|
||||
However, here we can quickly see that the specification contains three
|
||||
main parts. The first part provides preliminary and miscellaneous declarations
|
||||
to specify how the parser is to be generated, and supply parts of the
|
||||
runtime code. In this case we indicate that the <tt>java_cup.runtime</tt>
|
||||
classes should be imported, then supply a small bit of initialization code,
|
||||
and some code for invoking the scanner to retrieve the next input token.
|
||||
The second part of the specification declares terminals and non terminals,
|
||||
and associates object classes with each. In this case, we declare our terminals
|
||||
as being represented at runtime by two object types: <tt>token</tt> and
|
||||
<tt>int_token</tt> (which are supplied as part of the Java CUP runtime system),
|
||||
while various non terminals are represented by objects of types <tt>symbol</tt>
|
||||
and <tt>int_token</tt> (again supplied from the runtime system). The final
|
||||
part of the specification contains the grammar.<p>
|
||||
|
||||
To produce a parser from this specification we use the Java CUP generator.
|
||||
If this specification were stored in a file <tt>parser.cup</tt>, then
|
||||
(on a Unix system at least) we might invoke Java CUP using a command like:
|
||||
<pre><tt> java java_cup.Main < parser.cup</tt> </pre>
|
||||
In this case, the system will produce two Java source files containing
|
||||
parts of the generated parser: <tt>sym.java</tt> and <tt>parser.java</tt>.
|
||||
As you might expect, these two files contain declarations for the classes
|
||||
<tt>sym</tt> and <tt>parser</tt>. The <tt>sym</tt> class contains a series of
|
||||
constant declarations, one for each terminal symbol. This is typically used
|
||||
by the scanner to refer to symbols (e.g. with code such as
|
||||
"<tt>return new token(sym.SEMI);</tt>" ). The <tt>parser</tt> class
|
||||
implements the parser itself.<p>
|
||||
|
||||
The specification above, while constructing a full parser, does not perform
|
||||
any semantic actions -- it will only indicate success or failure of a parse.
|
||||
To calculate and print values of each expression, we must embed Java
|
||||
code within the parser to carry out actions at various points. In Java CUP,
|
||||
actions are contained in <i>code strings</i> which are surrounded by delimiters
|
||||
of the form <tt>{:</tt> and <tt>:}</tt> (we can see examples of this in the
|
||||
<tt>init with</tt> and <tt>scan with</tt> clauses above). In general, the
|
||||
system records all characters within the delimiters, but does not try to check
|
||||
that it contains valid Java code.<p>
|
||||
|
||||
A more complete Java CUP specification for our example system (with actions
|
||||
embedded at various points in the grammar) is shown below:<br>
|
||||
<hr>
|
||||
<pre><tt>// Java CUP specification for a simple expression evaluator (w/ actions)
|
||||
|
||||
import java_cup.runtime.*;
|
||||
|
||||
/* Preliminaries to set up and use the scanner. */
|
||||
init with {: scanner.init(); :};
|
||||
scan with {: return scanner.next_token(); :};
|
||||
|
||||
/* Terminals (tokens returned by the scanner). */
|
||||
terminal token SEMI, PLUS, MINUS, TIMES, DIVIDE, MOD, LPAREN, RPAREN;
|
||||
terminal int_token NUMBER;
|
||||
|
||||
/* Non terminals */
|
||||
non terminal symbol expr_list, expr_part;
|
||||
non terminal int_token expr, term, factor;
|
||||
|
||||
/* The grammar */
|
||||
expr_list ::= expr_list expr_part
|
||||
|
|
||||
expr_part;
|
||||
|
||||
expr_part ::= expr:e
|
||||
{: System.out.println("= " + e.int_val); :}
|
||||
SEMI
|
||||
;
|
||||
|
||||
expr ::= expr:e1 PLUS term:e2
|
||||
{: RESULT.int_val = e1.int_val + e2.int_val; :}
|
||||
|
|
||||
expr:e1 MINUS term:e2
|
||||
{: RESULT.int_val = e1.int_val - e2.int_val; :}
|
||||
|
|
||||
term:e1
|
||||
{: RESULT.int_val = e1.int_val; :}
|
||||
;
|
||||
|
||||
term ::= term:e1 TIMES factor:e2
|
||||
{: RESULT.int_val = e1.int_val * e2.int_val; :}
|
||||
|
|
||||
term:e1 DIVIDE factor:e2
|
||||
{: RESULT.int_val = e1.int_val / e2.int_val; :}
|
||||
|
|
||||
term:e1 MOD factor:e2
|
||||
{: RESULT.int_val = e1.int_val % e2.int_val; :}
|
||||
|
|
||||
factor:e
|
||||
{: RESULT.int_val = e.int_val; :}
|
||||
;
|
||||
|
||||
factor ::= NUMBER:n
|
||||
{: RESULT.int_val = n.int_val; :}
|
||||
|
|
||||
MINUS factor:e
|
||||
{: RESULT.int_val = -e.int_val; :}
|
||||
|
|
||||
LPAREN expr:e RPAREN
|
||||
{: RESULT.int_val = e.int_val; :}
|
||||
;
|
||||
</tt></pre>
|
||||
<hr><br>
|
||||
Here we can see several changes. Most importantly, code to be executed at
|
||||
various points in the parse is included inside code strings delimited by
|
||||
<tt>{:</tt> and <tt>:}</tt>. In addition, labels have been placed on various
|
||||
symbols in the right hand side of productions. For example in:<br>
|
||||
<pre> expr ::= expr:e1 PLUS term:e2
|
||||
{: RESULT.int_val = e1.int_val + e2.int_val; :}
|
||||
</pre>
|
||||
the non terminal <tt>expr</tt> has been labeled with <tt>e1</tt>, while
|
||||
<tt>term</tt> has been labeled with <tt>e2</tt>. The left hand side
|
||||
symbol of each production is always implicitly labeled as <tt>RESULT</tt>.<p>
|
||||
|
||||
Each symbol appearing in a production is represented at runtime by an
|
||||
object (on the parse stack). These labels allow code embedded in a
|
||||
production to refer to these objects. Since <tt>expr</tt> and <tt>term</tt>
|
||||
were both declared as <tt>int_token</tt>, they are both represented by
|
||||
an object of class <tt>int_token</tt>. These objects are created
|
||||
as the result of matching some other production. The code in that production
|
||||
fills in various fields of its result object, which are in turn used here to
|
||||
fill in a new result object, and so on. Overall this is a very common
|
||||
form of syntax directed translation related to attribute grammars and
|
||||
discussed at length in compiler construction textbooks such as
|
||||
<a href="#dragonbook">[2</a>,<a href="#crafting">3]</a>.
|
||||
<p>
|
||||
|
||||
In our specific example, the <tt>int_token</tt> class includes an
|
||||
<tt>int_val</tt> field which stores an <tt>int</tt> value. We use this
|
||||
field to compute the value of the expression from its component parts.
|
||||
In the production above, we compute the <tt>int_val</tt> field of the
|
||||
left hand side symbol (i.e. <tt>RESULT</tt>) as the sum of the values
|
||||
computed by the <tt>expr</tt> and <tt>term</tt> parts making up this
|
||||
expression. That value in turn may be combined with other to compute a
|
||||
final result.<p>
|
||||
|
||||
The final step in creating a working parser is to create a <i>scanner</i> (also
|
||||
known as a <i>lexical analyzer</i> or simply a <i>lexer</i>). This routine is
|
||||
responsible for reading individual characters, removing things things like
|
||||
white space and comments, recognizing which terminal symbols from the
|
||||
grammar each group of characters represents, then returning token objects
|
||||
representing these symbols to the parser. Example code for a workable (if
|
||||
not elegant or efficient) scanner for our example system can be found in
|
||||
<a href="#appendixb">Appendix B</a>.<p>
|
||||
|
||||
Like the very simple one given in Appendix B, all scanners need to return
|
||||
objects which are instances of <tt>java_cup.runtime.token</tt> (or one of
|
||||
its subclasses). The runtime system predefines three such classes:
|
||||
<tt>token</tt> which contains no specific information beyond the token
|
||||
type (and some internal information used by the parser), <tt>int_token</tt>
|
||||
which also records a single <tt>int</tt> value, and <tt>str_token</tt> which
|
||||
records a single string value. <p>
|
||||
|
||||
The code contained in the <tt>init with</tt> clause of the specification
|
||||
will be executed before any tokens are requested. Each token will be
|
||||
requested using whatever code is found in the <tt>scan with</tt> clause.
|
||||
Beyond this, the exact form the scanner takes is up to you. <p>
|
||||
|
||||
In the <a href="#spec">next section</a> a more detailed and formal
|
||||
explanation of all parts of a Java CUP specification will be given.
|
||||
<a href="#running">Section 3</a> describes options for running the
|
||||
Java CUP system. <a href="#parser">Section 4</a> discusses the details
|
||||
of how to customize a Java CUP parser, while <a href="#errors">Section 5</a>
|
||||
considers error recovery. Finally, <a href="#conclusion">Section 6</a>
|
||||
provides a conclusion.
|
||||
|
||||
<a name="spec">
|
||||
<h3>2. Specification Syntax</h3></a>
|
||||
Now that we have seen a small example, we present a complete description of all
|
||||
parts of a Java CUP specification. A specification has four sections with
|
||||
a total of eight specific parts (however, most of these are optional).
|
||||
A specification consists of:
|
||||
<ul>
|
||||
<li> <a href="#package_spec">package and import specifications</a>,
|
||||
<li> <a href="#code_part">user code components</a>,
|
||||
<li> <a href="#symbol_list">symbol (terminal and non-terminal) lists</a>, and
|
||||
<li> <a href="#production_list">the grammar</a>.
|
||||
</ul>
|
||||
Each of these parts must appear in the order presented here. (A complete
|
||||
grammar for the specification language is given in
|
||||
<a href="#appendixa">Appendix A</a>.) The particulars of each part of
|
||||
the specification are described in the subsections below.<p>
|
||||
|
||||
<h5><a name="package_spec">Package and Import Specifications</a></h5>
|
||||
|
||||
A specification begins with optional <tt>package</tt> and <tt>import</tt>
|
||||
declarations. These have the same syntax, and play the same
|
||||
role, as the package and import declarations found in a normal Java program.
|
||||
A package declaration is of the form:
|
||||
|
||||
<pre><tt> package <i>name</i>;</tt></pre>
|
||||
|
||||
where name <tt><i>name</i></tt> is a Java package identifier, possibly in
|
||||
several parts separated by ".". In general, Java CUP employs Java lexical
|
||||
conventions. So for example, both styles of Java comments are supported,
|
||||
and identifiers are constructed beginning with a letter, dollar
|
||||
sign ($), or underscore (_), which can then be followed by zero or more
|
||||
letters, numbers, dollar signs, and underscores.<p>
|
||||
|
||||
After an optional <tt>package</tt> declaration, there can be zero or more
|
||||
<tt>import</tt> declarations. As in a Java program these have the form:
|
||||
|
||||
<pre><tt> import <i>package_name.class_name</i>;</tt>
|
||||
</pre>
|
||||
or
|
||||
<pre><tt> import <i>package_name</i>.*;</tt>
|
||||
</pre>
|
||||
|
||||
The package declaration indicates what package the <tt>sym</tt> and
|
||||
<tt>parser</tt> classes that are generated by the system will be in.
|
||||
Any import declarations that appear in the specification will also appear
|
||||
in the source file for the <tt>parser</tt> class allowing various names from
|
||||
that package to be used directly in user supplied action code.
|
||||
|
||||
<h5><a name="code_part">User Code Components</a></h5>
|
||||
|
||||
Following the optional <tt>package</tt> and <tt>import</tt> declarations
|
||||
are a series of optional declarations that allow user code to be included
|
||||
as part of the generated parser (see <a href="#parser">Section 4</a> for a
|
||||
full description of how the parser uses this code). As a part of the parser
|
||||
file, a separate non-public class to contain all embedded user actions is
|
||||
produced. The first <tt>action code</tt> declaration section allows code to
|
||||
be included in this class. Routines and variables for use by the code
|
||||
embedded in the grammar would normally be placed in this section (a typical
|
||||
example might be symbol table manipulation routines). This declaration takes
|
||||
the form:
|
||||
|
||||
<pre><tt> action code {: ... :};</tt>
|
||||
</pre>
|
||||
|
||||
where <tt>{: ... :}</tt> is a code string whose contents will be placed
|
||||
directly within the <tt>action class</tt> class declaration.<p>
|
||||
|
||||
After the <tt>action code</tt> declaration is an optional
|
||||
<tt>parser code</tt> declaration. This declaration allows methods and
|
||||
variable to be placed directly within the generated parser class.
|
||||
Although this is less common, it can be helpful when customizing the
|
||||
parser -- it is possible for example, to include scanning methods inside
|
||||
the parser and/or override the default error reporting routines. This
|
||||
declaration is very similar to the <tt>action code</tt> declaration and
|
||||
takes the form:
|
||||
|
||||
<pre><tt> parser code {: ... :};</tt>
|
||||
</pre>
|
||||
|
||||
Again, code from the code string is placed directly into the generated parser
|
||||
class definition.<p>
|
||||
|
||||
Next in the specification is the optional <tt>init</tt> declaration
|
||||
which has the form:
|
||||
|
||||
<pre><tt> init with {: ... :};</tt></pre>
|
||||
|
||||
This declaration provides code that will be executed by the parser
|
||||
before it asks for the first token. Typically, this is used to initialize
|
||||
the scanner as well as various tables and other data structures that might
|
||||
be needed by semantic actions. In this case, the code given in the code
|
||||
string forms the body of a <tt>void</tt> method inside the <tt>parser</tt>
|
||||
class.<p>
|
||||
|
||||
The final (optional) user code section of the specification indicates how
|
||||
the parser should ask for the next token from the scanner. This has the
|
||||
form:
|
||||
|
||||
<pre><tt> scan with {: ... :};</tt></pre>
|
||||
|
||||
As with the <tt>init</tt> clause, the contents of the code string forms
|
||||
the body of a method in the generated parser. However, in this case
|
||||
the method returns an object of type <tt>java_cup.runtime.token</tt>.
|
||||
Consequently the code found in the <tt>scan with</tt> clause should
|
||||
return such a value.<p>
|
||||
|
||||
<h5><a name="symbol_list">Symbol Lists</a></h5>
|
||||
|
||||
Following user supplied code comes the first required part of the
|
||||
specification: the symbol lists. These declarations are responsible
|
||||
for naming and supplying a type for each terminal and non-terminal
|
||||
symbol that appears in the grammar. As indicated above, each terminal
|
||||
and non-terminal symbol is represented at runtime with an object. In
|
||||
the case of terminals, these are returned by the scanner and placed on
|
||||
the parse stack. In the case of non terminals these replace a series
|
||||
of symbol objects on the parse stack whenever the right hand side of
|
||||
some production is recognized. In order to tell the parser which object
|
||||
types should be used for which symbol, <tt>terminal</tt> and
|
||||
<tt>non terminal</tt> declarations are used. These take the forms:
|
||||
|
||||
<pre><tt> terminal <i>classname</i> <i>name1, name2,</i> ...;</tt>
|
||||
</pre>
|
||||
|
||||
and
|
||||
|
||||
<pre><tt> non terminal <i>classname</i> <i>name1, name2,</i> ...;</tt>
|
||||
</pre>
|
||||
|
||||
where <tt><i>classname</i></tt> can be a multiple part name separated with
|
||||
"."s. Since the parser uses these objects for internal bookkeeping, the
|
||||
classes used for non terminal symbols must be a subclass of
|
||||
<tt>java_cup.runtime.symbol</tt>. Similarly, the classes used for terminal
|
||||
symbols must be a subclass of <tt>java_cup.runtime.token</tt> (note that
|
||||
<tt>java_cup.runtime.token</tt> is itself a subclass of
|
||||
<tt>java_cup.runtime.symbol</tt>).
|
||||
|
||||
<h5><a name="production_list">The Grammar</a></h5>
|
||||
|
||||
The final section of a Java CUP declaration provides the grammar. This
|
||||
section optionally starts with a declaration of the form:
|
||||
|
||||
<pre><tt> start with <i>nonterminal</i>;</tt>
|
||||
</pre>
|
||||
|
||||
This indicates which non terminal is the <i>start</i> or <i>goal</i>
|
||||
non terminal for parsing. If a start non terminal is not explicitly
|
||||
declared, then the non terminal on the left hand side of the first
|
||||
production will be used.<p>
|
||||
|
||||
The grammar itself follows the optional <tt>start</tt> declaration. Each
|
||||
production in the grammar has a left hand side non terminal followed by
|
||||
the symbol "<tt>::=</tt>", which is then followed by a series of zero or more
|
||||
actions, terminal, or non terminal symbols, and terminated with a semicolon (;).
|
||||
Each symbol on the right hand side can optionally be labeled with a name.
|
||||
Label names appear after the symbol name separated by a colon (:). Label
|
||||
names must be unique within the production, and can be used within action
|
||||
code to refer to the runtime object that represents the symbol.
|
||||
If there are several productions for the same non terminal they may be
|
||||
declared together. In this case the productions start with the non terminal
|
||||
and "<tt>::=</tt>". This is followed by multiple right hand sides each
|
||||
separated by a bar (|). The full set of productions is then terminated by a
|
||||
semicolon.<p>
|
||||
|
||||
Actions appear in the right hand side as code strings (e.g., Java code inside
|
||||
<tt>{:</tt> ... <tt>:}</tt> delimiters). These are executed by the parser
|
||||
at the point when the portion of the production to the left of the
|
||||
action has been recognized. (Note that the scanner will have returned the
|
||||
token one past the point of the action since the parser needs this extra
|
||||
<i>lookahead</i> token for recognition.)
|
||||
|
||||
<a name="running">
|
||||
<h3>3. Running Java CUP</h3></a>
|
||||
|
||||
As mentioned above, Java CUP is written in Java. To invoke it, one needs
|
||||
to use the Java interpreter to invoke the static method
|
||||
<tt>java_cup.Main()</tt>, passing an array of strings containing options.
|
||||
Assuming a Unix machine, the simplest way to do this is typically to invoke it
|
||||
directly from the command line with a command such as:
|
||||
|
||||
<pre><tt> java java_cup.Main <i>options</i> < <i>inputfile</i></tt></pre>
|
||||
|
||||
Once running, Java CUP expects to find a specification file on standard input
|
||||
and produces two Java source files as output. <p>
|
||||
|
||||
In addition to the specification file, Java CUP's behavior can also be changed
|
||||
by passing various options to it. Legal options include:
|
||||
<dl>
|
||||
<dt><tt>-package</tt> <i>name</i>
|
||||
<dd>Specify that the <tt>parser</tt> and <tt>sym</tt> classes are to be
|
||||
placed in the named package. By default, no package specification
|
||||
is put in the generated code (hence the classes default to the special
|
||||
"unnamed" package).
|
||||
|
||||
<dt><tt>-parser</tt> <i>name</i>
|
||||
<dd>Output parser and action code into a file (and class) with the given
|
||||
name instead of the default of "<tt>parser</tt>".
|
||||
|
||||
<dt><tt>-symbols</tt> <i>name</i>
|
||||
<dd>Output the symbol constant code into a class with the given
|
||||
name instead of the default of "<tt>sym</tt>".
|
||||
|
||||
<dt><tt>-nonterms</tt>
|
||||
<dd>Place constants for non terminals into the symbol constant class.
|
||||
The parser does not need these symbol constants, so they are not normally
|
||||
output. However, it can be very helpful to refer to these constants
|
||||
when debugging a generated parser.
|
||||
|
||||
<dt><tt>-expect</tt> <i>number</i>
|
||||
<dd>During parser construction the system may detect that an ambiguous
|
||||
situation would occur at runtime. This is called a <i>conflict</i>.
|
||||
In general, the parser may be unable to decide whether to <i>shift</i>
|
||||
(read another symbol) or <i>reduce</i> (replace the recognized right
|
||||
hand side of a production with its left hand side). This is called a
|
||||
<i>shift/reduce conflict</i>. Similarly, the parser may not be able
|
||||
to decide between reduction with two different productions. This is
|
||||
called a <i>reduce/reduce conflict</i>. Normally, if one or more of
|
||||
these conflicts occur, parser generation is aborted. However, in
|
||||
certain carefully considered cases it may be advantageous to
|
||||
arbitrarily break such a conflict. In this case Java CUP uses YACC
|
||||
convention and resolves shift/reduce conflicts by shifting, and
|
||||
reduce/reduce conflicts using the "highest priority" production (the
|
||||
one declared first in the specification). In order to enable automatic
|
||||
breaking of conflicts the <tt>-expect</tt> option must be given
|
||||
indicating exactly how many conflicts are expected.
|
||||
|
||||
<dt><tt>-compact_red</tt>
|
||||
<dd>Including this option enables a table compaction optimization involving
|
||||
reductions. In particular, it allows the most common reduce entry in
|
||||
each row of the parse action table to be used as the default for that
|
||||
row. This typically saves considerable room in the tables, which can
|
||||
grow to be very large. This optimization has the effect of replacing
|
||||
all error entries in a row with the default reduce entry. While this
|
||||
may sound dangerous, if not down right incorrect, it turns out that this
|
||||
does not affect the correctness of the parser. In particular, some
|
||||
changes of this type are inherent in LALR parsers (when compared to
|
||||
canonical LR parsers), and the resulting parsers will still never
|
||||
read past the first token at which the error could be detected.
|
||||
The parser can, however, make extra erroneous reduces before detecting
|
||||
the error, so this can degrade the parser's ability to do
|
||||
<a href="#errors">error recovery</a>.
|
||||
(Refer to reference [2] pp. 244-247 or reference [3] pp. 190-194 for a
|
||||
complete explanation of this compaction technique.) <br><br>
|
||||
|
||||
<i>Special note</i>: at the time of this writing the standard
|
||||
javac compiler had a bug which caused it to produce corrupted
|
||||
class files when very large statically initialized arrays (i.e., large
|
||||
parse tables) are used. Consequently, if you have a large grammar, you
|
||||
may be <i>forced</i> to use this option in order to create tables
|
||||
that are small enough to compile correctly.
|
||||
|
||||
<dt><tt>-nowarn</tt>
|
||||
<dd>This options causes all warning messages (as opposed to error messages)
|
||||
produced by the system to be suppressed.
|
||||
|
||||
<dt><tt>-nosummary</tt>
|
||||
<dd>Normally, the system prints a summary listing such things as the
|
||||
number of terminals, non terminals, parse states, etc. at the end of
|
||||
its run. This option suppresses that summary.
|
||||
|
||||
<dt><tt>-progress</tt>
|
||||
<dd>This option causes the system to print short messages indicating its
|
||||
progress through various parts of the parser generation process.
|
||||
|
||||
<dt><tt>-dump_grammar</tt>
|
||||
<dt><tt>-dump_states</tt>
|
||||
<dt><tt>-dump_tables</tt>
|
||||
<dt><tt>-dump</tt>
|
||||
<dd> These options cause the system to produce a human readable dump of
|
||||
the grammar, the constructed parse states (often needed to resolve
|
||||
parse conflicts), and the parse tables (rarely needed), respectively.
|
||||
The <tt>-dump</tt> option can be used to produce all of these dumps.
|
||||
|
||||
<dt><tt>-time</tt>
|
||||
<dd>This option adds detailed timing statistics to the normal summary of
|
||||
results. This is normally of great interest only to maintainers of
|
||||
the system itself.
|
||||
|
||||
<dt><tt>-debug</tt>
|
||||
<dd>This option produces voluminous internal debugging information about
|
||||
the system as it runs. This is normally of interest only to maintainers
|
||||
of the system itself.
|
||||
|
||||
</dl>
|
||||
|
||||
<a name="parser">
|
||||
<h3>4. Customizing the Parser</h3></a>
|
||||
|
||||
Each generated parser consists of three generated classes. The
|
||||
<tt>sym</tt> class (which can be renamed using the <tt>-symbols</tt>
|
||||
option) simply contains a series of <tt>int</tt> constants,
|
||||
one for each terminal. Non terminals are also include if the <tt>-nonterms</tt>
|
||||
option is given. The source file for the <tt>parser</tt> class (which can
|
||||
be renamed using the <tt>-parser</tt> option) actually contains two
|
||||
class definitions, the public <tt>parser</tt> class that implements the
|
||||
actual parser, and another non-public class (called <tt>CUP$action</tt>) which
|
||||
encapsulates all user actions contained in the grammar, as well as code from
|
||||
the <tt>action code</tt> declaration. In addition to user supplied code, this
|
||||
class contains one method: <tt>CUP$do_action</tt> which consists of a large
|
||||
switch statement for selecting and executing various fragments of user
|
||||
supplied action code. In general, all names beginning with the prefix of
|
||||
<tt>CUP$</tt> are reserved for internal uses by Java CUP generated code. <p>
|
||||
|
||||
The <tt>parser</tt> class contains the actual generated parser. It is
|
||||
a subclass of <tt>java_cup.runtime.lr_parser</tt> which implements a
|
||||
general table driven framework for an LR parser. The generated <tt>parser</tt>
|
||||
class provides a series of tables for use by the general framework.
|
||||
Three tables are provided:
|
||||
<dl compact>
|
||||
<dt>the production table
|
||||
<dd>provides the symbol number of the left hand side non terminal, along with
|
||||
the length of the right hand side, for each production in the grammar,
|
||||
<dt>the action table
|
||||
<dd>indicates what action (shift, reduce, or error) is to be taken on each
|
||||
lookahead symbol when encountered in each state, and
|
||||
<dt>the reduce-goto table
|
||||
<dd>indicates which state to shift to after reduces (under each non-terminal
|
||||
from each state).
|
||||
</dl>
|
||||
(Note that the action and reduce-goto tables are not stored as simple arrays,
|
||||
but use a compacted "list" structure to save a significant amount of space.
|
||||
See comments the runtime system source code for details.)<p>
|
||||
|
||||
Beyond the parse tables, generated (or inherited) code provides a series
|
||||
of methods that can be used to customize the generated parser. Some of these
|
||||
methods are supplied by code found in part of the specification and can
|
||||
be customized directly in that fashion. The others are provided by the
|
||||
<tt>lr_parser</tt> base class and can be overridden with new versions (via
|
||||
the <tt>parser code</tt> declaration) to customize the system. Methods
|
||||
available for customization include:
|
||||
<dl compact>
|
||||
<dt><tt>public void user_init()</tt>
|
||||
<dd>This method is called by the parser prior to asking for the first token
|
||||
from the scanner. The body of this method contains the code from the
|
||||
<tt>init with</tt> clause of the the specification.
|
||||
<dt><tt>public java_cup.runtime.token scan()</tt>
|
||||
<dd>This method encapsulates the scanner and is called each time a new token is
|
||||
needed by the parser. The body of this method is supplied by the
|
||||
<tt>scan with</tt> clause of the specification.
|
||||
<dt><tt> public void report_error(String message, Object info)</tt>
|
||||
<dd>This method should be called whenever an error message is to be issued. In
|
||||
the default implementation of this method, the first parameter provides
|
||||
the text of a message which is printed on <tt>System.err</tt>
|
||||
and the second parameter is simply ignored. It is very typical to
|
||||
override this method in order to provide a more sophisticated error
|
||||
reporting mechanism.
|
||||
<dt><tt>public void report_fatal_error(String message, Object info)</tt>
|
||||
<dd>This method should be called whenever a non-recoverable error occurs. It
|
||||
responds by calling <tt>report_error()</tt>, then aborts parsing
|
||||
by calling the parser method <tt>done_parsing()</tt>, and finally
|
||||
throws an exception. (In general <tt>done_parsing()</tt> should be called
|
||||
at any point that parsing needs to be terminated early).
|
||||
<dt><tt>public void syntax_error(token cur_token)</tt>
|
||||
<dd>This method is called by the parser as soon as a syntax error is detected
|
||||
(but before error recovery is attempted). In the default implementation it
|
||||
calls: <tt>report_error("Syntax error", null);</tt>.
|
||||
<dt><tt>public void unrecovered_syntax_error(token cur_token)</tt>
|
||||
<dd>This method is called by the parser if it is unable to recover from a
|
||||
syntax error. In the default implementation it calls:
|
||||
<tt>report_fatal_error("Couldn't repair and continue parse", null);</tt>.
|
||||
<dt><tt> protected int error_sync_size()</tt>
|
||||
<dd>This method is called by the parser to determine how many tokens it must
|
||||
successfully parse in order to consider an error recovery successful.
|
||||
The default implementation returns 3. Values below 2 are not recommended.
|
||||
See the section on <a href="#errors">error recovery</a> for details.
|
||||
</dl>
|
||||
|
||||
Parsing itself is performed by the method <tt>public void parse()</tt>.
|
||||
This method starts by getting references to each of the parse tables,
|
||||
then initializes a <tt>CUP$action</tt> object (by calling
|
||||
<tt>protected void init_actions()</tt>). Next it calls <tt>user_init()</tt>,
|
||||
then fetches the first lookahead token with a call to <tt>scan()</tt>.
|
||||
Finally, it begins parsing. Parsing continues until <tt>done_parsing()</tt>
|
||||
is called (this is done automatically, for example, when the parser accepts).<p>
|
||||
|
||||
In addition to the normal parser, the runtime system also provides a debugging
|
||||
version of the parser. This operates in exactly the same way as the normal
|
||||
parser, but prints debugging messages (by calling
|
||||
<tt>public void debug_message(String mess)</tt> whose default implementation
|
||||
prints a message to <tt>System.err</tt>).<p>
|
||||
|
||||
Based on these routines, invocation of a Java CUP parser is typically done
|
||||
with code such as:
|
||||
<pre>
|
||||
/* create a parsing object */
|
||||
parser parse_obj = new parser();
|
||||
|
||||
/* open input files, etc. here */
|
||||
|
||||
try {
|
||||
if (do_debug_parse)
|
||||
parser_obj.debug_parse();
|
||||
else
|
||||
parser_obj.parse();
|
||||
} catch (Exception e) {
|
||||
/* do cleanup here -- possibly rethrow e */
|
||||
} finally {
|
||||
/* do close out here */
|
||||
}
|
||||
</pre>
|
||||
|
||||
<a name="errors">
|
||||
<h3>5. Error Recovery</h3></a>
|
||||
|
||||
A final important aspect of building parsers with Java CUP is
|
||||
support for syntactic error recovery. Java CUP uses the same
|
||||
error recovery mechanisms as YACC. In particular, it supports
|
||||
a special error symbol (denoted simply as <tt>error</tt>).
|
||||
This symbol plays the role of a special non terminal which, instead of
|
||||
being defined by productions, instead matches an erroneous input
|
||||
sequence.<p>
|
||||
|
||||
The error symbol only comes into play if a syntax error is
|
||||
detected. If a syntax error is detected then the parser tries to replace
|
||||
some portion of the input token stream with <tt>error</tt> and then
|
||||
continue parsing. For example, we might have productions such as:
|
||||
|
||||
<pre><tt> stmt ::= expr SEMI | while_stmt SEMI | if_stmt SEMI | ... |
|
||||
error SEMI
|
||||
;</tt></pre>
|
||||
|
||||
This indicates that if none of the normal productions for <tt>stmt</tt> can
|
||||
be matched by the input, then a syntax error should be declared, and recovery
|
||||
should be made by skipping erroneous tokens (equivalent to matching and
|
||||
replacing them with <tt>error</tt>) up to a point at which the parse can
|
||||
be continued with a semicolon (and additional context that legally follows a
|
||||
statement). An error is considered to be recovered from if and only if a
|
||||
sufficient number of tokens past the <tt>error</tt> symbol can be successfully
|
||||
parsed. (The number of tokens required is determined by the
|
||||
<tt>error_sync_size()</tt> method of the parser and defaults to 3). <p>
|
||||
|
||||
Specifically, the parser first looks for the closest state to the top
|
||||
of the parse stack that has an outgoing transition under
|
||||
<tt>error</tt>. This generally corresponds to working from
|
||||
productions that represent more detailed constructs (such as a specific
|
||||
kind of statement) up to productions that represent more general or
|
||||
enclosing constructs (such as the general production for all
|
||||
statements or a production representing a whole section of declarations)
|
||||
until we get to a place where an error recovery production
|
||||
has been provided for. Once the parser is placed into a configuration
|
||||
that has an immediate error recovery (by popping the stack to the first
|
||||
such state), the parser begins skipping tokens to find a point at
|
||||
which the parse can be continued. After discarding each token, the
|
||||
parser attempts to parse ahead in the input (without executing any
|
||||
embedded semantic actions). If the parser can successfully parse past
|
||||
the required number of tokens, then the input is backed up to the point
|
||||
of recovery and the parse is resumed normally (executing all actions).
|
||||
If the parse cannot be continued far enough, then another token is
|
||||
discarded and the parser again tries to parse ahead. If the end of
|
||||
input is reached without making a successful recovery (or there was no
|
||||
suitable error recovery state found on the parse stack to begin with)
|
||||
then error recovery fails.
|
||||
|
||||
<a name="conclusion">
|
||||
<h3>6. Conclusion</h3></a>
|
||||
|
||||
This manual has briefly described the Java CUP LALR parser generation system.
|
||||
Java CUP is designed to fill the same role as the well known YACC parser
|
||||
generator system, but is written in and operates entirely with Java code
|
||||
rather than C or C++. Additional details on the operation of the system can
|
||||
be found in the parser generator and runtime source code. See the Java CUP
|
||||
home page below for access to the API documentation for the system and its
|
||||
runtime.<p>
|
||||
|
||||
This document covers the system as it stands at the time of its fourth alpha
|
||||
release (v0.9d). Check the Java CUP home page:
|
||||
<a href="http://www.cc.gatech.edu/gvu/people/Faculty/hudson/java_cup/home.html">
|
||||
http://www.cc.gatech.edu/gvu/people/Faculty/hudson/java_cup/home.html</a>
|
||||
for the latest release information, instructions for downloading the
|
||||
system, and additional news about the system. Bug reports and other
|
||||
comments for the developers can be sent to
|
||||
<a href="mailto:java-cup@cc.gatech.edu"> java-cup@cc.gatech.edu</a><p>
|
||||
|
||||
Java CUP was originally written by
|
||||
<a href="http://www.cc.gatech.edu/gvu/people/Faculty/Scott.E.Hudson.html">
|
||||
Scott Hudson</a>, in August of 1995.<p>
|
||||
|
||||
<a name="refs">
|
||||
<h3>References</h3></a>
|
||||
<dl compact>
|
||||
|
||||
<dt><a name = "YACCref">[1]</a>
|
||||
<dd>S. C. Johnson,
|
||||
"YACC -- Yet Another Compiler Compiler",
|
||||
CS Technical Report #32,
|
||||
Bell Telephone Laboratories,
|
||||
Murray Hill, NJ,
|
||||
1975.
|
||||
|
||||
<dt><a name = "dragonbook">[2]</a>
|
||||
<dd>A. Aho, R. Sethi, and J. Ullman,
|
||||
<i>Compilers: Principles, Techniques, and Tools</i>,
|
||||
Addison-Wesley Publishing,
|
||||
Reading, MA,
|
||||
1986.
|
||||
|
||||
<dt><a name = "crafting">[3]</a>
|
||||
<dd>C. Fischer, and R. LeBlanc,
|
||||
<i>Crafting a Compiler with C</i>,
|
||||
Benjamin/Cummings Publishing,
|
||||
Redwood City, CA,
|
||||
1991.
|
||||
|
||||
</dl>
|
||||
|
||||
<h3><a name="appendixa">
|
||||
Appendix A. Grammar for Java CUP Specification Files</a></h3>
|
||||
<hr><br>
|
||||
<pre><tt>java_cup_spec ::= package_spec import_list code_part init_code
|
||||
scan_code symbol_list start_spec production_list
|
||||
package_spec ::= PACKAGE multipart_id SEMI | empty
|
||||
import_list ::= import_list import_spec | empty
|
||||
import_spec ::= IMPORT import_id SEMI
|
||||
code_part ::= action_code_part parser_code_part
|
||||
action_code_part ::= ACTION CODE CODE_STRING SEMI | empty
|
||||
parser_code_part ::= PARSER CODE CODE_STRING SEMI | empty
|
||||
init_code ::= INIT WITH CODE_STRING SEMI | empty
|
||||
scan_code ::= SCAN WITH CODE_STRING SEMI | empty
|
||||
symbol_list ::= symbol_list symbol | symbol
|
||||
symbol ::= TERMINAL type_id term_name_list SEMI |
|
||||
NON TERMINAL type_id non_term_name_list SEMI
|
||||
term_name_list ::= term_name_list COMMA new_term_id | new_term_id
|
||||
non_term_name_list ::= non_term_name_list COMMA new_non_term_id |
|
||||
new_non_term_id
|
||||
start_spec ::= START WITH nt_id SEMI | empty
|
||||
production_list ::= production_list production | production
|
||||
production ::= nt_id COLON_COLON_EQUALS rhs_list SEMI
|
||||
rhs_list ::= rhs_list BAR rhs | rhs
|
||||
rhs ::= prod_part_list
|
||||
prod_part_list ::= prod_part_list prod_part | empty
|
||||
prod_part ::= symbol_id opt_label | CODE_STRING
|
||||
opt_label ::= COLON label_id | empty
|
||||
multipart_id ::= multipart_id DOT ID | ID
|
||||
import_id ::= multipart_id DOT STAR | multipart_id
|
||||
type_id ::= multipart_id
|
||||
new_term_id ::= ID
|
||||
new_non_term_id ::= ID
|
||||
nt_id ::= ID
|
||||
symbol_id ::= ID
|
||||
label_id ::= ID
|
||||
</tt></pre>
|
||||
<hr><p><p>
|
||||
|
||||
<h3><a name = "appendixb">Appendix B. A Very Simple Example Scanner<a></h3>
|
||||
<hr><br>
|
||||
<pre>
|
||||
<tt>// Simple Example Scanner Class
|
||||
|
||||
import java_cup.runtime.*;
|
||||
|
||||
public class scanner {
|
||||
/* single lookahead character */
|
||||
protected static int next_char;
|
||||
|
||||
/* advance input by one character */
|
||||
protected static void advance() { next_char = System.in.read(); }
|
||||
|
||||
/* initialize the scanner */
|
||||
public static void init() { advance(); }
|
||||
|
||||
/* recognize and return the next complete token */
|
||||
public static token next_token()
|
||||
{
|
||||
for (;;)
|
||||
switch (next_char)
|
||||
{
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
/* parse a decimal integer */
|
||||
int i_val = 0;
|
||||
do {
|
||||
i_val = i_val * 10 + (next_char - '0');
|
||||
advance();
|
||||
} while (next_char >= '0' && next_char <= '9');
|
||||
return new int_token(sym.NUMBER, i_val);
|
||||
|
||||
case ';': advance(); return new token(sym.SEMI);
|
||||
case '+': advance(); return new token(sym.PLUS);
|
||||
case '-': advance(); return new token(sym.MINUS);
|
||||
case '*': advance(); return new token(sym.TIMES);
|
||||
case '/': advance(); return new token(sym.DIVIDE);
|
||||
case '%': advance(); return new token(sym.MOD);
|
||||
case '(': advance(); return new token(sym.LPAREN);
|
||||
case ')': advance(); return new token(sym.RPAREN);
|
||||
|
||||
case -1: return new token(sym.EOF);
|
||||
|
||||
default:
|
||||
/* in this simple scanner we just ignore everything else */
|
||||
advance();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
</tt></pre>
|
||||
|
||||
<hr>
|
||||
<a name="trademark">
|
||||
Java and HotJava are
|
||||
trademarks of <a href="http://www.sun.com/">Sun Microsystems, Inc.</a>,
|
||||
and refer to Sun's Java programming language and HotJava browser
|
||||
technologies.
|
||||
Java CUP is not sponsored by or affiliated with Sun Microsystems, Inc.
|
||||
</a>
|
||||
|
||||
<hr><p><p>
|
||||
|
||||
|
||||
</body></html>
|
27
jasmin/jasmin-2.4/lib/java_cup/simple_calc/Main.java
Normal file
27
jasmin/jasmin-2.4/lib/java_cup/simple_calc/Main.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
public class Main {
|
||||
public static void main(String argv[])
|
||||
{
|
||||
try {
|
||||
/* allocate a parser object */
|
||||
parser parse_obj = new parser();
|
||||
|
||||
/* prompt the user */
|
||||
System.out.println("Reading expressions from standard input...");
|
||||
|
||||
/* deterimine if we doing debug or normal parse, and do it */
|
||||
if (argv.length >= 1 && argv[0].equals("-debug"))
|
||||
{
|
||||
parse_obj.debug_parse();
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_obj.parse();
|
||||
}
|
||||
} catch (java.lang.Exception ex) {
|
||||
System.err.println("Exception: " + ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
};
|
58
jasmin/jasmin-2.4/lib/java_cup/simple_calc/parser.cup
Normal file
58
jasmin/jasmin-2.4/lib/java_cup/simple_calc/parser.cup
Normal file
|
@ -0,0 +1,58 @@
|
|||
// JavaCup specification for a simple expression evaluator (w/ actions)
|
||||
|
||||
import java_cup.runtime.*;
|
||||
|
||||
/* Preliminaries to set up and use the scanner. */
|
||||
init with {: scanner.init(); :};
|
||||
scan with {: return scanner.next_token(); :};
|
||||
|
||||
/* Terminals (tokens returned by the scanner). */
|
||||
terminal token SEMI, PLUS, MINUS, TIMES, DIVIDE, MOD, LPAREN, RPAREN;
|
||||
terminal int_token NUMBER;
|
||||
|
||||
/* Non terminals */
|
||||
non terminal symbol expr_list, expr_part;
|
||||
non terminal int_token expr, term, factor;
|
||||
|
||||
/* The grammar */
|
||||
expr_list ::= expr_list expr_part
|
||||
|
|
||||
expr_part;
|
||||
|
||||
expr_part ::= expr:e
|
||||
{: System.out.println("= " + e.int_val); :}
|
||||
SEMI
|
||||
;
|
||||
|
||||
expr ::= expr:e1 PLUS term:e2
|
||||
{: RESULT.int_val = e1.int_val + e2.int_val; :}
|
||||
|
|
||||
expr:e1 MINUS term:e2
|
||||
{: RESULT.int_val = e1.int_val - e2.int_val; :}
|
||||
|
|
||||
term:e1
|
||||
{: RESULT.int_val = e1.int_val; :}
|
||||
;
|
||||
|
||||
term ::= term:e1 TIMES factor:e2
|
||||
{: RESULT.int_val = e1.int_val * e2.int_val; :}
|
||||
|
|
||||
term:e1 DIVIDE factor:e2
|
||||
{: RESULT.int_val = e1.int_val / e2.int_val; :}
|
||||
|
|
||||
term:e1 MOD factor:e2
|
||||
{: RESULT.int_val = e1.int_val % e2.int_val; :}
|
||||
|
|
||||
factor:e
|
||||
{: RESULT.int_val = e.int_val; :}
|
||||
;
|
||||
|
||||
factor ::= NUMBER:n
|
||||
{: RESULT.int_val = n.int_val; :}
|
||||
|
|
||||
MINUS factor:e
|
||||
{: RESULT.int_val = -e.int_val; :}
|
||||
|
|
||||
LPAREN expr:e RPAREN
|
||||
{: RESULT.int_val = e.int_val; :}
|
||||
;
|
287
jasmin/jasmin-2.4/lib/java_cup/simple_calc/parser.java
Normal file
287
jasmin/jasmin-2.4/lib/java_cup/simple_calc/parser.java
Normal file
|
@ -0,0 +1,287 @@
|
|||
|
||||
//----------------------------------------------------
|
||||
// The following code was generated by Java(tm) CUP v0.9d
|
||||
// Sun Jan 07 17:10:11 EST 1996
|
||||
//----------------------------------------------------
|
||||
|
||||
import java_cup.runtime.*;
|
||||
|
||||
public class parser extends java_cup.runtime.lr_parser {
|
||||
|
||||
/** constructor */
|
||||
public parser() {super();}
|
||||
|
||||
/** production table */
|
||||
protected static final short _production_table[][] = {
|
||||
{1, 2}, {0, 2}, {1, 1}, {6, 0}, {2, 3},
|
||||
{3, 3}, {3, 3}, {3, 1}, {4, 3}, {4, 3},
|
||||
{4, 3}, {4, 1}, {5, 1}, {5, 2}, {5, 3}
|
||||
};
|
||||
|
||||
/** access to production table */
|
||||
public short[][] production_table() {return _production_table;}
|
||||
|
||||
/** parse action table */
|
||||
protected static final short[][] _action_table = {
|
||||
/*0*/{4,2,8,9,10,4,-1,0},
|
||||
/*1*/{4,2,8,9,10,4,-1,0},
|
||||
/*2*/{2,-12,3,-12,4,-12,5,-12,6,-12,7,-12,9,-12,-1,0},
|
||||
/*3*/{2,-13,3,-13,4,-13,5,-13,6,-13,7,-13,9,-13,-1,0},
|
||||
/*4*/{0,-3,4,-3,8,-3,10,-3,-1,0},
|
||||
/*5*/{2,-4,3,13,4,11,-1,0},
|
||||
/*6*/{0,23,4,2,8,9,10,4,-1,0},
|
||||
/*7*/{2,-8,3,-8,4,-8,5,16,6,17,7,15,9,-8,-1,0},
|
||||
/*8*/{4,2,8,9,10,4,-1,0},
|
||||
/*9*/{3,13,4,11,9,12,-1,0},
|
||||
/*10*/{4,2,8,9,10,4,-1,0},
|
||||
/*11*/{2,-15,3,-15,4,-15,5,-15,6,-15,7,-15,9,-15,-1,0},
|
||||
/*12*/{4,2,8,9,10,4,-1,0},
|
||||
/*13*/{2,-6,3,-6,4,-6,5,16,6,17,7,15,9,-6,-1,0},
|
||||
/*14*/{4,2,8,9,10,4,-1,0},
|
||||
/*15*/{4,2,8,9,10,4,-1,0},
|
||||
/*16*/{4,2,8,9,10,4,-1,0},
|
||||
/*17*/{2,-10,3,-10,4,-10,5,-10,6,-10,7,-10,9,-10,-1,0},
|
||||
/*18*/{2,-9,3,-9,4,-9,5,-9,6,-9,7,-9,9,-9,-1,0},
|
||||
/*19*/{2,-11,3,-11,4,-11,5,-11,6,-11,7,-11,9,-11,-1,0},
|
||||
/*20*/{2,-7,3,-7,4,-7,5,16,6,17,7,15,9,-7,-1,0},
|
||||
/*21*/{0,-1,4,-1,8,-1,10,-1,-1,0},
|
||||
/*22*/{0,-2,-1,0},
|
||||
/*23*/{2,25,-1,0},
|
||||
/*24*/{0,-5,4,-5,8,-5,10,-5,-1,0},
|
||||
/*25*/{2,-14,3,-14,4,-14,5,-14,6,-14,7,-14,9,-14,-1,0},
|
||||
};
|
||||
|
||||
/** access to parse action table */
|
||||
public short[][] action_table() {return _action_table;}
|
||||
|
||||
/** reduce_goto table */
|
||||
protected static final short[][] _reduce_table = {
|
||||
/*0*/{1,6,2,4,3,5,4,7,5,2,-1,-1},
|
||||
/*1*/{5,25,-1,-1},
|
||||
/*2*/{-1,-1},
|
||||
/*3*/{-1,-1},
|
||||
/*4*/{-1,-1},
|
||||
/*5*/{6,23,-1,-1},
|
||||
/*6*/{2,21,3,5,4,7,5,2,-1,-1},
|
||||
/*7*/{-1,-1},
|
||||
/*8*/{3,9,4,7,5,2,-1,-1},
|
||||
/*9*/{-1,-1},
|
||||
/*10*/{4,20,5,2,-1,-1},
|
||||
/*11*/{-1,-1},
|
||||
/*12*/{4,13,5,2,-1,-1},
|
||||
/*13*/{-1,-1},
|
||||
/*14*/{5,19,-1,-1},
|
||||
/*15*/{5,18,-1,-1},
|
||||
/*16*/{5,17,-1,-1},
|
||||
/*17*/{-1,-1},
|
||||
/*18*/{-1,-1},
|
||||
/*19*/{-1,-1},
|
||||
/*20*/{-1,-1},
|
||||
/*21*/{-1,-1},
|
||||
/*22*/{-1,-1},
|
||||
/*23*/{-1,-1},
|
||||
/*24*/{-1,-1},
|
||||
/*25*/{-1,-1},
|
||||
};
|
||||
|
||||
/** access to reduce_goto table */
|
||||
public short[][] reduce_table() {return _reduce_table;}
|
||||
|
||||
/** instance of action encapsulation class */
|
||||
protected CUP$actions action_obj;
|
||||
|
||||
/** action encapsulation object initializer */
|
||||
protected void init_actions()
|
||||
{
|
||||
action_obj = new CUP$actions();
|
||||
}
|
||||
|
||||
/** invoke a user supplied parse action */
|
||||
public java_cup.runtime.symbol do_action(
|
||||
int act_num,
|
||||
java_cup.runtime.lr_parser parser,
|
||||
java.util.Stack stack,
|
||||
int top)
|
||||
throws java.lang.Exception
|
||||
{
|
||||
/* call code in generated class */
|
||||
return action_obj.CUP$do_action(act_num, parser, stack, top);
|
||||
}
|
||||
|
||||
/** start state */
|
||||
public int start_state() {return 0;}
|
||||
/** start production */
|
||||
public int start_production() {return 1;}
|
||||
|
||||
/** EOF symbol index */
|
||||
public int EOF_sym() {return 0;}
|
||||
|
||||
/** error symbol index */
|
||||
public int error_sym() {return 1;}
|
||||
|
||||
|
||||
/** user initialization */
|
||||
public void user_init() throws java.lang.Exception
|
||||
{
|
||||
scanner.init();
|
||||
}
|
||||
|
||||
/** scan to get the next token */
|
||||
public java_cup.runtime.token scan()
|
||||
throws java.lang.Exception
|
||||
{
|
||||
return scanner.next_token();
|
||||
}
|
||||
};
|
||||
|
||||
/** JavaCup generated class to encapsulate user supplied action code.*/
|
||||
class CUP$actions {
|
||||
|
||||
/** Constructor */
|
||||
CUP$actions() { }
|
||||
|
||||
/** Method with the actual generated action code. */
|
||||
public final java_cup.runtime.symbol CUP$do_action(
|
||||
int CUP$act_num,
|
||||
java_cup.runtime.lr_parser CUP$parser,
|
||||
java.util.Stack CUP$stack,
|
||||
int CUP$top)
|
||||
throws java.lang.Exception
|
||||
{
|
||||
/* object for return from actions */
|
||||
java_cup.runtime.symbol CUP$result;
|
||||
|
||||
/* select the action based on the action number */
|
||||
switch (CUP$act_num)
|
||||
{
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 14: // factor ::= LPAREN expr RPAREN
|
||||
{
|
||||
CUP$result = new int_token(/*factor*/5);
|
||||
((int_token)CUP$result).int_val = (/*e*/(int_token)CUP$stack.elementAt(CUP$top-1)).int_val;
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 13: // factor ::= MINUS factor
|
||||
{
|
||||
CUP$result = new int_token(/*factor*/5);
|
||||
((int_token)CUP$result).int_val = -(/*e*/(int_token)CUP$stack.elementAt(CUP$top-0)).int_val;
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 12: // factor ::= NUMBER
|
||||
{
|
||||
CUP$result = new int_token(/*factor*/5);
|
||||
((int_token)CUP$result).int_val = (/*n*/(int_token)CUP$stack.elementAt(CUP$top-0)).int_val;
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 11: // term ::= factor
|
||||
{
|
||||
CUP$result = new int_token(/*term*/4);
|
||||
((int_token)CUP$result).int_val = (/*e*/(int_token)CUP$stack.elementAt(CUP$top-0)).int_val;
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 10: // term ::= term MOD factor
|
||||
{
|
||||
CUP$result = new int_token(/*term*/4);
|
||||
((int_token)CUP$result).int_val = (/*e1*/(int_token)CUP$stack.elementAt(CUP$top-2)).int_val % (/*e2*/(int_token)CUP$stack.elementAt(CUP$top-0)).int_val;
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 9: // term ::= term DIVIDE factor
|
||||
{
|
||||
CUP$result = new int_token(/*term*/4);
|
||||
((int_token)CUP$result).int_val = (/*e1*/(int_token)CUP$stack.elementAt(CUP$top-2)).int_val / (/*e2*/(int_token)CUP$stack.elementAt(CUP$top-0)).int_val;
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 8: // term ::= term TIMES factor
|
||||
{
|
||||
CUP$result = new int_token(/*term*/4);
|
||||
((int_token)CUP$result).int_val = (/*e1*/(int_token)CUP$stack.elementAt(CUP$top-2)).int_val * (/*e2*/(int_token)CUP$stack.elementAt(CUP$top-0)).int_val;
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 7: // expr ::= term
|
||||
{
|
||||
CUP$result = new int_token(/*expr*/3);
|
||||
((int_token)CUP$result).int_val = (/*e1*/(int_token)CUP$stack.elementAt(CUP$top-0)).int_val;
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 6: // expr ::= expr MINUS term
|
||||
{
|
||||
CUP$result = new int_token(/*expr*/3);
|
||||
((int_token)CUP$result).int_val = (/*e1*/(int_token)CUP$stack.elementAt(CUP$top-2)).int_val - (/*e2*/(int_token)CUP$stack.elementAt(CUP$top-0)).int_val;
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 5: // expr ::= expr PLUS term
|
||||
{
|
||||
CUP$result = new int_token(/*expr*/3);
|
||||
((int_token)CUP$result).int_val = (/*e1*/(int_token)CUP$stack.elementAt(CUP$top-2)).int_val + (/*e2*/(int_token)CUP$stack.elementAt(CUP$top-0)).int_val;
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 4: // expr_part ::= expr NT$0 SEMI
|
||||
{
|
||||
CUP$result = new symbol(/*expr_part*/2);
|
||||
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 3: // NT$0 ::=
|
||||
{
|
||||
CUP$result = new java_cup.runtime.token(/*NT$0*/6);
|
||||
System.out.println("= " + (/*e*/(int_token)CUP$stack.elementAt(CUP$top-0)).int_val);
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 2: // expr_list ::= expr_part
|
||||
{
|
||||
CUP$result = new symbol(/*expr_list*/1);
|
||||
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 1: // $START ::= expr_list EOF
|
||||
{
|
||||
CUP$result = new java_cup.runtime.token(/*$START*/0);
|
||||
|
||||
}
|
||||
/* ACCEPT */
|
||||
CUP$parser.done_parsing();
|
||||
return CUP$result;
|
||||
|
||||
/*. . . . . . . . . . . . . . . . . . . .*/
|
||||
case 0: // expr_list ::= expr_list expr_part
|
||||
{
|
||||
CUP$result = new symbol(/*expr_list*/1);
|
||||
|
||||
}
|
||||
return CUP$result;
|
||||
|
||||
/* . . . . . .*/
|
||||
default:
|
||||
throw new Exception(
|
||||
"Invalid action number found in internal parse table");
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
51
jasmin/jasmin-2.4/lib/java_cup/simple_calc/scanner.java
Normal file
51
jasmin/jasmin-2.4/lib/java_cup/simple_calc/scanner.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
// Simple Example Scanner Class
|
||||
|
||||
import java_cup.runtime.*;
|
||||
|
||||
public class scanner {
|
||||
/* single lookahead character */
|
||||
protected static int next_char;
|
||||
|
||||
/* advance input by one character */
|
||||
protected static void advance() throws java.io.IOException
|
||||
{
|
||||
next_char = System.in.read();
|
||||
}
|
||||
|
||||
/* initialize the scanner */
|
||||
public static void init() throws java.io.IOException { advance(); }
|
||||
|
||||
/* recognize and return the next complete token */
|
||||
public static token next_token() throws java.io.IOException
|
||||
{
|
||||
for (;;)
|
||||
switch (next_char)
|
||||
{
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
/* parse a decimal integer */
|
||||
int i_val = 0;
|
||||
do {
|
||||
i_val = i_val * 10 + (next_char - '0');
|
||||
advance();
|
||||
} while (next_char >= '0' && next_char <= '9');
|
||||
return new int_token(sym.NUMBER, i_val);
|
||||
|
||||
case ';': advance(); return new token(sym.SEMI);
|
||||
case '+': advance(); return new token(sym.PLUS);
|
||||
case '-': advance(); return new token(sym.MINUS);
|
||||
case '*': advance(); return new token(sym.TIMES);
|
||||
case '/': advance(); return new token(sym.DIVIDE);
|
||||
case '%': advance(); return new token(sym.MOD);
|
||||
case '(': advance(); return new token(sym.LPAREN);
|
||||
case ')': advance(); return new token(sym.RPAREN);
|
||||
|
||||
case -1: return new token(sym.EOF);
|
||||
|
||||
default:
|
||||
/* in this simple scanner we just ignore everything else */
|
||||
advance();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
22
jasmin/jasmin-2.4/lib/java_cup/simple_calc/sym.java
Normal file
22
jasmin/jasmin-2.4/lib/java_cup/simple_calc/sym.java
Normal file
|
@ -0,0 +1,22 @@
|
|||
|
||||
//----------------------------------------------------
|
||||
// The following code was generated by Java(tm) CUP v0.9d
|
||||
// Sun Jan 07 17:10:10 EST 1996
|
||||
//----------------------------------------------------
|
||||
|
||||
/** JavaCup generated class containing symbol constants. */
|
||||
public class sym {
|
||||
/* terminals */
|
||||
static final int SEMI = 2;
|
||||
static final int EOF = 0;
|
||||
static final int DIVIDE = 6;
|
||||
static final int NUMBER = 10;
|
||||
static final int error = 1;
|
||||
static final int MINUS = 4;
|
||||
static final int TIMES = 5;
|
||||
static final int LPAREN = 8;
|
||||
static final int RPAREN = 9;
|
||||
static final int MOD = 7;
|
||||
static final int PLUS = 3;
|
||||
};
|
||||
|
212
jasmin/jasmin-2.4/license-ant.txt
Normal file
212
jasmin/jasmin-2.4/license-ant.txt
Normal file
|
@ -0,0 +1,212 @@
|
|||
This is the license for Ant, the open source build system that Jasmin uses.
|
||||
This license applies only to ./lib/ant.jar
|
||||
You can learn more about Ant and download the files from http://jakarta.apache.org/ant/
|
||||
|
||||
- Jon Meyer
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Apache License
|
||||
* Version 2.0, January 2004
|
||||
* http://www.apache.org/licenses/
|
||||
*
|
||||
* TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
*
|
||||
* 1. Definitions.
|
||||
*
|
||||
* "License" shall mean the terms and conditions for use, reproduction,
|
||||
* and distribution as defined by Sections 1 through 9 of this document.
|
||||
*
|
||||
* "Licensor" shall mean the copyright owner or entity authorized by
|
||||
* the copyright owner that is granting the License.
|
||||
*
|
||||
* "Legal Entity" shall mean the union of the acting entity and all
|
||||
* other entities that control, are controlled by, or are under common
|
||||
* control with that entity. For the purposes of this definition,
|
||||
* "control" means (i) the power, direct or indirect, to cause the
|
||||
* direction or management of such entity, whether by contract or
|
||||
* otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
* outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
*
|
||||
* "You" (or "Your") shall mean an individual or Legal Entity
|
||||
* exercising permissions granted by this License.
|
||||
*
|
||||
* "Source" form shall mean the preferred form for making modifications,
|
||||
* including but not limited to software source code, documentation
|
||||
* source, and configuration files.
|
||||
*
|
||||
* "Object" form shall mean any form resulting from mechanical
|
||||
* transformation or translation of a Source form, including but
|
||||
* not limited to compiled object code, generated documentation,
|
||||
* and conversions to other media types.
|
||||
*
|
||||
* "Work" shall mean the work of authorship, whether in Source or
|
||||
* Object form, made available under the License, as indicated by a
|
||||
* copyright notice that is included in or attached to the work
|
||||
* (an example is provided in the Appendix below).
|
||||
*
|
||||
* "Derivative Works" shall mean any work, whether in Source or Object
|
||||
* form, that is based on (or derived from) the Work and for which the
|
||||
* editorial revisions, annotations, elaborations, or other modifications
|
||||
* represent, as a whole, an original work of authorship. For the purposes
|
||||
* of this License, Derivative Works shall not include works that remain
|
||||
* separable from, or merely link (or bind by name) to the interfaces of,
|
||||
* the Work and Derivative Works thereof.
|
||||
*
|
||||
* "Contribution" shall mean any work of authorship, including
|
||||
* the original version of the Work and any modifications or additions
|
||||
* to that Work or Derivative Works thereof, that is intentionally
|
||||
* submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
* or by an individual or Legal Entity authorized to submit on behalf of
|
||||
* the copyright owner. For the purposes of this definition, "submitted"
|
||||
* means any form of electronic, verbal, or written communication sent
|
||||
* to the Licensor or its representatives, including but not limited to
|
||||
* communication on electronic mailing lists, source code control systems,
|
||||
* and issue tracking systems that are managed by, or on behalf of, the
|
||||
* Licensor for the purpose of discussing and improving the Work, but
|
||||
* excluding communication that is conspicuously marked or otherwise
|
||||
* designated in writing by the copyright owner as "Not a Contribution."
|
||||
*
|
||||
* "Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
* on behalf of whom a Contribution has been received by Licensor and
|
||||
* subsequently incorporated within the Work.
|
||||
*
|
||||
* 2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
* this License, each Contributor hereby grants to You a perpetual,
|
||||
* worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
* copyright license to reproduce, prepare Derivative Works of,
|
||||
* publicly display, publicly perform, sublicense, and distribute the
|
||||
* Work and such Derivative Works in Source or Object form.
|
||||
*
|
||||
* 3. Grant of Patent License. Subject to the terms and conditions of
|
||||
* this License, each Contributor hereby grants to You a perpetual,
|
||||
* worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
* (except as stated in this section) patent license to make, have made,
|
||||
* use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
* where such license applies only to those patent claims licensable
|
||||
* by such Contributor that are necessarily infringed by their
|
||||
* Contribution(s) alone or by combination of their Contribution(s)
|
||||
* with the Work to which such Contribution(s) was submitted. If You
|
||||
* institute patent litigation against any entity (including a
|
||||
* cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
* or a Contribution incorporated within the Work constitutes direct
|
||||
* or contributory patent infringement, then any patent licenses
|
||||
* granted to You under this License for that Work shall terminate
|
||||
* as of the date such litigation is filed.
|
||||
*
|
||||
* 4. Redistribution. You may reproduce and distribute copies of the
|
||||
* Work or Derivative Works thereof in any medium, with or without
|
||||
* modifications, and in Source or Object form, provided that You
|
||||
* meet the following conditions:
|
||||
*
|
||||
* (a) You must give any other recipients of the Work or
|
||||
* Derivative Works a copy of this License; and
|
||||
*
|
||||
* (b) You must cause any modified files to carry prominent notices
|
||||
* stating that You changed the files; and
|
||||
*
|
||||
* (c) You must retain, in the Source form of any Derivative Works
|
||||
* that You distribute, all copyright, patent, trademark, and
|
||||
* attribution notices from the Source form of the Work,
|
||||
* excluding those notices that do not pertain to any part of
|
||||
* the Derivative Works; and
|
||||
*
|
||||
* (d) If the Work includes a "NOTICE" text file as part of its
|
||||
* distribution, then any Derivative Works that You distribute must
|
||||
* include a readable copy of the attribution notices contained
|
||||
* within such NOTICE file, excluding those notices that do not
|
||||
* pertain to any part of the Derivative Works, in at least one
|
||||
* of the following places: within a NOTICE text file distributed
|
||||
* as part of the Derivative Works; within the Source form or
|
||||
* documentation, if provided along with the Derivative Works; or,
|
||||
* within a display generated by the Derivative Works, if and
|
||||
* wherever such third-party notices normally appear. The contents
|
||||
* of the NOTICE file are for informational purposes only and
|
||||
* do not modify the License. You may add Your own attribution
|
||||
* notices within Derivative Works that You distribute, alongside
|
||||
* or as an addendum to the NOTICE text from the Work, provided
|
||||
* that such additional attribution notices cannot be construed
|
||||
* as modifying the License.
|
||||
*
|
||||
* You may add Your own copyright statement to Your modifications and
|
||||
* may provide additional or different license terms and conditions
|
||||
* for use, reproduction, or distribution of Your modifications, or
|
||||
* for any such Derivative Works as a whole, provided Your use,
|
||||
* reproduction, and distribution of the Work otherwise complies with
|
||||
* the conditions stated in this License.
|
||||
*
|
||||
* 5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
* any Contribution intentionally submitted for inclusion in the Work
|
||||
* by You to the Licensor shall be under the terms and conditions of
|
||||
* this License, without any additional terms or conditions.
|
||||
* Notwithstanding the above, nothing herein shall supersede or modify
|
||||
* the terms of any separate license agreement you may have executed
|
||||
* with Licensor regarding such Contributions.
|
||||
*
|
||||
* 6. Trademarks. This License does not grant permission to use the trade
|
||||
* names, trademarks, service marks, or product names of the Licensor,
|
||||
* except as required for reasonable and customary use in describing the
|
||||
* origin of the Work and reproducing the content of the NOTICE file.
|
||||
*
|
||||
* 7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
* agreed to in writing, Licensor provides the Work (and each
|
||||
* Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied, including, without limitation, any warranties or conditions
|
||||
* of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
* appropriateness of using or redistributing the Work and assume any
|
||||
* risks associated with Your exercise of permissions under this License.
|
||||
*
|
||||
* 8. Limitation of Liability. In no event and under no legal theory,
|
||||
* whether in tort (including negligence), contract, or otherwise,
|
||||
* unless required by applicable law (such as deliberate and grossly
|
||||
* negligent acts) or agreed to in writing, shall any Contributor be
|
||||
* liable to You for damages, including any direct, indirect, special,
|
||||
* incidental, or consequential damages of any character arising as a
|
||||
* result of this License or out of the use or inability to use the
|
||||
* Work (including but not limited to damages for loss of goodwill,
|
||||
* work stoppage, computer failure or malfunction, or any and all
|
||||
* other commercial damages or losses), even if such Contributor
|
||||
* has been advised of the possibility of such damages.
|
||||
*
|
||||
* 9. Accepting Warranty or Additional Liability. While redistributing
|
||||
* the Work or Derivative Works thereof, You may choose to offer,
|
||||
* and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
* or other liability obligations and/or rights consistent with this
|
||||
* License. However, in accepting such obligations, You may act only
|
||||
* on Your own behalf and on Your sole responsibility, not on behalf
|
||||
* of any other Contributor, and only if You agree to indemnify,
|
||||
* defend, and hold each Contributor harmless for any liability
|
||||
* incurred by, or claims asserted against, such Contributor by reason
|
||||
* of your accepting any such warranty or additional liability.
|
||||
*
|
||||
* END OF TERMS AND CONDITIONS
|
||||
*
|
||||
* APPENDIX: How to apply the Apache License to your work.
|
||||
*
|
||||
* To apply the Apache License to your work, attach the following
|
||||
* boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
* replaced with your own identifying information. (Don't include
|
||||
* the brackets!) The text should be enclosed in the appropriate
|
||||
* comment syntax for the file format. We also recommend that a
|
||||
* file or class name and description of purpose be included on the
|
||||
* same "printed page" as the copyright notice for easier
|
||||
* identification within third-party archives.
|
||||
*
|
||||
* Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
30
jasmin/jasmin-2.4/license-jasmin.txt
Normal file
30
jasmin/jasmin-2.4/license-jasmin.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 1996-2004, Jon Meyer
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
* and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
||||
* and the following disclaimer in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* Neither the name of the Jon Meyer nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Jasmin was written by Jon Meyer, www.cybergrain.com
|
||||
* The Jasmin website is jasmin.sourceforge.net.
|
||||
*/
|
||||
|
138
jasmin/jasmin-2.4/makefile
Normal file
138
jasmin/jasmin-2.4/makefile
Normal file
|
@ -0,0 +1,138 @@
|
|||
JDK = E:/JDK/BIN/
|
||||
|
||||
SRC = src/Jasmin.java \
|
||||
src/jasmin/ClassFile.java \
|
||||
src/jasmin/InsnInfo.java \
|
||||
src/jasmin/Main.java \
|
||||
src/jasmin/num_token.java \
|
||||
src/jasmin/parser.java \
|
||||
src/jasmin/relative_num_token.java \
|
||||
src/jasmin/ReservedWords.java \
|
||||
src/jasmin/Scanner.java \
|
||||
src/jasmin/ScannerUtils.java \
|
||||
src/jasmin/sym.java \
|
||||
src/jasmin/var_token.java \
|
||||
src/jas/Annotation.java \
|
||||
src/jas/AnnotationAttr.java \
|
||||
src/jas/AnnotationElement.java \
|
||||
src/jas/AnnotDefAttr.java \
|
||||
src/jas/AnnotParamAttr.java \
|
||||
src/jas/AsciiCP.java \
|
||||
src/jas/CatchEntry.java \
|
||||
src/jas/Catchtable.java \
|
||||
src/jas/ClassCP.java \
|
||||
src/jas/ClassEnv.java \
|
||||
src/jas/CodeAttr.java \
|
||||
src/jas/ConstAttr.java \
|
||||
src/jas/CP.java \
|
||||
src/jas/DeprecatedAttr.java \
|
||||
src/jas/DoubleCP.java \
|
||||
src/jas/EnclosingMethodAttr.java \
|
||||
src/jas/ExceptAttr.java \
|
||||
src/jas/FieldCP.java \
|
||||
src/jas/FloatCP.java \
|
||||
src/jas/GenericAttr.java \
|
||||
src/jas/IincInsn.java \
|
||||
src/jas/InnerClass.java \
|
||||
src/jas/InnerClassesAttr.java \
|
||||
src/jas/Insn.java \
|
||||
src/jas/InsnOperand.java \
|
||||
src/jas/IntegerCP.java \
|
||||
src/jas/InterfaceCP.java \
|
||||
src/jas/InvokeinterfaceInsn.java \
|
||||
src/jas/jasError.java \
|
||||
src/jas/Label.java \
|
||||
src/jas/LabelOrOffset.java \
|
||||
src/jas/LineTableAttr.java \
|
||||
src/jas/LocalVarEntry.java \
|
||||
src/jas/LocalVarTableAttr.java \
|
||||
src/jas/LocalVarTypeTableAttr.java \
|
||||
src/jas/LongCP.java \
|
||||
src/jas/LookupswitchInsn.java \
|
||||
src/jas/Method.java \
|
||||
src/jas/MethodCP.java \
|
||||
src/jas/MultiarrayInsn.java \
|
||||
src/jas/NameTypeCP.java \
|
||||
src/jas/RuntimeConstants.java \
|
||||
src/jas/SignatureAttr.java \
|
||||
src/jas/SourceAttr.java \
|
||||
src/jas/SourceDebugExtensionAttr.java \
|
||||
src/jas/StackMap.java \
|
||||
src/jas/StringCP.java \
|
||||
src/jas/TableswitchInsn.java \
|
||||
src/jas/Var.java \
|
||||
src/jas/VerificationTypeInfo.java \
|
||||
src/jas/VerifyFrame.java \
|
||||
src/java_cup/runtime/char_token.java \
|
||||
src/java_cup/runtime/double_token.java \
|
||||
src/java_cup/runtime/float_token.java \
|
||||
src/java_cup/runtime/int_token.java \
|
||||
src/java_cup/runtime/long_token.java \
|
||||
src/java_cup/runtime/lr_parser.java \
|
||||
src/java_cup/runtime/str_token.java \
|
||||
src/java_cup/runtime/symbol.java \
|
||||
src/java_cup/runtime/token.java \
|
||||
src/java_cup/runtime/virtual_parse_stack.java \
|
||||
src/jasmin.mf
|
||||
|
||||
CUP = src/java_cup/Main.java \
|
||||
src/java_cup/action_part.java \
|
||||
src/java_cup/action_production.java \
|
||||
src/java_cup/emit.java \
|
||||
src/java_cup/internal_error.java \
|
||||
src/java_cup/lalr_item.java \
|
||||
src/java_cup/lalr_item_set.java \
|
||||
src/java_cup/lalr_state.java \
|
||||
src/java_cup/lalr_transition.java \
|
||||
src/java_cup/lexer.java \
|
||||
src/java_cup/lr_item_core.java \
|
||||
src/java_cup/non_terminal.java \
|
||||
src/java_cup/parse_action.java \
|
||||
src/java_cup/parse_action_row.java \
|
||||
src/java_cup/parse_action_table.java \
|
||||
src/java_cup/parse_reduce_row.java \
|
||||
src/java_cup/parse_reduce_table.java \
|
||||
src/java_cup/parser.cup \
|
||||
src/java_cup/parser.java \
|
||||
src/java_cup/production.java \
|
||||
src/java_cup/production_part.java \
|
||||
src/java_cup/reduce_action.java \
|
||||
src/java_cup/shift_action.java \
|
||||
src/java_cup/sym.java \
|
||||
src/java_cup/symbol.java \
|
||||
src/java_cup/symbol_part.java \
|
||||
src/java_cup/symbol_set.java \
|
||||
src/java_cup/terminal.java \
|
||||
src/java_cup/terminal_set.java \
|
||||
src/java_cup/version.java \
|
||||
src/java_cup/runtime/lr_parser.java \
|
||||
src/java_cup/runtime/str_token.java \
|
||||
src/java_cup/runtime/symbol.java \
|
||||
src/java_cup/runtime/token.java \
|
||||
src/java_cup/runtime/virtual_parse_stack.java \
|
||||
src/java_cup.mf
|
||||
|
||||
##########################################################################
|
||||
|
||||
jasmin.jar : $(SRC)
|
||||
@if not exist out\nul mkdir out
|
||||
@$(JDK)javac -extdirs "" -source 1.2 -target 1.1 -d out -cp src src/Jasmin.java
|
||||
@$(JDK)jar cfm jasmin.jar src/jasmin.mf -C out .
|
||||
|
||||
src/jasmin/parser.java:
|
||||
src/jasmin/sym.java: src/jasmin/parser.cup java_cup.jar
|
||||
@$(JDK)java -jar java_cup.jar -out src/jasmin -nosummary <src/jasmin/parser.cup
|
||||
|
||||
|
||||
######################
|
||||
java_cup.jar : $(CUP)
|
||||
@if not exist out_cup\nul mkdir out_cup
|
||||
@if exist java_cup.jar copy java_cup.jar out_cup >nul
|
||||
@$(JDK)javac -extdirs "" -source 1.2 -target 1.1 -d out_cup -cp src src/java_cup/Main.java
|
||||
@$(JDK)jar cfm java_cup.jar src/java_cup.mf -C out_cup .
|
||||
|
||||
src/java_cup/parser.java:
|
||||
src/java_cup/sym.java: src/java_cup/parser.cup
|
||||
@$(JDK)java -jar java_cup.jar -out src/java_cup -nosummary <src/java_cup/parser.cup
|
||||
|
||||
#########EOF######
|
6
jasmin/jasmin-2.4/src/Jasmin.java
Normal file
6
jasmin/jasmin-2.4/src/Jasmin.java
Normal file
|
@ -0,0 +1,6 @@
|
|||
import jasmin.Main;
|
||||
|
||||
public class Jasmin {
|
||||
public static void main(String args[])
|
||||
{ Main.main(args); }
|
||||
}
|
38
jasmin/jasmin-2.4/src/jas/AnnotDefAttr.java
Normal file
38
jasmin/jasmin-2.4/src/jas/AnnotDefAttr.java
Normal file
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* This attribute can associated with a method, field or class.
|
||||
*
|
||||
* @author $Author: Iouri Kharon $
|
||||
* @version $Revision: 1.0 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class AnnotDefAttr
|
||||
{
|
||||
static final CP attr = new AsciiCP("AnnotationDefault");
|
||||
Annotation ann;
|
||||
|
||||
public AnnotDefAttr()
|
||||
{ ann = new Annotation(); }
|
||||
|
||||
public Annotation get()
|
||||
{ return(ann); }
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
e.addCPItem(attr);
|
||||
ann.resolve(e);
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeShort(e.getCPIndex(attr));
|
||||
out.writeInt(ann.size());
|
||||
ann.write(e, out);
|
||||
}
|
||||
}
|
72
jasmin/jasmin-2.4/src/jas/AnnotParamAttr.java
Normal file
72
jasmin/jasmin-2.4/src/jas/AnnotParamAttr.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* This attribute can associated with a method, field or class.
|
||||
*
|
||||
* @author $Author: Iouri Kharon $
|
||||
* @version $Revision: 1.0 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class AnnotParamAttr
|
||||
{
|
||||
CP attr;
|
||||
Vector anns; // Vector<Vector<Annotation>>
|
||||
|
||||
public AnnotParamAttr(boolean visible)
|
||||
{
|
||||
attr = new AsciiCP(visible ? "RuntimeVisibleParameterAnnotations" :
|
||||
"RuntimeInvisibleParameterAnnotations");
|
||||
anns = new Vector();
|
||||
}
|
||||
|
||||
public void add(Annotation annotation, int paramnum)
|
||||
{
|
||||
Vector ap = null;
|
||||
int top = anns.size();
|
||||
if(paramnum < top) ap = (Vector)anns.elementAt(paramnum);
|
||||
if(ap == null) {
|
||||
if(paramnum >= top) anns.setSize(paramnum+1);
|
||||
anns.set(paramnum, ap = new Vector());
|
||||
}
|
||||
ap.add(annotation);
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
e.addCPItem(attr);
|
||||
for(int i = 0, top = anns.size(); i < top; i++) {
|
||||
Vector ap = (Vector)anns.elementAt(i);
|
||||
if(ap == null) continue;
|
||||
for(Enumeration en = ap.elements(); en.hasMoreElements(); )
|
||||
((Annotation)en.nextElement()).resolve(e);
|
||||
}
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeShort(e.getCPIndex(attr));
|
||||
int top = anns.size(), len = 1 + 2*top;
|
||||
for(int i = 0; i < top; i++) {
|
||||
Vector ap = (Vector)anns.elementAt(i);
|
||||
if(ap != null)
|
||||
for(Enumeration en = ap.elements(); en.hasMoreElements(); )
|
||||
len += ((Annotation)en.nextElement()).size();
|
||||
}
|
||||
out.writeInt(len);
|
||||
out.writeByte((byte)top);
|
||||
for(int i = 0; i < top; i++) {
|
||||
Vector ap = (Vector)anns.elementAt(i);
|
||||
if(ap == null) out.writeShort(0);
|
||||
else {
|
||||
out.writeShort((short)ap.size());
|
||||
for(Enumeration en = ap.elements(); en.hasMoreElements(); )
|
||||
((Annotation)en.nextElement()).write(e, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
113
jasmin/jasmin-2.4/src/jas/Annotation.java
Normal file
113
jasmin/jasmin-2.4/src/jas/Annotation.java
Normal file
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* @author $Author: Iouri Kharon $
|
||||
* @version $Revision: 1.0 $
|
||||
*/
|
||||
|
||||
|
||||
package jas;
|
||||
// one class to ring them all...
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/*
|
||||
void addAnnotation() // default
|
||||
void addAnnotation(boolean visible, String clname)
|
||||
void addAnnotation(boolean visible, String clname, int paramnum)
|
||||
*/
|
||||
|
||||
public class Annotation extends CP
|
||||
{
|
||||
private Vector fields;
|
||||
private AsciiCP type;
|
||||
private Annotation parent;
|
||||
private AnnotationElement field;
|
||||
private boolean is_default;
|
||||
|
||||
public static final void ParserError() throws jasError
|
||||
{ throw new jasError("internal logic error in annotation parsing"); }
|
||||
|
||||
private Annotation(Annotation parent, AsciiCP type)
|
||||
{
|
||||
this.type = type;
|
||||
this.parent = parent;
|
||||
field = null;
|
||||
fields = new Vector();
|
||||
}
|
||||
|
||||
public Annotation(String type)
|
||||
{ this(null, new AsciiCP(type)); }
|
||||
|
||||
public Annotation() // fictive for AnnotationDefault
|
||||
{ this(null, null); }
|
||||
|
||||
public Annotation nestAnnotation() throws jasError
|
||||
{
|
||||
if(field == null) ParserError();
|
||||
Annotation tmp = new Annotation(this, field.nestType());
|
||||
field.addValue(tmp);
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
public Annotation endAnnotation() throws jasError
|
||||
{
|
||||
if(field != null) {
|
||||
field.done();
|
||||
field = null;
|
||||
}
|
||||
return(parent);
|
||||
}
|
||||
|
||||
public void addField(String name, String type, String add)
|
||||
throws jasError
|
||||
{
|
||||
if(this.type == null && fields.size() != 0) ParserError();
|
||||
if(field != null) {
|
||||
field.done();
|
||||
field = null;
|
||||
}
|
||||
if((name == null) != (this.type == null)) ParserError();
|
||||
field = new AnnotationElement(name, type, add);
|
||||
fields.add(field);
|
||||
}
|
||||
|
||||
public void addValue(Object value) throws jasError
|
||||
{
|
||||
if(field == null) ParserError();
|
||||
field.addValue(value);
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
if(type != null) e.addCPItem(type);
|
||||
for(Enumeration en = fields.elements(); en.hasMoreElements(); )
|
||||
((AnnotationElement)en.nextElement()).resolve(e);
|
||||
}
|
||||
|
||||
int size() throws jasError
|
||||
{
|
||||
if(field != null) ParserError();
|
||||
|
||||
int len = 2 + 2;
|
||||
if(type == null) {
|
||||
if(fields.size() != 1) ParserError();
|
||||
len = 0;
|
||||
}
|
||||
for(Enumeration en = fields.elements(); en.hasMoreElements(); )
|
||||
len += ((AnnotationElement)en.nextElement()).size();
|
||||
return(len);
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out) throws IOException, jasError
|
||||
{
|
||||
if(field != null) ParserError();
|
||||
|
||||
if(type != null) {
|
||||
out.writeShort(e.getCPIndex(type));
|
||||
out.writeShort((short)fields.size());
|
||||
} else if(fields.size() != 1) ParserError();
|
||||
for(Enumeration en = fields.elements(); en.hasMoreElements(); )
|
||||
((AnnotationElement)en.nextElement()).write(e, out);
|
||||
}
|
||||
}
|
48
jasmin/jasmin-2.4/src/jas/AnnotationAttr.java
Normal file
48
jasmin/jasmin-2.4/src/jas/AnnotationAttr.java
Normal file
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* This attribute can associated with a method, field or class.
|
||||
*
|
||||
* @author $Author: Iouri Kharon $
|
||||
* @version $Revision: 1.0 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class AnnotationAttr
|
||||
{
|
||||
CP attr;
|
||||
Vector anns;
|
||||
|
||||
public AnnotationAttr(boolean visible)
|
||||
{
|
||||
attr = new AsciiCP(visible ? "RuntimeVisibleAnnotations" :
|
||||
"RuntimeInvisibleAnnotations");
|
||||
anns = new Vector();
|
||||
}
|
||||
|
||||
public void add(Annotation annotation)
|
||||
{ anns.add(annotation); }
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
e.addCPItem(attr);
|
||||
for(Enumeration en = anns.elements(); en.hasMoreElements(); )
|
||||
((Annotation)en.nextElement()).resolve(e);
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeShort(e.getCPIndex(attr));
|
||||
int len = 2;
|
||||
for(Enumeration en = anns.elements(); en.hasMoreElements(); )
|
||||
len += ((Annotation)en.nextElement()).size();
|
||||
out.writeInt(len);
|
||||
out.writeShort((short)anns.size());
|
||||
for(Enumeration en = anns.elements(); en.hasMoreElements(); )
|
||||
((Annotation)en.nextElement()).write(e, out);
|
||||
}
|
||||
}
|
234
jasmin/jasmin-2.4/src/jas/AnnotationElement.java
Normal file
234
jasmin/jasmin-2.4/src/jas/AnnotationElement.java
Normal file
|
@ -0,0 +1,234 @@
|
|||
/**
|
||||
* AnnotationElement are used by Annotation attributes
|
||||
* @author $Author: Iouri Kharon $
|
||||
* @version $Revision: 1.0 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class AnnotationElement
|
||||
{
|
||||
private boolean array;
|
||||
private char sign;
|
||||
private CP name, exttype;
|
||||
private Vector values;
|
||||
|
||||
private static final char type_int = 'I'; // integer
|
||||
private static final char type_byte = 'B'; // signed byte
|
||||
private static final char type_char = 'C'; // unicode character
|
||||
private static final char type_short = 'S'; // signed short
|
||||
private static final char type_bool = 'Z'; // boolean true or false
|
||||
// end of int types
|
||||
private static final char type_float = 'F'; // single precision IEEE foat
|
||||
private static final char type_double = 'D'; // double precision IEEE float
|
||||
private static final char type_long = 'J'; // long integer
|
||||
//prefix
|
||||
private static final char type_array = '[';
|
||||
//annotation special
|
||||
private static final char type_string = 's'; // constant string
|
||||
private static final char type_class = 'c'; // return type descriptor
|
||||
//complex types
|
||||
private static final char type_enum = 'e'; // enum constant (type + name)
|
||||
private static final char type_annot = '@'; // nested annotation
|
||||
|
||||
private static void badsignature() throws jasError
|
||||
{ throw new jasError("invalid type signature for annotation field"); }
|
||||
|
||||
public AnnotationElement(String name, String type, String exttype)
|
||||
throws jasError
|
||||
{
|
||||
this.name = null;
|
||||
if(name != null) this.name = new AsciiCP(name);
|
||||
values = new Vector();
|
||||
|
||||
array = false;
|
||||
sign = type.charAt(0);
|
||||
if(sign != type_array) {
|
||||
if(type.length() != 1) badsignature();
|
||||
} else {
|
||||
array = true;
|
||||
if(type.length() != 2) badsignature();
|
||||
sign = type.charAt(1);
|
||||
}
|
||||
|
||||
switch(sign) {
|
||||
default:
|
||||
badsignature();
|
||||
|
||||
case type_enum:
|
||||
case type_annot:
|
||||
if(exttype == null) badsignature();
|
||||
this.exttype = new AsciiCP(exttype);
|
||||
break;
|
||||
|
||||
case type_int:
|
||||
case type_byte:
|
||||
case type_char:
|
||||
case type_short:
|
||||
case type_bool:
|
||||
case type_float:
|
||||
case type_double:
|
||||
case type_long:
|
||||
case type_string:
|
||||
case type_class:
|
||||
if(exttype != null) badsignature();
|
||||
this.exttype = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void addValue(Object value) throws jasError
|
||||
{
|
||||
if(value == null) Annotation.ParserError();
|
||||
|
||||
if(!array && values.size() != 0)
|
||||
throw new jasError("too many values for nonarray annotation field type");
|
||||
|
||||
CP cp = null;
|
||||
switch(sign) {
|
||||
case type_char:
|
||||
case type_bool:
|
||||
case type_byte:
|
||||
case type_short:
|
||||
case type_int:
|
||||
if(value instanceof Integer) {
|
||||
int val = ((Integer)value).intValue();
|
||||
boolean badval = false;
|
||||
switch(sign) {
|
||||
case type_bool:
|
||||
if(val < 0 || val > 1) badval = true;
|
||||
break;
|
||||
case type_char:
|
||||
if(val < 0 || val > 0xFFFF) badval = true;
|
||||
break;
|
||||
case type_byte:
|
||||
if(val < -128 || val > 127) badval = true;
|
||||
case type_short:
|
||||
if(val < -32768 || val > 32767) badval = true;
|
||||
default: // type_int
|
||||
break;
|
||||
}
|
||||
if(badval)
|
||||
throw new jasError("annotation field value exceed range of type", true);
|
||||
cp = new IntegerCP(val);
|
||||
}
|
||||
break;
|
||||
case type_float:
|
||||
if(value instanceof Float)
|
||||
cp = new FloatCP(((Float)value).floatValue());
|
||||
break;
|
||||
case type_double:
|
||||
if(value instanceof Double) {
|
||||
cp = new DoubleCP(((Double)value).doubleValue());
|
||||
} else if(value instanceof Float) {
|
||||
cp = new DoubleCP(((Float)value).floatValue());
|
||||
}
|
||||
break;
|
||||
case type_long:
|
||||
if(value instanceof Long) {
|
||||
cp = new LongCP(((Long)value).longValue());
|
||||
} else if(value instanceof Integer) {
|
||||
cp = new LongCP(((Integer)value).intValue());
|
||||
}
|
||||
break;
|
||||
case type_string:
|
||||
case type_class:
|
||||
case type_enum:
|
||||
if(value instanceof String)
|
||||
cp = new AsciiCP((String)value);
|
||||
break;
|
||||
case type_annot:
|
||||
if(value instanceof Annotation)
|
||||
cp = (Annotation)value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(cp == null)
|
||||
throw new jasError("incompatible value for annotation field type");
|
||||
|
||||
values.add(cp);
|
||||
}
|
||||
|
||||
public AsciiCP nestType() throws jasError
|
||||
{
|
||||
if(sign != type_annot) Annotation.ParserError();
|
||||
return((AsciiCP)exttype);
|
||||
}
|
||||
|
||||
public void done() throws jasError
|
||||
{
|
||||
switch(values.size()) {
|
||||
case 1:
|
||||
return;
|
||||
default:
|
||||
if(array) return;
|
||||
//pass thru
|
||||
case 0:
|
||||
Annotation.ParserError();
|
||||
}
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
if(name != null) e.addCPItem(name);
|
||||
if(sign == type_enum) e.addCPItem(exttype);
|
||||
for(Enumeration en = values.elements(); en.hasMoreElements(); ) {
|
||||
CP cp = ((CP)en.nextElement());
|
||||
if(sign != type_annot) e.addCPItem(cp);
|
||||
else cp.resolve(e);
|
||||
}
|
||||
}
|
||||
|
||||
int size() throws jasError
|
||||
{
|
||||
done();
|
||||
|
||||
int len;
|
||||
if(sign == type_annot) {
|
||||
len = values.size(); // tags
|
||||
for(Enumeration en = values.elements(); en.hasMoreElements(); )
|
||||
len += ((Annotation)en.nextElement()).size();
|
||||
} else {
|
||||
len = 1+2;
|
||||
if(sign == type_enum) len += 2;
|
||||
len *= values.size();
|
||||
}
|
||||
if(array) len += 1+2;
|
||||
if(name != null) len += 2;
|
||||
return(len);
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out) throws IOException, jasError
|
||||
{
|
||||
done();
|
||||
|
||||
if(name != null) out.writeShort(e.getCPIndex(name));
|
||||
if(array) {
|
||||
out.writeByte(type_array);
|
||||
out.writeShort((short)values.size());
|
||||
}
|
||||
short id = 0;
|
||||
if(sign == type_enum) id = e.getCPIndex(exttype);
|
||||
for(Enumeration en = values.elements(); en.hasMoreElements(); ) {
|
||||
out.writeByte(sign);
|
||||
CP cp = ((CP)en.nextElement());
|
||||
switch(sign) {
|
||||
case type_annot:
|
||||
((Annotation)cp).write(e, out);
|
||||
break;
|
||||
case type_enum:
|
||||
out.writeShort(id);
|
||||
//pass thru
|
||||
default:
|
||||
out.writeShort(e.getCPIndex(cp));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
30
jasmin/jasmin-2.4/src/jas/AsciiCP.java
Normal file
30
jasmin/jasmin-2.4/src/jas/AsciiCP.java
Normal file
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* This is a class to create Ascii CP entries.
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
public class AsciiCP extends CP implements RuntimeConstants
|
||||
{
|
||||
/**
|
||||
* @param s Name of the ascii constant pool entry
|
||||
*/
|
||||
public AsciiCP(String s)
|
||||
{ uniq = s.intern(); }
|
||||
void resolve(ClassEnv e)
|
||||
{ return; }
|
||||
|
||||
public String toString() { return "AsciiCP: " + uniq; }
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeByte(CONSTANT_UTF8);
|
||||
out.writeUTF(uniq);
|
||||
}
|
||||
}
|
37
jasmin/jasmin-2.4/src/jas/CP.java
Normal file
37
jasmin/jasmin-2.4/src/jas/CP.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* this is an abstraction to contain all the CPE items
|
||||
* that can be created.
|
||||
*
|
||||
* @see AsciiCP
|
||||
* @see ClassCP
|
||||
* @see NameTypeCP
|
||||
* @see FieldCP
|
||||
* @see InterfaceCP
|
||||
* @see MethodCP
|
||||
* @see IntegerCP
|
||||
* @see LongCP
|
||||
* @see FloatCP
|
||||
* @see DoubleCP
|
||||
* @see StringCP
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
|
||||
package jas;
|
||||
// one class to ring them all...
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public abstract class CP
|
||||
{
|
||||
String uniq;
|
||||
|
||||
String getUniq() { return uniq; }
|
||||
|
||||
abstract void resolve(ClassEnv e);
|
||||
|
||||
abstract void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError;
|
||||
}
|
80
jasmin/jasmin-2.4/src/jas/CatchEntry.java
Normal file
80
jasmin/jasmin-2.4/src/jas/CatchEntry.java
Normal file
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* This class
|
||||
* is used to build up entries in a catch table.
|
||||
* @see Catchtable
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class CatchEntry
|
||||
{
|
||||
Label start_pc, end_pc, handler_pc;
|
||||
int start_off, end_off, handler_off;
|
||||
CP catch_cpe;
|
||||
/**
|
||||
* Catch entries are created and then added to the Catchtable.
|
||||
* @param start Label marking the beginning of the area
|
||||
* where the catch table is active.
|
||||
* @param end Label marking the end of the area where the
|
||||
* table is active.
|
||||
* @param handler Label marking the entrypoint into the
|
||||
* exception handling routine.
|
||||
* @param cat (usually a classCP) informing the VM to direct
|
||||
* any exceptions of this (or its subclasses) to the handler.
|
||||
* @see Catchtable
|
||||
*/
|
||||
public
|
||||
CatchEntry(Label start, Label end, Label handler, CP cat)
|
||||
{
|
||||
start_pc = start;
|
||||
end_pc = end;
|
||||
handler_pc = handler;
|
||||
catch_cpe = cat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Catch entries are created and then added to the Catchtable.
|
||||
* @param start offset marking the beginning of the area
|
||||
* where the catch table is active.
|
||||
* @param end offset marking the end of the area where the
|
||||
* table is active.
|
||||
* @param handler offset marking the entrypoint into the
|
||||
* exception handling routine.
|
||||
* @param cat (usually a classCP) informing the VM to direct
|
||||
* any exceptions of this (or its subclasses) to the handler.
|
||||
* @see Catchtable
|
||||
*/
|
||||
public
|
||||
CatchEntry(int start, int end, int handler, CP cat)
|
||||
{
|
||||
start_off = start;
|
||||
end_off = end;
|
||||
handler_off = handler;
|
||||
catch_cpe = cat;
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{ if (catch_cpe != null) e.addCPItem(catch_cpe); }
|
||||
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
if(start_pc!=null && end_pc != null && handler_pc != null) {
|
||||
start_pc.writeOffset(ce, null, out);
|
||||
end_pc.writeOffset(ce, null, out);
|
||||
handler_pc.writeOffset(ce, null, out);
|
||||
} else {
|
||||
out.writeShort(start_off);
|
||||
out.writeShort(end_off);
|
||||
out.writeShort(handler_off);
|
||||
}
|
||||
if (catch_cpe != null)
|
||||
{ out.writeShort(e.getCPIndex(catch_cpe)); }
|
||||
else
|
||||
{ out.writeShort(0); }
|
||||
}
|
||||
}
|
65
jasmin/jasmin-2.4/src/jas/Catchtable.java
Normal file
65
jasmin/jasmin-2.4/src/jas/Catchtable.java
Normal file
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* This is used to make a table of catch handlers for a method.
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Catchtable
|
||||
{
|
||||
Vector entries;
|
||||
|
||||
public Catchtable() { entries = new Vector(); }
|
||||
|
||||
/**
|
||||
* add an entry to the catch table
|
||||
*/
|
||||
|
||||
public void addEntry(CatchEntry entry) { entries.addElement(entry); }
|
||||
|
||||
/**
|
||||
* add an entry to the catch table
|
||||
* @param start Label marking the beginning of the area
|
||||
* where the catch table is active.
|
||||
* @param end Label marking the end of the area where the
|
||||
* table is active.
|
||||
* @param handler Label marking the entrypoint into the
|
||||
* exception handling routine.
|
||||
* @param cat (usually a classCP) informing the VM to direct
|
||||
* any exceptions of this (or its subclasses) to the handler.
|
||||
*/
|
||||
|
||||
public void
|
||||
addEntry(Label start, Label end, Label handler, CP cat)
|
||||
{ addEntry(new CatchEntry(start, end, handler, cat)); }
|
||||
|
||||
public void
|
||||
addEntry(int start, int end, int handler, CP cat)
|
||||
{ addEntry(new CatchEntry(start, end, handler, cat)); }
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
for (Enumeration en=entries.elements(); en.hasMoreElements(); )
|
||||
{
|
||||
CatchEntry ce = (CatchEntry)(en.nextElement());
|
||||
ce.resolve(e);
|
||||
}
|
||||
}
|
||||
|
||||
int size()
|
||||
{ return (8*entries.size()); } // each entry is 8 bytes
|
||||
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeShort(entries.size());
|
||||
for (Enumeration en = entries.elements(); en.hasMoreElements();)
|
||||
{
|
||||
CatchEntry entry = (CatchEntry)(en.nextElement());
|
||||
entry.write(e, ce, out);
|
||||
}
|
||||
}
|
||||
}
|
35
jasmin/jasmin-2.4/src/jas/ClassCP.java
Normal file
35
jasmin/jasmin-2.4/src/jas/ClassCP.java
Normal file
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* This is used to create a Class constant pool item
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
public class ClassCP extends CP implements RuntimeConstants
|
||||
{
|
||||
AsciiCP name;
|
||||
|
||||
/**
|
||||
* @param name Name of the class
|
||||
*/
|
||||
public ClassCP(String name)
|
||||
{
|
||||
uniq = ("CLASS: #$%^#$" + name).intern();
|
||||
this.name = new AsciiCP(name);
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{ e.addCPItem(name); }
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeByte(CONSTANT_CLASS);
|
||||
out.writeShort(e.getCPIndex(name));
|
||||
}
|
||||
}
|
371
jasmin/jasmin-2.4/src/jas/ClassEnv.java
Normal file
371
jasmin/jasmin-2.4/src/jas/ClassEnv.java
Normal file
|
@ -0,0 +1,371 @@
|
|||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is the place where all information about the class to
|
||||
* be created resides.
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
public class ClassEnv implements RuntimeConstants
|
||||
{
|
||||
int magic;
|
||||
short version_lo, version_hi;
|
||||
CP this_class, super_class;
|
||||
short class_access;
|
||||
Hashtable cpe, cpe_index;
|
||||
Vector interfaces;
|
||||
Vector vars;
|
||||
Vector methods;
|
||||
SourceAttr source;
|
||||
SignatureAttr signature;
|
||||
SourceDebugExtensionAttr debug;
|
||||
EnclosingMethodAttr enclosing;
|
||||
DeprecatedAttr depr;
|
||||
InnerClassesAttr innerclasses;
|
||||
AnnotationAttr annVis, annInvis;
|
||||
Vector generic;
|
||||
|
||||
public ClassEnv()
|
||||
{
|
||||
// Fill in reasonable defaults
|
||||
magic = JAVA_MAGIC;
|
||||
version_lo = (short) JAVA_MINOR_VERSION;
|
||||
version_hi = (short) JAVA_VERSION;
|
||||
// Initialize bags
|
||||
cpe = new Hashtable();
|
||||
cpe_index = null;
|
||||
interfaces = new Vector();
|
||||
vars = new Vector();
|
||||
methods = new Vector();
|
||||
annVis = annInvis = null;
|
||||
generic = new Vector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define this class to have this name.
|
||||
* @param name CPE representing name for class. (This is usually
|
||||
* a ClassCP)
|
||||
*/
|
||||
public void setClass(CP name)
|
||||
{ this_class = name; addCPItem(name); }
|
||||
/**
|
||||
* Define this class to have this superclass
|
||||
* @param name CPE representing name for class. (This is usually
|
||||
* a ClassCP)
|
||||
*/
|
||||
public void setSuperClass(CP name)
|
||||
{ super_class = name; addCPItem(name); }
|
||||
|
||||
/**
|
||||
* Set the class access for this class. Constants understood
|
||||
* by this are present along with the java Beta distribution.
|
||||
* @param access number representing access permissions for
|
||||
* the entire class.
|
||||
* @see RuntimeConstants
|
||||
*/
|
||||
public void setClassAccess(short access)
|
||||
{ class_access = access; }
|
||||
|
||||
/**
|
||||
* Add this CP to the list of interfaces supposedly implemented by
|
||||
* this class. Note that the CP ought to be a ClassCP to make
|
||||
* sense to the VM.
|
||||
*/
|
||||
|
||||
public void addInterface(CP ifc)
|
||||
{
|
||||
addCPItem(ifc);
|
||||
interfaces.addElement(ifc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add this to the list of interfaces supposedly implemented
|
||||
* by this class. Note that each CP is usually a ClassCP.
|
||||
* @param ilist An array of CP items representing the
|
||||
* interfaces implemented by this class.
|
||||
*/
|
||||
public void addInterface(CP ilist[])
|
||||
{
|
||||
for (int i=0; i<ilist.length; i++)
|
||||
{
|
||||
interfaces.addElement(ilist[i]);
|
||||
addCPItem(ilist[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void addField(Var v)
|
||||
{
|
||||
vars.addElement(v);
|
||||
v.resolve(this);
|
||||
}
|
||||
/**
|
||||
* Write the contents of the class.
|
||||
*
|
||||
* @param out DataOutputStream on which the contents are written.
|
||||
*/
|
||||
public void write(DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
// Headers
|
||||
out.writeInt(magic);
|
||||
out.writeShort(version_lo);
|
||||
out.writeShort(version_hi);
|
||||
|
||||
// cpe items
|
||||
int curidx = 1;
|
||||
// make up indices for entries
|
||||
cpe_index = new Hashtable();
|
||||
for (Enumeration e = cpe.elements(); e.hasMoreElements();)
|
||||
{
|
||||
CP tmp = (CP)(e.nextElement());
|
||||
cpe_index.put(tmp.getUniq(), new Integer(curidx));
|
||||
curidx++;
|
||||
if ((tmp instanceof LongCP) ||
|
||||
(tmp instanceof DoubleCP))
|
||||
curidx++;
|
||||
}
|
||||
out.writeShort((short)curidx);
|
||||
|
||||
// Now write out all the entries
|
||||
for (Enumeration e = cpe.elements(); e.hasMoreElements();)
|
||||
{
|
||||
CP now = (CP) (e.nextElement());
|
||||
now.write(this, out);
|
||||
}
|
||||
|
||||
// Class hierarchy/access
|
||||
out.writeShort(class_access);
|
||||
out.writeShort(getCPIndex(this_class));
|
||||
out.writeShort(getCPIndex(super_class));
|
||||
// interfaces
|
||||
out.writeShort(interfaces.size());
|
||||
for (Enumeration e = interfaces.elements(); e.hasMoreElements();)
|
||||
{
|
||||
CP c = (CP)(e.nextElement());
|
||||
out.writeShort(getCPIndex(c));
|
||||
}
|
||||
// variables
|
||||
out.writeShort(vars.size());
|
||||
for (Enumeration e = vars.elements(); e.hasMoreElements();)
|
||||
{
|
||||
Var v = (Var)(e.nextElement());
|
||||
v.write(this, out);
|
||||
}
|
||||
|
||||
// methods
|
||||
out.writeShort(methods.size());
|
||||
for (Enumeration e = methods.elements(); e.hasMoreElements();)
|
||||
{
|
||||
Method m = (Method)(e.nextElement());
|
||||
m.write(this, out);
|
||||
}
|
||||
// additional attributes
|
||||
short numExtra = 0;
|
||||
if (source != null)
|
||||
{ numExtra++; }
|
||||
if (debug != null)
|
||||
{ numExtra++; }
|
||||
if (enclosing != null)
|
||||
{ numExtra++; }
|
||||
if (signature != null)
|
||||
{ numExtra++; }
|
||||
if (innerclasses != null)
|
||||
{ numExtra++; }
|
||||
if (depr != null)
|
||||
{ numExtra++; }
|
||||
if (annVis != null)
|
||||
{ numExtra++; }
|
||||
if (annInvis != null)
|
||||
{ numExtra++; }
|
||||
numExtra += generic.size();
|
||||
|
||||
out.writeShort(numExtra);
|
||||
if (source != null)
|
||||
{ source.write(this, out); }
|
||||
if (debug != null)
|
||||
{ debug.write(this, out); }
|
||||
if (enclosing != null)
|
||||
{ enclosing.write(this, out); }
|
||||
if (signature != null)
|
||||
{ signature.write(this, out); }
|
||||
if (innerclasses != null)
|
||||
{ innerclasses.write(this, out); }
|
||||
if (depr != null)
|
||||
{ depr.write(this, out); }
|
||||
if (annVis != null)
|
||||
{ annVis.write(this, out); }
|
||||
if (annInvis != null)
|
||||
{ annInvis.write(this, out); }
|
||||
for (Enumeration gen=generic.elements(); gen.hasMoreElements(); )
|
||||
{
|
||||
GenericAttr gattr = (GenericAttr)gen.nextElement();
|
||||
gattr.write(this, out);
|
||||
}
|
||||
out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the method to add CPE items to a class. CPE items for
|
||||
* a class are "uniquefied". Ie, if you add a CPE items whose
|
||||
* contents already exist in the class, only one entry is finally
|
||||
* written out when the class is written.
|
||||
*
|
||||
* @param cp Item to be added to the class
|
||||
*/
|
||||
|
||||
public void addCPItem(CP cp)
|
||||
{
|
||||
String uniq = cp.getUniq();
|
||||
CP intern;
|
||||
|
||||
if ((intern = (CP)(cpe.get(uniq))) == null)
|
||||
{
|
||||
// add it
|
||||
cpe.put(uniq, cp);
|
||||
// resolve it so it adds anything
|
||||
// which it depends on
|
||||
cp.resolve(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an attribute specifying the name of the source file
|
||||
* for the class
|
||||
* @param source SourceAttribute specifying the source for the file
|
||||
*/
|
||||
|
||||
public void setSource(SourceAttr source)
|
||||
{ this.source = source; source.resolve(this); }
|
||||
|
||||
/**
|
||||
* Add an attribute specifying the name of the source file
|
||||
* for the clas.
|
||||
* @param source String with the name of the class
|
||||
*/
|
||||
public void setSource(String source)
|
||||
{ this.source = new SourceAttr(source); this.source.resolve(this); }
|
||||
|
||||
/**
|
||||
* Add an attribute specifying extended debug information
|
||||
* @param debug String the extended debug information
|
||||
*/
|
||||
public void setSourceDebugExtension(String debug)
|
||||
{
|
||||
if ( this.debug != null )
|
||||
this.debug.append(debug);
|
||||
else {
|
||||
this.debug = new SourceDebugExtensionAttr(debug);
|
||||
this.debug.resolve(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an attribute specifying the enclosing method of this class
|
||||
* @param cls String the enclosing class
|
||||
* @param mtd String the enclosing method
|
||||
* @param dsc String the enclosing method descriptor
|
||||
*/
|
||||
public void setEnclosingMethod(String cls, String mtd, String dsc)
|
||||
{ this.enclosing = new EnclosingMethodAttr(cls, mtd, dsc);
|
||||
this.enclosing.resolve(this); }
|
||||
|
||||
|
||||
/**
|
||||
* Add an attribute specifying the signature of this class
|
||||
* @param sig String the signature
|
||||
*/
|
||||
public void setSignature(String sig)
|
||||
{ this.signature = new SignatureAttr(sig);
|
||||
this.signature.resolve(this); }
|
||||
|
||||
|
||||
public void setDeprecated(DeprecatedAttr depr)
|
||||
{ this.depr = depr; depr.resolve(this); }
|
||||
|
||||
/**
|
||||
* Add a generic attribute to the class file. A generic attribute
|
||||
* contains a stream of uninterpreted bytes which is ignored by
|
||||
* the VM (as long as its name doesn't conflict with other names
|
||||
* for attributes that are understood by the VM)
|
||||
*/
|
||||
public void addGenericAttr(GenericAttr g)
|
||||
{ generic.addElement(g); g.resolve(this); }
|
||||
|
||||
public void addInnerClass(short iacc, String name, String inner, String outer)
|
||||
{
|
||||
if(innerclasses == null) {
|
||||
innerclasses = new InnerClassesAttr();
|
||||
innerclasses.resolve(this);
|
||||
}
|
||||
InnerClass ic = new InnerClass(iacc, name, inner, outer);
|
||||
ic.resolve(this);
|
||||
innerclasses.addInnerClass(ic);
|
||||
}
|
||||
|
||||
/*
|
||||
* procedure group for annotation description
|
||||
*/
|
||||
public Annotation addAnnotation(boolean visible, String clsname)
|
||||
{
|
||||
Annotation ann = new Annotation(clsname);
|
||||
AnnotationAttr aa = visible ? annVis : annInvis;
|
||||
if(aa == null) {
|
||||
aa = new AnnotationAttr(visible);
|
||||
if(visible) annVis = aa;
|
||||
else annInvis = aa;
|
||||
}
|
||||
aa.add(ann);
|
||||
return(ann);
|
||||
}
|
||||
|
||||
public void endHeader()
|
||||
{
|
||||
if(annVis != null) annVis.resolve(this);
|
||||
if(annInvis != null) annInvis.resolve(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This allows more control over generating CP's for methods
|
||||
* if you feel so inclined.
|
||||
*/
|
||||
public void addMethod(Method m)
|
||||
{
|
||||
m.resolve(this);
|
||||
methods.addElement(m);
|
||||
}
|
||||
|
||||
short getCPIndex(CP cp)
|
||||
throws jasError
|
||||
{
|
||||
if (cpe_index == null)
|
||||
throw new jasError("Internal error: CPE index has not been generated");
|
||||
|
||||
Integer idx = (Integer)(cpe_index.get(cp.getUniq()));
|
||||
if (idx == null)
|
||||
throw new jasError("Item " + cp + " not in the class");
|
||||
return ((short)(idx.intValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the bytecode version of this class
|
||||
* The version will be version_high.version_low
|
||||
* @param version_high short
|
||||
* @param version_low short
|
||||
*/
|
||||
public void setVersion(short version_high, short version_low)
|
||||
{
|
||||
version_hi = version_high;
|
||||
version_lo = version_low;
|
||||
}
|
||||
}
|
218
jasmin/jasmin-2.4/src/jas/CodeAttr.java
Normal file
218
jasmin/jasmin-2.4/src/jas/CodeAttr.java
Normal file
|
@ -0,0 +1,218 @@
|
|||
/**
|
||||
* CodeAttr's are used as a bag to hold lists of instructions
|
||||
* until it is time to put them into a Class.
|
||||
* @see ClassEnv#addMethod
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class CodeAttr
|
||||
{
|
||||
static final CP attr = new AsciiCP("Code");
|
||||
short stack_size, num_locals;
|
||||
int code_size;
|
||||
Vector insns;
|
||||
Hashtable insn_pc;
|
||||
Catchtable ctb;
|
||||
LineTableAttr ltab;
|
||||
LocalVarTableAttr lvar;
|
||||
LocalVarTypeTableAttr lvtyp;
|
||||
StackMap stackmap;
|
||||
Vector generic;
|
||||
|
||||
/**
|
||||
* Create a new bag. Add instructions with the addInsn() method,
|
||||
* set the catch table with the setCatchTable() method.
|
||||
* @see Insn
|
||||
* @see Catchtable
|
||||
* @see ClassEnv#addMethod
|
||||
*/
|
||||
|
||||
public CodeAttr()
|
||||
{
|
||||
this.stack_size = 1;
|
||||
this.num_locals = 1;
|
||||
this.ctb = null;
|
||||
this.insns = new Vector();
|
||||
generic = new Vector();
|
||||
}
|
||||
/**
|
||||
* Set the catchtable for this code
|
||||
*/
|
||||
public void setCatchtable(Catchtable ctb)
|
||||
{ this.ctb = ctb; }
|
||||
|
||||
/**
|
||||
* Set the line number table for this method
|
||||
*/
|
||||
|
||||
public void setLineTable(LineTableAttr ltab)
|
||||
{ this.ltab = ltab; }
|
||||
|
||||
/**
|
||||
* Set the local variable information for this method
|
||||
*/
|
||||
|
||||
public void setLocalVarTable(LocalVarTableAttr lvar)
|
||||
{ this.lvar = lvar; }
|
||||
|
||||
|
||||
/**
|
||||
* Set the local variable type information for this method
|
||||
*/
|
||||
|
||||
public void setLocalVarTypeTable(LocalVarTypeTableAttr lvtyp)
|
||||
{ this.lvtyp = lvtyp; }
|
||||
|
||||
|
||||
/**
|
||||
* Set the StackMap attribute for this method
|
||||
*/
|
||||
public void setStackMap(StackMap s)
|
||||
{ stackmap = s; }
|
||||
|
||||
/**
|
||||
* Add a generic attribute to the method. A generic attribute
|
||||
* contains a stream of uninterpreted bytes which is ignored by
|
||||
* the VM (as long as its name doesn't conflict with other names
|
||||
* for attributes that are understood by the VM)
|
||||
*/
|
||||
public void addGenericAttr(GenericAttr g)
|
||||
{ generic.addElement(g); }
|
||||
|
||||
|
||||
/**
|
||||
* Append a new Insn to this code. Insn's are sequentially
|
||||
* stored, in the order in which this method is called. You
|
||||
* can't reorder code fragments after you've added it here.
|
||||
*/
|
||||
public void addInsn(Insn insn)
|
||||
{ insns.addElement(insn); }
|
||||
|
||||
public void setStackSize(short stack_size)
|
||||
{ this.stack_size = stack_size; }
|
||||
|
||||
public void setVarSize(short num_vars)
|
||||
{ num_locals = num_vars; }
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
// propagate this resolution to
|
||||
// the insns and catch table, so
|
||||
// that any CP's referenced by them
|
||||
// also get added.
|
||||
e.addCPItem(attr);
|
||||
for (Enumeration en = insns.elements(); en.hasMoreElements();)
|
||||
{
|
||||
Insn i = (Insn)(en.nextElement());
|
||||
i.resolve(e);
|
||||
}
|
||||
if (ctb != null) ctb.resolve(e);
|
||||
if (ltab != null) ltab.resolve(e);
|
||||
if (lvar != null) lvar.resolve(e);
|
||||
if (lvtyp != null) lvtyp.resolve(e);
|
||||
if (stackmap != null) stackmap.resolve(e);
|
||||
for (Enumeration gen = generic.elements(); gen.hasMoreElements();)
|
||||
{
|
||||
GenericAttr gattr = (GenericAttr)gen.nextElement();
|
||||
gattr.resolve(e);
|
||||
}
|
||||
}
|
||||
|
||||
int getPc(Insn i) throws jasError
|
||||
{
|
||||
if (insn_pc == null)
|
||||
throw new jasError("Internal error, insn_pc has not been initialized");
|
||||
Integer tmp;
|
||||
if (i instanceof Label)
|
||||
{
|
||||
tmp = (Integer)(insn_pc.get(((Label)i).id));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = (Integer)(insn_pc.get(i));
|
||||
}
|
||||
if (tmp == null)
|
||||
throw new jasError(i + " has not been added to the code");
|
||||
return tmp.intValue();
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
// First, resolve all labels and
|
||||
// compute total size
|
||||
int code_size = 0;
|
||||
insn_pc = new Hashtable();
|
||||
for (Enumeration en = insns.elements(); en.hasMoreElements();)
|
||||
{
|
||||
Insn now = (Insn)(en.nextElement());
|
||||
if (now instanceof Label)
|
||||
{
|
||||
insn_pc.put(((Label)now).id, new Integer(code_size));
|
||||
}
|
||||
else
|
||||
{ insn_pc.put(now, new Integer(code_size)); }
|
||||
code_size += now.size(e, this);
|
||||
}
|
||||
int total_size = code_size;
|
||||
if (ctb != null) total_size += ctb.size();
|
||||
if (ltab != null) total_size += ltab.size();
|
||||
if (lvar != null) total_size += lvar.size();
|
||||
if (lvtyp != null) total_size += lvtyp.size();
|
||||
if (stackmap != null) total_size += stackmap.size(e, this);
|
||||
for (Enumeration gen = generic.elements(); gen.hasMoreElements();)
|
||||
{
|
||||
GenericAttr gattr = (GenericAttr)(gen.nextElement());
|
||||
total_size += gattr.size();
|
||||
}
|
||||
|
||||
// extra headers
|
||||
total_size += 12;
|
||||
|
||||
|
||||
out.writeShort(e.getCPIndex(attr));
|
||||
out.writeInt(total_size);
|
||||
out.writeShort(stack_size);
|
||||
out.writeShort(num_locals);
|
||||
out.writeInt(code_size);
|
||||
for (Enumeration en = insns.elements(); en.hasMoreElements();)
|
||||
{
|
||||
Insn now = (Insn)(en.nextElement());
|
||||
now.write(e, this, out);
|
||||
}
|
||||
if (ctb != null)
|
||||
{ ctb.write(e, this, out); }
|
||||
else
|
||||
{ out.writeShort(0); }
|
||||
short extra = 0;
|
||||
if (ltab != null) extra++;
|
||||
if (lvar != null) extra++;
|
||||
if (lvtyp != null) extra++;
|
||||
if (stackmap != null) extra++;
|
||||
extra += generic.size();
|
||||
out.writeShort(extra);
|
||||
if (ltab != null)
|
||||
{ ltab.write(e, this, out); }
|
||||
if (lvar != null)
|
||||
{ lvar.write(e, this, out); }
|
||||
if (lvtyp != null)
|
||||
{ lvtyp.write(e, this, out); }
|
||||
if (stackmap != null)
|
||||
{ stackmap.write(e, this, out); }
|
||||
for (Enumeration gen = generic.elements(); gen.hasMoreElements();)
|
||||
{
|
||||
GenericAttr gattr = (GenericAttr)gen.nextElement();
|
||||
gattr.write(e, out);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{ return ("<#code-attr>"); }
|
||||
}
|
43
jasmin/jasmin-2.4/src/jas/ConstAttr.java
Normal file
43
jasmin/jasmin-2.4/src/jas/ConstAttr.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* This is typically used to represent a constant value for
|
||||
* a field entry (as in static final int foo = 20).
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class ConstAttr
|
||||
{
|
||||
static final CP attr = new AsciiCP("ConstantValue");
|
||||
CP val;
|
||||
|
||||
/**
|
||||
* Create a new constant attribute whose constant value
|
||||
* is picked up from constant pool with the given entry.
|
||||
* @param val Constant pool item whose value is associated
|
||||
* with the constant value attribute
|
||||
*/
|
||||
|
||||
public ConstAttr(CP val)
|
||||
{ this.val = val; }
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
e.addCPItem(val);
|
||||
e.addCPItem(attr);
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeShort(e.getCPIndex(attr));
|
||||
out.writeInt(2);
|
||||
out.writeShort(e.getCPIndex(val));
|
||||
}
|
||||
}
|
||||
|
||||
|
32
jasmin/jasmin-2.4/src/jas/DeprecatedAttr.java
Normal file
32
jasmin/jasmin-2.4/src/jas/DeprecatedAttr.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* This attribute is used to mark class/method/field as deprecated.
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class DeprecatedAttr
|
||||
{
|
||||
static final CP attr = new AsciiCP("Deprecated");
|
||||
|
||||
/**
|
||||
* Create a deprecated attribute.
|
||||
* @see ClassEnv#setDeprecated
|
||||
*/
|
||||
|
||||
public DeprecatedAttr() { }
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{ e.addCPItem(attr); }
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeShort(e.getCPIndex(attr));
|
||||
out.writeInt(0);
|
||||
}
|
||||
}
|
||||
|
32
jasmin/jasmin-2.4/src/jas/DoubleCP.java
Normal file
32
jasmin/jasmin-2.4/src/jas/DoubleCP.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
/**
|
||||
* Wrap an Double constant reference with this CPE.
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
public class DoubleCP extends CP implements RuntimeConstants
|
||||
{
|
||||
double val;
|
||||
|
||||
/**
|
||||
* @param n Value for Double constant
|
||||
*/
|
||||
public DoubleCP(double n)
|
||||
{
|
||||
uniq = ("Double: @#$" + n).intern();
|
||||
val = n;
|
||||
}
|
||||
void resolve(ClassEnv e) { return; }
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeByte(CONSTANT_DOUBLE);
|
||||
out.writeDouble(val);
|
||||
}
|
||||
}
|
55
jasmin/jasmin-2.4/src/jas/EnclosingMethodAttr.java
Normal file
55
jasmin/jasmin-2.4/src/jas/EnclosingMethodAttr.java
Normal file
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* This attribute is used to define the enclosing method of this class
|
||||
* @author $Author: Daniel Reynaud $
|
||||
* @version $Revision: 1.0 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class EnclosingMethodAttr
|
||||
{
|
||||
static final CP attr = new AsciiCP("EnclosingMethod");
|
||||
CP clscp,
|
||||
ntcp;
|
||||
|
||||
String cls, mtd, dsc;
|
||||
|
||||
/**
|
||||
* Create an EnclosingMethod attribute
|
||||
* @param cls Name of the enclosing class
|
||||
* @param mtd Name of the enclosing method (can be null)
|
||||
* @param dsc Name of the enclosing method descriptor (can be null)
|
||||
* @see ClassEnv#setEnclosingMethod
|
||||
*/
|
||||
|
||||
public EnclosingMethodAttr(String cls, String mtd, String dsc)
|
||||
{ this.cls = cls;
|
||||
this.mtd = mtd;
|
||||
this.dsc = dsc;
|
||||
clscp = new ClassCP(cls);
|
||||
if(mtd!=null && dsc!=null)
|
||||
ntcp = new NameTypeCP(mtd, dsc);
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{ e.addCPItem(attr);
|
||||
e.addCPItem(clscp); // add the CONSTANT_Class
|
||||
clscp.resolve(e); // add the CONSTANT_Utf8 for the class name
|
||||
if(ntcp!=null) {
|
||||
e.addCPItem(ntcp); // add the CONSTANT_NameAndType
|
||||
ntcp.resolve(e); // add the two CONSTANT_Utf8
|
||||
}
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeShort(e.getCPIndex(attr));
|
||||
out.writeInt(4);
|
||||
out.writeShort(e.getCPIndex(clscp));
|
||||
out.writeShort(ntcp==null ? 0 : e.getCPIndex(ntcp));
|
||||
}
|
||||
}
|
||||
|
45
jasmin/jasmin-2.4/src/jas/ExceptAttr.java
Normal file
45
jasmin/jasmin-2.4/src/jas/ExceptAttr.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* This attribute is associated with a method, and indicates
|
||||
* the set of exceptions (as classCP items) that can be thrown
|
||||
* by the method.
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class ExceptAttr
|
||||
{
|
||||
static final CP attr = new AsciiCP("Exceptions");
|
||||
|
||||
Vector cps;
|
||||
|
||||
public ExceptAttr() { cps = new Vector(); }
|
||||
/**
|
||||
* @param cp Exception class to be added to attribute. This is
|
||||
* typically a ClassCP
|
||||
*/
|
||||
public void addException(CP cp)
|
||||
{ cps.addElement(cp); }
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
e.addCPItem(attr);
|
||||
for (Enumeration en = cps.elements(); en.hasMoreElements();)
|
||||
{ e.addCPItem((CP)(en.nextElement())); }
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeShort(e.getCPIndex(attr));
|
||||
out.writeInt(cps.size()*2 + 2);
|
||||
out.writeShort(cps.size());
|
||||
for (Enumeration en = cps.elements(); en.hasMoreElements();)
|
||||
{ out.writeShort(e.getCPIndex((CP)(en.nextElement()))); }
|
||||
}
|
||||
}
|
51
jasmin/jasmin-2.4/src/jas/FieldCP.java
Normal file
51
jasmin/jasmin-2.4/src/jas/FieldCP.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* FieldCP's are used to refer to a field in a particular
|
||||
* class.
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
public class FieldCP extends CP implements RuntimeConstants
|
||||
{
|
||||
ClassCP clazz;
|
||||
NameTypeCP nt;
|
||||
|
||||
/**
|
||||
* FieldCP's are created by specifying the class to which the
|
||||
* field belongs, the name of the symbol, and its signature.
|
||||
* For instance, to refer to the field <tt>out</tt> in
|
||||
* <tt>System.out</tt> use
|
||||
* <tt> new FieldCP("java/lang/System", "out", "Ljava/io/PrintStream;")</tt>
|
||||
*
|
||||
* @param clazz Name of class
|
||||
* @param name Name of symbol
|
||||
* @param sig Signature for symbol
|
||||
*/
|
||||
|
||||
public FieldCP(String clazz, String name, String sig)
|
||||
{
|
||||
uniq = (clazz + "&%$#&" + name + "*()#$" + sig).intern();
|
||||
this.clazz = new ClassCP(clazz);
|
||||
this.nt = new NameTypeCP(name, sig);
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
e.addCPItem(clazz);
|
||||
e.addCPItem(nt);
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeByte(CONSTANT_FIELD);
|
||||
out.writeShort(e.getCPIndex(clazz));
|
||||
out.writeShort(e.getCPIndex(nt));
|
||||
}
|
||||
}
|
32
jasmin/jasmin-2.4/src/jas/FloatCP.java
Normal file
32
jasmin/jasmin-2.4/src/jas/FloatCP.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
/**
|
||||
* Wrap an Float constant reference with this CPE.
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
public class FloatCP extends CP implements RuntimeConstants
|
||||
{
|
||||
float val;
|
||||
|
||||
/**
|
||||
* @param n Value for Float constant
|
||||
*/
|
||||
public FloatCP(float n)
|
||||
{
|
||||
uniq = ("Float: @#$" + n).intern();
|
||||
val = n;
|
||||
}
|
||||
void resolve(ClassEnv e) { return; }
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeByte(CONSTANT_FLOAT);
|
||||
out.writeFloat(val);
|
||||
}
|
||||
}
|
75
jasmin/jasmin-2.4/src/jas/GenericAttr.java
Normal file
75
jasmin/jasmin-2.4/src/jas/GenericAttr.java
Normal file
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* This is an opaque attribute that lets you add an uninterpreted
|
||||
* stream of bytes into an attribute in a class file. This can be
|
||||
* used (for instance) to embed versioning or signatures into the
|
||||
* class file or method.
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class GenericAttr
|
||||
{
|
||||
CP attr_name;
|
||||
byte data[];
|
||||
|
||||
/**
|
||||
* Make up a new attribute
|
||||
* @param data stream of bytes to be placed with the attribute
|
||||
* @see ClassEnv#addGenericAttr
|
||||
* @see CodeAttr#addGenericAttr
|
||||
*/
|
||||
public GenericAttr(String name, byte data[])
|
||||
{
|
||||
attr_name = new AsciiCP(name);
|
||||
this.data = data;
|
||||
}
|
||||
/**
|
||||
* Make up a new attribute
|
||||
* @param name CP to be defined as the name of the attribute
|
||||
* @param data stream of bytes to be placed with the attribute
|
||||
* @see ClassEnv#addGenericAttr
|
||||
* @see CodeAttr#addGenericAttr
|
||||
*/
|
||||
public GenericAttr(CP name, byte data[])
|
||||
{
|
||||
attr_name = name;
|
||||
this.data = data;
|
||||
}
|
||||
/**
|
||||
* Make up a new attribute
|
||||
* @param name Name to be associated with the attribute
|
||||
* @param file name of file with attribute contens
|
||||
*/
|
||||
public GenericAttr(String name, String file) throws IOException, jasError
|
||||
{
|
||||
FileInputStream inp;
|
||||
try {
|
||||
inp = new FileInputStream(file);
|
||||
} catch(FileNotFoundException e) {
|
||||
throw new jasError("Generic atribute file " +file+ " not found");
|
||||
}
|
||||
data = new byte[inp.available()];
|
||||
inp.read(data);
|
||||
inp.close();
|
||||
attr_name = new AsciiCP(name);
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{ e.addCPItem(attr_name); }
|
||||
|
||||
int size()
|
||||
{ return (2 + 4 + data.length); }
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeShort(e.getCPIndex(attr_name));
|
||||
out.writeInt(data.length);
|
||||
out.write(data);
|
||||
}
|
||||
}
|
||||
|
38
jasmin/jasmin-2.4/src/jas/IincInsn.java
Normal file
38
jasmin/jasmin-2.4/src/jas/IincInsn.java
Normal file
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Some instructions are perniticky enough that its simpler
|
||||
* to write them separately instead of smushing them with
|
||||
* all the rest. the iinc instruction is one of them.
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
public class IincInsn extends Insn implements RuntimeConstants
|
||||
{
|
||||
/**
|
||||
* @param vindex Index of variable to be incremented.
|
||||
* @param increment value to be added to the variable.
|
||||
*
|
||||
* A wide prefix is automatically added if either the
|
||||
* vindex exceeds 256, or the increment value lies
|
||||
* outside the range [-128, 127]
|
||||
*
|
||||
* The VM spec is unclear on how the wide instruction is implemented,
|
||||
* but the implementation makes <em>both</em> the constant and the
|
||||
* variable index 16 bit values for the wide version of this instruction.
|
||||
*/
|
||||
public IincInsn(int vindex, int increment, boolean Wide)
|
||||
{
|
||||
opc = opc_iinc;
|
||||
operand = new IincOperand(vindex, increment, Wide);
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Revision History ---------------------------------------------------
|
||||
--- Iouri Kharon, Aug 10 2006
|
||||
Added 'Wide' prefix support
|
||||
*/
|
60
jasmin/jasmin-2.4/src/jas/InnerClass.java
Normal file
60
jasmin/jasmin-2.4/src/jas/InnerClass.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* @author $Author: Iouri Kharon $
|
||||
* @version $Revision: 1.0 $
|
||||
*/
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class InnerClass
|
||||
{
|
||||
ClassCP inner, outer;
|
||||
CP name;
|
||||
short access;
|
||||
|
||||
public static int size()
|
||||
{ return (4 * 2); }
|
||||
|
||||
/**
|
||||
* Make up a new attribute
|
||||
* @see ClassEnv#addInnerClass
|
||||
*/
|
||||
public InnerClass(short access, String name, String inner, String outer)
|
||||
{
|
||||
this.access = access;
|
||||
this.name = null;
|
||||
if(name != null) this.name = new AsciiCP(name);
|
||||
this.inner = null;
|
||||
if(inner != null) this.inner = new ClassCP(inner);
|
||||
this.outer = null;
|
||||
if(outer != null) this.outer = new ClassCP(outer);
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
if(name != null) e.addCPItem(name);
|
||||
if(inner != null) {
|
||||
e.addCPItem(inner);
|
||||
inner.resolve(e);
|
||||
}
|
||||
if(outer != null) {
|
||||
e.addCPItem(outer);
|
||||
outer.resolve(e);
|
||||
}
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out) throws IOException, jasError
|
||||
{
|
||||
short id = 0;
|
||||
if(inner != null) id = e.getCPIndex(inner);
|
||||
out.writeShort(id);
|
||||
id = 0;
|
||||
if(outer != null) id = e.getCPIndex(outer);
|
||||
out.writeShort(id);
|
||||
id = 0;
|
||||
if(name != null) id = e.getCPIndex(name);
|
||||
out.writeShort(id);
|
||||
out.writeShort(access);
|
||||
}
|
||||
}
|
||||
|
39
jasmin/jasmin-2.4/src/jas/InnerClassesAttr.java
Normal file
39
jasmin/jasmin-2.4/src/jas/InnerClassesAttr.java
Normal file
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* @author $Author: Iouri Kharon $
|
||||
* @version $Revision: 1.0 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class InnerClassesAttr
|
||||
{
|
||||
static final CP attr = new AsciiCP("InnerClasses");
|
||||
private Vector list;
|
||||
|
||||
public InnerClassesAttr()
|
||||
{ list = new Vector(); }
|
||||
|
||||
public void addInnerClass(InnerClass item)
|
||||
{ list.add(item); }
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
e.addCPItem(attr);
|
||||
for(Enumeration en = list.elements(); en.hasMoreElements(); )
|
||||
((InnerClass)en.nextElement()).resolve(e);
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out) throws IOException, jasError
|
||||
{
|
||||
out.writeShort(e.getCPIndex(attr));
|
||||
out.writeInt((list.size() * InnerClass.size()) + 2);
|
||||
out.writeShort((short)list.size());
|
||||
for(Enumeration en = list.elements(); en.hasMoreElements(); )
|
||||
((InnerClass)en.nextElement()).write(e, out);
|
||||
}
|
||||
}
|
||||
|
333
jasmin/jasmin-2.4/src/jas/Insn.java
Normal file
333
jasmin/jasmin-2.4/src/jas/Insn.java
Normal file
|
@ -0,0 +1,333 @@
|
|||
/**
|
||||
* An Insn is a generic instruction that is added to a
|
||||
* CodeAttr to build up the code for a method.
|
||||
* @see CodeAttr
|
||||
* @see RuntimeConstants
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class Insn implements RuntimeConstants
|
||||
{
|
||||
int opc;
|
||||
InsnOperand operand;
|
||||
|
||||
// private constructor, for the
|
||||
// "strange" opcodes
|
||||
Insn() { return; }
|
||||
/**
|
||||
* Instructions with no arguments are built with
|
||||
* this constructor.
|
||||
*/
|
||||
public Insn(int opc)
|
||||
throws jasError
|
||||
{
|
||||
if (opcLengths[opc] == 1)
|
||||
{ operand = null; this.opc = opc; return; }
|
||||
throw new jasError
|
||||
(opcNames[opc] + " cannot be used without more parameters");
|
||||
}
|
||||
|
||||
private void check_short(int val, int opc) throws jasError
|
||||
{
|
||||
if (val > 32767 || val < -32768)
|
||||
throw new jasError
|
||||
(opcNames[opc] + " numeric value exceed size for short");
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructions that take a single numeric argument. These are
|
||||
* opc_bipush,
|
||||
* opc_sipush,
|
||||
* opc_ret,
|
||||
* opc_iload,
|
||||
* opc_lload,
|
||||
* opc_fload,
|
||||
* opc_dload,
|
||||
* opc_aload,
|
||||
* opc_istore,
|
||||
* opc_lstore,
|
||||
* opc_fstore,
|
||||
* opc_dstore,
|
||||
* opc_astore,
|
||||
* opc_newarray
|
||||
*
|
||||
* Note that an extra wide prefix is automatically added
|
||||
* for the following instructions if the numeric argument
|
||||
* is larger than 256. Also note that while the spec makes
|
||||
* no mention of opc_ret as being a "wideable" opcode, thats
|
||||
* how the VM is implemented.
|
||||
*
|
||||
* opc_ret:
|
||||
* opc_iload:
|
||||
* opc_lload:
|
||||
* opc_fload:
|
||||
* opc_dload:
|
||||
* opc_aload:
|
||||
* opc_istore:
|
||||
* opc_lstore:
|
||||
* opc_fstore:
|
||||
* opc_dstore:
|
||||
* opc_astore:
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Added branch instructions
|
||||
*/
|
||||
|
||||
public Insn(int opc, int val, boolean Wide)
|
||||
throws jasError
|
||||
{
|
||||
this.opc = opc;
|
||||
switch (opc)
|
||||
{
|
||||
case opc_bipush:
|
||||
if(val > 127 || val < -128)
|
||||
throw new jasError("bipush value exceed size of byte", true);
|
||||
operand = new ByteOperand(val);
|
||||
break;
|
||||
|
||||
case opc_sipush:
|
||||
case opc_goto:
|
||||
case opc_if_acmpeq:
|
||||
case opc_if_acmpne:
|
||||
case opc_if_icmpeq:
|
||||
case opc_if_icmpge:
|
||||
case opc_if_icmpgt:
|
||||
case opc_if_icmple:
|
||||
case opc_if_icmplt:
|
||||
case opc_if_icmpne:
|
||||
case opc_ifeq:
|
||||
case opc_ifge:
|
||||
case opc_ifgt:
|
||||
case opc_ifle:
|
||||
case opc_iflt:
|
||||
case opc_ifne:
|
||||
case opc_ifnonnull:
|
||||
case opc_ifnull:
|
||||
case opc_jsr:
|
||||
check_short(val, opc);
|
||||
operand = new OffsetOperand(this, val); break;
|
||||
|
||||
case opc_goto_w:
|
||||
case opc_jsr_w:
|
||||
operand = new OffsetOperand(this, val, true); break;
|
||||
|
||||
case opc_newarray:
|
||||
if(val < 0 || val > 255)
|
||||
throw new jasError("newarray counter is illegal", true);
|
||||
operand = new UnsignedByteOperand(val);
|
||||
break;
|
||||
|
||||
case opc_ret:
|
||||
case opc_iload:
|
||||
case opc_lload:
|
||||
case opc_fload:
|
||||
case opc_dload:
|
||||
case opc_aload:
|
||||
case opc_istore:
|
||||
case opc_lstore:
|
||||
case opc_fstore:
|
||||
case opc_dstore:
|
||||
case opc_astore:
|
||||
operand = new UnsignedByteWideOperand(val, Wide);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new jasError
|
||||
(opcNames[opc] + " does not take a numeric argument");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// used for relative offsets (ex : goto $+5)
|
||||
|
||||
public Insn(int opc, int val, char relative)
|
||||
throws jasError
|
||||
{
|
||||
this.opc = opc;
|
||||
switch (opc)
|
||||
{
|
||||
case opc_goto:
|
||||
case opc_if_acmpeq:
|
||||
case opc_if_acmpne:
|
||||
case opc_if_icmpeq:
|
||||
case opc_if_icmpge:
|
||||
case opc_if_icmpgt:
|
||||
case opc_if_icmple:
|
||||
case opc_if_icmplt:
|
||||
case opc_if_icmpne:
|
||||
case opc_ifeq:
|
||||
case opc_ifge:
|
||||
case opc_ifgt:
|
||||
case opc_ifle:
|
||||
case opc_iflt:
|
||||
case opc_ifne:
|
||||
case opc_ifnonnull:
|
||||
case opc_ifnull:
|
||||
case opc_jsr:
|
||||
check_short(val, opc);
|
||||
operand = new RelativeOffsetOperand(this, val); break;
|
||||
|
||||
case opc_goto_w:
|
||||
case opc_jsr_w:
|
||||
operand = new RelativeOffsetOperand(this, val, true); break;
|
||||
|
||||
default:
|
||||
throw new jasError
|
||||
(opcNames[opc] + " does not take a relative numeric argument");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructions that take a Label as an argument. These are
|
||||
* opc_jsr,
|
||||
* opc_goto,
|
||||
* opc_if_acmpne,
|
||||
* opc_if_acmpeq,
|
||||
* opc_if_icmpge,
|
||||
* opc_if_icmple,
|
||||
* opc_if_icmpgt,
|
||||
* opc_if_icmplt,
|
||||
* opc_if_icmpne,
|
||||
* opc_if_icmpeq,
|
||||
* opc_ifge,
|
||||
* opc_ifgt,
|
||||
* opc_ifne,
|
||||
* opc_ifle,
|
||||
* opc_iflt,
|
||||
* opc_ifeq,
|
||||
* opc_ifnull,
|
||||
* opc_ifnonnull,
|
||||
* opc_goto_w,
|
||||
* opc_jsr_w
|
||||
*/
|
||||
public Insn(int opc, Label target, int line)
|
||||
throws jasError
|
||||
{
|
||||
this.opc = opc;
|
||||
switch(opc)
|
||||
{
|
||||
case opc_jsr:
|
||||
case opc_goto:
|
||||
case opc_if_acmpne:
|
||||
case opc_if_acmpeq:
|
||||
case opc_if_icmpge:
|
||||
case opc_if_icmple:
|
||||
case opc_if_icmpgt:
|
||||
case opc_if_icmplt:
|
||||
case opc_if_icmpne:
|
||||
case opc_if_icmpeq:
|
||||
case opc_ifge:
|
||||
case opc_ifgt:
|
||||
case opc_ifne:
|
||||
case opc_ifle:
|
||||
case opc_iflt:
|
||||
case opc_ifeq:
|
||||
case opc_ifnull:
|
||||
case opc_ifnonnull:
|
||||
operand = new LabelOperand(target, this, line);
|
||||
break;
|
||||
case opc_goto_w:
|
||||
case opc_jsr_w:
|
||||
operand = new LabelOperand(target, this, true, line);
|
||||
break;
|
||||
default:
|
||||
throw new jasError
|
||||
(opcNames[opc] + " does not take a label as its argument");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This constructor is used for instructions that take a CP item
|
||||
* as their argument. These are
|
||||
* opc_anewarray,
|
||||
* opc_ldc_w,
|
||||
* opc_ldc2_w,
|
||||
* opc_invokedynamic,
|
||||
* opc_invokenonvirtual,
|
||||
* opc_invokestatic,
|
||||
* opc_invokevirtual,
|
||||
* opc_new,
|
||||
* opc_checkcast,
|
||||
* opc_instanceof,
|
||||
* opc_getstatic,
|
||||
* opc_putstatic,
|
||||
* opc_getfield,
|
||||
* opc_putfield,
|
||||
* opc_ldc
|
||||
*/
|
||||
public Insn(int opc, CP arg)
|
||||
throws jasError
|
||||
{
|
||||
this.opc = opc;
|
||||
switch(opc)
|
||||
{
|
||||
case opc_anewarray:
|
||||
case opc_invokedynamic:
|
||||
case opc_invokenonvirtual:
|
||||
case opc_invokestatic:
|
||||
case opc_invokevirtual:
|
||||
case opc_new:
|
||||
case opc_checkcast:
|
||||
case opc_instanceof:
|
||||
case opc_getstatic:
|
||||
case opc_putstatic:
|
||||
case opc_getfield:
|
||||
case opc_putfield:
|
||||
operand = new CPOperand(arg);
|
||||
break;
|
||||
case opc_ldc2_w:
|
||||
case opc_ldc_w:
|
||||
operand = new LdcOperand(this, arg);
|
||||
break;
|
||||
case opc_ldc:
|
||||
operand = new LdcOperand(this, arg, false);
|
||||
break;
|
||||
default:
|
||||
throw new jasError
|
||||
(opcNames[opc] + " does not take a CP item as an argument");
|
||||
}
|
||||
}
|
||||
|
||||
// This allows the Insn a chance to
|
||||
// add things to the global env if
|
||||
// necessary. The CPInsnOperands
|
||||
// use this to add the CP to the
|
||||
// classEnv
|
||||
void resolve(ClassEnv e)
|
||||
{ if (operand != null) { operand.resolve(e); } }
|
||||
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
if (operand != null)
|
||||
operand.writePrefix(e, ce, out);
|
||||
out.writeByte((byte) opc);
|
||||
if (operand != null)
|
||||
operand.write(e, ce, out);
|
||||
}
|
||||
|
||||
int size(ClassEnv e, CodeAttr ce)
|
||||
throws jasError
|
||||
{
|
||||
if (operand == null) return 1;
|
||||
return (1 + operand.size(e, ce));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "instruction "+opc+" "+((operand!=null)?operand.toString():"");
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Revision History ---------------------------------------------------
|
||||
--- Iouri Kharon, Aug 10 2006
|
||||
Added 'wide' prefix to some instructions
|
||||
*/
|
465
jasmin/jasmin-2.4/src/jas/InsnOperand.java
Normal file
465
jasmin/jasmin-2.4/src/jas/InsnOperand.java
Normal file
|
@ -0,0 +1,465 @@
|
|||
// This is not visible outside the
|
||||
// package. It is used to
|
||||
// handle the various types
|
||||
// of operands used by Insns.
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
abstract class InsnOperand
|
||||
{
|
||||
abstract void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError;
|
||||
abstract int size(ClassEnv e, CodeAttr code) throws jasError;
|
||||
abstract void resolve(ClassEnv e);
|
||||
void writePrefix(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{ return; }
|
||||
}
|
||||
|
||||
// Used to implement targets of Insns
|
||||
class LabelOperand extends InsnOperand
|
||||
{
|
||||
Label target;
|
||||
Insn source;
|
||||
boolean wide;
|
||||
int ref;
|
||||
|
||||
LabelOperand(Label l, Insn source, int line)
|
||||
{ target = l; this.source = source; this.wide = false; this.ref = line; }
|
||||
LabelOperand(Label l, Insn source, boolean wide, int line)
|
||||
{ target = l; this.source = source; this.wide = wide; this.ref = line; }
|
||||
int size(ClassEnv ce, CodeAttr code) { if (wide) return 4; else return 2; }
|
||||
void resolve(ClassEnv e) { return; }
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
if (wide) { target.writeWideOffset(ce, source, out); }
|
||||
else {
|
||||
int offset = ce.getPc(target);
|
||||
if (source != null)
|
||||
offset -= ce.getPc(source);
|
||||
if (offset > 32767 || offset < -32768)
|
||||
throw new jasError
|
||||
("reference from line " +ref+ " exceed size for short");
|
||||
target.writeOffset(ce, source, out); }
|
||||
}
|
||||
}
|
||||
|
||||
class UnsignedByteOperand extends InsnOperand
|
||||
{
|
||||
int val;
|
||||
|
||||
UnsignedByteOperand(int n) { val = n; }
|
||||
int size(ClassEnv ce, CodeAttr code) { return 1; }
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
if (val >= 256)
|
||||
throw
|
||||
new jasError("Operand is too large (" +val+ ") for this instruction");
|
||||
out.writeByte((byte)(0xff & val));
|
||||
}
|
||||
void resolve(ClassEnv e) { return; }
|
||||
}
|
||||
|
||||
// This (conditionally) adds a wide
|
||||
// prefix if the value is larger than
|
||||
// 256
|
||||
class UnsignedByteWideOperand extends InsnOperand
|
||||
implements RuntimeConstants
|
||||
{
|
||||
int val;
|
||||
boolean Wide;
|
||||
|
||||
UnsignedByteWideOperand(int n, boolean Wide)
|
||||
{
|
||||
val = n;
|
||||
this.Wide = (Wide || val > 255);
|
||||
}
|
||||
|
||||
int size(ClassEnv ce, CodeAttr code)
|
||||
{ return Wide ? 3: 1; }
|
||||
|
||||
void writePrefix(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (Wide)
|
||||
out.writeByte((byte)(opc_wide));
|
||||
}
|
||||
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (Wide)
|
||||
out.writeShort((short)(0xffff & val));
|
||||
else
|
||||
out.writeByte((byte)(val & 0xff));
|
||||
}
|
||||
void resolve(ClassEnv e) { return; }
|
||||
}
|
||||
|
||||
class ByteOperand extends InsnOperand
|
||||
{
|
||||
int val;
|
||||
|
||||
ByteOperand(int n) { val = n; }
|
||||
int size(ClassEnv ce, CodeAttr code) { return 1; }
|
||||
void resolve(ClassEnv e) { return; }
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException
|
||||
{ out.writeByte((byte)val); }
|
||||
}
|
||||
|
||||
class IntegerOperand extends InsnOperand
|
||||
{
|
||||
int val;
|
||||
|
||||
IntegerOperand(int n) { val = n; }
|
||||
int size(ClassEnv ce, CodeAttr code) { return 4; }
|
||||
void resolve(ClassEnv e) { return; }
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException
|
||||
{ out.writeInt(val); }
|
||||
}
|
||||
|
||||
class ShortOperand extends InsnOperand
|
||||
{
|
||||
int offset;
|
||||
ShortOperand(int n) { offset = n; }
|
||||
void resolve(ClassEnv e) { return; }
|
||||
int size(ClassEnv ce, CodeAttr code) { return 2; }
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException
|
||||
{ out.writeShort((short)offset); }
|
||||
}
|
||||
|
||||
class CPOperand extends InsnOperand
|
||||
{
|
||||
CP cpe;
|
||||
boolean wide;
|
||||
int size(ClassEnv ce, CodeAttr code) { if (wide) return 2; else return 1; }
|
||||
CPOperand(CP cpe) { this.cpe = cpe; wide = true; }
|
||||
CPOperand(CP cpe, boolean wide)
|
||||
{ this.cpe = cpe; this.wide = wide; }
|
||||
void resolve(ClassEnv e)
|
||||
{ e.addCPItem(cpe); }
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
int idx = e.getCPIndex(cpe);
|
||||
if (wide)
|
||||
{ out.writeShort((short) idx); }
|
||||
else
|
||||
{
|
||||
if (idx > 255)
|
||||
{ throw new jasError("exceeded size for small cpidx" + cpe); }
|
||||
out.writeByte((byte) (0xff & (idx)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// these are unique enough that
|
||||
// they need a separate handler for their
|
||||
// args
|
||||
class LdcOperand extends InsnOperand implements RuntimeConstants
|
||||
{
|
||||
CP cpe;
|
||||
Insn source;
|
||||
boolean wide;
|
||||
|
||||
int size(ClassEnv ce, CodeAttr code) throws jasError
|
||||
{
|
||||
if (wide)
|
||||
{ return 2; }
|
||||
else
|
||||
{
|
||||
// Should we promote it?
|
||||
int idx = ce.getCPIndex(cpe);
|
||||
if (idx > 255)
|
||||
{
|
||||
wide = true;
|
||||
source.opc = opc_ldc_w;
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
LdcOperand(Insn s, CP cpe) { source = s; this.cpe = cpe; wide = true; }
|
||||
LdcOperand(Insn s, CP cpe, boolean wide)
|
||||
{ source = s; this.cpe = cpe; this.wide = wide; }
|
||||
void resolve(ClassEnv e)
|
||||
{ e.addCPItem(cpe); }
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
int idx = e.getCPIndex(cpe);
|
||||
if (wide)
|
||||
{ out.writeShort((short) idx); }
|
||||
else
|
||||
{
|
||||
if (idx > 255)
|
||||
{ throw new jasError("exceeded size for small cpidx" + cpe); }
|
||||
out.writeByte((byte) (0xff & (idx)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class InvokeinterfaceOperand extends InsnOperand
|
||||
{
|
||||
CP cpe;
|
||||
int nargs;
|
||||
|
||||
InvokeinterfaceOperand(CP cpe, int nargs)
|
||||
{ this.cpe = cpe; this.nargs = nargs; }
|
||||
|
||||
int size(ClassEnv ce, CodeAttr code) { return 4; }
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{ e.addCPItem(cpe); }
|
||||
|
||||
void write (ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeShort(e.getCPIndex(cpe));
|
||||
out.writeByte((byte) (0xff & nargs));
|
||||
out.writeByte(0);
|
||||
}
|
||||
}
|
||||
|
||||
class IincOperand extends InsnOperand
|
||||
implements RuntimeConstants
|
||||
{
|
||||
int vindex, constt;
|
||||
boolean Wide;
|
||||
|
||||
IincOperand(int vindex, int constt, boolean Wide)
|
||||
{
|
||||
this.vindex = vindex;
|
||||
this.constt = constt;
|
||||
this.Wide = (Wide ||
|
||||
vindex > 255 ||
|
||||
constt > 127 ||
|
||||
constt < 127);
|
||||
}
|
||||
|
||||
int size(ClassEnv ce, CodeAttr code)
|
||||
{
|
||||
return Wide ? 5 : 2;
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e) { return; }
|
||||
|
||||
void writePrefix(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (Wide)
|
||||
out.writeByte((byte)opc_wide);
|
||||
}
|
||||
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (Wide)
|
||||
{
|
||||
out.writeShort((short)(0xffff & vindex));
|
||||
out.writeShort((short)(0xffff & constt));
|
||||
}
|
||||
else
|
||||
{
|
||||
out.writeByte((byte) (0xff & vindex));
|
||||
out.writeByte((byte) (0xff & constt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MultiarrayOperand extends InsnOperand
|
||||
{
|
||||
CP cpe;
|
||||
int sz;
|
||||
|
||||
MultiarrayOperand(CP cpe, int sz)
|
||||
{ this.cpe = cpe; this.sz = sz; }
|
||||
void resolve(ClassEnv e) { e.addCPItem(cpe); }
|
||||
int size(ClassEnv ce, CodeAttr code) { return 3; }
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeShort(e.getCPIndex(cpe));
|
||||
out.writeByte((byte)(0xff & sz));
|
||||
}
|
||||
}
|
||||
|
||||
class LookupswitchOperand extends InsnOperand
|
||||
{
|
||||
LabelOrOffset dflt;
|
||||
Insn source;
|
||||
int match[];
|
||||
LabelOrOffset jmp[];
|
||||
|
||||
LookupswitchOperand(Insn s, LabelOrOffset def, int m[], LabelOrOffset j[])
|
||||
{ dflt = def; jmp = j; match = m; source = s; }
|
||||
|
||||
void resolve (ClassEnv e) { return; }
|
||||
int size(ClassEnv ce, CodeAttr code) throws jasError
|
||||
{
|
||||
int sz = 8; // 4 + 4 + padding + jumptable
|
||||
int source_pc = code.getPc(source);
|
||||
if (((source_pc+1) % 4) != 0)
|
||||
{
|
||||
// need padding
|
||||
sz += (4 - ((source_pc+1) % 4));
|
||||
}
|
||||
|
||||
if (jmp != null)
|
||||
{ sz += 8*(jmp.length); }
|
||||
return sz;
|
||||
}
|
||||
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
int pad;
|
||||
int source_pc = ce.getPc(source);
|
||||
|
||||
if (((source_pc+1) % 4) != 0)
|
||||
{ // need padding
|
||||
pad = (4 - ((source_pc+1) % 4));
|
||||
for (int x=0; x<pad; x++) out.writeByte(0);
|
||||
}
|
||||
|
||||
// write offset to default
|
||||
// as a 4 byte signed value
|
||||
dflt.writeWideOffset(ce, source, out);
|
||||
if (jmp == null)
|
||||
{ out.writeInt(0); }
|
||||
else
|
||||
{
|
||||
out.writeInt(jmp.length);
|
||||
for (int x=0; x<jmp.length; x++)
|
||||
{
|
||||
out.writeInt(match[x]);
|
||||
jmp[x].writeWideOffset(ce, source, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TableswitchOperand extends InsnOperand
|
||||
{
|
||||
int min, max;
|
||||
LabelOrOffset dflt;
|
||||
LabelOrOffset jmp[];
|
||||
Insn source;
|
||||
|
||||
TableswitchOperand(Insn s,int min, int max, LabelOrOffset def,
|
||||
LabelOrOffset j[])
|
||||
{
|
||||
this.min = min; this.max = max;
|
||||
dflt = def; jmp = j; source = s;
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e) { return; }
|
||||
|
||||
int size(ClassEnv ce, CodeAttr code)
|
||||
throws jasError
|
||||
// the *real* reason for making it a
|
||||
// method..
|
||||
{
|
||||
int sz = 12; // 4+4+4+jmptable+padding...
|
||||
int source_pc = code.getPc(source);
|
||||
if (((source_pc+1) % 4) != 0)
|
||||
{ // need padding
|
||||
sz += (4 - ((source_pc+1) % 4));
|
||||
}
|
||||
if (jmp != null)
|
||||
{ sz += 4*(jmp.length); }
|
||||
return sz;
|
||||
}
|
||||
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
int pad;
|
||||
int source_pc = ce.getPc(source);
|
||||
|
||||
if (((source_pc+1) % 4) != 0)
|
||||
{ // need padding
|
||||
pad = (4 - ((source_pc+1) % 4));
|
||||
for (int x=0; x<pad; x++) out.writeByte(0);
|
||||
}
|
||||
dflt.writeWideOffset(ce, source, out);
|
||||
out.writeInt(min);
|
||||
out.writeInt(max);
|
||||
int cnt = jmp.length;
|
||||
for (int x=0; x<cnt; x++)
|
||||
{ jmp[x].writeWideOffset(ce, source, out); }
|
||||
}
|
||||
}
|
||||
|
||||
class OffsetOperand extends InsnOperand {
|
||||
int val;
|
||||
boolean wide;
|
||||
Insn parent;
|
||||
|
||||
OffsetOperand(Insn parent, int val) {
|
||||
this(parent, val, false);
|
||||
}
|
||||
|
||||
OffsetOperand(Insn parent, int val, boolean wide) {
|
||||
this.parent = parent;
|
||||
this.val = val;
|
||||
this.wide = wide;
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e) { return; }
|
||||
|
||||
int size(ClassEnv e, CodeAttr ce) {
|
||||
return wide ? 4 : 2;
|
||||
}
|
||||
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError {
|
||||
if(wide)
|
||||
out.writeInt(val);
|
||||
else
|
||||
out.writeShort(val);
|
||||
}
|
||||
}
|
||||
|
||||
class RelativeOffsetOperand extends InsnOperand {
|
||||
int val;
|
||||
boolean wide;
|
||||
Insn parent;
|
||||
|
||||
RelativeOffsetOperand(Insn parent, int val) {
|
||||
this(parent, val, false);
|
||||
}
|
||||
|
||||
RelativeOffsetOperand(Insn parent, int val, boolean wide) {
|
||||
this.parent = parent;
|
||||
this.val = val;
|
||||
this.wide = wide;
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e) { return; }
|
||||
|
||||
int size(ClassEnv e, CodeAttr ce) {
|
||||
return wide ? 4 : 2;
|
||||
}
|
||||
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
throws IOException, jasError {
|
||||
if(wide)
|
||||
out.writeInt(val);
|
||||
else
|
||||
out.writeShort(val);
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Revision History ---------------------------------------------------
|
||||
--- Iouri Kharon, Aug 10 2006
|
||||
Added 'Wide' prefix support to IincOperand and UnsideWideOperand
|
||||
*/
|
32
jasmin/jasmin-2.4/src/jas/IntegerCP.java
Normal file
32
jasmin/jasmin-2.4/src/jas/IntegerCP.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
/**
|
||||
* Wrap an integer constant reference with this CPE.
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
public class IntegerCP extends CP implements RuntimeConstants
|
||||
{
|
||||
int val;
|
||||
|
||||
/**
|
||||
* @param n Value for integer constant
|
||||
*/
|
||||
public IntegerCP(int n)
|
||||
{
|
||||
uniq = ("Integer: @#$" + n).intern();
|
||||
val = n;
|
||||
}
|
||||
void resolve(ClassEnv e) { return; }
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeByte(CONSTANT_INTEGER);
|
||||
out.writeInt(val);
|
||||
}
|
||||
}
|
43
jasmin/jasmin-2.4/src/jas/InterfaceCP.java
Normal file
43
jasmin/jasmin-2.4/src/jas/InterfaceCP.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* An InterfaceCP is used to refer to an interface specification
|
||||
*
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
public class InterfaceCP extends CP implements RuntimeConstants
|
||||
{
|
||||
ClassCP clazz;
|
||||
NameTypeCP nt;
|
||||
|
||||
/**
|
||||
* @param cname Name of class defining the interface
|
||||
* @param varname symbol for the interface method
|
||||
* @param sig Signature for method
|
||||
*/
|
||||
public InterfaceCP(String cname, String varname, String sig)
|
||||
{
|
||||
uniq = (cname + "&%$#&" + varname + "*()#$" + sig).intern();
|
||||
clazz = new ClassCP(cname);
|
||||
nt = new NameTypeCP(varname, sig);
|
||||
}
|
||||
|
||||
void resolve(ClassEnv e)
|
||||
{
|
||||
e.addCPItem(clazz);
|
||||
e.addCPItem(nt);
|
||||
}
|
||||
|
||||
void write(ClassEnv e, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
out.writeByte(CONSTANT_INTERFACEMETHOD);
|
||||
out.writeShort(e.getCPIndex(clazz));
|
||||
out.writeShort(e.getCPIndex(nt));
|
||||
}
|
||||
}
|
21
jasmin/jasmin-2.4/src/jas/InvokeinterfaceInsn.java
Normal file
21
jasmin/jasmin-2.4/src/jas/InvokeinterfaceInsn.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Some instructions are perniticky enough that its simpler
|
||||
* to write them separately instead of smushing them with
|
||||
* all the rest. the invokeinterface instruction is one of them.
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
public class InvokeinterfaceInsn extends Insn implements RuntimeConstants
|
||||
{
|
||||
public InvokeinterfaceInsn(CP cpe, int nargs)
|
||||
{
|
||||
opc = opc_invokeinterface;
|
||||
operand = new InvokeinterfaceOperand(cpe, nargs);
|
||||
}
|
||||
}
|
73
jasmin/jasmin-2.4/src/jas/Label.java
Normal file
73
jasmin/jasmin-2.4/src/jas/Label.java
Normal file
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* Labels are implemented as Insn's, but are special (read
|
||||
* unseemly blobs of hacked up code). First, they don't
|
||||
* actually cause any code to be written, and second, are
|
||||
* identified globally through a String label that is associated
|
||||
* with them when they are created.
|
||||
* @author $Author: jonmeyerny $
|
||||
* @version $Revision: 1.2 $
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
public class Label extends Insn implements RuntimeConstants
|
||||
{
|
||||
String id;
|
||||
|
||||
/**
|
||||
* Create a new Label with this tag. Any label with this tag
|
||||
* will be treated as being identical to this one. You can
|
||||
* reuse labels if you like
|
||||
*/
|
||||
public Label(String tag)
|
||||
{
|
||||
id = tag.intern();
|
||||
opc = opc_label;
|
||||
operand = null;
|
||||
}
|
||||
// override the write method to do nothing.
|
||||
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
|
||||
{ return; }
|
||||
// and the size method appropriately
|
||||
int size(ClassEnv e, CodeAttr ce)
|
||||
{ return 0; }
|
||||
// This is called from the LabelOperand
|
||||
void writeOffset(CodeAttr ce, Insn source, DataOutputStream out)
|
||||
throws jasError, IOException
|
||||
{ // write the offset (as a short)
|
||||
// of source
|
||||
int pc, tpc;
|
||||
pc = ce.getPc(this);
|
||||
if (source == null)
|
||||
tpc = 0;
|
||||
else
|
||||
tpc = ce.getPc(source);
|
||||
short offset = (short) (pc - tpc);
|
||||
out.writeShort(offset);
|
||||
}
|
||||
|
||||
void writeWideOffset(CodeAttr ce, Insn source, DataOutputStream out)
|
||||
throws IOException, jasError
|
||||
{
|
||||
int pc, tpc;
|
||||
pc = ce.getPc(this);
|
||||
if (source == null)
|
||||
tpc = 0;
|
||||
else
|
||||
tpc = ce.getPc(source);
|
||||
out.writeInt(pc - tpc);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return ("Label: " + id);
|
||||
}
|
||||
|
||||
// method for StackMapFrame attribute (jdk1.6)
|
||||
int getOffset(CodeAttr ce) throws jasError
|
||||
{ return (short)ce.getPc(this); }
|
||||
}
|
||||
|
39
jasmin/jasmin-2.4/src/jas/LabelOrOffset.java
Normal file
39
jasmin/jasmin-2.4/src/jas/LabelOrOffset.java
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* The purpose of this class is to have a generic type
|
||||
* for labels and offsets, used by tableswitch and lookupswitch
|
||||
*
|
||||
*/
|
||||
|
||||
package jas;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LabelOrOffset {
|
||||
private Label label;
|
||||
private int offset;
|
||||
|
||||
public LabelOrOffset(Label l) {
|
||||
label = l;
|
||||
}
|
||||
|
||||
public LabelOrOffset(int o) {
|
||||
offset = o;
|
||||
}
|
||||
|
||||
Label getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
void writeWideOffset(CodeAttr ce, Insn source, DataOutputStream out)
|
||||
throws jasError, IOException {
|
||||
if(label!=null)
|
||||
label.writeWideOffset(ce, source, out);
|
||||
else
|
||||
out.writeInt(offset);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue