Initial sources!
This commit is contained in:
parent
10f0060dba
commit
691a9f8de6
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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
|
@ -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
|
||||
};
|
||||
* */
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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 << 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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
@ -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
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
* */
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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})"
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 << 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
|
||||
|
|
@ -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 {
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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}
|
|
@ -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() + ">";
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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(";");
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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") + ")";
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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%%
|
Loading…
Reference in New Issue