OSDN Git Service

b090b0baf3cf0b9a225b7de7142ae2d7185ee224
[jcfa/jcfa.git] / jcfa / src / jp / igapyon / jcfa / util / JcfaWriteUtil.java
1 package jp.igapyon.jcfa.util;
2
3 import java.io.BufferedWriter;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.io.OutputStreamWriter;
7
8 import jp.igapyon.jcfa.vo.JcfaClass;
9 import jp.igapyon.jcfa.vo.JcfaCode;
10 import jp.igapyon.jcfa.vo.JcfaComment;
11 import jp.igapyon.jcfa.vo.JcfaField;
12 import jp.igapyon.jcfa.vo.JcfaMethod;
13 import jp.igapyon.jcfa.vo.JcfaUnit;
14 import jp.igapyon.jcfa.vo.operandstack.JcfaOSLocalVariable;
15 import jp.igapyon.jcfa.vo.operandstack.JcfaOSNode;
16 import jp.igapyon.jcfa.vo.operandstack.JcfaOSRef;
17 import jp.igapyon.jcfa.vo.operandstack.JcfaOSString;
18
19 import org.apache.bcel.Constants;
20 import org.apache.bcel.classfile.JavaClass;
21
22 public class JcfaWriteUtil {
23         public static void writeToFile(final JcfaUnit jcfaUnit) throws IOException {
24                 final StringBuffer result = new StringBuffer();
25
26                 for (JcfaClass jcfaClass : jcfaUnit.getClassList()) {
27                         writeClass(jcfaClass, result);
28                 }
29
30                 final BufferedWriter writer = new BufferedWriter(
31                                 new OutputStreamWriter(new FileOutputStream(
32                                                 jcfaUnit.getTargetFile())));
33                 writer.write(JcfaEclipseUtil.formatSource(result.toString()));
34                 writer.close();
35         }
36
37         /**
38          * Write class
39          * 
40          * @param jcfaClass
41          * @param result
42          * @throws IOException
43          */
44         public static void writeClass(final JcfaClass jcfaClass,
45                         final StringBuffer result) throws IOException {
46
47                 if (jcfaClass.isMainClass()) {
48                         if (jcfaClass.getName().contains(".")) {
49                                 result.append(" package "
50                                                 + jcfaClass.getName().substring(0,
51                                                                 jcfaClass.getName().lastIndexOf(".")) + ";");
52                         }
53                 }
54
55                 writeComment(jcfaClass.getComment(), result);
56
57                 result.append(jcfaClass.getAccess());
58                 result.append(" class " + jcfaClass.getLocalName());
59                 if (jcfaClass.getExtendsName() != null
60                                 && jcfaClass.getExtendsName().length() > 0
61                                 && jcfaClass.getExtendsName().equals("java.lang.Object") == false) {
62                         result.append(" extends " + jcfaClass.getExtendsName());
63                 }
64                 result.append("{");
65
66                 for (JcfaField jcfaField : jcfaClass.getFieldList()) {
67                         writeField(jcfaField, result);
68                 }
69
70                 for (JcfaMethod jcfaMethod : jcfaClass.getMethodList()) {
71                         writeMethod(jcfaClass, jcfaMethod, result);
72                 }
73
74                 result.append("}");
75         }
76
77         /**
78          * Write field.
79          * 
80          * @param jcfaField
81          * @param result
82          */
83         public static void writeField(final JcfaField jcfaField,
84                         final StringBuffer result) {
85                 writeComment(jcfaField.getComment(), result);
86
87                 result.append(" " + jcfaField.getAccess() + " " + jcfaField.getType()
88                                 + " " + jcfaField.getName());
89                 if (jcfaField.getConstantValue() != null) {
90                         result.append(" = ");
91                         result.append(jcfaField.getConstantValue());
92                 }
93                 result.append(";");
94         }
95
96         /**
97          * Write method.
98          * 
99          * @param jcfaClass
100          * @param jcfaMethod
101          * @param result
102          * @throws IOException
103          */
104         public static void writeMethod(final JcfaClass jcfaClass,
105                         final JcfaMethod jcfaMethod, final StringBuffer result)
106                         throws IOException {
107
108                 writeComment(jcfaMethod.getComment(), result);
109
110                 if (jcfaMethod.getName().equals("<init>")) {
111                         result.append("public " + jcfaClass.getLocalName() + "(");
112                 } else {
113                         result.append("public " + jcfaMethod.getType() + " "
114                                         + jcfaMethod.getName() + "(");
115                 }
116
117                 int argNo = 0;
118                 for (String argumentType : jcfaMethod.getArugumentTypeList()) {
119                         if (argNo != 0) {
120                                 result.append(", ");
121                         }
122                         result.append(argumentType);
123                         result.append(" arg" + argNo);
124                 }
125
126                 result.append(")");
127
128                 result.append("{");
129
130                 writeCodes(jcfaClass, jcfaMethod, result);
131
132                 result.append("}");
133         }
134
135         public static void writeCodes(final JcfaClass jcfaClass,
136                         final JcfaMethod jcfaMethod, final StringBuffer result)
137                         throws IOException {
138                 for (JcfaCode jcfaCode : jcfaMethod.getCodeList()) {
139                         final byte[] codes = jcfaCode.getCodes();
140                         final JavaClass jc = jcfaCode.getJavaClass();
141
142                         switch (jcfaCode.getOpcode()) {
143                         case Constants.ALOAD_0: {
144                                 final JcfaOSLocalVariable osLocalVariable = new JcfaOSLocalVariable();
145                                 jcfaMethod.getFrame().getOperandStack().push(osLocalVariable);
146                                 osLocalVariable.setLocalVariable(jcfaMethod.getFrame()
147                                                 .getLocalVariableList().get(0));
148
149                                 jcfaCode.getComment().getCommentList()
150                                                 .add(osLocalVariable.getLocalVariable().getName());
151
152                                 break;
153                         }
154                         case Constants.RETURN: {
155                                 break;
156                         }
157                         case Constants.GETSTATIC: {
158                                 final JcfaOSRef osRef = new JcfaOSRef();
159                                 jcfaMethod.getFrame().getOperandStack().push(osRef);
160                                 osRef.setClassName(JcfaUtil.getConstantFieldrefString(jc,
161                                                 codes[1], codes[2]));
162
163                                 jcfaCode.getComment().getCommentList()
164                                                 .add(osRef.getClassName());
165                                 break;
166                         }
167                         case Constants.LDC: {
168                                 final JcfaOSString osString = new JcfaOSString();
169                                 jcfaMethod.getFrame().getOperandStack().push(osString);
170                                 osString.setString(JcfaUtil.getConstantString(jc, codes[1]));
171
172                                 jcfaCode.getComment().getCommentList()
173                                                 .add(osString.getString());
174                         }
175                                 break;
176                         case Constants.INVOKEVIRTUAL:
177                         case Constants.INVOKESPECIAL: {
178                                 final int operand = JcfaUtil.byte2UnsignedShort(codes[1],
179                                                 codes[2]);
180                                 jcfaCode.getComment().getCommentList()
181                                                 .add(JcfaUtil.getConstantMethodRefString(jc, operand));
182
183                                 jcfaCode.getComment().getCommentList()
184                                                 .add("TODO get args count from signature.");
185                                 // get n args.
186                                 final JcfaOSNode osNodeArg0 = jcfaMethod.getFrame()
187                                                 .getOperandStack().pop();
188
189                                 final JcfaOSRef osRef = (JcfaOSRef) jcfaMethod.getFrame()
190                                                 .getOperandStack().pop();
191
192                                 jcfaCode.getComment()
193                                                 .getCommentList()
194                                                 .add("" + osRef.getClassName() + "#"
195                                                                 + osNodeArg0.toString());
196
197                         }
198                                 break;
199                         case Constants.LOOKUPSWITCH:
200                                 if (true) {
201                                         jcfaCode.getComment().getCommentList()
202                                                         .add("  TODO temporary disabled.");
203                                         break;
204                                 }
205                                 int skipBytes = JcfaUtil.byte2Int(codes[1], codes[2], codes[3],
206                                                 codes[4]);
207
208                                 jcfaCode.getComment().getCommentList()
209                                                 .add("  TODO skipping bytes: " + (skipBytes));
210
211                                 int lookupOp = 5;
212
213                                 short diff = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);
214                                 jcfaCode.getComment().getCommentList()
215                                                 .add("  TODO skipping bytes: " + (diff));
216
217                                 int loopCount = JcfaUtil
218                                                 .byte2Int(codes[lookupOp++], codes[lookupOp++],
219                                                                 codes[lookupOp++], codes[lookupOp++]);
220                                 for (int index = 0; index < loopCount; index++) {
221                                         jcfaCode.getComment()
222                                                         .getCommentList()
223                                                         .add(JcfaUtil.byte2Int(codes[lookupOp++],
224                                                                         codes[lookupOp++], codes[lookupOp++],
225                                                                         codes[lookupOp++])
226                                                                         + ":"
227                                                                         + (JcfaUtil.byte2Int(codes[lookupOp++],
228                                                                                         codes[lookupOp++],
229                                                                                         codes[lookupOp++],
230                                                                                         codes[lookupOp++])));
231                                 }
232
233                                 short diff2 = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);
234                                 jcfaCode.getComment().getCommentList()
235                                                 .add("  TODO skipping bytes: " + (diff2));
236
237                                 break;
238                         default:
239                                 jcfaCode.getComment().getCommentList()
240                                                 .add("TODO unsupported opcode");
241                                 break;
242                         }
243
244                         writeComment(jcfaCode.getComment(), result);
245
246                         // TODO and code...
247                 }
248         }
249
250         /**
251          * Write comment.
252          * 
253          * @param jcfaComment
254          * @param result
255          */
256         public static void writeComment(final JcfaComment jcfaComment,
257                         final StringBuffer result) {
258                 if (jcfaComment.isJavaDoc()) {
259                         result.append("\n/** ");
260                 } else {
261                         result.append("\n/* ");
262                 }
263
264                 if (jcfaComment.getCommentList().size() > 1) {
265                         result.append("\n");
266                 }
267
268                 for (String comment : jcfaComment.getCommentList()) {
269                         if (jcfaComment.getCommentList().size() > 1) {
270                                 result.append(" * " + comment + "\n");
271                         } else {
272                                 result.append(comment);
273                         }
274                 }
275
276                 result.append(" */\n");
277         }
278 }