001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2005 Nomair A. Naeem
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: /*
021: * Maintained by Nomair A. Naeem
022: */
023:
024: /*
025: * CHANGLE LOG:
026: *
027: */
028: package soot.dava.toolkits.base.AST.traversals;
029:
030: import soot.*;
031: import java.util.*;
032: import soot.jimple.*;
033: import soot.dava.internal.javaRep.*;
034: import soot.dava.internal.AST.*;
035: import soot.dava.internal.SET.*;
036: import soot.dava.toolkits.base.AST.analysis.*;
037:
038: /**
039: * This class has been created because we need the immediate
040: * target of a implicit break/continue statement i.e. a break/continue
041: * statement which does not break/continue a particular label explicitly.
042:
043: * Notice that this is only allowed for
044: * while
045: * do while,
046: * unconditional loop
047: * for loop
048: * switch construct.
049:
050: * Notice continue is not allowed for switch also
051:
052: * Explicit breaks can on the other hand break any label (that on a construct) which we are not
053: * worried about in this analysis
054: */
055: public class ClosestAbruptTargetFinder extends DepthFirstAdapter {
056:
057: public ClosestAbruptTargetFinder(Singletons.Global g) {
058: }
059:
060: public static ClosestAbruptTargetFinder v() {
061: return G
062: .v()
063: .soot_dava_toolkits_base_AST_traversals_ClosestAbruptTargetFinder();
064: }
065:
066: HashMap<DAbruptStmt, ASTNode> closestNode = new HashMap<DAbruptStmt, ASTNode>();//a mapping of each abrupt statement to the node they are targeting
067: ArrayList<ASTLabeledNode> nodeStack = new ArrayList<ASTLabeledNode>(); //the last element will always be the "currentNode" meaning the closest target to a abrupt stmt
068:
069: /**
070: * To be invoked by other analyses. Given an abrupt stmt as input this method
071: * will locate the closest target and return it
072: */
073: public ASTNode getTarget(DAbruptStmt ab) {
074: Object node = closestNode.get(ab);
075: if (node != null)
076: return (ASTNode) node;
077: else
078: throw new RuntimeException(
079: "Unable to find target for AbruptStmt");
080: }
081:
082: /**
083: * Following methods add a new node to the end of the nodeStack arrayList
084: * Since that node becomes the closest target of an implicit break or continue
085: */
086:
087: public void inASTWhileNode(ASTWhileNode node) {
088: nodeStack.add(node);
089: }
090:
091: public void inASTDoWhileNode(ASTDoWhileNode node) {
092: nodeStack.add(node);
093: }
094:
095: public void inASTUnconditionalLoopNode(ASTUnconditionalLoopNode node) {
096: nodeStack.add(node);
097: }
098:
099: public void inASTForLoopNode(ASTForLoopNode node) {
100: nodeStack.add(node);
101: }
102:
103: public void inASTSwitchNode(ASTSwitchNode node) {
104: nodeStack.add(node);
105: }
106:
107: /**
108: * Following methods remove the last node from the end of the nodeStack arrayList
109: * Since the previous node now becomes the closest target to an implict break or continue
110: */
111:
112: public void outASTWhileNode(ASTWhileNode node) {
113: if (nodeStack.isEmpty())
114: throw new RuntimeException(
115: "trying to remove node from empty stack: ClosestBreakTargetFinder");
116: nodeStack.remove(nodeStack.size() - 1);
117: }
118:
119: public void outASTDoWhileNode(ASTDoWhileNode node) {
120: if (nodeStack.isEmpty())
121: throw new RuntimeException(
122: "trying to remove node from empty stack: ClosestBreakTargetFinder");
123: nodeStack.remove(nodeStack.size() - 1);
124: }
125:
126: public void outASTUnconditionalLoopNode(
127: ASTUnconditionalLoopNode node) {
128: if (nodeStack.isEmpty())
129: throw new RuntimeException(
130: "trying to remove node from empty stack: ClosestBreakTargetFinder");
131: nodeStack.remove(nodeStack.size() - 1);
132: }
133:
134: public void outASTForLoopNode(ASTForLoopNode node) {
135: if (nodeStack.isEmpty())
136: throw new RuntimeException(
137: "trying to remove node from empty stack: ClosestBreakTargetFinder");
138: nodeStack.remove(nodeStack.size() - 1);
139: }
140:
141: public void outASTSwitchNode(ASTSwitchNode node) {
142: if (nodeStack.isEmpty())
143: throw new RuntimeException(
144: "trying to remove node from empty stack: ClosestBreakTargetFinder");
145: nodeStack.remove(nodeStack.size() - 1);
146: }
147:
148: public void inStmt(Stmt s) {
149: if (s instanceof DAbruptStmt) {
150: //breaks and continues are abrupt statements
151: DAbruptStmt ab = (DAbruptStmt) s;
152:
153: SETNodeLabel label = ab.getLabel();
154: if (label != null) {
155: if (label.toString() != null) {
156: //not considering explicit breaks
157: return;
158: }
159: }
160:
161: //the break is an implict break
162: if (ab.is_Break()) {
163: //get the top of the stack
164: int index = nodeStack.size() - 1;
165: if (index < 0) {
166: //error
167: throw new RuntimeException("nodeStack empty??"
168: + nodeStack.toString());
169: }
170: ASTNode currentNode = nodeStack
171: .get(nodeStack.size() - 1);
172: closestNode.put(ab, currentNode);
173: } else if (ab.is_Continue()) {
174: //need something different because continues dont target switch
175: int index = nodeStack.size() - 1;
176: if (index < 0) {
177: //error
178: throw new RuntimeException("nodeStack empty??"
179: + nodeStack.toString());
180: }
181:
182: ASTNode currentNode = nodeStack.get(index);
183: while (currentNode instanceof ASTSwitchNode) {
184: if (index > 0) {
185: //more elements present in nodeStack
186: index--;
187: currentNode = nodeStack.get(index);
188: } else {
189: //error
190: throw new RuntimeException(
191: "Unable to find closest break Target");
192: }
193: }
194: //know that the currentNode is not an ASTSwitchNode
195: closestNode.put(ab, currentNode);
196: }
197: }
198: }
199:
200: /* public void outASTMethodNode(ASTMethodNode node){
201: Iterator it = closestNode.keySet().iterator();
202: while(it.hasNext()){
203: DAbruptStmt ab = (DAbruptStmt)it.next();
204: System.out.println("Closest to "+ab+" is "+((ASTNode)closestNode.get(ab)).toString()+"\n\n");
205: }
206:
207: }*/
208: }
|