001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2003, 2004 Ondrej Lhotak
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: */
019:
020: package soot;
021:
022: import soot.jimple.*;
023: import soot.util.*;
024: import java.util.*;
025:
026: /**
027: * UnitPrinter implementation for representations that have labelled stmts,
028: * such as Jimple, Grimp, and Baf
029: */
030: public abstract class LabeledUnitPrinter extends AbstractUnitPrinter {
031: /** branch targets **/
032: protected Map labels;
033: /** for unit references in Phi nodes **/
034: protected Map<Unit, String> references;
035:
036: public LabeledUnitPrinter(Body b) {
037: createLabelMaps(b);
038: }
039:
040: public Map labels() {
041: return labels;
042: }
043:
044: public Map<Unit, String> references() {
045: return references;
046: }
047:
048: public abstract void literal(String s);
049:
050: public abstract void methodRef(SootMethodRef m);
051:
052: public abstract void fieldRef(SootFieldRef f);
053:
054: public abstract void identityRef(IdentityRef r);
055:
056: public abstract void type(Type t);
057:
058: public void unitRef(Unit u, boolean branchTarget) {
059: String oldIndent = getIndent();
060:
061: // normal case, ie labels
062: if (branchTarget) {
063: setIndent(labelIndent);
064: handleIndent();
065: setIndent(oldIndent);
066: String label = (String) labels.get(u);
067: if (label == null || label.equals("<unnamed>"))
068: label = "[?= " + u + "]";
069: output.append(label);
070: }
071: // refs to control flow predecessors (for Shimple)
072: else {
073: String ref = references.get(u);
074:
075: if (startOfLine) {
076: String newIndent = "(" + ref + ")"
077: + indent.substring(ref.length() + 2);
078: setIndent(newIndent);
079: handleIndent();
080: setIndent(oldIndent);
081: } else
082: output.append(ref);
083: }
084: }
085:
086: private void createLabelMaps(Body body) {
087: Chain units = body.getUnits();
088:
089: labels = new HashMap(units.size() * 2 + 1, 0.7f);
090: references = new HashMap<Unit, String>(units.size() * 2 + 1,
091: 0.7f);
092:
093: // Create statement name table
094: {
095: Iterator boxIt = body.getAllUnitBoxes().iterator();
096:
097: Set<Unit> labelStmts = new HashSet<Unit>();
098: Set<Unit> refStmts = new HashSet<Unit>();
099:
100: // Build labelStmts and refStmts
101: {
102: while (boxIt.hasNext()) {
103: UnitBox box = (UnitBox) boxIt.next();
104: Unit stmt = box.getUnit();
105:
106: if (box.isBranchTarget())
107: labelStmts.add(stmt);
108: else
109: refStmts.add(stmt);
110: }
111:
112: }
113:
114: // Traverse the stmts and assign a label if necessary
115: {
116: int labelCount = 0;
117: int refCount = 0;
118:
119: Iterator stmtIt = units.iterator();
120:
121: while (stmtIt.hasNext()) {
122: Unit s = (Unit) stmtIt.next();
123:
124: if (labelStmts.contains(s))
125: labels.put(s, "label" + (labelCount++));
126:
127: if (refStmts.contains(s))
128: references.put(s, Integer.toString(refCount++));
129: }
130: }
131: }
132: }
133:
134: protected String labelIndent = " ";
135: }
|