All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.Printer Maven / Gradle / Ivy

There is a newer version: 1.12.0
Show newest version
/* Soot - a J*va Optimization Framework
 * Copyright (C) 2003 Ondrej Lhotak
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/*
 * Modified by the Sable Research Group and others 1997-1999.  
 * See the 'credits' file distributed with Soot for the complete list of
 * contributors.  (Soot is distributed at http://www.sable.mcgill.ca/soot)
 */

package soot;
import soot.options.*;
import java.io.*;
import soot.tagkit.*;
import java.util.*;

import soot.util.*;
import soot.toolkits.graph.*;

/**
* Prints out a class and all its methods.
*/
public class Printer {
    public Printer(Singletons.Global g) {
    }
    public static Printer v() {
        return G.v().soot_Printer();
    }

    final private static char fileSeparator =
        System.getProperty("file.separator").charAt(0);

    public static final int USE_ABBREVIATIONS = 0x0001, ADD_JIMPLE_LN = 0x0010;

    public boolean useAbbreviations() {
        return (options & USE_ABBREVIATIONS) != 0;
    }

    public boolean addJimpleLn() {
        return (options & ADD_JIMPLE_LN) != 0;
    }

    int options = 0;
    public void setOption(int opt) {
        options |= opt;
    }
    public void clearOption(int opt) {
        options &= ~opt;
    }

    int jimpleLnNum = 0; // actual line number

    public int getJimpleLnNum() {
        return jimpleLnNum;
    }
    public void setJimpleLnNum(int newVal) {
        jimpleLnNum = newVal;
    }
    public void incJimpleLnNum() {
        jimpleLnNum++;
	//G.v().out.println("jimple Ln Num: "+jimpleLnNum);
    }

    public void printTo(SootClass cl, PrintWriter out) {
        // add jimple line number tags
        setJimpleLnNum(1);

        // Print class name + modifiers
        {
            StringTokenizer st =
                new StringTokenizer(Modifier.toString(cl.getModifiers()));
            while (st.hasMoreTokens()) {
                String tok = st.nextToken();
                if( cl.isInterface() && tok.equals("abstract") ) continue;
                out.print(tok + " ");
            }

            String classPrefix = "";

            if (!cl.isInterface()) {
                classPrefix = classPrefix + " class";
                classPrefix = classPrefix.trim();
            }

            out.print(
                classPrefix + " " + Scene.v().quotedNameOf(cl.getName()) + "");
        }

        // Print extension
        {
            if (cl.hasSuperclass())
                out.print(
                    " extends "
                        + Scene.v().quotedNameOf(cl.getSuperclass().getName())
                        + "");
        }

        // Print interfaces
        {
            Iterator interfaceIt = cl.getInterfaces().iterator();

            if (interfaceIt.hasNext()) {
                out.print(" implements ");

                out.print(
                    ""
                        + Scene.v().quotedNameOf(
                            ((SootClass) interfaceIt.next()).getName())
                        + "");

                while (interfaceIt.hasNext()) {
                    out.print(",");
                    out.print(
                        " "
                            + Scene.v().quotedNameOf(
                                ((SootClass) interfaceIt.next()).getName())
                            + "");
                }
            }
        }

        out.println();
        incJimpleLnNum();
/*        if (!addJimpleLn()) {
            Iterator clTagsIt = cl.getTags().iterator();
            while (clTagsIt.hasNext()) {
                final Tag t = (Tag)clTagsIt.next();
                out.println(t);
            }
        }*/
        out.println("{");
        incJimpleLnNum();
        if (Options.v().print_tags_in_output()){
            Iterator cTagIterator = cl.getTags().iterator();
            while (cTagIterator.hasNext()) {
                Tag t = (Tag) cTagIterator.next();
                out.print("/*");
                out.print(t.toString());
                out.println("*/");
            }
        }

        // Print fields
        {
            Iterator fieldIt = cl.getFields().iterator();

            if (fieldIt.hasNext()) {
                while (fieldIt.hasNext()) {
                    SootField f = (SootField) fieldIt.next();

                    if (f.isPhantom())
                        continue;

                    if (Options.v().print_tags_in_output()){
                        Iterator fTagIterator = f.getTags().iterator();
                        while (fTagIterator.hasNext()) {
                            Tag t = (Tag) fTagIterator.next();
                            out.print("/*");
                            out.print(t.toString());
                            out.println("*/");
                        }
                    }
                    out.println("    " + f.getDeclaration() + ";");
                    if (addJimpleLn()) {
                        setJimpleLnNum(addJimpleLnTags(getJimpleLnNum(), f));		
                    }

                    //incJimpleLnNum();
                }
            }
        }

        // Print methods
        {
            Iterator methodIt = cl.methodIterator();

            if (methodIt.hasNext()) {
                if (cl.getMethodCount() != 0) {
                    out.println();
                    incJimpleLnNum();
                }

                while (methodIt.hasNext()) {
                    SootMethod method = (SootMethod) methodIt.next();

                    if (method.isPhantom())
                        continue;

                    if (!Modifier.isAbstract(method.getModifiers())
                        && !Modifier.isNative(method.getModifiers())) {
                        if (!method.hasActiveBody())
                            throw new RuntimeException(
                                "method "
                                    + method.getName()
                                    + " has no active body!");
                        else
                            if (Options.v().print_tags_in_output()){
                                Iterator mTagIterator = method.getTags().iterator();
                                while (mTagIterator.hasNext()) {
                                    Tag t = (Tag) mTagIterator.next();
                                    out.print("/*");
                                    out.print(t.toString());
                                    out.println("*/");
                                }
                            }
                            printTo(method.getActiveBody(), out);

                        if (methodIt.hasNext()) {
                            out.println();
                            incJimpleLnNum();
                        }
                    } else {
                           
                        if (Options.v().print_tags_in_output()){
                            Iterator mTagIterator = method.getTags().iterator();
                            while (mTagIterator.hasNext()) {
                                Tag t = (Tag) mTagIterator.next();
                                out.print("/*");
                                out.print(t.toString());
                                out.println("*/");
                            }
                        }
                        
                        out.print("    ");
                        out.print(method.getDeclaration());
                        out.println(";");
                        incJimpleLnNum();
                        if (methodIt.hasNext()) {
                            out.println();
                            incJimpleLnNum();
                        }
                    }
                }
            }
        }
        out.println("}");
        incJimpleLnNum();
    }


