asmtools/src/org/openjdk/asmtools/jcdec/Main.java

958 lines
36 KiB
Java

/*
* Copyright (c) 2009, 2017, 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_JAVACARD_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);
}
}