KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > flow > CatchBlock


1 /* CatchBlock Copyright (C) 1998-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; see the file COPYING.LESSER. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: CatchBlock.java.in,v 4.2.2.3 2002/05/28 17:34:08 hoenicke Exp $
18  */

19
20 package jode.flow;
21 import jode.type.Type;
22 import jode.decompiler.LocalInfo;
23 import jode.decompiler.Declarable;
24 import jode.expr.Expression;
25 import jode.expr.LocalLoadOperator;
26 import jode.expr.LocalStoreOperator;
27 import jode.expr.NopOperator;
28 import jode.expr.StoreInstruction;
29 import jode.util.SimpleSet;
30
31 import java.util.Collections JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.Set JavaDoc;
34
35
36 /**
37  *
38  * @author Jochen Hoenicke
39  */

40 public class CatchBlock extends StructuredBlock {
41     
42     /**
43      * The catch block.
44      */

45     StructuredBlock catchBlock;
46
47     /**
48      * The type of the exception.
49      */

50     Type exceptionType;
51     
52     /**
53      * The local containing the exception. May be null.
54      */

55     LocalInfo exceptionLocal;
56
57     public CatchBlock(Type type) {
58         exceptionType = type;
59     }
60
61     public Type getExceptionType() {
62     return exceptionType;
63     }
64
65     public LocalInfo getLocal() {
66     return exceptionLocal;
67     }
68
69     /**
70      * Sets the catch block.
71      * @param catchBlock the catch block.
72      */

73     public void setCatchBlock(StructuredBlock catchBlock) {
74         this.catchBlock = catchBlock;
75         catchBlock.outer = this;
76         catchBlock.setFlowBlock(flowBlock);
77     if (exceptionLocal == null)
78         combineLocal();
79     }
80
81     /* The implementation of getNext[Flow]Block is the standard
82      * implementation */

83
84     /**
85      * Replaces the given sub block with a new block.
86      * @param oldBlock the old sub block.
87      * @param newBlock the new sub block.
88      * @return false, if oldBlock wasn't a direct sub block.
89      */

90     public boolean replaceSubBlock(StructuredBlock oldBlock,
91                                    StructuredBlock newBlock) {
92         if (catchBlock == oldBlock)
93             catchBlock = newBlock;
94         else
95             return false;
96         return true;
97     }
98
99     /**
100      * Returns all sub block of this structured block.
101      */

102     public StructuredBlock[] getSubBlocks() {
103         return new StructuredBlock[] { catchBlock };
104     }
105
106     LocalInfo pushedLocal;
107
108     /**
109      * A catch block pushes the exception on the stack, iff a local
110      * doesn't exists.
111      * @param stack the stack before the instruction is called
112      * @return stack the stack afterwards.
113      */

114     public VariableStack mapStackToLocal(VariableStack stack) {
115     VariableStack newStack;
116     if (exceptionLocal == null) {
117         pushedLocal = new LocalInfo();
118         pushedLocal.setType(exceptionType);
119         newStack = stack.push(pushedLocal);
120     } else
121         newStack = stack;
122     return super.mapStackToLocal(newStack);
123     }
124
125     public void removePush() {
126     if (pushedLocal != null)
127         exceptionLocal = pushedLocal;
128     super.removePush();
129     }
130
131     public Set getDeclarables() {
132     if (exceptionLocal != null)
133         return Collections.singleton(exceptionLocal);
134     return Collections.EMPTY_SET;
135     }
136     
137     /**
138      * Make the declarations, i.e. initialize the declare variable
139      * to correct values. This will declare every variable that
140      * is marked as used, but not done.
141      * @param done The set of the already declare variables.
142      */

143     public void makeDeclaration(Set done) {
144     super.makeDeclaration(done);
145     /* Normally we have to declare our exceptionLocal. This
146      * is automatically done in dumpSource.
147      *
148      * If we are unlucky the exceptionLocal is used outside of
149      * this block. In that case we do a transformation.
150      */

151     if (exceptionLocal != null) {
152         if (declare.contains(exceptionLocal))
153         declare.remove(exceptionLocal);
154         else {
155         LocalInfo dummyLocal = new LocalInfo();
156         Expression store = new StoreInstruction
157             (new LocalStoreOperator
158              (exceptionLocal.getType(), exceptionLocal)).addOperand
159             (new LocalLoadOperator(dummyLocal.getType(),
160                        null, dummyLocal));
161         InstructionBlock ib = new InstructionBlock(store);
162         ib.setFlowBlock(flowBlock);
163         ib.appendBlock(catchBlock);
164         catchBlock = ib;
165         exceptionLocal = dummyLocal;
166         String JavaDoc localName = dummyLocal.guessName();
167         Iterator JavaDoc doneIter = done.iterator();
168         while (doneIter.hasNext()) {
169             Declarable previous = (Declarable) doneIter.next();
170             if (localName.equals(previous.getName())) {
171             /* A name conflict happened. */
172             dummyLocal.makeNameUnique();
173             break;
174             }
175         }
176         }
177     }
178     }
179
180     public void dumpInstruction(jode.decompiler.TabbedPrintWriter writer)
181         throws java.io.IOException JavaDoc {
182     writer.closeBraceContinue();
183         writer.print("catch (");
184     writer.printType(exceptionType);
185     writer.print(" " + (exceptionLocal != null
186                 ? exceptionLocal.getName() : "PUSH") + ")");
187     writer.openBrace();
188         writer.tab();
189         catchBlock.dumpSource(writer);
190         writer.untab();
191     }
192
193     /**
194      * Determines if there is a sub block, that flows through to the end
195      * of this block. If this returns true, you know that jump is null.
196      * @return true, if the jump may be safely changed.
197      */

198     public boolean jumpMayBeChanged() {
199         return (catchBlock.jump != null || catchBlock.jumpMayBeChanged());
200     }
201
202     /**
203      * Check if this is an local store instruction to a not yet declared
204      * variable. In that case mark this as declaration and return the
205      * variable.
206      */

207     public boolean combineLocal() {
208     StructuredBlock firstInstr = (catchBlock instanceof SequentialBlock)
209             ? catchBlock.getSubBlocks()[0] : catchBlock;
210
211     if (firstInstr instanceof SpecialBlock
212         && ((SpecialBlock) firstInstr).type == SpecialBlock.POP
213         && ((SpecialBlock) firstInstr).count == 1) {
214         /* The exception is ignored. Create a dummy local for it */
215         exceptionLocal = new LocalInfo();
216         exceptionLocal.setType(exceptionType);
217         firstInstr.removeBlock();
218         return true;
219     } else if (firstInstr instanceof InstructionBlock) {
220             Expression instr =
221                 ((InstructionBlock) firstInstr).getInstruction();
222             if (instr instanceof StoreInstruction) {
223         StoreInstruction store = (StoreInstruction) instr;
224         if (store.getOperatorIndex() == store.OPASSIGN_OP
225             && store.getSubExpressions()[1] instanceof NopOperator
226             && store.getLValue() instanceof LocalStoreOperator) {
227             /* The exception is stored in a local variable */
228             exceptionLocal = ((LocalStoreOperator) store.getLValue())
229             .getLocalInfo();
230             exceptionLocal.setType(exceptionType);
231             firstInstr.removeBlock();
232             return true;
233         }
234         }
235         }
236     return false;
237     }
238 }
239
Popular Tags