    /**
     *   Prints out the method corresponding to b Body, (declaration and body),
     *   in the textual format corresponding to the IR used to encode b body.
     *
     *   @param out a PrintWriter instance to print to.
     */
    public void printTo(Body b, PrintWriter out) {
        b.validate();

        boolean isPrecise = !useAbbreviations();

        String decl = b.getMethod().getDeclaration();

        out.println("    " + decl);
        //incJimpleLnNum();
    
        // only print tags if not printing attributes in a file 
        if (!addJimpleLn()) {
            /*for( Iterator tIt = b.getMethod().getTags().iterator(); tIt.hasNext(); ) {    final Tag t = (Tag) tIt.next();
                out.println(t);
                incJimpleLnNum();

            }*/
        }
       
        if (addJimpleLn()) {
            setJimpleLnNum(addJimpleLnTags(getJimpleLnNum(), b.getMethod()));		
            //G.v().out.println("added jimple ln tag for method: "+b.getMethod().toString()+" "+b.getMethod().getDeclaringClass().getName());
        }

        out.println("    {");
        incJimpleLnNum();
        
        UnitGraph unitGraph = new soot.toolkits.graph.BriefUnitGraph(b);

        LabeledUnitPrinter up;
        if( isPrecise ) up = new NormalUnitPrinter(b);
        else up = new BriefUnitPrinter(b);

        if (addJimpleLn()) {
            up.setPositionTagger( new AttributesUnitPrinter(getJimpleLnNum()) );
        }
	
        printLocalsInBody(b, up);

        printStatementsInBody(b, out, up, unitGraph);

        out.println("    }");
        incJimpleLnNum();

    }

