OSDN Git Service

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