serp.bytecode.visitor.PrettyPrintVisitor Maven / Gradle / Ivy
package serp.bytecode.visitor;
import java.io.*;
import serp.bytecode.*;
import serp.bytecode.lowlevel.*;
/**
* Visitor type that outputs a detailed, formatted document of the
* visited entity; similar to the javap -c command but more detailed.
*
* @author Abe White
*/
public class PrettyPrintVisitor extends BCVisitor {
private PrintWriter _out = null;
private String _prefix = "";
/**
* Constructor; all pritning will go to stdout.
*/
public PrettyPrintVisitor() {
_out = new PrintWriter(System.out);
}
/**
* Constructor.
*
* @param out the stream to print to
*/
public PrettyPrintVisitor(PrintWriter out) {
_out = out;
}
/**
* Invoke with the class or file names to pretty print; the
* functionality is similar to the javap -c command, but more
* detailed.
*/
public static void main(String[] args)
throws ClassNotFoundException, IOException {
if (args.length == 0) {
System.err.println("Usage: java "
+ PrettyPrintVisitor.class.getName()
+ " +");
System.exit(1);
}
PrettyPrintVisitor ppv = new PrettyPrintVisitor();
Project project = new Project();
BCClass type;
for (int i = 0; i < args.length; i++) {
if (args[i].endsWith(".class"))
type = project.loadClass(new File(args[i]));
else
type = project.loadClass(Class.forName(args[i], false,
PrettyPrintVisitor.class.getClassLoader()));
ppv.visit(type);
}
}
public void visit(VisitAcceptor entity) {
super.visit(entity);
_out.flush();
}
public void enterProject(Project obj) {
openBlock("Project");
println("name=" + obj.getName());
}
public void exitProject(Project obj) {
closeBlock();
}
public void enterBCClass(BCClass obj) {
openBlock("Class");
println("magic=" + obj.getMagic());
println("minor=" + obj.getMinorVersion());
println("major=" + obj.getMajorVersion());
println("access=" + obj.getAccessFlags());
println("name=" + obj.getIndex() + " <" + obj.getName() + ">");
println("super=" + obj.getSuperclassIndex() + " <" +
obj.getSuperclassName() + ">");
int[] indexes = obj.getDeclaredInterfaceIndexes();
String[] names = obj.getDeclaredInterfaceNames();
for (int i = 0; i < indexes.length; i++)
println("interface=" + indexes[i] + " <" + names[i] + ">");
}
public void exitBCClass(BCClass obj) {
closeBlock();
}
public void enterBCField(BCField obj) {
openBlock("Field");
println("access=" + obj.getAccessFlags());
println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
println("type=" + obj.getDescriptorIndex() + " <" + obj.getTypeName()
+ ">");
}
public void exitBCField(BCField obj) {
closeBlock();
}
public void enterBCMethod(BCMethod obj) {
openBlock("Method");
println("access=" + obj.getAccessFlags());
println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
println("descriptor=" + obj.getDescriptorIndex());
println("return=" + obj.getReturnName());
String[] params = obj.getParamNames();
for (int i = 0; i < params.length; i++)
println("param=" + params[i]);
}
public void exitBCMethod(BCMethod obj) {
closeBlock();
}
public void enterAttribute(Attribute obj) {
openBlock(obj.getName());
}
public void exitAttribute(Attribute obj) {
closeBlock();
}
public void enterConstantValue(ConstantValue obj) {
println("value=" + obj.getValueIndex() + " <" + obj.getTypeName() +
"=" + obj.getValue() + ">");
}
public void enterExceptions(Exceptions obj) {
int[] indexes = obj.getExceptionIndexes();
String[] names = obj.getExceptionNames();
for (int i = 0; i < indexes.length; i++)
println("exception=" + indexes[i] + " <" + names[i] + ">");
}
public void enterSourceFile(SourceFile obj) {
println("source=" + obj.getFileIndex() + " <" + obj.getFileName()
+ ">");
}
public void enterCode(Code obj) {
println("maxStack=" + obj.getMaxStack());
println("maxLocals=" + obj.getMaxLocals());
println("");
}
public void enterExceptionHandler(ExceptionHandler obj) {
openBlock("ExceptionHandler");
println("startPc=" + obj.getTryStartPc());
println("endPc=" + obj.getTryEndPc());
println("handlerPc=" + obj.getHandlerStartPc());
println("catch=" + obj.getCatchIndex() + " <" + obj.getCatchName()
+ ">");
}
public void exitExceptionHandler(ExceptionHandler obj) {
closeBlock();
}
public void enterInnerClass(InnerClass obj) {
openBlock("InnerClass");
println("access=" + obj.getAccessFlags());
println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
println("type=" + obj.getTypeIndex() + "<" + obj.getTypeName() + ">");
println("declarer=" + obj.getDeclarerIndex() + "<"
+ obj.getDeclarerName() + ">");
}
public void exitInnerClass(InnerClass obj) {
closeBlock();
}
public void enterLineNumber(LineNumber obj) {
openBlock("LineNumber");
println("startPc=" + obj.getStartPc());
println("line=" + obj.getLine());
}
public void exitLineNumber(LineNumber obj) {
closeBlock();
}
public void enterLocalVariable(LocalVariable obj) {
openBlock("LocalVariable");
println("startPc=" + obj.getStartPc());
println("length=" + obj.getLength());
println("local=" + obj.getLocal());
println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
println("type=" + obj.getTypeIndex() + " <" + obj.getTypeName() + ">");
}
public void exitLocalVariable(LocalVariable obj) {
closeBlock();
}
public void enterLocalVariableType(LocalVariableType obj) {
openBlock("LocalVariableType");
println("startPc=" + obj.getStartPc());
println("length=" + obj.getLength());
println("local=" + obj.getLocal());
println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
println("signature=" + obj.getTypeIndex() + " <" + obj.getTypeName()
+ ">");
}
public void exitLocalVariableType(LocalVariableType obj) {
closeBlock();
}
public void enterAnnotation(Annotation obj) {
openBlock("Annotation");
println("type=" + obj.getTypeIndex() + " <" + obj.getTypeName() + ">");
}
public void exitAnnotation(Annotation obj) {
closeBlock();
}
public void enterAnnotationProperty(Annotation.Property obj) {
openBlock("Property");
println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
Object val = obj.getValue();
if (val instanceof Object[]) {
Object[] arr = (Object[]) val;
for (int i = 0; i < arr.length; i++)
printAnnotationPropertyValue(arr[i]);
} else
printAnnotationPropertyValue(val);
}
private void printAnnotationPropertyValue(Object obj) {
if (obj == null)
println("value=null");
else if (obj instanceof Annotation) {
_out.print(_prefix);
_out.print("value=");
((Annotation) obj).acceptVisit(this);
} else
println("value=(" + obj.getClass().getName() + ") " + obj);
}
public void exitAnnotationProperty(Annotation.Property obj) {
closeBlock();
}
public void enterInstruction(Instruction obj) {
_out.print(_prefix + obj.getByteIndex() + " " + obj.getName() + " ");
}
public void exitInstruction(Instruction obj) {
_out.println();
}
public void enterClassInstruction(ClassInstruction obj) {
_out.print(obj.getTypeIndex() + " <" + obj.getTypeName() + ">");
}
public void enterConstantInstruction(ConstantInstruction obj) {
_out.print("<" + obj.getValue() + ">");
}
public void enterGetFieldInstruction(GetFieldInstruction obj) {
_out.print(obj.getFieldIndex() + " <" + obj.getFieldTypeName() + " "
+ obj.getFieldDeclarerName() + "." + obj.getFieldName() + ">");
}
public void enterIIncInstruction(IIncInstruction obj) {
_out.print(obj.getLocal() + " ");
if (obj.getIncrement() < 0)
_out.print("-");
_out.print(obj.getIncrement());
}
public void enterJumpInstruction(JumpInstruction obj) {
_out.print(obj.getOffset());
}
public void enterIfInstruction(IfInstruction obj) {
_out.print(obj.getOffset());
}
public void enterLoadInstruction(LoadInstruction obj) {
_out.print("<" + obj.getLocal() + ">");
}
public void enterLookupSwitchInstruction(LookupSwitchInstruction obj) {
_out.println();
_prefix += " ";
int[] offsets = obj.getOffsets();
int[] matches = obj.getMatches();
for (int i = 0; i < offsets.length; i++)
println("case " + matches[i] + "=" + offsets[i]);
_out.print(_prefix + "default=" + obj.getDefaultOffset());
_prefix = _prefix.substring(2);
}
public void enterMethodInstruction(MethodInstruction obj) {
_out.print(obj.getMethodIndex() + " <" + obj.getMethodReturnName()
+ " " + obj.getMethodDeclarerName() + "." + obj.getMethodName()
+ "(");
String[] params = obj.getMethodParamNames();
int dotIndex;
for (int i = 0; i < params.length; i++) {
dotIndex = params[i].lastIndexOf('.');
if (dotIndex != -1)
params[i] = params[i].substring(dotIndex + 1);
_out.print(params[i]);
if (i != (params.length - 1))
_out.print(", ");
}
_out.print(")>");
}
public void enterMultiANewArrayInstruction(MultiANewArrayInstruction obj) {
_out.print(obj.getTypeIndex() + " " + obj.getDimensions() + " <"
+ obj.getTypeName());
String post = "";
for (int i = 0; i < obj.getDimensions(); i++)
post += "[]";
_out.print(post + ">");
}
public void enterNewArrayInstruction(NewArrayInstruction obj) {
_out.print(obj.getTypeCode() + " <" + obj.getTypeName() + "[]>");
}
public void enterPutFieldInstruction(PutFieldInstruction obj) {
_out.print(obj.getFieldIndex() + " <" + obj.getFieldTypeName() + " "
+ obj.getFieldDeclarerName() + "." + obj.getFieldName() + ">");
}
public void enterRetInstruction(RetInstruction obj) {
_out.print(obj.getLocal());
}
public void enterStoreInstruction(StoreInstruction obj) {
_out.print("<" + obj.getLocal() + ">");
}
public void enterTableSwitchInstruction(TableSwitchInstruction obj) {
_out.println();
_prefix += " ";
println("low=" + obj.getLow());
println("high=" + obj.getHigh());
int[] offsets = obj.getOffsets();
for (int i = 0; i < offsets.length; i++)
println("case=" + offsets[i]);
_out.print(_prefix + "default=" + obj.getDefaultOffset());
_prefix = _prefix.substring(2);
}
public void enterWideInstruction(WideInstruction obj) {
int ins = obj.getInstruction();
_out.print(ins + " <" + Constants.OPCODE_NAMES[ins] + ">");
}
public void enterConstantPool(ConstantPool obj) {
openBlock("ConstantPool");
}
public void exitConstantPool(ConstantPool obj) {
closeBlock();
}
public void enterEntry(Entry obj) {
String name = obj.getClass().getName();
openBlock(obj.getIndex() + ": "
+ name.substring(name.lastIndexOf('.') + 1));
}
public void exitEntry(Entry obj) {
closeBlock();
}
public void enterClassEntry(ClassEntry obj) {
println("name=" + obj.getNameIndex());
}
public void enterDoubleEntry(DoubleEntry obj) {
println("value=" + obj.getValue());
}
public void enterFieldEntry(FieldEntry obj) {
println("class=" + obj.getClassIndex());
println("nameAndType=" + obj.getNameAndTypeIndex());
}
public void enterFloatEntry(FloatEntry obj) {
println("value=" + obj.getValue());
}
public void enterIntEntry(IntEntry obj) {
println("value=" + obj.getValue());
}
public void enterInterfaceMethodEntry(InterfaceMethodEntry obj) {
println("class=" + obj.getClassIndex());
println("nameAndType=" + obj.getNameAndTypeIndex());
}
public void enterLongEntry(LongEntry obj) {
println("value=" + obj.getValue());
}
public void enterMethodEntry(MethodEntry obj) {
println("class=" + obj.getClassIndex());
println("nameAndType=" + obj.getNameAndTypeIndex());
}
public void enterNameAndTypeEntry(NameAndTypeEntry obj) {
println("name=" + obj.getNameIndex());
println("descriptor=" + obj.getDescriptorIndex());
}
public void enterStringEntry(StringEntry obj) {
println("index=" + obj.getStringIndex());
}
public void enterUTF8Entry(UTF8Entry obj) {
println("value=" + obj.getValue());
}
private void println(String ln) {
_out.print(_prefix);
_out.println(ln);
}
private void openBlock(String name) {
println(name + " {");
_prefix += " ";
}
private void closeBlock() {
_prefix = _prefix.substring(2);
println("}");
}
}