    /** Prints the given JimpleBody to the specified PrintWriter. */
    private void printStatementsInBody(Body body, java.io.PrintWriter out, LabeledUnitPrinter up, UnitGraph unitGraph ) {
    	Chain units = body.getUnits();
        Iterator unitIt = units.iterator();
        Unit currentStmt = null, previousStmt;

        while (unitIt.hasNext()) {

            previousStmt = currentStmt;
            currentStmt = (Unit) unitIt.next();

            // Print appropriate header.
            {
                // Put an empty line if the previous node was a branch node, the current node is a join node
                //   or the previous statement does not have body statement as a successor, or if
                //   body statement has a label on it

                if (currentStmt != units.getFirst()) {
                    if (unitGraph.getSuccsOf(previousStmt).size() != 1
                        || unitGraph.getPredsOf(currentStmt).size() != 1
                        || up.labels().containsKey(currentStmt)) {
                        up.newline();
                    } else {
                        // Or if the previous node does not have body statement as a successor.

                        List succs = unitGraph.getSuccsOf(previousStmt);

                        if (succs.get(0) != currentStmt) {
                            up.newline();
                        }
                    }
                }

                if (up.labels().containsKey(currentStmt)) {
                    up.unitRef( currentStmt, true );
                    up.literal(":");
                    up.newline();
                }

                if (up.references().containsKey(currentStmt)) {
                    up.unitRef( currentStmt, false );
                }
            }

            up.startUnit(currentStmt);
            currentStmt.toString(up);
            up.endUnit(currentStmt);

            up.literal(";");
            up.newline();

            // only print them if not generating attributes files 
            // because they mess up line number
            //if (!addJimpleLn()) {
            if (Options.v().print_tags_in_output()){
                Iterator tagIterator = currentStmt.getTags().iterator();
                while (tagIterator.hasNext()) {
                    Tag t = (Tag) tagIterator.next();
                    up.noIndent();
                    up.literal("/*");
                    up.literal(t.toString());
                    up.literal("*/");
                    up.newline();
                }
                /*Iterator udIt = currentStmt.getUseAndDefBoxes().iterator();
                while (udIt.hasNext()) {
                    ValueBox temp = (ValueBox)udIt.next();
                    Iterator vbtags = temp.getTags().iterator();
                    while (vbtags.hasNext()) {
                        Tag t = (Tag) vbtags.next();
                        up.noIndent();
                        up.literal("VB Tag: "+t.toString());
                        up.newline();
                    }
                }*/
            }
        }

        out.print(up.toString());
		if (addJimpleLn()){
			setJimpleLnNum(up.getPositionTagger().getEndLn());
		}


        // Print out exceptions
        {
            Iterator trapIt = body.getTraps().iterator();

            if (trapIt.hasNext()) {
                out.println();
                incJimpleLnNum();
            }

            while (trapIt.hasNext()) {
                Trap trap = (Trap) trapIt.next();

                out.println(
                    "        catch "
                        + Scene.v().quotedNameOf(trap.getException().getName())
                        + " from "
                        + up.labels().get(trap.getBeginUnit())
                        + " to "
                        + up.labels().get(trap.getEndUnit())
                        + " with "
                        + up.labels().get(trap.getHandlerUnit())
                        + ";");

                incJimpleLnNum();

            }
        }
        // RoboVM note: This block added in RoboVM
        // Print out local variables
        {
            Iterator lvsIt = body.getLocalVariables().iterator();

            if (lvsIt.hasNext()) {
                out.println();
                incJimpleLnNum();
            }

            while (lvsIt.hasNext()) {
                LocalVariable lv = (LocalVariable) lvsIt.next();

                out.println(
                    "        localvar index=" + lv.getIndex()
                        + " name=" + Scene.v().quotedNameOf(lv.getName())
                        + " type="
                        + Scene.v().quotedNameOf(lv.getDescriptor())
                        + " start="
                        + up.labels().get(lv.getStartUnit())
                        + " end="
                        + (lv.getEndUnit() != null ? up.labels().get(lv.getEndUnit()) : "")
                        + ";");

                incJimpleLnNum();

            }
        }

    }

    private int addJimpleLnTags(int lnNum, SootMethod meth) {
    	meth.addTag(new JimpleLineNumberTag(lnNum));
	lnNum++;
	return lnNum;
    }
    
    private int addJimpleLnTags(int lnNum, SootField f) {
    	f.addTag(new JimpleLineNumberTag(lnNum));
	lnNum++;
	return lnNum;
    }

    /** Prints the given JimpleBody to the specified PrintWriter. */
    private void printLocalsInBody(
        Body body,
        UnitPrinter up) {
        // Print out local variables
        {
            Map typeToLocals =
                new DeterministicHashMap(body.getLocalCount() * 2 + 1, 0.7f);

            // Collect locals
            {
                Iterator localIt = body.getLocals().iterator();

                while (localIt.hasNext()) {
                    Local local = (Local) localIt.next();

                    List localList;

                    Type t = local.getType();

                    if (typeToLocals.containsKey(t))
                        localList = typeToLocals.get(t);
                    else {
                        localList = new ArrayList();
                        typeToLocals.put(t, localList);
                    }

                    localList.add(local);
                }
            }

            // Print locals
            {
                Iterator typeIt = typeToLocals.keySet().iterator();

                while (typeIt.hasNext()) {
                    Type type = typeIt.next();

                    List localList = typeToLocals.get(type);
                    Object[] locals = localList.toArray();
                    up.type( type );
                    up.literal( " " );

                    for (int k = 0; k < locals.length; k++) {
                        if (k != 0)
                            up.literal( ", " );

                        up.local( (Local) locals[k] );
                    }

                    up.literal(";");
                    up.newline();
                }
            }

            if (!typeToLocals.isEmpty()) {
                up.newline();
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy