/* This file is part of the db4o object database http://www.db4o.com
Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com
db4o is free software; you can redistribute it and/or modify it under
the terms of version 3 of the GNU General Public License as published
by the Free Software Foundation.
db4o 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
for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see http://www.gnu.org/licenses/. */
package EDU.purdue.cs.bloat.tree;
import java.io.*;
import java.util.*;
import EDU.purdue.cs.bloat.cfg.*;
/**
* PrintVistor traverses a Tree and prints some information about each visited
* Node to a stream.
*/
public class PrintVisitor extends TreeVisitor {
protected PrintWriter out; // The stream to which we are printing
/**
* Constructor. Prints to System.out.
*/
public PrintVisitor() {
this(System.out);
}
public PrintVisitor(final Writer out) {
this.out = new PrintWriter(out);
}
public PrintVisitor(final PrintStream out) {
this.out = new PrintWriter(out);
}
protected void println() {
out.println();
}
protected void println(final Object s) {
out.println(s);
}
protected void print(final Object s) {
out.print(s);
}
public void visitFlowGraph(final FlowGraph cfg) {
cfg.source().visit(this);
final Iterator e = cfg.trace().iterator();
while (e.hasNext()) {
final Block block = (Block) e.next();
block.visit(this);
}
cfg.sink().visit(this);
this.out.flush();
}
public void visitBlock(final Block block) {
println();
println(block);
final Handler handler = (Handler) block.graph().handlersMap()
.get(block);
if (handler != null) {
println("catches " + handler.catchType());
println("protects " + handler.protectedBlocks());
}
block.visitChildren(this);
}
public void visitExprStmt(final ExprStmt stmt) {
print("eval ");
stmt.expr().visit(this);
println();
}
public void visitIfZeroStmt(final IfZeroStmt stmt) {
print("if0 (");
stmt.expr().visit(this);
print(" ");
switch (stmt.comparison()) {
case IfStmt.EQ:
print("==");
break;
case IfStmt.NE:
print("!=");
break;
case IfStmt.GT:
print(">");
break;
case IfStmt.GE:
print(">=");
break;
case IfStmt.LT:
print("<");
break;
case IfStmt.LE:
print("<=");
break;
}
if (stmt.expr().type().isReference()) {
print(" null");
} else {
print(" 0");
}
print(") then " + stmt.trueTarget() + " else " + stmt.falseTarget());
println(" caught by " + stmt.catchTargets());
}
public void visitIfCmpStmt(final IfCmpStmt stmt) {
print("if (");
stmt.left().visit(this);
print(" ");
switch (stmt.comparison()) {
case IfStmt.EQ:
print("==");
break;
case IfStmt.NE:
print("!=");
break;
case IfStmt.GT:
print(">");
break;
case IfStmt.GE:
print(">=");
break;
case IfStmt.LT:
print("<");
break;
case IfStmt.LE:
print("<=");
break;
}
print(" ");
if (stmt.right() != null) {
stmt.right().visit(this);
}
print(") then " + stmt.trueTarget() + " else " + stmt.falseTarget());
println(" caught by " + stmt.catchTargets());
}
public void visitInitStmt(final InitStmt stmt) {
print("INIT");
final LocalExpr[] t = stmt.targets();
if (t != null) {
for (int i = 0; i < t.length; i++) {
if (t[i] != null) {
print(" ");
t[i].visit(this);
}
}
}
println();
}
public void visitGotoStmt(final GotoStmt stmt) {
print("goto " + stmt.target().label());
println(" caught by " + stmt.catchTargets());
}
public void visitLabelStmt(final LabelStmt stmt) {
if (stmt.label() != null) {
println(stmt.label());
}
}
public void visitMonitorStmt(final MonitorStmt stmt) {
if (stmt.kind() == MonitorStmt.ENTER) {
print("enter ");
} else {
print("exit ");
}
print("monitor (");
if (stmt.object() != null) {
stmt.object().visit(this);
}
println(")");
}
public void visitCatchExpr(final CatchExpr expr) {
print("Catch(" + expr.catchType() + ")");
}
public void visitStackManipStmt(final StackManipStmt stmt) {
print("(");
final StackExpr[] target = stmt.target();
if (target != null) {
for (int i = 0; i < target.length; i++) {
target[i].visit(this);
if (i != target.length - 1) {
print(", ");
}
}
}
final String[] str = new String[] { "swap", "dup", "dup_x1", "dup_x2",
"dup2", "dup2_x1", "dup2_x2" };
print(") := " + str[stmt.kind()] + "(");
final StackExpr[] source = stmt.source();
if (source != null) {
for (int i = 0; i < source.length; i++) {
source[i].visit(this);
if (i != source.length - 1) {
print(", ");
}
}
}
println(")");
}
public void visitPhiJoinStmt(final PhiJoinStmt stmt) {
if (stmt.target() != null) {
stmt.target().visit(this);
}
print(" := Phi(");
if (stmt.hasParent()) {
final Tree tree = (Tree) stmt.parent();
final Block block = tree.block();
final Iterator e = block.graph().preds(block).iterator();
while (e.hasNext()) {
final Block pred = (Block) e.next();
final Expr operand = stmt.operandAt(pred);
print(pred.label() + "=");
operand.visit(this);
if (e.hasNext()) {
print(", ");
}
}
} else {
final Iterator e = stmt.operands().iterator();
while (e.hasNext()) {
final Expr operand = (Expr) e.next();
operand.visit(this);
if (e.hasNext()) {
print(", ");
}
}
}
println(")");
}
public void visitPhiCatchStmt(final PhiCatchStmt stmt) {
if (stmt.target() != null) {
stmt.target().visit(this);
}
print(" := Phi-Catch(");
final Iterator e = stmt.operands().iterator();
while (e.hasNext()) {
final Expr operand = (Expr) e.next();
operand.visit(this);
if (e.hasNext()) {
print(", ");
}
}
println(")");
}
public void visitRetStmt(final RetStmt stmt) {
print("ret from " + stmt.sub());
println(" caught by " + stmt.catchTargets());
}
public void visitReturnExprStmt(final ReturnExprStmt stmt) {
print("return ");
if (stmt.expr() != null) {
stmt.expr().visit(this);
}
println(" caught by " + stmt.catchTargets());
}
public void visitReturnStmt(final ReturnStmt stmt) {
print("return");
println(" caught by " + stmt.catchTargets());
}
public void visitStoreExpr(final StoreExpr expr) {
print("(");
if (expr.target() != null) {
expr.target().visit(this);
}
print(" := ");
if (expr.expr() != null) {
expr.expr().visit(this);
}
print(")");
}
public void visitAddressStoreStmt(final AddressStoreStmt stmt) {
print("La");
if (stmt.sub() != null) {
print(new Integer(stmt.sub().returnAddress().index()));
} else {
print("???");
}
println(" := returnAddress");
}
public void visitJsrStmt(final JsrStmt stmt) {
print("jsr ");
if (stmt.sub() != null) {
print(stmt.sub().entry());
}
if (stmt.follow() != null) {
print(" ret to " + stmt.follow());
}
println(" caught by " + stmt.catchTargets());
}
public void visitSwitchStmt(final SwitchStmt stmt) {
print("switch (");
if (stmt.index() != null) {
stmt.index().visit(this);
}
print(")");
println(" caught by " + stmt.catchTargets());
if ((stmt.values() != null) && (stmt.targets() != null)) {
for (int i = 0; i < stmt.values().length; i++) {
println(" case " + stmt.values()[i] + ": "
+ stmt.targets()[i]);
}
}
println(" default: " + stmt.defaultTarget());
}
public void visitThrowStmt(final ThrowStmt stmt) {
print("throw ");
if (stmt.expr() != null) {
stmt.expr().visit(this);
}
println(" caught by " + stmt.catchTargets());
}
public void visitSCStmt(final SCStmt stmt) {
print("aswizzle ");
if (stmt.array() != null) {
stmt.array().visit(this);
}
if (stmt.index() != null) {
stmt.index().visit(this);
}
}
public void visitSRStmt(final SRStmt stmt) {
print("aswrange array: ");
if (stmt.array() != null) {
stmt.array().visit(this);
}
print(" start: ");
if (stmt.start() != null) {
stmt.start().visit(this);
}
print(" end: ");
if (stmt.end() != null) {
stmt.end().visit(this);
}
println("");
}
public void visitArithExpr(final ArithExpr expr) {
print("(");
if (expr.left() != null) {
expr.left().visit(this);
}
print(" ");
switch (expr.operation()) {
case ArithExpr.ADD:
print("+");
break;
case ArithExpr.SUB:
print("-");
break;
case ArithExpr.DIV:
print("/");
break;
case ArithExpr.MUL:
print("*");
break;
case ArithExpr.REM:
print("%");
break;
case ArithExpr.AND:
print("&");
break;
case ArithExpr.IOR:
print("|");
break;
case ArithExpr.XOR:
print("^");
break;
case ArithExpr.CMP:
print("<=>");
break;
case ArithExpr.CMPL:
print("<l=>");
break;
case ArithExpr.CMPG:
print("<g=>");
break;
}
print(" ");
if (expr.right() != null) {
expr.right().visit(this);
}
print(")");
}
public void visitArrayLengthExpr(final ArrayLengthExpr expr) {
if (expr.array() != null) {
expr.array().visit(this);
}
print(".length");
}
public void visitArrayRefExpr(final ArrayRefExpr expr) {
if (expr.array() != null) {
expr.array().visit(this);
}
print("[");
if (expr.index() != null) {
expr.index().visit(this);
}
print("]");
}
public void visitCallMethodExpr(final CallMethodExpr expr) {
if (expr.receiver() != null) {
expr.receiver().visit(this);
}
print(".");
if (expr.method() != null) {
print(expr.method().nameAndType().name());
}
print("(");
if (expr.params() != null) {
for (int i = 0; i < expr.params().length; i++) {
expr.params()[i].visit(this);
if (i != expr.params().length - 1) {
print(", ");
}
}
}
print(")");
}
public void visitCallStaticExpr(final CallStaticExpr expr) {
if (expr.method() != null) {
print(expr.method().declaringClass());
}
print(".");
if (expr.method() != null) {
print(expr.method().nameAndType().name());
}
print("(");
if (expr.params() != null) {
for (int i = 0; i < expr.params().length; i++) {
expr.params()[i].visit(this);
if (i != expr.params().length - 1) {
print(", ");
}
}
}
print(")");
}
public void visitCastExpr(final CastExpr expr) {
print("((" + expr.castType() + ") ");
if (expr.expr() != null) {
expr.expr().visit(this);
}
print(")");
}
public void visitConstantExpr(final ConstantExpr expr) {
if (expr.value() instanceof String) {
final StringBuffer sb = new StringBuffer();
final String s = (String) expr.value();
for (int i = 0; i < s.length(); i++) {
final char c = s.charAt(i);
if (Character.isWhitespace(c) || ((0x20 <= c) && (c <= 0x7e))) {
sb.append(c);
} else {
sb.append("\\u");
sb.append(Integer.toHexString(c));
}
if (sb.length() > 50) {
sb.append("...");
break;
}
}
print("'" + sb.toString() + "'");
} else if (expr.value() instanceof Float) {
print(expr.value() + "F");
} else if (expr.value() instanceof Long) {
print(expr.value() + "L");
} else {
print(expr.value());
}
}
public void visitFieldExpr(final FieldExpr expr) {
if (expr.object() != null) {
expr.object().visit(this);
}
print(".");
if (expr.field() != null) {
print(expr.field().nameAndType().name());
}
}
public void visitInstanceOfExpr(final InstanceOfExpr expr) {
if (expr.expr() != null) {
expr.expr().visit(this);
}
print(" instanceof " + expr.checkType());
}
public void visitLocalExpr(final LocalExpr expr) {
if (expr.fromStack()) {
print("T");
} else {
print("L");
}
print(expr.type().shortName().toLowerCase());
print(Integer.toString(expr.index()));
final DefExpr def = expr.def();
if ((def == null) || (def.version() == -1)) {
print("_undef");
} else {
print("_" + def.version());
}
}
public void visitNegExpr(final NegExpr expr) {
print("-");
if (expr.expr() != null) {
expr.expr().visit(this);
}
}
public void visitNewArrayExpr(final NewArrayExpr expr) {
print("new " + expr.elementType() + "[");
if (expr.size() != null) {
expr.size().visit(this);
}
print("]");
}
public void visitNewExpr(final NewExpr expr) {
print("new " + expr.objectType());
}
public void visitNewMultiArrayExpr(final NewMultiArrayExpr expr) {
print("new " + expr.elementType());
if (expr.dimensions() != null) {
for (int i = 0; i < expr.dimensions().length; i++) {
print("[" + expr.dimensions()[i] + "]");
}
}
}
public void visitZeroCheckExpr(final ZeroCheckExpr expr) {
if (expr.expr().type().isReference()) {
print("notNull(");
} else {
print("notZero(");
}
if (expr.expr() != null) {
expr.expr().visit(this);
}
print(")");
}
public void visitRCExpr(final RCExpr expr) {
print("rc(");
if (expr.expr() != null) {
expr.expr().visit(this);
}
print(")");
}
public void visitUCExpr(final UCExpr expr) {
if (expr.kind() == UCExpr.POINTER) {
print("aupdate(");
} else {
print("supdate(");
}
if (expr.expr() != null) {
expr.expr().visit(this);
}
print(")");
}
public void visitReturnAddressExpr(final ReturnAddressExpr expr) {
print("returnAddress");
}
public void visitShiftExpr(final ShiftExpr expr) {
print("(");
if (expr.expr() != null) {
expr.expr().visit(this);
}
if (expr.dir() == ShiftExpr.LEFT) {
print("<<");
} else if (expr.dir() == ShiftExpr.RIGHT) {
print(">>");
} else if (expr.dir() == ShiftExpr.UNSIGNED_RIGHT) {
print(">>>");
}
if (expr.bits() != null) {
expr.bits().visit(this);
}
print(")");
}
public void visitStackExpr(final StackExpr expr) {
print("S" + expr.type().shortName().toLowerCase() + expr.index());
final DefExpr def = expr.def();
if ((def == null) || (def.version() == -1)) {
print("_undef");
} else {
print("_" + def.version());
}
}
public void visitStaticFieldExpr(final StaticFieldExpr expr) {
if (expr.field() != null) {
print(expr.field().declaringClass() + "."
+ expr.field().nameAndType().name());
}
}
public void visitExpr(final Expr expr) {
print("EXPR");
}
public void visitStmt(final Stmt stmt) {
print("STMT");
}
}