1 package serp.bytecode.visitor;
2
3 import java.io.*;
4
5 import serp.bytecode.*;
6 import serp.bytecode.lowlevel.*;
7
8
9
10
11
12
13
14 public class PrettyPrintVisitor extends BCVisitor {
15 private PrintWriter _out = null;
16 private String _prefix = "";
17
18
19
20
21 public PrettyPrintVisitor() {
22 _out = new PrintWriter(System.out);
23 }
24
25
26
27
28
29
30 public PrettyPrintVisitor(PrintWriter out) {
31 _out = out;
32 }
33
34
35
36
37
38
39 public static void main(String[] args)
40 throws ClassNotFoundException, IOException {
41 if (args.length == 0) {
42 System.err.println("Usage: java "
43 + PrettyPrintVisitor.class.getName()
44 + " <class name | .class file>+");
45 System.exit(1);
46 }
47
48 PrettyPrintVisitor ppv = new PrettyPrintVisitor();
49 Project project = new Project();
50 BCClass type;
51 for (int i = 0; i < args.length; i++) {
52 if (args[i].endsWith(".class"))
53 type = project.loadClass(new File(args[i]));
54 else
55 type = project.loadClass(Class.forName(args[i], false,
56 PrettyPrintVisitor.class.getClassLoader()));
57 ppv.visit(type);
58 }
59 }
60
61 public void visit(VisitAcceptor entity) {
62 super.visit(entity);
63 _out.flush();
64 }
65
66 public void enterProject(Project obj) {
67 openBlock("Project");
68 println("name=" + obj.getName());
69 }
70
71 public void exitProject(Project obj) {
72 closeBlock();
73 }
74
75 public void enterBCClass(BCClass obj) {
76 openBlock("Class");
77
78 println("magic=" + obj.getMagic());
79 println("minor=" + obj.getMinorVersion());
80 println("major=" + obj.getMajorVersion());
81 println("access=" + obj.getAccessFlags());
82 println("name=" + obj.getIndex() + " <" + obj.getName() + ">");
83 println("super=" + obj.getSuperclassIndex() + " <" +
84 obj.getSuperclassName() + ">");
85
86 int[] indexes = obj.getDeclaredInterfaceIndexes();
87 String[] names = obj.getDeclaredInterfaceNames();
88 for (int i = 0; i < indexes.length; i++)
89 println("interface=" + indexes[i] + " <" + names[i] + ">");
90 }
91
92 public void exitBCClass(BCClass obj) {
93 closeBlock();
94 }
95
96 public void enterBCField(BCField obj) {
97 openBlock("Field");
98 println("access=" + obj.getAccessFlags());
99 println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
100 println("type=" + obj.getDescriptorIndex() + " <" + obj.getTypeName()
101 + ">");
102 }
103
104 public void exitBCField(BCField obj) {
105 closeBlock();
106 }
107
108 public void enterBCMethod(BCMethod obj) {
109 openBlock("Method");
110 println("access=" + obj.getAccessFlags());
111 println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
112 println("descriptor=" + obj.getDescriptorIndex());
113 println("return=" + obj.getReturnName());
114 String[] params = obj.getParamNames();
115 for (int i = 0; i < params.length; i++)
116 println("param=" + params[i]);
117 }
118
119 public void exitBCMethod(BCMethod obj) {
120 closeBlock();
121 }
122
123 public void enterAttribute(Attribute obj) {
124 openBlock(obj.getName());
125 }
126
127 public void exitAttribute(Attribute obj) {
128 closeBlock();
129 }
130
131 public void enterConstantValue(ConstantValue obj) {
132 println("value=" + obj.getValueIndex() + " <" + obj.getTypeName() +
133 "=" + obj.getValue() + ">");
134 }
135
136 public void enterExceptions(Exceptions obj) {
137 int[] indexes = obj.getExceptionIndexes();
138 String[] names = obj.getExceptionNames();
139 for (int i = 0; i < indexes.length; i++)
140 println("exception=" + indexes[i] + " <" + names[i] + ">");
141 }
142
143 public void enterSourceFile(SourceFile obj) {
144 println("source=" + obj.getFileIndex() + " <" + obj.getFileName()
145 + ">");
146 }
147
148 public void enterCode(Code obj) {
149 println("maxStack=" + obj.getMaxStack());
150 println("maxLocals=" + obj.getMaxLocals());
151 println("");
152 }
153
154 public void enterExceptionHandler(ExceptionHandler obj) {
155 openBlock("ExceptionHandler");
156 println("startPc=" + obj.getTryStartPc());
157 println("endPc=" + obj.getTryEndPc());
158 println("handlerPc=" + obj.getHandlerStartPc());
159 println("catch=" + obj.getCatchIndex() + " <" + obj.getCatchName()
160 + ">");
161 }
162
163 public void exitExceptionHandler(ExceptionHandler obj) {
164 closeBlock();
165 }
166
167 public void enterInnerClass(InnerClass obj) {
168 openBlock("InnerClass");
169 println("access=" + obj.getAccessFlags());
170 println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
171 println("type=" + obj.getTypeIndex() + "<" + obj.getTypeName() + ">");
172 println("declarer=" + obj.getDeclarerIndex() + "<"
173 + obj.getDeclarerName() + ">");
174 }
175
176 public void exitInnerClass(InnerClass obj) {
177 closeBlock();
178 }
179
180 public void enterLineNumber(LineNumber obj) {
181 openBlock("LineNumber");
182 println("startPc=" + obj.getStartPc());
183 println("line=" + obj.getLine());
184 }
185
186 public void exitLineNumber(LineNumber obj) {
187 closeBlock();
188 }
189
190 public void enterLocalVariable(LocalVariable obj) {
191 openBlock("LocalVariable");
192 println("startPc=" + obj.getStartPc());
193 println("length=" + obj.getLength());
194 println("local=" + obj.getLocal());
195 println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
196 println("type=" + obj.getTypeIndex() + " <" + obj.getTypeName() + ">");
197 }
198
199 public void exitLocalVariable(LocalVariable obj) {
200 closeBlock();
201 }
202
203 public void enterLocalVariableType(LocalVariableType obj) {
204 openBlock("LocalVariableType");
205 println("startPc=" + obj.getStartPc());
206 println("length=" + obj.getLength());
207 println("local=" + obj.getLocal());
208 println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
209 println("signature=" + obj.getTypeIndex() + " <" + obj.getTypeName()
210 + ">");
211 }
212
213 public void exitLocalVariableType(LocalVariableType obj) {
214 closeBlock();
215 }
216
217 public void enterAnnotation(Annotation obj) {
218 openBlock("Annotation");
219 println("type=" + obj.getTypeIndex() + " <" + obj.getTypeName() + ">");
220 }
221
222 public void exitAnnotation(Annotation obj) {
223 closeBlock();
224 }
225
226 public void enterAnnotationProperty(Annotation.Property obj) {
227 openBlock("Property");
228 println("name=" + obj.getNameIndex() + " <" + obj.getName() + ">");
229 Object val = obj.getValue();
230 if (val instanceof Object[]) {
231 Object[] arr = (Object[]) val;
232 for (int i = 0; i < arr.length; i++)
233 printAnnotationPropertyValue(arr[i]);
234 } else
235 printAnnotationPropertyValue(val);
236 }
237
238 private void printAnnotationPropertyValue(Object obj) {
239 if (obj == null)
240 println("value=null");
241 else if (obj instanceof Annotation) {
242 _out.print(_prefix);
243 _out.print("value=");
244 ((Annotation) obj).acceptVisit(this);
245 } else
246 println("value=(" + obj.getClass().getName() + ") " + obj);
247 }
248
249 public void exitAnnotationProperty(Annotation.Property obj) {
250 closeBlock();
251 }
252
253 public void enterInstruction(Instruction obj) {
254 _out.print(_prefix + obj.getByteIndex() + " " + obj.getName() + " ");
255 }
256
257 public void exitInstruction(Instruction obj) {
258 _out.println();
259 }
260
261 public void enterClassInstruction(ClassInstruction obj) {
262 _out.print(obj.getTypeIndex() + " <" + obj.getTypeName() + ">");
263 }
264
265 public void enterConstantInstruction(ConstantInstruction obj) {
266 _out.print("<" + obj.getValue() + ">");
267 }
268
269 public void enterGetFieldInstruction(GetFieldInstruction obj) {
270 _out.print(obj.getFieldIndex() + " <" + obj.getFieldTypeName() + " "
271 + obj.getFieldDeclarerName() + "." + obj.getFieldName() + ">");
272 }
273
274 public void enterIIncInstruction(IIncInstruction obj) {
275 _out.print(obj.getLocal() + " ");
276 if (obj.getIncrement() < 0)
277 _out.print("-");
278 _out.print(obj.getIncrement());
279 }
280
281 public void enterJumpInstruction(JumpInstruction obj) {
282 _out.print(obj.getOffset());
283 }
284
285 public void enterIfInstruction(IfInstruction obj) {
286 _out.print(obj.getOffset());
287 }
288
289 public void enterLoadInstruction(LoadInstruction obj) {
290 _out.print("<" + obj.getLocal() + ">");
291 }
292
293 public void enterLookupSwitchInstruction(LookupSwitchInstruction obj) {
294 _out.println();
295 _prefix += " ";
296
297 int[] offsets = obj.getOffsets();
298 int[] matches = obj.getMatches();
299 for (int i = 0; i < offsets.length; i++)
300 println("case " + matches[i] + "=" + offsets[i]);
301 _out.print(_prefix + "default=" + obj.getDefaultOffset());
302 _prefix = _prefix.substring(2);
303 }
304
305 public void enterMethodInstruction(MethodInstruction obj) {
306 _out.print(obj.getMethodIndex() + " <" + obj.getMethodReturnName()
307 + " " + obj.getMethodDeclarerName() + "." + obj.getMethodName()
308 + "(");
309
310 String[] params = obj.getMethodParamNames();
311 int dotIndex;
312 for (int i = 0; i < params.length; i++) {
313 dotIndex = params[i].lastIndexOf('.');
314 if (dotIndex != -1)
315 params[i] = params[i].substring(dotIndex + 1);
316
317 _out.print(params[i]);
318 if (i != (params.length - 1))
319 _out.print(", ");
320 }
321 _out.print(")>");
322 }
323
324 public void enterMultiANewArrayInstruction(MultiANewArrayInstruction obj) {
325 _out.print(obj.getTypeIndex() + " " + obj.getDimensions() + " <"
326 + obj.getTypeName());
327 String post = "";
328 for (int i = 0; i < obj.getDimensions(); i++)
329 post += "[]";
330 _out.print(post + ">");
331 }
332
333 public void enterNewArrayInstruction(NewArrayInstruction obj) {
334 _out.print(obj.getTypeCode() + " <" + obj.getTypeName() + "[]>");
335 }
336
337 public void enterPutFieldInstruction(PutFieldInstruction obj) {
338 _out.print(obj.getFieldIndex() + " <" + obj.getFieldTypeName() + " "
339 + obj.getFieldDeclarerName() + "." + obj.getFieldName() + ">");
340 }
341
342 public void enterRetInstruction(RetInstruction obj) {
343 _out.print(obj.getLocal());
344 }
345
346 public void enterStoreInstruction(StoreInstruction obj) {
347 _out.print("<" + obj.getLocal() + ">");
348 }
349
350 public void enterTableSwitchInstruction(TableSwitchInstruction obj) {
351 _out.println();
352 _prefix += " ";
353
354 println("low=" + obj.getLow());
355 println("high=" + obj.getHigh());
356 int[] offsets = obj.getOffsets();
357 for (int i = 0; i < offsets.length; i++)
358 println("case=" + offsets[i]);
359 _out.print(_prefix + "default=" + obj.getDefaultOffset());
360 _prefix = _prefix.substring(2);
361 }
362
363 public void enterWideInstruction(WideInstruction obj) {
364 int ins = obj.getInstruction();
365 _out.print(ins + " <" + Constants.OPCODE_NAMES[ins] + ">");
366 }
367
368 public void enterConstantPool(ConstantPool obj) {
369 openBlock("ConstantPool");
370 }
371
372 public void exitConstantPool(ConstantPool obj) {
373 closeBlock();
374 }
375
376 public void enterEntry(Entry obj) {
377 String name = obj.getClass().getName();
378 openBlock(obj.getIndex() + ": "
379 + name.substring(name.lastIndexOf('.') + 1));
380 }
381
382 public void exitEntry(Entry obj) {
383 closeBlock();
384 }
385
386 public void enterClassEntry(ClassEntry obj) {
387 println("name=" + obj.getNameIndex());
388 }
389
390 public void enterDoubleEntry(DoubleEntry obj) {
391 println("value=" + obj.getValue());
392 }
393
394 public void enterFieldEntry(FieldEntry obj) {
395 println("class=" + obj.getClassIndex());
396 println("nameAndType=" + obj.getNameAndTypeIndex());
397 }
398
399 public void enterFloatEntry(FloatEntry obj) {
400 println("value=" + obj.getValue());
401 }
402
403 public void enterIntEntry(IntEntry obj) {
404 println("value=" + obj.getValue());
405 }
406
407 public void enterInterfaceMethodEntry(InterfaceMethodEntry obj) {
408 println("class=" + obj.getClassIndex());
409 println("nameAndType=" + obj.getNameAndTypeIndex());
410 }
411
412 public void enterLongEntry(LongEntry obj) {
413 println("value=" + obj.getValue());
414 }
415
416 public void enterMethodEntry(MethodEntry obj) {
417 println("class=" + obj.getClassIndex());
418 println("nameAndType=" + obj.getNameAndTypeIndex());
419 }
420
421 public void enterNameAndTypeEntry(NameAndTypeEntry obj) {
422 println("name=" + obj.getNameIndex());
423 println("descriptor=" + obj.getDescriptorIndex());
424 }
425
426 public void enterStringEntry(StringEntry obj) {
427 println("index=" + obj.getStringIndex());
428 }
429
430 public void enterUTF8Entry(UTF8Entry obj) {
431 println("value=" + obj.getValue());
432 }
433
434 private void println(String ln) {
435 _out.print(_prefix);
436 _out.println(ln);
437 }
438
439 private void openBlock(String name) {
440 println(name + " {");
441 _prefix += " ";
442 }
443
444 private void closeBlock() {
445 _prefix = _prefix.substring(2);
446 println("}");
447 }
448 }