/*
* Copyright (C) 2012 Sony Mobile Communications AB
*
* This file is part of ApkAnalyser.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package codegen;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import java.util.TreeMap;
import codegen.Parser.Identifier;
public class BytecodeTableGenerator
{
static String[] REFERENCE =
{
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc1.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc2.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc3.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc4.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc5.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc6.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc7.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc8.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc9.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc10.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc11.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc12.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc13.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc14.html",
"http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc15.html"
};
static final String FORMAT_ID_PRE = "<p><b>Format</b><br>";
static final String FORMAT_ID_IDX_PRE = "<i>";
static final String FORMAT_ID_IDX_POST = "</i>";
static final String FORMAT_ID_POST = "</Table>";
static final String FORMS_ID_PRE = "<p><b>Forms</b><br>";
static final String FORMS_ID_IDX_NAME_PRE = "<i>";
static final String FORMS_ID_IDX_NAME_POST = "</i>";
static final String FORMS_ID_IDX_CODE_PRE = "=";
static final String FORMS_ID_IDX_CODE_POST = "(0x";
static final String FORMS_ID_POST = "<p><b>Operand Stack</b><br>";
static final Parser.Identifier FORMAT =
new Parser.Identifier(FORMAT_ID_PRE, FORMAT_ID_POST, false, "FORMAT");
static final Parser.Identifier FORMAT_IDX =
new Parser.Identifier(FORMAT_ID_IDX_PRE, FORMAT_ID_IDX_POST, true, "FORMAT_IDX");
static final Parser.Identifier FORMS =
new Parser.Identifier(FORMS_ID_PRE, FORMS_ID_POST, false, "FORMS");
static final Parser.Identifier FORMS_NC_MULT =
new Parser.Identifier(true, "FORMS_NC_MULT");
static final Parser.Identifier FORMS_NAME =
new Parser.Identifier(FORMS_ID_IDX_NAME_PRE, FORMS_ID_IDX_NAME_POST, false, "FORMS_NAME");
static final Parser.Identifier FORMS_CODE =
new Parser.Identifier(FORMS_ID_IDX_CODE_PRE, FORMS_ID_IDX_CODE_POST, false, "FORMS_CODE");
static Parser m_parser;
static ParserReporter m_reporter = new ByteCodeReporter();
static Map<Integer, ByteCode> m_byteCodeMap = new TreeMap<Integer, ByteCode>();
public static void main(String[] args) throws Exception
{
FORMAT.add(FORMAT_IDX);
FORMS.add(FORMS_NC_MULT);
FORMS_NC_MULT.add(FORMS_NAME);
FORMS_NC_MULT.add(FORMS_CODE);
m_parser = new Parser();
m_parser.add(FORMAT);
m_parser.add(FORMS);
for (int i = 0; i < REFERENCE.length; i++)
{
URL url = new URL(REFERENCE[i]);
URLConnection urlconn = url.openConnection();
urlconn.connect();
InputStream is = (InputStream) urlconn.getContent();
parse(read(is));
}
printByteCodes();
}
public static void printByteCodes()
{
System.out.println(" public static final String OP_UNDEFINED = \"N/A\";");
System.out.println(" public static final int OP_UNDEFINED_LEN = 1;");
System.out.println();
System.out.println(" public static final String[] BC_OPCODES = {");
for (int i = 0; i < 256; i++)
{
ByteCode bc = m_byteCodeMap.get(new Integer(i));
if (bc == null) {
System.out.print(" OP_UNDEFINED + \"[" + Integer.toHexString(i) + "]\"");
} else {
System.out.print(" \"" + bc.instr + "\"");
}
if (i < 255) {
System.out.print(",");
}
if (bc != null)
{
System.out.print("\t\t");
System.out.print("// " + bc.length);
}
System.out.println();
}
System.out.println(" };");
System.out.println(" public static final int[] BC_LENGTHS = {");
for (int i = 0; i < 256; i++)
{
ByteCode bc = m_byteCodeMap.get(new Integer(i));
if (bc == null) {
System.out.print(" OP_UNDEFINED_LEN");
} else {
System.out.print(" " + bc.length);
}
if (i < 255) {
System.out.print(",");
}
if (bc != null)
{
System.out.print("\t\t");
System.out.print("// " + bc.instr);
}
System.out.println();
}
System.out.println(" };");
}
public static void parse(final StringBuffer sb)
{
m_parser.parse(m_reporter, sb);
}
public static StringBuffer read(InputStream is) throws Exception
{
StringBuffer sb = new StringBuffer();
int i = 0;
do
{
i = is.read();
if (i != -1)
{
sb.append((char) i);
}
} while (i != -1);
return sb;
}
static class ByteCodeReporter implements ParserReporter
{
boolean firstIndex = true;
int index = 0;
String name = null;
String code = null;
@Override
public void match(Identifier id, StringBuffer sb, int startIndex, int endIndex)
{
if (id == FORMAT_IDX)
{
System.err.println("FORMAT_IX :\t" + sb.substring(startIndex, endIndex));
if (firstIndex) {
index = 1;
} else {
index++;
}
firstIndex = false;
}
else
{
firstIndex = true;
}
if (id == FORMS_NAME)
{
System.err.println("FORMS_NAME:\t" + sb.substring(startIndex, endIndex));
name = sb.substring(startIndex, endIndex).trim();
}
else if (id == FORMS_CODE)
{
System.err.println("FORMS_CODE:\t" + sb.substring(startIndex, endIndex));
code = sb.substring(startIndex, endIndex);
int iCode = Integer.parseInt(code.trim());
m_byteCodeMap.put(new Integer(iCode), new ByteCode(name, iCode, index));
}
}
}
static class ByteCode
{
public String instr;
public int code;
public int length;
public ByteCode(String instr, int code, int length)
{
this.instr = instr;
this.code = code;
this.length = length;
}
}
}