Source code: jreversepro/runtime/JOperandStack.java
1 /**
2 * JOperandStack.java
3 *
4 * JReversePro - Java Decompiler / Disassembler.
5 * Copyright (C) 2000 2001 Karthik Kumar.
6 * EMail: akkumar@users.sourceforge.net
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it , under the terms of the GNU General Public License as published
10 * by the Free Software Foundation; either version 2 of the License,
11 * or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program.If not, write to
19 * The Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 **/
23 package jreversepro.runtime;
24
25
26 import java.util.Stack;
27 import java.util.Vector;
28 import java.util.List;
29 import jreversepro.common.KeyWords;
30 import jreversepro.revengine.RevEngineException;
31
32 /**
33 * Operand Stack is the abstraction of the Java Method Operand Stack.
34 * The variables are pushed to and popped from, this stack.
35 * @author Karthik Kumar.
36 **/
37 public class JOperandStack extends Stack
38 implements KeyWords,
39 OperandConstants {
40 /**
41 * A Vector of constants. The individual members of this
42 * vector are 'String'. They are primarily used in the following
43 * case. Lets say - we have a code called .
44 * String [] args = { "run", "args", "args1" };
45 * In this case all the individual members of the array
46 * namely args come into the constants.
47 **/
48 Vector constants;
49
50 /**
51 * Empty constructor
52 **/
53 public JOperandStack() {
54 constants = new Vector();
55 }
56
57 /**
58 * Adds a new constant.
59 * @param constant New Constant to be added to the vector.
60 **/
61 public void addConstant(String constant) {
62 constants.add(constant);
63 }
64
65 /**
66 * Deletes all the constants that were stored in the
67 * vector already.
68 **/
69 public void removeAllConstants() {
70 constants.removeAllElements();
71 }
72
73 /**
74 * @return List of constants that were stored.
75 **/
76 public List getConstants() {
77 return constants;
78 }
79
80 /**
81 * Returns the values of the constants serialized such
82 * that it corresponds to java syntax code too.
83 * @return Constant values.
84 **/
85 public String getConstantValues() {
86 StringBuffer result = new StringBuffer("{");
87 for (int i = 0; i < constants.size(); i++) {
88 if (i != 0) {
89 result.append(",");
90 }
91 result.append(constants.get(i));
92 }
93 result.append("}");
94 return result.toString();
95 }
96
97 /**
98 * @param value Value of the Operand - Stack element.
99 * The Value is String.
100 * @param datatype Datatype of the stack element.
101 * @param precedence precedence of the stack element.
102 **/
103 public void push(String value, String datatype, int precedence) {
104 super.push(new Operand(value, datatype, precedence));
105 }
106
107 /**
108 * @param value Value of the Operand - Stack element.
109 * The Value is int.
110 * @param datatype Datatype of the stack element.
111 * @param precedence precedence of the stack element.
112 **/
113 public void push(int value, String datatype, int precedence) {
114 super.push(new Operand(value, datatype, precedence));
115 }
116
117 /**
118 * @return Returns the data type of the topmost content of the
119 * stack.
120 **/
121 public String topDatatype() {
122 return ((Operand) this.peek()).datatype;
123 }
124
125 /**
126 * Lets us know if the top data type is foreign. Mainly this method
127 * is necessary when we have a operand loaded onto the stack from
128 * outside. ( Eg: an argument to the exception handler of the
129 * exception type ).
130 * @return true, if the top type is foreign. false. otherwise.
131 **/
132 public boolean isTopDatatypeForeign() {
133 if (this.empty()) {
134 return false;
135 } else {
136 String dataType = ((Operand) this.peek()).getDatatype();
137 return dataType.equals(FOREIGN_CLASS)
138 || dataType.indexOf("<") != -1 ;
139 }
140 }
141
142 /**
143 * Merges the top two contents of the operand stack.
144 * Eg, if the stack contents are
145 * ab String
146 * cd String ( in reverse order - stack top first ).,
147 * On merging it becomes
148 * abcd String ( in reverse order - stack top first ).,
149 * The precondition is that the datatypes of first top two elements
150 * ought to be the same. Then only this is valid.
151 * @throws RevEngineException Thrown when there are less than 2 elements
152 * in the stack.
153 **/
154 public void mergeTopTwo()
155 throws RevEngineException {
156 if (this.size() < 2) {
157 throw new
158 RevEngineException("Cannot merge ternary expressions");
159 }
160 Operand op1 = (Operand) this.pop();
161 Operand op2 = (Operand) this.pop();
162
163 push (new Operand(op2.getValue() + op1.getValue(),
164 op2.getDatatype(), L_TERN));
165 }
166 }