Initial sources!

This commit is contained in:
bkurotsu 2014-12-18 14:56:02 -07:00
parent 10f0060dba
commit 691a9f8de6
81 changed files with 24126 additions and 0 deletions

View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools;
import org.openjdk.asmtools.util.I18NResourceBundle;
import org.openjdk.asmtools.util.ProductInfo;
/**
* Wrapper class that reads the first command line argument and invokes a corresponding
* tool.
*/
public class Main {
public static final I18NResourceBundle i18n
= I18NResourceBundle.getBundleForClass(Main.class);
/**
* Parses the first argument and deligates execution to an appropriate tool
*
* @param args - command line arguments
*/
public static void main(String args[]) {
if (args.length == 0) {
usage(i18n.getString("main.error.no_arguments"), 1);
}
String cmd = args[0];
if (cmd.equals("-?") || cmd.equals("-h") || cmd.equals("-help")) {
usage(null, 0);
} else if (cmd.equals("-version")) {
printVersion();
} else {
String[] newArgs = new String[args.length - 1];
System.arraycopy(args, 1, newArgs, 0, args.length - 1);
if (cmd.equals("jasm")) {
jasm(newArgs);
} else if (cmd.equals("jdis")) {
jdis(newArgs);
} else if (cmd.equals("jcoder")) {
jcoder(newArgs);
} else if (cmd.equals("jdec")) {
jdec(newArgs);
} else if (cmd.equals("jcdec")) {
jcdec(newArgs);
} else {
usage(i18n.getString("main.error.unknown_tool", cmd), 1);
}
}
}
/**
* Prints usage info and error message, afterwards invokes System.exit()
*
* @param msg - error message to print, or null if no errors occurred
* @param exitCode - exit code to be returned by System.exit()
*/
public static void usage(String msg, int exitCode) {
System.err.println(i18n.getString("main.usage", "asmtools.jar"));
if (msg != null) {
System.err.println(msg);
}
System.exit(exitCode);
}
/**
* Prints the tools version and calls System.exit(0)
*/
public static void printVersion() {
System.err.println(ProductInfo.FULL_VERSION);
System.exit(0);
}
/**
* Invokes jasm main class with passed arguments
*/
public static void jasm(String[] args) {
org.openjdk.asmtools.jasm.Main.main(args);
}
/**
* Invokes jcdec main class with passed arguments
*/
public static void jcdec(String[] args) {
org.openjdk.asmtools.jcdec.Main.main(args);
}
/**
* Invokes jcoder main class with passed arguments
*/
public static void jcoder(String[] args) {
org.openjdk.asmtools.jcoder.Main.main(args);
}
/**
* Invokes jdec main class with passed arguments
*/
public static void jdec(String[] args) {
org.openjdk.asmtools.jdec.Main.main(args);
}
/**
* Invokes jdis main class with passed arguments
*/
public static void jdis(String[] args) {
org.openjdk.asmtools.jdis.Main.main(args);
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.openjdk.asmtools.asmutils;
/**
*
*/
public class HexUtils {
/*======================================================== Hex */
private static final String hexString = "0123456789ABCDEF";
private static final char hexTable[] = hexString.toCharArray();
public static String toHex(long val, int width) {
StringBuffer s = new StringBuffer();
for (int i = width - 1; i >= 0; i--) {
s.append(hexTable[((int) (val >> (4 * i))) & 0xF]);
}
return "0x" + s.toString();
}
public static String toHex(long val) {
int width;
for (width = 16; width > 0; width--) {
if ((val >> (width - 1) * 4) != 0) {
break;
}
}
return toHex(val, width);
}
public static String toHex(int val) {
int width;
for (width = 8; width > 0; width--) {
if ((val >> (width - 1) * 4) != 0) {
break;
}
}
return toHex(val, width);
}
}

View File

@ -0,0 +1,33 @@
# Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
main.usage=\
Usage: \n\
to run an assembly tool: \n\
\ $ java -jar {0} toolName [args...] \n\
\ where toolName one of: jasm, jdis, jcoder, jdec, jcdec \n\
to get the version: \n\
\ $ java -jar {0} -version \n\
to get this message \n\
\ $ java -jar {0} -?|-h|-help\n
main.error.no_arguments=No arguments provided! See options above.
main.error.unknown_tool=Tool name ''{0}'' unrecognized. See usage above for possible tool choices.

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.util.ArrayList;
/**
* See JVMS3, section 4.8.16.
*/
class AnnotationData implements Data {
boolean invisible;
Argument typeCPX;
ArrayList<ElemValuePair> elemValuePairs;
int annotationLength = 0;
/**
* AnnotationElemValue
*
* Used to store Annotation Data
*/
static public class ElemValuePair implements Data {
ConstantPool.ConstCell name;
Data value;
public ElemValuePair(ConstantPool.ConstCell name, Data value) {
this.name = name;
this.value = value;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
name.write(out);
value.write(out);
}
@Override
public int getLength() {
return 2 + value.getLength();
}
}
public AnnotationData(Argument typeCPX, boolean invisible) {
this.typeCPX = typeCPX;
this.elemValuePairs = new ArrayList<>();
this.invisible = invisible;
}
public void add(ElemValuePair elemValuePair) {
elemValuePairs.add(elemValuePair);
annotationLength += elemValuePair.getLength();
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(typeCPX.arg);
out.writeShort(elemValuePairs.size());
for (Data pair : elemValuePairs) {
pair.write(out);
}
}
@Override
public int getLength() {
return 4 + annotationLength;
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
/**
*
*/
class Argument {
static final int NotSet = -1;
int arg;
Argument() {
arg = NotSet;
}
Argument(int arg) {
this.arg = arg;
}
public int hashCode() {
return arg;
}
/**
* Compares this object to the specified object.
*
* @param obj the object to compare with
* @return true if the objects are the same; false otherwise.
*/
public boolean equals(Object obj) {
throw new Parser.CompilerError("ConstCell.equals");
}
boolean isSet() {
return arg != NotSet;
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
/**
* AttrData
*
* AttrData is the base class for many attributes (or parts of attributes), and it is
* instantiated directly for simple attributes (like Synthetic or Deprecated).
*/
class AttrData implements Data {
private final ClassData clsData;
private final Argument attrNameCPX;
AttrData(ClassData cdata, String name) {
clsData = cdata;
attrNameCPX = cdata.pool.FindCellAsciz(name);
}
// full length of the attribute
// declared in Data
public int getLength() {
return 6 + attrLength();
}
// subclasses must redefine this
public int attrLength() {
return 0;
}
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(attrNameCPX.arg);
out.writeInt(attrLength()); // attr len
}
} // end class AttrData

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.util.ArrayList;
/**
*
*/
class BootstrapMethodData extends Argument implements Data {
ConstantPool.ConstCell bootstrapMethodHandle;
ArrayList<ConstantPool.ConstCell> arguments;
public int placeholder_index = -1;
public BootstrapMethodData(ConstantPool.ConstCell bsmHandle, ArrayList<ConstantPool.ConstCell> arguments) {
super();
this.bootstrapMethodHandle = bsmHandle;
this.arguments = arguments;
}
public BootstrapMethodData(int placeholder) {
super();
this.bootstrapMethodHandle = null;
this.arguments = null;
this.placeholder_index = placeholder;
}
public int getLength() {
return 4 + arguments.size() * 2;
}
public boolean isPlaceholder() {
return placeholder_index > -1;
}
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(bootstrapMethodHandle.arg);
out.writeShort(arguments.size());
for (ConstantPool.ConstCell argument : arguments) {
out.writeShort(argument.arg);
}
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
/**
* Constant Pool Index Attribute
*/
class CPXAttr extends AttrData {
Argument cell;
public CPXAttr(ClassData cls, String attrName, Argument cell) {
super(cls, attrName);
this.cell = cell;
}
public int attrLength() {
return 2;
}
public void write(CheckedDataOutputStream out) throws IOException {
super.write(out); // attr name, attr len
out.writeShort(cell.arg);
}
} // end class CPXAttr

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.openjdk.asmtools.jasm;
import java.io.DataOutput;
import java.io.IOException;
/**
*
*/
public interface CheckedDataOutputStream {
public void write(int b) throws IOException;
public void write(byte b[], int off, int len) throws IOException;
public void writeBoolean(boolean v) throws IOException;
public void writeByte(int v) throws IOException;
public void writeShort(int v) throws IOException;
public void writeChar(int v) throws IOException;
public void writeInt(int v) throws IOException;
public void writeLong(long v) throws IOException;
public void writeFloat(float v) throws IOException;
public void writeDouble(double v) throws IOException;
public void writeBytes(String s) throws IOException;
public void writeChars(String s) throws IOException;
public void writeUTF(String s) throws IOException;
// public int writeUTF(String str, DataOutput out) throws IOException;
}

View File

@ -0,0 +1,577 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import static org.openjdk.asmtools.jasm.Constants.DEFAULT_MAJOR_VERSION;
import static org.openjdk.asmtools.jasm.Constants.DEFAULT_MINOR_VERSION;
import static org.openjdk.asmtools.jasm.Tables.*;
import java.io.*;
import java.util.ArrayList;
/**
* ClassData
*
* This is the main data structure for representing parsed class data. This structure
* renders directly to a class file.
*
*/
class ClassData extends MemberData {
/*-------------------------------------------------------- */
/* ClassData inner classes */
/*-------------------------------------------------------- */
/* ClassData Fields */
short major_version = DEFAULT_MAJOR_VERSION;
short minor_version = DEFAULT_MINOR_VERSION;
ConstantPool.ConstCell me, father;
String myClassName;
AttrData sourceFileNameAttr;
ArrayList<Argument> interfaces;
ArrayList<FieldData> fields = new ArrayList<>();
ArrayList<MethodData> methods = new ArrayList<>();
DataVectorAttr<InnerClassData> innerClasses = null;
DataVectorAttr<BootstrapMethodData> bootstrapMethodsAttr = null;
String mdl = null;
Environment env;
protected ConstantPool pool;
private static final String DEFAULT_EXTENSION = ".class";
String fileExtension = DEFAULT_EXTENSION;
public CDOutputStream cdos;
/*-------------------------------------------------------- */
/**
* init
*
* Initializes the ClassData.
*
* @param me The constant pool reference to this class
* @param father The constant pool reference to the super class
* @param interfaces A list of interfaces that this class implements
*/
public final void init(int access, ConstantPool.ConstCell me, ConstantPool.ConstCell father, ArrayList<Argument> interfaces) {
this.access = access;
// normalize the modifiers to access flags
if (Modifiers.hasPseudoMod(access)) {
createPseudoMod();
}
this.me = me;
if (father == null) {
father = pool.FindCellClassByName("java/lang/Object");
}
this.father = father;
this.interfaces = interfaces;
}
/**
* default constructor
*
* @param env
*/
public ClassData(Environment env) {
super(null, 0); // for a class, these get inited in the super - later.
cls = this;
this.env = env;
pool = new ConstantPool(env);
cdos = new CDOutputStream();
}
/**
* canonical default constructor
*
* @param env The error reporting environment.
* @param major_version The major version that this class file supports.
* @param minor_version The minor version that this class file supports
*/
public ClassData(Environment env, short major_version, short minor_version) {
this(env);
this.major_version = major_version;
this.minor_version = minor_version;
}
public ClassData(Environment env, int acc, ConstantPool.ConstCell me, ConstantPool.ConstCell father, ArrayList<Argument> impls) {
this(env);
init(acc, me, father, impls);
}
/* *********************************************** */
/**
* isInterface
*
* Predicate that describes if this class has an access flag indicating that it is an
* interface.
*
* @return True if the classes access flag indicates it is an interface.
*/
public final boolean isInterface() {
return Modifiers.isInterface(access);
}
/*
* After a constant pool has been explicitly declared,
* this method links the Constant_InvokeDynamic constants
* with any bootstrap methods that they index in the
* Bootstrap Methods Attribute
*/
protected void relinkBootstrapMethods() {
if (bootstrapMethodsAttr == null) {
return;
}
env.traceln("relinkBootstrapMethods");
for (ConstantPool.ConstCell cell : pool) {
ConstantPool.ConstValue ref = null;
if (cell != null) {
ref = cell.ref;
}
if (ref != null
&& ref.tag == ConstType.CONSTANT_INVOKEDYNAMIC) {
// Find only the Constant
ConstantPool.ConstValue_IndyPair refval = (ConstantPool.ConstValue_IndyPair) ref;
if (refval != null) {
BootstrapMethodData bsmdata = refval.bsmData;
// only care about BSM Data that were placeholders
if (bsmdata != null && bsmdata.isPlaceholder()) {
// find the real BSM Data at the index
int bsmindex = bsmdata.placeholder_index;
if (bsmindex < 0 || bsmindex > bootstrapMethodsAttr.size()) {
// bad BSM index --
// give a warning, but place the index in the arg anyway
env.traceln("Warning: (ClassData.relinkBootstrapMethods()): Bad bootstrapMethods index: " + bsmindex);
// env.error("const.bsmindex", bsmindex);
bsmdata.arg = bsmindex;
} else {
BootstrapMethodData realbsmdata = bootstrapMethodsAttr.get(bsmindex);
// make the IndyPairs BSM Data point to the one from the attribute
refval.bsmData = realbsmdata;
}
}
}
}
}
}
protected void numberBootstrapMethods() {
env.traceln("Numbering Bootstrap Methods");
if (bootstrapMethodsAttr == null) {
return;
}
int index = 0;
for (BootstrapMethodData data : bootstrapMethodsAttr) {
data.arg = index++;
}
}
/*-------------------------------------------------------- API */
public ConstantPool.ConstValue_Pair mkNape(ConstantPool.ConstCell name, ConstantPool.ConstCell sig) {
return new ConstantPool.ConstValue_Pair(ConstType.CONSTANT_NAMEANDTYPE, name, sig);
}
public ConstantPool.ConstValue_Pair mkNape(String name, String sig) {
return mkNape(pool.FindCellAsciz(name), pool.FindCellAsciz(sig));
}
public void setSourceFileName(String name) {
}
public FieldData addField(int access, ConstantPool.ConstValue_Pair nape) {
env.traceln(" [ClassData.addField]: #" + nape.left.arg + ":#" + nape.right.arg);
FieldData res = new FieldData(this, access, nape);
fields.add(res);
return res;
}
public FieldData addField(int access, ConstantPool.ConstCell name, ConstantPool.ConstCell sig) {
return addField(access, mkNape(name, sig));
}
public FieldData addField(int access, String name, String type) {
return addField(access, pool.FindCellAsciz(name), pool.FindCellAsciz(type));
}
public ConstantPool.ConstCell LocalFieldRef(FieldData field) {
return pool.FindCell(ConstType.CONSTANT_FIELD, me, pool.FindCell(field.nape));
}
public ConstantPool.ConstCell LocalFieldRef(ConstantPool.ConstValue nape) {
return pool.FindCell(ConstType.CONSTANT_FIELD, me, pool.FindCell(nape));
}
public ConstantPool.ConstCell LocalFieldRef(ConstantPool.ConstCell name, ConstantPool.ConstCell sig) {
return LocalFieldRef(mkNape(name, sig));
}
public ConstantPool.ConstCell LocalFieldRef(String name, String sig) {
return LocalFieldRef(pool.FindCellAsciz(name), pool.FindCellAsciz(sig));
}
MethodData curMethod;
public MethodData StartMethod(int access, ConstantPool.ConstCell name, ConstantPool.ConstCell sig, ArrayList exc_table) {
EndMethod();
env.traceln(" [ClassData.StartMethod]: #" + name.arg + ":#" + sig.arg);
curMethod = new MethodData(this, access, name, sig, exc_table);
methods.add(curMethod);
return curMethod;
}
public void EndMethod() {
curMethod = null;
}
public ConstantPool.ConstCell LocalMethodRef(ConstantPool.ConstValue nape) {
return pool.FindCell(ConstType.CONSTANT_METHOD, me, pool.FindCell(nape));
}
public ConstantPool.ConstCell LocalMethodRef(ConstantPool.ConstCell name, ConstantPool.ConstCell sig) {
return LocalMethodRef(mkNape(name, sig));
}
void addLocVarData(int opc, Argument arg) {
}
public void addInnerClass(int access, ConstantPool.ConstCell name, ConstantPool.ConstCell innerClass, ConstantPool.ConstCell outerClass) {
env.traceln("addInnerClass (with indexes: Name (" + name.toString() + "), Inner (" + innerClass.toString() + "), Outer (" + outerClass.toString() + ").");
if (innerClasses == null) {
innerClasses = new DataVectorAttr<>(this, AttrTag.ATT_InnerClasses.parsekey());
}
innerClasses.add(new InnerClassData(access, name, innerClass, outerClass));
}
public void addBootstrapMethod(BootstrapMethodData bsmData) {
env.traceln("addBootstrapMethod");
if (bootstrapMethodsAttr == null) {
bootstrapMethodsAttr = new DataVectorAttr<>(this, AttrTag.ATT_BootstrapMethods.parsekey());
}
bootstrapMethodsAttr.add(bsmData);
}
public void endClass() {
sourceFileNameAttr = new CPXAttr(this,
AttrTag.ATT_SourceFile.parsekey(),
pool.FindCellAsciz(env.getSourceName()));
pool.NumberizePool();
pool.CheckGlobals();
numberBootstrapMethods();
try {
me = pool.uncheckedGetCell(me.arg);
env.traceln("me=" + me);
ConstantPool.ConstValue_Cell me_value = (ConstantPool.ConstValue_Cell) me.ref;
ConstantPool.ConstCell ascicell = me_value.cell;
env.traceln("ascicell=" + ascicell);
ConstantPool.ConstValue_String me_str = (ConstantPool.ConstValue_String) ascicell.ref;
myClassName = me_str.value;
env.traceln("--------------------------------------------");
env.traceln("-- Constant Pool --");
env.traceln("-------------------");
pool.printPool();
env.traceln("--------------------------------------------");
env.traceln(" ");
env.traceln(" ");
env.traceln("--------------------------------------------");
env.traceln("-- Inner Classes --");
env.traceln("-------------------");
printInnerClasses();
} catch (Throwable e) {
env.traceln("check name:" + e);
env.error("no.classname");
e.printStackTrace();
}
}
private void printInnerClasses() {
if (innerClasses != null) {
int i = 1;
for (InnerClassData entry : innerClasses) {
env.trace(" InnerClass[" + i + "]: (" + Modifiers.toString(entry.access, CF_Context.CTX_INNERCLASS) + "]), ");
env.trace("Name: " + entry.name.toString() + " ");
env.trace("IC_info: " + entry.innerClass.toString() + " ");
env.trace("OC_info: " + entry.outerClass.toString() + " ");
env.traceln(" ");
i += 1;
}
} else {
env.traceln("<< NO INNER CLASSES >>");
}
}
/*====================================================== write */
public void write(CheckedDataOutputStream out) throws IOException {
// Write the header
out.writeInt(JAVA_MAGIC);
out.writeShort(minor_version);
out.writeShort(major_version);
pool.write(out);
out.writeShort(access); // & MM_CLASS; // Q
out.writeShort(me.arg);
out.writeShort(father.arg);
// Write the interface names
if (interfaces != null) {
out.writeShort(interfaces.size());
for (Argument intf : interfaces) {
out.writeShort(intf.arg);
}
} else {
out.writeShort(0);
}
// Write the fields
if (fields != null) {
out.writeShort(fields.size());
for (FieldData field : fields) {
field.write(out);
}
} else {
out.writeShort(0);
}
// Write the methods
if (methods != null) {
out.writeShort(methods.size());
for (MethodData method : methods) {
method.write(out);
}
} else {
out.writeShort(0);
}
// Write the attributes
DataVector attrs = new DataVector();
attrs.add(sourceFileNameAttr);
if (innerClasses != null) {
attrs.add(innerClasses);
}
if (syntheticAttr != null) {
attrs.add(syntheticAttr);
}
if (deprecatedAttr != null) {
attrs.add(deprecatedAttr);
}
if (annotAttrVis != null) {
attrs.add(annotAttrVis);
}
if (annotAttrInv != null) {
attrs.add(annotAttrInv);
}
if (type_annotAttrVis != null) {
attrs.add(type_annotAttrVis);
}
if (type_annotAttrInv != null) {
attrs.add(type_annotAttrInv);
}
if (bootstrapMethodsAttr != null) {
attrs.add(bootstrapMethodsAttr);
}
attrs.write(out);
} // end ClassData.write()
static char fileSeparator; //=System.getProperty("file.separator");
/**
* write to the directory passed with -d option
*/
public void write(File destdir) throws IOException {
File outfile;
if (destdir == null) {
int startofname = myClassName.lastIndexOf("/");
if (startofname != -1) {
myClassName = myClassName.substring(startofname + 1);
}
outfile = new File(myClassName + fileExtension);
} else {
env.traceln("writing -d " + destdir.getPath());
if (fileSeparator == 0) {
fileSeparator = System.getProperty("file.separator").charAt(0);
}
if (fileSeparator != '/') {
myClassName = myClassName.replace('/', fileSeparator);
}
outfile = new File(destdir, myClassName + fileExtension);
File outdir = new File(outfile.getParent());
if (!outdir.exists() && !outdir.mkdirs()) {
env.error("cannot.write", outdir.getPath());
return;
}
}
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream(outfile)));
cdos.setDataOutputStream(dos);
try {
write(cdos);
} finally {
dos.close();
}
} // end write()
public void setByteLimit(int bytelimit) {
cdos.enable();
cdos.setLimit(bytelimit);
}
/**
* CDOutputStream
*
* This is a wrapper for DataOutputStream, used for debugging purposes. it allows
* writing the byte-stream of a class up to a given byte number.
*/
static private class CDOutputStream implements CheckedDataOutputStream {
private int bytelimit;
private DataOutputStream dos;
public boolean enabled = false;
public CDOutputStream() {
dos = null;
}
public CDOutputStream(OutputStream out) {
setOutputStream(out);
}
public final void setOutputStream(OutputStream out) {
dos = new DataOutputStream(out);
}
public void setDataOutputStream(DataOutputStream dos) {
this.dos = dos;
}
public void setLimit(int lim) {
bytelimit = lim;
}
public void enable() {
enabled = true;
}
private synchronized void check(String loc) throws IOException {
if (enabled && dos.size() >= bytelimit) {
throw new IOException(loc);
}
}
@Override
public synchronized void write(int b) throws IOException {
dos.write(b);
check("Writing byte: " + b);
}
@Override
public synchronized void write(byte b[], int off, int len) throws IOException {
dos.write(b, off, len);
check("Writing byte-array: " + b);
}
@Override
public final void writeBoolean(boolean v) throws IOException {
dos.writeBoolean(v);
check("Writing writeBoolean: " + (v ? "true" : "false"));
}
@Override
public final void writeByte(int v) throws IOException {
dos.writeByte(v);
check("Writing writeByte: " + v);
}
@Override
public void writeShort(int v) throws IOException {
dos.writeShort(v);
check("Writing writeShort: " + v);
}
@Override
public void writeChar(int v) throws IOException {
dos.writeChar(v);
check("Writing writeChar: " + v);
}
@Override
public void writeInt(int v) throws IOException {
dos.writeInt(v);
check("Writing writeInt: " + v);
}
@Override
public void writeLong(long v) throws IOException {
dos.writeLong(v);
check("Writing writeLong: " + v);
}
@Override
public void writeFloat(float v) throws IOException {
dos.writeFloat(v);
check("Writing writeFloat: " + v);
}
@Override
public void writeDouble(double v) throws IOException {
dos.writeDouble(v);
check("Writing writeDouble: " + v);
}
@Override
public void writeBytes(String s) throws IOException {
dos.writeBytes(s);
check("Writing writeBytes: " + s);
}
@Override
public void writeChars(String s) throws IOException {
dos.writeChars(s);
check("Writing writeChars: " + s);
}
@Override
public void writeUTF(String s) throws IOException {
dos.writeUTF(s);
check("Writing writeUTF: " + s);
}
/*
public int writeUTF(String str, DataOutput out) throws IOException{
int ret = dos.writeUTF(str, out);
check("Writing writeUTF: " + str);
return ret;
}
* */
}
}// end class ClassData

View File

@ -0,0 +1,522 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import org.openjdk.asmtools.jasm.OpcodeTables.Opcode;
import static org.openjdk.asmtools.jasm.RuntimeConstants.SPLIT_VERIFIER_CFV;
import org.openjdk.asmtools.jasm.Tables.AttrTag;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
class CodeAttr extends AttrData {
/*-------------------------------------------------------- */
/* CodeAttr inner classes */
static public class Local extends Argument {
String name;
boolean defd = false, refd = false;
public Local(String name) {
this.name = name;
}
}
/**
*
*/
static public class Label extends Local {
public Label(String name) {
super(name);
}
}
/**
*
*/
class LocVarData extends Local implements Data {
// arg means slot
short start_pc, length;
ConstantPool.ConstCell name_cpx, sig_cpx;
public LocVarData(String name) {
super(name);
}
@Override
public int getLength() {
return 10;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(start_pc);
out.writeShort(length);
out.writeShort(name_cpx.arg);
out.writeShort(sig_cpx.arg);
out.writeShort(arg);
}
}
/**
*
*/
class LineNumData implements Data {
int start_pc, line_number;
public LineNumData(int start_pc, int line_number) {
this.start_pc = start_pc;
this.line_number = line_number;
}
@Override
public int getLength() {
return 4;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(start_pc);
out.writeShort(line_number);
}
}
/**
*
*/
class Trap extends Local {
int start_pc = Argument.NotSet, end_pc = Argument.NotSet;
int pos;
Trap(int pos, String name) {
super(name);
this.pos = pos;
}
}
/**
*
*/
class TrapData implements Data {
int pos;
Trap trap;
int handler_pc;
Argument catchType;
public TrapData(int pos, Trap trap, int handler_pc, Argument catchType) {
this.pos = pos;
this.trap = trap;
this.handler_pc = handler_pc;
this.catchType = catchType;
}
@Override
public int getLength() {
return 8; // add the length of number of elements
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(trap.start_pc);
out.writeShort(trap.end_pc);
out.writeShort(handler_pc);
if (catchType.isSet()) {
out.writeShort(catchType.arg);
} else {
out.writeShort(0);
}
}
} // end TrapData
/*-------------------------------------------------------- */
/* CodeAttr Fields */
protected MethodData mtd;
protected ClassData cls;
protected Environment env;
protected Argument max_stack, max_locals;
protected Instr zeroInstr, lastInstr;
protected int cur_pc = 0;
protected DataVector<TrapData> trap_table
= new DataVector<>(0); // TrapData
protected DataVectorAttr<LineNumData> lin_num_tb; // LineNumData
protected int lastln = 0;
protected DataVectorAttr<LocVarData> loc_var_tb; // LocVarData
protected DataVector<DataVectorAttr<? extends Data>> attrs;
// protected iVector slots;
protected ArrayList<Integer> slots;
protected HashMap<String, LocVarData> locvarsHash;
protected HashMap<String, Label> labelsHash;
protected HashMap<String, Trap> trapsHash;
protected StackMapData curMapEntry = null;
protected DataVectorAttr<StackMapData> stackMap;
/*-------------------------------------------------------- */
public CodeAttr(MethodData mtd, int pos, int paramcnt, Argument max_stack, Argument max_locals) {
super(mtd.cls, AttrTag.ATT_Code.parsekey());
this.mtd = mtd;
this.cls = mtd.cls;
this.env = cls.env;
this.max_stack = max_stack;
this.max_locals = max_locals;
lastInstr = zeroInstr = new Instr();
trap_table = new DataVector<>(0); // TrapData
attrs = new DataVector<>();
if (env.debugInfoFlag) {
lin_num_tb = new DataVectorAttr<>(cls, AttrTag.ATT_LineNumberTable.parsekey());
attrs.add(lin_num_tb);
}
// slots = new iVector(paramcnt);
slots = new ArrayList<>(paramcnt);
for (int k = 0; k < paramcnt; k++) {
// slots.setElement(1, k);
slots.add(k, 1);
}
}
void endCode() {
checkTraps();
checkLocVars();
checkLabels();
}
/* -------------------------------------- Traps */
Trap trapDecl(int pos, String name) {
Trap local;
if (trapsHash == null) {
trapsHash = new HashMap<>(10);
local = null;
} else {
local = trapsHash.get(name);
}
if (local == null) {
local = new Trap(pos, name);
trapsHash.put(name, local);
}
return local;
}
void beginTrap(int pos, String name) {
Trap trap = trapDecl(pos, name);
if (trap.start_pc != Argument.NotSet) {
env.error("trap.tryredecl", name);
return;
}
trap.start_pc = cur_pc;
}
void endTrap(int pos, String name) {
Trap trap = trapDecl(pos, name);
if (trap.end_pc != Argument.NotSet) {
env.error("trap.endtryredecl", name);
return;
}
trap.end_pc = cur_pc;
}
void trapHandler(int pos, String name, Argument type) {
Trap trap = trapDecl(pos, name);
trap.refd = true;
TrapData trapData = new TrapData(pos, trap, cur_pc, type);
trap_table.addElement(trapData);
}
void checkTraps() {
if (trapsHash == null) {
return;
}
for (Trap trap : trapsHash.values()) {
if (!trap.refd) {
env.error(trap.pos, "warn.trap.notref", trap.name);
}
}
for (TrapData trapData : trap_table) {
Trap trapLabel = trapData.trap;
if (trapLabel.start_pc == Argument.NotSet) {
env.error(trapData.pos, "trap.notry", trapLabel.name);
}
if (trapLabel.end_pc == Argument.NotSet) {
env.error(trapData.pos, "trap.noendtry", trapLabel.name);
}
}
}
/* -------------------------------------- Labels */
Label labelDecl(String name) {
Label local;
if (labelsHash == null) {
labelsHash = new HashMap<>(10);
local = null;
} else {
local = labelsHash.get(name);
}
if (local == null) {
local = new Label(name);
labelsHash.put(name, local);
}
return local;
}
public Label LabelDef(int pos, String name) {
Label label = labelDecl(name);
if (label.defd) {
env.error(pos, "label.redecl", name);
return null;
}
label.defd = true;
label.arg = cur_pc;
return label;
}
public Label LabelRef(String name) {
Label label = labelDecl(name);
label.refd = true;
return label;
}
void checkLabels() {
if (labelsHash == null) {
return;
}
for (Label local : labelsHash.values()) {
// check that every label is defined
if (!local.defd) {
env.error("label.undecl", local.name);
}
}
}
/* -------------------------------------- Variables */
LocVarData locvarDecl(String name) {
LocVarData local;
if (locvarsHash == null) {
locvarsHash = new HashMap<>(10);
local = null;
} else {
local = locvarsHash.get(name);
}
if (local == null) {
local = new LocVarData(name);
locvarsHash.put(name, local);
}
return local;
}
public void LocVarDataDef(int slot) {
// slots.setElement(1, slot);
slots.set(slot, 1);
if ((max_locals != null) && (max_locals.arg < slots.size())) {
// if ((max_locals != null) && (max_locals.arg < slots.length)) {
env.error("warn.illslot", new Integer(slot).toString());
}
}
public void LocVarDataDef(String name, ConstantPool.ConstCell type) {
LocVarData locvar = locvarDecl(name);
if (locvar.defd) {
env.error("locvar.redecl", name);
return;
}
locvar.defd = true;
locvar.start_pc = (short) cur_pc;
locvar.name_cpx = cls.pool.FindCellAsciz(name);
locvar.sig_cpx = type;
int k;
findSlot:
{
/*
for (k = 0; k < slots.length; k++) {
if (slots.data[k] == 0) {
break findSlot;
}
}
k = slots.length;
*
*/
for (k = 0; k < slots.size(); k++) {
if (slots.get(k) == 0) {
break findSlot;
}
}
k = slots.size();
}
LocVarDataDef(k);
locvar.arg = k;
if (loc_var_tb == null) {
loc_var_tb = new DataVectorAttr<>(cls, AttrTag.ATT_LocalVariableTable.parsekey());
attrs.add(loc_var_tb);
}
loc_var_tb.add(locvar);
}
public Argument LocVarDataRef(String name) {
LocVarData locvar = locvarDecl(name);
if (!locvar.defd) {
env.error("locvar.undecl", name);
locvar.defd = true; // to avoid multiple error messages
}
locvar.refd = true;
return locvar;
}
public void LocVarDataEnd(int slot) {
// slots.data[slot] = 0;
slots.set(slot, 0);
}
public void LocVarDataEnd(String name) {
LocVarData locvar = locvarsHash.get(name);
if (locvar == null) {
env.error("locvar.undecl", name);
return;
} else if (!locvar.defd) {
env.error("locvar.undecl", name);
return;
}
locvar.length = (short) (cur_pc - locvar.start_pc);
// slots.data[locvar.arg] = 0;
slots.set(locvar.arg, 0);
// locvarsHash.put(name, null); unfortunately, prohibited
locvarsHash.put(name, new LocVarData(name));
}
void checkLocVars() {
if (locvarsHash == null) {
return;
}
for (LocVarData locvar : locvarsHash.values()) {
if (!locvar.defd) {
continue;
} // this is false locvar
// set end of scope, if not set
if (slots.get(locvar.arg) == 1) {
// if (slots.data[locvar.arg] == 1) {
locvar.length = (short) (cur_pc - locvar.start_pc);
// slots.data[locvar.arg] = 0;
slots.set(locvar.arg, 0);
}
}
}
/* -------------------------------------- StackMap */
public StackMapData getStackMap() {
if (curMapEntry == null) {
curMapEntry = new StackMapData(env);
if (cls.major_version >= SPLIT_VERIFIER_CFV) {
curMapEntry.setIsStackMapTable(true);
}
}
return curMapEntry;
}
/*====================================================== Instr */
void addInstr(int mnenoc_pos, Opcode opcode, Argument arg, Object arg2) {
Instr newInstr = new Instr(cur_pc, cls.env.pos, opcode, arg, arg2);
lastInstr.next = newInstr;
lastInstr = newInstr;
int len = opcode.length();
switch (opcode) {
case opc_tableswitch:
len = ((SwitchTable) arg2).recalcTableSwitch(cur_pc);
break;
case opc_lookupswitch:
len = ((SwitchTable) arg2).calcLookupSwitch(cur_pc);
break;
case opc_ldc:
((ConstantPool.ConstCell) arg).setRank(0);
break;
default:
if (arg instanceof ConstantPool.ConstCell) {
((ConstantPool.ConstCell) arg).setRank(1);
}
}
if (env.debugInfoFlag) {
int ln = env.lineNumber(mnenoc_pos);
if (ln != lastln) { // only one entry in lin_num_tb per line
lin_num_tb.add(new LineNumData(cur_pc, ln));
lastln = ln;
}
}
if (curMapEntry != null) {
curMapEntry.pc = cur_pc;
StackMapData prevStackFrame = null;
if (stackMap == null) {
if (cls.major_version >= SPLIT_VERIFIER_CFV) {
stackMap = new DataVectorAttr<>(cls, AttrTag.ATT_StackMapTable.parsekey());
} else {
stackMap = new DataVectorAttr<>(cls, AttrTag.ATT_StackMap.parsekey());
}
attrs.add(stackMap);
} else if (stackMap.size() > 0) {
prevStackFrame = stackMap.get(stackMap.size() - 1);
}
curMapEntry.setOffset(prevStackFrame);
stackMap.add(curMapEntry);
curMapEntry = null;
}
cur_pc += len;
}
/*====================================================== Attr interface */
// subclasses must redefine this
@Override
public int attrLength() {
return 2 + 2 + 4 // for max_stack, max_locals, and cur_pc
+ cur_pc // + 2+trap_table.size()*8
+ trap_table.getLength() + attrs.getLength();
}
@Override
public void write(CheckedDataOutputStream out)
throws IOException, Parser.CompilerError {
int mxstck = (max_stack != null) ? max_stack.arg : 0;
// int mxloc = (max_locals != null) ? max_locals.arg : slots.length;
int mxloc = (max_locals != null) ? max_locals.arg : slots.size();
super.write(out); // attr name, attr len
out.writeShort(mxstck);
out.writeShort(mxloc);
out.writeInt(cur_pc);
for (Instr instr = zeroInstr.next; instr != null; instr = instr.next) {
instr.write(out, env);
}
trap_table.write(out);
attrs.write(out);
}
} // end CodeAttr

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
/**
* This interface defines constant that are used throughout the compiler. It inherits from
* RuntimeConstants, which is an autogenerated class that contains constants defined in
* the interpreter.
*/
public interface Constants extends RuntimeConstants {
/**
* Default version of class file
*/
public static final short DEFAULT_MAJOR_VERSION = 45;
public static final short DEFAULT_MINOR_VERSION = 3;
/**
* End of input
*/
public static final int EOF = -1;
/*
* Flags
*/
public static final int F_VERBOSE = 1 << 0;
public static final int F_DUMP = 1 << 1;
public static final int F_WARNINGS = 1 << 2;
public static final int F_DEBUG = 1 << 3;
public static final int F_OPTIMIZE = 1 << 4;
public static final int F_DEPENDENCIES = 1 << 5;
/*
* Type codes
*/
public static final int TC_BOOLEAN = 0;
public static final int TC_BYTE = 1;
public static final int TC_CHAR = 2;
public static final int TC_SHORT = 3;
public static final int TC_INT = 4;
public static final int TC_LONG = 5;
public static final int TC_FLOAT = 6;
public static final int TC_DOUBLE = 7;
public static final int TC_NULL = 8;
public static final int TC_ARRAY = 9;
public static final int TC_CLASS = 10;
public static final int TC_VOID = 11;
public static final int TC_METHOD = 12;
public static final int TC_ERROR = 13;
/*
* Type Masks
*/
public static final int TM_NULL = 1 << TC_NULL;
public static final int TM_VOID = 1 << TC_VOID;
public static final int TM_BOOLEAN = 1 << TC_BOOLEAN;
public static final int TM_BYTE = 1 << TC_BYTE;
public static final int TM_CHAR = 1 << TC_CHAR;
public static final int TM_SHORT = 1 << TC_SHORT;
public static final int TM_INT = 1 << TC_INT;
public static final int TM_LONG = 1 << TC_LONG;
public static final int TM_FLOAT = 1 << TC_FLOAT;
public static final int TM_DOUBLE = 1 << TC_DOUBLE;
public static final int TM_ARRAY = 1 << TC_ARRAY;
public static final int TM_CLASS = 1 << TC_CLASS;
public static final int TM_METHOD = 1 << TC_METHOD;
public static final int TM_ERROR = 1 << TC_ERROR;
public static final int TM_INT32 = TM_BYTE | TM_SHORT | TM_CHAR | TM_INT;
public static final int TM_NUM32 = TM_INT32 | TM_FLOAT;
public static final int TM_NUM64 = TM_LONG | TM_DOUBLE;
public static final int TM_INTEGER = TM_INT32 | TM_LONG;
public static final int TM_REAL = TM_FLOAT | TM_DOUBLE;
public static final int TM_NUMBER = TM_INTEGER | TM_REAL;
public static final int TM_REFERENCE = TM_ARRAY | TM_CLASS | TM_NULL;
/*
* Class status
*/
public static final int CS_UNDEFINED = 0;
public static final int CS_UNDECIDED = 1;
public static final int CS_BINARY = 2;
public static final int CS_SOURCE = 3;
public static final int CS_PARSED = 4;
public static final int CS_COMPILED = 5;
public static final int CS_NOTFOUND = 6;
/*
* Attributes
*/
public static final int ATT_ALL = -1;
public static final int ATT_CODE = 1;
/*
* Number of bits used in file offsets
*/
public static final int OFFSETBITS = 19;
public static final int MAXFILESIZE = (1 << OFFSETBITS) - 1;
public static final int MAXLINENUMBER = (1 << (32 - OFFSETBITS)) - 1;
/*
* Operator precedence
*/
/* Who uses this????
public static final int opPrecedence[] = {
10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 12, 13, 14, 15, 16, 17, 18,
18, 19, 19, 19, 19, 19, 20, 20, 20, 21,
21, 22, 22, 22, 23, 24, 24, 24, 24, 24,
24, 25, 25, 26, 26, 26, 26, 26, 26
};
* */
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
/**
*
*/
interface Data {
public void write(CheckedDataOutputStream out) throws IOException;
public int getLength();
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
/**
*
*/
public class DataVector<T extends Data> implements Iterable<T> {
ArrayList<T> elements;
public DataVector(int initSize) {
elements = new ArrayList<>(initSize);
}
public DataVector() {
this(12);
}
public Iterator<T> iterator() {
return elements.iterator();
}
public void add(T element) {
elements.add(element);
}
// full length of the attribute
// declared in Data
public int getLength() {
int length = 0;
// calculate overall size here rather than in add()
// because it may not be available at the time of invoking of add()
for (T element : elements) {
length += element.getLength();
}
return 2 + length; // add the length of number of elements
}
public void write(CheckedDataOutputStream out)
throws IOException {
out.writeShort(elements.size());
writeElements(out);
}
public void writeElements(CheckedDataOutputStream out)
throws IOException {
for (Data element : elements) {
element.write(out);
}
}
/* for compatibility with Vector */
public void addElement(T element) {
elements.add(element);
}
public int size() {
return elements.size();
}
public Data elementAt(int k) {
return elements.get(k);
}
}// end class DataVector

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
/**
*
*/
// public class DataVectorAttr extends AttrData implements Constants {
// }
class DataVectorAttr<T extends Data> extends AttrData implements Iterable<T> {
private ArrayList<T> elements;
private boolean byteIndex;
public DataVectorAttr(ClassData cls, String name, boolean byteIndex, ArrayList<T> initialData) {
super(cls, name);
this.elements = initialData;
this.byteIndex = byteIndex;
}
public DataVectorAttr(ClassData cls, String name, ArrayList<T> initialData) {
this(cls, name, false, initialData);
}
public DataVectorAttr(ClassData cls, String name) {
this(cls, name, false, new ArrayList<T>());
}
public DataVectorAttr(ClassData cls, String name, boolean byteIndex) {
this(cls, name, byteIndex, new ArrayList<T>());
}
public T get(int index) {
return elements.get(index);
}
public void add(T element) {
elements.add(element);
}
public void add(int i, T element) {
elements.add(i, element);
}
public int size() {
return elements.size();
}
@Override
public Iterator<T> iterator() {
return elements.iterator();
}
@Override
public int attrLength() {
int length = 0;
// calculate overall size here rather than in add()
// because it may not be available at the time of invoking of add()
for (T elem : elements) {
length += elem.getLength();
}
// add the length of number of elements
if (byteIndex) {
length += 1;
} else {
length += 2;
}
return length;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
super.write(out); // attr name, attr len
if (byteIndex) {
out.writeByte(elements.size());
} else {
out.writeShort(elements.size());
} // number of elements
for (T elem : elements) {
elem.write(out);
}
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
/**
* DefaultAnnotationAttr
*
* Used to represent Default Annotation Attributes
*
*/
public class DefaultAnnotationAttr extends AttrData {
Data element; // Data
public DefaultAnnotationAttr(ClassData cls, String name, Data element) {
super(cls, name);
this.element = element;
}
public DefaultAnnotationAttr(ClassData cls, String name) {
super(cls, name);
this.element = null;
}
public void add(Data element) {
this.element = element;
}
@Override
public int attrLength() {
return element.getLength(); // add the length of number of elements
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
super.write(out); // attr name, attr len
element.write(out);
}
}// end class DataVectorAttr

View File

@ -0,0 +1,463 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import static org.openjdk.asmtools.jasm.Constants.EOF;
import static org.openjdk.asmtools.jasm.Constants.OFFSETBITS;
import org.openjdk.asmtools.util.I18NResourceBundle;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.text.MessageFormat;
/**
* An input stream for java programs. The stream treats either "\n", "\r" or "\r\n" as the
* end of a line, it always returns \n. It also parses UNICODE characters expressed as
* \uffff. However, if it sees "\\", the second slash cannot begin a unicode sequence. It
* keeps track of the current position in the input stream.
*
* An position consists of: ((linenr &lt;&lt; OFFSETBITS) | offset) this means that both
* the line number and the exact offset into the file are encoded in each position
* value.<p>
*/
public class Environment {
/*-------------------------------------------------------- */
/* Environment Inner Classes */
/**
* A sorted list of error messages
*/
final class ErrorMessage {
int where;
String message;
ErrorMessage next;
/**
* Constructor
*/
ErrorMessage(int where, String message) {
this.where = where;
this.message = message;
}
}
/*-------------------------------------------------------- */
/* Environment Fields */
static boolean traceFlag = false;
boolean debugInfoFlag = false;
private File source;
public PrintStream out;
boolean nowarn;
private byte data[];
private int bytepos;
private int linepos;
public int pos;
/*-------------------------------------------------------- */
public Environment(File source, PrintStream out, boolean nowarn) throws IOException {
this.out = out;
errorFileName = source.getPath();
this.source = source;
this.nowarn = nowarn;
// Read the file
FileInputStream in = new FileInputStream(source);
data = new byte[in.available()];
in.read(data);
in.close();
bytepos = 0;
linepos = 1;
}
public String getErrorFile() {
return errorFileName;
}
public String getSourceName() {
return source.getName();
}
public int lookForward() {
try {
return data[bytepos];
} catch (ArrayIndexOutOfBoundsException e) {
return EOF;
}
}
public int convertUnicode() {
int c;
try {
while ((c = data[bytepos]) == 'u') {
bytepos++;
}
int d = 0;
for (int i = 0; i < 4; i++) {
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
d = (d << 4) + c - '0';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
d = (d << 4) + 10 + c - 'a';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
d = (d << 4) + 10 + c - 'A';
break;
default:
error(pos, "invalid.escape.char");
return d;
}
++bytepos;
c = data[bytepos];
}
return d;
} catch (ArrayIndexOutOfBoundsException e) {
error(pos, "invalid.escape.char");
return EOF;
}
}
public int read() {
int c;
pos = (linepos << OFFSETBITS) | bytepos;
try {
c = data[bytepos];
} catch (ArrayIndexOutOfBoundsException e) {
return EOF;
}
bytepos++;
// parse special characters
switch (c) {
/* case '\\':
if (lookForward() != 'u') {
return '\\';
}
// we have a unicode sequence
return convertUnicode();*/
case '\n':
linepos++;
return '\n';
case '\r':
if (lookForward() == '\n') {
bytepos++;
}
linepos++;
return '\n';
default:
return c;
}
}
public int lineNumber(int lcpos) {
return lcpos >>> OFFSETBITS;
}
public int lineNumber() {
return lineNumber(pos);
}
public int lineOffset(int lcpos) {
return lcpos & ((1 << OFFSETBITS) - 1);
}
public int lineOffset() {
return lineOffset(pos);
}
/*============================================================== Environment */
/**
* The number of errors and warnings
*/
public int nerrors;
public int nwarnings;
public static final I18NResourceBundle i18n
= I18NResourceBundle.getBundleForClass(Main.class);
/**
* Error String
*/
String errorString(String err, Object arg1, Object arg2, Object arg3) {
String str = null;
//str = getProperty(err);
str = i18n.getString(err);
if (str == null) {
return "error message '" + err + "' not found";
}
StringBuffer buf = new StringBuffer();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if ((c == '%') && (i + 1 < str.length())) {
switch (str.charAt(++i)) {
case 's':
String arg = arg1.toString();
for (int j = 0; j < arg.length(); j++) {
switch (c = arg.charAt(j)) {
case ' ':
case '\t':
case '\n':
case '\r':
buf.append((char) c);
break;
default:
if ((c > ' ') && (c <= 255)) {
buf.append((char) c);
} else {
buf.append('\\');
buf.append('u');
buf.append(Integer.toString(c, 16));
}
}
}
arg1 = arg2;
arg2 = arg3;
break;
case '%':
buf.append('%');
break;
default:
buf.append('?');
break;
}
} else {
buf.append((char) c);
}
}
// KTL
// Need to do message format to substitute args
String msg = buf.toString();
MessageFormat form = new MessageFormat(msg);
Object args[] = {arg1, arg2, arg3};
msg = form.format(args);
return msg;
}
/**
* The filename where the last errors have occurred
*/
String errorFileName;
/**
* List of outstanding error messages
*/
ErrorMessage errors;
/**
* Insert an error message in the list of outstanding error messages. The list is
* sorted on input position.
*/
void insertError(int where, String message) {
//output("ERR = " + message);
ErrorMessage msg = new ErrorMessage(where, message);
if (errors == null) {
errors = msg;
} else if (errors.where > where) {
msg.next = errors;
errors = msg;
} else {
ErrorMessage m = errors;
for (; (m.next != null) && (m.next.where <= where); m = m.next);
msg.next = m.next;
m.next = msg;
}
}
/**
* Flush outstanding errors
*/
public void flushErrors() {
if (errors == null) {
traceln("flushErrors: errors == null");
return;
}
// Report the errors
for (ErrorMessage msg = errors; msg != null; msg = msg.next) {
int ln = lineNumber(msg.where);
int off = lineOffset(msg.where);
int i, j;
for (i = off; (i > 0) && (data[i - 1] != '\n') && (data[i - 1] != '\r'); i--);
for (j = off; (j < data.length) && (data[j] != '\n') && (data[j] != '\r'); j++);
String prefix = errorFileName + ":" + ln + ":";
outputln(prefix + " " + msg.message);
outputln(new String(data, i, j - i));
char strdata[] = new char[(off - i) + 1];
for (j = i; j < off; j++) {
strdata[j - i] = (data[j] == '\t') ? '\t' : ' ';
}
strdata[off - i] = '^';
outputln(new String(strdata));
}
errors = null;
}
/**
* Output a string. This can either be an error message or something for debugging.
* This should be used instead of print.
*/
public void output(String msg) {
// try {
int len = msg.length();
for (int i = 0; i < len; i++) {
out.write(msg.charAt(i));
}
// } catch (IOException e) {
// }
}
/**
* Output a string. This can either be an error message or something for debugging.
* This should be used instead of println.
*/
public void outputln(String msg) {
output(msg);
out.write('\n');
}
/**
* Issue an error. source - the input source, usually a file name string offset - the
* offset in the source of the error err - the error number (as defined in this
* interface) arg1 - an optional argument to the error (null if not applicable) arg2 -
* a second optional argument to the error (null if not applicable) arg3 - a third
* optional argument to the error (null if not applicable)
*/
/**
* Issue an error
*/
public void error(int where, String err, Object arg1, Object arg2, Object arg3) {
String msg;
if (err.startsWith("warn.")) {
if (nowarn) {
return;
}
nwarnings++;
msg = "Warning: ";
} else {
err = "err." + err;
nerrors++;
msg = "Error: ";
}
msg = msg + errorString(err, arg1, arg2, arg3);
traceln("error(" + lineNumber(where) + ":" + lineOffset(where) + "):" + msg);
insertError(where, msg);
}
public final void error(int where, String err, Object arg1, Object arg2) {
error(where, err, arg1, arg2, null);
}
public final void error(int where, String err, Object arg1) {
error(where, err, arg1, null, null);
}
public final void error(int where, String err) {
error(where, err, null, null, null);
}
public final void error(String err, Object arg1, Object arg2, Object arg3) {
error(pos, err, arg1, arg2, arg3);
}
public final void error(String err, Object arg1, Object arg2) {
error(pos, err, arg1, arg2, null);
}
public final void error(String err, Object arg1) {
error(pos, err, arg1, null, null);
}
public final void error(String err) {
error(pos, err, null, null, null);
}
public final String errorStr(String err, Object arg1, Object arg2, Object arg3) {
return errorString(err, arg1, arg2, arg3);
}
public final String errorStr(String err, Object arg1, Object arg2) {
return errorStr(err, arg1, arg2, null);
}
public final String errorStr(String err, Object arg1) {
return errorStr(err, arg1, null, null);
}
public final String errorStr(String err) {
return errorStr(err, null, null, null);
}
/*============================================================== trace */
public boolean isTraceEnabled() {
return traceFlag;
}
public boolean isDebugEnabled() {
return debugInfoFlag;
}
void trace(String message) {
if (traceFlag) {
output(message);
}
}
void traceln(String message) {
if (traceFlag) {
outputln(message);
}
}
} // end Environment

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import org.openjdk.asmtools.jasm.Tables.AttrTag;
import java.io.IOException;
/**
*
*/
class FieldData extends MemberData {
/*-------------------------------------------------------- */
/* FieldData Fields */
protected ConstantPool.ConstValue_Pair nape;
private AttrData initValue;
/*-------------------------------------------------------- */
public FieldData(ClassData cls, int acc, ConstantPool.ConstValue_Pair nape) {
super(cls, acc);
this.nape = nape;
if (Modifiers.hasPseudoMod(acc)) {
createPseudoMod();
}
}
public void SetValue(Argument value_cpx) {
initValue = new CPXAttr(cls, AttrTag.ATT_ConstantValue.parsekey(),
value_cpx);
}
public void write(CheckedDataOutputStream out) throws IOException, Parser.CompilerError {
out.writeShort(access);
out.writeShort(nape.left.arg);
out.writeShort(nape.right.arg);
DataVector attrs = new DataVector();
if (initValue != null) {
attrs.add(initValue);
}
if (syntheticAttr != null) {
attrs.add(syntheticAttr);
}
if (deprecatedAttr != null) {
attrs.add(deprecatedAttr);
}
if (annotAttrVis != null) {
attrs.add(annotAttrVis);
}
if (annotAttrInv != null) {
attrs.add(annotAttrInv);
}
if (type_annotAttrVis != null) {
attrs.add(type_annotAttrVis);
}
if (type_annotAttrInv != null) {
attrs.add(type_annotAttrInv);
}
attrs.write(out);
}
} // end FieldData

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
/**
*
*/
class InnerClassData implements Data {
int access;
ConstantPool.ConstCell name, innerClass, outerClass;
public InnerClassData(int access, ConstantPool.ConstCell name, ConstantPool.ConstCell innerClass, ConstantPool.ConstCell outerClass) {
this.access = access;
this.name = name;
this.innerClass = innerClass;
this.outerClass = outerClass;
}
@Override
public int getLength() {
return 8;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(innerClass.arg);
if (outerClass.isSet()) {
out.writeShort(outerClass.arg);
} else {
out.writeShort(0);
}
if (name.isSet()) {
out.writeShort(name.arg);
} else {
out.writeShort(0);
}
out.writeShort(access);
}
}// end class InnerClassData

View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
import static org.openjdk.asmtools.jasm.OpcodeTables.*;
/**
*
*/
class Instr {
Instr next = null;
int pc;
int pos;
Opcode opc;
Argument arg;
Object arg2; // second or unusual argument
public Instr(int pc, int pos, Opcode opc, Argument arg, Object arg2) {
this.pc = pc;
this.pos = pos;
this.opc = opc;
this.arg = arg;
this.arg2 = arg2;
}
public Instr() {
}
public void write(CheckedDataOutputStream out, Environment env) throws IOException {
OpcodeType type = opc.type();
switch (type) {
case NORMAL: {
if (opc == Opcode.opc_bytecode) {
out.writeByte(arg.arg);
return;
}
out.writeByte(opc.value());
int opcLen = opc.length();
if (opcLen == 1) {
return;
}
switch (opc) {
case opc_tableswitch:
((SwitchTable) arg2).writeTableSwitch(out);
return;
case opc_lookupswitch:
((SwitchTable) arg2).writeLookupSwitch(out);
return;
}
int iarg;
try {
iarg = arg.arg;
} catch (NullPointerException e) {
throw new Parser.CompilerError(env.errorStr("comperr.instr.nullarg", opc.parsekey()));
}
//env.traceln("instr:"+opcNamesTab[opc]+" len="+opcLen+" arg:"+iarg);
switch (opc) {
case opc_jsr:
case opc_goto:
case opc_ifeq:
case opc_ifge:
case opc_ifgt:
case opc_ifle:
case opc_iflt:
case opc_ifne:
case opc_if_icmpeq:
case opc_if_icmpne:
case opc_if_icmpge:
case opc_if_icmpgt:
case opc_if_icmple:
case opc_if_icmplt:
case opc_if_acmpeq:
case opc_if_acmpne:
case opc_ifnull:
case opc_ifnonnull:
case opc_jsr_w:
case opc_goto_w:
iarg = iarg - pc;
break;
case opc_iinc:
iarg = (iarg << 8) | (((Argument) arg2).arg & 0xFF);
break;
case opc_invokeinterface:
iarg = ((iarg << 8) | (((Argument) arg2).arg & 0xFF)) << 8;
break;
case opc_invokedynamic: // JSR-292
iarg = (iarg << 16);
break;
case opc_ldc:
if ((iarg & 0xFFFFFF00) != 0) {
throw new Parser.CompilerError(
env.errorStr("comperr.instr.arglong", opc.parsekey(), iarg));
}
break;
}
switch (opcLen) {
case 1:
return;
case 2:
out.writeByte(iarg);
return;
case 3:
out.writeShort(iarg);
return;
case 4: // opc_multianewarray only
out.writeShort(iarg);
iarg = ((Argument) arg2).arg;
out.writeByte(iarg);
return;
case 5:
out.writeInt(iarg);
return;
default:
throw new Parser.CompilerError(
env.errorStr("comperr.instr.opclen", opc.parsekey()));
}
}
case WIDE:
out.writeByte(Opcode.opc_wide.value());
out.writeByte(opc.value() & 0xFF);
out.writeShort(arg.arg);
if (opc == Opcode.opc_iinc_w) {
out.writeShort(((Argument) arg2).arg);
}
return;
case PRIVELEGED:
case NONPRIVELEGED:
out.writeByte(opc.value() >> 8);
out.writeByte(opc.value() & 0xFF);
return;
default:
throw new Parser.CompilerError(
env.errorStr("comperr.instr.opclen", opc.parsekey()));
} // end writeSpecCode
}
} // end Instr

View File

@ -0,0 +1,505 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.util.HashMap;
/**
*
* JasmTokens
*
* This class contains tokens specific to parsing JASM syntax.
*
* The classes in JasmTokens are following a Singleton Pattern. These classes are Enums,
* and they are contained in private hash maps (lookup tables and reverse lookup tables).
* These hash maps all have public accessors, which clients use to look-up enums.
*
* Tokens in this table carry no external state, and are typically treated as constants.
* They do not need to be reset.
*/
public class JasmTokens {
/*-------------------------------------------------------- */
/* Marker: describes the type of Keyword */
static public enum KeywordType {
TOKEN (0, "TOKEN"),
VALUE (1, "VALUE"),
JASMIDENTIFIER (2, "JASM"),
KEYWORD (3, "KEYWORD");
private final Integer value;
private final String printval;
KeywordType(Integer val, String print) {
value = val;
printval = print;
}
public String printval() {
return printval;
}
}
/*-------------------------------------------------------- */
/* Marker - describes the type of token */
/* this is rather cosmetic, no function currently. */
static public enum TokenType {
MODIFIER (0, "Modifier"),
OPERATOR (1, "Operator"),
VALUE (2, "Value"),
TYPE (3, "Type"),
EXPRESSION (4, "Expression"),
STATEMENT (5, "Statement"),
DECLARATION (6, "Declaration"),
PUNCTUATION (7, "Punctuation"),
SPECIAL (8, "Special"),
JASM (9, "Jasm"),
MISC (10, "Misc");
private final Integer value;
private final String printval;
TokenType(Integer val, String print) {
value = val;
printval = print;
}
public String printval() {
return printval;
}
}
/*-------------------------------------------------------- */
/**
* Scanner Tokens (Definitive List)
*/
static public enum Token {
EOF (-1, "EOF", "EOF", TokenType.MISC),
COMMA (0, "COMMA", ",", TokenType.OPERATOR),
ASSIGN (1, "ASSIGN", "=", TokenType.OPERATOR),
ASGMUL (2, "ASGMUL", "*=", TokenType.OPERATOR),
ASGDIV (3, "ASGDIV", "/=", TokenType.OPERATOR),
ASGREM (4, "ASGREM", "%=", TokenType.OPERATOR),
ASGADD (5, "ASGADD", "+=", TokenType.OPERATOR),
ASGSUB (6, "ASGSUB", "-=", TokenType.OPERATOR),
ASGLSHIFT (7, "ASGLSHIFT", "<<=", TokenType.OPERATOR),
ASGRSHIFT (8, "ASGRSHIFT", ">>=", TokenType.OPERATOR),
ASGURSHIFT (9, "ASGURSHIFT", "<<<=", TokenType.OPERATOR),
ASGBITAND (10, "ASGBITAND", "&=", TokenType.OPERATOR),
ASGBITOR (11, "ASGBITOR", "|=", TokenType.OPERATOR),
ASGBITXOR (12, "ASGBITXOR", "^=", TokenType.OPERATOR),
COND (13, "COND", "?:", TokenType.OPERATOR),
OR (14, "OR", "||", TokenType.OPERATOR),
AND (15, "AND", "&&", TokenType.OPERATOR),
BITOR (16, "BITOR", "|", TokenType.OPERATOR),
BITXOR (17, "BITXOR", "^", TokenType.OPERATOR),
BITAND (18, "BITAND", "&", TokenType.OPERATOR),
NE (19, "NE", "!=", TokenType.OPERATOR),
EQ (20, "EQ", "==", TokenType.OPERATOR),
GE (21, "GE", ">=", TokenType.OPERATOR),
GT (22, "GT", ">", TokenType.OPERATOR),
LE (23, "LE", "<=", TokenType.OPERATOR),
LT (24, "LT", "<", TokenType.OPERATOR),
INSTANCEOF (25, "INSTANCEOF", "instanceof", TokenType.OPERATOR),
LSHIFT (26, "LSHIFT", "<<", TokenType.OPERATOR),
RSHIFT (27, "RSHIFT", ">>", TokenType.OPERATOR),
URSHIFT (28, "URSHIFT", "<<<", TokenType.OPERATOR),
ADD (29, "ADD", "+", TokenType.OPERATOR),
SUB (30, "SUB", "-", TokenType.OPERATOR),
DIV (31, "DIV", "/", TokenType.OPERATOR),
REM (32, "REM", "%", TokenType.OPERATOR),
MUL (33, "MUL", "*", TokenType.OPERATOR),
CAST (34, "CAST", "cast", TokenType.OPERATOR),
POS (35, "POS", "+", TokenType.OPERATOR),
NEG (36, "NEG", "-", TokenType.OPERATOR),
NOT (37, "NOT", "!", TokenType.OPERATOR),
BITNOT (38, "BITNOT", "~", TokenType.OPERATOR),
PREINC (39, "PREINC", "++", TokenType.OPERATOR),
PREDEC (40, "PREDEC", "--", TokenType.OPERATOR),
NEWARRAY (41, "NEWARRAY", "new", TokenType.OPERATOR),
NEWINSTANCE (42, "NEWINSTANCE", "new", TokenType.OPERATOR),
NEWFROMNAME (43, "NEWFROMNAME", "new", TokenType.OPERATOR),
POSTINC (44, "POSTINC", "++", TokenType.OPERATOR),
POSTDEC (45, "POSTDEC", "--", TokenType.OPERATOR),
FIELD (46, "FIELD", "field", TokenType.OPERATOR),
METHOD (47, "METHOD", "method", TokenType.OPERATOR),
ARRAYACCESS (48, "ARRAYACCESS", "[]", TokenType.OPERATOR),
NEW (49, "NEW", "new", TokenType.OPERATOR),
INC (50, "INC", "++", TokenType.OPERATOR),
DEC (51, "DEC", "--", TokenType.OPERATOR),
CONVERT (55, "CONVERT", "convert", TokenType.OPERATOR),
EXPR (56, "EXPR", "expr", TokenType.OPERATOR),
ARRAY (57, "ARRAY", "array", TokenType.OPERATOR),
GOTO (58, "GOTO", "goto", TokenType.OPERATOR),
/*
* Value tokens
*/
IDENT (60, "IDENT", "Identifier", TokenType.VALUE, KeywordType.VALUE, true),
BOOLEANVAL (61, "BOOLEANVAL", "Boolean", TokenType.VALUE, KeywordType.VALUE),
BYTEVAL (62, "BYTEVAL", "Byte", TokenType.VALUE),
CHARVAL (63, "CHARVAL", "Char", TokenType.VALUE),
SHORTVAL (64, "SHORTVAL", "Short", TokenType.VALUE),
INTVAL (65, "INTVAL", "Integer", TokenType.VALUE, KeywordType.VALUE),
LONGVAL (66, "LONGVAL", "Long", TokenType.VALUE, KeywordType.VALUE),
FLOATVAL (67, "FLOATVAL", "Float", TokenType.VALUE, KeywordType.VALUE),
DOUBLEVAL (68, "DOUBLEVAL", "Double", TokenType.VALUE, KeywordType.VALUE),
STRINGVAL (69, "STRINGVAL", "String", TokenType.VALUE, KeywordType.VALUE),
/*
* Type keywords
*/
BYTE (70, "BYTE", "byte", TokenType.TYPE),
CHAR (71, "CHAR", "char", TokenType.TYPE),
SHORT (72, "SHORT", "short", TokenType.TYPE),
INT (73, "INT", "int", TokenType.TYPE),
LONG (74, "LONG", "long", TokenType.TYPE),
FLOAT (75, "FLOAT", "float", TokenType.TYPE),
DOUBLE (76, "DOUBLE", "double", TokenType.TYPE),
VOID (77, "VOID", "void", TokenType.TYPE),
BOOLEAN (78, "BOOLEAN", "boolean", TokenType.TYPE),
/*
* Expression keywords
*/
TRUE (80, "TRUE", "true", TokenType.EXPRESSION),
FALSE (81, "FALSE", "false", TokenType.EXPRESSION),
THIS (82, "THIS", "this", TokenType.EXPRESSION),
SUPER (83, "SUPER", "super", TokenType.MODIFIER, KeywordType.KEYWORD),
NULL (84, "NULL", "null", TokenType.EXPRESSION),
/*
* Statement keywords
*/
IF (90, "IF", "if", TokenType.STATEMENT),
ELSE (91, "ELSE", "else", TokenType.STATEMENT),
FOR (92, "FOR", "for", TokenType.STATEMENT),
WHILE (93, "WHILE", "while", TokenType.STATEMENT),
DO (94, "DO", "do", TokenType.STATEMENT),
SWITCH (95, "SWITCH", "switch", TokenType.STATEMENT),
CASE (96, "CASE", "case", TokenType.STATEMENT),
DEFAULT (97, "DEFAULT", "default", TokenType.STATEMENT, KeywordType.KEYWORD),
BREAK (98, "BREAK", "break", TokenType.STATEMENT),
CONTINUE (99, "CONTINUE", "continue", TokenType.STATEMENT),
RETURN (100, "RETURN", "return", TokenType.STATEMENT),
TRY (101, "TRY", "try", TokenType.STATEMENT),
CATCH (102, "CATCH", "catch", TokenType.STATEMENT),
FINALLY (103, "FINALLY", "finally", TokenType.STATEMENT),
THROW (104, "THROW", "throw", TokenType.STATEMENT),
STAT (105, "STAT", "stat", TokenType.STATEMENT),
EXPRESSION (106, "EXPRESSION", "expression", TokenType.STATEMENT),
DECLARATION (107, "DECLARATION", "declaration", TokenType.STATEMENT),
VARDECLARATION (108, "VARDECLARATION", "vdeclaration", TokenType.STATEMENT),
/*
* Declaration keywords
*/
IMPORT (110, "IMPORT", "import", TokenType.DECLARATION),
CLASS (111, "CLASS", "class", TokenType.DECLARATION, KeywordType.KEYWORD),
EXTENDS (112, "EXTENDS", "extends", TokenType.DECLARATION, KeywordType.KEYWORD),
IMPLEMENTS (113, "IMPLEMENTS", "implements", TokenType.DECLARATION, KeywordType.KEYWORD),
INTERFACE (114, "INTERFACE", "interface", TokenType.DECLARATION, KeywordType.KEYWORD),
PACKAGE (115, "PACKAGE", "package", TokenType.DECLARATION, KeywordType.KEYWORD),
ENUM (116, "ENUM", "enum", TokenType.DECLARATION, KeywordType.KEYWORD),
MANDATED (117, "MANDATED", "mandated", TokenType.DECLARATION, KeywordType.KEYWORD),
/*
* Modifier keywords
*/
PRIVATE (120, "PRIVATE", "private", TokenType.MODIFIER, KeywordType.KEYWORD),
PUBLIC (121, "PUBLIC", "public", TokenType.MODIFIER, KeywordType.KEYWORD),
PROTECTED (122, "PROTECTED", "protected", TokenType.MODIFIER, KeywordType.KEYWORD),
CONST (123, "CONST", "const", TokenType.DECLARATION, KeywordType.KEYWORD),
STATIC (124, "STATIC", "static", TokenType.MODIFIER, KeywordType.KEYWORD),
TRANSIENT (125, "TRANSIENT", "transient", TokenType.MODIFIER, KeywordType.KEYWORD),
SYNCHRONIZED (126, "SYNCHRONIZED", "synchronized", TokenType.MODIFIER, KeywordType.KEYWORD),
NATIVE (127, "NATIVE", "native", TokenType.MODIFIER, KeywordType.KEYWORD),
FINAL (128, "FINAL", "final", TokenType.MODIFIER, KeywordType.KEYWORD),
VOLATILE (129, "VOLATILE", "volatile", TokenType.MODIFIER, KeywordType.KEYWORD),
ABSTRACT (130, "ABSTRACT", "abstract", TokenType.MODIFIER, KeywordType.KEYWORD),
/*
* Punctuation
*/
SEMICOLON (135, "SEMICOLON", ";", TokenType.PUNCTUATION, KeywordType.VALUE),
COLON (136, "COLON", ":", TokenType.PUNCTUATION, KeywordType.VALUE),
QUESTIONMARK (137, "QUESTIONMARK", "?", TokenType.PUNCTUATION),
LBRACE (138, "LBRACE", "{", TokenType.PUNCTUATION, KeywordType.VALUE),
RBRACE (139, "RBRACE", "}", TokenType.PUNCTUATION, KeywordType.VALUE),
LPAREN (140, "LPAREN", "(", TokenType.PUNCTUATION),
RPAREN (141, "RPAREN", ")", TokenType.PUNCTUATION),
LSQBRACKET (142, "LSQBRACKET", "[", TokenType.PUNCTUATION),
RSQBRACKET (143, "RSQBRACKET", "]", TokenType.PUNCTUATION),
THROWS (144, "THROWS", "throws", TokenType.DECLARATION, KeywordType.KEYWORD),
/*
* Special tokens
*/
ERROR (145, "ERROR", "error", TokenType.MODIFIER),
COMMENT (146, "COMMENT", "comment", TokenType.MODIFIER),
TYPE (147, "TYPE", "type", TokenType.MODIFIER),
LENGTH (148, "LENGTH", "length", TokenType.DECLARATION),
INLINERETURN (149, "INLINERETURN", "inline-return", TokenType.MODIFIER),
INLINEMETHOD (150, "INLINEMETHOD", "inline-method", TokenType.MODIFIER),
INLINENEWINSTANCE (151, "INLINENEWINSTANCE", "inline-new", TokenType.MODIFIER),
/*
* Added for jasm
*/
METHODREF (152, "METHODREF", "Method", TokenType.DECLARATION, KeywordType.KEYWORD, true),
FIELDREF (153, "FIELD", "Field", TokenType.DECLARATION, KeywordType.KEYWORD, true),
STACK (154, "STACK", "stack", TokenType.DECLARATION, KeywordType.KEYWORD, true),
LOCAL (155, "LOCAL", "locals", TokenType.DECLARATION, KeywordType.KEYWORD, true),
CPINDEX (156, "CPINDEX", "CPINDEX", TokenType.DECLARATION, true),
CPNAME (157, "CPNAME", "CPName", TokenType.DECLARATION, true),
SIGN (158, "SIGN", "SIGN", TokenType.DECLARATION, true),
BITS (159, "BITS", "bits", TokenType.MISC, KeywordType.KEYWORD, true),
INF (160, "INF", "Inf", "Infinity", TokenType.MISC, KeywordType.KEYWORD),
NAN (161, "NAN", "NaN", TokenType.MISC, KeywordType.KEYWORD, true),
INNERCLASS (162, "INNERCLASS", "InnerClass", TokenType.DECLARATION, KeywordType.KEYWORD, true),
OF (163, "OF", "of", TokenType.DECLARATION, KeywordType.KEYWORD, true),
SYNTHETIC (164, "SYNTHETIC", "synthetic", TokenType.MODIFIER, KeywordType.KEYWORD, true),
STRICT (165, "STRICT", "strict", TokenType.MODIFIER, KeywordType.KEYWORD, true),
DEPRECATED (166, "DEPRECATED", "deprecated", TokenType.MODIFIER, KeywordType.KEYWORD, true),
VERSION (167, "VERSION", "version", TokenType.DECLARATION, KeywordType.KEYWORD, true),
MODULE (168, "MODULE", "module", TokenType.DECLARATION, KeywordType.KEYWORD),
ANNOTATION (169, "ANNOTATION", "@", TokenType.MISC),
PARAM_NAME (173, "PARAM_NAME", "#", TokenType.MISC),
VARARGS (170, "VARARGS", "varargs", TokenType.MODIFIER, KeywordType.KEYWORD),
BRIDGE (171, "BRIDGE", "bridge", TokenType.MODIFIER, KeywordType.KEYWORD),
// Declaration keywords
BOOTSTRAPMETHOD (172, "BOOTSTRAPMETHOD", "BootstrapMethod", TokenType.DECLARATION, KeywordType.KEYWORD, true);
// Misc Keywords
private Integer value;
private String printval;
private String alias;
private TokenType tok_type;
private KeywordType key_type;
private String parsekey;
private boolean possible_jasm_identifier;
// By default, if a KeywordType is not specified, it has the value 'TOKEN'
Token(Integer val, String print, String op, TokenType ttype) {
init(val, print, op, null, ttype, KeywordType.TOKEN, false);
}
Token(Integer val, String print, String op, TokenType ttype, boolean ident) {
init(val, print, op, null, ttype, KeywordType.TOKEN, ident);
}
Token(Integer val, String print, String op, String als, TokenType ttype) {
init(val, print, op, als, ttype, KeywordType.TOKEN, false);
}
Token(Integer val, String print, String op, TokenType ttype, KeywordType ktype) {
init(val, print, op, null, ttype, ktype, false);
}
Token(Integer val, String print, String op, TokenType ttype, KeywordType ktype, boolean ident) {
init(val, print, op, null, ttype, ktype, ident);
}
Token(Integer val, String print, String op, String als, TokenType ttype, KeywordType ktype) {
init(val, print, op, als, ttype, ktype, false);
}
private void init(Integer val, String print, String op, String als, TokenType ttype, KeywordType ktype, boolean ident) {
value = val;
printval = print;
parsekey = op;
tok_type = ttype;
key_type = ktype;
alias = als;
possible_jasm_identifier = ident;
}
public String printval() {
return printval;
}
public String parsekey() {
return parsekey;
}
public int value() {
return value;
}
public boolean possibleJasmIdentifier() {
return possible_jasm_identifier;
}
@Override
public String toString() {
return "<" + printval + "> [" + value + "]";
}
}
/**
* Initialized keyword and token Hash Maps (and Reverse Tables)
*/
static protected final int MaxTokens = 172;
private static HashMap<Integer, Token> TagToTokens = new HashMap<>(MaxTokens);
private static HashMap<String, Token> SymbolToTokens = new HashMap<>(MaxTokens);
private static HashMap<String, Token> ParsekeyToTokens = new HashMap<>(MaxTokens);
static protected final int MaxValTokens = 12;
private static HashMap<Integer, Token> TagToValTokens = new HashMap<>(MaxValTokens);
private static HashMap<String, Token> SymbolToValTokens = new HashMap<>(MaxValTokens);
private static HashMap<String, Token> ParsekeyToValTokens = new HashMap<>(MaxValTokens);
private static HashMap<Integer, Token> PossibleJasmIdentifiers = new HashMap<>(MaxValTokens);
static protected final int MaxKeywords = 40;
private static HashMap<Integer, Token> TagToKeywords = new HashMap<>(MaxKeywords);
private static HashMap<String, Token> SymbolToKeywords = new HashMap<>(MaxKeywords);
private static HashMap<String, Token> ParsekeyToKeywords = new HashMap<>(MaxKeywords);
static {
// register all of the tokens
for (Token tk : Token.values()) {
registerToken(tk);
}
}
private static void registerToken(Token tk) {
// Tag is a keyword
if (tk.key_type == KeywordType.KEYWORD) {
TagToKeywords.put(tk.value, tk);
if (tk.alias != null) {
ParsekeyToKeywords.put(tk.alias, tk);
}
SymbolToKeywords.put(tk.printval, tk);
if (tk.parsekey != null) {
ParsekeyToKeywords.put(tk.parsekey, tk);
}
}
// Values (and Keywords) go on the Val tokens list
if (tk.key_type == KeywordType.KEYWORD
|| tk.key_type == KeywordType.VALUE) {
TagToValTokens.put(tk.value, tk);
SymbolToValTokens.put(tk.printval, tk);
if (tk.alias != null) {
SymbolToValTokens.put(tk.alias, tk);
}
if (tk.parsekey != null) {
ParsekeyToValTokens.put(tk.parsekey, tk);
}
}
// make the list of 'possible jasm identifiers'
if (tk.possible_jasm_identifier) {
PossibleJasmIdentifiers.put(tk.value(), tk);
}
// Finally, register all tokens
TagToTokens.put(tk.value, tk);
SymbolToTokens.put(tk.printval, tk);
ParsekeyToTokens.put(tk.printval, tk);
}
/* Token accessors */
public static Token token(int tk) {
return TagToTokens.get(tk);
}
public static Token val_token(int tk) {
return TagToValTokens.get(tk);
}
public static Token keyword_token(int tk) {
return TagToKeywords.get(tk);
}
public static Token possibleJasmIdentifiers(int token) {
return PossibleJasmIdentifiers.get(token);
}
/* Reverse lookup accessors */
public static Token token(String parsekey) {
return ParsekeyToTokens.get(parsekey);
}
public static Token val_token(String parsekey) {
return ParsekeyToValTokens.get(parsekey);
}
public static Token keyword_token(String parsekey) {
return ParsekeyToKeywords.get(parsekey);
}
/* Reverse lookup by ID accessors */
public static Token token_ID(String ID) {
return ParsekeyToTokens.get(ID);
}
public static Token val_token_ID(String ID) {
return ParsekeyToValTokens.get(ID);
}
public static Token keyword_token_ID(String ID) {
return ParsekeyToKeywords.get(ID);
}
public static String keywordName(int token) {
String retval = null;
Token tk = keyword_token(token);
if (tk != null) {
retval = tk.parsekey;
}
return retval;
}
public static int val_token_int(String idValue) {
Token kwd = val_token(idValue);
int retval = Token.IDENT.value;
if (kwd != null) {
retval = kwd.value;
}
return retval;
}
public static Token keyword_token_ident(String idValue) {
Token kwd = keyword_token(idValue);
if (kwd == null) {
kwd = Token.IDENT;
}
return kwd;
}
public static int keyword_token_int(String idValue) {
return keyword_token_ident(idValue).value();
}
}

View File

@ -0,0 +1,343 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import static org.openjdk.asmtools.jasm.Constants.DEFAULT_MAJOR_VERSION;
import static org.openjdk.asmtools.jasm.Constants.DEFAULT_MINOR_VERSION;
import org.openjdk.asmtools.util.I18NResourceBundle;
import org.openjdk.asmtools.util.ProductInfo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
/**
*
*
*/
public class Main {
/**
* Name of the program.
*/
String program;
/**
* The stream where error message are printed.
*/
PrintStream out;
int nerrors = 0;
public static final I18NResourceBundle i18n
= I18NResourceBundle.getBundleForClass(Main.class);
private File destDir = null;
private boolean traceFlag = false;
private boolean debugInfoFlag = false;
private long tm = System.currentTimeMillis();
private ArrayList<String> v = new ArrayList<>();
private boolean nowrite = false;
private boolean nowarn = false;
private boolean strict = false;
private String props = null;
private int nwarnings = 0;
private short major_version = DEFAULT_MAJOR_VERSION;
private short minor_version = DEFAULT_MINOR_VERSION;
private int bytelimit = 0;
private boolean debugScanner = false;
private boolean debugMembers = false;
private boolean debugCP = false;
private boolean debugAnnot = false;
private boolean debugInstr = false;
/**
* Constructor.
*/
public Main(PrintStream out, String program) {
this.out = out;
this.program = program;
}
/**
* Top level error message
*/
public void error(String msg) {
nerrors++;
out.println(program + ": " + msg);
}
/**
* Usage
*/
public void usage() {
out.println(i18n.getString("jasm.usage"));
out.println(i18n.getString("jasm.opt.d"));
out.println(i18n.getString("jasm.opt.g"));
out.println(i18n.getString("jasm.opt.v"));
out.println(i18n.getString("jasm.opt.nowrite"));
out.println(i18n.getString("jasm.opt.nowarn"));
out.println(i18n.getString("jasm.opt.strict"));
out.println(i18n.getString("jasm.opt.cv", DEFAULT_MAJOR_VERSION, DEFAULT_MINOR_VERSION));
out.println(i18n.getString("jasm.opt.version"));
}
/**
* Run the compiler
*/
private synchronized boolean parseArgs(String argv[]) {
// Parse arguments
for (int i = 0; i < argv.length; i++) {
String arg = argv[i];
switch (arg) {
case "-v":
traceFlag = true;
break;
case "-g":
debugInfoFlag = true;
break;
case "-nowrite":
nowrite = true;
break;
case "-strict":
strict = true;
break;
case "-nowarn":
nowarn = true;
break;
case "-version":
out.println(ProductInfo.FULL_VERSION);
break;
case "-d":
if ((i + 1) >= argv.length) {
error(i18n.getString("jasm.error.d_requires_argument"));
usage();
return false;
}
destDir = new File(argv[++i]);
if (!destDir.exists()) {
error(i18n.getString("jasm.error.does_not_exist", destDir.getPath()));
return false;
}
break;
// non-public options
case "-XdScanner":
debugScanner = true;
break;
case "-XdMember":
debugMembers = true;
break;
case "-XdCP":
debugCP = true;
break;
case "-XdInstr":
debugInstr = true;
break;
case "-XdAnnot":
debugAnnot = true;
break;
case "-XdAll":
debugScanner = true;
debugMembers = true;
debugCP = true;
debugInstr = true;
debugAnnot = true;
break;
case "-Xdlimit":
// parses file until the specified byte number
if (i + 1 > argv.length) {
out.println(" Error: Unspecified byte-limit");
return false;
} else {
i++;
String bytelimstr = argv[i];
bytelimit = 0;
try {
bytelimit = Integer.parseInt(bytelimstr);
} catch (NumberFormatException e) {
out.println(" Error: Unspecified byte-limit");
return false;
}
}
break;
case "-cv":
if ((i + 1) >= argv.length) {
error(i18n.getString("jasm.error.cv_requires_arg"));
usage();
return false;
}
String[] versions = {"", ""}; // workaround for String.split()
int index = argv[++i].indexOf("."); //
if (index != -1) { //
versions[0] = argv[i].substring(0, index); //
versions[1] = argv[i].substring(index + 1); //
} //
if (versions.length != 2) {
error(i18n.getString("jasm.error.invalid_major_minor_param"));
usage();
return false;
}
try {
major_version = Short.parseShort(versions[0]);
minor_version = Short.parseShort(versions[1]);
} catch (NumberFormatException e) {
error(i18n.getString("jasm.error.invalid_major_minor_param"));
usage();
return false;
}
break;
default:
if (arg.startsWith("-")) {
error(i18n.getString("jasm.error.invalid_option", arg));
usage();
return false;
} else {
v.add(argv[i]);
}
break;
}
}
if (v.size() == 0) {
usage();
return false;
}
if (strict) {
nowarn = false;
}
return true;
}
private void reset() {
destDir = null;
traceFlag = false;
debugInfoFlag = false;
System.currentTimeMillis();
v = new ArrayList<>();
nowrite = false;
nowarn = false;
strict = false;
props = null;
nwarnings = 0;
major_version = DEFAULT_MAJOR_VERSION;
minor_version = DEFAULT_MINOR_VERSION;
bytelimit = 0;
}
/**
* Run the compiler
*/
public synchronized boolean compile(String argv[]) {
// Reset the state of all objs
reset();
boolean validArgs = parseArgs(argv);
if (!validArgs) {
return false;
}
// compile all input files
Environment sf = null;
try {
for (String inpname : v) {
Parser p;
try {
sf = new Environment(new File(inpname), out, nowarn);
sf.traceFlag = traceFlag;
sf.debugInfoFlag = debugInfoFlag;
p = new Parser(sf, major_version, minor_version);
p.setDebugFlags(debugScanner, debugMembers, debugCP, debugAnnot, debugInstr);
p.parseFile();
} catch (FileNotFoundException ex) {
error(i18n.getString("jasm.error.cannot_read", inpname));
continue;
}
nerrors += sf.nerrors;
nwarnings += sf.nwarnings;
if (nowrite || (nerrors > 0)) {
sf.flushErrors();
continue;
}
try {
ClassData[] clsData = p.getClassesData();
for (int i = 0; i < clsData.length; i++) {
ClassData cd = clsData[i];
if (bytelimit > 0) {
cd.setByteLimit(bytelimit);
}
cd.write(destDir);
}
} catch (IOException ex) {
if (bytelimit > 0) {
// IO Error thrown from user-specified byte ount
ex.printStackTrace();
error("UserSpecified byte-limit at byte[" + bytelimit + "]: " + ex.getMessage() + "\n" + sf.getErrorFile() + ": [" + sf.lineNumber() + ", " + sf.lineOffset() + "]");
} else {
String er = i18n.getString("jasm.error.cannot_write", ex.getMessage());
error(er + "\n" + sf.getErrorFile() + ": [" + sf.lineNumber() + ", " + sf.lineOffset() + "]");
}
}
sf.flushErrors(); // possible errors from write()
}
} catch (Error ee) {
if (debugInfoFlag) {
ee.printStackTrace();
}
String er = ee.getMessage() + "\n" + i18n.getString("jasm.error.fatal_error");
error(er + "\n" + sf.getErrorFile() + ": [" + sf.lineNumber() + ", " + sf.lineOffset() + "]");
} catch (Exception ee) {
if (debugInfoFlag) {
ee.printStackTrace();
}
String er = ee.getMessage() + "\n" + ee.getMessage() + "\n" + i18n.getString("jasm.error.fatal_exception");
error(er + "\n" + sf.getErrorFile() + ": [" + sf.lineNumber() + ", " + sf.lineOffset() + "]");
}
boolean errs = nerrors > 0;
boolean warns = (nwarnings > 0) && (!nowarn);
boolean errsOrWarns = errs || warns;
if (!errsOrWarns) {
return true;
}
if (errs) {
out.print(nerrors > 1 ? (nerrors + " errors") : "1 error");
}
if (errs && warns) {
out.print(", ");
}
if (warns) {
out.print(nwarnings > 1 ? (nwarnings + " warnings") : "1 warning");
}
out.println();
if (strict) {
return !errsOrWarns;
} else {
return !errs;
}
}
/**
* main program
*/
public static void main(String argv[]) {
Main compiler = new Main(System.out, "jasm");
System.exit(compiler.compile(argv) ? 0 : 1);
}
}

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import static org.openjdk.asmtools.jasm.RuntimeConstants.DEPRECATED_ATTRIBUTE;
import static org.openjdk.asmtools.jasm.RuntimeConstants.SYNTHETIC_ATTRIBUTE;
import org.openjdk.asmtools.jasm.Tables.AttrTag;
import java.util.ArrayList;
/**
*
*
*/
public class MemberData {
protected int access;
protected AttrData syntheticAttr,
deprecatedAttr;
protected DataVectorAttr<AnnotationData> annotAttrVis = null;
protected DataVectorAttr<AnnotationData> annotAttrInv = null;
protected DataVectorAttr<TypeAnnotationData> type_annotAttrVis = null;
protected DataVectorAttr<TypeAnnotationData> type_annotAttrInv = null;
protected ClassData cls;
public MemberData(ClassData cls, int access) {
this.cls = cls;
init(access);
}
public void init(int access) {
this.access = access;
}
public void createPseudoMod() {
// If a member has a Pseudo-modifier
// create the appropriate marker attributes,
// and clear the PseudoModifiers from the access flags.
if (Modifiers.isSyntheticPseudoMod(access)) {
syntheticAttr = new AttrData(cls,
AttrTag.ATT_Synthetic.parsekey());
access &= ~SYNTHETIC_ATTRIBUTE;
}
if (Modifiers.isDeprecatedPseudoMod(access)) {
deprecatedAttr = new AttrData(cls,
AttrTag.ATT_Deprecated.parsekey());
access &= ~DEPRECATED_ATTRIBUTE;
}
}
public void addAnnotations(ArrayList<AnnotationData> annttns) {
for (AnnotationData annot : annttns) {
boolean invisible = annot.invisible;
if (annot instanceof TypeAnnotationData) {
// Type Annotations
TypeAnnotationData tannot = (TypeAnnotationData) annot;
if (invisible) {
if (type_annotAttrInv == null) {
type_annotAttrInv = new DataVectorAttr(cls,
AttrTag.ATT_RuntimeInvisibleTypeAnnotations.parsekey());
}
type_annotAttrInv.add(tannot);
} else {
if (type_annotAttrVis == null) {
type_annotAttrVis = new DataVectorAttr(cls,
AttrTag.ATT_RuntimeVisibleTypeAnnotations.parsekey());
}
type_annotAttrVis.add(tannot);
}
} else {
// Regular Annotations
if (invisible) {
if (annotAttrInv == null) {
annotAttrInv = new DataVectorAttr(cls,
AttrTag.ATT_RuntimeInvisibleAnnotations.parsekey());
}
annotAttrInv.add(annot);
} else {
if (annotAttrVis == null) {
annotAttrVis = new DataVectorAttr(cls,
AttrTag.ATT_RuntimeVisibleAnnotations.parsekey());
}
annotAttrVis.add(annot);
}
}
}
}
}

View File

@ -0,0 +1,263 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import org.openjdk.asmtools.jasm.Tables.AttrTag;
import org.openjdk.asmtools.jasm.ConstantPool.ConstCell;
import java.io.IOException;
import java.util.ArrayList;
import java.util.TreeMap;
/**
*
*/
class MethodData extends MemberData {
/**
* MethodParamData
*/
class ParamNameData implements Data {
int access;
ConstCell name;
public ParamNameData(int access, ConstCell name) {
this.access = access;
this.name = name;
}
@Override
public int getLength() {
return 4;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
int nm = 0;
int ac = 0;
if (name != null) {
nm = name.arg;
ac = access;
}
// short acc = (short) ac;
// env.traceln("ParamNameData.write() (name[" + nm + "], Flags: (" + access + "). [TESTING: short_access=" + acc + "]");
out.writeShort(nm);
out.writeShort(ac);
}
}// end class MethodParamData
/*-------------------------------------------------------- */
/* MethodParamData Inner Classes */
/**
* DataPArrayAttr
*
* Used to store Parameter Arrays (as attributes)
*/
static public class DataPArrayAttr<T extends Data> extends AttrData implements Constants {
TreeMap<Integer, ArrayList<T>> elements; // Data
int paramsTotal;
public DataPArrayAttr(ClassData cls, String name, int paramsTotal, TreeMap<Integer, ArrayList<T>> elements) {
super(cls, name);
this.paramsTotal = paramsTotal;
this.elements = elements;
}
public DataPArrayAttr(ClassData cls, String name, int paramsTotal) {
this(cls, name, paramsTotal, new TreeMap<Integer, ArrayList<T>>());
}
public void put(int paramNum, T element) {
ArrayList<T> v = get(paramNum);
if (v == null) {
v = new ArrayList<>();
elements.put(paramNum, v);
}
v.add(element);
}
public ArrayList<T> get(int paramNum) {
return elements.get(paramNum);
}
@Override
public int attrLength() {
int length = 1; // One byte for the paramater count
// calculate overall size here rather than in add()
// because it may not be available at the time of invoking of add()
for (int i = 0; i < paramsTotal; i++) {
ArrayList<T> attrarray = get(i);
if (attrarray != null) {
for (Data item : attrarray) {
length += item.getLength();
}
}
length += 2; // 2 bytes for the annotation count for each parameter
}
return length;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
super.write(out); // attr name, attr len
out.writeByte(paramsTotal); // number of parameters total (in byte)
for (int i = 0; i < paramsTotal; i++) {
ArrayList<T> attrarray = get(i);
if (attrarray != null) {
// write out the number of annotations for the current param
out.writeShort(attrarray.size());
for (T item : attrarray) {
item.write(out); // write the current annotation
}
} else {
out.writeShort(0);
// No annotations to write out
}
}
}
}// end class DataPArrayAttr
/*-------------------------------------------------------- */
/* Method Data Fields */
protected Environment env;
protected ConstCell nameCell, sigCell;
protected CodeAttr code;
protected DataVectorAttr<ConstCell> exceptions = null;
protected DataVectorAttr<ParamNameData> paramNames = null;
protected DataPArrayAttr<AnnotationData> pannotAttrVis = null;
protected DataPArrayAttr<AnnotationData> pannotAttrInv = null;
protected DefaultAnnotationAttr defaultAnnot = null;
protected DataVector attrs = new DataVector();
/*-------------------------------------------------------- */
public MethodData(ClassData cls, int acc,
ConstCell name, ConstCell sig, ArrayList<ConstCell> exc_table) {
super(cls, acc);
this.env = cls.env;
nameCell = name;
sigCell = sig;
if ((exc_table != null) && (!exc_table.isEmpty())) {
exceptions = new DataVectorAttr<>(cls,
AttrTag.ATT_Exceptions.parsekey(),
exc_table);
}
// Normalize the modifiers to access flags
if (Modifiers.hasPseudoMod(acc)) {
createPseudoMod();
}
}
public void addMethodParameter(int totalParams, int paramNum, ConstCell name, int access) {
env.traceln("addMethodParameter Param[" + paramNum + "] (name: " + name.toString() + ", Flags (" + access + ").");
if (paramNames == null) {
paramNames = new DataVectorAttr<>(cls, AttrTag.ATT_MethodParameters.parsekey(), true);
for (int i = 0; i < totalParams; i++) {
// initialize the paramName array (in case the name is not given in Jasm syntax)
paramNames.add(new ParamNameData(0, null));
}
}
paramNames.add(paramNum, new ParamNameData(access, name));
}
public CodeAttr startCode(int pos, int paramcnt, Argument max_stack, Argument max_locals) {
code = new CodeAttr(this, pos, paramcnt, max_stack, max_locals);
return code;
}
public void addDefaultAnnotation(DefaultAnnotationAttr data) {
defaultAnnot = data;
}
public void addParamAnnotation(int totalParams, int paramNum, AnnotationData data) {
if (!data.invisible) {
if (pannotAttrVis == null) {
pannotAttrVis = new DataPArrayAttr<>(cls,
AttrTag.ATT_RuntimeVisibleParameterAnnotations.parsekey(),
totalParams);
}
pannotAttrVis.put(paramNum, data);
} else {
if (pannotAttrInv == null) {
pannotAttrInv = new DataPArrayAttr<>(cls,
AttrTag.ATT_RuntimeInvisibleParameterAnnotations.parsekey(),
totalParams);
}
pannotAttrInv.put(paramNum, data);
}
}
/*====================================================== Write */
public void write(CheckedDataOutputStream out) throws IOException, Parser.CompilerError {
out.writeShort(access);
out.writeShort(nameCell.arg);
out.writeShort(sigCell.arg);
if (exceptions != null) {
attrs.add(exceptions);
}
if (syntheticAttr != null) {
attrs.add(syntheticAttr);
}
if (deprecatedAttr != null) {
attrs.add(deprecatedAttr);
}
if (paramNames != null) {
attrs.add(paramNames);
}
if (code != null) {
attrs.add(code);
}
if (defaultAnnot != null) {
attrs.add(defaultAnnot);
}
if (annotAttrVis != null) {
attrs.add(annotAttrVis);
}
if (annotAttrInv != null) {
attrs.add(annotAttrInv);
}
if (type_annotAttrVis != null) {
attrs.add(type_annotAttrVis);
}
if (type_annotAttrInv != null) {
attrs.add(type_annotAttrInv);
}
if (pannotAttrVis != null) {
attrs.add(pannotAttrVis);
}
if (pannotAttrInv != null) {
attrs.add(pannotAttrInv);
}
attrs.write(out);
}
} // end MethodData

View File

@ -0,0 +1,429 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import static org.openjdk.asmtools.jasm.RuntimeConstants.*;
import static org.openjdk.asmtools.jasm.JasmTokens.*;
import static org.openjdk.asmtools.jasm.Tables.CF_Context;
/**
*
*
*/
public class Modifiers {
private static Modifiers ref;
/*
* Modifier masks
*/
public static final int MM_ATTR = SYNTHETIC_ATTRIBUTE | DEPRECATED_ATTRIBUTE;
public static final int MM_INTRF = ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE | MM_ATTR ; // | ACC_MODULE ;
public static final int MM_CLASS = ACC_PUBLIC | ACC_FINAL| ACC_SUPER | ACC_ABSTRACT | ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM | MM_ATTR ; // | ACC_MODULE ;
public static final int MM_ACCESS = ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED; // | ACC_MODULE;
public static final int MM_FIELD = MM_ACCESS | ACC_STATIC | ACC_FINAL | ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM | MM_ATTR ; // | ACC_MODULE ;
public static final int MM_I_METHOD = ACC_ABSTRACT | ACC_PUBLIC | ACC_VARARGS | ACC_BRIDGE | ACC_SYNTHETIC ; // interface method
public static final int MM_A_METHOD = MM_ACCESS | ACC_ABSTRACT | MM_ATTR;
public static final int MM_N_METHOD = MM_ACCESS | ACC_STRICT | ACC_VARARGS | ACC_SYNTHETIC | MM_ATTR; // <init>
public static final int MM_METHOD = MM_ACCESS | ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED | ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE | ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC | MM_ATTR ; // | ACC_MODULE ;
public static final int MM_INNERCLASS = MM_ACCESS | ACC_STATIC | ACC_FINAL | ACC_SUPER | ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM | MM_ATTR ; // | ACC_MODULE ;
private Modifiers() {
}
public static Modifiers ModifiersObject() {
if (ref == null) {
ref = new Modifiers();
}
return ref;
}
public static boolean validClass(int mod) {
return (mod & ~MM_CLASS) == 0;
}
public static boolean validInnerClass(int mod) {
return (mod & ~MM_INNERCLASS) == 0;
}
public static boolean validField(int mod) {
return (mod & ~MM_FIELD) == 0;
}
public static boolean validMethod(int mod) {
return (mod & ~MM_METHOD) == 0;
}
public static boolean validInterface(int mod) {
return (mod & ~MM_INTRF) == 0;
}
public static boolean validAbstractMethod(int mod) {
return (mod & ~MM_A_METHOD) == 0;
}
public static boolean validInitMethod(int mod) {
return (mod & ~MM_N_METHOD) == 0;
}
public static boolean validInterfaceMethod(int mod) {
// return (mod & ~MM_ATTR) == MM_I_METHOD;
return ((mod & ~MM_I_METHOD) == 0) && isPublic(mod) && isAbstract(mod);
}
public static boolean validInterfaceField(int mod) {
return mod == (ACC_STATIC | ACC_PUBLIC | ACC_FINAL);
}
public static boolean isPublic(int mod) {
return (mod & ACC_PUBLIC) != 0;
}
public static boolean isPrivate(int mod) {
return (mod & ACC_PRIVATE) != 0;
}
public static boolean isProtected(int mod) {
return (mod & ACC_PROTECTED) != 0;
}
public static boolean isInterface(int mod) {
return (mod & ACC_INTERFACE) != 0;
}
public static boolean isAbstract(int mod) {
return (mod & ACC_ABSTRACT) != 0;
}
public static boolean isFinal(int mod) {
return (mod & ACC_FINAL) != 0;
}
public static boolean isStatic(int mod) {
return (mod & ACC_STATIC) != 0;
}
public static boolean isSynthetic(int mod) {
return (mod & ACC_SYNTHETIC) != 0;
}
public static boolean isDeprecated(int mod) {
return (mod & DEPRECATED_ATTRIBUTE) != 0;
}
public static boolean isTransient(int mod) {
return (mod & ACC_TRANSIENT) != 0;
}
public static boolean isAnnotation(int mod) {
return (mod & ACC_ANNOTATION) != 0;
}
public static boolean isNative(int mod) {
return (mod & ACC_NATIVE) != 0;
}
public static boolean isStrict(int mod) {
return (mod & ACC_STRICT) != 0;
}
public static boolean isEnum(int mod) {
return (mod & ACC_ENUM) != 0;
}
public static boolean isSuper(int mod) {
return (mod & ACC_SUPER) != 0;
}
/*
public static boolean isModule(int mod) {
return (mod & ACC_MODULE)!=0;
}
* */
public static boolean isMandated(int mod) {
return (mod & ACC_MANDATED) != 0;
}
public static boolean isSynchronized(int mod) {
return (mod & ACC_SYNCHRONIZED) != 0;
}
public static boolean isBridge(int mod) {
return (mod & ACC_BRIDGE) != 0;
}
public static boolean isVolatile(int mod) {
return (mod & ACC_VOLATILE) != 0;
}
public static boolean isVarArgs(int mod) {
return (mod & ACC_VARARGS) != 0;
}
public static boolean isSyntheticPseudoMod(int mod) {
return (mod & SYNTHETIC_ATTRIBUTE) != 0;
}
public static boolean isDeprecatedPseudoMod(int mod) {
return (mod & DEPRECATED_ATTRIBUTE) != 0;
}
public static boolean hasPseudoMod(int mod) {
return isSyntheticPseudoMod(mod) || isDeprecatedPseudoMod(mod);
}
/*
* Checks that only one (or none) of the Access flags are set.
*/
public static boolean validAccess(int mod) {
boolean retval = true;
switch (mod & MM_ACCESS) {
case 0:
// case ACC_MODULE:
case ACC_PUBLIC:
case ACC_PRIVATE:
case ACC_PROTECTED:
break;
default:
retval = false;
}
return retval;
}
/*
* Are both flags set
*
*/
public static boolean both(int mod, int flagA, int flagB) {
return (mod & (flagA | flagB)) == (flagA | flagB);
}
/**
* Check the modifier flags for the class
*
* @param env The error reporting environment.
* @param mod The modifier flags being checked
* @param pos the position of the parser in the file
*/
public static void checkClassModifiers(Environment env, int mod, int pos) {
if (isInterface(mod)) {
if (!validInterface(mod)) {
env.error(pos, "warn.invalid.modifier.int");
}
if (!isAbstract(mod)) {
env.error(pos, "warn.invalid.modifier.int.abs");
}
} else {
if (!validClass(mod)) {
env.error(pos, "warn.invalid.modifier.class");
}
if (isAbstract(mod) && Modifiers.isFinal(mod)) {
env.error(pos, "warn.invalid.modifier.class.finabs");
}
}
}
/**
* Check the modifier flags for the field
*
* @param cd The ClassData for the current class
* @param mod The modifier flags being checked
* @param pos the position of the parser in the file
*/
public static void checkFieldModifiers(ClassData cd, int mod, int pos) {
Environment env = cd.env;
if (cd.isInterface()) {
// For interfaces
if (!validInterfaceField(mod)) {
env.error(pos, "warn.invalid.modifier.intfield");
}
} else {
// For non-interfaces
if (!validField(mod)) {
env.error(pos, "warn.invalid.modifier.field");
}
if (both(mod, ACC_FINAL, ACC_VOLATILE)) {
env.error(pos, "warn.invalid.modifier.fiva");
}
if (!validAccess(mod)) {
env.error(pos, "warn.invalid.modifier.acc");
}
}
}
/**
* Check the modifier flags for the method
*
* @param cd The ClassData for the current class
* @param mod The modifier flags being checked
* @param pos the position of the parser in the file
*/
public static void checkMethodModifiers(ClassData cd, int mod, int pos, boolean is_init, boolean is_clinit) {
Environment env = cd.env;
if (!is_clinit) {
if (cd.isInterface()) {
if (is_init) {
env.error(pos, "warn.init.in_int");
} else if (!validInterfaceMethod(mod)) {
int badflags = (mod & ~MM_I_METHOD);
env.error(pos, "warn.invalid.modifier.intmth", toString(badflags, CF_Context.CTX_METHOD)
+ " *****" + toString(mod, CF_Context.CTX_METHOD) + "*****");
}
} else {
if (is_init && !validInitMethod(mod)) {
int badflags = (mod & ~MM_N_METHOD);
env.error(pos, "warn.invalid.modifier.init", toString(badflags, CF_Context.CTX_METHOD)
+ " *****" + toString(mod, CF_Context.CTX_METHOD) + "*****");
} else if (isAbstract(mod)) {
if (!validAbstractMethod(mod)) {
int badflags = (mod & ~MM_A_METHOD);
env.error(pos, "warn.invalid.modifier.abst", toString(badflags, CF_Context.CTX_METHOD)
+ " *****" + toString(mod, CF_Context.CTX_METHOD) + "*****");
}
} else {
if (!validMethod(mod)) {
env.error(pos, "warn.invalid.modifier.mth");
}
}
if (!validAccess(mod)) {
env.error(pos, "warn.invalid.modifier.acc");
}
}
}
}
/**
* Check the modifier flags for the inner-class
*
* @param cd The ClassData for the current class
* @param mod The modifier flags being checked
* @param pos the position of the parser in the file
*/
public static void checkInnerClassModifiers(ClassData cd, int mod, int pos) {
Environment env = cd.env;
if (!validInnerClass(mod)) {
int badflags = (mod & ~MM_INNERCLASS);
env.error(pos, "warn.invalid.modifier.innerclass",
toString(badflags, CF_Context.CTX_INNERCLASS)
+ " *****" + toString(mod, CF_Context.CTX_INNERCLASS) + "*****");
}
}
private static StringBuffer _accessString(int mod, CF_Context context) {
StringBuffer sb = new StringBuffer();
// if (isModule(mod))
// sb.append(Tables.keywordName(Tables.Module) + " ");
if (isPublic(mod)) {
sb.append(Token.PUBLIC.parsekey() + " ");
}
if (isPrivate(mod)) {
sb.append(Token.PRIVATE.parsekey() + " ");
}
if (isProtected(mod)) {
sb.append(Token.PROTECTED.parsekey() + " ");
}
if (isStatic(mod)) {
sb.append(Token.STATIC.parsekey() + " ");
}
if (context == CF_Context.CTX_METHOD && isFinal(mod)) {
sb.append(Token.FINAL.parsekey() + " ");
}
if (context == CF_Context.CTX_FIELD && isTransient(mod)) {
sb.append(Token.TRANSIENT.parsekey() + " ");
}
if (context == CF_Context.CTX_CLASS && isSuper(mod)) {
sb.append(Token.SUPER.parsekey() + " ");
}
if (context == CF_Context.CTX_METHOD && isSynchronized(mod)) {
sb.append(Token.SYNCHRONIZED.parsekey() + " ");
}
if (context == CF_Context.CTX_METHOD) {
if (isBridge(mod)) {
sb.append(Token.BRIDGE.parsekey() + " ");
}
if (isVarArgs(mod)) {
sb.append(Token.VARARGS.parsekey() + " ");
}
if (isNative(mod)) {
sb.append(Token.NATIVE.parsekey() + " ");
}
}
if (isAbstract(mod)) {
if ((context != CF_Context.CTX_CLASS) || !isInterface(mod)) {
sb.append(Token.ABSTRACT.parsekey() + " ");
}
}
if ((context == CF_Context.CTX_CLASS || context == CF_Context.CTX_INNERCLASS || context == CF_Context.CTX_FIELD) && isFinal(mod)) {
sb.append(Token.FINAL.parsekey() + " ");
}
if ((context == CF_Context.CTX_CLASS || context == CF_Context.CTX_INNERCLASS) && isInterface(mod)) {
sb.append(Token.INTERFACE.parsekey() + " ");
}
if (isStrict(mod)) {
sb.append(Token.STRICT.parsekey() + " ");
}
if (isSynthetic(mod)) {
sb.append(Token.SYNTHETIC.parsekey() + " ");
}
if (context == CF_Context.CTX_FIELD && isVolatile(mod)) {
sb.append(Token.VOLATILE.parsekey() + " ");
}
if (isEnum(mod)) {
sb.append(Token.ENUM.parsekey() + " ");
}
if (isMandated(mod)) {
sb.append(Token.MANDATED.parsekey() + " ");
}
// We don't have print identifiers for annotation flags
// if (isAnnotation(mod))
// sb.append(Tables.keywordName(Tables.ANNOTATION) + " ");
return sb;
}
public static String toString(int mod, CF_Context context) {
StringBuffer sb = _accessString(mod, context);
if (isSyntheticPseudoMod(mod)) {
sb.append("Synthetic(Pseudo) ");
}
if (isDeprecatedPseudoMod(mod)) {
sb.append("Deprecated(Pseudo) ");
}
return sb.toString();
}
public static String accessString(int mod, CF_Context context) {
StringBuffer sb = _accessString(mod, context);
return sb.toString();
}
}

View File

@ -0,0 +1,567 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.util.HashMap;
/**
*
* OpcodeTables
*
* The OpcodeTables class follows a Singleton Pattern. This class contains Enums, that are
* contained in private hash maps (lookup tables and reverse lookup tables). These hash
* maps all have public accessors, which clients use to look-up opcodes.
*
* Tokens in this table carry no external state, and are typically treated as constants.
* They do not need to be reset.
*
*/
public class OpcodeTables {
/**
* Initialized keyword and token Hash Maps (and Reverse Tables)
*/
static private final int MaxOpcodes = 301;
static private HashMap<Integer, Opcode> IntToNormalOpcodes = new HashMap<>(MaxOpcodes);
static private HashMap<Integer, Opcode> IntToAllOpcodes = new HashMap<>(MaxOpcodes);
static private HashMap<String, Opcode> mnemocodes = new HashMap<>(MaxOpcodes);
static private HashMap<Integer, Opcode> IntToPrivOpcode = new HashMap<>(MaxOpcodes);
static private HashMap<String, Opcode> PrivMnemocodes = new HashMap<>(MaxOpcodes);
static private HashMap<Integer, Opcode> IntToNonPrivOpcode = new HashMap<>(MaxOpcodes);
static private HashMap<String, Opcode> NonPrivMnemocodes = new HashMap<>(MaxOpcodes);
static {
// register all of the tokens
for (Opcode opc : Opcode.values()) {
registerOpcode(opc);
}
}
private static void registerOpcode(Opcode opc) {
IntToAllOpcodes.put(opc.value, opc);
mnemocodes.put(opc.parsekey, opc);
if (opc.alias != null) {
mnemocodes.put(opc.alias, opc);
}
if (opc.type == OpcodeType.PRIVELEGED) {
PrivMnemocodes.put(opc.parsekey, opc);
IntToPrivOpcode.put(opc.baseVal, opc);
} else if (opc.type == OpcodeType.NONPRIVELEGED) {
NonPrivMnemocodes.put(opc.parsekey, opc);
IntToNonPrivOpcode.put(opc.baseVal, opc);
}
}
public static Opcode opcode(String mnemonic) {
return mnemocodes.get(mnemonic);
}
public static Opcode opcode(Integer mnem_code) {
return IntToAllOpcodes.get(mnem_code);
}
/*-------------------------------------------------------- */
/**
* Marker: describes the type of Opcode.
*
* certain types of Opcodes will be added to specific lookup tables.
*/
static public enum OpcodeType {
NORMAL (0, "Normal"),
NONPRIVELEGED (1, "NonPriv"),
PRIVELEGED (2, "Priv"),
WIDE (3, "Wide");
private final Integer value;
private final String printval;
OpcodeType(Integer val, String print) {
value = val;
printval = print;
}
public String printval() {
return printval;
}
}
/*-------------------------------------------------------- */
/* Opcode Enums */
static public enum Opcode {
/* Opcodes */
opc_dead (-2, " opc_dead", 0),
opc_label (-1, "opc_label", 0),
opc_nop (0, "nop", 1),
opc_aconst_null (1, "aconst_null", 1),
opc_iconst_m1 (2, "iconst_m1", 1),
opc_iconst_0 (3, "iconst_0", 1),
opc_iconst_1 (4, "iconst_1", 1),
opc_iconst_2 (5, "iconst_2", 1),
opc_iconst_3 (6, "iconst_3", 1),
opc_iconst_4 (7, "iconst_4", 1),
opc_iconst_5 (8, "iconst_5", 1),
opc_lconst_0 (9, "lconst_0", 1),
opc_lconst_1 (10, "lconst_1", 1),
opc_fconst_0 (11, "fconst_0", 1),
opc_fconst_1 (12, "fconst_1", 1),
opc_fconst_2 (13, "fconst_2", 1),
opc_dconst_0 (14, "dconst_0", 1),
opc_dconst_1 (15, "dconst_1", 1),
opc_bipush (16, "bipush", 2),
opc_sipush (17, "sipush", 3),
opc_ldc (18, "ldc", 2),
opc_ldc_w (19, "ldc_w", 3),
opc_ldc2_w (20, "ldc2_w", 3),
opc_iload (21, "iload", 2),
opc_lload (22, "lload", 2),
opc_fload (23, "fload", 2),
opc_dload (24, "dload", 2),
opc_aload (25, "aload", 2),
opc_iload_0 (26, "iload_0", 1),
opc_iload_1 (27, "iload_1", 1),
opc_iload_2 (28, "iload_2", 1),
opc_iload_3 (29, "iload_3", 1),
opc_lload_0 (30, "lload_0", 1),
opc_lload_1 (31, "lload_1", 1),
opc_lload_2 (32, "lload_2", 1),
opc_lload_3 (33, "lload_3", 1),
opc_fload_0 (34, "fload_0", 1),
opc_fload_1 (35, "fload_1", 1),
opc_fload_2 (36, "fload_2", 1),
opc_fload_3 (37, "fload_3", 1),
opc_dload_0 (38, "dload_0", 1),
opc_dload_1 (39, "dload_1", 1),
opc_dload_2 (40, "dload_2", 1),
opc_dload_3 (41, "dload_3", 1),
opc_aload_0 (42, "aload_0", 1),
opc_aload_1 (43, "aload_1", 1),
opc_aload_2 (44, "aload_2", 1),
opc_aload_3 (45, "aload_3", 1),
opc_iaload (46, "iaload", 1),
opc_laload (47, "laload", 1),
opc_faload (48, "faload", 1),
opc_daload (49, "daload", 1),
opc_aaload (50, "aaload", 1),
opc_baload (51, "baload", 1),
opc_caload (52, "caload", 1),
opc_saload (53, "saload", 1),
opc_istore (54, "istore", 2),
opc_lstore (55, "lstore", 2),
opc_fstore (56, "fstore", 2),
opc_dstore (57, "dstore", 2),
opc_astore (58, "astore", 2),
opc_istore_0 (59, "istore_0", 1),
opc_istore_1 (60, "istore_1", 1),
opc_istore_2 (61, "istore_2", 1),
opc_istore_3 (62, "istore_3", 1),
opc_lstore_0 (63, "lstore_0", 1),
opc_lstore_1 (64, "lstore_1", 1),
opc_lstore_2 (65, "lstore_2", 1),
opc_lstore_3 (66, "lstore_3", 1),
opc_fstore_0 (67, "fstore_0", 1),
opc_fstore_1 (68, "fstore_1", 1),
opc_fstore_2 (69, "fstore_2", 1),
opc_fstore_3 (70, "fstore_3", 1),
opc_dstore_0 (71, "dstore_0", 1),
opc_dstore_1 (72, "dstore_1", 1),
opc_dstore_2 (73, "dstore_2", 1),
opc_dstore_3 (74, "dstore_3", 1),
opc_astore_0 (75, "astore_0", 1),
opc_astore_1 (76, "astore_1", 1),
opc_astore_2 (77, "astore_2", 1),
opc_astore_3 (78, "astore_3", 1),
opc_iastore (79, "iastore", 1),
opc_lastore (80, "lastore", 1),
opc_fastore (81, "fastore", 1),
opc_dastore (82, "dastore", 1),
opc_aastore (83, "aastore", 1),
opc_bastore (84, "bastore", 1),
opc_castore (85, "castore", 1),
opc_sastore (86, "sastore", 1),
opc_pop (87, "pop", 1),
opc_pop2 (88, "pop2", 1),
opc_dup (89, "dup", 1),
opc_dup_x1 (90, "dup_x1", 1),
opc_dup_x2 (91, "dup_x2", 1),
opc_dup2 (92, "dup2", 1),
opc_dup2_x1 (93, "dup2_x1", 1),
opc_dup2_x2 (94, "dup2_x2", 1),
opc_swap (95, "swap", 1),
opc_iadd (96, "iadd", 1),
opc_ladd (97, "ladd", 1),
opc_fadd (98, "fadd", 1),
opc_dadd (99, "dadd", 1),
opc_isub (100, "isub", 1),
opc_lsub (101, "lsub", 1),
opc_fsub (102, "fsub", 1),
opc_dsub (103, "dsub", 1),
opc_imul (104, "imul", 1),
opc_lmul (105, "lmul", 1),
opc_fmul (106, "fmul", 1),
opc_dmul (107, "dmul", 1),
opc_idiv (108, "idiv", 1),
opc_ldiv (109, "ldiv", 1),
opc_fdiv (110, "fdiv", 1),
opc_ddiv (111, "ddiv", 1),
opc_irem (112, "irem", 1),
opc_lrem (113, "lrem", 1),
opc_frem (114, "frem", 1),
opc_drem (115, "drem", 1),
opc_ineg (116, "ineg", 1),
opc_lneg (117, "lneg", 1),
opc_fneg (118, "fneg", 1),
opc_dneg (119, "dneg", 1),
opc_ishl (120, "ishl", 1),
opc_lshl (121, "lshl", 1),
opc_ishr (122, "ishr", 1),
opc_lshr (123, "lshr", 1),
opc_iushr (124, "iushr", 1),
opc_lushr (125, "lushr", 1),
opc_iand (126, "iand", 1),
opc_land (127, "land", 1),
opc_ior (128, "ior", 1),
opc_lor (129, "lor", 1),
opc_ixor (130, "ixor", 1),
opc_lxor (131, "lxor", 1),
opc_iinc (132, "iinc", 3),
opc_i2l (133, "i2l", 1),
opc_i2f (134, "i2f", 1),
opc_i2d (135, "i2d", 1),
opc_l2i (136, "l2i", 1),
opc_l2f (137, "l2f", 1),
opc_l2d (138, "l2d", 1),
opc_f2i (139, "f2i", 1),
opc_f2l (140, "f2l", 1),
opc_f2d (141, "f2d", 1),
opc_d2i (142, "d2i", 1),
opc_d2l (143, "d2l", 1),
opc_d2f (144, "d2f", 1),
opc_i2b (145, "i2b", 1),
opc_i2c (146, "i2c", 1),
opc_i2s (147, "i2s", 1),
opc_lcmp (148, "lcmp", 1),
opc_fcmpl (149, "fcmpl", 1),
opc_fcmpg (150, "fcmpg", 1),
opc_dcmpl (151, "dcmpl", 1),
opc_dcmpg (152, "dcmpg", 1),
opc_ifeq (153, "ifeq", 3),
opc_ifne (154, "ifne", 3),
opc_iflt (155, "iflt", 3),
opc_ifge (156, "ifge", 3),
opc_ifgt (157, "ifgt", 3),
opc_ifle (158, "ifle", 3),
opc_if_icmpeq (159, "if_icmpeq", 3),
opc_if_icmpne (160, "if_icmpne", 3),
opc_if_icmplt (161, "if_icmplt", 3),
opc_if_icmpge (162, "if_icmpge", 3),
opc_if_icmpgt (163, "if_icmpgt", 3),
opc_if_icmple (164, "if_icmple", 3),
opc_if_acmpeq (165, "if_acmpeq", 3),
opc_if_acmpne (166, "if_acmpne", 3),
opc_goto (167, "goto", 3),
opc_jsr (168, "jsr", 3),
opc_ret (169, "ret", 2),
opc_tableswitch (170, "tableswitch", 99),
opc_lookupswitch (171, "lookupswitch", 99),
opc_ireturn (172, "ireturn", 1),
opc_lreturn (173, "lreturn", 1),
opc_freturn (174, "freturn", 1),
opc_dreturn (175, "dreturn", 1),
opc_areturn (176, "areturn", 1),
opc_return (177, "return", 1),
opc_getstatic (178, "getstatic", 3),
opc_putstatic (179, "putstatic", 3),
opc_getfield (180, "getfield", 3),
opc_putfield (181, "putfield", 3),
opc_invokevirtual (182, "invokevirtual", 3),
opc_invokespecial (183, "invokespecial", "invokenonvirtual", 3),
opc_invokestatic (184, "invokestatic", 3),
opc_invokeinterface (185, "invokeinterface", 5),
opc_invokedynamic (186, "invokedynamic", 5),
opc_new (187, "new", 3),
opc_newarray (188, "newarray", 2),
opc_anewarray (189, "anewarray", 3),
opc_arraylength (190, "arraylength", 1),
opc_athrow (191, "athrow", 1),
opc_checkcast (192, "checkcast", 3),
opc_instanceof (193, "instanceof", 3),
opc_monitorenter (194, "monitorenter", 1),
opc_monitorexit (195, "monitorexit", 1),
// Wide Marker (not really an opcode)
opc_wide (196, null, 0),
opc_multianewarray (197, "multianewarray", 4),
opc_ifnull (198, "ifnull", 3),
opc_ifnonnull (199, "ifnonnull", 3),
opc_goto_w (200, "goto_w", 5),
opc_jsr_w (201, "jsr_w", 5),
// opc_bytecode 202 (202, "bytecode 202", 1),
/* Pseudo-instructions */
opc_bytecode (203, "bytecode", 1),
opc_try (204, "try", 0),
opc_endtry (205, "endtry", 0),
opc_catch (206, "catch", 0),
opc_var (207, "var", 0),
opc_endvar (208, "endvar", 0),
opc_locals_map (209, "locals_map", 0),
opc_stack_map (210, "stack_map", 0),
opc_stack_frame_type (211, "stack_frame_type", 0),
// Priv/NonPriv Marker (not really an opcode)
opc_nonpriv (254, "priv", 0),
opc_priv (255, "nonpriv", 0),
/* Wide instructions */
opc_iload_w (opc_iload.value, "iload_w", 4, OpcodeType.WIDE),
opc_lload_w (opc_lload.value, "lload_w", 4, OpcodeType.WIDE),
opc_fload_w (opc_fload.value, "fload_w", 4, OpcodeType.WIDE),
opc_dload_w (opc_dload.value, "dload_w", 4, OpcodeType.WIDE),
opc_aload_w (opc_aload.value, "aload_w", 4, OpcodeType.WIDE),
opc_istore_w (opc_istore.value, "istore_w", 4, OpcodeType.WIDE),
opc_lstore_w (opc_lstore.value, "lstore_w", 4, OpcodeType.WIDE),
opc_fstore_w (opc_fstore.value, "fstore_w", 4, OpcodeType.WIDE),
opc_dstore_w (opc_dstore.value, "dstore_w", 4, OpcodeType.WIDE),
opc_astore_w (opc_astore.value, "astore_w", 4, OpcodeType.WIDE),
opc_ret_w (opc_ret.value, "ret_w", 4, OpcodeType.WIDE),
opc_iinc_w (opc_iinc.value, "iinc_w", 6, OpcodeType.WIDE),
/* Priveleged instructions */
opc_load_ubyte (0, "load_ubyte", OpcodeType.NONPRIVELEGED),
opc_priv_load_ubyte (0, "priv_load_ubyte", OpcodeType.PRIVELEGED),
opc_load_byte (1, "load_byte", OpcodeType.NONPRIVELEGED),
opc_priv_load_byte (1, "priv_load_byte", OpcodeType.PRIVELEGED),
opc_load_char (2, "load_char", OpcodeType.NONPRIVELEGED),
opc_priv_load_char (2, "priv_load_char", OpcodeType.PRIVELEGED),
opc_load_short (3, "load_short", OpcodeType.NONPRIVELEGED),
opc_priv_load_short (3, "priv_load_short", OpcodeType.PRIVELEGED),
opc_load_word (4, "load_word", OpcodeType.NONPRIVELEGED),
opc_priv_load_word (4, "priv_load_word", OpcodeType.PRIVELEGED),
opc_load_char_oe (10, "load_char_oe", OpcodeType.NONPRIVELEGED),
opc_priv_load_char_oe (10, "priv_load_char_oe", OpcodeType.PRIVELEGED),
opc_load_short_oe (11, "load_short_oe", OpcodeType.NONPRIVELEGED),
opc_priv_load_short_oe (11, "priv_load_short_oe", OpcodeType.PRIVELEGED),
opc_load_word_oe (12, "load_word_oe", OpcodeType.NONPRIVELEGED),
opc_priv_load_word_oe (12, "priv_load_word_oe", OpcodeType.PRIVELEGED),
opc_ncload_ubyte (16, "ncload_ubyte", OpcodeType.NONPRIVELEGED),
opc_priv_ncload_ubyte (16, "priv_ncload_ubyte", OpcodeType.PRIVELEGED),
opc_ncload_byte (17, "ncload_byte", OpcodeType.NONPRIVELEGED),
opc_priv_ncload_byte (17, "priv_ncload_byte", OpcodeType.PRIVELEGED),
opc_ncload_char (18, "ncload_char", OpcodeType.NONPRIVELEGED),
opc_priv_ncload_char (18, "priv_ncload_char", OpcodeType.PRIVELEGED),
opc_ncload_short (19, "ncload_short", OpcodeType.NONPRIVELEGED),
opc_priv_ncload_short (19, "priv_ncload_short", OpcodeType.PRIVELEGED),
opc_ncload_word (20, "ncload_word", OpcodeType.NONPRIVELEGED),
opc_priv_ncload_word (20, "priv_ncload_word", OpcodeType.PRIVELEGED),
opc_ncload_char_oe (26, "ncload_char_oe", OpcodeType.NONPRIVELEGED),
opc_priv_ncload_char_oe (26, "priv_ncload_char_oe", OpcodeType.PRIVELEGED),
opc_ncload_short_oe (27, "ncload_short_oe", OpcodeType.NONPRIVELEGED),
opc_priv_ncload_short_oe (27, "priv_ncload_short_oe", OpcodeType.PRIVELEGED),
opc_ncload_word_oe (28, "ncload_word_oe", OpcodeType.NONPRIVELEGED),
opc_priv_ncload_word_oe (28, "priv_ncload_word_oe", OpcodeType.PRIVELEGED),
opc_cache_flush (30, "cache_flush", OpcodeType.NONPRIVELEGED),
opc_priv_cache_flush (30, "priv_cache_flush", OpcodeType.PRIVELEGED),
opc_store_byte (32, "store_byte", OpcodeType.NONPRIVELEGED),
opc_priv_store_byte (32, "priv_store_byte", OpcodeType.PRIVELEGED),
opc_store_short (34, "store_short", OpcodeType.NONPRIVELEGED),
opc_priv_store_short (34, "priv_store_short", OpcodeType.PRIVELEGED),
opc_store_word (36, "store_word", OpcodeType.NONPRIVELEGED),
opc_priv_store_word (36, "priv_store_word", OpcodeType.PRIVELEGED),
opc_store_short_oe (42, "store_short_oe", OpcodeType.NONPRIVELEGED),
opc_priv_store_short_oe (42, "priv_store_short_oe", OpcodeType.PRIVELEGED),
opc_store_word_oe (44, "store_word_oe", OpcodeType.NONPRIVELEGED),
opc_priv_store_word_oe (44, "priv_store_word_oe", OpcodeType.PRIVELEGED),
opc_ncstore_byte (48, "ncstore_byte", OpcodeType.NONPRIVELEGED),
opc_priv_ncstore_byte (48, "priv_ncstore_byte", OpcodeType.PRIVELEGED),
opc_ncstore_short (50, "ncstore_short", OpcodeType.NONPRIVELEGED),
opc_priv_ncstore_short (50, "priv_ncstore_short", OpcodeType.PRIVELEGED),
opc_ncstore_word (52, "ncstore_word", OpcodeType.NONPRIVELEGED),
opc_priv_ncstore_word (52, "priv_ncstore_word", OpcodeType.PRIVELEGED),
opc_ncstore_short_oe (58, "ncstore_short_oe", OpcodeType.NONPRIVELEGED),
opc_priv_ncstore_short_oe (58, "priv_ncstore_short_oe", OpcodeType.PRIVELEGED),
opc_ncstore_word_oe (60, "ncstore_word_oe", OpcodeType.NONPRIVELEGED),
opc_priv_ncstore_word_oe (60, "priv_ncstore_word_oe", OpcodeType.PRIVELEGED),
opc_zero_line (62, "zero_line", OpcodeType.NONPRIVELEGED),
opc_priv_zero_line (62, "priv_zero_line", OpcodeType.PRIVELEGED),
opc_ret_from_sub (5, "ret_from_sub", OpcodeType.NONPRIVELEGED),
opc_enter_sync_method (63, "enter_sync_method", OpcodeType.NONPRIVELEGED),
opc_priv_ret_from_trap (5, "priv_ret_from_trap", OpcodeType.PRIVELEGED),
opc_priv_read_dcache_tag (6, "priv_read_dcache_tag", OpcodeType.PRIVELEGED),
opc_priv_read_dcache_data (7, "priv_read_dcache_data", OpcodeType.PRIVELEGED),
opc_priv_read_icache_tag (14, "priv_read_icache_tag", OpcodeType.PRIVELEGED),
opc_priv_read_icache_data (15, "priv_read_icache_data", OpcodeType.PRIVELEGED),
opc_priv_powerdown (22, "priv_powerdown", OpcodeType.PRIVELEGED),
opc_priv_read_scache_data (23, "priv_read_scache_data", OpcodeType.PRIVELEGED),
opc_priv_cache_index_flush (31, "priv_cache_index_flush", OpcodeType.PRIVELEGED),
opc_priv_write_dcache_tag (38, "priv_write_dcache_tag", OpcodeType.PRIVELEGED),
opc_priv_write_dcache_data (39, "priv_write_dcache_data", OpcodeType.PRIVELEGED),
opc_priv_write_icache_tag (46, "priv_write_icache_tag", OpcodeType.PRIVELEGED),
opc_priv_write_icache_data (47, "priv_write_icache_data", OpcodeType.PRIVELEGED),
opc_priv_reset (54, "priv_reset", OpcodeType.PRIVELEGED),
opc_priv_write_scache_data (55, "priv_write_scache_data", OpcodeType.PRIVELEGED),
opc_priv_read_reg_0 (64, "priv_read_reg_0", OpcodeType.PRIVELEGED),
opc_priv_read_reg_1 (65, "priv_read_reg_1", OpcodeType.PRIVELEGED),
opc_priv_read_reg_2 (66, "priv_read_reg_2", OpcodeType.PRIVELEGED),
opc_priv_read_reg_3 (67, "priv_read_reg_3", OpcodeType.PRIVELEGED),
opc_priv_read_reg_4 (68, "priv_read_reg_4", OpcodeType.PRIVELEGED),
opc_priv_read_reg_5 (69, "priv_read_reg_5", OpcodeType.PRIVELEGED),
opc_priv_read_reg_6 (70, "priv_read_reg_6", OpcodeType.PRIVELEGED),
opc_priv_read_reg_7 (71, "priv_read_reg_7", OpcodeType.PRIVELEGED),
opc_priv_read_reg_8 (72, "priv_read_reg_8", OpcodeType.PRIVELEGED),
opc_priv_read_reg_9 (73, "priv_read_reg_9", OpcodeType.PRIVELEGED),
opc_priv_read_reg_10 (74, "priv_read_reg_10", OpcodeType.PRIVELEGED),
opc_priv_read_reg_11 (75, "priv_read_reg_11", OpcodeType.PRIVELEGED),
opc_priv_read_reg_12 (76, "priv_read_reg_12", OpcodeType.PRIVELEGED),
opc_priv_read_reg_13 (77, "priv_read_reg_13", OpcodeType.PRIVELEGED),
opc_priv_read_reg_14 (78, "priv_read_reg_14", OpcodeType.PRIVELEGED),
opc_priv_read_reg_15 (79, "priv_read_reg_15", OpcodeType.PRIVELEGED),
opc_priv_read_reg_16 (80, "priv_read_reg_16", OpcodeType.PRIVELEGED),
opc_priv_read_reg_17 (81, "priv_read_reg_17", OpcodeType.PRIVELEGED),
opc_priv_read_reg_18 (82, "priv_read_reg_18", OpcodeType.PRIVELEGED),
opc_priv_read_reg_19 (83, "priv_read_reg_19", OpcodeType.PRIVELEGED),
opc_priv_read_reg_20 (84, "priv_read_reg_20", OpcodeType.PRIVELEGED),
opc_priv_read_reg_21 (85, "priv_read_reg_21", OpcodeType.PRIVELEGED),
opc_priv_read_reg_22 (86, "priv_read_reg_22", OpcodeType.PRIVELEGED),
opc_priv_read_reg_23 (87, "priv_read_reg_23", OpcodeType.PRIVELEGED),
opc_priv_read_reg_24 (88, "priv_read_reg_24", OpcodeType.PRIVELEGED),
opc_priv_read_reg_25 (89, "priv_read_reg_25", OpcodeType.PRIVELEGED),
opc_priv_read_reg_26 (90, "priv_read_reg_26", OpcodeType.PRIVELEGED),
opc_priv_read_reg_27 (91, "priv_read_reg_27", OpcodeType.PRIVELEGED),
opc_priv_read_reg_28 (92, "priv_read_reg_28", OpcodeType.PRIVELEGED),
opc_priv_read_reg_29 (93, "priv_read_reg_29", OpcodeType.PRIVELEGED),
opc_priv_read_reg_30 (94, "priv_read_reg_30", OpcodeType.PRIVELEGED),
opc_priv_read_reg_31 (95, "priv_read_reg_31", OpcodeType.PRIVELEGED),
opc_priv_write_reg_0 (96, "priv_write_reg_0", OpcodeType.PRIVELEGED),
opc_priv_write_reg_1 (97, "priv_write_reg_1", OpcodeType.PRIVELEGED),
opc_priv_write_reg_2 (98, "priv_write_reg_2", OpcodeType.PRIVELEGED),
opc_priv_write_reg_3 (99, "priv_write_reg_3", OpcodeType.PRIVELEGED),
opc_priv_write_reg_4 (100, "priv_write_reg_4", OpcodeType.PRIVELEGED),
opc_priv_write_reg_5 (101, "priv_write_reg_5", OpcodeType.PRIVELEGED),
opc_priv_write_reg_6 (102, "priv_write_reg_6", OpcodeType.PRIVELEGED),
opc_priv_write_reg_7 (103, "priv_write_reg_7", OpcodeType.PRIVELEGED),
opc_priv_write_reg_8 (104, "priv_write_reg_8", OpcodeType.PRIVELEGED),
opc_priv_write_reg_9 (105, "priv_write_reg_9", OpcodeType.PRIVELEGED),
opc_priv_write_reg_10 (106, "priv_write_reg_10", OpcodeType.PRIVELEGED),
opc_priv_write_reg_11 (107, "priv_write_reg_11", OpcodeType.PRIVELEGED),
opc_priv_write_reg_12 (108, "priv_write_reg_12", OpcodeType.PRIVELEGED),
opc_priv_write_reg_13 (109, "priv_write_reg_13", OpcodeType.PRIVELEGED),
opc_priv_write_reg_14 (110, "priv_write_reg_14", OpcodeType.PRIVELEGED),
opc_priv_write_reg_15 (111, "priv_write_reg_15", OpcodeType.PRIVELEGED),
opc_priv_write_reg_16 (112, "priv_write_reg_16", OpcodeType.PRIVELEGED),
opc_priv_write_reg_17 (113, "priv_write_reg_17", OpcodeType.PRIVELEGED),
opc_priv_write_reg_18 (114, "priv_write_reg_18", OpcodeType.PRIVELEGED),
opc_priv_write_reg_19 (115, "priv_write_reg_19", OpcodeType.PRIVELEGED),
opc_priv_write_reg_20 (116, "priv_write_reg_20", OpcodeType.PRIVELEGED),
opc_priv_write_reg_21 (117, "priv_write_reg_21", OpcodeType.PRIVELEGED),
opc_priv_write_reg_22 (118, "priv_write_reg_22", OpcodeType.PRIVELEGED),
opc_priv_write_reg_23 (119, "priv_write_reg_23", OpcodeType.PRIVELEGED),
opc_priv_write_reg_24 (120, "priv_write_reg_24", OpcodeType.PRIVELEGED),
opc_priv_write_reg_25 (121, "priv_write_reg_25", OpcodeType.PRIVELEGED),
opc_priv_write_reg_26 (122, "priv_write_reg_26", OpcodeType.PRIVELEGED),
opc_priv_write_reg_27 (123, "priv_write_reg_27", OpcodeType.PRIVELEGED),
opc_priv_write_reg_28 (124, "priv_write_reg_28", OpcodeType.PRIVELEGED),
opc_priv_write_reg_29 (125, "priv_write_reg_29", OpcodeType.PRIVELEGED),
opc_priv_write_reg_30 (126, "priv_write_reg_30", OpcodeType.PRIVELEGED),
opc_priv_write_reg_31 (127, "priv_write_reg_31", OpcodeType.PRIVELEGED);
private Integer value;
private String parsekey;
private String alias;
private Integer length;
private Integer baseVal;
private OpcodeType type;
Opcode(Integer val, String parse, OpcodeType tp) {
init(val, parse, null, 2, tp);
}
Opcode(Integer val, String parse, int len, OpcodeType tp) {
init(val, parse, null, len, tp);
}
Opcode(Integer val, String parse) {
init(val, parse, null, 2, OpcodeType.NORMAL);
}
Opcode(Integer val, String parse, int len) {
init(val, parse, null, len, OpcodeType.NORMAL);
}
Opcode(Integer val, String parse, String als, int len) {
init(val, parse, als, len, OpcodeType.NORMAL);
}
Opcode(Integer val, String parse, String als, int len, OpcodeType tp) {
init(val, parse, als, len, tp);
}
private void init(Integer val, String parse, String als, int len, OpcodeType tp) {
type = tp;
baseVal = null;
switch (tp) {
case NORMAL:
value = val;
break;
case WIDE:
value = (opc_wide.value << 8) | val;
break;
case PRIVELEGED:
value = (opc_priv.value * 0xFF) + val;
baseVal = val;
break;
case NONPRIVELEGED:
value = (opc_nonpriv.value * 0xFF) + val;
baseVal = val;
break;
}
parsekey = parse;
alias = als;
length = len;
}
public Integer value() {
return value;
}
public int length() {
return length;
}
public String parsekey() {
return parsekey;
}
public OpcodeType type() {
return type;
}
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
/**
*
*/
public class ParseBase {
protected boolean debugFlag;
protected Scanner scanner;
protected Parser parser;
protected Environment env;
public ParseBase() {
init(null, null, null);
}
public void init(Scanner scnr, Parser prsr, Environment envr) {
debugFlag = false;
scanner = scnr;
parser = prsr;
env = envr;
}
public void enableDebug(boolean debState) {
debugFlag = debState;
}
protected void debugStr(String str) {
if (debugFlag) {
env.traceln(str);
}
}
protected void debugScan(String str) {
if (debugFlag) {
scanner.debugScan(str);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,587 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import static org.openjdk.asmtools.jasm.JasmTokens.*;
import static org.openjdk.asmtools.jasm.Tables.*;
import java.io.IOException;
import java.util.ArrayList;
/**
* ParserCP
*
* ParseCP is a parser class owned by Parser.java. It is primarily responsible for parsing
* the constant pool and constant declarations.
*/
public class ParserCP extends ParseBase {
/**
* local handles on the scanner, main parser, and the error reporting env
*/
/**
* Visitor object
*/
private ParserCPVisitor pConstVstr;
/**
* main constructor
*
* @param scanner
* @param parser
* @param env
*/
protected ParserCP(Scanner scanner, Parser parser, Environment env) {
super.init(scanner, parser, env);
pConstVstr = new ParserCPVisitor();
}
/**
* ParserCPVisitor
*
* This inner class overrides a constant pool visitor to provide specific parsing
* instructions (per method) for each type of Constant.
*
* Note: since the generic visitor throws no exceptions, this derived class tunnels
* the exceptions, rethrown in the visitEcept method.
*/
class ParserCPVisitor extends ConstantPool.CPTagVisitor<ConstantPool.ConstValue> {
private IOException IOProb;
private Scanner.SyntaxError SyProb;
public ParserCPVisitor() {
IOProb = null;
SyProb = null;
}
//This is the entry point for a visitor that tunnels exceptions
public ConstantPool.ConstValue visitExcept(ConstType tag) throws IOException, Scanner.SyntaxError {
IOProb = null;
SyProb = null;
debugStr("------- [ParserCPVisitor.visitExcept]: ");
ConstantPool.ConstValue ret = visit(tag);
if (IOProb != null) {
throw IOProb;
}
if (SyProb != null) {
throw SyProb;
}
return ret;
}
@Override
public ConstantPool.ConstValue visitUTF8(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitUTF8]: ");
try {
scanner.expect(Token.STRINGVAL);
} catch (IOException e) {
IOProb = e;
}
ConstantPool.ConstValue_String obj
= new ConstantPool.ConstValue_String(scanner.stringValue);
return obj;
}
@Override
public ConstantPool.ConstValue visitInteger(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitInteger]: ");
ConstantPool.ConstValue_Integer obj;
int v = 0;
try {
if (scanner.token == Token.BITS) {
scanner.scan();
scanner.inBits = true;
}
v = scanner.intValue * scanner.sign;
scanner.expect(Token.INTVAL);
} catch (IOException e) {
IOProb = e;
}
obj = new ConstantPool.ConstValue_Integer(tag, new Integer(v));
return obj;
}
@Override
public ConstantPool.ConstValue visitLong(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitLong]: ");
ConstantPool.ConstValue_Long obj = null;
try {
long v;
if (scanner.token == Token.BITS) {
scanner.scan();
scanner.inBits = true;
}
switch (scanner.token) {
case INTVAL:
v = scanner.intValue;
break;
case LONGVAL:
v = scanner.longValue;
break;
default:
env.error(scanner.prevPos, "token.expected", "Integer");
throw new Scanner.SyntaxError();
}
obj = new ConstantPool.ConstValue_Long(tag, new Long(v * scanner.sign));
scanner.scan();
} catch (IOException e) {
IOProb = e;
} catch (Scanner.SyntaxError e) {
SyProb = e;
}
return obj;
}
@Override
public ConstantPool.ConstValue visitFloat(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitFloat]: ");
ConstantPool.ConstValue_Integer obj = null;
try {
int v;
float f;
scanner.inBits = false; // this needs to be initialized for each float!
if (scanner.token == Token.BITS) {
scanner.scan();
scanner.inBits = true;
}
i2f: {
switch (scanner.token) {
case INTVAL:
if (scanner.inBits) {
v = scanner.intValue;
break i2f;
} else {
f = (float) scanner.intValue;
break;
}
case FLOATVAL:
f = scanner.floatValue;
break;
case DOUBLEVAL:
f = (float) scanner.doubleValue; // to be excluded?
break;
case INF:
f = Float.POSITIVE_INFINITY;
break;
case NAN:
f = Float.NaN;
break;
default:
env.traceln("token=" + scanner.token);
env.error(scanner.pos, "token.expected", "<Float>");
throw new Scanner.SyntaxError();
}
v = Float.floatToIntBits(f);
}
if (scanner.sign == -1) {
v = v ^ 0x80000000;
}
obj = new ConstantPool.ConstValue_Integer(tag, new Integer(v));
scanner.scan();
} catch (IOException e) {
IOProb = e;
} catch (Scanner.SyntaxError e) {
SyProb = e;
}
return obj;
}
@Override
public ConstantPool.ConstValue visitDouble(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitDouble]: ");
ConstantPool.ConstValue_Long obj = null;
try {
long v;
double d;
if (scanner.token == Token.BITS) {
scanner.scan();
scanner.inBits = true;
}
d2l: {
switch (scanner.token) {
case INTVAL:
if (scanner.inBits) {
v = scanner.intValue;
break d2l;
} else {
d = (double) scanner.intValue;
break;
}
case LONGVAL:
if (scanner.inBits) {
v = scanner.longValue;
break d2l;
} else {
d = (double) scanner.longValue;
break;
}
case FLOATVAL:
d = scanner.floatValue;
break;
case DOUBLEVAL:
d = scanner.doubleValue;
break;
case INF:
d = Double.POSITIVE_INFINITY;
break;
case NAN:
d = Double.NaN;
break;
default:
env.error(scanner.pos, "token.expected", "Double");
throw new Scanner.SyntaxError();
}
v = Double.doubleToLongBits(d);
}
if (scanner.sign == -1) {
v = v ^ 0x8000000000000000L;
}
obj = new ConstantPool.ConstValue_Long(tag, new Long(v));
scanner.scan();
} catch (IOException e) {
IOProb = e;
} catch (Scanner.SyntaxError e) {
SyProb = e;
}
return obj;
}
private ConstantPool.ConstCell visitName(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitName]: ");
ConstantPool.ConstCell obj = null;
try {
obj = parser.parseName();
} catch (IOException e) {
IOProb = e;
}
return obj;
}
@Override
public ConstantPool.ConstValue visitMethodtype(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitMethodtype]: ");
ConstantPool.ConstValue_Cell obj = null;
ConstantPool.ConstCell cell = visitName(tag);
if (IOProb == null) {
obj = new ConstantPool.ConstValue_Cell(tag, cell);
}
return obj;
}
@Override
public ConstantPool.ConstValue visitString(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitString]: ");
ConstantPool.ConstValue_Cell obj = null;
ConstantPool.ConstCell cell = visitName(tag);
if (IOProb == null) {
obj = new ConstantPool.ConstValue_Cell(tag, cell);
}
return obj;
}
@Override
public ConstantPool.ConstValue visitClass(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitClass]: ");
ConstantPool.ConstValue_Cell obj = null;
try {
ConstantPool.ConstCell cell = parser.parseClassName(true);
obj = new ConstantPool.ConstValue_Cell(tag, cell);
} catch (IOException e) {
IOProb = e;
}
return obj;
}
@Override
public ConstantPool.ConstValue visitMethodhandle(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitMethodHandle]: ");
ConstantPool.ConstValue_Pair obj = null;
try {
ConstantPool.ConstCell refCell;
ConstantPool.ConstCell subtagCell;
SubTag subtag;
if (scanner.token == Token.INTVAL) {
// Handle explicit constant pool form
subtag = subtag(scanner.intValue);
subtagCell = new ConstantPool.ConstCell(subtag.value());
scanner.scan();
scanner.expect(Token.COLON);
if (scanner.token != Token.CPINDEX) {
env.traceln("token=" + scanner.token);
env.error(scanner.pos, "token.expected", "<CPINDEX>");
throw new Scanner.SyntaxError();
}
int cpx = scanner.intValue;
refCell = parser.pool.getCell(cpx);
scanner.scan();
} else {
// normal JASM
subtag = parser.parseSubtag();
subtagCell = new ConstantPool.ConstCell(subtag.value());
scanner.expect(Token.COLON);
refCell = parser.parseMethodHandle(subtag);
}
obj = new ConstantPool.ConstValue_Pair(tag, subtagCell, refCell);
} catch (IOException e) {
IOProb = e;
}
return obj;
}
private ConstantPool.ConstValue_Pair visitMember(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitMember]: ");
ConstantPool.ConstValue_Pair obj = null;
try {
Token prevtoken = scanner.token;
ConstantPool.ConstCell firstName, ClassCell, NameCell, NapeCell;
firstName = parser.parseClassName(false);
if (scanner.token == Token.FIELD) { // DOT
scanner.scan();
if (prevtoken == Token.CPINDEX) {
ClassCell = firstName;
} else {
ClassCell = parser.pool.FindCell(ConstType.CONSTANT_CLASS, firstName);
}
NameCell = parser.parseName();
} else {
// no class provided - assume current class
ClassCell = parser.cd.me;
NameCell = firstName;
}
if (scanner.token == Token.COLON) {
// name and type separately
scanner.scan();
NapeCell = parser.pool.FindCell(ConstType.CONSTANT_NAMEANDTYPE, NameCell, parser.parseName());
} else {
// name and type as single name
NapeCell = NameCell;
}
obj = new ConstantPool.ConstValue_Pair(tag, ClassCell, NapeCell);
} catch (IOException e) {
IOProb = e;
}
return obj;
}
@Override
public ConstantPool.ConstValue visitField(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitField]: ");
return visitMember(tag);
}
@Override
public ConstantPool.ConstValue visitMethod(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitMethod]: ");
return visitMember(tag);
}
@Override
public ConstantPool.ConstValue visitInterfacemethod(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitInterfacemethod]: ");
return visitMember(tag);
}
@Override
public ConstantPool.ConstValue visitNameandtype(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitNameandtype]: ");
ConstantPool.ConstValue_Pair obj = null;
try {
ConstantPool.ConstCell NameCell = parser.parseName(), TypeCell;
scanner.expect(Token.COLON);
TypeCell = parser.parseName();
obj = new ConstantPool.ConstValue_Pair(tag, NameCell, TypeCell);
} catch (IOException e) {
IOProb = e;
}
return obj;
}
@Override
public ConstantPool.ConstValue_IndyPair visitInvokedynamic(ConstType tag) {
debugStr("------- [ParserCPVisitor.visitInvokeDynamic]: ");
ConstantPool.ConstValue_IndyPair obj = null;
try {
if (scanner.token == Token.INTVAL) {
// Handle explicit constant pool form
int bsmIndex = scanner.intValue;
scanner.scan();
scanner.expect(Token.COLON);
if (scanner.token != Token.CPINDEX) {
env.traceln("token=" + scanner.token);
env.error(scanner.pos, "token.expected", "<CPINDEX>");
throw new Scanner.SyntaxError();
}
int cpx = scanner.intValue;
scanner.scan();
// Put a placeholder in place of BSM.
// resolve placeholder after the attributes are scanned.
BootstrapMethodData bsmData = new BootstrapMethodData(bsmIndex);
obj = new ConstantPool.ConstValue_IndyPair(bsmData, parser.pool.getCell(cpx));
} else {
// Handle full form
ConstantPool.ConstCell MHCell = parser.pool.FindCell(parseConstValue(ConstType.CONSTANT_METHODHANDLE));
scanner.expect(Token.COLON);
ConstantPool.ConstCell NapeCell = parser.pool.FindCell(parseConstValue(ConstType.CONSTANT_NAMEANDTYPE));
ArrayList<ConstantPool.ConstCell> bsm_args = new ArrayList<>(256);
while (scanner.token != Token.SEMICOLON) {
if (scanner.token == Token.COMMA) {
scanner.scan();
}
bsm_args.add(parseConstRef(null));
}
BootstrapMethodData bsmData = new BootstrapMethodData(MHCell, bsm_args);
parser.cd.addBootstrapMethod(bsmData);
obj = new ConstantPool.ConstValue_IndyPair(bsmData, NapeCell);
}
} catch (IOException e) {
IOProb = e;
}
return obj;
}
} // End Visitor
/**
* Parse CONSTVALUE
*/
protected ConstantPool.ConstValue parseConstValue(ConstType tag) throws IOException, Scanner.SyntaxError {
return pConstVstr.visitExcept(tag);
}
/**
* Parse [TAG] CONSTVALUE
*/
protected ConstantPool.ConstValue parseTagConstValue(ConstType defaultTag) throws Scanner.SyntaxError, IOException {
return parseTagConstValue(defaultTag, null, false);
}
private ConstType scanConstByID(boolean ignoreKeywords) {
ConstType tag = null;
if (!ignoreKeywords) {
ConstType tg = Tables.tag(scanner.idValue);
if (tg != null) {
tag = tg;
}
debugStr(" *^*^*^*^ [ParserCP.scanConst]: {TAG = " + (tg == null ? "null" : tg.toString()) + " ");
}
return tag;
}
private ConstType scanConstPrimVal() throws Scanner.SyntaxError, IOException {
ConstType tag = null;
switch (scanner.token) {
case INTVAL:
tag = ConstType.CONSTANT_INTEGER;
break;
case LONGVAL:
tag = ConstType.CONSTANT_LONG;
break;
case FLOATVAL:
tag = ConstType.CONSTANT_FLOAT;
break;
case DOUBLEVAL:
tag = ConstType.CONSTANT_DOUBLE;
break;
case STRINGVAL:
case BITS:
case IDENT:
tag = ConstType.CONSTANT_STRING;
break;
default:
// problem - no constant value
System.err.println("NEAR: " + scanner.token.printval());
env.error(scanner.pos, "value.expected");
throw new Scanner.SyntaxError();
}
return tag;
}
private void checkWrongTag(ConstType tag, ConstType defaultTag, ConstType default2Tag) throws Scanner.SyntaxError, IOException {
if (defaultTag != null) {
if (tag != defaultTag) {
if (default2Tag == null) {
env.error("warn.wrong.tag", defaultTag.parseKey());
} else if (tag != default2Tag) {
env.error("warn.wrong.tag2", defaultTag.parseKey(), default2Tag.parseKey());
}
}
}
}
protected ConstantPool.ConstValue parseTagConstValue(ConstType defaultTag, ConstType default2Tag, boolean ignoreKeywords) throws Scanner.SyntaxError, IOException {
debugScan(" *^*^*^*^ [ParserCP.parseTagConstValue]: Begin default_tag: ignoreKeywords: " + (ignoreKeywords ? "true" : "false"));
// Lookup the Tag from the scanner
ConstType tag = scanConstByID(ignoreKeywords);
debugStr(" *^*^*^*^ [ParserCP.parseTagConstValue]: {tag = " + tag + ", defaulttag = " + defaultTag + "} ");
// If the scanned tag is null
if (tag == null) {
// and, if the expected tag is null
if (defaultTag == null) {
// return some other type of constant as the tag
tag = scanConstPrimVal();
} else {
// otherwise, make the scanned-tag the same constant-type
// as the expected tag.
tag = defaultTag;
}
} else {
// If the scanned tag is some constant type
// and the scanned type does not equal the expected type
checkWrongTag(tag, defaultTag, default2Tag);
scanner.scan();
}
return parseConstValue(tag);
} // end parseTagConstValue
protected ConstantPool.ConstCell parseConstRef(ConstType defaultTag) throws Scanner.SyntaxError, IOException {
return parseConstRef(defaultTag, null, false);
}
protected ConstantPool.ConstCell parseConstRef(ConstType defaultTag, ConstType default2Tag) throws Scanner.SyntaxError, IOException {
return parseConstRef(defaultTag, default2Tag, false);
}
/**
* Parse an instruction argument, one of: * #NUMBER, #NAME, [TAG] CONSTVALUE
*/
protected ConstantPool.ConstCell parseConstRef(ConstType defaultTag,
ConstType default2Tag,
boolean ignoreKeywords) throws Scanner.SyntaxError, IOException {
if (scanner.token == Token.CPINDEX) {
int cpx = scanner.intValue;
scanner.scan();
return parser.pool.getCell(cpx);
} else {
ConstantPool.ConstValue ref = null;
ref = parseTagConstValue(defaultTag, default2Tag, ignoreKeywords);
return parser.pool.FindCell(ref);
}
} // end parseConstRef
}

View File

@ -0,0 +1,405 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import static org.openjdk.asmtools.jasm.JasmTokens.*;
import static org.openjdk.asmtools.jasm.Tables.*;
import static org.openjdk.asmtools.jasm.OpcodeTables.*;
import java.io.IOException;
/**
* ParserInstr
*
* ParserInstr is a parser class owned by Parser.java. It is primarily responsible for
* parsing instruction byte codes.
*/
public class ParserInstr extends ParseBase {
/**
* local handle for the constant parser - needed for parsing constants during
* instruction construction.
*/
private ParserCP cpParser = null;
/**
* main constructor
*
* @param scanner
* @param parser
* @param env
*/
protected ParserInstr(Scanner scanner, Parser parser, ParserCP cpParser, Environment env) {
super.init(scanner, parser, env);
this.cpParser = cpParser;
}
/**
* Parse an instruction.
*/
protected void parseInstr() throws Scanner.SyntaxError, IOException {
// ignore possible line numbers after java disassembler
if (scanner.token == Token.INTVAL) {
scanner.scan();
}
// ignore possible numeric labels after java disassembler
if (scanner.token == Token.INTVAL) {
scanner.scan();
}
if (scanner.token == Token.COLON) {
scanner.scan();
}
String mnemocode;
int mnenoc_pos;
for (;;) { // read labels
if (scanner.token != Token.IDENT) {
return;
}
mnemocode = scanner.idValue;
mnenoc_pos = scanner.pos;
scanner.scan();
if (scanner.token != Token.COLON) {
break;
}
// actually it was a label
scanner.scan();
parser.curCode.LabelDef(mnenoc_pos, mnemocode);
}
Opcode opcode = OpcodeTables.opcode(mnemocode);
if (opcode == null) {
debugScan(" %%error%%error%%% $$$$$$$$$$$$$$$ mnemocode = '" + mnemocode + "'. ");
}
OpcodeType optype = opcode.type();
Argument arg = null;
Object arg2 = null;
StackMapData sMap = null;
debugScan(" --IIIII---[ParserInstr:[parseInstr]: (Pos: " + mnenoc_pos + ") mnemocode: '" + opcode.parsekey() + "' ");
switch (optype) {
case NORMAL:
switch (opcode) {
// pseudo-instructions:
case opc_bytecode:
for (;;) {
parser.curCode.addInstr(mnenoc_pos, Opcode.opc_bytecode, parser.parseUInt(1), null);
if (scanner.token != Token.COMMA) {
return;
}
scanner.scan();
}
case opc_try:
for (;;) {
parser.curCode.beginTrap(scanner.pos, parser.parseIdent());
if (scanner.token != Token.COMMA) {
return;
}
scanner.scan();
}
case opc_endtry:
for (;;) {
parser.curCode.endTrap(scanner.pos, parser.parseIdent());
if (scanner.token != Token.COMMA) {
return;
}
scanner.scan();
}
case opc_catch:
parser.curCode.trapHandler(scanner.pos, parser.parseIdent(),
cpParser.parseConstRef(ConstType.CONSTANT_CLASS));
return;
case opc_var:
for (;;) {
parser.parseLocVarDef();
if (scanner.token != Token.COMMA) {
return;
}
scanner.scan();
}
case opc_endvar:
for (;;) {
parser.parseLocVarEnd();
if (scanner.token != Token.COMMA) {
return;
}
scanner.scan();
}
case opc_locals_map:
sMap = parser.curCode.getStackMap();
if (sMap.localsMap != null) {
env.error(scanner.pos, "localsmap.repeated");
}
;
DataVector localsMap = new DataVector();
sMap.localsMap = localsMap;
if (scanner.token == Token.SEMICOLON) {
return; // empty locals_map allowed
}
for (;;) {
parser.parseMapItem(localsMap);
if (scanner.token != Token.COMMA) {
return;
}
scanner.scan();
}
case opc_stack_map:
sMap = parser.curCode.getStackMap();
if (sMap.stackMap != null) {
env.error(scanner.pos, "stackmap.repeated");
}
;
DataVector stackMap = new DataVector();
sMap.stackMap = stackMap;
if (scanner.token == Token.SEMICOLON) {
return; // empty stack_map allowed
}
for (;;) {
parser.parseMapItem(stackMap);
if (scanner.token != Token.COMMA) {
return;
}
scanner.scan();
}
case opc_stack_frame_type:
sMap = parser.curCode.getStackMap();
if (sMap.stackFrameType != null) {
env.error(scanner.pos, "frametype.repeated");
}
;
sMap.setStackFrameType(parser.parseIdent());
return;
// normal instructions:
case opc_aload:
case opc_astore:
case opc_fload:
case opc_fstore:
case opc_iload:
case opc_istore:
case opc_lload:
case opc_lstore:
case opc_dload:
case opc_dstore:
case opc_ret:
case opc_aload_w:
case opc_astore_w:
case opc_fload_w:
case opc_fstore_w:
case opc_iload_w:
case opc_istore_w:
case opc_lload_w:
case opc_lstore_w:
case opc_dload_w:
case opc_dstore_w:
case opc_ret_w:
// loc var
arg = parser.parseLocVarRef();
break;
case opc_iinc: // loc var, const
arg = parser.parseLocVarRef();
scanner.expect(Token.COMMA);
arg2 = parser.parseInt(1);
break;
case opc_tableswitch:
case opc_lookupswitch:
arg2 = parseSwitchTable();
break;
case opc_newarray: {
int type;
if (scanner.token == Token.INTVAL) {
type = scanner.intValue;
} else if ((type = Tables.basictypeValue(scanner.idValue)) == -1) {
env.error(scanner.pos, "type.expected");
throw new Scanner.SyntaxError();
}
scanner.scan();
arg = new Argument(type);
break;
}
case opc_new:
case opc_anewarray:
case opc_instanceof:
case opc_checkcast:
arg = cpParser.parseConstRef(ConstType.CONSTANT_CLASS);
break;
case opc_bipush:
arg = parser.parseInt(1);
break;
case opc_sipush:
arg = parser.parseInt(2);
break;
case opc_ldc:
case opc_ldc_w:
case opc_ldc2_w:
arg = cpParser.parseConstRef(null);
break;
case opc_putstatic:
case opc_getstatic:
case opc_putfield:
case opc_getfield:
arg = cpParser.parseConstRef(ConstType.CONSTANT_FIELD);
break;
case opc_invokevirtual:
arg = cpParser.parseConstRef(ConstType.CONSTANT_METHOD);
break;
case opc_invokestatic:
case opc_invokespecial:
arg = cpParser.parseConstRef(ConstType.CONSTANT_METHOD, ConstType.CONSTANT_INTERFACEMETHOD);
break;
case opc_jsr:
case opc_goto:
case opc_ifeq:
case opc_ifge:
case opc_ifgt:
case opc_ifle:
case opc_iflt:
case opc_ifne:
case opc_if_icmpeq:
case opc_if_icmpne:
case opc_if_icmpge:
case opc_if_icmpgt:
case opc_if_icmple:
case opc_if_icmplt:
case opc_if_acmpeq:
case opc_if_acmpne:
case opc_ifnull:
case opc_ifnonnull:
case opc_jsr_w:
case opc_goto_w:
arg = parseLabelRef();
break;
case opc_invokeinterface:
arg = cpParser.parseConstRef(ConstType.CONSTANT_INTERFACEMETHOD);
scanner.expect(Token.COMMA);
arg2 = parser.parseUInt(1);
break;
case opc_invokedynamic:
arg = cpParser.parseConstRef(ConstType.CONSTANT_INVOKEDYNAMIC);
break;
case opc_multianewarray:
arg = cpParser.parseConstRef(ConstType.CONSTANT_CLASS);
scanner.expect(Token.COMMA);
arg2 = parser.parseUInt(1);
break;
case opc_wide:
case opc_nonpriv:
case opc_priv:
int opc2 = (opcode.value() << 8) | parser.parseUInt(1).arg;
opcode = opcode(opc2);
break;
}
break;
case WIDE:
arg = parser.parseLocVarRef();
if (opcode == Opcode.opc_iinc_w) { // loc var, const
scanner.expect(Token.COMMA);
arg2 = parser.parseInt(2);
}
break;
case NONPRIVELEGED:
case PRIVELEGED:
break;
default:
env.error(scanner.prevPos, "wrong.mnemocode", mnemocode);
throw new Scanner.SyntaxError();
}
// env.traceln(" [ParserInstr.parseInstr] ===============> Adding Instruction: [" + mnenoc_pos + "]: instr: "+ mnemocode /* opcNamesTab[opc] */);
parser.curCode.addInstr(mnenoc_pos, opcode, arg, arg2);
} //end parseInstr
/**
* Parse a Switch Table. return value: SwitchTable.
*/
protected SwitchTable parseSwitchTable() throws Scanner.SyntaxError, IOException {
scanner.expect(Token.LBRACE);
Argument label;
int numpairs = 0, key;
SwitchTable table = new SwitchTable(env);
tableScan:
{
while (numpairs < 1000) {
// env.traceln("start tableScan:" + token);
switch (scanner.token) {
case INTVAL:
// env.traceln("enter tableScan:" + token);
key = scanner.intValue * scanner.sign;
scanner.scan();
scanner.expect(Token.COLON);
table.addEntry(key, parseLabelRef());
numpairs++;
if (scanner.token != Token.SEMICOLON) {
// env.traceln("break tableScan1:" + token);
break tableScan;
}
scanner.scan();
break;
case DEFAULT:
scanner.scan();
scanner.expect(Token.COLON);
if (table.deflabel != null) {
env.error("default.redecl");
}
table.deflabel = parseLabelRef();
if (scanner.token != Token.SEMICOLON) {
// env.traceln("break tableScan2:" + token);
break tableScan;
}
scanner.scan();
break;
default:
// env.traceln("break tableScan3:" + token + "val=" + intValue);
break tableScan;
} // end switch
} // while (numpairs<1000)
env.error("long.switchtable", "1000");
} // end tableScan
scanner.expect(Token.RBRACE);
return table;
} // end parseSwitchTable
/**
* Parse a label instruction argument
*/
protected Argument parseLabelRef() throws Scanner.SyntaxError, IOException {
switch (scanner.token) {
case INTVAL: {
int v = scanner.intValue * scanner.sign;
scanner.scan();
return new Argument(v);
}
case IDENT: {
String label = scanner.stringValue;
scanner.scan();
return parser.curCode.LabelRef(label);
}
}
env.error("label.expected");
throw new Scanner.SyntaxError();
}
}

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
/**
*
*/
public interface RuntimeConstants {
/* Signature Characters */
public static final char SIGC_VOID = 'V';
public static final String SIG_VOID = "V";
public static final char SIGC_BOOLEAN = 'Z';
public static final String SIG_BOOLEAN = "Z";
public static final char SIGC_BYTE = 'B';
public static final String SIG_BYTE = "B";
public static final char SIGC_CHAR = 'C';
public static final String SIG_CHAR = "C";
public static final char SIGC_SHORT = 'S';
public static final String SIG_SHORT = "S";
public static final char SIGC_INT = 'I';
public static final String SIG_INT = "I";
public static final char SIGC_LONG = 'J';
public static final String SIG_LONG = "J";
public static final char SIGC_FLOAT = 'F';
public static final String SIG_FLOAT = "F";
public static final char SIGC_DOUBLE = 'D';
public static final String SIG_DOUBLE = "D";
public static final char SIGC_ARRAY = '[';
public static final String SIG_ARRAY = "[";
public static final char SIGC_CLASS = 'L';
public static final String SIG_CLASS = "L";
public static final char SIGC_METHOD = '(';
public static final String SIG_METHOD = "(";
public static final char SIGC_ENDCLASS = ';';
public static final String SIG_ENDCLASS = ";";
public static final char SIGC_ENDMETHOD = ')';
public static final String SIG_ENDMETHOD = ")";
public static final char SIGC_PACKAGE = '/';
public static final String SIG_PACKAGE = "/";
/* Class File Constants */
// public static final int JAVA_MAGIC = 0xcafebabe;
public static final int JAVA_VERSION = 45;
public static final int JAVA_MINOR_VERSION = 3;
/* Access Flags */
public static final int ACC_PUBLIC = 0x0001; // class, inner, field, method
public static final int ACC_PRIVATE = 0x0002; // inner, field, method
public static final int ACC_PROTECTED = 0x0004; // inner, field, method
public static final int ACC_STATIC = 0x0008; // inner, field, method
public static final int ACC_FINAL = 0x0010; // class, inner, field, method
public static final int ACC_SUPER = 0x0020; // class
public static final int ACC_SYNCHRONIZED = 0x0020; // method
public static final int ACC_VOLATILE = 0x0040; // field
public static final int ACC_BRIDGE = 0x0040; // method
public static final int ACC_TRANSIENT = 0x0080; // field
public static final int ACC_VARARGS = 0x0080; // method
public static final int ACC_NATIVE = 0x0100; // method
public static final int ACC_INTERFACE = 0x0200; // class, inner
public static final int ACC_ABSTRACT = 0x0400; // class, inner, method
public static final int ACC_STRICT = 0x0800; // method
public static final int ACC_SYNTHETIC = 0x1000; // class, inner, field, method
public static final int ACC_ANNOTATION = 0x2000; // class, inner
public static final int ACC_ENUM = 0x4000; // class, inner, field
// public static final int ACC_MODULE = 0x8000; // class, inner, field, method
public static final int ACC_MANDATED = 0x8000; // method
/* Attribute codes */
public static final int SYNTHETIC_ATTRIBUTE = 0x00010000; // actually, this is an attribute
public static final int DEPRECATED_ATTRIBUTE = 0x00020000; // actually, this is an attribute
/* The version of a class file since which the compact format of stack map
* is necessary */
public final int SPLIT_VERIFIER_CFV = 50;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,281 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import static org.openjdk.asmtools.jasm.Tables.*;
import java.io.IOException;
/**
*
*/
public class StackMapData implements Data {
/**
*
*/
static public class StackMapItem1 implements Data {
StackMapType itemType;
StackMapItem1(StackMapType itemType) {
this.itemType = itemType;
}
@Override
public int getLength() {
return 1;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeByte(itemType.value());
}
}
/**
*
*/
static public class StackMapItem2 implements Data {
StackMapType itemType;
Argument arg;
StackMapItem2(StackMapType itemType, Argument arg) {
this.itemType = itemType;
this.arg = arg;
}
@Override
public int getLength() {
return 3;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeByte(itemType.value());
out.writeShort(arg.arg);
}
}
int pc;
int offset;
int type;
String stackFrameType = null;
boolean isStackMapTable = false;
DataVector localsMap, stackMap;
Environment env;
StackMapData(Environment env) {
this.env = env;
}
void setPC(int pc) {
this.pc = pc;
}
void setOffset(int offset) {
this.offset = offset;
}
void setOffset(StackMapData prevFrame) {
offset = (prevFrame == null) ? pc : (pc - prevFrame.pc - 1);
}
void setStackFrameType(String stackFrameType) {
this.stackFrameType = stackFrameType;
if (stackFrameType != null) {
type = stackMapFrameTypeValue(stackFrameType);
}
if (stackFrameType == null || type == -1) {
env.error(pc, "invalid.stack.frame.type", stackFrameType, "" + type);
}
}
void setIsStackMapTable(boolean isStackMapTable) {
this.isStackMapTable = isStackMapTable;
}
void setLocalsMap(DataVector localsMap) {
this.localsMap = localsMap;
}
void setStackMap(DataVector stackMap) {
this.stackMap = stackMap;
}
@Override
public int getLength() {
int res = 0;
StackMapFrameType frame_type = StackMapFrameType.FULL_FRAME;
// int frame_type = FULL_FRAME;
if (isStackMapTable) {
if (stackFrameType != null) {
frame_type = stackMapFrameType(type);
}
res += 1;
}
switch (frame_type) {
case SAME_FRAME:
break;
case SAME_LOCALS_1_STACK_ITEM_FRAME:
res += stackMap.getLength() - 2;
break;
case SAME_LOCALS_1_STACK_ITEM_EXTENDED_FRAME:
res += stackMap.getLength();
break;
case CHOP_1_FRAME:
case CHOP_2_FRAME:
case CHOP_3_FRAME:
res += 2;
break;
case SAME_FRAME_EX:
res += 2;
break;
case APPEND_FRAME:
res += 2 + (localsMap == null ? 0 : (localsMap.getLength() - 2));
break;
case FULL_FRAME:
res += 2;
res += (localsMap == null ? 2 : localsMap.getLength());
res += (stackMap == null ? 2 : stackMap.getLength());
break;
default:
;
}
return res;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
StackMapFrameType frame_type = StackMapFrameType.FULL_FRAME;
if (isStackMapTable) {
if (stackFrameType != null) {
frame_type = stackMapFrameType(type);
}
}
switch (frame_type) {
case SAME_FRAME:
if (offset >= 64) {
env.error(pc, "invalid.offset.same.frame", "" + offset);
}
out.writeByte(offset);
break;
case SAME_LOCALS_1_STACK_ITEM_FRAME:
if (stackMap == null) {
env.error(pc, "no.stack.map.same.locals");
break;
}
if (stackMap.elements.size() != 1) {
env.error(pc, "should.be.only.one.stack.map.element");
break;
}
if (offset >= 64) {
env.error(pc, "invalid.offset.same.locals", "" + offset);
break;
}
out.writeByte(frame_type.value() + offset);
stackMap.writeElements(out);
break;
case SAME_LOCALS_1_STACK_ITEM_EXTENDED_FRAME:
if (stackMap == null) {
env.error(pc, "no.stack.map.same.locals");
break;
}
if (stackMap.elements.size() != 1) {
env.error(pc, "should.be.only.one.stack.map.element");
break;
}
out.writeByte(frame_type.value());
out.writeShort(offset);
stackMap.writeElements(out);
break;
case CHOP_1_FRAME:
case CHOP_2_FRAME:
case CHOP_3_FRAME:
case SAME_FRAME_EX:
boolean error = false;
if (stackMap != null) {
env.error(pc, "unexpected.stack.maps");
error = true;
}
if (localsMap != null) {
env.error(pc, "unexpected.locals.maps");
error = true;
}
if (error) {
break;
}
out.writeByte(frame_type.value());
out.writeShort(offset);
break;
case APPEND_FRAME:
if (localsMap == null) {
env.error(pc, "no.locals.map.append");
break;
}
if (localsMap.elements.size() > 3) {
env.error(pc, "more.locals.map.elements");
break;
}
out.writeByte(frame_type.value() + localsMap.elements.size() - 1);
out.writeShort(offset);
localsMap.writeElements(out);
break;
case FULL_FRAME:
if (isStackMapTable) {
out.writeByte(frame_type.value());
out.writeShort(offset);
} else {
out.writeShort(pc);
}
if (localsMap == null) {
out.writeShort(0);
} else {
localsMap.write(out);
}
if (stackMap == null) {
out.writeShort(0);
} else {
stackMap.write(out);
}
break;
default:
env.error(pc, "invalid.stack.frame.type", "" + frame_type);
}
}
}

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.util.ArrayList;
/**
*
*/
class SwitchTable {
Argument deflabel = null;
ArrayList<Argument> labels = new ArrayList<>();
ArrayList<Integer> keys = new ArrayList<>();
// for tableswitch:
Argument[] resLabels;
int high, low;
int pc, pad;
Environment env;
SwitchTable(Environment env) {
this.env = env;
}
void addEntry(int key, Argument label) {
keys.add(key);
labels.add(label);
}
// for lookupswitch:
int calcLookupSwitch(int pc) {
this.pc = pc;
pad = ((3 - pc) & 0x3);
int len = 1 + pad + (keys.size() + 1) * 8;
if (deflabel == null) {
deflabel = new Argument(pc + len);
}
return len;
}
void writeLookupSwitch(CheckedDataOutputStream out) throws IOException {
env.traceln(" writeLookupSwitch: pc=" + pc + " pad=" + pad + " deflabel=" + deflabel.arg);
int k;
for (k = 0; k < pad; k++) {
out.writeByte(0);
}
out.writeInt(deflabel.arg - pc);
out.writeInt(keys.size());
for (k = 0; k < keys.size(); k++) {
out.writeInt(keys.get(k));
out.writeInt((labels.get(k)).arg - pc);
}
}
int recalcTableSwitch(int pc) {
int k;
int numpairs = keys.size();
int high1 = Integer.MIN_VALUE, low1 = Integer.MAX_VALUE;
int numslots = 0;
if (numpairs > 0) {
for (k = 0; k < numpairs; k++) {
int key = keys.get(k);
if (key > high1) {
high1 = key;
}
if (key < low1) {
low1 = key;
}
}
numslots = high1 - low1 + 1;
}
// if (numslots>2000) env.error("long.switchtable", "2000");
env.traceln(" recalcTableSwitch: low=" + low1 + " high=" + high1);
this.pc = pc;
pad = ((3 - pc) & 0x3);
int len = 1 + pad + (numslots + 3) * 4;
if (deflabel == null) {
deflabel = new Argument(pc + len);
}
Argument[] resLabels1 = new Argument[numslots];
for (k = 0; k < numslots; k++) {
resLabels1[k] = deflabel;
}
for (k = 0; k < numpairs; k++) {
env.traceln(" keys.data[" + k + "]=" + keys.get(k));
resLabels1[keys.get(k) - low1] = labels.get(k);
}
this.resLabels = resLabels1;
this.labels = null;
this.keys = null;
this.high = high1;
this.low = low1;
return len;
}
void writeTableSwitch(CheckedDataOutputStream out) throws IOException {
int k;
for (k = 0; k < pad; k++) {
out.writeByte(0);
}
out.writeInt(deflabel.arg - pc);
out.writeInt(low);
out.writeInt(high);
for (k = 0; k < resLabels.length; k++) {
out.writeInt(resLabels[k].arg - pc);
}
}
}

View File

@ -0,0 +1,653 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.PrintWriter;
import java.util.HashMap;
/**
*
* Tables
*
* The classes in Tables are following a Singleton Pattern. These classes are Enums, and
* they are contained in private hash maps (lookup tables and reverse lookup tables).
* These hash maps all have public accessors, which clients use to look-up enums.
*
* Tokens in this table carry no external state, and are typically treated as constants.
* They do not need to be reset.
*
*/
public class Tables {
public static final int JAVA_MAGIC = 0xCAFEBABE;
/**
* Lookup-tables for various types.
*/
private static HashMap<String, AttrTag> NameToAttrTag = new HashMap<>(9);
private static HashMap<Integer, AttrTag> AttrTags = new HashMap<>(9);
private static HashMap<String, SubTag> NameToSubTag = new HashMap<>(9);
private static HashMap<Integer, SubTag> SubTags = new HashMap<>(9);
private static HashMap<String, BasicType> NameToBasicType = new HashMap<>(10);
private static HashMap<Integer, BasicType> BasicTypes = new HashMap<>(10);
private static HashMap<String, AnnotElemType> NameToAnnotElemType = new HashMap<>(10);
private static HashMap<Character, AnnotElemType> AnnotElemTypes = new HashMap<>(10);
private static HashMap<String, StackMapType> KeyToStackMapType = new HashMap<>(10);
private static HashMap<String, StackMapType> NameToStackMapType = new HashMap<>(10);
private static HashMap<Integer, StackMapType> StackMapTypes = new HashMap<>(10);
private static HashMap<String, StackMapFrameType> NameToStackMapFrameType = new HashMap<>(10);
private static HashMap<Integer, StackMapFrameType> StackMapFrameTypes = new HashMap<>(10);
private static HashMap<String, ConstType> NameToConstantType = new HashMap<>(ConstType.maxTag);
private static HashMap<Integer, ConstType> ConstantTypes = new HashMap<>(ConstType.maxTag);
static {
// register all of the tokens
for (ConstType ct : ConstType.values()) {
registerConstantType(ct);
}
/* Type codes for SubTags */
for (AttrTag at : AttrTag.values()) {
registerAttrtag(at);
}
/* Type codes for SubTags */
for (SubTag st : SubTag.values()) {
registerSubtag(st);
}
/* Type codes for BasicTypes */
for (BasicType bt : BasicType.values()) {
registerBasicType(bt);
}
/* Type codes for BasicTypes */
for (AnnotElemType aet : AnnotElemType.values()) {
registerAnnotElemType(aet);
}
/* Type codes for StackMapTypes */
for (StackMapType smt : StackMapType.values()) {
registerStackMapType(smt);
}
/* Type codes for StackMapFrame attribute */
for (StackMapFrameType smft : StackMapFrameType.values()) {
registerStackMapFrameType(smft);
}
}
/**
* ConstType
*
* A (typed) tag (constant) representing the type of Constant in the Constant Pool.
*/
static public enum ConstType {
CONSTANT_ZERO (-3, "CONSTANT_ZERO", ""),
CONSTANT_UTF8 (1, "CONSTANT_UTF8", "Asciz"),
CONSTANT_UNICODE (2, "CONSTANT_UNICODE", ""),
CONSTANT_INTEGER (3, "CONSTANT_INTEGER", "int"),
CONSTANT_FLOAT (4, "CONSTANT_FLOAT", "float"),
CONSTANT_LONG (5, "CONSTANT_LONG", "long"),
CONSTANT_DOUBLE (6, "CONSTANT_DOUBLE", "double"),
CONSTANT_CLASS (7, "CONSTANT_CLASS", "class"),
CONSTANT_STRING (8, "CONSTANT_STRING", "String"),
CONSTANT_FIELD (9, "CONSTANT_FIELD", "Field"),
CONSTANT_METHOD (10, "CONSTANT_METHOD", "Method"),
CONSTANT_INTERFACEMETHOD (11, "CONSTANT_INTERFACEMETHOD", "InterfaceMethod"),
CONSTANT_NAMEANDTYPE (12, "CONSTANT_NAMEANDTYPE", "NameAndType"),
// Constant 13 reserved
// Constant 14 reserved
CONSTANT_METHODHANDLE (15, "CONSTANT_METHODHANDLE", "MethodHandle"),
CONSTANT_METHODTYPE (16, "CONSTANT_METHODTYPE", "MethodType"),
CONSTANT_INVOKEDYNAMIC_TRANS (17, "CONSTANT_INVOKEDYNAMIC_TRANS", "InvokeDynamicTrans"),
CONSTANT_INVOKEDYNAMIC (18, "CONSTANT_INVOKEDYNAMIC", "InvokeDynamic");
static final public int maxTag = 18;
private final int value;
private final String parseKey;
private final String printval;
ConstType(int val, String print, String parse) {
value = val;
parseKey = parse;
printval = print;
}
public int value() {
return value;
}
public String parseKey() {
return parseKey;
}
public String printval() {
return printval;
}
public void print(PrintWriter out) {
out.print(parseKey);
}
@Override
public String toString() {
return "<" + printval + "> [" + Integer.toString(value) + "]";
}
};
static public ConstType tag(int i) {
return ConstantTypes.get(i);
}
static public ConstType tag(String parsekey) {
return NameToConstantType.get(parsekey);
}
private static void registerConstantType(ConstType tt) {
NameToConstantType.put(tt.parseKey, tt);
ConstantTypes.put(tt.value, tt);
}
/*-------------------------------------------------------- */
/**
* Attribute descriptor enums
*/
static public enum AttrTag {
// Constant for ME Spec (StackMap does not appear in SE VM Spec)
ATT_Unrecognized (0, "ATT_Unrecognized", ""),
ATT_StackMap (1, "ATT_StackMap", "StackMap"),
// Numbers corespond to VM spec (chapter 4.7.X)
ATT_ConstantValue (2, "ATT_ConstantValue", "ConstantValue"),
ATT_Code (3, "ATT_Code", "Code"),
ATT_StackMapTable (4, "ATT_StackMapTable", "StackMapTable"),
ATT_Exceptions (5, "ATT_Exceptions", "Exceptions"),
ATT_InnerClasses (6, "ATT_InnerClasses", "InnerClasses"),
ATT_EnclosingMethod (7, "ATT_EnclosingMethod", "EnclosingMethod"),
ATT_Synthetic (8, "ATT_Synthetic", "Synthetic"),
ATT_Signature (9, "ATT_Signature", "Signature"),
ATT_SourceFile (10, "ATT_SourceFile", "SourceFile"),
ATT_SourceDebugExtension (11, "ATT_SourceDebugExtension", "SourceDebugExtension"),
ATT_LineNumberTable (12, "ATT_LineNumberTable", "LineNumberTable"),
ATT_LocalVariableTable (13, "ATT_LocalVariableTable", "LocalVariableTable"),
ATT_LocalVariableTypeTable (14, "ATT_LocalVariableTypeTable", "LocalVariableTypeTable"),
ATT_Deprecated (15, "ATT_Deprecated", "Deprecated"),
ATT_RuntimeVisibleAnnotations (16, "ATT_RuntimeVisibleAnnotations", "RuntimeVisibleAnnotations"),
ATT_RuntimeInvisibleAnnotations (17, "ATT_RuntimeInvisibleAnnotations", "RuntimeInvisibleAnnotations"),
ATT_RuntimeVisibleParameterAnnotations (18, "ATT_RuntimeVisibleParameterAnnotations", "RuntimeVisibleParameterAnnotations"),
ATT_RuntimeInvisibleParameterAnnotations (19, "ATT_RuntimeInvisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations"),
ATT_AnnotationDefault (20, "ATT_AnnotationDefault", "AnnotationDefault"),
ATT_BootstrapMethods (21, "ATT_BootstrapMethods", "BootstrapMethods"),
ATT_RuntimeVisibleTypeAnnotations (22, "ATT_RuntimeVisibleTypeAnnotations", "RuntimeVisibleTypeAnnotations"),
ATT_RuntimeInvisibleTypeAnnotations (23, "ATT_RuntimeInvisibleTypeAnnotations", "RuntimeInvisibleTypeAnnotations"),
ATT_MethodParameters (24, "ATT_MethodParameters", "MethodParameters");
private final Integer value;
private final String printval;
private final String parsekey;
AttrTag(Integer val, String print, String parse) {
value = val;
printval = print;
parsekey = parse;
}
public String printval() {
return printval;
}
public String parsekey() {
return parsekey;
}
}
private static void registerAttrtag(AttrTag tg) {
NameToAttrTag.put(tg.parsekey, tg);
AttrTags.put(tg.value, tg);
}
public static AttrTag attrtag(int val) {
AttrTag tg = AttrTags.get(val);
if (tg == null) {
tg = AttrTag.ATT_Unrecognized;
}
return tg;
}
public static AttrTag attrtag(String idValue) {
AttrTag tg = NameToAttrTag.get(idValue);
if (tg == null) {
tg = AttrTag.ATT_Unrecognized;
}
return tg;
}
public static String attrtagName(int subtag) {
AttrTag tg = AttrTags.get(subtag);
return tg.parsekey;
}
public static int attrtagValue(String idValue) {
AttrTag tg = attrtag(idValue);
return tg.value;
}
/*-------------------------------------------------------- */
/**
* SubTag enums
*/
static public enum SubTag {
REF_GETFIELD (1, "REF_getField"),
REF_GETSTATIC (2, "REF_getStatic"),
REF_PUTFIELD (3, "REF_putField"),
REF_PUTSTATIC (4, "REF_putStatic"),
REF_INVOKEVIRTUAL (5, "REF_invokeVirtual"),
REF_INVOKESTATIC (6, "REF_invokeStatic"),
REF_INVOKESPECIAL (7, "REF_invokeSpecial"),
REF_NEWINVOKESPECIAL (8, "REF_newInvokeSpecial"),
REF_INVOKEINTERFACE (9, "REF_invokeInterface");
private final Integer value;
private final String printval;
SubTag(Integer val, String print) {
value = val;
printval = print;
}
public String printval() {
return printval;
}
public Integer value() {
return value;
}
}
private static void registerSubtag(SubTag tg) {
NameToSubTag.put(tg.printval, tg);
SubTags.put(tg.value, tg);
}
public static SubTag subtag(String subtag) {
return NameToSubTag.get(subtag);
}
public static SubTag subtag(int subtag) {
return SubTags.get(subtag);
}
public static String subtagName(int subtag) {
String retval = null;
SubTag tg = SubTags.get(subtag);
if (tg != null) {
retval = tg.printval;
}
return retval;
}
public static int subtagValue(String idValue) {
int retval = 0;
SubTag tg = NameToSubTag.get(idValue);
if (tg != null) {
retval = tg.value;
}
return retval;
}
/*-------------------------------------------------------- */
/**
* BasicType enums
*/
static public enum BasicType {
T_INT (0x0000000a, "int"),
T_LONG (0x0000000b, "long"),
T_FLOAT (0x00000006, "float"),
T_DOUBLE (0x00000007, "double"),
T_CLASS (0x00000002, "class"),
T_BOOLEAN (0x00000004, "boolean"),
T_CHAR (0x00000005, "char"),
T_BYTE (0x00000008, "byte"),
T_SHORT (0x00000009, "short");
private final Integer value;
private final String printval;
BasicType(Integer val, String print) {
value = val;
printval = print;
}
public String printval() {
return printval;
}
}
private static void registerBasicType(BasicType typ) {
NameToBasicType.put(typ.printval, typ);
BasicTypes.put(typ.value, typ);
}
public static BasicType basictype(String idValue) {
return NameToBasicType.get(idValue);
}
public static BasicType basictype(int subtag) {
return BasicTypes.get(subtag);
}
public static String basictypeName(int subtag) {
String retval = null;
BasicType tg = BasicTypes.get(subtag);
if (tg != null) {
retval = tg.printval;
}
return retval;
}
public static int basictypeValue(String idValue) {
int retval = -1;
BasicType tg = NameToBasicType.get(idValue);
if (tg != null) {
retval = tg.value;
}
return retval;
}
/*-------------------------------------------------------- */
/**
* AnnotElemType enums
*/
static public enum AnnotElemType {
AE_BYTE ('B', "byte"),
AE_CHAR ('C', "char"),
AE_SHORT ('S', "short"),
AE_INT ('I', "int"),
AE_LONG ('J', "long"),
AE_FLOAT ('F', "float"),
AE_DOUBLE ('D', "double"),
AE_BOOLEAN ('Z', "boolean"),
AE_STRING ('s', "string"),
AE_ENUM ('e', "enum"),
AE_CLASS ('c', "class"),
AE_ANNOTATION ('@', "annotation"),
AE_ARRAY ('[', "array");
private final char value;
private final String printval;
AnnotElemType(char val, String print) {
value = val;
printval = print;
}
public char val() {
return value;
}
public String printval() {
return printval;
}
}
private static void registerAnnotElemType(AnnotElemType typ) {
NameToAnnotElemType.put(typ.printval, typ);
AnnotElemTypes.put(typ.value, typ);
}
public static AnnotElemType annotElemType(String idValue) {
return NameToAnnotElemType.get(idValue);
}
public static AnnotElemType annotElemType(char subtag) {
return AnnotElemTypes.get(subtag);
}
public static String annotElemTypeName(char subtag) {
String retval = null;
AnnotElemType tg = AnnotElemTypes.get(subtag);
if (tg != null) {
retval = tg.printval;
}
return retval;
}
public static char annotElemTypeVal(String idValue) {
char retval = 0;
AnnotElemType tg = NameToAnnotElemType.get(idValue);
if (tg != null) {
retval = tg.value;
}
return retval;
}
/*-------------------------------------------------------- */
/**
* MapTypes table. These constants are used in stackmap pseudo-instructions only.
*/
static public enum StackMapType {
/* Type codes for StackMap attribute */
ITEM_Bogus (0, "bogus", "B"), // an unknown or uninitialized value
ITEM_Integer (1, "int", "I"), // a 32-bit integer
ITEM_Float (2, "float", "F"), // not used
ITEM_Double (3, "double", "D"), // not used
ITEM_Long (4, "long", "L"), // a 64-bit integer
ITEM_Null (5, "null", "N"), // the type of null
ITEM_InitObject (6, "this", "IO"), // "this" in constructor
ITEM_Object (7, "CP", "O"), // followed by 2-byte index of class name
ITEM_NewObject (8, "at", "NO"); // followed by 2-byte ref to "new"
private final Integer value;
private final String printval;
private final String parsekey;
StackMapType(Integer val, String print, String parse) {
value = val;
printval = print;
parsekey = parse;
}
public String parsekey() {
return parsekey;
}
public String printval() {
return printval;
}
public Integer value() {
return value;
}
}
private static void registerStackMapType(StackMapType typ) {
KeyToStackMapType.put(typ.parsekey, typ);
NameToStackMapType.put(typ.printval, typ);
StackMapTypes.put(typ.value, typ);
}
public static StackMapType stackMapType(int subtag) {
return StackMapTypes.get(subtag);
}
public static StackMapType stackMapType(String subtag) {
return NameToStackMapType.get(subtag);
}
public static StackMapType stackMapTypeKey(String subtag) {
return KeyToStackMapType.get(subtag);
}
public static String stackMapTypeName(int subtag) {
String retval = null;
StackMapType tg = StackMapTypes.get(subtag);
if (tg != null) {
retval = tg.printval;
}
return retval;
}
public static int stackMapTypeValue(String idValue) {
int retval = 0;
StackMapType tg = NameToStackMapType.get(idValue);
if (tg != null) {
retval = tg.value;
}
return retval;
}
/*-------------------------------------------------------- */
/**
* StackMap-FrameType table. These constants are used in stackmap pseudo-instructions
* only.
*/
static public enum StackMapFrameType {
/* Type codes for StackMapFrame attribute */
SAME_FRAME (0, "same"),
SAME_LOCALS_1_STACK_ITEM_FRAME (64, "stack1"),
SAME_LOCALS_1_STACK_ITEM_EXTENDED_FRAME (247, "stack1_ex"),
CHOP_1_FRAME (250, "chop1"),
CHOP_2_FRAME (249, "chop2"),
CHOP_3_FRAME (248, "chop3"),
SAME_FRAME_EX (251, "same_ex"),
APPEND_FRAME (252, "append"),
FULL_FRAME (255, "full");
private final Integer value;
private final String parsekey;
StackMapFrameType(Integer val, String print) {
value = val;
parsekey = print;
}
public String parsekey() {
return parsekey;
}
public Integer value() {
return value;
}
}
private static void registerStackMapFrameType(StackMapFrameType typ) {
NameToStackMapFrameType.put(typ.parsekey, typ);
StackMapFrameTypes.put(typ.value, typ);
}
public static StackMapFrameType stackMapFrameTypeVal(int subtag) {
return StackMapFrameTypes.get(subtag);
}
public static String stackMapFrameTypeName(int subtag) {
String retval = null;
StackMapFrameType tg = StackMapFrameTypes.get(subtag);
if (tg != null) {
retval = tg.parsekey;
}
return retval;
}
public static StackMapFrameType stackMapFrameType(int subtag) {
StackMapFrameType frametype;
if (subtag < StackMapFrameType.SAME_LOCALS_1_STACK_ITEM_FRAME.value()) {
// type is same_frame;
frametype = StackMapFrameType.SAME_FRAME;
} else if (subtag >= StackMapFrameType.SAME_LOCALS_1_STACK_ITEM_FRAME.value()
&& subtag <= 127) {
// type is same_locals_1_stack_item_frame
frametype = StackMapFrameType.SAME_LOCALS_1_STACK_ITEM_FRAME;
} else if (subtag >= StackMapFrameType.APPEND_FRAME.value()
&& subtag < StackMapFrameType.FULL_FRAME.value()) {
// type is append_frame
frametype = StackMapFrameType.APPEND_FRAME;
} else {
frametype = StackMapFrameTypes.get(subtag);
}
return frametype;
}
public static int stackMapFrameTypeValue(String idValue) {
int retval = 0;
StackMapFrameType tg = NameToStackMapFrameType.get(idValue);
if (tg != null) {
retval = tg.value;
}
return retval;
}
/*-------------------------------------------------------- */
/**
* CF_Context enums
*/
static public enum CF_Context {
CTX_CLASS (0, "class"),
CTX_FIELD (1, "field"),
CTX_METHOD (2, "method"),
CTX_INNERCLASS (3, "inner-class");
private final int value;
private final String printval;
CF_Context(int val, String print) {
value = val;
printval = print;
}
public int val() {
return value;
}
public String printval() {
return printval;
}
}
private static void registerAnnotElemType(CF_Context ctx) {
// NameToAnnotElemType.put(typ.printval, typ);
// AnnotElemTypes.put(typ.value, typ);
}
/*
public static CF_Context annotElemType(String idValue) {
return NameToAnnotElemType.get(idValue);
}
public static CF_Context annotElemType(int subtag) {
return AnnotElemTypes.get(subtag);
}
* */
}

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.util.ArrayList;
import org.openjdk.asmtools.jasm.TypeAnnotationUtils.*;
/**
*
*/
public class TypeAnnotationData extends AnnotationData {
protected TargetType targetType;
protected TargetInfo targetInfo;
protected ArrayList<TypePathEntry> targetPath;
/*-------------------------------------------------------- */
/*-------------------------------------------------------- */
/* TypeAnnotationData Methods */
public TypeAnnotationData(Argument typeCPX, boolean invisible) {
super(typeCPX, invisible);
}
@Override
public int getLength() {
return super.getLength() + 2 + targetInfo.getLength();
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
super.write(out);
// KTL: (1/10/13) Spec changed: char -> byte
// out.writeShort(targetType.value);
out.writeByte(targetType.value);
targetInfo.write(out);
}
@Override
public String toString() {
return toString(0);
}
public String toString(int tabLevel) {
StringBuilder sb = new StringBuilder();
String tabStr = tabString(tabLevel);
sb.append(tabStr + "Target Type: ");
sb.append(targetType.toString());
sb.append('\n');
sb.append(tabStr + "Target Info: ");
sb.append(targetInfo.toString(tabLevel));
sb.append('\n');
sb.append(tabStr + "Target Path: [");
boolean first = true;
for (TypePathEntry tpe : targetPath) {
if (!first) {
sb.append(", ");
}
first = false;
sb.append(tpe);
}
sb.append("]");
sb.append('\n');
return sb.toString();
}
protected static String tabString(int tabLevel) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < tabLevel; i++) {
sb.append('\t');
}
return sb.toString();
}
}

View File

@ -0,0 +1,891 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
/**
*
*/
public class TypeAnnotationUtils {
/*-------------------------------------------------------- */
/* TypeAnnotationData Inner Classes */
static public enum PathKind {
DEEPER_ARRAY (0, "DEEPER_ARRAY", "ARRAY"),
DEEPER_NESTEDTYPE (1, "DEEPER_NESTEDTYPE", "INNER_TYPE"),
BOUND_WILDCARDTYPE (2, "BOUND_WILDCARDTYPE", "WILDCARD"),
ITHARG_PARAMETERTYPE (3, "ITHARG_PARAMETERTYPE", "TYPE_ARGUMENT");
private final int key;
private final String type;
private final String parseKey;
public static final int maxLen = 3;
PathKind(int key, String type, String parseval) {
this.key = key;
this.type = type;
this.parseKey = parseval;
}
public int key() {
return key;
}
public String parsekey() {
return parseKey;
}
}
static private HashMap<String, PathKind> PathTypeHash = new HashMap<>(PathKind.maxLen);
private static void initPathTypes(PathKind pk) {
PathTypeHash.put(pk.parseKey, pk);
}
static {
for (PathKind pk : PathKind.values()) {
initPathTypes(pk);
}
}
public static PathKind pathKind(String parseKey) {
return PathTypeHash.get(parseKey);
}
// will throw ArrayIndexOutOfBounds if i < 0 or i > 3
static public PathKind getPathKind(int i) {
return PathKind.values()[i];
}
/*-------------------------------------------------------- */
/* TypeAnnotationData Inner Classes */
static public class TypePathEntry {
private final PathKind kind;
private final char index;
public TypePathEntry(int kind, char index) {
this.kind = getPathKind(kind);
this.index = index;
}
public PathKind kind() {
return kind;
}
public char index() {
return index;
}
public String toString() {
return kind.parsekey() + "(" + index + ")";
}
}
/*-------------------------------------------------------- */
/* TypeAnnotationData Inner Classes */
static public enum InfoType {
TYPEPARAM ("TYPEPARAM", "TYPEPARAM"),
SUPERTYPE ("SUPERTYPE", "SUPERTYPE"),
TYPEPARAM_BOUND ("TYPEPARAM_BOUND", "TYPEPARAM_BOUND"),
EMPTY ("EMPTY", "EMPTY"),
METHODPARAM ("METHODPARAM", "METHODPARAM"),
EXCEPTION ("EXCEPTION", "EXCEPTION"),
LOCALVAR ("LOCALVAR", "LOCALVAR"),
CATCH ("CATCH", "CATCH"),
OFFSET ("OFFSET", "OFFSET"),
TYPEARG ("TYPEARG", "TYPEARG");
private final String parseKey;
private final String printval;
InfoType(String parse, String print) {
parseKey = parse;
printval = print;
}
public String parseKey() {
return parseKey;
}
}
/**
* TargetType
*
* A (typed) tag (constant) representing the type of Annotation Target.
*/
static public enum TargetType {
class_type_param (0x00, "CLASS_TYPE_PARAMETER", InfoType.TYPEPARAM, "class type parameter"),
meth_type_param (0x01, "METHOD_TYPE_PARAMETER", InfoType.TYPEPARAM, "method type parameter"),
class_exts_impls (0x10, "CLASS_EXTENDS", InfoType.SUPERTYPE, "class extends/implements"),
class_type_param_bnds (0x11, "CLASS_TYPE_PARAMETER_BOUND", InfoType.TYPEPARAM_BOUND, "class type parameter bounds"),
meth_type_param_bnds (0x12, "METHOD_TYPE_PARAMETER_BOUND", InfoType.TYPEPARAM_BOUND, "method type parameter bounds"),
field (0x13, "FIELD", InfoType.EMPTY, "field"),
meth_ret_type (0x14, "METHOD_RETURN", InfoType.EMPTY, "method return type"),
meth_reciever (0x15, "METHOD_RECEIVER", InfoType.EMPTY, "method reciever"),
meth_formal_param (0x16, "METHOD_FORMAL_PARAMETER", InfoType.METHODPARAM, "method formal parameter type"),
throws_type (0x17, "THROWS", InfoType.EXCEPTION, "exception type in throws"),
local_var (0x40, "LOCAL_VARIABLE", InfoType.LOCALVAR, "local variable"),
resource_var (0x41, "RESOURCE_VARIABLE", InfoType.LOCALVAR, "resource variable"), // TODO
exception_param (0x42, "EXCEPTION_PARAM", InfoType.CATCH, "exception parameter"), // TODO
type_test (0x43, "INSTANCEOF", InfoType.OFFSET, "type test (instanceof)"),
obj_creat (0x44, "NEW", InfoType.OFFSET, "object creation (new)"),
constr_ref_receiver (0x45, "CONSTRUCTOR_REFERENCE_RECEIVER", InfoType.OFFSET, "constructor reference receiver"),
meth_ref_receiver (0x46, "METHOD_REFERENCE_RECEIVER", InfoType.OFFSET, "method reference receiver"),
cast (0x47, "CAST", InfoType.TYPEARG, "cast"),
constr_invoc_typearg (0x48, "CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT", InfoType.TYPEARG, "type argument in constructor call"),
meth_invoc_typearg (0x49, "METHOD_INVOCATION_TYPE_ARGUMENT", InfoType.TYPEARG, "type argument in method call"),
constr_ref_typearg (0x4A, "CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT", InfoType.TYPEARG, "type argument in constructor reference"),
meth_ref_typearg (0x4B, "METHOD_REFERENCE_TYPE_ARGUMENT", InfoType.TYPEARG, "type argument in method reference");
public static final int maxTag = 0x9A;
public static final int maxLen = 36;
public final int value;
private final String parseKey;
private final InfoType infoKey;
private final String printval;
TargetType(int val, String parse, InfoType info, String print) {
value = val;
parseKey = parse;
infoKey = info;
printval = print;
}
public String parseKey() {
return parseKey;
}
public String infoKey() {
return infoKey.parseKey();
}
public InfoType infoType() {
return infoKey;
}
public void print(PrintWriter out) {
out.print(parseKey);
}
@Override
public String toString() {
return parseKey + " (" + infoKey() + ") <" + printval + "> [" + Integer.toHexString(value) + "]";
}
};
static private HashMap<String, TargetType> TargetTypeHash = new HashMap<>(TargetType.maxLen);
static private HashMap<Integer, TargetType> TargetTypeList = new HashMap<>(TargetType.maxLen);
private static void initTargetTypes(TypeAnnotationUtils.TargetType tt) {
TargetTypeList.put(tt.value, tt);
TargetTypeHash.put(tt.parseKey, tt);
}
static {
for (TargetType type : TargetType.values()) {
initTargetTypes(type);
}
}
public static TargetType targetType(String parseKey) {
return TargetTypeHash.get(parseKey);
}
public static TargetType targetTypeEnum(Integer typeCode) {
return TargetTypeList.get(typeCode);
}
/**
* TargetInfo
*
* BaseClass for any Type Annotation Target-Info.
*/
public static class TargetInfo {
protected TargetType targettype = null;
public TargetInfo(TargetType tt) {
targettype = tt;
}
public TargetType getTargetType() {
return targettype;
}
public void print(PrintWriter out, String tab) {
// print the TargetType and TargetInfo
out.print(tab + " {");
targettype.print(out);
_print(out, tab);
out.print(tab + "}");
}
public void _print(PrintWriter out, String tab) {
// sub-classes override
}
public void write(CheckedDataOutputStream out) throws IOException {
// placeholder
}
public int getLength() {
return 0;
}
@Override
public String toString() {
return toString(0);
}
protected void _toString(StringBuilder sb, int tabLevel) {
// sub-classes override
}
public String toString(int tabLevel) {
StringBuilder sb = new StringBuilder();
String tabStr = tabString(tabLevel);
// first print the name/target-type
sb.append(tabStr);
sb.append(targettype.infoKey() + " \n");
sb.append(tabStr);
sb.append(targettype + " \n");
// get the sub-classes parts
_toString(sb, tabLevel);
return sb.toString();
}
protected static String tabString(int tabLevel) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < tabLevel; i++) {
sb.append('\t');
}
return sb.toString();
}
}
/**
* TypeParams_Target (3.3.1 Type parameters)
*
* BaseClass for any Type Annotation Target-Info that is in a parameterized type,
* array, or nested type.
*
* These need location information to identify the annotated element.
*/
public static class typeparam_target extends TargetInfo {
int pindex;
public typeparam_target(TargetType tt, int indx) {
super(tt);
pindex = indx;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeByte(pindex);
super.write(out);
}
@Override
public void _print(PrintWriter out, String tab) {
out.print(" ");
out.print(pindex);
}
@Override
public int getLength() {
return 1 + super.getLength();
}
@Override
protected void _toString(StringBuilder sb, int tabLevel) {
String tabStr = tabString(tabLevel);
sb.append(tabStr);
sb.append("param_index: ");
sb.append(pindex);
sb.append('\n');
}
}
/**
* supertype_target (3.3.2 Class extends and implements)
*
* BaseClass for any Type Annotation Target-Info that is in a parameterized type,
* array, or nested type.
*
* These need location information to identify the annotated element.
*/
public static class supertype_target extends TargetInfo {
int type_index;
public supertype_target(TargetType tt, int tindex) {
super(tt);
type_index = tindex;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(type_index);
super.write(out);
}
@Override
public void _print(PrintWriter out, String tab) {
out.print(" ");
out.print(type_index);
}
@Override
public int getLength() {
return 2 + super.getLength();
}
@Override
protected void _toString(StringBuilder sb, int tabLevel) {
String tabStr = tabString(tabLevel);
sb.append(tabStr);
sb.append("type_index: ");
sb.append(type_index);
sb.append('\n');
}
}
/**
* typeparam_bound_target (3.3.3 Type parameter bounds)
*
* BaseClass for any Type Annotation Target-Info that is in a parameterized type,
* array, or nested type.
*
* These need location information to identify the annotated element.
*/
public static class typeparam_bound_target extends TargetInfo {
int pindex;
int bindex;
public typeparam_bound_target(TargetType tt, int pindx, int bindx) {
super(tt);
pindex = pindx;
bindex = bindx;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeByte(pindex);
out.writeByte(bindex);
super.write(out);
}
@Override
public void _print(PrintWriter out, String tab) {
out.print(" ");
out.print(pindex);
out.print(" ");
out.print(bindex);
}
@Override
public int getLength() {
return 2 + super.getLength();
}
@Override
protected void _toString(StringBuilder sb, int tabLevel) {
String tabStr = tabString(tabLevel);
sb.append(tabStr);
sb.append("param_index: ");
sb.append(pindex);
sb.append('\n');
sb.append(tabStr);
sb.append("bound_index: ");
sb.append(bindex);
sb.append('\n');
}
}
/**
* empty_target (3.3.4 )
*
* Types without arguments.
*
* Basic types without arguments, like field, method return, or method receiver.
*/
public static class empty_target extends TargetInfo {
public empty_target(TargetType tt) {
super(tt);
}
}
/**
* methodformalparam_target (3.3.5 Method parameters)
*
* BaseClass for any Type Annotation Target-Info that is in a parameterized type,
* array, or nested type.
*
* These need location information to identify the annotated element.
*/
public static class methodformalparam_target extends TargetInfo {
int index;
public methodformalparam_target(TargetType tt, int indx) {
super(tt);
index = indx;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeByte(index);
super.write(out);
}
@Override
public void _print(PrintWriter out, String tab) {
out.print(" ");
out.print(index);
}
@Override
public int getLength() {
return 1 + super.getLength();
}
@Override
protected void _toString(StringBuilder sb, int tabLevel) {
String tabStr = tabString(tabLevel);
sb.append(tabStr);
sb.append("index: ");
sb.append(index);
sb.append('\n');
}
}
/**
* throws_target (3.3.6 throws clauses)
*
* BaseClass for any Type Annotation Target-Info that is in a parameterized type,
* array, or nested type.
*
* These need location information to identify the annotated element.
*/
public static class throws_target extends TargetInfo {
int type_index;
public throws_target(TargetType tt, int tindex) {
super(tt);
type_index = tindex;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(type_index);
super.write(out);
}
@Override
public void _print(PrintWriter out, String tab) {
out.print(" ");
out.print(type_index);
}
@Override
public int getLength() {
return 2 + super.getLength();
}
@Override
protected void _toString(StringBuilder sb, int tabLevel) {
String tabStr = tabString(tabLevel);
sb.append(tabStr);
sb.append("type_index: ");
sb.append(type_index);
sb.append('\n');
}
}
/**
* localvar_target (3.3.7 Local variables)
*
* BaseClass for any Type Annotation Target-Info that is in a parameterized type,
* array, or nested type.
*
* These need location information to identify the annotated element.
*/
public static class localvar_target extends TargetInfo {
public static class LocalVar_Entry {
public int startPC;
public int length;
public int cpx;
public LocalVar_Entry(int st, int len, int index) {
startPC = st;
length = len;
cpx = index;
}
void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(startPC);
out.writeShort(length);
out.writeShort(cpx);
}
public void _print(PrintWriter out, String tab) {
out.print(tab + "{");
out.print(startPC);
out.print(" ");
out.print(length);
out.print(" ");
out.print(cpx);
out.println("}");
}
public String toString() {
return new String("startPC: " + startPC
+ " length: " + length
+ " cpx: " + cpx);
}
}
ArrayList<LocalVar_Entry> table = null;
public localvar_target(TargetType tt, int size) {
super(tt);
table = new ArrayList<>(size);
}
public void addEntry(int startPC, int length, int cpx) {
LocalVar_Entry entry = new LocalVar_Entry(startPC, length, cpx);
table.add(entry);
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(table.size());
for (LocalVar_Entry entry : table) {
entry.write(out);
}
super.write(out);
}
@Override
public void _print(PrintWriter out, String tab) {
String innerTab = tab + " ";
out.println();
for (LocalVar_Entry entry : table) {
entry._print(out, innerTab);
}
out.print(innerTab);
}
@Override
public int getLength() {
return 2 + // U2 for table size
(6 * table.size()) + // (3 * U2) for each table entry
super.getLength();
}
@Override
protected void _toString(StringBuilder sb, int tabLevel) {
String tabStr1 = tabString(tabLevel + 1);
int i = 1;
for (LocalVar_Entry entry : table) {
sb.append(tabStr1);
sb.append("[" + i + "]: ");
sb.append(entry.toString());
sb.append('\n');
i += 1;
}
}
}
/**
* catch_target (3.3.8 Exception parameters (catch clauses))
*
* Index to the exception type (the type that shows up in a catch clause).
*
* These need location information to identify the annotated element.
*/
public static class catch_target extends TargetInfo {
int exception_table_index;
public catch_target(TargetType tt, int indx) {
super(tt);
exception_table_index = indx;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(exception_table_index);
super.write(out);
}
@Override
public void _print(PrintWriter out, String tab) {
out.print(" ");
out.print(exception_table_index);
}
@Override
public int getLength() {
return 2 + super.getLength();
}
@Override
protected void _toString(StringBuilder sb, int tabLevel) {
String tabStr = tabString(tabLevel);
sb.append(tabStr);
sb.append("exception_table_index: ");
sb.append(exception_table_index);
sb.append('\n');
}
}
/**
* offset_target (3.3.9 Typecasts, type tests, and object creation)
*
* BaseClass for any Type Annotation Target-Info that is in a parameterized type,
* array, or nested type.
*
* These need location information to identify the annotated element.
*/
public static class offset_target extends TargetInfo {
int offset;
public offset_target(TargetType tt, int ofst) {
super(tt);
offset = ofst;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(offset);
super.write(out);
}
@Override
public void _print(PrintWriter out, String tab) {
out.print(" ");
out.print(offset);
}
@Override
public int getLength() {
return 2 + super.getLength();
}
@Override
protected void _toString(StringBuilder sb, int tabLevel) {
String tabStr = tabString(tabLevel);
sb.append(tabStr);
sb.append("offset: ");
sb.append(offset);
sb.append('\n');
}
}
/**
* typearg_target (3.3.10 Constructor and method call type arguments)
*
* BaseClass for any Type Annotation Target-Info that is in a parameterized type,
* array, or nested type.
*
* These need location information to identify the annotated element.
*/
public static class typearg_target extends TargetInfo {
int offset;
int typeIndex;
public typearg_target(TargetType tt, int ofst, int tindx) {
super(tt);
offset = ofst;
typeIndex = tindx;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
out.writeShort(offset);
out.writeByte(typeIndex);
super.write(out);
}
@Override
public void _print(PrintWriter out, String tab) {
out.print(" ");
out.print(offset);
out.print(" ");
out.print(typeIndex);
}
@Override
public int getLength() {
return 3 + super.getLength();
}
@Override
protected void _toString(StringBuilder sb, int tabLevel) {
String tabStr = tabString(tabLevel);
sb.append(tabStr);
sb.append("offset: ");
sb.append(offset);
sb.append('\n');
sb.append(tabStr);
sb.append("type_index: ");
sb.append(typeIndex);
sb.append('\n');
}
}
/*-------------------------------------------------------- */
/* TypeAnnotationVisitor Methods */
public static class TypeAnnotationTargetVisitor {
public final void visit(TargetType tt) {
switch (tt) {
case class_type_param:
case meth_type_param:
visit_type_param_target(tt);
break;
case class_exts_impls:
visit_supertype_target(tt);
break;
case class_type_param_bnds:
case meth_type_param_bnds:
visit_typeparam_bound_target(tt);
break;
case field:
case meth_ret_type:
case meth_reciever:
visit_empty_target(tt);
break;
case meth_formal_param:
visit_methodformalparam_target(tt);
break;
case throws_type:
visit_throws_target(tt);
break;
case local_var:
case resource_var:
visit_localvar_target(tt);
break;
case exception_param:
visit_catch_target(tt);
break;
case type_test:
case obj_creat:
case constr_ref_receiver:
case meth_ref_receiver:
visit_offset_target(tt);
break;
case cast:
case constr_invoc_typearg:
case meth_invoc_typearg:
case constr_ref_typearg:
case meth_ref_typearg:
visit_typearg_target(tt);
break;
}
}
public void visit_type_param_target(TargetType tt) {
}
public void visit_supertype_target(TargetType tt) {
}
public void visit_typeparam_bound_target(TargetType tt) {
}
public void visit_empty_target(TargetType tt) {
}
public void visit_methodformalparam_target(TargetType tt) {
}
public void visit_throws_target(TargetType tt) {
}
public void visit_localvar_target(TargetType tt) {
}
public void visit_catch_target(TargetType tt) {
}
public void visit_offset_target(TargetType tt) {
}
public void visit_typearg_target(TargetType tt) {
}
}
/*-------------------------------------------------------- */
/*-------------------------------------------------------- */
/* TypeAnnotationData Methods */
public TypeAnnotationUtils() {
}
public static TargetType getTargetType(int tt_index) {
if (tt_index < 0 || tt_index > TargetType.maxTag) {
return null;
}
return TargetTypeList.get(tt_index);
}
static public TargetType getTargetType(String tt) {
TargetType retval = TargetTypeHash.get(tt);
if (retval.name().equals("UNUSED")) {
retval = null;
}
return retval;
}
}

View File

@ -0,0 +1,186 @@
# Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
jasm.usage=\
Usage: java -jar asmtools.jar jasm [options] file.jasm...\n\
where possible options include:
jasm.opt.d=\
\ -d destdir directory to place resulting .class files
jasm.opt.v=\
\ -v add trace information
jasm.opt.g=\
\ -g add debug information
jasm.opt.version=\
\ -version prints the program version
jasm.opt.nowrite=\
\ -nowrite do not write resulting .class files
jasm.opt.strict=\
\ -strict consider warnings as errors
jasm.opt.nowarn=\
\ -nowarn do not print warnings
jasm.opt.cv=\
\ -cv major.minor set operating class file version (by default {0}.{1})
jasm.error.d_requires_argument=-d requires argument
jasm.error.does_not_exist={0} does not exist
jasm.error.cv_requires_arg=-cv requires argument
jasm.error.invalid_major_minor_param=invalid parameter major.minor
jasm.error.invalid_option=invalid option: {0}
jasm.error.cannot_read=cannot read {0}
jasm.error.cannot_write=cannot write {0}
jasm.error.fatal_error=fatal error
jasm.error.fatal_exception=fatal exception
#err.not.implemented=Sorry, {0} not implemented.
# Scanner:
err.invalid.escape.char=Invalid escape character.
err.eof.in.comment=Comment not terminated at end of input.
err.invalid.number=Invalid character "{0}" in number.
err.invalid.octal.number=Invalid character in octal number.
err.overflow=Numeric overflow.
err.float.format=Invalid floating point format.
err.eof.in.string=String not terminated at end of input.
err.newline.in.string=String not terminated at end of line.
#err.invalid.char.constant=Invalid character constant.
err.funny.char=Invalid character in input.
err.unbalanced.paren=Unbalanced parentheses.
# Parser:
err.package.repeated=Package statement repeated.
#err.module.repeated=Module statement repeated.
warn.intf.repeated=Interface {0} repeated.
warn.exc.repeated=Exception repeated in throws clause.
err.multiple.inherit=Multiple inheritance is not supported.
err.toplevel.expected=Class or interface declaration expected.
err.const.def.expected=Constant declaration expected.
err.const.undecl=Constant #{0} not declared.
err.const.redecl=Constant {0} redeclared.
warn.const0.redecl=Re-declaration of Constant #0 cannot be written to the class file.
#err.const.bsmindex=Bad Bootstrap Methods index {0} specified.
#warn.const.misused=Constant {0} was assumed to have another tag.
err.field.expected=Field or method declaration expected.
err.token.expected={0} expected.
err.identifier.expected=Identifier expected.
#err.missing.term=Missing term.
#err.tag.expected=Tag expected.
err.name.expected=Name expected, got {0}.
err.int.expected=Integer expected.
err.neg.forbidden=Negative integer is not allowed here.
err.value.large=Value doesn't fit in {0}.
err.value.expected=Value expected.
err.wrong.mnemocode=Invalid mnemocode ({0}).
#err.class.expected='class' or 'interface' keyword expected.
err.default.redecl=Default statement already declared in this table.
err.long.switchtable=Switchtable too long: > {0}.
err.io.exception=I/O error in {0}.
warn.wrong.tag=Wrong tag: {0} expected.
warn.wrong.tag2=Wrong tags: {0} or {1} expected.
# Code Gen:
err.locvar.redecl=Local variable {0} redeclared.
err.locvar.undecl=Local variable {0} not declared.
#err.locvar.expected=Local variable expected.
err.label.redecl=Label {0} redeclared.
err.label.undecl=Label {0} not declared.
err.label.expected=Label expected.
err.subtag.expected=Subtag expected.
err.type.expected=Type expected.
err.trap.tryredecl=<try {0}> redeclared.
err.trap.endtryredecl=<endtry {0}> redeclared.
err.trap.notry=No <try {0}> found.
err.trap.noendtry=No <endtry {0}> found.
warn.trap.notref=No <catch {0}> declared.
err.cannot.write=Cannot write to {0}.
err.msig.malformed=Malformed method signature at char {0}. [err={1}]
err.no.classname=Class name not defined.
warn.msig.more255=Number of parameters too large ({0}>255).
#warn.msig.large=Number of parameters ({0}) exceeds max_locals value ({1}).
warn.illslot=Local variable at Illegal slot {0}.
#warn.invalid.modifier=This modifier is not allowed here
warn.repeated.modifier=Repeated modifier.
warn.invalid.modifier.init=invalid modifier for <init> method \"{0}\".
warn.invalid.modifier.fiva=at most one of final and volatile modifiers can be used for a field.
warn.invalid.modifier.intfield=interface field must be public static final only
warn.invalid.modifier.field=invalid modifier for a field.
warn.init.in_int=<init> method cannot be placed in an interface.
warn.invalid.modifier.intmth=interface method must be abstract public only \"{0}\".
warn.invalid.modifier.abst=invalid modifier for abstract method.
warn.invalid.modifier.mth=invalid modifier for a method.
warn.invalid.modifier.acc=at most one of public, protected, and private modifiers can be used.
warn.invalid.modifier.int=invalid modifier for an interface.
warn.invalid.modifier.int.abs=interface class must have abstract modifier.
warn.invalid.modifier.class=invalid modifier for a class.
warn.invalid.modifier.class.finabs=class cannot be both abstract and final.
warn.invalid.modifier.innerclass=invalid modifier for an inner class \"{0}\".
err.itemtype.expected=StackMap item type expected instead of {0}.
err.localsmap.repeated=locals_map redeclared.
err.invalid.stack.frame.type=invalid stack frame type.
err.invalid.offset.same.frame=offset value more than 64 for the 'same_frame' type frame.
err.no.stack.map.same.locals=stack map element for the 'same_locals_1_stack_item_frame' type frame is absent.
err.should.be.only.one.stack.map.element=should be only one stack map element for the 'same_locals_1_stack_item_frame' type frame.
err.invalid.offset.same.locals=offset value more than 64 for the 'same_locals_1_stack_item_frame' type frame.
err.unexpected.stack.maps=there are unexpected stack maps.
err.unexpected.locals.maps=there are unexpected locals maps.
err.no.locals.map.append=locals map element for the 'append_frame' type frame is absent.
err.more.locals.map.elements=there are more than 3 locals map element for the 'append_frame' type frame.
err.stackmap.repeated=stack_map redeclared.
err.version.expected=class file version expected
err.invalid.innerclass=Invalid declaration of Inner Class
err.invalid.bootstrapmethod=Invalid declaration of BootstrapMethod Entry
#err.table.expected=Table expected
#err.package.module.expected=package or module expected
err.frametype.repeated=Frametype repeated
#err.module.expected=module expected
err.invalid.paramnum=Invalid Parameter Number: {0}.
err.duplicate.paramnum=Duplicate Parameter Number: {0}.
err.paramname.constnum.invaltype=ParameterName CPX at {0} is not a ConstantString.
err.paramname.token.unexpected=Incorrect ParamName, unrecognized token: \"{0}\".
#
# annotations Errors
#
err.incorrect.annot.class=Incorrect Annotation (class), expected class name or CPX), got \"{0}\".
err.incorrect.annot.enum=Incorrect Annotation (enum), expected type field IDENT, \"{0}\".
err.incorrect.annot.enum.cpx==Incorrect Annotation (enum), expexted type field CPX.
err.incorrect.annot.token=Incorrect Annotation, unrecognized token: \"{0}\".
err.incorrect.annot.bool=Incorrect Annotation (boolean), expected Integer), got \"{0}\".
err.incorrect.annot.byte=Incorrect Annotation (byte), expected Integer), got \"{0}\".
err.incorrect.annot.char=Incorrect Annotation (char), expected Integer), got \"{0}\".
err.incorrect.annot.short=Incorrect Annotation (short), expected Integer), got \"{0}\".
err.incorrect.annot.keyword=Incorrect Annotation keyword \"{0}\".
err.incorrect.typeannot.target=Incorrect TypeAnnotation target \"{0}\".
err.incorrect.typeannot.targtype.string=Incorrect TypeAnnotation \"{0}\" argument: (expected String), \"{1}\".
err.incorrect.typeannot.targtype.int=Incorrect TypeAnnotation \"{0}\" argument: (expected Integer), \"{1}\".
err.incorrect.typeannot.pathentry=Incorrect TypeAnnotation TargetPath PathEntry \"{0}\".
err.incorrect.typeannot.pathentry.argindex=Incorrect TypeAnnotation TargetPath PathEntry ArgIndex (expected Integer), \"{0}\".
#
# Compiler Errors
#
# comperr.hashcode.err="CV hash:{0}"
comperr.constcell.nullvalset="Cell without value in setCell"
comperr.constcell.nullvalhash="Cell without value in cpoolHashByValue"
comperr.constcell.invarg="Cell[{0}] has #{1}"
comperr.constcell.nullval="ConstCell.value=null??"
comperr.val.noteq="Values not eq"
comperr.instr.nullarg="null arg for {0}"
comperr.instr.arglong="Too long argument of {0}: {1}"
comperr.instr.opclen="Wrong opcLength({0})"

View File

@ -0,0 +1,957 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jcdec;
import static org.openjdk.asmtools.jcoder.JcodTokens.*;
import org.openjdk.asmtools.jdis.uEscWriter;
import org.openjdk.asmtools.util.I18NResourceBundle;
import org.openjdk.asmtools.util.ProductInfo;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
* Main program of the JavaCard DeCoder
*
*/
public class Main {
/*-------------------------------------------------------- */
/* Main Fields */
/**
* Name of the program.
*/
String program;
public static final I18NResourceBundle i18n
= I18NResourceBundle.getBundleForClass(Main.class);
/**
* The stream where error message are printed.
*/
PrintWriter out;
boolean DebugFlag = false;
boolean printDetails = false;
int shift = 0;
private static final char hexTable[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
/*-------------------------------------------------------- */
static String toHex(long val, int width) {
StringBuffer s = new StringBuffer();
for (int i = width * 2 - 1; i >= 0; i--) {
s.append(hexTable[((int) (val >> (4 * i))) & 0xF]);
}
return "0x" + s.toString();
}
static String toHex(long val) {
int width;
for (width = 8; width > 0; width--) {
if ((val >> (width - 1) * 8) != 0) {
break;
}
}
return toHex(val, width);
}
void printByteHex(PrintWriter out, int b) {
out.print(hexTable[(b >> 4) & 0xF]);
out.print(hexTable[b & 0xF]);
}
/*========================================================*/
void out_begin(String s) {
for (int i = 0; i < shift; i++) {
out.print(" ");
}
out.println(s);
shift++;
}
void out_print(String s) {
for (int i = 0; i < shift; i++) {
out.print(" ");
}
out.print(s);
}
void out_println(String s) {
for (int i = 0; i < shift; i++) {
out.print(" ");
}
out.println(s);
}
void out_end(String s) {
shift--;
for (int i = 0; i < shift; i++) {
out.print(" ");
}
out.println(s);
}
String startArray(int length) {
return "[" + (printDetails ? Integer.toString(length) : "") + "]";
}
void printBytes(DataInputStream in, int len) throws IOException {
try {
for (int i = 0; i < len; i++) {
if (i % 8 == 0) {
out_print("0x");
}
printByteHex(out, in.readByte());
if (i % 8 == 7) {
out.println(";");
}
}
} finally {
if (len % 8 != 0) {
out.println(";");
}
}
}
/*========================================================*/
static final int EXPORT_MAGIC = 0x00FACADE;
static final int HEADER_MAGIC = 0xDECAFFED;
static String[] compNames = {
"Header",
"Directory",
"Applet",
"Import",
"ConstantPool",
"Class",
"Method",
"StaticField",
"RefLocation",
"Export",
"Descriptor"
};
static String compName(int compNum) {
try {
return compNames[compNum - 1];
} catch (ArrayIndexOutOfBoundsException e) {
return "tag " + compNum + "???";
}
}
String[] cPoolStrings;
void decodeAttr(DataInputStream in) throws IOException {
int name_cpx = in.readUnsignedShort(), len = in.readInt();
String AttrName = null;
String endingComment = "Attr(#" + name_cpx + ")";
try {
endingComment = AttrName = cPoolStrings[name_cpx];
} catch (ArrayIndexOutOfBoundsException e) {
}
if (printDetails) {
out_begin("Attr(#" + name_cpx + ", " + len + ") { // " + AttrName);
} else {
out_begin("Attr(#" + name_cpx + ") { // " + AttrName);
}
if (AttrName == null) {
printBytes(in, len);
} else if (AttrName.equals("ConstantValue")) {
if (len != 2) {
out_println("// invalid length of ConstantValue attr: " + len + " (should be 2)");
printBytes(in, len);
} else {
out_println("#" + in.readUnsignedShort() + ";");
}
} else {
printBytes(in, len);
}
out_end("} // end " + endingComment);
}
void decodeExp(String inpName) throws IOException {
DataInputStream in = new DataInputStream(new FileInputStream(inpName));
out_println("file " + inpName);
out_begin("{ // export file");
int magic = in.readInt();
out_print(toHex(magic, 4) + "; // ");
if (magic != EXPORT_MAGIC) {
out.print("wrong magic: 0x" + Integer.toString(EXPORT_MAGIC, 16) + " expected");
} else {
out_print("magic");
}
out.println();
out_println(in.readUnsignedByte() + "b; // minor version");
out_println(in.readUnsignedByte() + "b; // major version");
int cp_count = in.readUnsignedShort();
cPoolStrings = new String[cp_count];
out_begin(startArray(cp_count) + " { // Constant Pool");
for (int i = 0; i < cp_count; i++) {
int tag = in.readUnsignedByte();
ConstType tg = constType(tag);
switch (tg) {
case CONSTANT_UTF8:
out_print("Utf8 \"");
StringBuffer sb = new StringBuffer();
String s = in.readUTF();
cPoolStrings[i] = s;
for (int k = 0; k < s.length(); k++) {
char c = s.charAt(k);
switch (c) {
case '\t':
sb.append('\\').append('t');
break;
case '\n':
sb.append('\\').append('n');
break;
case '\r':
sb.append('\\').append('r');
break;
case '\"':
sb.append('\\').append('\"');
break;
default:
sb.append(c);
}
}
out.println(sb.append("\"; // #").append(i).toString());
break;
case CONSTANT_INTEGER:
out_println("int " + toHex(in.readInt(), 4) + "; // #" + i);
break;
case CONSTANT_CLASS:
out_println("class #" + in.readUnsignedShort() + "; // #" + i);
break;
case CONSTANT_PACKAGE:
out_begin("package { // #" + i);
out_println(toHex(in.readUnsignedByte(), 1) + "; // flags");
out_println("#" + in.readUnsignedShort() + "; // name");
out_println(in.readUnsignedByte() + "b; // minor version");
out_println(in.readUnsignedByte() + "b; // major version");
int aid_len = in.readUnsignedByte();
out_begin("Bytes" + startArray(aid_len) + "b {");
printBytes(in, aid_len);
out_end("};"); // Bytes[]
out_end("};"); // package info
break;
default:
throw new Error("invalid constant type: " + (int) tag);
}
}
;
out_end("} // Constant pool");
out_println("#" + in.readUnsignedShort() + "; // this package");
int class_count = in.readUnsignedByte();
out_begin(startArray(class_count) + "b { // classes");
for (int i = 0; i < class_count; i++) {
out_begin("{ // class " + i);
out_println(in.readUnsignedByte() + "b; // token");
int flags = in.readUnsignedShort();
out_print("0x");
printByteHex(out, flags >> 8);
printByteHex(out, flags);
out.println("; // flags");
out_println("#" + in.readUnsignedShort() + "; // this class");
int sup_count = in.readUnsignedShort();
out_begin(startArray(sup_count) + " { // supers");
for (int k = 0; k < sup_count; k++) {
out_println("#" + in.readUnsignedShort() + ";");
}
out_end("} // supers");
int int_count = in.readUnsignedByte();
out_begin(startArray(int_count) + "b { // interfaces");
for (int k = 0; k < int_count; k++) {
out_println("#" + in.readUnsignedShort() + ";");
}
out_end("} // interfaces");
int field_count = in.readUnsignedShort();
out_begin(startArray(field_count) + " { // fields");
for (int k = 0; k < field_count; k++) {
out_begin("{ // field " + k);
out_println(in.readUnsignedByte() + "b; // token");
int f_flags = in.readUnsignedShort();
out_print("0x");
printByteHex(out, f_flags >> 8);
printByteHex(out, f_flags);
out.println("; // flags");
out_println("#" + in.readUnsignedShort() + "; // this field name");
out_println("#" + in.readUnsignedShort() + "; // this field descriptor");
int attr_count = in.readUnsignedShort();
out_begin(startArray(attr_count) + " { // Attributes");
for (int ai = 0; ai < attr_count; ai++) {
decodeAttr(in);
}
out_end("} // Attributes");
out_end("};");
}
out_end("} // fields");
int mth_count = in.readUnsignedShort();
out_begin(startArray(mth_count) + " { // methods");
for (int k = 0; k < mth_count; k++) {
out_begin("{ // method " + k);
out_println(in.readUnsignedByte() + "b; // token");
int mth_flags = in.readUnsignedShort();
out_print("0x");
printByteHex(out, mth_flags >> 8);
printByteHex(out, mth_flags);
out.println("; // flags");
out_println("#" + in.readUnsignedShort() + "; // this method name");
out_println("#" + in.readUnsignedShort() + "; // this method descriptor");
out_end("};");
}
out_end("} // methods");
out_end("};");
}
out_end("} // classes");
endComponent(in);
}
DataInputStream beginComponent(String inpName) throws IOException {
DataInputStream in = new DataInputStream(new FileInputStream(inpName));
out_println("file " + inpName);
int tag = in.readUnsignedByte();
out_print("Component(" + tag);
int size = in.readUnsignedShort();
if (printDetails) {
out.print(", " + size);
}
out_begin(") { // " + compName(tag));
return in;
}
void endComponent(DataInputStream in) throws IOException {
out_end("};"); // Component
int avail = in.available();
if (avail > 0) {
out.println("=========== extra bytes:");
for (int k = 0; k < 8; k++) {
printBytes(in, avail >= 8 ? 8 : avail);
avail = in.available();
if (avail == 0) {
break;
}
}
if (avail > 0) {
out.println(" there is also " + avail + " bytes available");
}
}
in.close();
}
ArrayList<Integer> methodsLengths = null;
ArrayList<Integer> methodsOffsets = null;
void decodeHeader(String inpName) throws IOException {
DataInputStream in = beginComponent(inpName);
int magic = in.readInt();
out_print(toHex(magic, 4) + "; // ");
if (magic != HEADER_MAGIC) {
out.print("wrong magic: 0x" + Integer.toString(HEADER_MAGIC, 16) + " expected");
} else {
out_print("magic");
}
out.println();
out_println(in.readUnsignedByte() + "b; // minor version");
out_println(in.readUnsignedByte() + "b; // major version");
out_println(toHex(in.readUnsignedByte(), 1) + "; // flags");
out_begin("{ // package info");
out_println(in.readUnsignedByte() + "b; // minor version");
out_println(in.readUnsignedByte() + "b; // major version");
int aid_len = in.readUnsignedByte();
out_begin("Bytes" + startArray(aid_len) + "b {");
printBytes(in, aid_len);
out_end("};"); // Bytes[]
out_end("};"); // package info
endComponent(in);
}
void decodeDirectory(String inpName) throws IOException {
DataInputStream in = beginComponent(inpName);
int i;
out_begin("{ // component sizes");
for (i = 0; i < 11; i++) {
out_println(in.readUnsignedShort() + "; // " + (i + 1));
}
out_end("};");
out_begin("{ // static field size");
out_println(in.readUnsignedShort() + "; // image size");
out_println(in.readUnsignedShort() + "; // array init count");
out_println(in.readUnsignedShort() + "; // array init size");
out_end("};");
out_println(in.readUnsignedByte() + "b; // import count");
out_println(in.readUnsignedByte() + "b; // applet count");
int custom_count = in.readUnsignedByte();
out_begin(startArray(custom_count) + "b { // custom components");
for (i = 0; i < custom_count; i++) {
out_print("Comp(" + in.readUnsignedByte()); // tag;
int size2 = in.readUnsignedShort();
if (printDetails) {
out_print(", " + size2);
}
out_begin(") {");
int aid_len = in.readUnsignedByte();
out_begin("Bytes" + startArray(aid_len) + "b {");
printBytes(in, aid_len);
out_end("};");
out_end("};");
}
out_end("};");
endComponent(in);
}
void decodeApplet(String inpName) throws IOException {
DataInputStream in = beginComponent(inpName);
int applet_count = in.readUnsignedByte();
out_begin(startArray(applet_count) + "b { // applets");
for (int i = 0; i < applet_count; i++) {
out_begin("{ // applet " + i);
int aid_len = in.readUnsignedByte();
out_begin("Bytes" + startArray(aid_len) + "b {");
printBytes(in, aid_len);
out_end("};"); // Bytes[]
out_println(in.readUnsignedShort() + "; // install method offset");
out_end("};"); // applet
}
out_end("};"); // applets
endComponent(in);
}
void decodeImport(String inpName) throws IOException {
DataInputStream in = beginComponent(inpName);
int package_count = in.readUnsignedByte();
out_begin(startArray(package_count) + "b { // packages");
for (int i = 0; i < package_count; i++) {
out_begin("{ // package " + i);
out_println(in.readUnsignedByte() + "b; // minor version");
out_println(in.readUnsignedByte() + "b; // major version");
int aid_len = in.readUnsignedByte();
out_begin("Bytes" + startArray(aid_len) + "b {");
printBytes(in, aid_len);
out_end("};"); // Bytes[]
out_end("};"); // package info
}
out_end("};"); // package info
endComponent(in);
}
static String[] refNames = {
"Classref",
"InstanceFieldref",
"VirtualMethodref",
"SuperMethodref",
"StaticFieldref",
"StaticMethodref"
};
void decodeConstantPool(String inpName) throws IOException {
DataInputStream in = beginComponent(inpName);
int items_count = in.readUnsignedShort();
out_begin(startArray(items_count) + " { // items");
for (int i = 0; i < items_count; i++) {
int tag = in.readUnsignedByte();
int info1 = in.readUnsignedByte(),
info2 = in.readUnsignedByte(),
info3 = in.readUnsignedByte();
out_print(tag + "b ");
if ((tag > 0) && (tag <= 6)) {
if ((info1 & 0x80) == 0) {
if (tag <= 4) {
out_print(((info1 << 8) | info2) + " " + info3 + "b;");
} else {
out_print(info1 + "b " + ((info2 << 8) | info3) + ";");
}
out.print(" // internal ");
} else {
out.print(info1 + "b " + info2 + "b " + info3 + "b;");
out.print(" // external ");
}
out.println(refNames[tag - 1]);
} else {
out.print(info1 + "b " + info2 + "b " + info3 + "b;");
out.println(" // unknown tag ");
}
}
out_end("};"); // CP array
endComponent(in);
}
void printClassref(DataInputStream in) throws IOException {
int info1 = in.readUnsignedByte(),
info2 = in.readUnsignedByte();
if ((info1 & 0x80) == 0) {
out_print(((info1 << 8) | info2) + ";");
out_print(" // internal ");
} else {
out_print(info1 + "b " + info2 + "b;");
out_print(" // external ");
}
out_println(" Classref ");
}
void decodeClass(String inpName) throws IOException {
DataInputStream in = beginComponent(inpName);
for (int i = 0; in.available() > 0; i++) {
out_begin("{ // class " + i);
int bitfield = in.readUnsignedByte();
int interface_count = bitfield & 0x0F;
out_print("0x");
printByteHex(out, bitfield);
out.println("; // bitfield");
if ((bitfield & 0x80) != 0) {
// interface
for (int k = 0; k < interface_count; k++) {
printClassref(in);
}
} else {
// class
printClassref(in);
out_println(in.readUnsignedByte() + "b; // declared instance size");
out_println(in.readUnsignedByte() + "b; // first reference token");
out_println(in.readUnsignedByte() + "b; // reference count");
out_println(in.readUnsignedByte() + "b; // public method table base");
int pumrc = in.readUnsignedByte();
out_println(pumrc + "b; // public method table count");
out_println(in.readUnsignedByte() + "b; // package method table base");
int pamrc = in.readUnsignedByte();
out_println(pamrc + "b; // package method table count");
out_begin("{ // public method table");
for (int k = 0; k < pumrc; k++) {
out_println(in.readUnsignedShort() + ";");
}
out_end("};");
out_begin("{ // package method table");
for (int k = 0; k < pamrc; k++) {
out_println(in.readUnsignedShort() + ";");
}
out_end("};");
out_begin("{ // implemented interfaces");
for (int k = 0; k < interface_count; k++) {
out_begin("{ // interface " + k);
printClassref(in);
int count = in.readUnsignedByte();
out_begin("Bytes" + startArray(count) + "b {");
printBytes(in, count);
out_end("};"); // Bytes[]
out_end("};");
}
out_end("};");
}
out_end("};");
}
endComponent(in);
}
void decodeDescriptor(String inpName) throws IOException {
DataInputStream in = beginComponent(inpName);
methodsLengths = new ArrayList<>();
methodsOffsets = new ArrayList<>();
int class_count = in.readUnsignedByte();
out_begin(startArray(class_count) + "b { // classes");
for (int c = 0; c < class_count; c++) {
out_begin("{ // class " + c);
out_println(in.readUnsignedByte() + "b; // token");
out_print("0x");
printByteHex(out, in.readUnsignedByte());
out.println("; // flags");
printClassref(in);
int icount = in.readUnsignedByte();
out_println(icount + "b; // interface count");
int fcount = in.readUnsignedShort();
out_println(fcount + "; // field count");
int mcount = in.readUnsignedShort();
out_println(mcount + "; // method count");
if (icount != 0) {
out_begin("{ // interfaces");
for (int i = 0; i < icount; i++) {
printClassref(in);
}
out_end("};");
}
for (int i = 0; i < fcount; i++) {
out_begin("{ // field " + i);
out_println(in.readUnsignedByte() + "b; // token");
int flags = in.readUnsignedByte();
out_print("0x");
printByteHex(out, flags);
out.println("; // flags");
if ((flags & 0x08) == 0) {
printClassref(in);
out_println(in.readUnsignedByte() + "b; // token");
} else { // static field
int info1 = in.readUnsignedByte(),
info2 = in.readUnsignedByte(),
info3 = in.readUnsignedByte();
if ((info1 & 0x80) == 0) {
out_print(info1 + "b " + ((info2 << 8) | info3) + ";");
out.println(" // internal field");
} else {
out.print(info1 + "b " + info2 + "b " + info3 + "b;");
out.println(" // external field");
}
}
int type = in.readUnsignedShort();
if ((type & 0x8000) == 0) {
out_println(type + "; // reference type");
} else {
out_print("0x");
printByteHex(out, type >> 8);
printByteHex(out, type);
out.println("; // primitive type");
}
out_end("};");
}
for (int i = 0; i < mcount; i++) {
int token = in.readUnsignedByte();
int flags = in.readUnsignedByte();
int m_offset = in.readUnsignedShort();
int t_offset = in.readUnsignedShort();
int bytecode_count = in.readUnsignedShort();
if (m_offset != 0) {
out_begin("{ // method " + i + " (" + methodsLengths.size() + ")");
methodsLengths.add(bytecode_count);
methodsOffsets.add(m_offset);
} else {
out_begin("{ // method " + i);
}
out_println(token + "b; // token");
out_print("0x");
printByteHex(out, flags);
out.println("; // flags");
out_println(m_offset + "; // method offset");
out_println(t_offset + "; // type offset");
out_println(bytecode_count + "; // bytecode count");
out_println(in.readUnsignedShort() + "; // exception handler count");
out_println(in.readUnsignedShort() + "; // exception handler index");
out_end("};");
}
out_end("};"); // class i
}
out_end("}; // classes");
int cp_count = in.readUnsignedShort();
out_begin(startArray(cp_count) + " { // constant pool types");
for (int i = 0; i < cp_count; i++) {
int type = in.readUnsignedShort();
if (type == 0xFFFF) {
out_println("0xFFFF;");
} else {
out_println(type + "; ");
}
}
out_end("}; // constant pool types");
out_begin("{ // type descriptors");
for (int i = 0; in.available() > 0; i++) {
int nibble_count = in.readUnsignedByte();
out_print(nibble_count + "b; ");
printBytes(in, (nibble_count + 1) / 2);
}
out_end("}; // type descriptors");
endComponent(in);
}
void decodeMethod(String inpName) throws IOException {
DataInputStream in = beginComponent(inpName);
int handler_count = in.readUnsignedByte();
out_begin(startArray(handler_count) + "b { // exception handlers");
for (int i = 0; i < handler_count; i++) {
out_print(in.readUnsignedShort() + ", ");
int bitfield = in.readUnsignedShort();
out.print("0x");
printByteHex(out, bitfield >> 8);
printByteHex(out, bitfield);
out.print(", " + in.readUnsignedShort() + ", ");
out.println(in.readUnsignedShort() + "; // handler " + i);
}
out_end("};"); // handlers
if (methodsLengths == null) {
out.println("// Descriptor.cap absent - methods not printed");
} else {
int f_offset = 1 + handler_count * 8;
for (int i = 0; i < methodsLengths.size(); i++) {
out_begin("{ // method " + i);
int m_offset = methodsOffsets.get(i);
if (m_offset != f_offset) {
out.println("file offset=" + f_offset + " but m_offset=" + m_offset);
break;
}
int bitfield = in.readUnsignedByte();
if ((bitfield & 0x80) == 0) {
out_print("0x");
printByteHex(out, bitfield);
out.println("; // flags, max_stack");
out_print("0x");
printByteHex(out, in.readUnsignedByte());
out.println("; // nargs, max_locals");
f_offset += 2;
} else {
out_print("0x");
printByteHex(out, bitfield);
out.println("; // flags, padding");
out_println(in.readUnsignedByte() + "b; // max_stack");
out_println(in.readUnsignedByte() + "b; // nargs");
out_println(in.readUnsignedByte() + "b; // max_locals");
f_offset += 4;
}
int bytecode_count = methodsLengths.get(i);
out_begin("{ // bytecodes");
printBytes(in, bytecode_count);
f_offset += bytecode_count;
out_end("};");
out_end("};");
}
}
endComponent(in);
}
void decodeStaticField(String inpName) throws IOException {
DataInputStream in = beginComponent(inpName);
int image_size = in.readUnsignedShort();
out_println(image_size + "; // image size");
int reference_count = in.readUnsignedShort();
out_println(reference_count + "; // reference count");
int array_init_count = in.readUnsignedShort();
out_begin(startArray(array_init_count) + " { // array_init_info");
for (int i = 0; i < array_init_count; i++) {
out_println(in.readUnsignedByte() + "b // type ");
int count = in.readUnsignedShort();
out_begin("Bytes" + startArray(count) + "s { // values");
printBytes(in, count);
out_end("};"); // Bytes[]
}
out_end("};"); // array_init_info
int default_value_count = in.readUnsignedShort();
out_println(default_value_count + "; // default value count");
int non_default_value_count = in.readUnsignedShort();
out_begin("Bytes" + startArray(non_default_value_count) + "s { // non default values");
printBytes(in, non_default_value_count);
out_end("};"); // Bytes[]
endComponent(in);
}
void decodeRefLocation(String inpName) throws IOException {
DataInputStream in = beginComponent(inpName);
int byte_index_count = in.readUnsignedShort();
out_begin("Bytes" + startArray(byte_index_count) + "s { // offsets to byte indices");
printBytes(in, byte_index_count);
out_end("};"); // Bytes[]
byte_index_count = in.readUnsignedShort();
out_begin("Bytes" + startArray(byte_index_count) + "s { // offsets to byte2 indices");
printBytes(in, byte_index_count);
out_end("};"); // Bytes[]
endComponent(in);
}
void decodeExport(String inpName) throws IOException {
DataInputStream in = beginComponent(inpName);
int class_count = in.readUnsignedByte();
out_begin(startArray(class_count) + "b { // classes");
for (int i = 0; i < class_count; i++) {
out_begin("{ // class " + i);
out_println(in.readUnsignedShort() + "; // class offset");
int fcount = in.readUnsignedByte();
out_println(fcount + "b; // static field count");
int mcount = in.readUnsignedByte();
out_println(mcount + "b; // static method count");
out_begin("{ // static field offsets");
for (int j = 0; j < fcount; j++) {
out_println(in.readUnsignedShort() + "; // field " + j + " offset");
}
out_end("};");
out_begin("{ // static method offsets");
for (int j = 0; j < mcount; j++) {
out_println(in.readUnsignedShort() + "; // method " + j + " offset");
}
out_end("};");
out_end("};"); // class i
}
out_end("};"); // classes
endComponent(in);
}
/*========================================================*/
/**
* Constructor.
*/
public Main(PrintWriter out, String program) {
this.out = out;
this.program = program;
}
public void error(String msg) {
out.println(program + ": " + msg);
}
/**
* Usage
*/
public void usage() {
out.println(i18n.getString("jcdec.usage"));
out.println(i18n.getString("jcdec.opt.g"));
out.println(i18n.getString("jcdec.opt.version"));
}
/**
* Run the decoder
*/
public synchronized boolean decode(String argv[]) {
// int flags = F_WARNINGS;
long tm = System.currentTimeMillis();
ArrayList<String> vargs = new ArrayList<>();
ArrayList<String> vj = new ArrayList<>();
boolean nowrite = false;
int addOptions = 0;
// Parse arguments
for (int i = 0; i < argv.length; i++) {
String arg = argv[i];
if (arg.equals("-g")) {
printDetails = true;
vargs.add(arg);
} else if (arg.equals("-v")) {
DebugFlag = true;
vargs.add(arg);
out.println("arg[" + i + "]=" + argv[i] + "/verbose");
} else if (arg.equals("-version")) {
out.println(ProductInfo.FULL_VERSION);
} else if (arg.startsWith("-")) {
//out.println("arg["+i+"]="+argv[i]+"/invalid flag");
error(i18n.getString("jcdec.error.invalid_flag", arg));
usage();
return false;
} else {
vargs.add(arg);
vj.add(arg);
}
}
if (vj.isEmpty()) {
usage();
return false;
}
// String[] names = new String[vj.size()];
// vj.copyInto(names);
String[] names = null;
names = vj.toArray(names);
decode:
for (int k = 0; k < names.length; k++) {
String inpname = names[k];
try {
if (inpname.endsWith(".cap")) {
String shortName = inpname.substring(0, inpname.length() - 4);
if (shortName.endsWith("Header")) {
decodeHeader(inpname);
} else if (shortName.endsWith("Directory")) {
decodeDirectory(inpname);
} else if (shortName.endsWith("Applet")) {
decodeApplet(inpname);
} else if (shortName.endsWith("Import")) {
decodeImport(inpname);
} else if (shortName.endsWith("ConstantPool")) {
decodeConstantPool(inpname);
} else if (shortName.endsWith("Class")) {
decodeClass(inpname);
} else if (shortName.endsWith("Descriptor")) {
decodeDescriptor(inpname);
} else if (shortName.endsWith("Method")) {
decodeMethod(inpname);
} else if (shortName.endsWith("StaticField")) {
decodeStaticField(inpname);
} else if (shortName.endsWith("RefLocation")) {
decodeRefLocation(inpname);
} else if (shortName.endsWith("Export")) {
decodeExport(inpname);
} else {
continue decode;
}
out.println("");
} else if (inpname.endsWith(".exp")) {
decodeExp(inpname);
out.println("");
}
continue decode;
} catch (FileNotFoundException ee) {
error(i18n.getString("jcdec.error.cannot_read", inpname));
} catch (Error ee) {
ee.printStackTrace();
error(i18n.getString("jcdec.error.fatal_error"));
} catch (Exception ee) {
ee.printStackTrace();
error(i18n.getString("jcdec.error.fatal_exception"));
}
return false;
}
return true;
}
/**
* Main program
*/
public static void main(String argv[]) {
Main decoder = new Main(new PrintWriter(new uEscWriter(System.out)), "jcdec");
System.exit(decoder.decode(argv) ? 0 : 1);
}
}

View File

@ -0,0 +1,34 @@
# Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
jcdec.error.invalid_flag=invalid flag: " {0}
jcdec.error.fatal_error=fatal error
jcdec.error.fatal_exception=fatal exception
jcdec.error.cannot_read=cannot read {0}
jcdec.usage=\
Usage: java -jar asmtools.jar jcdec [options] FILE.class... > FILE.jcod\n\
where possible options include:
jcdec.opt.g=\
\ -g: detailed output format
jcdec.opt.version=\
\ -version: print version number and date

View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jcoder;
/**
* Compiles just 1 source file
*/
class ByteBuffer extends java.io.OutputStream {
String myname;
/**
* The buffer where elements are stored.
*/
byte data[];
/**
* The number of elements in the buffer.
*/
int length;
/**
* The size of the increment. If it is 0 the size of the the buffer is doubled
* everytime it needs to grow.
*/
protected int capacityIncrement;
/**
* Constructs an empty vector with the specified storage capacity and the specified
* capacityIncrement.
*
* @param initialCapacity the initial storage capacity of the vector
* @param capacityIncrement how much to increase the element's size by.
*/
public ByteBuffer(int initialCapacity, int capacityIncrement) {
// super();
this.data = new byte[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
/**
* Constructs an empty vector with the specified storage capacity.
*
* @param initialCapacity the initial storage capacity of the vector
*/
public ByteBuffer(int initialCapacity) {
this(initialCapacity, 0);
}
/**
* Constructs an empty vector.
*/
public ByteBuffer() {
this(30);
}
/**
* Constructs a full vector.
*/
public ByteBuffer(byte data[], int capacityIncrement) {
this.length = data.length;
this.data = data;
this.capacityIncrement = capacityIncrement;
}
/**
* Constructs a full vector.
*/
public ByteBuffer(byte data[]) {
this(data, 0);
}
/**
* Returns the number of elements in the vector. Note that this is not the same as the
* vector's capacity.
*/
public final int size() {
return length;
}
/**
* Ensures that the vector has at least the specified capacity.
*
* @param minCapacity the desired minimum capacity
*/
public final synchronized void ensureCapacity(int minCapacity) {
int oldCapacity = data.length;
if (minCapacity <= oldCapacity) {
return;
}
byte oldData[] = data;
int newCapacity = (capacityIncrement > 0) ? (oldCapacity + capacityIncrement) : (oldCapacity * 2);
if (newCapacity < minCapacity) {
newCapacity = minCapacity;
}
data = new byte[newCapacity];
System.arraycopy(oldData, 0, data, 0, length);
}
/*======================================*/
/**
* Adds the specified object as the last element of the vector.
*
* @param obj the element to be added
*/
public void write(int val) {
ensureCapacity(length + 1);
data[length++] = (byte) val;
}
public void writeAt(int index, long val, int width) {
for (int i = 0; i < width; i++) {
data[index + i] = (byte) (val >> (width - 1 - i) * 8);
}
}
public void append(long val, int width) {
ensureCapacity(length + width);
writeAt(length, val, width);
length += width;
}
/*======================================================*/
} // end ByteBuffer

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jcoder;
/**
* A sorted list of error messages
*/
final class ErrorMessage {
int where;
String message;
ErrorMessage next;
/**
* Constructor
*/
ErrorMessage(int where, String message) {
this.where = where;
this.message = message;
}
}

View File

@ -0,0 +1,386 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jcoder;
import static org.openjdk.asmtools.jasm.Tables.*;
import java.io.PrintWriter;
import java.util.HashMap;
/**
*
* JcodTokens
*
* This class contains tokens specific to parsing JCOD syntax.
*
* The classes in JcodTokens are following a Singleton Pattern. These classes are Enums,
* and they are contained in private hash maps (lookup tables and reverse lookup tables).
* These hash maps all have public accessors, which clients use to look-up enums.
*
* Tokens in this table carry no external state, and are typically treated as constants.
* They do not need to be reset.
*/
public class JcodTokens {
/*-------------------------------------------------------- */
/* Marker: describes the type of Keyword */
static public enum KeywordType {
TOKEN(0, "TOKEN"),
KEYWORD(3, "KEYWORD");
private final Integer value;
private final String printval;
KeywordType(Integer val, String print) {
value = val;
printval = print;
}
public String printval() {
return printval;
}
}
/*-------------------------------------------------------- */
/* Marker - describes the type of token */
/* this is rather cosmetic, no function currently. */
static public enum TokenType {
VALUE (0, "Value"),
KEYWORDS (1, "Keywords"),
PUNCTUATION (2, "Punctuation"),
JDEC (3, "JDec"),
STACKMAP (4, "StackMap"),
MISC (5, "Misc");
private final Integer value;
private final String printval;
TokenType(Integer val, String print) {
value = val;
printval = print;
}
public String printval() {
return printval;
}
}
/*-------------------------------------------------------- */
/** Scanner Tokens (Definitive List) */
static public enum Token {
EOF (-1, "EOF", "EOF", TokenType.MISC),
IDENT (60, "IDENT", "IDENT", TokenType.VALUE),
LONGSTRINGVAL (61, "LONGSTRINGVAL", "LONGSTRING", TokenType.VALUE),
INTVAL (65, "INTVAL", "INT", TokenType.VALUE),
LONGVAL (66, "LONGVAL", "LONG", TokenType.VALUE),
STRINGVAL (69, "STRINGVAL", "STRING", TokenType.VALUE),
CLASS (70, "CLASS", "class", TokenType.KEYWORDS, KeywordType.KEYWORD),
INTERFACE (71, "INTERFACE", "interface", TokenType.KEYWORDS, KeywordType.KEYWORD),
DIV (72, "DIV", "div", TokenType.KEYWORDS),
EQ (73, "EQ", "eq", TokenType.KEYWORDS),
ASSIGN (74, "ASSIGN", "assign", TokenType.KEYWORDS),
COLON (134, "COLON", ":", TokenType.PUNCTUATION),
SEMICOLON (135, "SEMICOLON", ";", TokenType.PUNCTUATION, KeywordType.KEYWORD),
COMMA (0, "COMMA", ",", TokenType.PUNCTUATION, KeywordType.KEYWORD),
LBRACE (138, "LBRACE", "{", TokenType.PUNCTUATION, KeywordType.KEYWORD),
RBRACE (139, "RBRACE", "}", TokenType.PUNCTUATION, KeywordType.KEYWORD),
LPAREN (140, "LPAREN", "(", TokenType.PUNCTUATION, KeywordType.KEYWORD),
RPAREN (141, "RPAREN", ")", TokenType.PUNCTUATION, KeywordType.KEYWORD),
LSQBRACKET (142, "LSQBRACKET", "[", TokenType.PUNCTUATION, KeywordType.KEYWORD),
RSQBRACKET (143, "RSQBRACKET", "]", TokenType.PUNCTUATION, KeywordType.KEYWORD),
BYTEINDEX (156, "BYTEINDEX", "b", TokenType.JDEC, KeywordType.KEYWORD),
SHORTINDEX (157, "SHORTINDEX", "s", TokenType.JDEC, KeywordType.KEYWORD),
ATTR (158, "ATTR", "Attr", TokenType.JDEC, KeywordType.KEYWORD),
BYTES (159, "BYTES", "Bytes", TokenType.JDEC, KeywordType.KEYWORD),
MACRO (160, "MACRO", "Attr", TokenType.JDEC),
COMP (161, "COMP", "Component", TokenType.JDEC, KeywordType.KEYWORD),
FILE (162, "FILE", "file", TokenType.JDEC, KeywordType.KEYWORD),
ZEROINDEX (163, "ZEROINDEX", "z", TokenType.STACKMAP, KeywordType.KEYWORD);
private Integer value;
private String printval;
private String parsekey;
private TokenType tk_type;
private KeywordType key_type;
// By default, if a KeywordType is not specified, it has the value 'TOKEN'
Token(Integer val, String print, String op) {
init(val, print, op, TokenType.VALUE, KeywordType.TOKEN);
}
Token(Integer val, String print, String op, TokenType tt) {
init(val, print, op, tt, KeywordType.TOKEN);
}
Token(Integer val, String print, String op, TokenType tt, KeywordType kt) {
init(val, print, op, tt, kt);
}
private void init(Integer val, String print, String op, TokenType tt, KeywordType kt) {
value = val;
printval = print;
parsekey = op;
tk_type = tt;
key_type = kt;
}
public String printval() {
return printval;
}
public String parsekey() {
return parsekey;
}
public int value() {
return value;
}
@Override
public String toString() {
return "<" + printval + "> [" + value + "]";
}
}
/**
* Initialized keyword and token Hash Maps (and Reverse Tables)
*/
protected static final int MaxTokens = 172;
private static HashMap<Integer, Token> TagToTokens = new HashMap<>(MaxTokens);
private static HashMap<String, Token> SymbolToTokens = new HashMap<>(MaxTokens);
private static HashMap<String, Token> ParsekeyToTokens = new HashMap<>(MaxTokens);
protected static final int MaxKeywords = 40;
private static HashMap<Integer, Token> TagToKeywords = new HashMap<>(MaxKeywords);
private static HashMap<String, Token> SymbolToKeywords = new HashMap<>(MaxKeywords);
private static HashMap<String, Token> ParsekeyToKeywords = new HashMap<>(MaxKeywords);
static {
// register all of the tokens
for (Token tk : Token.values()) {
registerToken(tk);
}
SymbolToKeywords.put(Token.INTVAL.printval(), Token.INTVAL);
ParsekeyToKeywords.put(Token.INTVAL.parsekey(), Token.INTVAL);
SymbolToKeywords.put(Token.STRINGVAL.printval(), Token.STRINGVAL);
ParsekeyToKeywords.put(Token.STRINGVAL.parsekey(), Token.STRINGVAL);
}
private static void registerToken(Token tk) {
// Tag is a keyword
if (tk.key_type == KeywordType.KEYWORD) {
TagToKeywords.put(tk.value, tk);
SymbolToKeywords.put(tk.printval, tk);
if (tk.parsekey != null) {
ParsekeyToKeywords.put(tk.parsekey, tk);
}
}
// Finally, register all tokens
TagToTokens.put(tk.value, tk);
SymbolToTokens.put(tk.printval, tk);
ParsekeyToTokens.put(tk.printval, tk);
}
/* Token accessors */
public static Token token(int tk) {
return TagToTokens.get(tk);
}
public static Token keyword_token(int tk) {
return TagToKeywords.get(tk);
}
/* Reverse lookup accessors */
public static Token token(String parsekey) {
return ParsekeyToTokens.get(parsekey);
}
public static Token keyword_token(String parsekey) {
return ParsekeyToKeywords.get(parsekey);
}
/* Reverse lookup by ID accessors */
public static Token token_ID(String ID) {
return ParsekeyToTokens.get(ID);
}
public static Token keyword_token_ID(String ID) {
return ParsekeyToKeywords.get(ID);
}
public static String keywordName(int token) {
String retval = "";
if (token > TagToTokens.size()) {
retval = null;
} else {
Token tk = keyword_token(token);
if (tk != null) {
retval = tk.parsekey;
}
}
return retval;
}
public static Token keyword_token_ident(String idValue) {
Token kwd = keyword_token(idValue);
if (kwd == null) {
kwd = Token.IDENT;
}
return kwd;
}
public static int keyword_token_int(String idValue) {
return keyword_token_ident(idValue).value();
}
private static HashMap<String, ConstType> NameToConstantType = new HashMap<>(ConstType.maxTag);
private static HashMap<Integer, ConstType> ConstantTypes = new HashMap<>(ConstType.maxTag);
static {
// register all of the tokens
for (ConstType ct : ConstType.values()) {
registerConstantType(ct);
}
}
/**
* ConstType
*
* A (typed) tag (constant) representing the type of Constant in the Constant Pool.
*
* This is more-or-less a copy of jasm.ConstType. Unfortunately, there's no way to
* sub-class (or slightly alter) the members of an enum. This enum set is slightly
* modified from the Jasm one.
*/
static public enum ConstType {
// CONSTANT_ZERO (-3, "CONSTANT_ZERO", ""),
CONSTANT_UTF8 (1, "CONSTANT_UTF8", "Asciz", "Utf8"),
CONSTANT_UNICODE (2, "CONSTANT_UNICODE", ""),
CONSTANT_INTEGER (3, "CONSTANT_INTEGER", "int", "u4"),
CONSTANT_FLOAT (4, "CONSTANT_FLOAT", "float"),
CONSTANT_LONG (5, "CONSTANT_LONG", "long"),
CONSTANT_DOUBLE (6, "CONSTANT_DOUBLE", "double"),
// Class is removed for JavaCard (???)
CONSTANT_CLASS (7, "CONSTANT_CLASS", "class"),
CONSTANT_STRING (8, "CONSTANT_STRING", "String"),
CONSTANT_FIELD (9, "CONSTANT_FIELD", "Field"),
CONSTANT_METHOD (10, "CONSTANT_METHOD", "Method"),
CONSTANT_INTERFACEMETHOD (11, "CONSTANT_INTERFACEMETHOD", "InterfaceMethod"),
CONSTANT_NAMEANDTYPE (12, "CONSTANT_NAMEANDTYPE", "NameAndType"),
// added for JavaCard
CONSTANT_PACKAGE (13, "CONSTANT_PACKAGE", "package"), // in javacard export file
// Constant 14 reserved
CONSTANT_METHODHANDLE (15, "CONSTANT_METHODHANDLE", "MethodHandle"),
CONSTANT_METHODTYPE (16, "CONSTANT_METHODTYPE", "MethodType"),
CONSTANT_INVOKEDYNAMIC_TRANS (17, "CONSTANT_INVOKEDYNAMIC_TRANS", "InvokeDynamicTrans"),
CONSTANT_INVOKEDYNAMIC (18, "CONSTANT_INVOKEDYNAMIC", "InvokeDynamic");
public static final int maxTag = 18;
private final int value;
private final String parseKey;
private final String printval;
private final String alias;
ConstType(int val, String print, String parse) {
value = val;
parseKey = parse;
printval = print;
alias = null;
}
ConstType(int val, String print, String parse, String als) {
value = val;
parseKey = parse;
printval = print;
alias = als;
}
public int value() {
return value;
}
public String parseKey() {
return parseKey;
}
public String printval() {
return printval;
}
public void print(PrintWriter out) {
out.print(parseKey);
}
@Override
public String toString() {
return "<" + printval + "> [" + Integer.toString(value) + "]";
}
};
static public ConstType constType(int i) {
return ConstantTypes.get(i);
}
static public ConstType constType(String parsekey) {
return NameToConstantType.get(parsekey);
}
private static void registerConstantType(ConstType tt) {
NameToConstantType.put(tt.parseKey, tt);
if (tt.alias != null) {
NameToConstantType.put(tt.alias, tt);
}
ConstantTypes.put(tt.value, tt);
}
static int constValue(String stringValue) {
ConstType Val = constType(stringValue);
int val = -1;
if (Val != null) {
val = Val.value();
} else {
StackMapType smt = stackMapTypeKey(stringValue);
if (smt != null) {
val = smt.value();
}
}
return val;
}
}

View File

@ -0,0 +1,761 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jcoder;
import static org.openjdk.asmtools.jcoder.JcodTokens.*;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Stack;
import java.util.ArrayList;
/**
* Compiles just 1 source file
*/
class Jcoder {
/*-------------------------------------------------------- */
/* Jcoder Fields */
ArrayList<ByteBuffer> Classes = new ArrayList<>();
ByteBuffer buf;
DataOutputStream bufstream;
String pkg = null, pkgPrefix = "";
int depth = 0;
String tabStr = "";
Context context = null;
protected SourceFile env;
protected Scanner scanner;
/*-------------------------------------------------------- */
/* Jcoder inner classes */
/*-------------------------------------------------------- */
/* ContextTag (marker) - describes the type of token */
/* this is rather cosmetic, no function currently. */
static public enum ContextTag {
NULL (0, ""),
CLASS (1, "Class"),
CONSTANTPOOL (2, "Constant-Pool"),
INTERFACES (3, "Interfaces"),
INTERFACE (4, "Interface"),
METHODS (5, "Methods"),
METHOD (6, "Method"),
FIELDS (7, "Fields"),
FIELD (8, "Field"),
ATTRIBUTE (9, "Attribute");
private final Integer value;
private final String printval;
ContextTag(Integer val, String print) {
value = val;
printval = print;
}
public String printval() {
return printval;
}
}
/*-------------------------------------------------------- */
/* ContextVal (marker) - Specific value on a context stack */
public class ContextVal {
public ContextTag tag;
public int compCount;
public ContextVal owner;
public ContextVal(ContextTag tg) {
tag = tg;
compCount = 0;
owner = null;
}
public ContextVal(ContextTag tg, ContextVal ownr) {
tag = tg;
compCount = 0;
owner = ownr;
}
}
/*-------------------------------------------------------- */
/* Context - Context stack */
public class Context {
Stack<ContextVal> stack;
private boolean hasCP;
private boolean hasMethods;
private boolean hasInterfaces;
private boolean hasFields;
Context() {
stack = new Stack<>();
init();
}
public boolean isConstantPool() {
if (stack.empty()) {
return false;
}
return (stack.peek().tag == ContextTag.CONSTANTPOOL);
}
public void init() {
stack.removeAllElements();
hasCP = false;
hasMethods = false;
hasInterfaces = false;
hasFields = false;
}
public void update() {
if (stack.empty()) {
stack.push(new ContextVal(ContextTag.CLASS));
return;
}
ContextVal currentCtx = stack.peek();
switch (currentCtx.tag) {
case CLASS:
if (!hasCP) {
stack.push(new ContextVal(ContextTag.CONSTANTPOOL));
hasCP = true;
} else if (!hasInterfaces) {
stack.push(new ContextVal(ContextTag.INTERFACES));
hasInterfaces = true;
} else if (!hasFields) {
stack.push(new ContextVal(ContextTag.FIELDS));
hasFields = true;
} else if (!hasMethods) {
stack.push(new ContextVal(ContextTag.METHODS));
hasMethods = true;
} else {
// must be class attributes
currentCtx.compCount += 1;
stack.push(new ContextVal(ContextTag.ATTRIBUTE, currentCtx));
}
break;
case INTERFACES:
currentCtx.compCount += 1;
stack.push(new ContextVal(ContextTag.INTERFACE, currentCtx));
break;
// case INTERFACE:
// break;
case FIELDS:
currentCtx.compCount += 1;
stack.push(new ContextVal(ContextTag.FIELD, currentCtx));
break;
case METHODS:
currentCtx.compCount += 1;
stack.push(new ContextVal(ContextTag.METHOD, currentCtx));
break;
case FIELD:
case METHOD:
case ATTRIBUTE:
currentCtx.compCount += 1;
stack.push(new ContextVal(ContextTag.ATTRIBUTE, currentCtx));
break;
default:
break;
}
}
public void exit() {
if (!stack.isEmpty()) {
stack.pop();
}
}
public String toString() {
if (stack.isEmpty()) {
return "";
}
ContextVal currentCtx = stack.peek();
String retval = currentCtx.tag.printval();
switch (currentCtx.tag) {
case INTERFACE:
case METHOD:
case FIELD:
case ATTRIBUTE:
if (currentCtx.owner != null) {
retval += "[" + currentCtx.owner.compCount + "]";
}
}
return retval;
}
}
/*-------------------------------------------------------- */
/* Jcoder */
/**
* Create a parser
*/
protected Jcoder(SourceFile sf, HashMap<String, String> macros) throws IOException {
scanner = new Scanner(sf, macros);
env = sf;
context = new Context();
}
/*-------------------------------------------------------- */
/**
* Expect a token, return its value, scan the next token or throw an exception.
*/
protected final void expect(Token t) throws SyntaxError, IOException {
if (scanner.token != t) {
env.traceln("expect:" + t + " instead of " + scanner.token);
switch (t) {
case IDENT:
// env.error(prevPos, "identifier.expected");
env.error(scanner.pos, "identifier.expected");
break;
default:
// env.error(prevPos, "token.expected", keywordName(t)]);
env.error(scanner.pos, "token.expected", t.toString());
break;
}
throw new SyntaxError();
}
scanner.scan();
}
protected void recoverField() throws SyntaxError, IOException {
while (true) {
switch (scanner.token) {
case LBRACE:
scanner.match(Token.LBRACE, Token.RBRACE);
scanner.scan();
break;
case LPAREN:
scanner.match(Token.LPAREN, Token.RPAREN);
scanner.scan();
break;
case LSQBRACKET:
scanner.match(Token.LSQBRACKET, Token.RSQBRACKET);
scanner.scan();
break;
case RBRACE:
case EOF:
case INTERFACE:
case CLASS:
// begin of something outside a class, panic more
// endClass(pos);
throw new SyntaxError();
default:
// don't know what to do, skip
scanner.scan();
break;
}
}
}
/**
* Parse an array of struct.
*/
protected void parseArray() throws IOException {
scanner.scan();
int length0 = buf.length, pos0 = scanner.pos;
int num_expected;
if (scanner.token == Token.INTVAL) {
num_expected = scanner.intValue;
scanner.scan();
} else {
num_expected = -1;
}
expect(Token.RSQBRACKET);
int numSize;
switch (scanner.token) {
case BYTEINDEX:
scanner.scan();
numSize = 1;
break;
case SHORTINDEX:
scanner.scan();
numSize = 2;
break;
case ZEROINDEX:
scanner.scan();
numSize = 0;
break;
default:
numSize = 2;
}
// skip array size
if (numSize > 0) {
buf.append(num_expected, numSize);
}
int num_present = parseStruct();
if (num_expected == -1) {
env.trace(" buf.writeAt(" + length0 + ", " + num_present + ", " + numSize + "); ");
// skip array size
if (numSize > 0) {
buf.writeAt(length0, num_present, numSize);
}
} else if (num_expected != num_present) {
env.error(pos0, "warn.array.wronglength", new Integer(num_expected), new Integer(num_present));
}
}
/**
* Parse a byte array.
*/
protected void parseByteArray() throws IOException {
scanner.scan();
expect(Token.LSQBRACKET);
int length0 = buf.length, pos0 = scanner.pos;
int len_expected;
if (scanner.token == Token.INTVAL) {
len_expected = scanner.intValue;
scanner.scan();
} else {
len_expected = -1;
}
expect(Token.RSQBRACKET);
int lenSize;
switch (scanner.token) {
case BYTEINDEX:
scanner.scan();
lenSize = 1;
break;
case SHORTINDEX:
scanner.scan();
lenSize = 2;
break;
case ZEROINDEX:
scanner.scan();
lenSize = 0;
break;
default:
lenSize = 4;
}
// skip array size
if (lenSize > 0) {
buf.append(len_expected, lenSize);
}
int length1 = buf.length;
parseStruct();
int len_present = buf.length - length1;
if (len_expected == -1) {
env.trace(" buf.writeAt(" + length0 + ", " + len_present + ", " + lenSize + "); ");
// skip array size
if (lenSize > 0) {
buf.writeAt(length0, len_present, lenSize);
}
} else if (len_expected != len_present) {
env.error(pos0, "warn.array.wronglength", new Integer(len_expected), new Integer(len_present));
}
}
/**
* Parse an Attribute.
*/
protected void parseAttr() throws IOException {
scanner.scan();
expect(Token.LPAREN);
int cpx; // index int const. pool
if (scanner.token == Token.INTVAL) {
cpx = scanner.intValue;
scanner.scan();
/* } else if (token==STRINGVAL) {
Integer Val=(Integer)(CP_Strings.get(stringValue));
if (Val == null) {
env.error(pos, "attrname.notfound", stringValue);
throw new SyntaxError();
}
cpx=Val.intValue();
*/ } else {
env.error(scanner.pos, "attrname.expected");
throw new SyntaxError();
}
buf.append(cpx, 2);
int pos0 = scanner.pos, length0 = buf.length;
int len_expected;
if (scanner.token == Token.COMMA) {
scanner.scan();
len_expected = scanner.intValue;
expect(Token.INTVAL);
} else {
len_expected = -1;
}
buf.append(len_expected, 4);
expect(Token.RPAREN);
parseStruct();
int len_present = buf.length - (length0 + 4);
if (len_expected == -1) {
buf.writeAt(length0, len_present, 4);
} else if (len_expected != len_present) {
env.error(pos0, "warn.attr.wronglength", new Integer(len_expected), new Integer(len_present));
}
} // end parseAttr
/**
* Parse a Component of JavaCard .cap file.
*/
protected void parseComp() throws IOException {
scanner.scan();
expect(Token.LPAREN);
int tag = scanner.intValue; // index int const. pool
expect(Token.INTVAL);
buf.append(tag, 1);
int pos0 = scanner.pos, length0 = buf.length;
int len_expected;
if (scanner.token == Token.COMMA) {
scanner.scan();
len_expected = scanner.intValue;
expect(Token.INTVAL);
} else {
len_expected = -1;
}
buf.append(len_expected, 2);
expect(Token.RPAREN);
parseStruct();
int len_present = buf.length - (length0 + 2);
if (len_expected == -1) {
buf.writeAt(length0, len_present, 2);
} else if (len_expected != len_present) {
env.error(pos0, "warn.attr.wronglength", new Integer(len_expected), new Integer(len_present));
}
} // end parseComp
private void adjustDepth(boolean up) {
if (up) {
depth += 1;
context.update();
scanner.setDebugCP(context.isConstantPool());
} else {
depth -= 1;
context.exit();
}
StringBuilder bldr = new StringBuilder();
int tabAmt = 4;
int len = depth * tabAmt;
for (int i = 0; i < len; i++) {
bldr.append(" ");
}
tabStr = bldr.toString();
}
/**
* Parse a structure.
*/
protected int parseStruct() throws IOException {
adjustDepth(true);
env.traceln(" ");
env.traceln(tabStr + "Struct { <" + context + "> ");
expect(Token.LBRACE);
int num = 0;
int addElem = 0;
while (true) {
try {
switch (scanner.token) {
case COMMA: // ignored
scanner.scan();
break;
case SEMICOLON:
num++;
addElem = 0;
scanner.scan();
break;
case CLASS:
scanner.addConstDebug(ConstType.CONSTANT_CLASS);
env.trace("class ");
scanner.longValue = ConstType.CONSTANT_CLASS.value();
scanner.intSize = 1;
case INTVAL:
env.trace("int [" + scanner.longValue + "] ");
buf.append(scanner.longValue, scanner.intSize);
scanner.scan();
addElem = 1;
break;
case STRINGVAL:
scanner.scan();
scanner.addConstDebug(ConstType.CONSTANT_UTF8);
env.trace("UTF8 [\"" + scanner.stringValue + "\"] ");
bufstream.writeUTF(scanner.stringValue);
addElem = 1;
break;
case LONGSTRINGVAL:
scanner.scan();
env.traceln("LongString [\"" + scanner.longStringValue.data + "\"] ");
buf.write(scanner.longStringValue.data, 0, scanner.longStringValue.length);
addElem = 1;
break;
case LBRACE:
parseStruct();
addElem = 1;
break;
case LSQBRACKET:
parseArray();
addElem = 1;
break;
case BYTES:
env.trace("bytes ");
parseByteArray();
addElem = 1;
break;
case ATTR:
env.trace("attr ");
parseAttr();
addElem = 1;
break;
case COMP:
env.trace("comp ");
parseComp();
addElem = 1;
break;
case RBRACE:
scanner.scan();
env.traceln(" ");
env.traceln(tabStr + "} // Struct <" + context + "> [");
adjustDepth(false);
return num + addElem;
default:
env.traceln("unexp token=" + scanner.token);
env.traceln(" scanner.stringval = \"" + scanner.stringValue + "\"");
env.error(scanner.pos, "element.expected");
throw new SyntaxError();
}
} catch (SyntaxError e) {
recoverField();
}
}
} // end parseStruct
/**
* Recover after a syntax error in the file. This involves discarding tokens until an
* EOF or a possible legal continuation is encountered.
*/
protected void recoverFile() throws IOException {
while (true) {
switch (scanner.token) {
case CLASS:
case INTERFACE:
// Start of a new source file statement, continue
return;
case LBRACE:
scanner.match(Token.LBRACE, Token.RBRACE);
scanner.scan();
break;
case LPAREN:
scanner.match(Token.LPAREN, Token.RPAREN);
scanner.scan();
break;
case LSQBRACKET:
scanner.match(Token.LSQBRACKET, Token.RSQBRACKET);
scanner.scan();
break;
case EOF:
return;
default:
// Don't know what to do, skip
scanner.scan();
break;
}
}
}
/**
* Parse a class or interface declaration.
*/
protected void parseClass() throws IOException {
// Begin a new class
Token prev = scanner.token;
scanner.scan();
buf = new ByteBuffer();
bufstream = new DataOutputStream(buf);
String doc = scanner.docComment;
// Parse the class name
int p = scanner.pos;
switch (scanner.token) {
case STRINGVAL:
buf.myname = scanner.stringValue;
break;
case BYTEINDEX:
case SHORTINDEX:
case ATTR:
case BYTES:
case MACRO:
case COMP:
case FILE:
case IDENT:
if (prev == Token.FILE) {
buf.myname = scanner.stringValue;
} else {
buf.myname = scanner.stringValue + ".class";
}
break;
default:
env.error(scanner.prevPos, "name.expected");
throw new SyntaxError();
}
scanner.scan();
env.traceln("starting class " + buf.myname);
// Parse the clause
switch (scanner.token) {
case LBRACE:
parseStruct(); // ??
break;
case LSQBRACKET:
parseArray();
break;
case BYTES:
parseByteArray();
break;
case ATTR:
parseAttr();
break;
case COMP:
parseComp();
break;
default:
env.error(scanner.pos, "struct.expected");
}
env.traceln("ending class " + buf.myname);
// End the class
env.flushErrors();
Classes.add(buf);
} // end parseClass
/**
* Parse an Jcoder file.
*/
public ArrayList<ByteBuffer> parseFile() {
env.traceln("PARSER");
context.init();
try {
while (scanner.token != Token.EOF) {
try {
switch (scanner.token) {
case CLASS:
case INTERFACE:
case FILE:
// Start of a class
// scan();
parseClass();
break;
case SEMICOLON:
// Bogus semi colon
scanner.scan();
break;
case EOF:
// The end
return Classes;
default:
env.traceln("unexpected token=" + scanner.token.toString());
env.error(scanner.pos, "toplevel.expected");
throw new SyntaxError();
}
} catch (SyntaxError e) {
env.traceln("SyntaxError " + e.getMessage());
e.printStackTrace();
recoverFile();
}
}
} catch (IOException e) {
env.error(scanner.pos, "io.exception", env.getSource());
return Classes;
}
return Classes;
} //end parseFile
/*---------------------------------------------*/
static char fileSeparator; //=System.getProperty("file.separator");
/**
* write to the directory passed with -d option
*/
public void write(ByteBuffer cls, File destdir) throws IOException {
String myname = cls.myname;
if (myname == null) {
env.error("cannot.write", null);
return;
}
env.traceln("writing class " + myname);
File outfile;
if (destdir == null) {
int startofname = myname.lastIndexOf('/');
if (startofname != -1) {
myname = myname.substring(startofname + 1);
}
outfile = new File(myname);
} else {
env.traceln("writing -d " + destdir.getPath());
if (fileSeparator == 0) {
fileSeparator = System.getProperty("file.separator").charAt(0);
}
if (fileSeparator != '/') {
myname = myname.replace('/', fileSeparator);
}
outfile = new File(destdir, myname);
File outdir = new File(outfile.getParent());
if (!outdir.exists() && !outdir.mkdirs()) {
env.error("cannot.write", outdir.getPath());
return;
}
}
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outfile));
out.write(cls.data, 0, cls.length);
try {
out.close();
} catch (IOException e) {
}
}
/**
* Writes the classes
*/
public void write(File destdir) throws IOException {
for (ByteBuffer cls : Classes) {
write(cls, destdir);
}
} // end write()
} // end Jcoder

View File

@ -0,0 +1,213 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jcoder;
import org.openjdk.asmtools.util.I18NResourceBundle;
import org.openjdk.asmtools.util.ProductInfo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
/**
*
*
*/
public class Main {
/*-------------------------------------------------------- */
/* Main Fields */
/**
* Name of the program.
*/
String program;
/**
* The stream where error message are printed.
*/
PrintStream out;
int nerrors = 0;
public static final I18NResourceBundle i18n
= I18NResourceBundle.getBundleForClass(Main.class);
/*-------------------------------------------------------- */
/**
* Constructor.
*/
public Main(PrintStream out, String program) {
this.out = out;
this.program = program;
}
/*-------------------------------------------------------- */
/**
* Top level error message
*/
public void error(String msg) {
nerrors++;
out.println(program + ": " + msg);
}
/**
* Usage
*/
public void usage() {
out.println(i18n.getString("jcoder.usage"));
out.println(i18n.getString("jcoder.opt.nowrite"));
out.println(i18n.getString("jcoder.opt.d"));
out.println(i18n.getString("jcoder.opt.version"));
// out.println(" -D<macroDef>=<string> macro declaration");
}
/**
* Run the compiler
*/
public synchronized boolean compile(String argv[]) {
File destDir = null;
boolean traceFlag = false;
boolean debugInfoFlag = false;
long tm = System.currentTimeMillis();
ArrayList<String> v = new ArrayList<>();
boolean nowrite = false;
String props = null;
int nwarnings = 0;
HashMap<String, String> macros = new HashMap<>();
macros.put("VERSION", "3;45");
// Parse arguments
for (int i = 0; i < argv.length; i++) {
String arg = argv[i];
if (!arg.startsWith("-")) {
v.add(arg);
} else if (arg.startsWith("-D")) {
int argLength = arg.length();
if (argLength == 2) {
error(i18n.getString("jcoder.error.D_needs_marco"));
return false;
}
int index = arg.indexOf('=');
if (index == -1) {
error(i18n.getString("jcoder.error.D_needs_marco"));
return false;
}
String macroId = arg.substring(2, index);
index++;
if (argLength == index) {
error(i18n.getString("jcoder.error.D_needs_marco"));
return false;
}
String macro;
if (arg.charAt(index) == '"') {
index++;
if (argLength == index || arg.charAt(argLength - 1) != '"') {
error(i18n.getString("jcoder.error.no_closing_quota"));
return false;
}
macro = arg.substring(index, argLength - 1);
} else {
macro = arg.substring(index, argLength);
}
macros.put(macroId, macro);
} else if (arg.equals("-v")) {
traceFlag = true;
} else if (arg.equals("-nowrite")) {
nowrite = true;
} else if (arg.equals("-d")) {
if ((i + 1) == argv.length) {
error(i18n.getString("jcoder.error.d_requires_argument"));
usage();
return false;
}
destDir = new File(argv[++i]);
if (!destDir.exists()) {
error(i18n.getString("jcoder.error.does_not_exist", destDir));
return false;
}
} else if (arg.equals("-version")) {
out.println(ProductInfo.FULL_VERSION);
} else {
error(i18n.getString("jcoder.error.invalid_option", arg));
usage();
return false;
}
}
if (v.isEmpty()) {
usage();
return false;
}
// compile all input files
try {
for (String inpname : v) {
SourceFile env;
Jcoder p;
try {
env = new SourceFile(new File(inpname), out);
env.traceFlag = traceFlag;
env.debugInfoFlag = debugInfoFlag;
p = new Jcoder(env, macros);
p.parseFile();
env.traceln("END PARSER");
env.closeInp();
} catch (FileNotFoundException ex) {
error(i18n.getString("jcoder.error.cannot_read", inpname));
continue;
}
nerrors += env.nerrors;
nwarnings += env.nwarnings;
if (nowrite || (nerrors > 0)) {
continue;
}
try {
env.traceln("WRITE");
p.write(destDir);
} catch (FileNotFoundException ex) {
error(i18n.getString("jcoder.error.cannot_write", ex.getMessage()));
}
}
} catch (Error ee) {
ee.printStackTrace();
error(i18n.getString("jcoder.error.fatal_error"));
} catch (Exception ee) {
ee.printStackTrace();
error(i18n.getString("jcoder.error.fatal_exception"));
}
boolean errs = nerrors > 0;
boolean warns = nwarnings > 0;
if (!errs && !warns) {
return true;
}
out.println(errs ? (nerrors > 1 ? (nerrors + " errors") : "1 error") : "" + ((errs && warns) ? ", " : "") + (warns ? (nwarnings > 1 ? (nwarnings + " warnings") : "1 warning") : ""));
return !errs;
}
/**
* main program
*/
public static void main(String argv[]) {
Main compiler = new Main(System.out, "jcoder");
System.exit(compiler.compile(argv) ? 0 : 1);
}
}

View File

@ -0,0 +1,898 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jcoder;
import static org.openjdk.asmtools.jcoder.JcodTokens.*;
import java.io.IOException;
import java.util.HashMap;
/**
* A Scanner for Jcoder tokens. Errors are reported to the environment object.<p>
*
* The scanner keeps track of the current token, the value of the current token (if any),
* and the start position of the current token.<p>
*
* The scan() method advances the scanner to the next token in the input.<p>
*
* The match() method is used to quickly match opening brackets (ie: '(', '{', or '[')
* with their closing counter part. This is useful during error recovery.<p>
*
* The compiler treats either "\n", "\r" or "\r\n" as the end of a line.<p>
*/
public class Scanner {
/*-------------------------------------------------------- */
/* Scanner Fields */
/**
* End of input
*/
public static final int EOF = -1;
private boolean debugCP = false;
private int numCPentrs = 0;
/**
* Where errors are reported
*/
protected SourceFile env;
/**
* Input stream
*/
protected SourceFile in;
HashMap<String, String> macros;
/**
* The current character
*/
protected int ch, prevCh = -1;
protected String macro;
protected int indexMacro;
/**
* Current token
*/
protected Token token;
/**
* The position of the current token
*/
protected int pos;
/**
* The position of the previous token
*/
protected int prevPos;
/* Token values. */
protected long longValue;
protected int intValue;
protected int intSize;
protected String stringValue;
protected ByteBuffer longStringValue;
protected int sign; // sign, when reading number
/* A doc comment preceding the most recent token */
protected String docComment;
/**
* A growable character buffer.
*/
private int count;
private char buffer[] = new char[32];
/*-------------------------------------------------------- */
/**
* Create a scanner to scan an input stream.
*/
protected Scanner(SourceFile sf, HashMap<String, String> macros)
throws IOException {
this.env = sf;
this.in = sf;
this.macros = macros;
ch = sf.read();
prevPos = sf.pos;
scan();
}
/**
* for use in jcfront.
*/
protected Scanner(SourceFile sf)
throws IOException {
this.env = sf;
this.in = sf;
this.macros = new HashMap<>();
ch = sf.read();
prevPos = sf.pos;
scan();
}
/* *********************************************** */
void setDebugCP(boolean enable) {
if (enable) {
numCPentrs = 0;
}
debugCP = enable;
}
void addConstDebug(ConstType ct) {
numCPentrs += 1;
env.traceln("\n Const[" + numCPentrs + "] = " + ct.printval());
}
void setMacro(String macro) {
this.macro = macro;
indexMacro = 0;
prevCh = ch;
}
void readCh() throws IOException {
if (macro != null) {
if (indexMacro < macro.length()) {
ch = macro.charAt(indexMacro);
}
macro = null;
}
if (prevCh >= 0) {
ch = prevCh;
prevCh = -1;
} else {
ch = in.read();
}
}
private void putc(int ch) {
if (count == buffer.length) {
char newBuffer[] = new char[buffer.length * 2];
System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
buffer = newBuffer;
}
buffer[count++] = (char) ch;
}
private String bufferString() {
char buf[] = new char[count];
System.arraycopy(buffer, 0, buf, 0, count);
return new String(buf);
}
/**
* Scan a comment. This method should be called once the initial /, * and the next
* character have been read.
*/
private void skipComment() throws IOException {
while (true) {
switch (ch) {
case EOF:
env.error(pos, "eof.in.comment");
return;
case '*':
readCh();
if (ch == '/') {
readCh();
return;
}
break;
default:
readCh();
break;
}
}
}
/**
* Scan a doc comment. This method should be called once the initial /, * and * have
* been read. It gathers the content of the comment (witout leading spaces and '*'s)
* in the string buffer.
*/
private String scanDocComment() throws IOException {
count = 0;
if (ch == '*') {
do {
readCh();
} while (ch == '*');
if (ch == '/') {
readCh();
return "";
}
}
switch (ch) {
case '\n':
case ' ':
readCh();
break;
}
boolean seenstar = false;
int c = count;
while (true) {
switch (ch) {
case EOF:
env.error(pos, "eof.in.comment");
return bufferString();
case '\n':
putc('\n');
readCh();
seenstar = false;
c = count;
break;
case ' ':
case '\t':
putc(ch);
readCh();
break;
case '*':
if (seenstar) {
readCh();
if (ch == '/') {
readCh();
count = c;
return bufferString();
}
putc('*');
} else {
seenstar = true;
count = c;
do {
readCh();
} while (ch == '*');
switch (ch) {
case ' ':
readCh();
break;
case '/':
readCh();
count = c;
return bufferString();
}
}
break;
default:
if (!seenstar) {
seenstar = true;
}
putc(ch);
readCh();
c = count;
break;
}
}
}
/**
* Scan a decimal number
*/
private void scanDecNumber() throws IOException {
boolean overflow = false;
long value = ch - '0';
count = 0;
token = Token.INTVAL;
intSize = 2; // default
putc(ch); // save character in buffer
numberLoop:
for (;;) {
readCh();
switch (ch) {
case '8':
case '9':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
putc(ch);
overflow = overflow || (value * 10) / 10 != value;
value = (value * 10) + (ch - '0');
overflow = overflow || (value - 1 < -1);
break;
case 'b':
readCh();
intSize = 1;
break numberLoop;
case 's':
readCh();
intSize = 2;
break numberLoop;
case 'i':
readCh();
intSize = 4;
break numberLoop;
case 'l':
readCh();
intSize = 8;
break numberLoop;
default:
break numberLoop;
}
}
longValue = value;
intValue = (int) value;
// we have just finished reading the number. The next thing better
// not be a letter or digit.
if (Character.isJavaIdentifierPart((char) ch) || ch == '.') {
env.error(in.pos, "invalid.number", (new Character((char) ch)).toString());
do {
readCh();
} while (Character.isJavaIdentifierPart((char) ch) || ch == '.');
return;
}
if (overflow) {
env.error(pos, "overflow");
}
} // scanNumber()
/**
* Scan a hex number.
*/
private void scanHexNumber() throws IOException {
boolean overflow = false;
long value = 0;
int cypher;
count = 0;
token = Token.INTVAL;
intSize = 2; // default
putc(ch); // save character in buffer
numberLoop:
for (int k = 0;; k++) {
readCh();
switch (ch) {
case '8':
case '9':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
cypher = (char) ch - '0';
break;
case 'd':
case 'D':
case 'e':
case 'E':
case 'f':
case 'F':
case 'a':
case 'A':
case 'b':
case 'B':
case 'c':
case 'C':
cypher = 10 + Character.toLowerCase((char) ch) - 'a';
break;
default:
break numberLoop;
}
putc(ch);
overflow = overflow || ((value >>> 60) != 0);
value = (value << 4) + cypher;
intSize = (k + 1) / 2;
}
longValue = value;
intValue = (int) value;
// we have just finished reading the number. The next thing better
// not be a letter or digit.
if (Character.isJavaIdentifierPart((char) ch) || ch == '.') {
env.error(in.pos, "invalid.number", (new Character((char) ch)).toString());
do {
readCh();
} while (Character.isJavaIdentifierPart((char) ch) || ch == '.');
intValue = 0;
// } else if ( overflow || (intValue - 1 < -1) ) {
} else if (overflow) {
intValue = 0; // so we don't get second overflow in Parser
env.error(pos, "overflow");
}
} // scanNumber()
/**
* Scan an escape character.
*
* @return the character or -1 if it escaped an end-of-line.
*/
private int scanEscapeChar() throws IOException {
int p = in.pos;
readCh();
switch (ch) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7': {
int n = ch - '0';
for (int i = 2; i > 0; i--) {
readCh();
switch (ch) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
n = (n << 3) + ch - '0';
break;
default:
if (n > 0xFF) {
env.error(p, "invalid.escape.char");
}
return n;
}
}
readCh();
if (n > 0xFF) {
env.error(p, "invalid.escape.char");
}
return n;
}
case 'r':
readCh();
return '\r';
case 'n':
readCh();
return '\n';
case 'f':
readCh();
return '\f';
case 'b':
readCh();
return '\b';
case 't':
readCh();
return '\t';
case '\\':
readCh();
return '\\';
case '\"':
readCh();
return '\"';
case '\'':
readCh();
return '\'';
}
env.error(p, "invalid.escape.char");
readCh();
return -1;
}
/**
* Scan a string. The current character should be the opening " of the string.
*/
private void scanString() throws IOException {
token = Token.STRINGVAL;
count = 0;
readCh();
loop:
for (;;) {
switch (ch) {
case EOF:
env.error(pos, "eof.in.string");
break loop;
case '\n':
readCh();
env.error(pos, "newline.in.string");
break loop;
case '"':
readCh();
break loop;
case '\\': {
int c = scanEscapeChar();
if (c >= 0) {
putc((char) c);
}
break;
}
default:
putc(ch);
readCh();
break;
}
}
stringValue = bufferString();
}
/**
* Scan a character array. The current character should be the opening ' of the array.
*/
private void scanCharArray() throws IOException {
token = Token.LONGSTRINGVAL;
ByteBuffer buf = new ByteBuffer();
count = 0;
readCh();
loop:
for (;;) {
int c = ch;
switch (ch) {
case EOF:
env.error(pos, "eof.in.string");
break loop;
case '\n':
readCh();
env.error(pos, "newline.in.string");
break loop;
case '\'':
readCh();
break loop;
case '\\':
c = scanEscapeChar();
if (c < 0) {
break;
}
// no break - continue
default:
// see description of java.io.DataOutput.writeUTF()
if ((c > 0) && (c <= 0x7F)) {
buf.write(c);
} else if ((c == 0) || ((c >= 0x80) && (c <= 0x7FF))) {
buf.write(0xC0 | (0x1F & (c >> 6)));
buf.write(0x80 | (0x3f & c));
} else {
buf.write(0xc0 | (0x0f & (c >> 12)));
buf.write(0x80 | (0x3f & (c >> 6)));
buf.write(0x80 | (0x3f & c));
}
readCh();
}
}
longStringValue = buf;
}
/**
* Scan an Identifier. The current character should be the first character of the
* identifier.
*/
private void scanIdentifier() throws IOException {
count = 0;
boolean compound = false;
for (;;) {
putc(ch);
readCh();
//env.traceln(" read:"+(char)ch);
if ((ch == '/') || (ch == '.') || (ch == '-')) {
//env.traceln(" =>compound");
compound = true;
continue;
} else if (!Character.isJavaIdentifierPart((char) ch)) {
break;
}
}
//env.traceln(" end:"+(char)ch);
stringValue = bufferString();
if (compound) {
token = Token.IDENT;
} else {
token = keyword_token_ident(stringValue);
if (token == Token.IDENT) {
intValue = constValue(stringValue);
if (intValue != -1) {
// this is a constant
if (debugCP) {
ConstType ct = constType(stringValue);
if (ct != null) {
addConstDebug(ct);
}
}
token = Token.INTVAL;
intSize = 1;
longValue = intValue;
} else {
//env.traceln(" ^^^^^^^^ Massive Weirdness here: Can't locate IDENT '" + stringValue + "'. ^^^^^^^^^^");
}
}
}
} // end scanIdentifier
protected int xscan() throws IOException {
int retPos = pos;
prevPos = in.pos;
docComment = null;
sign = 1;
for (;;) {
pos = in.pos;
switch (ch) {
case EOF:
token = Token.EOF;
return retPos;
case '\n':
case ' ':
case '\t':
case '\f':
readCh();
break;
case '/':
readCh();
switch (ch) {
case '/':
// Parse a // comment
do {
readCh();
} while ((ch != EOF) && (ch != '\n'));
break;
case '*':
readCh();
if (ch == '*') {
docComment = scanDocComment();
} else {
skipComment();
}
break;
default:
token = Token.DIV;
return retPos;
}
break;
case '"':
scanString();
return retPos;
case '\'':
scanCharArray();
return retPos;
case '-':
sign = -sign; // hack: no check that numbers only are allowed after
case '+':
readCh();
break;
case '0':
readCh();
token = Token.INTVAL;
longValue = intValue = 0;
switch (ch) {
case 'x':
case 'X':
scanHexNumber();
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
scanDecNumber();
break;
case 'b':
readCh();
intSize = 1;
break;
case 's':
readCh();
intSize = 2;
break;
case 'i':
readCh();
intSize = 4;
break;
case 'l':
readCh();
intSize = 8;
break;
default:
intSize = 2;
}
return retPos;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
scanDecNumber();
return retPos;
case '{':
readCh();
token = Token.LBRACE;
return retPos;
case '}':
readCh();
token = Token.RBRACE;
return retPos;
case '(':
readCh();
token = Token.LPAREN;
return retPos;
case ')':
readCh();
token = Token.RPAREN;
return retPos;
case '[':
readCh();
token = Token.LSQBRACKET;
return retPos;
case ']':
readCh();
token = Token.RSQBRACKET;
return retPos;
case ',':
readCh();
token = Token.COMMA;
return retPos;
case ';':
readCh();
token = Token.SEMICOLON;
return retPos;
case ':':
readCh();
token = Token.COLON;
return retPos;
case '=':
readCh();
if (ch == '=') {
readCh();
token = Token.EQ;
return retPos;
}
token = Token.ASSIGN;
return retPos;
case '\u001a':
// Our one concession to DOS.
readCh();
if (ch == EOF) {
token = Token.EOF;
return retPos;
}
env.error(pos, "funny.char");
readCh();
break;
case '#':
readCh();
scanDecNumber();
return retPos;
case '&': {
readCh();
retPos = pos;
if (!Character.isJavaIdentifierStart((char) ch)) {
env.error(pos, "identifier.expected");
}
scanIdentifier();
String macroId = stringValue;
String macro = (String) macros.get(macroId);
if (macro == null) {
env.error(pos, "macro.undecl", macroId);
throw new SyntaxError();
}
setMacro(macro);
readCh();
}
break;
default:
if (Character.isJavaIdentifierStart((char) ch)) {
scanIdentifier();
return retPos;
}
env.error(pos, "funny.char");
readCh();
break;
}
}
}
/**
* Scan to a matching '}', ']' or ')'. The current token must be a '{', '[' or '(';
*/
protected void match(Token open, Token close) throws IOException {
int depth = 1;
while (true) {
scan();
if (token == open) {
depth++;
} else if (token == close) {
if (--depth == 0) {
return;
}
} else if (token == Token.EOF) {
env.error(pos, "unbalanced.paren");
return;
}
}
}
/**
* Scan the next token.
*
* @return the position of the previous token.
*/
protected int scan() throws IOException {
int retPos = xscan();
//env.traceln("scanned:"+token+" ("+keywordName(token)+")");
return retPos;
}
/**
* Scan the next token.
*
* @return the position of the previous token.
*/
protected int scanMacro() throws IOException {
int retPos = xscan();
//env.traceln("scanned:"+token+" ("+keywordName(token)+")");
return retPos;
}
}

View File

@ -0,0 +1,443 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jcoder;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Hashtable;
import org.openjdk.asmtools.util.I18NResourceBundle;
/**
* An input stream for java programs. The stream treats either "\n", "\r" or "\r\n" as the
* end of a line, it always returns \n. It also parses UNICODE characters expressed as
* \uffff. However, if it sees "\\", the second slash cannot begin a unicode sequence. It
* keeps track of the current position in the input stream.
*
* An position consists of: ((linenr &lt;&lt; OFFSETBITS) | offset) this means that both
* the line number and the exact offset into the file are encoded in each postion
* value.<p>
*/
public class SourceFile implements org.openjdk.asmtools.jasm.Constants {
public boolean traceFlag = false;
public boolean debugInfoFlag = false;
/**
* The increment for each character.
*/
protected static final int OFFSETINC = 1;
/**
* The increment for each line.
*/
protected static final int LINEINC = 1 << OFFSETBITS;
File source;
InputStream in;
PrintStream out;
int pos;
private int chpos;
private int pushBack = -1;
public SourceFile(File source, PrintStream out) throws IOException {
this.source = source;
this.in = new BufferedInputStream(new FileInputStream(source));
chpos = LINEINC;
this.out = out;
errorFileName = source.getPath();
}
public String getSource() {
return source.getPath();
}
public void closeInp() {
try {
in.close();
} catch (IOException e) {
}
flushErrors();
}
public int read() throws IOException {
pos = chpos;
chpos += OFFSETINC;
int c = pushBack;
if (c == -1) {
c = in.read();
} else {
pushBack = -1;
}
// parse special characters
switch (c) {
case -2:
// -2 is a special code indicating a pushback of a backslash that
// definitely isn't the start of a unicode sequence.
return '\\';
case '\\':
if ((c = in.read()) != 'u') {
pushBack = (c == '\\' ? -2 : c);
return '\\';
}
// we have a unicode sequence
chpos += OFFSETINC;
while ((c = in.read()) == 'u') {
chpos += OFFSETINC;
}
// unicode escape sequence
int d = 0;
for (int i = 0; i < 4; i++, chpos += OFFSETINC, c = in.read()) {
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
d = (d << 4) + c - '0';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
d = (d << 4) + 10 + c - 'a';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
d = (d << 4) + 10 + c - 'A';
break;
default:
error(pos, "invalid.escape.char");
pushBack = c;
return d;
}
}
pushBack = c;
return d;
case '\n':
chpos += LINEINC;
return '\n';
case '\r':
if ((c = in.read()) != '\n') {
pushBack = c;
} else {
chpos += OFFSETINC;
}
chpos += LINEINC;
return '\n';
default:
return c;
}
}
public int lineNumber(int pos) {
return pos >>> OFFSETBITS;
}
public int lineNumber() {
return pos >>> OFFSETBITS;
}
/*============================================================== Environment */
/**
* The number of errors and warnings
*/
public int nerrors;
public int nwarnings;
public static final I18NResourceBundle i18n
= I18NResourceBundle.getBundleForClass(Main.class);
/*
* Until place for jasm.properties is defind,
* I have to keep them right here
*
static Hashtable properties = new Hashtable(40);
static {
// Scanner:
properties.put("err.eof.in.comment", "Comment not terminated at end of input.");
properties.put("err.invalid.number", "Invalid character \'%s\' in number.");
properties.put("err.invalid.octal.number", "Invalid character in octal number.");
properties.put("err.overflow", "Numeric overflow.");
properties.put("err.float.format", "Invalid floating point format.");
properties.put("err.eof.in.string", "String not terminated at end of input.");
properties.put("err.newline.in.string", "String not terminated at end of line.");
properties.put("err.funny.char", "Invalid character in input.");
properties.put("err.unbalanced.paren", "Unbalanced parentheses.");
// Parser:
properties.put("err.toplevel.expected", "Class or interface declaration expected.");
properties.put("err.token.expected", "'%s' expected.");
properties.put("err.identifier.expected", "Identifier expected.");
properties.put("err.name.expected", "Name expected.");
properties.put("err.io.exception", "I/O error in %s.");
properties.put("err.cannot.write", "Cannot write to %s.");
properties.put("warn.array.wronglength", "expected array length %s do not match real length %s; expected length written");
properties.put("warn.attr.wronglength", "expected attribute length %s do not match real length %s; expected length written");
properties.put("attrname.notfound", "Cannot find \"%s\" in constant pool");
properties.put("err.attrname.expected", "Attribute's name or index expected.");
properties.put("err.element.expected", "Primary data item expected.");
properties.put("err.struct.expected", "Structured data item expected.");
properties.put("err.macro.undecl", "Macro %s undefined.");
}
static String getProperty(String nm) {
return (String) properties.get(nm);
}
*/
/**
* Error String
*/
String errorString(String err, Object arg1, Object arg2, Object arg3) {
String str = null;
if (!err.startsWith("warn.")) {
err = "err." + err;
}
//str = getProperty(err);
str = i18n.getString(err);
if (str == null) {
return "error message '" + err + "' not found";
}
StringBuffer buf = new StringBuffer();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if ((c == '%') && (i + 1 < str.length())) {
switch (str.charAt(++i)) {
case 's':
String arg = arg1.toString();
for (int j = 0; j < arg.length(); j++) {
switch (c = arg.charAt(j)) {
case ' ':
case '\t':
case '\n':
case '\r':
buf.append((char) c);
break;
default:
if ((c > ' ') && (c <= 255)) {
buf.append((char) c);
} else {
buf.append('\\');
buf.append('u');
buf.append(Integer.toString(c, 16));
}
}
}
arg1 = arg2;
arg2 = arg3;
break;
case '%':
buf.append('%');
break;
default:
buf.append('?');
break;
}
} else {
buf.append((char) c);
}
}
return buf.toString();
}
/**
* The filename where the last errors have occurred
*/
String errorFileName;
/**
* List of outstanding error messages
*/
ErrorMessage errors;
/**
* Insert an error message in the list of outstanding error messages. The list is
* sorted on input position.
*/
void insertError(int where, String message) {
//output("ERR = " + message);
ErrorMessage msg = new ErrorMessage(where, message);
if (errors == null) {
errors = msg;
} else if (errors.where > where) {
msg.next = errors;
errors = msg;
} else {
ErrorMessage m = errors;
for (; (m.next != null) && (m.next.where <= where); m = m.next) {
;
}
msg.next = m.next;
m.next = msg;
}
}
/**
* Flush outstanding errors
*/
public void flushErrors() {
if (errors == null) {
return;
}
try {
// Read the file
FileInputStream in = new FileInputStream(errorFileName);
byte data[] = new byte[in.available()];
in.read(data);
in.close();
// Report the errors
for (ErrorMessage msg = errors; msg != null; msg = msg.next) {
int ln = msg.where >>> OFFSETBITS;
int off = msg.where & ((1 << OFFSETBITS) - 1);
int i, j;
for (i = off; (i > 0) && (data[i - 1] != '\n') && (data[i - 1] != '\r'); i--) {
;
}
for (j = off; (j < data.length) && (data[j] != '\n') && (data[j] != '\r'); j++) {
;
}
String prefix = errorFileName + ":" + ln + ":";
outputln(prefix + " " + msg.message);
outputln(new String(data, i, j - i));
char strdata[] = new char[(off - i) + 1];
for (j = i; j < off; j++) {
strdata[j - i] = (data[j] == '\t') ? '\t' : ' ';
}
strdata[off - i] = '^';
outputln(new String(strdata));
}
} catch (IOException e) {
outputln("I/O exception");
}
errors = null;
}
/**
* Output a string. This can either be an error message or something for debugging.
* This should be used instead of print.
*/
public void output(String msg) {
// try {
int len = msg.length();
for (int i = 0; i < len; i++) {
out.write(msg.charAt(i));
}
// } catch (IOException e) {
// }
}
/**
* Output a string. This can either be an error message or something for debugging.
* This should be used instead of println.
*/
public void outputln(String msg) {
output(msg);
out.write('\n');
}
/**
* Issue an error.
* @param where Offset in the source for the error
* @param err Error number (as defined in this interface)
* @param arg1 Optional argument to the error (null if not applicable)
* @param arg2 Optional argument to the error (null if not applicable)
* @param arg3 Optional argument to the error (null if not applicable)
*/
/**
* Issue an error
*/
public void error(int where, String err, Object arg1, Object arg2, Object arg3) {
String msg = errorString(err, arg1, arg2, arg3);
if (err.startsWith("warn.")) {
nwarnings++;
} else {
nerrors++;
}
traceln("error:" + msg);
insertError(where, msg);
}
public final void error(int where, String err, Object arg1, Object arg2) {
error(where, err, arg1, arg2, null);
}
public final void error(int where, String err, Object arg1) {
error(where, err, arg1, null, null);
}
public final void error(int where, String err) {
error(where, err, null, null, null);
}
public final void error(String err) {
error(pos, err, null, null, null);
}
public final void error(String err, Object arg1) {
error(pos, err, arg1, null, null);
}
/*============================================================== trace */
public void trace(String message) {
if (traceFlag) {
output(message);
}
}
public void traceln(String message) {
if (traceFlag) {
outputln(message);
}
}
} // end SourceFile

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jcoder;
/**
* Syntax errors, should always be caught inside the parser for error recovery.
*/
class SyntaxError extends Error {
}

View File

@ -0,0 +1,65 @@
# Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
jcoder.usage=\
Usage: java -jar asmtools.jar jcoder [options] file.jcod...\n\
where possible options include:
jcoder.opt.nowrite=\
\ -nowrite do not write resulting .class files
jcoder.opt.d=\
\ -d destdir directory to place resulting .class files
jcoder.opt.version=\
\ -version prints the program version
jcoder.error.D_needs_marco=-D needs macro declaration
jcoder.error.no_closing_quota=no closing quota in macro definition
jcoder.error.d_requires_argument=-d requires argument
jcoder.error.does_not_exist={0} does not exist
jcoder.error.invalid_option=invalid option: {0}
jcoder.error.cannot_read=cannot read {0}
jcoder.error.cannot_write=cannot write {0}
jcoder.error.fatal_error=fatal error
jcoder.error.fatal_exception=fatal exception
err.eof.in.comment=Comment not terminated at end of input.
err.invalid.number=Invalid character '{0}' in number.
#err.invalid.octal.number=Invalid character in octal number.
err.overflow=Numeric overflow.
#err.float.format=Invalid floating point format.
err.eof.in.string=String not terminated at end of input.
err.newline.in.string=String not terminated at end of line.
err.funny.char=Invalid character in input.
err.unbalanced.paren=Unbalanced parentheses.
err.toplevel.expected=Class or interface declaration expected.
err.token.expected='{0}' expected.
err.identifier.expected=Identifier expected.
err.name.expected=Name expected.
err.io.exception=I/O error in {0}.
err.cannot.write=Cannot write to {0}.
warn.array.wronglength=expected array length {0} do not match real length {1}; expected length written
warn.attr.wronglength=expected attribute length {0} do not match real length {1}; expected length written
#attrname.notfound=Cannot find "{0}" in constant pool
err.attrname.expected=Attribute's name or index expected.
err.element.expected=Primary data item expected.
err.struct.expected=Structured data item expected.
err.macro.undecl=Macro {0} undefined.
err.invalid.escape.char=Invalid escape char

View File

@ -0,0 +1,969 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdec;
import org.openjdk.asmtools.util.I18NResourceBundle;
import static org.openjdk.asmtools.jasm.Tables.*;
import static org.openjdk.asmtools.jasm.TypeAnnotationUtils.*;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
/**
*
*
*/
class ClassData {
byte types[];
Object cpool[];
int CPlen;
NestedByteArrayInputStream countedin;
DataInputStream in;
PrintWriter out;
String inpname;
int[] cpe_pos;
boolean printDetails;
public static I18NResourceBundle i18n
= I18NResourceBundle.getBundleForClass(Main.class);
public ClassData(String inpname, int printFlags, PrintWriter out) throws IOException {
FileInputStream filein = new FileInputStream(inpname);
byte buf[] = new byte[filein.available()];
filein.read(buf);
countedin = new NestedByteArrayInputStream(buf);
in = new DataInputStream(countedin);
this.out = out;
this.inpname = inpname;
printDetails = ((printFlags & 1) == 1);
}
/*========================================================*/
public static final char hexTable[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
String toHex(long val, int width) {
StringBuilder s = new StringBuilder();
for (int i = width * 2 - 1; i >= 0; i--) {
s.append(hexTable[((int) (val >> (4 * i))) & 0xF]);
}
return "0x" + s.toString();
}
String toHex(long val) {
int width;
for (width = 8; width > 0; width--) {
if ((val >> (width - 1) * 8) != 0) {
break;
}
}
return toHex(val, width);
}
void printByteHex(PrintWriter out, int b) {
out.print(hexTable[(b >> 4) & 0xF]);
out.print(hexTable[b & 0xF]);
}
void printBytes(PrintWriter out, DataInputStream in, int len)
throws IOException {
try {
for (int i = 0; i < len; i++) {
if (i % 8 == 0) {
out_print("0x");
}
printByteHex(out, in.readByte());
if (i % 8 == 7) {
out.println(";");
}
}
} finally {
if (len % 8 != 0) {
out.println(";");
}
}
}
void printRestOfBytes() throws IOException {
for (int i = 0;; i++) {
try {
if (i % 8 == 0) {
out_print("0x");
}
printByteHex(out, in.readByte());
if (i % 8 == 7) {
out.print(";\n");
}
} catch (IOException e) {
out.println();
return;
}
}
}
/*========================================================*/
int shift = 0;
void out_begin(String s) {
for (int i = 0; i < shift; i++) {
out.print(" ");
}
out.println(s);
shift++;
}
void out_print(String s) {
for (int i = 0; i < shift; i++) {
out.print(" ");
}
out.print(s);
}
void out_println(String s) {
for (int i = 0; i < shift; i++) {
out.print(" ");
}
out.println(s);
}
void out_end(String s) {
shift--;
for (int i = 0; i < shift; i++) {
out.print(" ");
}
out.println(s);
}
String startArray(int length) {
return "[" + (printDetails ? Integer.toString(length) : "") + "]";
}
void startArrayCmt(int length, String comment) {
out_begin(startArray(length) + " { // " + comment);
}
void startArrayCmtB(int length, String comment) {
out_begin(startArray(length) + "b { // " + comment);
}
/*========================================================*/
void readCP(DataInputStream in) throws IOException {
int length = in.readUnsignedShort();
CPlen = length;
traceln(i18n.getString("jdec.trace.CP_len", length));
types = new byte[length];
cpool = new Object[length];
cpe_pos = new int[length];
for (int i = 1; i < length; i++) {
byte btag;
int v1, v2, n = i;
long lv;
cpe_pos[i] = countedin.getPos();
btag = in.readByte();
traceln(i18n.getString("jdec.trace.CP_entry", i, btag));
types[i] = btag;
ConstType tg = tag(btag);
switch (tg) {
case CONSTANT_UTF8:
cpool[i] = in.readUTF();
break;
case CONSTANT_INTEGER:
v1 = in.readInt();
cpool[i] = new Integer(v1);
break;
case CONSTANT_FLOAT:
v1 = Float.floatToIntBits(in.readFloat());
cpool[i] = new Integer(v1);
break;
case CONSTANT_LONG:
lv = in.readLong();
cpool[i] = new Long(lv);
i++;
break;
case CONSTANT_DOUBLE:
lv = Double.doubleToLongBits(in.readDouble());
cpool[i] = new Long(lv);
i++;
break;
case CONSTANT_CLASS:
case CONSTANT_STRING:
v1 = in.readUnsignedShort();
cpool[i] = new Integer(v1);
break;
case CONSTANT_INTERFACEMETHOD:
case CONSTANT_FIELD:
case CONSTANT_METHOD:
case CONSTANT_NAMEANDTYPE:
// case CONSTANT_INVOKEDYNAMIC_TRANS:
cpool[i] = "#" + in.readUnsignedShort() + " #" + in.readUnsignedShort();
break;
case CONSTANT_INVOKEDYNAMIC:
cpool[i] = in.readUnsignedShort() + "s #" + in.readUnsignedShort();
break;
case CONSTANT_METHODHANDLE:
cpool[i] = in.readUnsignedByte() + "b #" + in.readUnsignedShort();
break;
case CONSTANT_METHODTYPE:
cpool[i] = "#" + in.readUnsignedShort();
break;
default:
CPlen = i;
printCP(out);
out_println(toHex(btag, 1) + "; // invalid constant type: " + (int) btag + " for element " + i);
throw new ClassFormatError();
}
}
}
void printCP(PrintWriter out) throws IOException {
int length = CPlen;
startArrayCmt(length, "Constant Pool");
out_println("; // first element is empty");
int size;
for (int i = 1; i < length; i = i + size) {
size = 1;
byte btag = types[i];
ConstType tg = tag(btag);
int pos = cpe_pos[i];
String tagstr = "";
String valstr;
int v1, v2;
long lv;
if (tg != null) {
tagstr = tg.parseKey();
}
switch (tg) {
case CONSTANT_UTF8: {
tagstr = "Utf8";
StringBuilder sb = new StringBuilder();
String s = (String) cpool[i];
sb.append('\"');
for (int k = 0; k < s.length(); k++) {
char c = s.charAt(k);
switch (c) {
case '\t':
sb.append('\\').append('t');
break;
case '\n':
sb.append('\\').append('n');
break;
case '\r':
sb.append('\\').append('r');
break;
case '\"':
sb.append('\\').append('\"');
break;
default:
sb.append(c);
}
}
valstr = sb.append('\"').toString();
}
break;
case CONSTANT_FLOAT:
v1 = ((Integer) cpool[i]).intValue();
valstr = toHex(v1, 4);
break;
case CONSTANT_INTEGER:
v1 = ((Integer) cpool[i]).intValue();
valstr = toHex(v1, 4);
break;
case CONSTANT_DOUBLE:
lv = ((Long) cpool[i]).longValue();
valstr = toHex(lv, 8) + ";";
size = 2;
break;
case CONSTANT_LONG:
lv = ((Long) cpool[i]).longValue();
valstr = toHex(lv, 8) + ";";
size = 2;
break;
case CONSTANT_CLASS:
v1 = ((Integer) cpool[i]).intValue();
valstr = "#" + v1;
break;
case CONSTANT_STRING:
v1 = ((Integer) cpool[i]).intValue();
valstr = "#" + v1;
break;
case CONSTANT_INTERFACEMETHOD:
valstr = (String) cpool[i];
break;
case CONSTANT_FIELD:
valstr = (String) cpool[i];
break;
case CONSTANT_METHOD:
valstr = (String) cpool[i];
break;
case CONSTANT_NAMEANDTYPE:
valstr = (String) cpool[i];
break;
case CONSTANT_METHODHANDLE:
valstr = (String) cpool[i];
break;
case CONSTANT_METHODTYPE:
valstr = (String) cpool[i];
break;
// case CONSTANT_INVOKEDYNAMIC_TRANS:
// tagstr = "InvokeDynamicTrans";
// valstr = (String) cpool[i];
// break;
case CONSTANT_INVOKEDYNAMIC:
valstr = (String) cpool[i];
break;
default:
throw new Error("invalid constant type: " + (int) btag);
}
out_print(tagstr + " " + valstr + "; // #" + i);
if (printDetails) {
out_println(" at " + toHex(pos));
} else {
out_println("");
}
}
out_end("} // Constant Pool");
out.println();
}
String getStringPos() {
return " at " + toHex(countedin.getPos());
}
String getStringPosCond() {
if (printDetails) {
return getStringPos();
} else {
return "";
}
}
String getCommentPosCond() {
if (printDetails) {
return " // " + getStringPos();
} else {
return "";
}
}
void decodeCPXAttr(DataInputStream in, int len, String attrname, PrintWriter out) throws IOException {
decodeCPXAttrM(in, len, attrname, out, 1);
}
void decodeCPXAttrM(DataInputStream in, int len, String attrname, PrintWriter out, int expectedIndices) throws IOException {
if (len != expectedIndices * 2) {
out_println("// invalid length of " + attrname + " attr: " + len + " (should be " + (expectedIndices * 2) + ") > ");
printBytes(out, in, len);
} else {
String outputString = "";
String space = "";
for (int k = 0; k < expectedIndices; k++) {
outputString += (space + "#" + in.readUnsignedShort());
space = " ";
}
out_println(outputString + ";");
}
}
void printStackMap(DataInputStream in, int elementsNum) throws IOException {
int num;
if (elementsNum > 0) {
num = elementsNum;
} else {
num = in.readUnsignedShort();
}
out.print(startArray(num) + (elementsNum > 0 ? "z" : "") + "{");
for (int k = 0; k < num; k++) {
int maptype = in.readUnsignedByte();
StackMapType mptyp = stackMapType(maptype);
String maptypeImg;
if (printDetails) {
maptypeImg = Integer.toString(maptype) + "b";
} else {
try {
maptypeImg = mptyp.parsekey();
// maptypeImg = ITEM_Names[maptype];
} catch (ArrayIndexOutOfBoundsException e) {
maptypeImg = "/* BAD TYPE: */ " + maptype + "b";
}
}
switch (mptyp) {
case ITEM_Object:
case ITEM_NewObject:
maptypeImg = maptypeImg + "," + in.readUnsignedShort();
break;
default:
}
out.print(maptypeImg);
if (k < num - 1) {
out.print("; ");
}
}
out.print("}");
}
/**
* Processes JSR-308 <code>extended_annotation</code> structure.
*/
void decodeTargetTypeAndRefInfo(DataInputStream in, int len, PrintWriter out, boolean isWildcard) throws IOException {
int tt = in.readUnsignedShort();
TargetType target_type = targetTypeEnum(tt);
InfoType info_type = target_type.infoType();
out_println(toHex(tt, 2) + "; // target_type: " + target_type.parseKey());
switch (info_type) {
case TYPEPARAM: //[3.3.1] meth_type_param, class_type_param:
out_println(toHex(in.readUnsignedByte(), 1) + "; // param_index");
break;
case SUPERTYPE: //[3.3.2] class_exts_impls
out_println(toHex(in.readUnsignedShort(), 2) + "; // type_index");
break;
case TYPEPARAM_BOUND: //[3.3.3] class_type_param_bnds, meth_type_param_bnds
out_println(toHex(in.readUnsignedByte(), 1) + "; // param_index");
out_println(toHex(in.readUnsignedByte(), 1) + "; // bound_index");
break;
case EMPTY: //[3.3.4] meth_reciever, meth_ret_type, field
// NOTE: reference_info is empty for this annotation's target
break;
case METHODPARAM: //[3.3.5] meth_formal_param:
out_println(toHex(in.readUnsignedByte(), 1) + "; // parameter_index");
break;
case EXCEPTION: //[3.3.61] throws_type
//KTL: Updated index to UShort for JSR308 change
out_println(in.readUnsignedShort() + "; // type_index");
break;
case LOCALVAR: //[3.3.7] local_var, resource_var
{
int lv_num = in.readUnsignedShort();
startArrayCmt(lv_num, "local_variables");
for (int i = 0; i < lv_num; i++) {
out_println(in.readUnsignedShort() + " " + in.readUnsignedShort()
+ " " + in.readUnsignedShort() + ";" + getCommentPosCond());
}
out_end("}");
}
break;
case CATCH: //[3.3.8] exception_param
out_println(in.readUnsignedShort() + "; // exception_table_index");
break;
case OFFSET: //[3.3.9] type_test (instanceof), obj_creat (new)
// constr_ref_receiver, meth_ref_receiver
out_println(in.readUnsignedShort() + "; // offset");
break;
case TYPEARG: //[3.3.10] cast, constr_ref_typearg, meth_invoc_typearg
// constr_invoc_typearg, meth_ref_typearg
out_println(in.readUnsignedShort() + "; // offset");
out_println(toHex(in.readUnsignedByte(), 1) + "; // type_index");
break;
default: // should never happen
out_println(toHex(tt, 1) + "; // invalid target_info: " + tt);
throw new ClassFormatError();
}
int path_len = in.readUnsignedShort();
startArrayCmt(path_len, "type_paths");
for (int i = 0; i < path_len; i++) {
// print the type Path elements
out_println("{ " + toHex(in.readUnsignedByte(), 1)
+ "; " + toHex(in.readUnsignedByte(), 1)
+ "; } // type_path[" + i + "]"); // type path kind
}
out_end("}");
}
void decodeElementValue(DataInputStream in, int len, PrintWriter out) throws IOException {
out_begin("{ // element_value");
char tg = (char) in.readByte();
AnnotElemType tag = annotElemType(tg);
out_println("'" + tg + "';");
switch (tag) {
case AE_BYTE:
case AE_CHAR:
case AE_DOUBLE:
case AE_FLOAT:
case AE_INT:
case AE_LONG:
case AE_SHORT:
case AE_BOOLEAN:
case AE_STRING:
decodeCPXAttr(in, 2, "const_value_index", out);
break;
case AE_ENUM:
out_begin("{ // enum_const_value");
decodeCPXAttr(in, 2, "type_name_index", out);
decodeCPXAttr(in, 2, "const_name_index", out);
out_end("} // enum_const_value");
break;
case AE_CLASS:
decodeCPXAttr(in, 2, "class_info_index", out);
break;
case AE_ANNOTATION:
decodeAnnotation(in, out);
break;
case AE_ARRAY:
int ev_num = in.readUnsignedShort();
startArrayCmt(ev_num, "array_value");
for (int i = 0; i < ev_num; i++) {
decodeElementValue(in, 0, out);
if (i < ev_num - 1) {
out_println(";");
}
}
out_end("} // array_value");
break;
default:
out_println(toHex(tg, 1) + "; // invalid element_value tag type: " + tg);
throw new ClassFormatError();
}
out_end("} // element_value");
}
void decodeAnnotation(DataInputStream in, PrintWriter out) throws IOException {
out_begin("{ // annotation");
decodeCPXAttr(in, 2, "field descriptor", out);
int evp_num = in.readUnsignedShort();
startArrayCmt(evp_num, "element_value_pairs");
for (int i = 0; i < evp_num; i++) {
out_begin("{ // element value pair");
decodeCPXAttr(in, 2, "name of the annotation type element", out);
decodeElementValue(in, 0, out);
out_end("} // element value pair");
if (i < evp_num - 1) {
out_println(";");
}
}
out_end("} // element_value_pairs");
out_end("} // annotation");
}
void decodeExtendedAnnotation(DataInputStream in, PrintWriter out) throws IOException {
out_begin("{ // annotation");
decodeCPXAttr(in, 2, "field descriptor", out);
int evp_num = in.readUnsignedShort();
startArrayCmt(evp_num, "element_value_pairs");
for (int i = 0; i < evp_num; i++) {
out_begin("{ // element value pair");
decodeCPXAttr(in, 2, "name of the annotation type element", out);
decodeElementValue(in, 0, out);
out_end("} // element value pair");
if (i < evp_num - 1) {
out_println(";");
}
}
out_end("} // element_value_pairs");
decodeTargetTypeAndRefInfo(in, 0, out, false);
out_end("} // annotation");
}
void decodeBootstrapMethod(DataInputStream in, PrintWriter out) throws IOException {
out_begin("{ // bootstrap_method");
out_println("#" + in.readUnsignedShort() + "; // bootstrap_method_ref");
int bm_args_cnt = in.readUnsignedShort();
startArrayCmt(bm_args_cnt, "bootstrap_arguments");
for (int i = 0; i < bm_args_cnt; i++) {
out_println("#" + in.readUnsignedShort() + ";" + getCommentPosCond());
}
out_end("} // bootstrap_arguments");
out_end("} // bootstrap_method");
}
void decodeAttr(DataInputStream in0, PrintWriter out) throws IOException {
// Read one attribute
String posComment = getStringPos();
int name_cpx = in0.readUnsignedShort(), btag, len;
String AttrName = "";
try {
btag = types[name_cpx];
ConstType tag = tag(btag);
if (tag == ConstType.CONSTANT_UTF8) {
AttrName = (String) cpool[name_cpx];
}
} catch (ArrayIndexOutOfBoundsException e) {
}
AttrTag tg = attrtag(AttrName);
String endingComment = AttrName;
len = in0.readInt();
countedin.enter(len);
try {
if (printDetails) {
out_begin("Attr(#" + name_cpx + ", " + len + ") { // " + AttrName + posComment);
} else {
out_begin("Attr(#" + name_cpx + ") { // " + AttrName);
}
switch (tg) {
case ATT_Code:
out_println(in.readUnsignedShort() + "; // max_stack");
out_println(in.readUnsignedShort() + "; // max_locals");
int code_len = in.readInt();
out_begin("Bytes" + startArray(code_len) + "{");
printBytes(out, in, code_len);
out_end("};");
int trap_num = in.readUnsignedShort();
startArrayCmt(trap_num, "Traps");
for (int i = 0; i < trap_num; i++) {
out_println(in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + ";" + getCommentPosCond());
}
out_end("} // end Traps");
// Read the attributes
decodeAttrs(in, out);
break;
case ATT_ConstantValue:
decodeCPXAttr(in, len, AttrName, out);
break;
case ATT_Exceptions:
int exc_num = in.readUnsignedShort();
startArrayCmt(exc_num, AttrName);
for (int i = 0; i < exc_num; i++) {
out_println("#" + in.readUnsignedShort() + ";" + getCommentPosCond());
}
out_end("}");
break;
case ATT_LineNumberTable:
int ll_num = in.readUnsignedShort();
startArrayCmt(ll_num, AttrName);
for (int i = 0; i < ll_num; i++) {
out_println(in.readUnsignedShort() + " " + in.readUnsignedShort() + ";" + getCommentPosCond());
}
out_end("}");
break;
case ATT_LocalVariableTable:
int lv_num = in.readUnsignedShort();
startArrayCmt(lv_num, AttrName);
for (int i = 0; i < lv_num; i++) {
out_println(in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + ";" + getCommentPosCond());
}
out_end("}");
break;
case ATT_LocalVariableTypeTable:
int lvt_num = in.readUnsignedShort();
startArrayCmt(lvt_num, AttrName);
for (int i = 0; i < lvt_num; i++) {
out_println(in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + ";" + getCommentPosCond());
}
out_end("}");
break;
case ATT_InnerClasses:
int ic_num = in.readUnsignedShort();
startArrayCmt(ic_num, AttrName);
for (int i = 0; i < ic_num; i++) {
out_println("#" + in.readUnsignedShort() + " #" + in.readUnsignedShort() + " #" + in.readUnsignedShort() + " " + in.readUnsignedShort() + ";" + getCommentPosCond());
}
out_end("}");
break;
case ATT_Signature:
decodeCPXAttr(in, len, AttrName, out);
break;
case ATT_StackMap:
int e_num = in.readUnsignedShort();
startArrayCmt(e_num, "");
for (int k = 0; k < e_num; k++) {
int start_pc = in.readUnsignedShort();
out_print("" + start_pc + ", ");
printStackMap(in, 0);
out.print(", ");
printStackMap(in, 0);
out.println(";");
}
out_end("}");
break;
case ATT_StackMapTable:
int et_num = in.readUnsignedShort();
startArrayCmt(et_num, "");
for (int k = 0; k < et_num; k++) {
int frame_type = in.readUnsignedByte();
StackMapFrameType ftype = stackMapFrameType(frame_type);
switch (ftype) {
case SAME_FRAME:
// type is same_frame;
out_print("" + frame_type + "b");
out.println("; // same_frame");
break;
case SAME_LOCALS_1_STACK_ITEM_FRAME:
// type is same_locals_1_stack_item_frame
int offset = frame_type - 64;
out_print("" + frame_type + "b, ");
// read additional single stack element
printStackMap(in, 1);
out.println("; // same_locals_1_stack_item_frame");
break;
case SAME_LOCALS_1_STACK_ITEM_EXTENDED_FRAME:
// type is same_locals_1_stack_item_frame_extended
int noffset = in.readUnsignedShort();
out_print("" + frame_type + "b, " + noffset + ", ");
// read additional single stack element
printStackMap(in, 1);
out.println("; // same_locals_1_stack_item_frame_extended");
break;
case CHOP_1_FRAME:
case CHOP_2_FRAME:
case CHOP_3_FRAME:
// type is chop_frame
int coffset = in.readUnsignedShort();
out_print("" + frame_type + "b, " + coffset);
out.println("; // chop_frame " + (251 - frame_type));
break;
case SAME_FRAME_EX:
// type is same_frame_extended;
int xoffset = in.readUnsignedShort();
out_print("" + frame_type + "b, " + xoffset);
out.println("; // same_frame_extended");
break;
case APPEND_FRAME:
// type is append_frame
int aoffset = in.readUnsignedShort();
out_print("" + frame_type + "b, " + aoffset + ", ");
// read additional locals
printStackMap(in, frame_type - 251);
out.println("; // append_frame " + (frame_type - 251));
break;
case FULL_FRAME:
// type is full_frame
int foffset = in.readUnsignedShort();
out_print("" + frame_type + "b, " + foffset + ", ");
printStackMap(in, 0);
out.print(", ");
printStackMap(in, 0);
out.println("; // full_frame");
break;
}
}
out_end("}");
break;
case ATT_EnclosingMethod:
decodeCPXAttrM(in, len, AttrName, out, 2);
break;
case ATT_SourceFile:
decodeCPXAttr(in, len, AttrName, out);
break;
case ATT_AnnotationDefault:
decodeElementValue(in, len, out);
break;
case ATT_RuntimeInvisibleAnnotations:
case ATT_RuntimeVisibleAnnotations:
int an_num = in.readUnsignedShort();
startArrayCmt(an_num, "annotations");
for (int i = 0; i < an_num; i++) {
decodeAnnotation(in, out);
if (i < an_num - 1) {
out_println(";");
}
}
out_end("}");
break;
case ATT_RuntimeInvisibleTypeAnnotations:
case ATT_RuntimeVisibleTypeAnnotations:
int ant_num = in.readUnsignedShort();
startArrayCmt(ant_num, "annotations");
for (int i = 0; i < ant_num; i++) {
decodeExtendedAnnotation(in, out);
if (i < ant_num - 1) {
out_println(";");
}
}
out_end("}");
break;
case ATT_RuntimeInvisibleParameterAnnotations:
case ATT_RuntimeVisibleParameterAnnotations:
int pm_num = in.readUnsignedByte();
startArrayCmtB(pm_num, "parameters");
for (int k = 0; k < pm_num; k++) {
int anp_num = in.readUnsignedShort();
startArrayCmt(anp_num, "annotations");
for (int i = 0; i < anp_num; i++) {
decodeAnnotation(in, out);
if (k < anp_num - 1) {
out_println(";");
}
}
out_end("}");
if (k < pm_num - 1) {
out_println(";");
}
}
out_end("}");
break;
case ATT_BootstrapMethods:
int bm_num = in.readUnsignedShort();
startArrayCmt(bm_num, "bootstrap_methods");
for (int i = 0; i < bm_num; i++) {
decodeBootstrapMethod(in, out);
if (i < bm_num - 1) {
out_println(";");
}
}
out_end("}");
break;
default:
if (AttrName == null) {
printBytes(out, in, len);
endingComment = "Attr(#" + name_cpx + ")";
} else {
// some kind of error?
printBytes(out, in, len);
}
}
} catch (EOFException e) {
out.println("// ======== unexpected end of attribute array");
}
int rest = countedin.available();
if (rest > 0) {
out.println("// ======== attribute array started " + posComment + " has " + rest + " bytes more:");
printBytes(out, in, rest);
}
out_end("} // end " + endingComment);
countedin.leave();
}
void decodeAttrs(DataInputStream in, PrintWriter out) throws IOException {
// Read the attributes
int attr_num = in.readUnsignedShort();
startArrayCmt(attr_num, "Attributes");
for (int i = 0; i < attr_num; i++) {
decodeAttr(in, out);
if (i + 1 < attr_num) {
out_println(";");
}
}
out_end("} // Attributes");
}
void decodeMembers(DataInputStream in, PrintWriter out, String comment) throws IOException {
int nfields = in.readUnsignedShort();
traceln(comment + "=" + nfields);
startArrayCmt(nfields, "" + comment);
try {
for (int i = 0; i < nfields; i++) {
out_begin("{ // Member" + getStringPosCond());
int access = in.readShort();
out_println(toHex(access, 2) + "; // access");
int name_cpx = in.readUnsignedShort();
out_println("#" + name_cpx + "; // name_cpx");
int sig_cpx = in.readUnsignedShort();
out_println("#" + sig_cpx + "; // sig_cpx");
// Read the attributes
decodeAttrs(in, out);
out_end("} // Member");
if (i + 1 < nfields) {
out_println(";");
}
}
} finally {
out_end("} // " + comment);
out.println();
}
}
public void decodeClass() throws IOException {
String classname = "N/A";
// Read the header
try {
int magic = in.readInt();
int min_version = in.readUnsignedShort();
int version = in.readUnsignedShort();
// Read the constant pool
readCP(in);
short access = in.readShort(); // dont care about sign
int this_cpx = in.readUnsignedShort();
try {
classname = (String) cpool[((Integer) cpool[this_cpx]).intValue()];
out_begin("class " + classname + " {");
} catch (Exception e) {
classname = inpname;
out.println("// " + e.getMessage() + " while accessing classname");
out_begin("class " + classname + " { // source file name");
}
out_print(toHex(magic, 4) + ";");
if (magic != JAVA_MAGIC) {
out.print(" // wrong magic: 0x" + Integer.toString(JAVA_MAGIC, 16) + " expected");
}
out.println();
out_println(min_version + "; // minor version");
out_println(version + "; // version");
// Print the constant pool
printCP(out);
out_println(toHex(access, 2) + "; // access");
out_println("#" + this_cpx + ";// this_cpx");
int super_cpx = in.readUnsignedShort();
out_println("#" + super_cpx + ";// super_cpx");
traceln(i18n.getString("jdec.trace.access_thisCpx_superCpx", access, this_cpx, super_cpx));
out.println();
// Read the interface names
int numinterfaces = in.readUnsignedShort();
traceln(i18n.getString("jdec.trace.numinterfaces", numinterfaces));
startArrayCmt(numinterfaces, "Interfaces");
for (int i = 0; i < numinterfaces; i++) {
int intrf_cpx = in.readUnsignedShort();
traceln(i18n.getString("jdec.trace.intrf", i, intrf_cpx));
out_println("#" + intrf_cpx + ";");
}
out_end("} // Interfaces\n");
// Read the fields
decodeMembers(in, out, "fields");
// Read the methods
decodeMembers(in, out, "methods");
// Read the attributes
decodeAttrs(in, out);
} catch (EOFException e) {
} catch (ClassFormatError err) {
out.println("//------- ClassFormatError:" + err.getMessage());
printRestOfBytes();
} finally {
out_end("} // end class " + classname);
}
} // end decodeClass()
/* ====================================================== */
public boolean DebugFlag = false;
public void trace(String s) {
if (!DebugFlag) {
return;
}
System.out.print(s);
}
public void traceln(String s) {
if (!DebugFlag) {
return;
}
System.out.println(s);
}
}// end class ClassData

View File

@ -0,0 +1,148 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdec;
import org.openjdk.asmtools.jdis.uEscWriter;
import org.openjdk.asmtools.util.I18NResourceBundle;
import org.openjdk.asmtools.util.ProductInfo;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
* Main program of the Java DeCoder
*/
public class Main {
/*-------------------------------------------------------- */
/* Main Fields */
/**
* Name of the program.
*/
String program;
/**
* The stream where error message are printed.
*/
PrintWriter out;
boolean DebugFlag = false;
int printFlags = 0;
public static final I18NResourceBundle i18n
= I18NResourceBundle.getBundleForClass(Main.class);
/*-------------------------------------------------------- */
/**
* Constructor.
*/
public Main(PrintWriter out, String program) {
this.out = out;
this.program = program;
}
/*-------------------------------------------------------- */
public void error(String msg) {
out.println(program + ": " + msg);
}
/**
* Usage
*/
public void usage() {
out.println(i18n.getString("jdec.usage"));
out.println(i18n.getString("jdec.opt.g"));
out.println(i18n.getString("jdec.opt.version"));
}
/**
* Run the decoder
*/
public synchronized boolean decode(String argv[]) {
// int flags = F_WARNINGS;
long tm = System.currentTimeMillis();
ArrayList<String> vargs = new ArrayList<>();
ArrayList<String> vj = new ArrayList<>();
boolean nowrite = false;
int addOptions = 0;
// Parse arguments
int i = 0;
for (String arg : argv) {
if (arg.equals("-g")) {
printFlags = printFlags | 1;
vargs.add(arg);
//out.println("arg["+i+"]="+argv[i]+"/printFlags");
} else if (arg.equals("-v")) {
DebugFlag = true;
vargs.add(arg);
out.println("arg[" + i + "]=" + argv[i] + "/verbose");
} else if (arg.equals("-version")) {
out.println(ProductInfo.FULL_VERSION);
} else if (arg.startsWith("-")) {
//out.println("arg["+i+"]="+argv[i]+"/invalid flag");
error(i18n.getString("jdec.error.invalid_flag", arg));
usage();
return false;
} else {
vargs.add(arg);
vj.add(arg);
}
i += 1;
}
if (vj.isEmpty()) {
usage();
return false;
}
String[] names = new String[0];
names = vj.toArray(names);
decode:
for (String inpname : names) {
try {
ClassData cc = new ClassData(inpname, printFlags, out);
cc.DebugFlag = DebugFlag;
cc.decodeClass();
continue decode;
} catch (FileNotFoundException ee) {
error(i18n.getString("jdec.error.cannot_read", inpname));
} catch (Error ee) {
ee.printStackTrace();
error(i18n.getString("jdec.error.fatal_error"));
} catch (Exception ee) {
ee.printStackTrace();
error(i18n.getString("jdec.error.fatal_exception"));
}
return false;
}
return true;
}
/**
* Main program
*/
public static void main(String argv[]) {
Main decoder = new Main(new PrintWriter(new uEscWriter(System.out)), "jdec");
System.exit(decoder.decode(argv) ? 0 : 1);
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdec;
import java.io.ByteArrayInputStream;
import java.util.Stack;
/**
* this class provides functionality needed to read class files:
* <ul>
* <li>methods to read unsigned integers of various length
* <li>counts bytes read so far
* </ul>
*/
public class NestedByteArrayInputStream extends ByteArrayInputStream {
NestedByteArrayInputStream(byte buf[]) {
super(buf);
}
NestedByteArrayInputStream(byte buf[], int offset, int length) {
super(buf, offset, length);
}
/*---- */
public int getPos() {
return pos;
}
Stack savedStates = new Stack();
public void enter(int range) {
savedStates.push(new Integer(count));
if (pos + range < count) {
count = pos + range;
}
}
public void leave() {
pos = count;
count = ((Integer) savedStates.pop()).intValue();
}
} // end class NestedByteArrayInputStream

View File

@ -0,0 +1,41 @@
# Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
jdec.error.invalid_flag=invalid flag: " {0}
jdec.error.fatal_error=fatal error
jdec.error.fatal_exception=fatal exception
jdec.error.cannot_read=cannot read {0}
jdec.usage=\
Usage: java -jar asmtools.jar jdec [options] FILE.class... > FILE.jcod\n\
where possible options include:
jdec.opt.g=\
\ -g: detailed output format
jdec.opt.version=\
\ -version: print version number and date
jdec.trace.CP_len=CP len= {0}
jdec.trace.CP_entry=CP entry # {0} tag= {1}
jdec.trace.access_thisCpx_superCpx=access={0} this_cpx={1} super_cpx={2}
jdec.trace.numinterfaces=numinterfaces={0}
jdec.trace.intrf=\
\ intrf_cpx[{0}]={1}

View File

@ -0,0 +1,397 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import static org.openjdk.asmtools.jasm.Tables.*;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
*
* AnnotElem
*
* Base class of all AnnotationElement entries
*
*/
public class AnnotElem {
/**
*
* CPX_AnnotElem
*
* base class for an annotation value.
*
*/
public static class AnnotValue {
/*-------------------------------------------------------- */
/* AnnotElem Fields */
/**
* tag the descriptor for the constant
*/
public AnnotElemType tag;
// internal references
protected ClassData cls;
/*-------------------------------------------------------- */
public AnnotValue(AnnotElemType tagval, ClassData cls) {
tag = tagval;
this.cls = cls;
}
public String stringVal() {
return "";
}
public void print(PrintWriter out, String tab) {
out.print(tag.val() + "\t");
}
@Override
public String toString() {
return "<AnnotValue " + tag.printval() + " " + stringVal() + ">";
}
}
/**
*
* CPX_AnnotElem
*
* Annotation value which is described by a single CPX entry (ie. String, byte, char,
* int, short, boolean, float, long, double, class reference).
*
*/
public static class CPX_AnnotValue extends AnnotValue {
/**
* tag the descriptor for the constant
*/
public int cpx;
public CPX_AnnotValue(AnnotElemType tag, ClassData cls, int cpx) {
super(tag, cls);
this.cpx = cpx;
}
@Override
public String stringVal() {
StringBuilder sb = new StringBuilder();
switch (tag) {
case AE_STRING: // String
sb.append('"' + cls.pool.getString(cpx) + '"');
break;
case AE_BYTE: // Byte
sb.append("byte " + cls.pool.getConst(cpx).stringVal());
break;
case AE_CHAR: // Char
sb.append("char " + cls.pool.getConst(cpx).stringVal());
break;
case AE_INT: // Int (no need to add keyword)
sb.append(cls.pool.getConst(cpx).stringVal());
break;
case AE_SHORT: // Short
sb.append("short " + cls.pool.getConst(cpx).stringVal());
break;
case AE_BOOLEAN: // Boolean
ConstantPool.CP_Int cns = (ConstantPool.CP_Int) cls.pool.getConst(cpx);
sb.append("boolean " + (cns.value == 0 ? "false" : "true"));
break;
case AE_FLOAT: // Float
sb.append(cls.pool.getConst(cpx).stringVal()); // + "f");
break;
case AE_DOUBLE: // Double
sb.append(cls.pool.getConst(cpx).stringVal()); // + "d");
break;
case AE_LONG: // Long
sb.append(cls.pool.getConst(cpx).stringVal()); // + "l");
break;
case AE_CLASS: // Class
sb.append("class " + cls.pool.decodeClassDescriptor(cpx));
break;
default:
break;
}
return sb.toString();
}
@Override
public void print(PrintWriter out, String tab) {
out.print(tab + stringVal());
}
@Override
public String toString() {
return "<CPX_AnnotValue tag: '" + tag + "' stringVal=" + this.stringVal() + ">";
}
}
/**
*
* CPX_AnnotElem
*
* AnnotElements that contain 2 cpx indices (ie. enums).
*
*/
public static class CPX2_AnnotValue extends AnnotValue {
/**
* tag the descriptor for the constant
*/
public int cpx1;
public int cpx2;
public CPX2_AnnotValue(AnnotElemType tag, ClassData cls, int cpx1, int cpx2) {
super(tag, cls);
this.cpx1 = cpx1;
this.cpx2 = cpx2;
}
@Override
public String stringVal() {
StringBuilder sb = new StringBuilder();
switch (tag) {
case AE_ENUM: // Enum
// print the enum type and constant name
sb.append("enum " + cls.pool.decodeClassDescriptor(cpx1)
+ " " + cls.pool.getName(cpx2));
break;
default:
break;
}
return sb.toString();
}
@Override
public void print(PrintWriter out, String tab) {
out.print(tab + stringVal());
}
@Override
public String toString() {
return "<CPX2_AnnotValue tag: '" + tag + "' stringVal=" + this.stringVal() + ">";
}
}
/**
*
* Array_AnnotElem
*
* Annotation value that is an array of annotation elements.
*
*/
public static class Array_AnnotValue extends AnnotValue {
/**
* tag the descriptor for the constant
*/
public ArrayList<AnnotValue> array = new ArrayList<>();
public Array_AnnotValue(AnnotElemType tagval, ClassData cls) {
super(tagval, cls);
}
@Override
public String stringVal() {
StringBuilder sb = new StringBuilder();
sb.append(super.stringVal() + " = ");
sb.append("{");
int i = 0;
int cnt = array.size();
for (AnnotValue arrayelem : array) {
sb.append(arrayelem.toString());
if (i < cnt - 1) {
sb.append(",");
}
}
sb.append("}");
return sb.toString();
}
public void add(AnnotValue elem) {
array.add(elem);
}
@Override
public void print(PrintWriter out, String tab) {
out.println("{");
int i = 0;
int cnt = array.size();
for (AnnotValue arrayelem : array) {
arrayelem.print(out, tab + " ");
if (i < cnt - 1) {
out.println(",");
}
i += 1;
}
out.println("}");
}
@Override
public String toString() {
return "<Array_AnnotValue " + tag + " " + stringVal() + ">";
}
}
/**
*
* Annot_AnnotValue
*
* Annotation value that is a reference to an annotation.
*
*/
public static class Annot_AnnotValue extends AnnotValue {
/**
* tag the descriptor for the constant
*/
AnnotationData annot;
public Annot_AnnotValue(AnnotElemType tagval, ClassData cls, AnnotationData annot) {
super(tagval, cls);
this.annot = annot;
}
@Override
public String stringVal() {
return annot.toString();
}
@Override
public void print(PrintWriter out, String tab) {
// out.print(tag + "\t");
annot.print(out, tab);
}
@Override
public String toString() {
return "<Annot_AnnotValue " + tag + " " + stringVal() + ">";
}
}
/*========================================================*/
/* Factory Method */
/**
*
* read
*
* Static factory - creates Annotation Elements.
*
*/
public static AnnotValue readValue(DataInputStream in, ClassData cls, boolean invisible) throws IOException {
AnnotValue val = null;
char tg = (char) in.readByte();
AnnotElemType tag = annotElemType(tg);
switch (tag) {
case AE_STRING: // String
case AE_BYTE: // Byte
case AE_CHAR: // Char
case AE_INT: // Int (no need to add keyword)
case AE_SHORT: // Short
case AE_BOOLEAN: // Boolean
case AE_FLOAT: // Float
case AE_DOUBLE: // Double
case AE_LONG: // Long
case AE_CLASS: // Class
// CPX based Annotation
int CPX = in.readShort();
val = new CPX_AnnotValue(tag, cls, CPX);
break;
case AE_ENUM: // Enum
// CPX2 based Annotation
int CPX1 = in.readShort();
int CPX2 = in.readShort();
val = new CPX2_AnnotValue(tag, cls, CPX1, CPX2);
break;
case AE_ANNOTATION: // Annotation
AnnotationData ad = new AnnotationData(invisible, cls);
ad.read(in);
val = new Annot_AnnotValue(tag, cls, ad);
break;
case AE_ARRAY: // Array
Array_AnnotValue aelem = new Array_AnnotValue(tag, cls);
val = aelem;
int cnt = in.readShort();
for (int i = 0; i < cnt; i++) {
aelem.add(readValue(in, cls, invisible));
}
break;
default:
throw new IOException("Unknown tag in annotation '" + tg + "' [" + Integer.toHexString(tg) + "]");
}
return val;
}
/*========================================================*/
/*-------------------------------------------------------- */
/* AnnotElem Fields */
/**
* constant pool index for the name of the Annotation Element
*/
public int name_cpx;
public AnnotValue value = null;
// internal references
protected ClassData cls;
/*-------------------------------------------------------- */
public AnnotElem(ClassData cls) {
this.cls = cls;
}
/**
*
* read
*
* read and resolve the method data called from ClassData. precondition: NumFields has
* already been read from the stream.
*
*/
public void read(DataInputStream in, boolean invisible) throws IOException {
name_cpx = in.readShort();
TraceUtils.traceln(" AnnotElem: name[" + name_cpx + "]=" + cls.pool.getString(name_cpx));
value = readValue(in, cls, invisible);
TraceUtils.traceln(" " + value.toString());
}
public String stringVal() {
return cls.pool.getName(name_cpx);
}
public void print(PrintWriter out, String tab) {
out.print(stringVal() + " = ");
value.print(out, tab);
}
@Override
public String toString() {
return "<AnnotElem " + stringVal() + " = " + value.toString() + ">";
}
}

View File

@ -0,0 +1,147 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
*
*/
public class AnnotationData {
/*-------------------------------------------------------- */
/* AnnotData Fields */
private boolean invisible = false;
private int type_cpx = 0; //an index into the constant pool indicating the annotation type for this annotation.
private ArrayList<AnnotElem> array = new ArrayList<>();
private ClassData cls;
protected String visAnnotToken = "@+";
protected String invAnnotToken = "@-";
protected String dataName = "AnnotationData";
/*-------------------------------------------------------- */
public AnnotationData(boolean invisible, ClassData cls) {
this.cls = cls;
this.invisible = invisible;
}
public void read(DataInputStream in) throws IOException {
type_cpx = in.readShort();
TraceUtils.traceln(" " + dataName + ": name[" + type_cpx + "]=" + cls.pool.getString(type_cpx));
int elemValueLength = in.readShort();
TraceUtils.traceln(" " + dataName + ": " + cls.pool.getString(type_cpx) + "num_elems: " + elemValueLength);
for (int evc = 0; evc < elemValueLength; evc++) {
AnnotElem elem = new AnnotElem(cls);
TraceUtils.traceln(" " + dataName + ": " + cls.pool.getString(type_cpx) + " reading [" + evc + "]");
elem.read(in, invisible);
array.add(elem);
}
}
public void print(PrintWriter out, String tab) {
printHeader(out, tab);
printBody(out, tab);
}
protected void printHeader(PrintWriter out, String tab) {
//Print annotation Header, which consists of the
// Annotation Token ('@'), visibility ('+', '-'),
// and the annotation name (type index, CPX).
// Mark whether it is invisible or not.
if (invisible) {
out.print(tab + invAnnotToken);
} else {
out.print(tab + visAnnotToken);
}
String annoName = cls.pool.getString(type_cpx);
// converts class type to java class name
if (annoName.startsWith("L") && annoName.endsWith(";")) {
annoName = annoName.substring(1, annoName.length() - 1);
}
out.print(annoName);
}
protected void printBody(PrintWriter out, String tab) {
// For a standard annotation, print out brackets,
// and list the name/value pairs.
out.print(" { ");
int i = 0;
for (AnnotElem elem : array) {
elem.print(out, tab);
if (i++ < array.size() - 1) {
out.print(", ");
}
}
out.print("}");
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
String annoName = cls.pool.getString(type_cpx);
// converts class type to java class name
if (annoName.startsWith("L") && annoName.endsWith(";")) {
annoName = annoName.substring(1, annoName.length() - 1);
}
//Print annotation
// Mark whether it is invisible or not.
if (invisible) {
sb.append(invAnnotToken);
} else {
sb.append(visAnnotToken);
}
sb.append(annoName);
sb.append(" { ");
int i = 0;
for (AnnotElem elem : array) {
sb.append(elem.toString());
if (i++ < array.size() - 1) {
sb.append(", ");
}
}
_toString(sb);
sb.append("}");
return sb.toString();
}
protected void _toString(StringBuilder sb) {
// sub-classes override this
}
} // end AnnotData

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.jasm.Tables;
import java.io.DataInputStream;
import java.io.IOException;
/**
*
*/
public class AttrData {
/**
*
* attributeTag
*
* returns either -1 (not found), or the hashed integer tag key.
*
*/
public static int attributeTag(String tagname) {
int intgr = Tables.attrtagValue(tagname);
if (intgr == 0) {
return -1;
}
return intgr;
}
/*-------------------------------------------------------- */
/* AttrData Fields */
int name_cpx;
byte data[];
ClassData cls;
/*-------------------------------------------------------- */
public AttrData(ClassData cls) {
this.cls = cls;
}
public void read(int name_cpx, int attrlen, DataInputStream in) throws IOException {
this.name_cpx = name_cpx;
data = new byte[attrlen];
TraceUtils.traceln(" AttrData:#" + name_cpx + " len=" + attrlen);
in.readFully(data);
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
*
*/
public class BootstrapMethodData {
/*-------------------------------------------------------- */
/* BootstrapMethodData Fields */
int bsm_index;
ArrayList<Integer> bsm_args_indexes;
// internal references
private Options options = Options.OptionObject();
private ClassData cls;
private PrintWriter out;
/*-------------------------------------------------------- */
public BootstrapMethodData(ClassData cls) {
this.cls = cls;
out = cls.out;
}
/*========================================================*/
/* Read Methods */
/**
*
* read
*
* read and resolve the bootstrap method data called from ClassData. precondition:
* NumFields has already been read from the stream.
*
*/
public void read(DataInputStream in) throws IOException {
// read the Methods CP indexes
bsm_index = in.readUnsignedShort();
int arg_num = in.readUnsignedShort();
bsm_args_indexes = new ArrayList<>(arg_num);
for (int i = 0; i < arg_num; i++) {
bsm_args_indexes.add(in.readUnsignedShort());
}
}
/*========================================================*/
/* Print Methods */
public void print() throws IOException {
out.print("BootstrapMethod ");
out.print("#" + bsm_index);
for (int i = 0; i < bsm_args_indexes.size(); i++) {
// cls.PrintConstant(bsm_args_indexes.elementAt(i));
out.print(" #" + bsm_args_indexes.get(i));
}
out.println(";");
}
}

View File

@ -0,0 +1,509 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.asmutils.HexUtils;
import org.openjdk.asmtools.jasm.Modifiers;
import static org.openjdk.asmtools.jasm.RuntimeConstants.*;
import static org.openjdk.asmtools.jasm.Tables.*;
import java.io.*;
import java.util.ArrayList;
/**
* Central class data for of the Java Disassembler
*/
public class ClassData extends MemberData {
/*-------------------------------------------------------- */
/* ClassData Fields */
// -----------------------------
// Header Info
// -----------------------------
/**
* Version info
*/
protected int minor_version,
major_version;
/**
* Constant Pool index to this class
*/
protected int this_cpx;
/**
* Constant Pool index to this classes parent (super)
*/
protected int super_cpx;
/**
* Constant Pool index to a file reference to the Java source
*/
protected int source_cpx = 0;
/**
* The Constant Pool
*/
protected ConstantPool pool;
/**
* The interfaces this class implements
*/
protected int[] interfaces;
/**
* The fields of this class
*/
protected ArrayList<FieldData> fields;
/**
* The methods of this class
*/
protected ArrayList<MethodData> methods;
/**
* The inner-classes of this class
*/
protected ArrayList<InnerClassData> innerClasses;
/**
* The bootstrapmethods this class implements
*/
protected ArrayList<BootstrapMethodData> bootstrapMethods;
// other parsing fields
protected PrintWriter out;
protected String pkgPrefix = "";
private int pkgPrefixLen = 0;
private int length; //The number of elements in the buffer
private TextLines source = null;
private static final String initialTab = ""; //The number of elements in the buffer
/* -------------------------------------------------------- */
/* ClassData Methods */
public ClassData(PrintWriter out) {
this.out = out;
init(this);
memberType = "ClassData";
TraceUtils.traceln("printOptions=" + options.toString());
pool = new ConstantPool(this);
}
/*========================================================*/
/* Read Methods */
public void read(File in) throws IOException {
read(new DataInputStream(new FileInputStream(in)));
}
public void read(String in) throws IOException {
read(new DataInputStream(new FileInputStream(in)));
}
/**
*
* readFields
*
* read and resolve the field data
*
*/
protected void readFields(DataInputStream in) throws IOException {
int nfields = in.readUnsignedShort();
TraceUtils.traceln("nfields=" + nfields);
fields = new ArrayList<>(nfields);
for (int k = 0; k < nfields; k++) {
FieldData field = new FieldData(this);
TraceUtils.traceln(" FieldData: #" + k);
field.read(in);
fields.add(field);
}
}
/**
*
* readMethods
*
* read and resolve the method data
*
*/
protected void readMethods(DataInputStream in) throws IOException {
int nmethods = in.readUnsignedShort();
TraceUtils.traceln("nmethods=" + nmethods);
methods = new ArrayList<>(nmethods);
for (int k = 0; k < nmethods; k++) {
MethodData method = new MethodData(this);
TraceUtils.traceln(" MethodData: #" + k);
method.read(in);
methods.add(method);
}
}
/**
*
* readInterfaces
*
* read and resolve the interface data
*
*/
protected void readInterfaces(DataInputStream in) throws IOException {
// Read the interface names
int numinterfaces = in.readUnsignedShort();
TraceUtils.traceln("numinterfaces=" + numinterfaces);
interfaces = new int[numinterfaces];
for (int i = 0; i < numinterfaces; i++) {
int intrf_cpx = in.readShort();
TraceUtils.traceln(" intrf_cpx[" + i + "]=" + intrf_cpx);
interfaces[i] = intrf_cpx;
}
}
/**
*
* readAttributes
*
* read and resolve the attribute data
*
*/
@Override
protected boolean handleAttributes(DataInputStream in, AttrTag attrtag, int attrlen) throws IOException {
// Read the Attributes
boolean handled = true;
switch (attrtag) {
case ATT_SourceFile:
// Read SourceFile Attr
if (attrlen != 2) {
throw new ClassFormatError("invalid attr length");
}
source_cpx = in.readUnsignedShort();
break;
case ATT_InnerClasses:
// Read InnerClasses Attr
int num1 = in.readUnsignedShort();
if (2 + num1 * 8 != attrlen) {
throw new ClassFormatError("invalid attr length");
}
innerClasses = new ArrayList<>(num1);
for (int j = 0; j < num1; j++) {
InnerClassData innerClass = new InnerClassData(this);
innerClass.read(in);
innerClasses.add(innerClass);
}
break;
case ATT_BootstrapMethods:
// Read BootstrapMethods Attr
int num2 = in.readUnsignedShort();
bootstrapMethods = new ArrayList<>(num2);
for (int j = 0; j < num2; j++) {
BootstrapMethodData bsmData = new BootstrapMethodData(this);
bsmData.read(in);
bootstrapMethods.add(bsmData);
}
break;
default:
handled = false;
break;
}
return handled;
}
/**
*
* read
*
* read and resolve the class data
*
*/
public void read(DataInputStream in) throws IOException {
// Read the header
// -----------------------------------------------
int magic = in.readInt();
if (magic != JAVA_MAGIC) {
throw new ClassFormatError("wrong magic: " + HexUtils.toHex(magic) + ", expected " + HexUtils.toHex(JAVA_MAGIC));
}
minor_version = in.readShort();
major_version = in.readShort();
// if (major_version != JAVA_VERSION) {
// throw new ClassFormatError("wrong version: " + major_version + ", expected " + JAVA_VERSION);
// }
// Read the constant pool
// -----------------------------------------------
pool.read(in);
access = in.readUnsignedShort(); // & MM_CLASS; // Q
this_cpx = in.readUnsignedShort();
super_cpx = in.readUnsignedShort();
TraceUtils.traceln("access=" + access + " " + Modifiers.accessString(access, CF_Context.CTX_INNERCLASS) + " this_cpx=" + this_cpx + " super_cpx=" + super_cpx);
// Read the interfaces
// -----------------------------------------------
readInterfaces(in);
// Read the fields
// -----------------------------------------------
readFields(in);
// Read the methods
// -----------------------------------------------
readMethods(in);
// Read the attributes
readAttributes(in);
TraceUtils.traceln("");
TraceUtils.traceln("--------------------------------------------------------------------");
TraceUtils.traceln("");
}
/*========================================================*/
/**
*
* getSrcLine
*
* read and resolve the attribute data
*
*/
public String getSrcLine(int lnum) {
if (source == null) {
return null; // impossible call
}
String line;
try {
line = source.getLine(lnum);
} catch (ArrayIndexOutOfBoundsException e) {
line = "Line number " + lnum + " is out of bounds";
}
return line;
}
public void print() throws IOException {
int k, l;
// Write the header
String classname = pool.getClassName(this_cpx);
pkgPrefixLen = classname.lastIndexOf("/") + 1;
// package-info compilation unit
if (classname.endsWith("package-info")) {
// Print the Annotations
if (visibleAnnotations != null) {
for (AnnotationData visad : visibleAnnotations) {
visad.print(out, initialTab);
out.println();
}
}
if (invisibleAnnotations != null) {
for (AnnotationData invisad : invisibleAnnotations) {
invisad.print(out, initialTab);
out.println();
}
}
if (visibleTypeAnnotations != null) {
out.println();
for (TypeAnnotationData visad : visibleTypeAnnotations) {
visad.print(out, initialTab);
out.println();
}
}
if (invisibleTypeAnnotations != null) {
out.println();
for (TypeAnnotationData invisad : invisibleTypeAnnotations) {
invisad.print(out, initialTab);
out.println();
}
}
if (pkgPrefixLen != 0) {
pkgPrefix = classname.substring(0, pkgPrefixLen);
out.print("package " + pkgPrefix.substring(0, pkgPrefixLen - 1) + " ");
out.print("version " + major_version + ":" + minor_version + ";");
}
out.println();
return;
}
if (pkgPrefixLen != 0) {
pkgPrefix = classname.substring(0, pkgPrefixLen);
out.println("package " + pkgPrefix.substring(0, pkgPrefixLen - 1) + ";");
classname = pool.getShortClassName(this_cpx, pkgPrefix);
}
out.println();
// Print the Annotations
if (visibleAnnotations != null) {
for (AnnotationData visad : visibleAnnotations) {
visad.print(out, initialTab);
out.println();
}
}
if (invisibleAnnotations != null) {
for (AnnotationData invisad : invisibleAnnotations) {
invisad.print(out, initialTab);
out.println();
}
}
if (visibleTypeAnnotations != null) {
out.println();
for (TypeAnnotationData visad : visibleTypeAnnotations) {
visad.print(out, initialTab);
out.println();
}
}
if (invisibleTypeAnnotations != null) {
out.println();
for (TypeAnnotationData invisad : invisibleTypeAnnotations) {
invisad.print(out, initialTab);
out.println();
}
}
if ((access & ACC_SUPER) != 0) {
out.print("super ");
access = access & ~ACC_SUPER;
}
// see if we are going to print: abstract interface class
// then replace it with just: interface
printHeader:
{
printSugar:
{
if ((access & ACC_ABSTRACT) == 0) {
break printSugar;
}
if ((access & ACC_INTERFACE) == 0) {
break printSugar;
}
if (options.contains(Options.PR.CPX)) {
break printSugar;
}
if (this_cpx == 0) {
break printSugar;
}
// make sure the this_class is a valid class ref
ConstantPool.Constant this_const = pool.getConst(this_cpx);
if (this_const == null || this_const.tag != ConstantPool.TAG.CONSTANT_CLASS) {
break printSugar;
}
// all conditions met, print syntactic sugar:
out.print(Modifiers.accessString(access & ~ACC_ABSTRACT, CF_Context.CTX_CLASS));
if (isSynthetic) {
out.print("synthetic ");
}
if (isDeprecated) {
out.print("deprecated ");
}
out.print(" " + pool.getShortClassName(this_cpx, pkgPrefix));
break printHeader;
}
// not all conditions met, print header in ordinary way:
out.print(Modifiers.accessString(access, CF_Context.CTX_CLASS));
if (isSynthetic) {
out.print("synthetic ");
}
if (isDeprecated) {
out.print("deprecated ");
}
if (options.contains(Options.PR.CPX)) {
out.print("\t#" + this_cpx + "; //");
}
pool.PrintConstant(out, this_cpx);
}
out.println();
if (!pool.getClassName(super_cpx).equals("java/lang/Object")) {
out.print("\textends ");
pool.printlnClassId(out, super_cpx);
out.println();
}
l = interfaces.length;
if (l > 0) {
for (k = 0; k < l; k++) {
if (k == 0) {
out.print("\timplements ");
} else {
out.print("\t\t ");
}
boolean printComma = (l > 1 && k < (l - 1));
pool.printlnClassId(out, interfaces[k], printComma);
out.println();
}
}
out.println("\tversion " + major_version + ":" + minor_version);
out.println("{");
if ((options.contains(Options.PR.SRC)) && (source_cpx != 0)) {
String source_name = pool.getName(source_cpx);
out.println("\t// Compiled from " + source_name);
try {
source = new TextLines(source_name);
} catch (IOException e) {
}
}
out.println();
// Print the constant pool
if (options.contains(Options.PR.CP)) {
pool.print(out);
out.println();
}
// Print the fields
if (fields != null) {
for (FieldData curf : fields) {
curf.print();
}
}
// Print the methods
if (methods != null) {
for (MethodData curm : methods) {
boolean skipBlankLine = false;
curm.print(skipBlankLine);
}
out.println();
}
// Print the inner classes
if (innerClasses != null) {
for (InnerClassData icd : innerClasses) {
icd.print();
}
out.println();
}
// Print the BootstrapMethods
//
// Only print these if printing extended constants
if ((options.contains(Options.PR.CPX)) && bootstrapMethods != null) {
for (BootstrapMethodData bsmdd : bootstrapMethods) {
bsmdd.print();
}
out.println();
}
out.println("} // end Class " + classname);
} // end ClassData.print()
}// end class ClassData

View File

@ -0,0 +1,693 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import static org.openjdk.asmtools.jasm.Tables.*;
import static org.openjdk.asmtools.jasm.OpcodeTables.*;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
/**
*
* Code data for a code attribute in method members in a class of the Java Disassembler
*/
public class CodeData {
/*-------------------------------------------------------- */
/* Code Data inner classes */
class LineNumData {
short start_pc, line_number;
public LineNumData() {
}
public LineNumData(DataInputStream in) throws IOException {
start_pc = in.readShort();
line_number = in.readShort();
//traceln(" line:"+start_pc+":="+line_number);
}
}
public static class LocVarData {
short start_pc, length, name_cpx, sig_cpx, slot;
public LocVarData() {
}
public LocVarData(DataInputStream in) throws IOException {
start_pc = in.readShort();
length = in.readShort();
name_cpx = in.readShort();
sig_cpx = in.readShort();
slot = in.readShort();
//cls.traceln(" var #"+name_cpx+" start:"+start_pc
//+" length:"+length+"sig_cpx:"+sig_cpx+" sig_cpx:"+sig_cpx);
}
}
/*-------------------------------------------------------- */
/* CodeData Fields */
/**
* Raw byte array for the byte codes
*/
protected byte[] code;
/**
* Limit for the stack size
*/
protected int max_stack;
/**
* Limit for the number of local vars
*/
protected int max_locals;
/**
* (parsed) Trap table, describes exceptions caught
*/
private ArrayList<TrapData> trap_table = new ArrayList<>(0); // TrapData
/**
* (parsed) Line Number table, describes source lines associated with ByteCode indexes
*/
private ArrayList<LineNumData> lin_num_tb = new ArrayList<>(0); // LineNumData
/**
* (parsed) Local Variable table, describes variable scopes associated with ByteCode
* indexes
*/
private ArrayList<LocVarData> loc_var_tb = new ArrayList<>(0); // LocVarData
/**
* (parsed) stack map table, describes compiler hints for stack rep, associated with
* ByteCode indexes
*/
private ArrayList<StackMapData> stack_map = null;
/**
* (parsed) reversed bytecode index hash, associates labels with ByteCode indexes
*/
private HashMap<Integer, iAtt> iattrs = new HashMap<>();
/**
* The remaining attributes of this class
*/
protected ArrayList<AttrData> attrs = new ArrayList<>(0); // AttrData
// internal references
protected ClassData cls;
protected MethodData meth;
private PrintWriter out;
/*-------------------------------------------------------- */
public CodeData(MethodData meth) {
this.meth = meth;
this.cls = meth.cls;
this.out = cls.out;
}
private int getbyte(int pc) {
return code[pc];
}
private int getUbyte(int pc) {
return code[pc] & 0xFF;
}
private int getShort(int pc) {
return (code[pc] << 8) | (code[pc + 1] & 0xFF);
}
private int getUShort(int pc) {
return ((code[pc] << 8) | (code[pc + 1] & 0xFF)) & 0xFFFF;
}
private int getInt(int pc) {
return (getShort(pc) << 16) | (getShort(pc + 2) & 0xFFFF);
}
private static int align(int n) {
return (n + 3) & ~3;
}
protected iAtt get_iAtt(int pc) {
Integer PC = new Integer(pc);
iAtt res = iattrs.get(PC);
if (res == null) {
res = new iAtt(this);
iattrs.put(PC, res);
}
return res;
}
/*========================================================*/
/* Read Methods */
private void readLineNumTable(DataInputStream in) throws IOException {
int len = in.readInt(); // attr_length
int numlines = in.readUnsignedShort();
lin_num_tb = new ArrayList<>(numlines);
TraceUtils.traceln(" CodeAttr: LineNumTable[" + numlines + "] len=" + len);
for (int l = 0; l < numlines; l++) {
lin_num_tb.add(new LineNumData(in));
}
}
private void readLocVarTable(DataInputStream in) throws IOException {
int len = in.readInt(); // attr_length
int numlines = in.readUnsignedShort();
loc_var_tb = new ArrayList<>(numlines);
TraceUtils.traceln(" CodeAttr: LocalVariableTable[" + numlines + "] len=" + len);
for (int l = 0; l < numlines; l++) {
loc_var_tb.add(new LocVarData(in));
}
}
private void readTrapTable(DataInputStream in) throws IOException {
int trap_table_len = in.readUnsignedShort();
TraceUtils.traceln(" CodeAttr: TrapTable[" + trap_table_len + "]");
trap_table = new ArrayList<>(trap_table_len);
for (int l = 0; l < trap_table_len; l++) {
trap_table.add(new TrapData(in, l));
}
}
private void readStackMap(DataInputStream in) throws IOException {
int len = in.readInt(); // attr_length
int stack_map_len = in.readUnsignedShort();
TraceUtils.traceln(" CodeAttr: Stack_Map: attrlen=" + len + " num=" + stack_map_len);
stack_map = new ArrayList<>(stack_map_len);
StackMapData.prevFramePC = 0;
for (int k = 0; k < stack_map_len; k++) {
stack_map.add(new StackMapData(this, in));
}
}
private void readStackMapTable(DataInputStream in) throws IOException {
int len = in.readInt(); // attr_length
int stack_map_len = in.readUnsignedShort();
TraceUtils.traceln(" CodeAttr: Stack_Map_Table: attrlen=" + len + " num=" + stack_map_len);
stack_map = new ArrayList<>(stack_map_len);
StackMapData.prevFramePC = 0;
for (int k = 0; k < stack_map_len; k++) {
stack_map.add(new StackMapData(this, in, true));
}
}
/**
*
* read
*
* read and resolve the code attribute data called from MethodData. precondition:
* NumFields has already been read from the stream.
*
*/
public void read(DataInputStream in, int codeattrlen) throws IOException {
// Read the code in the Code Attribute
max_stack = in.readUnsignedShort();
max_locals = in.readUnsignedShort();
int codelen = in.readInt();
TraceUtils.traceln(" CodeAttr: Codelen=" + codelen + " fulllen=" + codeattrlen + " max_stack=" + max_stack + " max_locals=" + max_locals);
// read the raw code bytes
code = new byte[codelen];
in.read(code, 0, codelen);
//read the trap table
readTrapTable(in);
// Read any attributes of the Code Attribute
int nattr = in.readUnsignedShort();
TraceUtils.traceln(" CodeAttr: add.attr:" + nattr);
for (int k = 0; k < nattr; k++) {
int name_cpx = in.readUnsignedShort();
// verify the Attrs name
ConstantPool.Constant name_const = cls.pool.getConst(name_cpx);
if (name_const != null && name_const.tag == ConstantPool.TAG.CONSTANT_UTF8) {
String attrname = cls.pool.getString(name_cpx);
TraceUtils.traceln(" CodeAttr: attr: " + attrname);
// process the attr
AttrTag attrtag = attrtag(attrname);
switch (attrtag) {
case ATT_LineNumberTable:
readLineNumTable(in);
break;
case ATT_LocalVariableTable:
readLocVarTable(in);
break;
case ATT_StackMap:
readStackMap(in);
break;
case ATT_StackMapTable:
readStackMapTable(in);
break;
default:
AttrData attr = new AttrData(cls);
int attrlen = in.readInt(); // attr_length
attr.read(name_cpx, attrlen, in);
attrs.add(attr);
break;
}
}
}
}
/*========================================================*/
/* Code Resolution Methods */
private int checkForLabelRef(int pc) {
// throws IOException {
int opc = getUbyte(pc);
Opcode opcode = opcode(opc);
switch (opcode) {
case opc_tableswitch: {
int tb = align(pc + 1);
int default_skip = getInt(tb); /* default skip pamount */
int low = getInt(tb + 4);
int high = getInt(tb + 8);
int count = high - low;
for (int i = 0; i <= count; i++) {
get_iAtt(pc + getInt(tb + 12 + 4 * i)).referred = true;
}
get_iAtt(default_skip + pc).referred = true;
return tb - pc + 16 + count * 4;
}
case opc_lookupswitch: {
int tb = align(pc + 1);
int default_skip = getInt(tb); /* default skip pamount */
int npairs = getInt(tb + 4);
for (int i = 1; i <= npairs; i++) {
get_iAtt(pc + getInt(tb + 4 + i * 8)).referred = true;
}
get_iAtt(default_skip + pc).referred = true;
return tb - pc + (npairs + 1) * 8;
}
case opc_jsr:
case opc_goto:
case opc_ifeq:
case opc_ifge:
case opc_ifgt:
case opc_ifle:
case opc_iflt:
case opc_ifne:
case opc_if_icmpeq:
case opc_if_icmpne:
case opc_if_icmpge:
case opc_if_icmpgt:
case opc_if_icmple:
case opc_if_icmplt:
case opc_if_acmpeq:
case opc_if_acmpne:
case opc_ifnull:
case opc_ifnonnull:
get_iAtt(pc + getShort(pc + 1)).referred = true;
return 3;
case opc_jsr_w:
case opc_goto_w:
get_iAtt(pc + getInt(pc + 1)).referred = true;
return 5;
case opc_wide:
case opc_nonpriv:
case opc_priv:
int opc2 = (opcode.value() << 8) + getUbyte(pc + 1);
opcode = opcode(opc2);
}
try {
int opclen = opcode.length();
return opclen == 0 ? 1 : opclen; // bugfix for 4614404
} catch (ArrayIndexOutOfBoundsException e) {
return 1;
}
} // end checkForLabelRef
private void loadLabelTable() {
for (int pc = 0; pc < code.length;) {
pc = pc + checkForLabelRef(pc);
}
}
private void loadLineNumTable() {
for (LineNumData entry : lin_num_tb) {
get_iAtt(entry.start_pc).lnum = entry.line_number;
}
}
private void loadStackMap() {
for (StackMapData entry : stack_map) {
get_iAtt(entry.start_pc).stackMapEntry = entry;
}
}
private void loadLocVarTable() throws IOException {
for (LocVarData entry : loc_var_tb) {
get_iAtt(entry.start_pc).add_var(entry);
get_iAtt(entry.start_pc + entry.length).add_endvar(entry);
}
}
private void loadTrapTable() {
for (TrapData entry : trap_table) {
get_iAtt(entry.start_pc).add_trap(entry);
get_iAtt(entry.end_pc).add_endtrap(entry);
get_iAtt(entry.handler_pc).add_handler(entry);
}
}
/*========================================================*/
/* Print Methods */
private void PrintConstant(int cpx) {
out.print("\t");
cls.pool.PrintConstant(out, cpx);
}
private int printInstr(int pc) throws IOException {
boolean pr_cpx = meth.options.contains(Options.PR.CPX);
int opc = getUbyte(pc);
int opc2;
Opcode opcode = opcode(opc);
Opcode opcode2;
String mnem;
switch (opcode) {
case opc_nonpriv:
case opc_priv:
opc2 = getUbyte(pc + 1);
int finalopc = (opc << 8) + opc2;
opcode2 = opcode(finalopc);
if (opcode2 == null) {
// assume all (even nonexistent) priv and nonpriv instructions
// are 2 bytes long
mnem = opcode.parsekey() + " " + opc2;
} else {
mnem = opcode2.parsekey();
}
out.print(mnem);
return 2;
case opc_wide: {
opc2 = getUbyte(pc + 1);
int finalopcwide = (opc << 8) + opc2;
opcode2 = opcode(finalopcwide);
if (opcode2 == null) {
// nonexistent opcode - but we have to print something
out.print("bytecode " + opcode);
return 1;
} else {
mnem = opcode2.parsekey();
}
out.print(mnem + " " + getUShort(pc + 2));
if (opcode2 == Opcode.opc_iinc) {
out.print(", " + getShort(pc + 4));
return 6;
}
return 4;
}
}
mnem = opcode.parsekey();
if (mnem == null) {
// nonexistent opcode - but we have to print something
out.print("bytecode " + opcode);
return 1;
}
if (opcode.value() > Opcode.opc_jsr_w.value()) {
// pseudo opcodes should be printed as bytecodes
out.print("bytecode " + opcode);
return 1;
}
out.print(opcode.parsekey());
// TraceUtils.traceln("****** [CodeData.printInstr]: got an '" + opcode.parsekey() + "' [" + opc + "] instruction ****** ");
switch (opcode) {
case opc_aload:
case opc_astore:
case opc_fload:
case opc_fstore:
case opc_iload:
case opc_istore:
case opc_lload:
case opc_lstore:
case opc_dload:
case opc_dstore:
case opc_ret:
out.print("\t" + getUbyte(pc + 1));
return 2;
case opc_iinc:
out.print("\t" + getUbyte(pc + 1) + ", " + getbyte(pc + 2));
return 3;
case opc_tableswitch: {
int tb = align(pc + 1);
int default_skip = getInt(tb); /* default skip pamount */
int low = getInt(tb + 4);
int high = getInt(tb + 8);
int count = high - low;
out.print("{ //" + low + " to " + high);
for (int i = 0; i <= count; i++) {
out.print("\n\t\t" + (i + low) + ": " + meth.lP + (pc + getInt(tb + 12 + 4 * i)) + ";");
}
out.print("\n\t\tdefault: " + meth.lP + (default_skip + pc) + " }");
return tb - pc + 16 + count * 4;
}
case opc_lookupswitch: {
int tb = align(pc + 1);
int default_skip = getInt(tb);
int npairs = getInt(tb + 4);
out.print("{ //" + npairs);
for (int i = 1; i <= npairs; i++) {
out.print("\n\t\t" + getInt(tb + i * 8) + ": " + meth.lP + (pc + getInt(tb + 4 + i * 8)) + ";");
}
out.print("\n\t\tdefault: " + meth.lP + (default_skip + pc) + " }");
return tb - pc + (npairs + 1) * 8;
}
case opc_newarray:
int tp = getUbyte(pc + 1);
BasicType type = basictype(tp);
switch (type) {
case T_BOOLEAN:
out.print(" boolean");
break;
case T_BYTE:
out.print(" byte");
break;
case T_CHAR:
out.print(" char");
break;
case T_SHORT:
out.print(" short");
break;
case T_INT:
out.print(" int");
break;
case T_LONG:
out.print(" long");
break;
case T_FLOAT:
out.print(" float");
break;
case T_DOUBLE:
out.print(" double");
break;
case T_CLASS:
out.print(" class");
break;
default:
out.print(" BOGUS TYPE:" + type);
}
return 2;
case opc_anewarray: {
int index = getUShort(pc + 1);
if (pr_cpx) {
out.print("\t#" + index + "; //");
}
PrintConstant(index);
return 3;
}
case opc_sipush:
out.print("\t" + getShort(pc + 1));
return 3;
case opc_bipush:
out.print("\t" + getbyte(pc + 1));
return 2;
case opc_ldc: {
int index = getUbyte(pc + 1);
if (pr_cpx) {
out.print("\t#" + index + "; //");
}
PrintConstant(index);
return 2;
}
case opc_ldc_w:
case opc_ldc2_w:
case opc_instanceof:
case opc_checkcast:
case opc_new:
case opc_putstatic:
case opc_getstatic:
case opc_putfield:
case opc_getfield:
case opc_invokevirtual:
case opc_invokespecial:
case opc_invokestatic: {
int index = getUShort(pc + 1);
if (pr_cpx) {
out.print("\t#" + index + "; //");
}
PrintConstant(index);
return 3;
}
case opc_invokeinterface: {
int index = getUShort(pc + 1), nargs = getUbyte(pc + 3);
// getUbyte(pc + 4); // reserved byte
if (pr_cpx) {
out.print("\t#" + index + ", " + nargs + "; //");
PrintConstant(index);
} else {
PrintConstant(index);
out.print(", " + nargs); // args count
}
return 5;
}
case opc_invokedynamic: { // JSR-292
int index = getUShort(pc + 1);
// getUbyte(pc + 3); // reserved byte
// getUbyte(pc + 4); // reserved byte
if (pr_cpx) {
out.print("\t#" + index + "; //");
PrintConstant(index);
} else {
PrintConstant(index);
}
return 5;
}
case opc_multianewarray: {
int index = getUShort(pc + 1), dimensions = getUbyte(pc + 3);
if (pr_cpx) {
out.print("\t#" + index + ", " + dimensions + "; //");
PrintConstant(index);
} else {
PrintConstant(index);
out.print(", " + dimensions); // dimensions count
}
return 4;
}
case opc_jsr:
case opc_goto:
case opc_ifeq:
case opc_ifge:
case opc_ifgt:
case opc_ifle:
case opc_iflt:
case opc_ifne:
case opc_if_icmpeq:
case opc_if_icmpne:
case opc_if_icmpge:
case opc_if_icmpgt:
case opc_if_icmple:
case opc_if_icmplt:
case opc_if_acmpeq:
case opc_if_acmpne:
case opc_ifnull:
case opc_ifnonnull:
out.print("\t" + meth.lP + (pc + getShort(pc + 1)));
return 3;
case opc_jsr_w:
case opc_goto_w:
out.print("\t" + meth.lP + (pc + getInt(pc + 1)));
return 5;
default:
return 1;
}
} // end printInstr
/**
*
* print
*
* prints the code data to the current output stream. called from MethodData.
*
*/
public void print() throws IOException {
if (!lin_num_tb.isEmpty()) {
loadLineNumTable();
}
if (stack_map != null) {
loadStackMap();
}
if (!meth.options.contains(Options.PR.PC)) {
loadLabelTable();
}
loadTrapTable();
if (!loc_var_tb.isEmpty()) {
loadLocVarTable();
}
out.println();
out.println("\tstack " + max_stack + " locals " + max_locals);
// Need to print ParamAnnotations here.
meth.printPAnnotations();
out.println("{");
iAtt iatt = iattrs.get(new Integer(0));
for (int pc = 0; pc < code.length;) {
if (iatt != null) {
iatt.printBegins(); // equ. print("\t");
} else {
out.print("\t");
}
if (meth.options.contains(Options.PR.PC)) {
out.print(pc + ":\t");
} else if ((iatt != null) && iatt.referred) {
out.print(meth.lP + pc + ":\t");
} else {
out.print("\t");
}
if (iatt != null) {
iatt.printStackMap();
}
pc = pc + printInstr(pc);
out.println(";");
iatt = iattrs.get(new Integer(pc));
if (iatt != null) {
iatt.printEnds();
}
}
// the right brace can be labelled:
if (iatt != null) {
iatt.printBegins(); // equ. print("\t");
if (iatt.referred) {
out.print(meth.lP + code.length + ":\t");
}
iatt.printStackMap();
out.println();
}
out.println("}");
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.jasm.Modifiers;
import static org.openjdk.asmtools.jasm.Tables.*;
import java.io.DataInputStream;
import java.io.IOException;
/**
* Field data for field members in a class of the Java Disassembler
*/
public class FieldData extends MemberData {
/*-------------------------------------------------------- */
/* FieldData Fields */
/**
* CP index to the field name
*/
protected int name_cpx;
/**
* CP index to the field type
*/
protected int sig_cpx;
/**
* CP index to the field value
*/
protected int value_cpx = 0;
public static final String initialTab = "";
/*-------------------------------------------------------- */
public FieldData(ClassData cls) {
init(cls);
memberType = "FieldData";
}
/*========================================================*/
/* Read Methods */
@Override
protected boolean handleAttributes(DataInputStream in, AttrTag attrtag, int attrlen) throws IOException {
// Read the Attributes
boolean handled = true;
switch (attrtag) {
case ATT_ConstantValue:
if (attrlen != 2) {
throw new ClassFormatError("invalid ConstantValue attr length");
}
value_cpx = in.readUnsignedShort();
break;
default:
handled = false;
break;
}
return handled;
}
/**
*
* read
*
* read and resolve the field data called from ClassData. precondition: NumFields has
* already been read from the stream.
*
*/
public void read(DataInputStream in) throws IOException {
// read the Fields CP indexes
access = in.readUnsignedShort();
name_cpx = in.readUnsignedShort();
sig_cpx = in.readUnsignedShort();
TraceUtils.traceln(" FieldData: name[" + name_cpx + "]=" + cls.pool.getString(name_cpx)
+ " sig[" + sig_cpx + "]=" + cls.pool.getString(sig_cpx));
// Read the attributes
readAttributes(in);
} // end read
/*========================================================*/
/* Print Methods */
/**
*
* print
*
* prints the field data to the current output stream. called from ClassData.
* precondition: NumFields has already been printed to the stream.
*
*/
public void print() throws IOException {
// Print annotations first
// Print the Annotations
if (visibleAnnotations != null) {
out.println();
for (AnnotationData visad : visibleAnnotations) {
visad.print(out, initialTab);
}
}
if (invisibleAnnotations != null) {
out.println();
for (AnnotationData invisad : invisibleAnnotations) {
invisad.print(out, initialTab);
}
}
if (visibleTypeAnnotations != null) {
out.println();
for (TypeAnnotationData visad : visibleTypeAnnotations) {
visad.print(out, initialTab);
out.println();
}
}
if (invisibleTypeAnnotations != null) {
out.println();
for (TypeAnnotationData invisad : invisibleTypeAnnotations) {
invisad.print(out, initialTab);
out.println();
}
}
boolean pr_cpx = options.contains(Options.PR.CPX);
out.print(Modifiers.accessString(access, CF_Context.CTX_FIELD));
if (isSynthetic) {
out.print("synthetic ");
}
if (isDeprecated) {
out.print("deprecated ");
}
out.print("Field ");
if (pr_cpx) {
out.print("#" + name_cpx + ":#" + sig_cpx);
} else {
out.print(cls.pool.getName(name_cpx) + ":" + cls.pool.getName(sig_cpx));
}
if (value_cpx != 0) {
out.print("\t= ");
cls.pool.PrintConstant(cls.out, value_cpx);
}
if (pr_cpx) {
out.println(";\t // " + cls.pool.getName(name_cpx) + ":" + cls.pool.getName(sig_cpx));
} else {
out.println(";");
}
}
} // end FieldData

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import static org.openjdk.asmtools.jasm.Tables.*;
import org.openjdk.asmtools.jasm.Modifiers;
import java.io.DataInputStream;
import java.io.IOException;
/**
*
*/
class InnerClassData {
/*-------------------------------------------------------- */
/* InnerClassData Fields */
private Options options = Options.OptionObject();
ClassData cls;
int inner_class_info_index;
int outer_class_info_index;
int inner_name_index;
int access;
/*-------------------------------------------------------- */
public InnerClassData(ClassData cls) {
this.cls = cls;
}
public void read(DataInputStream in) throws IOException {
inner_class_info_index = in.readUnsignedShort();
outer_class_info_index = in.readUnsignedShort();
inner_name_index = in.readUnsignedShort();
access = in.readUnsignedShort();
} // end read
public void print() throws IOException {
boolean pr_cpx = options.contains(Options.PR.CPX);
cls.out.print(Modifiers.accessString(access, CF_Context.CTX_INNERCLASS));
cls.out.print("InnerClass ");
if (pr_cpx) {
if (inner_name_index != 0) {
cls.out.print("#" + inner_name_index + "= ");
}
cls.out.print("#" + inner_class_info_index);
if (outer_class_info_index != 0) {
cls.out.print(" of #" + outer_class_info_index);
}
cls.out.print("; //");
}
if (inner_name_index != 0) {
cls.out.print(cls.pool.getName(inner_name_index) + "=");
}
if (inner_class_info_index != 0) {
cls.pool.PrintConstant(cls.out, inner_class_info_index);
}
if (outer_class_info_index != 0) {
cls.out.print(" of ");
cls.pool.PrintConstant(cls.out, outer_class_info_index);
}
if (pr_cpx) {
cls.out.println();
} else {
cls.out.println(";");
}
}
} // end InnerClassData

View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.util.I18NResourceBundle;
import org.openjdk.asmtools.util.ProductInfo;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
* Main program of the Java Disassembler
*/
public class Main {
private Options options = Options.OptionObject();
/**
* Name of the program.
*/
String program;
/**
* The stream where error message are printed.
*/
PrintWriter out;
boolean DebugFlag = false;
/* debugging value, output stream will only allow this many
* bytes to be written before throwing an error.
*/
private int bytelimit = 0;
public static final I18NResourceBundle i18n
= I18NResourceBundle.getBundleForClass(Main.class);
/**
* Constructor.
*/
public Main(PrintWriter out, String program) {
this.out = out;
this.program = program;
}
/**
* Top level error message
*/
public void error(String msg) {
System.err.println(program + ": " + msg);
}
/**
* Usage
*/
public void usage() {
error(i18n.getString("jdis.usage"));
error(i18n.getString("jdis.opt.g"));
error(i18n.getString("jdis.opt.sl"));
error(i18n.getString("jdis.opt.hx"));
error(i18n.getString("jdis.opt.v"));
error(i18n.getString("jdis.opt.version"));
}
/**
* Run the disassembler
*/
public synchronized boolean disasm(String argv[]) {
ArrayList<String> vj = new ArrayList<>();
// Parse arguments
for (int i = 0; i < argv.length; i++) {
String arg = argv[i];
switch (arg) {
case "-g":
options.set(Options.PR.DEBUG);
break;
case "-v":
options.setCodeOptions();
break;
case "-sl":
options.set(Options.PR.SRC);
break;
case "-hx":
options.set(Options.PR.HEX);
break;
case "-version":
out.println(ProductInfo.FULL_VERSION);
break;
default:
if (arg.startsWith("-")) {
error(i18n.getString("jdis.error.invalid_option", arg));
usage();
return false;
} else {
vj.add(arg);
}
break;
}
}
if (vj.isEmpty()) {
usage();
return false;
}
disasm:
for (String inpname : vj) {
if (inpname == null) {
continue;
} // cross out by CompilerChoice.compile
try {
ClassData cc = new ClassData(out);
cc.read(new DataInputStream(new FileInputStream(inpname)));
cc.print();
continue disasm;
} catch (FileNotFoundException ee) {
error(i18n.getString("jdis.error.cannot_read", inpname));
} catch (Error ee) {
ee.printStackTrace();
error(i18n.getString("jdis.error.fatal_error", inpname));
} catch (Exception ee) {
ee.printStackTrace();
error(i18n.getString("jdis.error.fatal_exception", inpname));
}
return false;
}
return true;
}
/**
* Main program
*/
public static void main(String argv[]) {
Main disassembler = new Main(new PrintWriter(new uEscWriter(System.out)), "jdis");
boolean result = disassembler.disasm(argv);
System.exit(result ? 0 : 1);
}
}

View File

@ -0,0 +1,171 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.jasm.Tables;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
*
*/
public class MemberData {
/**
* access flags (modifiers)
*/
protected int access;
// flags
protected boolean isSynthetic = false;
protected boolean isDeprecated = false;
/**
* The visible annotations for this class
*/
protected ArrayList<AnnotationData> visibleAnnotations;
/**
* The invisible annotations for this class
*/
protected ArrayList<AnnotationData> invisibleAnnotations;
/**
* The visible annotations for this class
*/
protected ArrayList<TypeAnnotationData> visibleTypeAnnotations;
/**
* The invisible annotations for this class
*/
protected ArrayList<TypeAnnotationData> invisibleTypeAnnotations;
/**
* The remaining attributes of this class
*/
protected ArrayList<AttrData> attrs;
// internal references
protected Options options = Options.OptionObject();
protected ClassData cls;
protected PrintWriter out;
protected String memberType = "";
/* -------------------------------------------------------- */
/* ClassData Methods */
public MemberData() {
}
public void init(ClassData cls) {
this.out = cls.out;
this.cls = cls;
this.options = cls.options;
}
protected boolean handleAttributes(DataInputStream in, Tables.AttrTag attrtag, int attrlen) throws IOException {
// sub-classes override
return false;
}
protected void readAttributes(DataInputStream in) throws IOException {
// Read the Attributes
int natt = in.readUnsignedShort();
TraceUtils.traceln("natt=" + natt);
attrs = new ArrayList<>(natt);
TraceUtils.traceln(memberType + " - Attributes: " + natt);
AttrData attr;
for (int k = 0; k < natt; k++) {
int name_cpx = in.readUnsignedShort();
attr = new AttrData(cls);
attrs.add(attr);
String attr_name = cls.pool.getString(name_cpx);
TraceUtils.traceln(" " + memberType + ": #" + k + " name[" + name_cpx + "]=" + attr_name);
Tables.AttrTag tag = Tables.attrtag(attr_name);
int attrlen = in.readInt();
switch (tag) {
case ATT_Synthetic:
// Read Synthetic Attr
if (attrlen != 0) {
throw new ClassFormatError("invalid Synthetic attr length");
}
isSynthetic = true;
break;
case ATT_Deprecated:
// Read Deprecated Attr
if (attrlen != 0) {
throw new ClassFormatError("invalid Deprecated attr length");
}
isDeprecated = true;
break;
case ATT_RuntimeVisibleAnnotations:
case ATT_RuntimeInvisibleAnnotations:
// Read Annotations Attr
int cnt = in.readShort();
ArrayList<AnnotationData> annots = new ArrayList<>(cnt);
boolean invisible = (tag == Tables.AttrTag.ATT_RuntimeInvisibleAnnotations);
for (int i = 0; i < cnt; i++) {
TraceUtils.traceln(" AnnotationData: #" + i);
AnnotationData annot = new AnnotationData(invisible, cls);
annot.read(in);
annots.add(annot);
}
if (invisible) {
invisibleAnnotations = annots;
} else {
visibleAnnotations = annots;
}
break;
case ATT_RuntimeVisibleTypeAnnotations:
case ATT_RuntimeInvisibleTypeAnnotations:
// Read Type Annotations Attr
int tcnt = in.readShort();
ArrayList<TypeAnnotationData> tannots = new ArrayList<>(tcnt);
boolean tinvisible = (tag == Tables.AttrTag.ATT_RuntimeInvisibleTypeAnnotations);
for (int tindex = 0; tindex < tcnt; tindex++) {
TraceUtils.traceln(" TypeAnnotationData: #" + tindex);
TypeAnnotationData tannot = new TypeAnnotationData(tinvisible, cls);
tannot.read(in);
tannots.add(tannot);
}
if (tinvisible) {
invisibleTypeAnnotations = tannots;
} else {
visibleTypeAnnotations = tannots;
}
break;
default:
boolean handled = handleAttributes(in, tag, attrlen);
if (!handled) {
attr.read(name_cpx, attrlen, in);
}
break;
}
}
}
}

View File

@ -0,0 +1,393 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.jasm.Modifiers;
import static org.openjdk.asmtools.jasm.Tables.*;
import static org.openjdk.asmtools.jasm.JasmTokens.Token;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
/**
*
* Method data for method members in a class of the Java Disassembler
*/
public class MethodData extends MemberData {
/*-------------------------------------------------------- */
/* MethodData Fields */
/**
* MethodParamData
*/
class ParamNameData {
public int access;
public int name_cpx;
public ParamNameData(int name, int access) {
this.access = access;
this.name_cpx = name;
}
}
/*-------------------------------------------------------- */
/**
* CP index to the method name
*/
protected int name_cpx;
/**
* CP index to the method type
*/
protected int sig_cpx;
/**
* The code data for this method. May be null
*/
private CodeData code;
/**
* The exception table (thrown exceptions) for this method. May be null
*/
private int[] exc_table = null;
protected String lP; // labelPrefix
public static final String initialTab = "";
/**
* The parameter names for this method
*/
protected ArrayList<ParamNameData> paramNames;
/**
* The visible parameter annotations for this method
*/
protected ParameterAnnotationData visibleParameterAnnotations;
/**
* The invisible parameter annotations for this method
*/
protected ParameterAnnotationData invisibleParameterAnnotations;
/**
* The invisible parameter annotations for this method
*/
protected AnnotElem.AnnotValue defaultAnnotation;
/*-------------------------------------------------------- */
public MethodData(ClassData cls) {
init(cls);
memberType = "MethodData";
lP = (options.contains(Options.PR.LABS)) ? "L" : "";
paramNames = null;
}
/*========================================================*/
/* Read Methods */
@Override
protected boolean handleAttributes(DataInputStream in, AttrTag attrtag, int attrlen) throws IOException {
// Read the Attributes
boolean handled = true;
switch (attrtag) {
case ATT_Code:
code = new CodeData(this);
code.read(in, attrlen);
break;
case ATT_Exceptions:
readExceptions(in);
break;
case ATT_MethodParameters:
readMethodParameters(in);
break;
case ATT_RuntimeVisibleParameterAnnotations:
case ATT_RuntimeInvisibleParameterAnnotations:
boolean invisible1 = (attrtag == AttrTag.ATT_RuntimeInvisibleParameterAnnotations);
ParameterAnnotationData pannots = new ParameterAnnotationData(cls, invisible1);
pannots.read(in);
if (invisible1) {
invisibleParameterAnnotations = pannots;
} else {
visibleParameterAnnotations = pannots;
}
break;
case ATT_AnnotationDefault:
defaultAnnotation = AnnotElem.readValue(in, cls, false);
break;
default:
handled = false;
break;
}
return handled;
}
/**
*
* read
*
* read and resolve the method data called from ClassData. precondition: NumFields has
* already been read from the stream.
*
*/
public void read(DataInputStream in) throws IOException {
// read the Methods CP indexes
access = in.readUnsignedShort(); // & MM_METHOD; // Q
name_cpx = in.readUnsignedShort();
sig_cpx = in.readUnsignedShort();
TraceUtils.traceln(" MethodData: {modifiers}: " + Modifiers.toString(access, CF_Context.CTX_METHOD));
TraceUtils.traceln(" MethodData: name[" + name_cpx + "]=" + cls.pool.getString(name_cpx)
+ " sig[" + sig_cpx + "]=" + cls.pool.getString(sig_cpx));
// Read the attributes
readAttributes(in);
}
private void readExceptions(DataInputStream in) throws IOException {
// this is not really a CodeAttr attribute, it's part of the CodeAttr
int exc_table_len = in.readUnsignedShort();
TraceUtils.traceln(" ExceptionsAttr[" + exc_table_len + "]");
exc_table = new int[exc_table_len];
for (int l = 0; l < exc_table_len; l++) {
int exc = in.readShort();
TraceUtils.traceln(" throws:#" + exc);
exc_table[l] = exc;
}
}
private void readMethodParameters(DataInputStream in) throws IOException {
// this is not really a CodeAttr attribute, it's part of the CodeAttr
int num_params = in.readUnsignedByte();
TraceUtils.traceln(" MethodParametersAttr[" + num_params + "]");
paramNames = new ArrayList<>(num_params);
for (int l = 0; l < num_params; l++) {
short pname_cpx = (short) in.readUnsignedShort();
int paccess = in.readUnsignedShort();
TraceUtils.traceln(" P[" + l + "] ={ name[" + pname_cpx + "]: " + cls.pool.getString(pname_cpx)
+ " modifiers [" + paccess + "]: " + Modifiers.toString(paccess, CF_Context.CTX_METHOD) + "}");
paramNames.add(l, new ParamNameData(pname_cpx, paccess));
}
}
/*========================================================*/
/* Print Methods */
/**
*
* printPAnnotations
*
* prints the parameter annotations for this method. called from CodeAttr (since JASM
* code integrates the PAnnotation Syntax inside the method body).
*
*/
// This is called from the CodeAttr
public void printPAnnotations() throws IOException {
int visSize = 0;
int invisSize = 0;
int pNumSize = 0;
if (visibleParameterAnnotations != null) {
visSize = visibleParameterAnnotations.numParams();
}
if (invisibleParameterAnnotations != null) {
invisSize = invisibleParameterAnnotations.numParams();
}
if (paramNames != null) {
pNumSize = paramNames.size();
}
int maxParams;
maxParams = (pNumSize > invisSize) ? pNumSize : invisSize;
maxParams = (visSize > maxParams) ? visSize : maxParams;
for (int paramNum = 0; paramNum < maxParams; paramNum++) {
ArrayList<AnnotationData> visAnnots = null;
if (visibleParameterAnnotations != null && paramNum < visSize) {
visAnnots = visibleParameterAnnotations.get(paramNum);
}
ArrayList<AnnotationData> invisAnnots = null;
if (invisibleParameterAnnotations != null && paramNum < invisSize) {
invisAnnots = invisibleParameterAnnotations.get(paramNum);
}
ParamNameData pname = (paramNames == null) ? null : paramNames.get(paramNum);
boolean nullAnnots = ((visAnnots == null) && (invisAnnots == null));
if (pname != null && pname.name_cpx == 0) {
pname = null;
}
// Print the Param number (header)
if ((pname != null) || !nullAnnots) {
out.print("\t" + paramNum + ": ");
} else {
continue;
}
boolean firstTime = true;
// Print the Parameter name
if (pname != null) {
out.print(Token.PARAM_NAME.parsekey());
out.print(Token.LBRACE.parsekey());
out.print(cls.pool.getString(pname.name_cpx));
out.print(" ");
out.print(Modifiers.toString(pname.access, CF_Context.CTX_METHOD));
out.print(Token.RBRACE.parsekey());
out.print(" ");
}
// Print any visible param annotations
if (visAnnots != null) {
for (AnnotationData annot : visAnnots) {
if (!firstTime) {
out.print("\t ");
}
annot.print(out, initialTab);
// out.println();
firstTime = false;
}
}
// Print any invisible param annotations
if (invisAnnots != null) {
for (AnnotationData annot : invisAnnots) {
if (!firstTime) {
out.print("\t ");
}
annot.print(out, initialTab);
// out.println();
firstTime = false;
}
}
// Reset the line, if there were parameters
if ((pname != null) || !nullAnnots) {
out.println("");
}
}
}
/**
*
* print
*
* prints the method data to the current output stream. called from ClassData.
* precondition: NumMethods has already been printed to the stream.
*
*/
public void print(boolean skipBlankLine) throws IOException {
// Print the Annotations
if (visibleAnnotations != null) {
out.println();
for (AnnotationData visad : visibleAnnotations) {
visad.print(out, initialTab);
out.println();
skipBlankLine = true;
}
}
if (invisibleAnnotations != null) {
out.println();
for (AnnotationData invisad : invisibleAnnotations) {
invisad.print(out, initialTab);
out.println();
skipBlankLine = true;
}
}
if (visibleTypeAnnotations != null) {
out.println();
for (TypeAnnotationData visad : visibleTypeAnnotations) {
visad.print(out, initialTab);
out.println();
skipBlankLine = true;
}
}
if (invisibleTypeAnnotations != null) {
out.println();
for (TypeAnnotationData invisad : invisibleTypeAnnotations) {
invisad.print(out, initialTab);
out.println();
skipBlankLine = true;
}
}
boolean pr_cpx = options.contains(Options.PR.CPX);
if (!skipBlankLine) {
out.println();
}
out.print(Modifiers.accessString(access, CF_Context.CTX_METHOD));
if (isSynthetic) {
out.print(Token.SYNTHETIC.parsekey() + " ");
}
if (isDeprecated) {
out.print(Token.DEPRECATED.parsekey() + " ");
}
out.print(Token.METHODREF.parsekey() + " ");
if (pr_cpx) {
// print the CPX method descriptor
out.print("#" + name_cpx + ":#" + sig_cpx);
out.print("\t // ");
out.println(cls.pool.getName(name_cpx) + ":" + cls.pool.getName(sig_cpx));
} else {
out.print(cls.pool.getName(name_cpx) + ":" + cls.pool.getName(sig_cpx));
}
// followed by default annotation
if (defaultAnnotation != null) {
out.print(" default { ");
defaultAnnotation.print(out, initialTab);
out.print(" } ");
}
// followed by exception table
printExceptionTable();
// if ((code == null) || ((access & ACC_ABSTRACT) != 0)) {
if (code == null) {
out.print(";");
if (pr_cpx) {
out.print("\t // ");
out.print(cls.pool.getName(name_cpx) + ":" + cls.pool.getName(sig_cpx));
}
out.println("");
} else {
code.print();
}
}
private void printExceptionTable() {
if (exc_table != null) {
out.print("\n\tthrows ");
int len = exc_table.length;
for (int exceptNum = 0; exceptNum < len; exceptNum++) {
out.print(cls.pool.getClassName(exc_table[exceptNum]));
if (exceptNum < len - 1) {
out.print(", ");
}
}
}
}
} // end MethodData

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import java.util.EnumSet;
/**
*
*/
public class Options {
/*-------------------------------------------------------- */
/* Options Fields */
private static Options ref;
static public enum PR {
CP, // print Constant Pool
LNT, // print Line Number table
PC, // print Program Counter - for all instr
LABS, // print Labels (as identifiers)
CPX, // print CP indeX along with arguments
SRC, // print Source Line as comment
HEX, // print numbers as hexadecimals
VAR, // print local variables declarations
DEBUG; // Debug flag
};
static private final EnumSet<PR> JASM = EnumSet.<PR>of(PR.LABS); // default options
static private final EnumSet<PR> CODE = EnumSet.<PR>of(
PR.CP,
PR.LNT,
PR.PC,
PR.CPX,
PR.VAR
);
static private EnumSet<PR> printOptions = JASM;
/*-------------------------------------------------------- */
private Options() {
}
public static Options OptionObject() {
if (ref == null) {
ref = new Options();
}
return ref;
}
public void set(PR val) {
printOptions.add(val);
}
public void setCodeOptions() {
printOptions = CODE;
}
public boolean contains(PR val) {
return printOptions.contains(val);
}
public boolean debug() {
return printOptions.contains(PR.DEBUG);
}
@Override
public String toString() {
return printOptions.toString();
}
}

View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
*
*/
public class ParameterAnnotationData {
/*-------------------------------------------------------- */
/* AnnotData Fields */
private boolean invisible = false;
private static final String initialTab = "";
private ArrayList<ArrayList<AnnotationData>> array = null;
private ClassData cls;
/*-------------------------------------------------------- */
public ParameterAnnotationData(ClassData cls, boolean invisible) {
this.cls = cls;
this.invisible = invisible;
}
public int numParams() {
if (array == null) {
return 0;
}
return array.size();
}
public ArrayList<AnnotationData> get(int i) {
return array.get(i);
}
public void read(DataInputStream in) throws IOException {
int numParams = in.readByte();
TraceUtils.traceln(" ParameterAnnotationData[" + numParams + "]");
array = new ArrayList<>(numParams);
for (int paramNum = 0; paramNum < numParams; paramNum++) {
int numAnnots = in.readShort();
TraceUtils.traceln(" Param#[" + paramNum + "]: numAnnots=" + numAnnots);
if (numAnnots > 0) {
// read annotation
ArrayList<AnnotationData> p_annots = new ArrayList<>(numAnnots);
for (int annotIndex = 0; annotIndex < numAnnots; annotIndex++) {
AnnotationData annot = new AnnotationData(invisible, cls);
annot.read(in);
p_annots.add(annot);
}
array.add(paramNum, p_annots);
} else {
array.add(paramNum, null);
}
}
}
// Don't need to do this --
// we need to print annotations (both vis and invisible) per each param number
public void print(PrintWriter out, String tab) {
if (array != null && array.size() > 0) {
out.println();
int paramNum = 0;
for (ArrayList<AnnotationData> p_annot : array) {
if (p_annot != null && p_annot.size() > 0) {
out.print("\t" + paramNum + ": ");
boolean firstTime = true;
for (AnnotationData annot : p_annot) {
if (!firstTime) {
out.print("\t ");
}
annot.print(out, initialTab);
firstTime = false;
}
}
paramNum += 1;
out.println();
}
}
}
}

View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.asmutils.HexUtils;
import static org.openjdk.asmtools.jasm.Tables.*;
import java.io.DataInputStream;
import java.io.IOException;
/**
* represents one entry of StackMap attribute
*/
class StackMapData {
/*-------------------------------------------------------- */
/* StackMapData Fields */
static int prevFramePC = 0;
boolean isStackMapTable = false;
StackMapFrameType stackFrameType = null;
int start_pc;
int[] lockMap;
int[] stackMap;
/*-------------------------------------------------------- */
public StackMapData() {
}
public StackMapData(CodeData code, DataInputStream in) throws IOException {
start_pc = in.readUnsignedShort();
TraceUtils.trace(" stack_map_entry:pc=" + start_pc);
TraceUtils.trace(" numloc=");
lockMap = readMap(code, in);
TraceUtils.trace(" numstack=");
stackMap = readMap(code, in);
TraceUtils.traceln("");
}
public StackMapData(CodeData code, DataInputStream in,
boolean isStackMapTable) throws IOException {
this.isStackMapTable = isStackMapTable;
int ft_val = in.readUnsignedByte();
StackMapFrameType frame_type = stackMapFrameType(ft_val);
int offset = 0;
switch (frame_type) {
case SAME_FRAME:
// type is same_frame;
TraceUtils.trace(" same_frame=" + ft_val);
TraceUtils.traceln("");
offset = ft_val;
break;
case SAME_FRAME_EX:
// type is same_frame_extended;
TraceUtils.trace(" same_frame_extended=" + ft_val);
TraceUtils.traceln("");
offset = in.readUnsignedShort();
TraceUtils.trace(" offset=" + offset);
break;
case SAME_LOCALS_1_STACK_ITEM_FRAME:
// type is same_locals_1_stack_item_frame
TraceUtils.trace(" same_locals_1_stack_item_frame=" + ft_val);
offset = ft_val - 64;
TraceUtils.trace(" offset=" + offset);
// read additional single stack element
TraceUtils.trace(" numstack=");
stackMap = readMapElements(code, in, 1);
TraceUtils.traceln("");
break;
case SAME_LOCALS_1_STACK_ITEM_EXTENDED_FRAME:
// type is same_locals_1_stack_item_frame_extended
TraceUtils.trace(" same_locals_1_stack_item_frame_extended=" + ft_val);
offset = in.readUnsignedShort();
TraceUtils.trace(" offset=" + offset);
// read additional single stack element
TraceUtils.trace(" numstack=");
stackMap = readMapElements(code, in, 1);
TraceUtils.traceln("");
break;
case CHOP_1_FRAME:
case CHOP_2_FRAME:
case CHOP_3_FRAME:
// type is chop_frame
TraceUtils.trace(" chop_frame=" + ft_val);
TraceUtils.traceln("");
offset = in.readUnsignedShort();
TraceUtils.trace(" offset=" + offset);
break;
case APPEND_FRAME:
// type is append_frame
TraceUtils.trace(" append_frame=" + ft_val);
offset = in.readUnsignedShort();
TraceUtils.trace(" offset=" + offset);
// read additional locals
TraceUtils.trace(" numloc=");
lockMap = readMapElements(code, in, ft_val - 251);
TraceUtils.traceln("");
break;
case FULL_FRAME:
// type is full_frame
TraceUtils.trace(" full_frame=" + ft_val);
offset = in.readUnsignedShort();
TraceUtils.trace(" offset=" + offset);
TraceUtils.trace(" numloc=");
lockMap = readMap(code, in);
TraceUtils.trace(" numstack=");
stackMap = readMap(code, in);
TraceUtils.traceln("");
break;
default:
TraceUtils.trace("incorrect frame_type argument");
}
stackFrameType = frame_type;
start_pc = prevFramePC == 0 ? offset : prevFramePC + offset + 1;
prevFramePC = start_pc;
}
private int[] readMap(CodeData code, DataInputStream in) throws IOException {
int num = in.readUnsignedShort();
TraceUtils.trace("" + num);
return readMapElements(code, in, num);
}
private int[] readMapElements(CodeData code, DataInputStream in, int num) throws IOException {
int[] map = new int[num];
for (int k = 0; k < num; k++) {
int mt_val = in.readUnsignedByte();
StackMapType maptype = stackMapType(mt_val);
switch (maptype) {
case ITEM_Object:
mt_val = mt_val | (in.readUnsignedShort() << 8);
break;
case ITEM_NewObject: {
int pc = in.readUnsignedShort();
code.get_iAtt(pc).referred = true;
mt_val = mt_val | (pc << 8);
}
}
map[k] = mt_val;
TraceUtils.trace(" " + HexUtils.toHex(mt_val));
}
return map;
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
/**
*
*/
public class TextLines {
/*-------------------------------------------------------- */
/* TextLines Fields */
byte data[];
// ends[k] points to the end of k-th line
ArrayList<Integer> ends = new ArrayList<>(60);
public int length;
/*-------------------------------------------------------- */
public TextLines() {
}
public TextLines(String textfilename) throws IOException {
read(textfilename);
}
private void read(String textfilename) throws IOException {
FileInputStream in = new FileInputStream(textfilename);
data = new byte[in.available()];
in.read(data);
in.close();
ends.add(-1);
for (int k = 0; k < data.length; k++) {
if (data[k] == '\n') {
ends.add(k);
}
}
length = ends.size(); // but if text is empty??
}
public String getLine(int linenumber) {
int entry = linenumber - 1;
int start;
int end;
ends.add(entry);
start = ends.size() + 1;
searchEnd:
for (end = start; end < data.length; end++) {
switch (data[end]) {
case '\n':
case '\r':
break searchEnd;
}
}
//System.out.println("start="+start+" end="+end);
return new String(data, start, end - start);
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
/**
*
*/
public class TraceUtils {
/* ====================================================== */
public static void trace(String s) {
if (!(Options.OptionObject()).debug()) {
return;
}
System.out.print(s);
}
public static void traceln(String s) {
if (!(Options.OptionObject()).debug()) {
return;
}
System.out.println(s);
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import java.io.DataInputStream;
import java.io.IOException;
/**
*
*/
class TrapData {
short start_pc, end_pc, handler_pc, catch_cpx;
int num;
public TrapData(DataInputStream in, int num) throws IOException {
this.num = num;
start_pc = in.readShort();
end_pc = in.readShort();
handler_pc = in.readShort();
catch_cpx = in.readShort();
}
/* returns recommended identifier
*/
public String ident() {
return "t" + num;
}
}

View File

@ -0,0 +1,326 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import static org.openjdk.asmtools.jasm.TypeAnnotationUtils.*;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
* Type Annotation data is a specific kind of AnnotationData. As well as the normal data
* items needed to present an annotation, Type annotations require a TargetInfo
* descriptor. This descriptor is based on a TargetType, and it optionally may contain a
* location descriptor (when the Type is embedded in a collection).
*
* The TypeAnnotationData class is based on JDis's AnnotationData class, and contains the
* (jasm) class for representing TargetInfo.
*/
public class TypeAnnotationData extends AnnotationData {
private TargetInfo target_info;
private ArrayList<TypePathEntry> target_path;
private static TTVis TT_Visitor = new TTVis();
public TypeAnnotationData(boolean invisible, ClassData cls) {
super(invisible, cls);
target_info = null;
visAnnotToken = "@T+";
invAnnotToken = "@T-";
dataName = "TypeAnnotationData";
}
@Override
public void read(DataInputStream in) throws IOException {
super.read(in);
// read everything related to the Type Annotation
// target type tag
// KTL 1/10/13 (changed short-> byte for latest spec rev)
// int tt = (char) in.readUnsignedShort(); // cast to introduce signedness
int tt = (byte) in.readUnsignedByte(); // cast to introduce signedness
Integer ttInt = new Integer(tt);
TargetType ttype;
ttype = targetTypeEnum(ttInt);
if (ttype == null) {
// Throw some kind of error for bad target type index
throw new IOException("Bad target type: " + tt + " in TypeAnnotationData");
}
// read the target info
TT_Visitor.init(in);
TT_Visitor.visitExcept(ttype);
target_info = TT_Visitor.getTargetInfo();
// read the target path info
int len = in.readUnsignedShort();
target_path = new ArrayList<>(len);
TraceUtils.traceln(" --------- [TypeAnnotationData.read]: Reading Location (length = " + len + ").");
TraceUtils.trace(" --------- [TypeAnnotationData.read]: [ ");
for (int i = 0; i < len; i++) {
int pathType = in.readUnsignedByte();
String pk = (getPathKind(pathType)).parsekey();
char pathArgIndex = (char) in.readUnsignedByte();
target_path.add(new TypePathEntry(pathType, pathArgIndex));
TraceUtils.trace(" " + pk + "(" + pathType + "," + pathArgIndex + "), ");
}
TraceUtils.traceln("] ");
// target_info.setLocation(location);
}
@Override
protected void printBody(PrintWriter out, String tab) {
// For a type annotation, print out brackets,
// print out the (regular) annotation name/value pairs,
// then print out the target types.
out.print(" {");
super.printBody(out, tab);
target_info.print(out, tab);
printPath(out, tab);
out.print("}");
}
protected void printPath(PrintWriter out, String tab) {
// For a type annotation, print out brackets,
// print out the (regular) annotation name/value pairs,
// then print out the target types.
out.print(" {");
boolean first = true;
for (TypePathEntry tpe : target_path) {
if (!first) {
out.print(", ");
}
first = false;
out.print(tpe.toString());
}
target_info.print(out, tab);
printPath(out, tab);
out.print("}");
}
@Override
protected void _toString(StringBuilder sb) {
// sub-classes override this
sb.append(target_info.toString());
}
/**
* TTVis
*
* Target Type visitor, used for constructing the target-info within a type
* annotation. visitExcept() is the entry point. ti is the constructed target info.
*/
private static class TTVis extends TypeAnnotationTargetVisitor {
private TargetInfo ti = null;
private IOException IOProb = null;
private DataInputStream in;
public TTVis() {
}
public void init(DataInputStream in) {
this.in = in;
}
public int scanByteVal() {
int val = 0;
try {
val = in.readUnsignedByte();
} catch (IOException e) {
IOProb = e;
}
return val;
}
public int scanShortVal() {
int val = 0;
try {
val = in.readUnsignedShort();
} catch (IOException e) {
IOProb = e;
}
return val;
}
public int scanIntVal() {
int val = 0;
try {
val = in.readInt();
} catch (IOException e) {
IOProb = e;
}
return val;
}
//This is the entry point for a visitor that tunnels exceptions
public void visitExcept(TargetType tt) throws IOException {
IOProb = null;
ti = null;
TraceUtils.traceln(" Target Type: " + tt.parseKey());
visit(tt);
if (IOProb != null) {
throw IOProb;
}
}
public TargetInfo getTargetInfo() {
return ti;
}
private boolean error() {
return IOProb != null;
}
@Override
public void visit_type_param_target(TargetType tt) {
TraceUtils.trace(" Type Param Target: ");
int byteval = scanByteVal(); // param index
TraceUtils.traceln("{ param_index: " + byteval + "}");
if (!error()) {
ti = new typeparam_target(tt, byteval);
}
}
@Override
public void visit_supertype_target(TargetType tt) {
TraceUtils.trace(" SuperType Target: ");
int shortval = scanShortVal(); // type index
TraceUtils.traceln("{ type_index: " + shortval + "}");
if (!error()) {
ti = new supertype_target(tt, shortval);
}
}
@Override
public void visit_typeparam_bound_target(TargetType tt) {
TraceUtils.trace(" TypeParam Bound Target: ");
int byteval1 = scanByteVal(); // param index
if (error()) {
return;
}
int byteval2 = scanByteVal(); // bound index
if (error()) {
return;
}
TraceUtils.traceln("{ param_index: " + byteval1 + " bound_index: " + byteval2 + "}");
ti = new typeparam_bound_target(tt, byteval1, byteval2);
}
@Override
public void visit_empty_target(TargetType tt) {
TraceUtils.traceln(" Empty Target: ");
if (!error()) {
ti = new empty_target(tt);
}
}
@Override
public void visit_methodformalparam_target(TargetType tt) {
TraceUtils.trace(" MethodFormalParam Target: ");
int byteval = scanByteVal(); // param index
TraceUtils.traceln("{ param_index: " + byteval + "}");
if (!error()) {
ti = new methodformalparam_target(tt, byteval);
}
}
@Override
public void visit_throws_target(TargetType tt) {
TraceUtils.trace(" Throws Target: ");
int shortval = scanShortVal(); // exception index
TraceUtils.traceln("{ exception_index: " + shortval + "}");
if (!error()) {
ti = new throws_target(tt, shortval);
}
}
@Override
public void visit_localvar_target(TargetType tt) {
TraceUtils.traceln(" LocalVar Target: ");
int tblsize = scanShortVal(); // table length (short)
if (error()) {
return;
}
localvar_target locvartab = new localvar_target(tt, tblsize);
ti = locvartab;
for (int i = 0; i < tblsize; i++) {
int shortval1 = scanShortVal(); // startPC
if (error()) {
return;
}
int shortval2 = scanShortVal(); // length
if (error()) {
return;
}
int shortval3 = scanShortVal(); // CPX
TraceUtils.trace(" LocalVar[" + i + "]: ");
TraceUtils.traceln("{ startPC: " + shortval1 + ", length: " + shortval2 + ", CPX: " + shortval3 + "}");
locvartab.addEntry(shortval1, shortval2, shortval3);
}
}
@Override
public void visit_catch_target(TargetType tt) {
TraceUtils.trace(" Catch Target: ");
int shortval = scanShortVal(); // catch index
TraceUtils.traceln("{ catch_index: " + shortval + "}");
if (!error()) {
ti = new catch_target(tt, shortval);
}
}
@Override
public void visit_offset_target(TargetType tt) {
TraceUtils.trace(" Offset Target: ");
int shortval = scanShortVal(); // offset index
TraceUtils.traceln("{ offset_index: " + shortval + "}");
if (!error()) {
ti = new offset_target(tt, shortval);
}
}
@Override
public void visit_typearg_target(TargetType tt) {
TraceUtils.trace(" TypeArg Target: ");
int shortval = scanShortVal(); // offset
if (error()) {
return;
}
int byteval = scanByteVal(); // type index
if (error()) {
return;
}
TraceUtils.traceln("{ offset: " + shortval + " type_index: " + byteval + "}");
ti = new typearg_target(tt, shortval, byteval);
}
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
/**
*
*/
public class Utils {
static public String javaName(String name) {
if (name == null) {
return "null";
}
int len = name.length();
if (len == 0) {
return "\"\"";
}
char cc = '/';
fullname:
{ // xxx/yyy/zzz
for (int k = 0; k < len; k++) {
char c = name.charAt(k);
if (cc == '/') {
if (!Character.isJavaIdentifierStart(c) && c != '-') {
break fullname;
}
} else if (c != '/') {
if (!Character.isJavaIdentifierPart(c) && c != '-') {
break fullname;
}
}
cc = c;
}
return name;
}
return "\"" + name + "\"";
}
static public boolean isClassArrayDescriptor(String name) {
boolean retval = false;
if (name != null) {
if (name.startsWith("[")) {
retval = true;
}
}
return retval;
}
}

View File

@ -0,0 +1,40 @@
# Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
jdis.usage=\
Usage: java -jar asmtools.jar jdis [options] FILE.class...\n\
where possible options include:
jdis.opt.g=\
\ -g detailed output format
jdis.opt.sl=\
\ -sl source lines in comments
jdis.opt.v=\
\ -v debug mode
jdis.opt.hx=\
\ -hx hexadecimal numbers
jdis.opt.version=\
\ -version prints the version info
jdis.error.invalid_option=invalid option: {0}
jdis.error.cannot_read=cannot read {0}
jdis.error.fatal_error=fatal error in file: {0}
jdis.error.fatal_exception=fatal exception in file: {0}

View File

@ -0,0 +1,238 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.jasm.RuntimeConstants;
import static org.openjdk.asmtools.jasm.Tables.*;
import static org.openjdk.asmtools.jasm.OpcodeTables.*;
import org.openjdk.asmtools.jasm.Tables;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
* instruction attributes
*/
class iAtt {
/*-------------------------------------------------------- */
/* iAtt Fields */
private Options options;
short lnum = 0;
boolean referred = false; // from some other instruction
ArrayList<CodeData.LocVarData> vars;
ArrayList<CodeData.LocVarData> endvars;
ArrayList<TrapData> handlers;
ArrayList<TrapData> traps;
ArrayList<TrapData> endtraps;
StackMapData stackMapEntry;
CodeData code;
ClassData cls;
PrintWriter out; // =cls.out;
/*-------------------------------------------------------- */
public iAtt(CodeData code) {
this.code = code;
this.cls = code.meth.cls;
out = cls.out;
options = cls.options;
}
void add_var(CodeData.LocVarData var) {
if (vars == null) {
vars = new ArrayList<>(4);
}
vars.add(var);
}
void add_endvar(CodeData.LocVarData endvar) {
if (endvars == null) {
endvars = new ArrayList<>(4);
}
endvars.add(endvar);
}
void add_trap(TrapData trap) {
if (traps == null) {
traps = new ArrayList<>(4);
}
traps.add(trap);
}
void add_endtrap(TrapData endtrap) {
if (endtraps == null) {
endtraps = new ArrayList<>(4);
}
endtraps.add(endtrap);
}
void add_handler(TrapData endtrap) {
if (handlers == null) {
handlers = new ArrayList<>(4);
}
handlers.add(endtrap);
}
public void printEnds() throws IOException {
// prints additional information for instruction:
// end of local variable and trap scopes;
int len;
if ((endvars != null) && (options.contains(Options.PR.VAR))) {
len = endvars.size() - 1;
out.print("\t\tendvar");
for (CodeData.LocVarData line : endvars) {
out.print(" " + line.slot);
if (len-- > 0) {
out.print(",");
}
}
out.println(";");
}
if (endtraps != null) {
len = endtraps.size() - 1;
out.print("\t\tendtry");
for (TrapData line : endtraps) {
out.print(" " + line.ident());
if (len-- > 0) {
out.print(",");
}
}
out.println(";");
}
}
public void printBegins()
throws IOException {
// prints additional information for instruction:
// source line number;
// start of exception handler;
// begin of locvar and trap scopes;
boolean eitherOpt = options.contains(Options.PR.LNT) || options.contains(Options.PR.SRC);
boolean bothOpt = options.contains(Options.PR.LNT) && options.contains(Options.PR.SRC);
int k;
if ((lnum != 0) && eitherOpt) {
if (bothOpt) {
out.println("// " + lnum + ": " + cls.getSrcLine(lnum));
} else if (options.contains(Options.PR.LNT)) {
out.print(lnum);
} else if (options.contains(Options.PR.SRC)) {
out.println("// " + cls.getSrcLine(lnum));
}
}
out.print("\t");
if (handlers != null) {
for (TrapData line : handlers) {
out.print("\tcatch " + line.ident());
out.print(" " + cls.pool.getClassName(line.catch_cpx) + ";\n\t");
}
}
if (traps != null) {
int len = traps.size() - 1;
out.print("\ttry");
for (TrapData line : traps) {
out.print(" " + line.ident());
if (len-- > 0) {
out.print(",");
}
}
out.print(";\n\t");
}
if ((vars != null) && options.contains(Options.PR.VAR)) {
for (CodeData.LocVarData line : vars) {
out.println("\tvar " + line.slot + "; // " + cls.pool.getName(line.name_cpx) + ":" + cls.pool.getName(line.sig_cpx));
out.print("\t");
}
}
}
public void printMapList(int[] map) {
boolean pr_cpx = options.contains(Options.PR.CPX);
for (int k = 0; k < map.length; k++) {
int fullmaptype = map[k];
int mt_val = fullmaptype & 0xFF;
StackMapType maptype = stackMapType(mt_val);
int argument = fullmaptype >> 8;
switch (maptype) {
case ITEM_Object:
if (pr_cpx) {
out.print(" #" + argument);
} else {
out.print(" ");
cls.pool.PrintConstant(out, argument);
}
break;
case ITEM_NewObject:
if (pr_cpx) {
out.print(" " + mt_val);
} else {
out.print(" " + maptype.printval());
}
out.print(" " + code.meth.lP + argument);
break;
default:
if (pr_cpx) {
out.print(" " + mt_val);
} else {
out.print(" " + maptype.printval());
}
}
out.print((k == (map.length - 1) ? ';' : ','));
}
}
public void printStackMap() throws IOException {
if (stackMapEntry == null) {
return;
}
boolean printed = false;
if (stackMapEntry.stackFrameType != null) {
out.print(Opcode.opc_stack_frame_type.parsekey()); // opcNamesTab[opc_stackframetype]);
out.print(" " + stackMapEntry.stackFrameType.parsekey() + ';');
out.print("\n\t\t");
printed = true;
}
int[] map = stackMapEntry.lockMap;
if ((map != null) && (map.length > 0)) {
out.print(Opcode.opc_locals_map.parsekey());
printMapList(map);
out.print("\n\t\t");
printed = true;
}
map = stackMapEntry.stackMap;
if ((map != null) && (map.length > 0)) {
out.print(Opcode.opc_stack_map.parsekey());
printMapList(map);
out.print("\n\t\t");
printed = true;
}
if (!printed) {
// empty attribute should be printed anyway - it should not
// be eliminated after jdis/jasm cycle
out.print(Opcode.opc_locals_map.parsekey() + " ;\n\t\t");
}
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
/**
*
*/
public class uEscWriter extends Writer {
/*-------------------------------------------------------- */
/* uEscWriter Fields */
static final char[] hexTable = "0123456789ABCDEF".toCharArray();
OutputStream out;
byte[] tmpl;
/*-------------------------------------------------------- */
public uEscWriter(OutputStream out) {
this.out = out;
tmpl = new byte[6];
tmpl[0] = (byte) '\\';
tmpl[1] = (byte) 'u';
}
@Override
public synchronized void write(int c) throws IOException {
if (c < 128) {
out.write(c);
return;
}
// write \udddd
byte[] tmpll = tmpl;
for (int k = 3; k >= 0; k--) {
tmpll[5 - k] = (byte) hexTable[(c >> 4 * k) & 0xF];
}
out.write(tmpll, 0, 6);
}
@Override
public synchronized void write(char[] cc, int ofs, int len) throws IOException {
for (int k = ofs; k < len; k++) {
write(cc[k]);
}
}
@Override
public void flush() {
}
@Override
public void close() {
}
} // end uEscWriter

View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.util;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* A class that lazily opens a package-specific resource bundle containing localization
* data for a class.
*/
public class I18NResourceBundle extends ResourceBundle {
/**
* Get a package-specific resource bundle for a class containing localization data.
* The bundle is named i18n.properties in the same package as the given class.
*
* @param c the class for which to obtain the resource bundle
* @return the appropriate resource bundle for the class
*/
public static I18NResourceBundle getBundleForClass(Class c) {
String cn = c.getName();
int dot = cn.lastIndexOf('.');
String rn = (dot == -1 ? "i18n" : cn.substring(0, dot) + ".i18n");
return new I18NResourceBundle(rn, c.getClassLoader());
}
/**
* Create a resource bundle for the given name. The actual resource bundle will not be
* loaded until it is needed.
*
* @param name The name of the actual resource bundle to use.
*/
private I18NResourceBundle(String name, ClassLoader cl) {
this.name = name;
this.classLoader = cl;
}
/**
* Get an entry from the resource bundle. If the resource cannot be found, a message
* is printed to the console and the result will be a string containing the method
* parameters.
*
* @param key the name of the entry to be returned
* @param arg an argument to be formatted into the result using
* {@link java.text.MessageFormat#format}
* @return the formatted string
*/
public String getString(String key, Object arg) {
return getString(key, new Object[]{arg});
}
/**
* Get an entry from the resource bundle. If the resource cannot be found, a message
* is printed to the console and the result will be a string containing the method
* parameters.
*
* @param key the name of the entry to be returned
* @param args an array of arguments to be formatted into the result using
* {@link java.text.MessageFormat#format}
* @return the formatted string
*/
public String getString(String key, Object... args) {
try {
return MessageFormat.format(getString(key), args);
} catch (MissingResourceException e) {
System.err.println("WARNING: missing resource: " + key + " for " + name);
StringBuffer sb = new StringBuffer(key);
for (int i = 0; i < args.length; i++) {
sb.append('\n');
sb.append(args.toString());
}
return sb.toString();
}
}
/**
* Get an entry from the bundle, returning null if it is not found.
*
* @param key the name of the entry to be returned
* @return the value of the entry, or null if it is not found.
*/
public String getOptionalString(String key) {
if (delegate == null) {
delegate = ResourceBundle.getBundle(name, Locale.getDefault(), classLoader);
}
try {
String s = (String) (delegate.getObject(key));
if (s != null) {
System.out.println("i18n: " + key);
}
return s;
} catch (MissingResourceException e) {
return null;
}
}
/**
* A required internal method for ResourceBundle. Load the actual resource bundle, if
* it has not yet been loaded, then hand the request off to that bundle. If the
* resource cannot be found, a message is printed to the console and the result will
* be the original key.
*/
protected Object handleGetObject(String key) throws MissingResourceException {
try {
if (delegate == null) {
delegate = ResourceBundle.getBundle(name, Locale.getDefault(), classLoader);
}
return delegate.getObject(key);
} catch (MissingResourceException e) {
System.err.println("WARNING: missing resource: " + key + " for " + name);
return key;
}
}
/**
* A required internal method for ResourceBundle. Load the actual resource bundle, if
* it has not yet been loaded, then hand the request off to that bundle.
*/
public Enumeration getKeys() {
if (delegate == null) {
delegate = ResourceBundle.getBundle(name);
}
return delegate.getKeys();
}
/**
* Returns the name of this bundle (useful for methods using bundle name instead of
* instance, such as <code>Logger</code> creation,
*
* @return the name of this resource bundle
*/
public String getName() {
return name;
}
private String name;
private ResourceBundle delegate;
private ClassLoader classLoader;
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.util;
import java.util.ResourceBundle;
/**
* Class providing an access to the product info.
* <i>productinfo.properties</i> will be generated during the build
*/
public class ProductInfo {
static {
init();
}
;
/**
* Returns the value of the specified property
*/
public static String getProperty(String propName) {
try {
return bundle.getString(propName);
} catch (java.util.MissingResourceException e) {
return null;
}
}
/**
* Version of the product in the short format, like 5.0
*/
public static final String VERSION = version();
/**
* Full version of the product, including build number and date of creation
*/
public static final String FULL_VERSION = fullVersion();
private static final String BUNDLE_NAME = "org.openjdk.asmtools.util.productinfo";
private static ResourceBundle bundle;
/**
* Initializes the bundle
*/
private static void init() {
bundle = ResourceBundle.getBundle(BUNDLE_NAME);
}
private static String version() {
return getProperty("PRODUCT_VERSION");
}
private static String fullVersion() {
return getProperty("PRODUCT_NAME_LONG") + ", version " + version()
+ " " + getProperty("PRODUCT_MILESTONE")
+ " " + getProperty("PRODUCT_BUILDNUMBER")
+ " (" + getProperty("PRODUCT_DATE") + ")";
}
}

View File

@ -0,0 +1,27 @@
# Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
PRODUCT_NAME = %%PRODUCT_NAME%%
PRODUCT_VERSION = %%PRODUCT_VERSION%%
PRODUCT_MILESTONE = %%PRODUCT_MILESTONE%%
PRODUCT_BUILDNUMBER = %%PRODUCT_BUILDNUMBER%%
PRODUCT_NAME_LONG = %%PRODUCT_NAME_LONG%%
PRODUCT_DATE = %%BUILD_DATE%%