OSDN Git Service

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