Fixing a new bug: Considering parameters with Type and Type array, e.g., T and T[].
[jpf-core.git] / src / main / gov / nasa / jpf / jvm / ClassFilePrinter.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18
19 package gov.nasa.jpf.jvm;
20
21 import java.io.PrintWriter;
22
23 import gov.nasa.jpf.util.StructuredPrinter;
24 import gov.nasa.jpf.vm.ClassParseException;
25
26 /**
27  * simple tool to print contents of a classfile
28  *
29  * <2do> use indentation level variable and formated output
30  */
31 public class ClassFilePrinter extends StructuredPrinter implements ClassFileReader {
32
33
34   public static void main(String[] args){
35     ClassFilePrinter printer = new ClassFilePrinter();
36
37     try {
38       ClassFile cf = new ClassFile(args[0]);
39       cf.parse(printer);
40
41     } catch (ClassParseException cfx){
42       cfx.printStackTrace();
43     }
44   }
45
46   @Override
47   public void setClass(ClassFile cf, String clsName, String superClsName, int flags, int cpCount) {
48     printSectionHeader( "constpool");
49     printCp(pw,cf);
50
51     incIndent();
52     printSectionHeader( "class");
53     pw.printf("%sclass=%s\n", indent, clsName);
54     pw.printf("%ssuperclass=%s\n", indent, superClsName);
55     pw.printf("%sflags=0x%X\n", indent, flags);
56   }
57
58   //--- interfaces
59   @Override
60   public void setInterfaceCount(ClassFile cf, int ifcCount) {
61     pw.printf("%sinterface count=%d\n", indent, ifcCount);
62     incIndent();
63   }
64
65   @Override
66   public void setInterface(ClassFile cf, int ifcIndex, String ifcName) {
67     pw.printf("%s[%d]: %s\n", indent, ifcIndex, ifcName);
68   }
69
70   @Override
71   public void setInterfacesDone(ClassFile cf){
72     decIndent();
73   }
74
75   //--- fields
76   @Override
77   public void setFieldCount(ClassFile cf, int fieldCount) {
78     printSectionHeader( "fields");
79     pw.printf( "%sfield count=%d\n", indent, fieldCount);
80   }
81
82   @Override
83   public void setField(ClassFile cf, int fieldIndex, int accessFlags, String name, String descriptor) {
84     pw.printf("%s[%d]: %s, type=%s,flags=0x%X", indent, fieldIndex, name, descriptor, accessFlags);
85   }
86
87   @Override
88   public void setFieldAttributeCount(ClassFile cf, int fieldIndex, int attrCount) {
89     pw.printf(", attr count=%d\n", attrCount);
90     incIndent();
91   }
92
93   @Override
94   public void setFieldAttribute(ClassFile cf, int fieldIndex, int attrIndex, String name, int attrLength) {
95     pw.printf("%s[%d]: %s", indent, attrIndex, name);
96
97     if (name == ClassFile.CONST_VALUE_ATTR) {
98       cf.parseConstValueAttr(this, null);
99
100     } else if (name == ClassFile.RUNTIME_VISIBLE_ANNOTATIONS_ATTR){
101       cf.parseAnnotationsAttr(this, null);
102
103     } else if (name == ClassFile.RUNTIME_INVISIBLE_ANNOTATIONS_ATTR){
104       cf.parseAnnotationsAttr(this, null);
105
106     } else if (name == ClassFile.RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR){
107         cf.parseTypeAnnotationsAttr(this, null);
108
109     } else if (name == ClassFile.SIGNATURE_ATTR){
110       cf.parseSignatureAttr(this, null);
111
112     } else {
113       pw.printf(" ,length=%d,data=[",attrLength );
114       printRawData(pw, cf, attrLength, 10);
115       pw.println(']');
116     }
117   }
118
119   @Override
120   public void setFieldAttributesDone(ClassFile cf, int fieldIndex){
121     decIndent();
122   }
123
124   @Override
125   public void setFieldDone(ClassFile cf, int fieldIndex){
126     pw.println();
127   }
128
129   @Override
130   public void setFieldsDone(ClassFile cf){
131   }
132
133   @Override
134   public void setConstantValue(ClassFile cf, Object tag, Object value) {
135     pw.printf(" value=%s\n", value);
136   }
137
138   //--- methods
139   @Override
140   public void setMethodCount(ClassFile cf, int methodCount) {
141     printSectionHeader( "methods");
142     pw.printf( "%smethod count=%d\n", indent, methodCount);
143   }
144
145   @Override
146   public void setMethod(ClassFile cf, int methodIndex, int accessFlags, String name, String descriptor) {
147     pw.printf("%s[%d]: %s%s, flags=0x%X", indent, methodIndex, name, descriptor, accessFlags);
148   }
149
150   @Override
151   public void setMethodAttributeCount(ClassFile cf, int methodIndex, int attrCount) {
152     pw.printf(", attr count=%d\n", attrCount);
153     incIndent();
154   }
155
156   @Override
157   public void setMethodAttribute(ClassFile cf, int methodIndex, int attrIndex, String name, int attrLength) {
158     pw.printf("%s[%d]: %s", indent, attrIndex, name);
159
160     if (name == ClassFile.CODE_ATTR) {
161       cf.parseCodeAttr(this, null);
162
163     } else if (name == ClassFile.EXCEPTIONS_ATTR){
164       cf.parseExceptionAttr(this, null);
165
166     } else if (name == ClassFile.RUNTIME_VISIBLE_ANNOTATIONS_ATTR){
167       cf.parseAnnotationsAttr(this, null);
168
169     } else if (name == ClassFile.RUNTIME_INVISIBLE_ANNOTATIONS_ATTR){
170       cf.parseAnnotationsAttr(this, null);
171
172     } else if (name == ClassFile.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS_ATTR){
173       cf.parseParameterAnnotationsAttr(this, null);
174
175     } else if (name == ClassFile.RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR){
176       cf.parseTypeAnnotationsAttr(this, null);
177       
178     } else if (name == ClassFile.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS_ATTR){
179       cf.parseParameterAnnotationsAttr(this, null);
180
181     } else if (name == ClassFile.SIGNATURE_ATTR){
182       cf.parseSignatureAttr(this, null);
183
184     } else {
185       pw.printf(" ,length=%d,data=[", attrLength );
186       printRawData(pw, cf, attrLength, 10);
187       pw.println(']');
188     }
189   }
190
191   @Override
192   public void setMethodAttributesDone(ClassFile cf, int methodIndex){
193     decIndent();
194   }
195
196   @Override
197   public void setMethodDone(ClassFile cf, int methodIndex){
198     pw.println();
199   }
200
201   @Override
202   public void setMethodsDone(ClassFile cf){
203   }
204
205   @Override
206   public void setExceptionCount(ClassFile cf, Object tag, int exceptionCount){
207     pw.printf(", count=%d\n", exceptionCount);
208     incIndent();
209   }
210   @Override
211   public void setException(ClassFile cf, Object tag, int exceptionIndex, String exceptionType){
212     pw.printf("%s[%d]: %s\n", indent, exceptionIndex, exceptionType);
213   }
214   @Override
215   public void setExceptionsDone(ClassFile cf, Object tag){
216     decIndent();
217   }
218
219
220   @Override
221   public void setCode(ClassFile cf, Object tag, int maxStack, int maxLocals, int codeLength) {
222     pw.printf(", maxStack=%d,maxLocals=%d,length=%d\n", maxStack, maxLocals,codeLength);
223     incIndent();
224     JVMByteCodePrinter bcPrinter = new JVMByteCodePrinter(pw, cf, indent);
225     cf.parseBytecode(bcPrinter, tag, codeLength);
226     decIndent();
227   }
228
229   @Override
230   public void setExceptionHandlerTableCount(ClassFile cf, Object tag, int exceptionTableCount) {
231     pw.printf("%sexception table count=%d\n", indent, exceptionTableCount);
232     incIndent();
233   }
234   @Override
235   public void setExceptionHandler(ClassFile cf, Object tag, int exceptionIndex,
236           int startPc, int endPc, int handlerPc, String catchType) {
237     pw.printf("%s[%d]: type=%s, range=[%d..%d], handler=%d\n", indent, exceptionIndex, catchType, startPc, endPc, handlerPc);
238   }
239   @Override
240   public void setExceptionHandlerTableDone(ClassFile cf, Object tag){
241     decIndent();
242   }
243
244   @Override
245   public void setCodeAttributeCount(ClassFile cf, Object tag, int attrCount) {
246     pw.printf("%scode attribute count=%d\n", indent, attrCount);
247     incIndent();
248   }
249   @Override
250   public void setCodeAttribute(ClassFile cf, Object tag, int attrIndex, String name, int attrLength) {
251     pw.printf("%s[%d]: %s", indent, attrIndex, name);
252
253     if (name == ClassFile.LINE_NUMBER_TABLE_ATTR) {
254       cf.parseLineNumberTableAttr(this, tag);
255
256     } else if (name == ClassFile.LOCAL_VAR_TABLE_ATTR) {
257       cf.parseLocalVarTableAttr(this, tag);
258
259     } else if (name == ClassFile.RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR){
260         cf.parseTypeAnnotationsAttr(this, tag);
261
262     } else {  // generic
263       pw.printf(" ,length=%d,data=[", attrLength );
264       printRawData(pw, cf, attrLength, 10);
265       pw.println(']');
266     }
267   }
268   @Override
269   public void setCodeAttributesDone(ClassFile cf, Object tag){
270     decIndent();
271   }
272
273   @Override
274   public void setLineNumberTableCount(ClassFile cf, Object tag, int lineNumberCount) {
275     pw.printf(", linenumber count=%d\n", lineNumberCount);
276     incIndent();
277   }
278   @Override
279   public void setLineNumber(ClassFile cf, Object tag, int lineIndex, int lineNumber, int startPc) {
280     pw.printf("%s[%d]: line=%d, pc=%d\n", indent, lineIndex, lineNumber, startPc);
281   }
282   @Override
283   public void setLineNumberTableDone(ClassFile cf, Object tag){
284     decIndent();
285   }
286
287   @Override
288   public void setLocalVarTableCount(ClassFile cf, Object tag, int localVarCount) {
289     pw.printf(", localVar count=%d\n", localVarCount);
290     incIndent();
291   }
292   @Override
293   public void setLocalVar(ClassFile cf, Object tag, int localVarIndex,
294           String varName, String descriptor, int scopeStartPc, int scopeEndPc, int slotIndex) {
295     pw.printf("%s[%d]: %s, type=%s, scope=[%d..%d], slot=%d\n", indent, localVarIndex, varName, descriptor,
296             scopeStartPc, scopeEndPc, slotIndex);
297   }
298   @Override
299   public void setLocalVarTableDone(ClassFile cf, Object tag){
300     decIndent();
301   }
302
303   //--- class attributes
304   @Override
305   public void setClassAttributeCount(ClassFile cf, int attrCount) {
306     printSectionHeader( "class attributes");
307     pw.printf("%sclass attribute count=%d\n", indent, attrCount);
308     incIndent();
309   }
310   @Override
311   public void setClassAttribute(ClassFile cf, int attrIndex, String name, int attrLength) {
312     pw.printf("%s[%d]: %s", indent, attrIndex, name);
313
314     if (name == ClassFile.SOURCE_FILE_ATTR) {
315       cf.parseSourceFileAttr(this, null);
316
317     } else if (name == ClassFile.DEPRECATED_ATTR) {
318
319     } else if (name == ClassFile.INNER_CLASSES_ATTR) {
320       cf.parseInnerClassesAttr(this, null);
321
322     } else if (name == ClassFile.RUNTIME_VISIBLE_ANNOTATIONS_ATTR){
323       cf.parseAnnotationsAttr(this, null);
324
325     } else if (name == ClassFile.RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR){
326       cf.parseTypeAnnotationsAttr(this, null);
327
328     } else if (name == ClassFile.RUNTIME_INVISIBLE_ANNOTATIONS_ATTR){
329       cf.parseAnnotationsAttr(this, null);
330
331     } else if (name == ClassFile.SIGNATURE_ATTR){
332       cf.parseSignatureAttr(this, null);
333
334     } else if (name == ClassFile.ENCLOSING_METHOD_ATTR){
335       cf.parseEnclosingMethodAttr(this, null);
336
337     } else if (name == ClassFile.BOOTSTRAP_METHOD_ATTR){
338       cf.parseBootstrapMethodAttr(this, null);
339
340     } else {
341       pw.printf(" ,length=%d,data=[", attrLength );
342       printRawData(pw, cf, attrLength, 10);
343       pw.println(']');
344     }
345   }
346   @Override
347   public void setClassAttributesDone(ClassFile cf){
348     decIndent();
349   }
350
351   @Override
352   public void setEnclosingMethod(ClassFile cf, Object tag, String enclosingClass, String enclosingMethod, String descriptor) {
353     if (enclosingMethod != null){
354       pw.printf(", enclosingClass=%s, method=%s%s\n", enclosingClass, enclosingMethod, descriptor);
355     } else {
356       pw.printf(", enclosingClass=%s\n", enclosingClass);
357     }
358   }
359
360   
361   @Override
362   public void setSourceFile(ClassFile cf, Object tag, String pathName){
363     pw.printf(", path=%s\n", pathName);
364   }
365
366   @Override
367   public void setInnerClassCount(ClassFile cf, Object tag, int innerClsCount) {
368     pw.printf( ", inner class count=%d\n", innerClsCount);
369     incIndent();
370   }
371   @Override
372   public void setInnerClass(ClassFile cf, Object tag, int innerClsIndex,
373           String outerName, String innerName, String innerSimpleName, int accessFlags) {
374     pw.printf("%s[%d]: %s, fullName=%s, outerClass=%s, flags=0x%X\n", indent, innerClsIndex,
375             innerSimpleName, innerName, outerName, accessFlags);
376   }
377   @Override
378   public void setInnerClassesDone(ClassFile cf, Object tag){
379     decIndent();
380   }
381
382   @Override
383   public void setBootstrapMethodCount (ClassFile cf, Object tag, int count) {
384     pw.printf( ", bootstrap method count=%d\n", count);
385     incIndent();
386   }
387   
388   @Override
389   public void setBootstrapMethod (ClassFile cf, Object tag, int idx, 
390                                   int refKind, String cls, String mth, String descriptor, int[] cpArgs){
391     String refTypeName = cf.getRefTypeName(refKind);
392     pw.printf("%s[%d]: %s %s.%s%s\n", indent, idx, refTypeName, cls, mth, descriptor);
393     incIndent();
394     pw.printf("%smethod arg count: %d\n", indent, cpArgs.length);
395     incIndent();
396     for (int i=0; i<cpArgs.length; i++){
397       int cpIdx = cpArgs[i];
398       String arg = getBootstrapMethodArgAsString(cf, cpIdx);
399       pw.printf("%s[%d]: %s\n", indent, i, arg);
400     }
401     decIndent();
402     decIndent();
403   }
404   
405   String getBootstrapMethodArgAsString (ClassFile cf, int cpIdx){
406     StringBuilder sb = new StringBuilder();
407     Object cpValue = cf.getCpValue(cpIdx);
408     sb.append('@');
409     sb.append(cpIdx);
410     sb.append(" (");
411     sb.append( cpValue);
412     sb.append("): ");
413     
414     if (cpValue instanceof ClassFile.CpInfo){
415       switch ((ClassFile.CpInfo)cpValue){
416         case MethodType:
417           sb.append( cf.methodTypeDescriptorAt(cpIdx));
418           break;
419         case MethodHandle:
420           int methodRefIdx = cf.mhMethodRefIndexAt(cpIdx);
421           
422           sb.append( cf.getRefTypeName(cf.mhRefTypeAt(cpIdx)));
423           sb.append(' ');
424           sb.append( cf.methodClassNameAt(methodRefIdx));
425           sb.append('.');
426           sb.append( cf.methodNameAt(methodRefIdx));
427           sb.append( cf.methodDescriptorAt(methodRefIdx));
428           break;
429         default:
430           sb.append( cpValue.toString());
431       }
432     } else {
433       sb.append( cpValue.toString());
434     }
435     
436     return sb.toString();
437   }
438   
439   @Override
440   public void setBootstrapMethodsDone (ClassFile cf, Object tag) {
441     decIndent();
442   }
443   
444   @Override
445   public void setAnnotationCount(ClassFile cf, Object tag, int annotationCount){
446     pw.printf( " count=%d\n", annotationCount);
447     incIndent();
448   }
449   @Override
450   public void setAnnotation(ClassFile cf, Object tag, int annotationIndex, String annotationType){
451     pw.printf("%s[%d]: %s", indent, annotationIndex, annotationType);
452   }
453   @Override
454   public void setAnnotationsDone(ClassFile cf, Object tag){
455     decIndent();
456   }
457   
458   // Java 8 type annotations
459
460   @Override
461   public void setTypeAnnotationCount(ClassFile cf, Object tag, int annotationCount){
462     pw.printf( " count=%d\n", annotationCount);
463     incIndent();
464   }
465
466   @Override
467   public void setTypeParameterAnnotation(ClassFile cf, Object tag, int annotationIndex, int targetType, 
468                                          int typeIndex, short[] typePath, String annotationType){
469     pw.printf("%s[%d]: %s (%s, type path=%s, type index=%d)", indent, annotationIndex, annotationType, 
470             ClassFile.getTargetTypeName(targetType), ClassFile.getTypePathEncoding(typePath), typeIndex);
471   }
472   @Override
473   public void setSuperTypeAnnotation(ClassFile cf, Object tag, int annotationIndex, int targetType, 
474                                      int superTypeIdx, short[] typePath, String annotationType){
475     pw.printf("%s[%d]: %s (%s, type path=%s, super type index=%d)", indent, annotationIndex, annotationType, 
476             ClassFile.getTargetTypeName(targetType),  ClassFile.getTypePathEncoding(typePath), superTypeIdx);
477   }
478   @Override
479   public void setTypeParameterBoundAnnotation(ClassFile cf, Object tag, int annotationIndex, int targetType,
480                                      int typeParamIdx, int boundIdx, short[] typePath, String annotationType){
481     pw.printf("%s[%d]: %s (%s, type path=%s, type index=%d, bound=%d)", indent, annotationIndex, annotationType,
482             ClassFile.getTargetTypeName(targetType),  ClassFile.getTypePathEncoding(typePath), typeParamIdx, boundIdx);
483   }
484   @Override
485   public void setTypeAnnotation(ClassFile cf, Object tag, int annotationIndex, int targetType,
486                                 short[] typePath, String annotationType){
487     pw.printf("%s[%d]: %s (%s, type path=%s)", indent, annotationIndex, annotationType,
488             ClassFile.getTargetTypeName(targetType), ClassFile.getTypePathEncoding(typePath));
489   }
490   @Override
491   public void setFormalParameterAnnotation(ClassFile cf, Object tag, int annotationIndex, int targetType, 
492                                            int formalParamIdx, short[] typePath, String annotationType){
493     pw.printf("%s[%d]: %s (%s, type path=%s, formal param index=%d)", indent, annotationIndex, annotationType,
494             ClassFile.getTargetTypeName(targetType),  ClassFile.getTypePathEncoding(typePath), formalParamIdx);
495   }
496   @Override
497   public void setThrowsAnnotation(ClassFile cf, Object tag, int annotationIndex, int targetType, 
498                                   int throwsTypeIdx, short[] typePath, String annotationType){
499     pw.printf("%s[%d]: %s (%s, type path=%s, throws index=%d)", indent, annotationIndex, annotationType, 
500             ClassFile.getTargetTypeName(targetType),  ClassFile.getTypePathEncoding(typePath), throwsTypeIdx);
501   }
502   @Override
503   public void setVariableAnnotation(ClassFile cf, Object tag, int annotationIndex, int targetType, 
504                                     long[] scopeEntries, short[] typePath, String annotationType){
505     pw.printf("%s[%d]: %s (%s, type path=%s, scope=%s)", indent, annotationIndex, annotationType, 
506             ClassFile.getTargetTypeName(targetType), ClassFile.getTypePathEncoding(typePath), ClassFile.getScopeEncoding(scopeEntries));
507     // 2do
508   }
509   @Override
510   public void setExceptionParameterAnnotation(ClassFile cf, Object tag, int annotationIndex, int targetType, 
511                                               int exceptionIndex, short[] typePath, String annotationType){
512     pw.printf("%s[%d]: %s (%s, type path=%s, catch type index=%d)", indent, annotationIndex, annotationType, 
513             ClassFile.getTargetTypeName(targetType),  ClassFile.getTypePathEncoding(typePath), exceptionIndex);
514   }
515   @Override
516   public void setBytecodeAnnotation(ClassFile cf, Object tag, int annotationIndex, int targetType, 
517                                     int offset, short[] typePath, String annotationType){
518     pw.printf("%s[%d]: %s (%s, type path=%s, bytecode offset=%d)", indent, annotationIndex, annotationType, 
519             ClassFile.getTargetTypeName(targetType), ClassFile.getTypePathEncoding(typePath), offset);
520   }
521   @Override
522   public void setBytecodeTypeParameterAnnotation(ClassFile cf, Object tag, int annotationIndex, int targetType, 
523                                            int offset, int typeArgIdx, short[] typePath, String annotationType){
524     pw.printf("%s[%d]: %s (%s, type path=%s, bytecode offset=%d, type arg=%d)", indent, annotationIndex, annotationType, 
525             ClassFile.getTargetTypeName(targetType), ClassFile.getTypePathEncoding(typePath), offset, typeArgIdx);
526   }
527   
528   @Override
529   public void setTypeAnnotationsDone(ClassFile cf, Object tag) {
530     decIndent();
531   }
532     
533   @Override
534   public void setAnnotationValueCount(ClassFile cf, Object tag, int annotationIndex, int nValuePairs){
535     pw.printf(" valueCount=%d\n", nValuePairs);
536     incIndent();
537   }
538
539   @Override
540   public void setPrimitiveAnnotationValue(ClassFile cf, Object tag, int annotationIndex, int valueIndex,
541           String elementName, int arrayIndex, Object val){
542     if (arrayIndex < 0){
543       pw.printf("%s[%d]: %s=%s\n", indent, annotationIndex, elementName, val);
544     } else {
545       if (arrayIndex==0) {
546         pw.printf("%s[%d]: %s={", indent, valueIndex, elementName);
547       }  else {
548         pw.print(',');
549       }
550       pw.print(val);
551     }
552   }
553
554   @Override
555   public void setStringAnnotationValue(ClassFile cf, Object tag, int annotationIndex, int valueIndex,
556           String elementName, int arrayIndex, String s){
557     if (arrayIndex < 0){
558       pw.printf("%s[%d]: %s=\"%s\"\n", indent, annotationIndex, elementName, s);
559     } else {
560       if (arrayIndex==0) {
561         pw.printf("%s[%d]: %s={", indent, valueIndex, elementName);
562       }  else {
563         pw.print(',');
564       }
565       pw.printf("\"%s\"", s);
566     }
567   }
568
569   @Override
570   public void setClassAnnotationValue(ClassFile cf, Object tag, int annotationIndex, int valueIndex,
571           String elementName, int arrayIndex, String typeName){
572     if (arrayIndex < 0){
573       pw.printf("%s[%d]: %s=class %s\n", indent, annotationIndex, elementName, typeName);
574     } else {
575       if (arrayIndex==0) {
576         pw.printf("%s[%d]: %s={", indent, valueIndex, elementName);
577       }  else {
578         pw.print(',');
579       }
580       pw.printf("class %s", typeName);
581     }
582   }
583
584   @Override
585   public void setEnumAnnotationValue(ClassFile cf, Object tag, int annotationIndex, int valueIndex,
586           String elementName, int arrayIndex, String enumType, String enumValue){
587     if (arrayIndex < 0){
588       pw.printf("%s[%d]: %s=%s.%s\n", indent, annotationIndex, elementName, enumType, enumValue);
589     } else {
590       if (arrayIndex==0) {
591         pw.printf("%s[%d]: %s={", indent, valueIndex, elementName);
592       }  else {
593         pw.print(',');
594       }
595       pw.printf("%s.%s", enumType, enumValue);
596     }
597   }
598
599
600   @Override
601   public void setAnnotationValueElementCount(ClassFile cf, Object tag, int annotationIndex, int valueIndex,
602           String elementName, int elementCount){
603   }
604   @Override
605   public void setAnnotationValueElementsDone(ClassFile cf, Object tag, int annotationIndex, int valueIndex,
606           String elementName){
607     pw.println("}");
608   }
609
610   @Override
611   public void setAnnotationValuesDone(ClassFile cf, Object tag, int annotationIndex){
612     decIndent();
613   }
614
615   @Override
616   public void setParameterCount(ClassFile cf, Object tag, int parameterCount){
617     pw.printf(" parameterCount=%d\n", parameterCount);
618     incIndent();
619   }
620
621   @Override
622   public void setParameterAnnotationCount(ClassFile cf, Object tag, int paramIndex, int annotationCount){
623     pw.printf("%s[%d] count: %d\n", indent, paramIndex, annotationCount);
624     incIndent();
625   }
626
627   @Override
628   public void setParameterAnnotation(ClassFile cf, Object tag, int annotationIndex, String annotationType){
629     pw.printf("%s[%d]: %s", indent, annotationIndex, annotationType);
630   }
631
632   @Override
633   public void setParameterAnnotationsDone(ClassFile cf, Object tag, int paramIndex){
634     decIndent();
635   }
636
637   @Override
638   public void setParametersDone(ClassFile cf, Object tag){
639     decIndent();
640   }
641
642
643   @Override
644   public void setSignature(ClassFile cf, Object tag, String signature){
645     pw.printf(" %s\n", signature);
646   }
647
648   //--- internal stuff
649
650   protected void printCp (PrintWriter pw, ClassFile cf){
651     int nCpEntries = cf.getNumberOfCpEntries();
652
653     for (int i=1; i<nCpEntries; i++){
654
655       int j = cf.getDataPosOfCpEntry(i);
656
657       pw.print("  [");
658       pw.print(i);
659       pw.print("]: ");
660
661       if (j < 0) {
662         pw.println("<unused>");
663         continue;
664       }
665
666       switch (cf.u1(j)){
667         case ClassFile.CONSTANT_UTF8:
668           pw.print( "constant_utf8 {\"");
669           pw.print( cf.getCpValue(i));
670           pw.println("\"}");
671           break;
672         case ClassFile.CONSTANT_INTEGER:
673           pw.print( "constant_integer {");
674           pw.print( cf.getCpValue(i));
675           pw.println("}");
676           break;
677         case ClassFile.CONSTANT_FLOAT:
678           pw.print( "constant_float {");
679           pw.print( cf.getCpValue(i));
680           pw.println("}");
681           break;
682         case ClassFile.CONSTANT_LONG:
683           pw.print( "constant_long {");
684           pw.print( cf.getCpValue(i));
685           pw.println("}");
686           break;
687         case ClassFile.CONSTANT_DOUBLE:
688           pw.print( "constant_double {");
689           pw.print( cf.getCpValue(i));
690           pw.println("}");
691           break;
692         case ClassFile.CONSTANT_CLASS:
693           pw.print("constant_class {name=#");
694           pw.print( cf.u2(j+1));
695           pw.print("(\"");
696           pw.print( cf.classNameAt(i));
697           pw.println("\")}");
698           break;
699         case ClassFile.CONSTANT_STRING:
700           pw.print("constant_string {utf8=#");
701           pw.print( cf.u2(j+1));
702           pw.print("(\"");
703           pw.print( cf.stringAt(i));
704           pw.println("\")}");
705           break;
706         case ClassFile.FIELD_REF:
707           printRef(pw, cf, i, j, "fieldref");
708           break;
709         case ClassFile.METHOD_REF:
710           printRef(pw, cf, i, j, "methodref");
711           break;
712         case ClassFile.INTERFACE_METHOD_REF:
713           printRef(pw, cf, i, j, "interface_methodref");
714           break;
715         case ClassFile.NAME_AND_TYPE:
716           pw.print("name_and_type {name=#");
717           pw.print( cf.u2(j+1));
718           pw.print("(\"");
719           pw.print(cf.utf8At(cf.u2(j+1)));
720           pw.print("\"),desciptor=#");
721           pw.print( cf.u2(j+3));
722           pw.print("(\"");
723           pw.print(cf.utf8At(cf.u2(j+3)));
724           pw.println("\")}");
725           break;
726           
727         case ClassFile.METHOD_HANDLE:
728           pw.print("method_handle {");
729           pw.print("(\"");
730           pw.println("\")}");
731           break;
732           
733         case ClassFile.METHOD_TYPE:
734           pw.print("method_type {");
735           pw.print("(\"");
736           pw.println("\")}");
737           break;
738           
739         case ClassFile.INVOKE_DYNAMIC:
740           pw.print("invoke_dynamic {bootstrap=#");
741           pw.print(cf.u2(j+1));
742           pw.print("(\"");
743           pw.println("\")}");
744           break;
745           
746         default:
747           pw.print("ERROR: illegal tag" + cf.u1(j));
748       }
749     }
750     pw.println();
751   }
752
753   void printRef(PrintWriter pw, ClassFile cf, int cpIdx, int dataPos, String refType){
754     pw.print(refType);
755     pw.print(" {class=#");
756     pw.print(cf.u2(dataPos + 1));
757     pw.print("(\"");
758     pw.print(cf.refClassNameAt(cpIdx));
759     pw.print("\"),nameType=#");
760     pw.print(cf.u2(dataPos + 3));
761     pw.print("(\"");
762     pw.print(cf.refNameAt(cpIdx));
763     pw.print("\",\"");
764     pw.print(cf.refDescriptorAt(cpIdx));
765     pw.println("\")}");
766   }
767
768   void printRawData(PrintWriter pw, ClassFile cf, int dataLength, int maxBytes){
769     int max = Math.min(dataLength, maxBytes);
770     int max1 = max-1;
771     for (int i=0; i<max1; i++){
772       pw.printf("%02x ", cf.readUByte());
773     }
774     pw.printf("%02x", cf.readUByte());
775
776     if (dataLength>maxBytes){
777       pw.print("..");
778     }
779   }
780
781   @Override
782   public void setAnnotationFieldValue(ClassFile cf, Object tag, int annotationIndex, int valueIndex, String elementName, int arrayIndex) {
783     
784   }
785 }