langtools/src/jdk.compiler/share/classes/com/sun/tools/javap/AttributeWriter.java
changeset 30846 2b3f379840f0
parent 30845 43ddd58a5a56
child 30847 9385b9c8506b
equal deleted inserted replaced
30845:43ddd58a5a56 30846:2b3f379840f0
     1 /*
       
     2  * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.sun.tools.javap;
       
    27 
       
    28 import java.util.Formatter;
       
    29 
       
    30 import com.sun.tools.classfile.AccessFlags;
       
    31 import com.sun.tools.classfile.AnnotationDefault_attribute;
       
    32 import com.sun.tools.classfile.Attribute;
       
    33 import com.sun.tools.classfile.Attributes;
       
    34 import com.sun.tools.classfile.BootstrapMethods_attribute;
       
    35 import com.sun.tools.classfile.CharacterRangeTable_attribute;
       
    36 import com.sun.tools.classfile.Code_attribute;
       
    37 import com.sun.tools.classfile.CompilationID_attribute;
       
    38 import com.sun.tools.classfile.ConstantPool;
       
    39 import com.sun.tools.classfile.ConstantPoolException;
       
    40 import com.sun.tools.classfile.ConstantValue_attribute;
       
    41 import com.sun.tools.classfile.DefaultAttribute;
       
    42 import com.sun.tools.classfile.Deprecated_attribute;
       
    43 import com.sun.tools.classfile.EnclosingMethod_attribute;
       
    44 import com.sun.tools.classfile.Exceptions_attribute;
       
    45 import com.sun.tools.classfile.InnerClasses_attribute;
       
    46 import com.sun.tools.classfile.LineNumberTable_attribute;
       
    47 import com.sun.tools.classfile.LocalVariableTable_attribute;
       
    48 import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
       
    49 import com.sun.tools.classfile.MethodParameters_attribute;
       
    50 import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
       
    51 import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
       
    52 import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
       
    53 import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
       
    54 import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute;
       
    55 import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute;
       
    56 import com.sun.tools.classfile.Signature_attribute;
       
    57 import com.sun.tools.classfile.SourceDebugExtension_attribute;
       
    58 import com.sun.tools.classfile.SourceFile_attribute;
       
    59 import com.sun.tools.classfile.SourceID_attribute;
       
    60 import com.sun.tools.classfile.StackMapTable_attribute;
       
    61 import com.sun.tools.classfile.StackMap_attribute;
       
    62 import com.sun.tools.classfile.Synthetic_attribute;
       
    63 
       
    64 import static com.sun.tools.classfile.AccessFlags.*;
       
    65 
       
    66 import com.sun.tools.javac.util.Assert;
       
    67 import com.sun.tools.javac.util.StringUtils;
       
    68 
       
    69 /*
       
    70  *  A writer for writing Attributes as text.
       
    71  *
       
    72  *  <p><b>This is NOT part of any supported API.
       
    73  *  If you write code that depends on this, you do so at your own risk.
       
    74  *  This code and its internal interfaces are subject to change or
       
    75  *  deletion without notice.</b>
       
    76  */
       
    77 public class AttributeWriter extends BasicWriter
       
    78         implements Attribute.Visitor<Void,Void>
       
    79 {
       
    80     public static AttributeWriter instance(Context context) {
       
    81         AttributeWriter instance = context.get(AttributeWriter.class);
       
    82         if (instance == null)
       
    83             instance = new AttributeWriter(context);
       
    84         return instance;
       
    85     }
       
    86 
       
    87     protected AttributeWriter(Context context) {
       
    88         super(context);
       
    89         context.put(AttributeWriter.class, this);
       
    90         annotationWriter = AnnotationWriter.instance(context);
       
    91         codeWriter = CodeWriter.instance(context);
       
    92         constantWriter = ConstantWriter.instance(context);
       
    93         options = Options.instance(context);
       
    94     }
       
    95 
       
    96     public void write(Object owner, Attribute attr, ConstantPool constant_pool) {
       
    97         if (attr != null) {
       
    98             Assert.checkNonNull(constant_pool);
       
    99             Assert.checkNonNull(owner);
       
   100             this.constant_pool = constant_pool;
       
   101             this.owner = owner;
       
   102             attr.accept(this, null);
       
   103         }
       
   104     }
       
   105 
       
   106     public void write(Object owner, Attributes attrs, ConstantPool constant_pool) {
       
   107         if (attrs != null) {
       
   108             Assert.checkNonNull(constant_pool);
       
   109             Assert.checkNonNull(owner);
       
   110             this.constant_pool = constant_pool;
       
   111             this.owner = owner;
       
   112             for (Attribute attr: attrs)
       
   113                 attr.accept(this, null);
       
   114         }
       
   115     }
       
   116 
       
   117     public Void visitDefault(DefaultAttribute attr, Void ignore) {
       
   118         if (attr.reason != null) {
       
   119             report(attr.reason);
       
   120         }
       
   121         byte[] data = attr.info;
       
   122         int i = 0;
       
   123         int j = 0;
       
   124         print("  ");
       
   125         try {
       
   126             print(attr.getName(constant_pool));
       
   127         } catch (ConstantPoolException e) {
       
   128             report(e);
       
   129             print("attribute name = #" + attr.attribute_name_index);
       
   130         }
       
   131         print(": ");
       
   132         println("length = 0x" + toHex(attr.info.length));
       
   133 
       
   134         print("   ");
       
   135 
       
   136         while (i < data.length) {
       
   137             print(toHex(data[i], 2));
       
   138 
       
   139             j++;
       
   140             if (j == 16) {
       
   141                 println();
       
   142                 print("   ");
       
   143                 j = 0;
       
   144             } else {
       
   145                 print(" ");
       
   146             }
       
   147             i++;
       
   148         }
       
   149         println();
       
   150         return null;
       
   151     }
       
   152 
       
   153     public Void visitAnnotationDefault(AnnotationDefault_attribute attr, Void ignore) {
       
   154         println("AnnotationDefault:");
       
   155         indent(+1);
       
   156         print("default_value: ");
       
   157         annotationWriter.write(attr.default_value);
       
   158         indent(-1);
       
   159         return null;
       
   160     }
       
   161 
       
   162     public Void visitBootstrapMethods(BootstrapMethods_attribute attr, Void p) {
       
   163         println(Attribute.BootstrapMethods + ":");
       
   164         for (int i = 0; i < attr.bootstrap_method_specifiers.length ; i++) {
       
   165             BootstrapMethods_attribute.BootstrapMethodSpecifier bsm = attr.bootstrap_method_specifiers[i];
       
   166             indent(+1);
       
   167             print(i + ": #" + bsm.bootstrap_method_ref + " ");
       
   168             println(constantWriter.stringValue(bsm.bootstrap_method_ref));
       
   169             indent(+1);
       
   170             println("Method arguments:");
       
   171             indent(+1);
       
   172             for (int j = 0; j < bsm.bootstrap_arguments.length; j++) {
       
   173                 print("#" + bsm.bootstrap_arguments[j] + " ");
       
   174                 println(constantWriter.stringValue(bsm.bootstrap_arguments[j]));
       
   175             }
       
   176             indent(-3);
       
   177         }
       
   178         return null;
       
   179     }
       
   180 
       
   181     public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, Void ignore) {
       
   182         println("CharacterRangeTable:");
       
   183         indent(+1);
       
   184         for (int i = 0; i < attr.character_range_table.length; i++) {
       
   185             CharacterRangeTable_attribute.Entry e = attr.character_range_table[i];
       
   186             print(String.format("    %2d, %2d, %6x, %6x, %4x",
       
   187                     e.start_pc, e.end_pc,
       
   188                     e.character_range_start, e.character_range_end,
       
   189                     e.flags));
       
   190             tab();
       
   191             print(String.format("// %2d, %2d, %4d:%02d, %4d:%02d",
       
   192                     e.start_pc, e.end_pc,
       
   193                     (e.character_range_start >> 10), (e.character_range_start & 0x3ff),
       
   194                     (e.character_range_end >> 10), (e.character_range_end & 0x3ff)));
       
   195             if ((e.flags & CharacterRangeTable_attribute.CRT_STATEMENT) != 0)
       
   196                 print(", statement");
       
   197             if ((e.flags & CharacterRangeTable_attribute.CRT_BLOCK) != 0)
       
   198                 print(", block");
       
   199             if ((e.flags & CharacterRangeTable_attribute.CRT_ASSIGNMENT) != 0)
       
   200                 print(", assignment");
       
   201             if ((e.flags & CharacterRangeTable_attribute.CRT_FLOW_CONTROLLER) != 0)
       
   202                 print(", flow-controller");
       
   203             if ((e.flags & CharacterRangeTable_attribute.CRT_FLOW_TARGET) != 0)
       
   204                 print(", flow-target");
       
   205             if ((e.flags & CharacterRangeTable_attribute.CRT_INVOKE) != 0)
       
   206                 print(", invoke");
       
   207             if ((e.flags & CharacterRangeTable_attribute.CRT_CREATE) != 0)
       
   208                 print(", create");
       
   209             if ((e.flags & CharacterRangeTable_attribute.CRT_BRANCH_TRUE) != 0)
       
   210                 print(", branch-true");
       
   211             if ((e.flags & CharacterRangeTable_attribute.CRT_BRANCH_FALSE) != 0)
       
   212                 print(", branch-false");
       
   213             println();
       
   214         }
       
   215         indent(-1);
       
   216         return null;
       
   217     }
       
   218 
       
   219     public Void visitCode(Code_attribute attr, Void ignore) {
       
   220         codeWriter.write(attr, constant_pool);
       
   221         return null;
       
   222     }
       
   223 
       
   224     public Void visitCompilationID(CompilationID_attribute attr, Void ignore) {
       
   225         constantWriter.write(attr.compilationID_index);
       
   226         return null;
       
   227     }
       
   228 
       
   229     public Void visitConstantValue(ConstantValue_attribute attr, Void ignore) {
       
   230         print("ConstantValue: ");
       
   231         constantWriter.write(attr.constantvalue_index);
       
   232         println();
       
   233         return null;
       
   234     }
       
   235 
       
   236     public Void visitDeprecated(Deprecated_attribute attr, Void ignore) {
       
   237         println("Deprecated: true");
       
   238         return null;
       
   239     }
       
   240 
       
   241     public Void visitEnclosingMethod(EnclosingMethod_attribute attr, Void ignore) {
       
   242         print("EnclosingMethod: #" + attr.class_index + ".#" + attr.method_index);
       
   243         tab();
       
   244         print("// " + getJavaClassName(attr));
       
   245         if (attr.method_index != 0)
       
   246             print("." + getMethodName(attr));
       
   247         println();
       
   248         return null;
       
   249     }
       
   250 
       
   251     private String getJavaClassName(EnclosingMethod_attribute a) {
       
   252         try {
       
   253             return getJavaName(a.getClassName(constant_pool));
       
   254         } catch (ConstantPoolException e) {
       
   255             return report(e);
       
   256         }
       
   257     }
       
   258 
       
   259     private String getMethodName(EnclosingMethod_attribute a) {
       
   260         try {
       
   261             return a.getMethodName(constant_pool);
       
   262         } catch (ConstantPoolException e) {
       
   263             return report(e);
       
   264         }
       
   265     }
       
   266 
       
   267     public Void visitExceptions(Exceptions_attribute attr, Void ignore) {
       
   268         println("Exceptions:");
       
   269         indent(+1);
       
   270         print("throws ");
       
   271         for (int i = 0; i < attr.number_of_exceptions; i++) {
       
   272             if (i > 0)
       
   273                 print(", ");
       
   274             print(getJavaException(attr, i));
       
   275         }
       
   276         println();
       
   277         indent(-1);
       
   278         return null;
       
   279     }
       
   280 
       
   281     private String getJavaException(Exceptions_attribute attr, int index) {
       
   282         try {
       
   283             return getJavaName(attr.getException(index, constant_pool));
       
   284         } catch (ConstantPoolException e) {
       
   285             return report(e);
       
   286         }
       
   287     }
       
   288 
       
   289     public Void visitInnerClasses(InnerClasses_attribute attr, Void ignore) {
       
   290         boolean first = true;
       
   291         for (int i = 0 ; i < attr.classes.length; i++) {
       
   292             InnerClasses_attribute.Info info = attr.classes[i];
       
   293             //access
       
   294             AccessFlags access_flags = info.inner_class_access_flags;
       
   295             if (options.checkAccess(access_flags)) {
       
   296                 if (first) {
       
   297                     writeInnerClassHeader();
       
   298                     first = false;
       
   299                 }
       
   300                 for (String name: access_flags.getInnerClassModifiers())
       
   301                     print(name + " ");
       
   302                 if (info.inner_name_index != 0) {
       
   303                     print("#" + info.inner_name_index + "= ");
       
   304                 }
       
   305                 print("#" + info.inner_class_info_index);
       
   306                 if (info.outer_class_info_index != 0) {
       
   307                     print(" of #" + info.outer_class_info_index);
       
   308                 }
       
   309                 print(";");
       
   310                 tab();
       
   311                 print("// ");
       
   312                 if (info.inner_name_index != 0) {
       
   313                     print(getInnerName(constant_pool, info) + "=");
       
   314                 }
       
   315                 constantWriter.write(info.inner_class_info_index);
       
   316                 if (info.outer_class_info_index != 0) {
       
   317                     print(" of ");
       
   318                     constantWriter.write(info.outer_class_info_index);
       
   319                 }
       
   320                 println();
       
   321             }
       
   322         }
       
   323         if (!first)
       
   324             indent(-1);
       
   325         return null;
       
   326     }
       
   327 
       
   328     String getInnerName(ConstantPool constant_pool, InnerClasses_attribute.Info info) {
       
   329         try {
       
   330             return info.getInnerName(constant_pool);
       
   331         } catch (ConstantPoolException e) {
       
   332             return report(e);
       
   333         }
       
   334     }
       
   335 
       
   336     private void writeInnerClassHeader() {
       
   337         println("InnerClasses:");
       
   338         indent(+1);
       
   339     }
       
   340 
       
   341     public Void visitLineNumberTable(LineNumberTable_attribute attr, Void ignore) {
       
   342         println("LineNumberTable:");
       
   343         indent(+1);
       
   344         for (LineNumberTable_attribute.Entry entry: attr.line_number_table) {
       
   345             println("line " + entry.line_number + ": " + entry.start_pc);
       
   346         }
       
   347         indent(-1);
       
   348         return null;
       
   349     }
       
   350 
       
   351     public Void visitLocalVariableTable(LocalVariableTable_attribute attr, Void ignore) {
       
   352         println("LocalVariableTable:");
       
   353         indent(+1);
       
   354         println("Start  Length  Slot  Name   Signature");
       
   355         for (LocalVariableTable_attribute.Entry entry : attr.local_variable_table) {
       
   356             println(String.format("%5d %7d %5d %5s   %s",
       
   357                     entry.start_pc, entry.length, entry.index,
       
   358                     constantWriter.stringValue(entry.name_index),
       
   359                     constantWriter.stringValue(entry.descriptor_index)));
       
   360         }
       
   361         indent(-1);
       
   362         return null;
       
   363     }
       
   364 
       
   365     public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, Void ignore) {
       
   366         println("LocalVariableTypeTable:");
       
   367         indent(+1);
       
   368         println("Start  Length  Slot  Name   Signature");
       
   369         for (LocalVariableTypeTable_attribute.Entry entry : attr.local_variable_table) {
       
   370             println(String.format("%5d %7d %5d %5s   %s",
       
   371                     entry.start_pc, entry.length, entry.index,
       
   372                     constantWriter.stringValue(entry.name_index),
       
   373                     constantWriter.stringValue(entry.signature_index)));
       
   374         }
       
   375         indent(-1);
       
   376         return null;
       
   377     }
       
   378 
       
   379     private static final String format = "%-31s%s";
       
   380 
       
   381     public Void visitMethodParameters(MethodParameters_attribute attr,
       
   382                                       Void ignore) {
       
   383 
       
   384         final String header = String.format(format, "Name", "Flags");
       
   385         println("MethodParameters:");
       
   386         indent(+1);
       
   387         println(header);
       
   388         for (MethodParameters_attribute.Entry entry :
       
   389                  attr.method_parameter_table) {
       
   390             String namestr =
       
   391                 entry.name_index != 0 ?
       
   392                 constantWriter.stringValue(entry.name_index) : "<no name>";
       
   393             String flagstr =
       
   394                 (0 != (entry.flags & ACC_FINAL) ? "final " : "") +
       
   395                 (0 != (entry.flags & ACC_MANDATED) ? "mandated " : "") +
       
   396                 (0 != (entry.flags & ACC_SYNTHETIC) ? "synthetic" : "");
       
   397             println(String.format(format, namestr, flagstr));
       
   398         }
       
   399         indent(-1);
       
   400         return null;
       
   401     }
       
   402 
       
   403     public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, Void ignore) {
       
   404         println("RuntimeVisibleAnnotations:");
       
   405         indent(+1);
       
   406         for (int i = 0; i < attr.annotations.length; i++) {
       
   407             print(i + ": ");
       
   408             annotationWriter.write(attr.annotations[i]);
       
   409             println();
       
   410         }
       
   411         indent(-1);
       
   412         return null;
       
   413     }
       
   414 
       
   415     public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, Void ignore) {
       
   416         println("RuntimeInvisibleAnnotations:");
       
   417         indent(+1);
       
   418         for (int i = 0; i < attr.annotations.length; i++) {
       
   419             print(i + ": ");
       
   420             annotationWriter.write(attr.annotations[i]);
       
   421             println();
       
   422         }
       
   423         indent(-1);
       
   424         return null;
       
   425     }
       
   426 
       
   427     public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) {
       
   428         println("RuntimeVisibleTypeAnnotations:");
       
   429         indent(+1);
       
   430         for (int i = 0; i < attr.annotations.length; i++) {
       
   431             print(i + ": ");
       
   432             annotationWriter.write(attr.annotations[i]);
       
   433             println();
       
   434         }
       
   435         indent(-1);
       
   436         return null;
       
   437     }
       
   438 
       
   439     public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) {
       
   440         println("RuntimeInvisibleTypeAnnotations:");
       
   441         indent(+1);
       
   442         for (int i = 0; i < attr.annotations.length; i++) {
       
   443             print(i + ": ");
       
   444             annotationWriter.write(attr.annotations[i]);
       
   445             println();
       
   446         }
       
   447         indent(-1);
       
   448         return null;
       
   449     }
       
   450 
       
   451     public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) {
       
   452         println("RuntimeVisibleParameterAnnotations:");
       
   453         indent(+1);
       
   454         for (int param = 0; param < attr.parameter_annotations.length; param++) {
       
   455             println("parameter " + param + ": ");
       
   456             indent(+1);
       
   457             for (int i = 0; i < attr.parameter_annotations[param].length; i++) {
       
   458                 print(i + ": ");
       
   459                 annotationWriter.write(attr.parameter_annotations[param][i]);
       
   460                 println();
       
   461             }
       
   462             indent(-1);
       
   463         }
       
   464         indent(-1);
       
   465         return null;
       
   466     }
       
   467 
       
   468     public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, Void ignore) {
       
   469         println("RuntimeInvisibleParameterAnnotations:");
       
   470         indent(+1);
       
   471         for (int param = 0; param < attr.parameter_annotations.length; param++) {
       
   472             println(param + ": ");
       
   473             indent(+1);
       
   474             for (int i = 0; i < attr.parameter_annotations[param].length; i++) {
       
   475                 print(i + ": ");
       
   476                 annotationWriter.write(attr.parameter_annotations[param][i]);
       
   477                 println();
       
   478             }
       
   479             indent(-1);
       
   480         }
       
   481         indent(-1);
       
   482         return null;
       
   483     }
       
   484 
       
   485     public Void visitSignature(Signature_attribute attr, Void ignore) {
       
   486         print("Signature: #" + attr.signature_index);
       
   487         tab();
       
   488         println("// " + getSignature(attr));
       
   489         return null;
       
   490     }
       
   491 
       
   492     String getSignature(Signature_attribute info) {
       
   493         try {
       
   494             return info.getSignature(constant_pool);
       
   495         } catch (ConstantPoolException e) {
       
   496             return report(e);
       
   497         }
       
   498     }
       
   499 
       
   500     public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, Void ignore) {
       
   501         println("SourceDebugExtension:");
       
   502         indent(+1);
       
   503         for (String s: attr.getValue().split("[\r\n]+")) {
       
   504             println(s);
       
   505         }
       
   506         indent(-1);
       
   507         return null;
       
   508     }
       
   509 
       
   510     public Void visitSourceFile(SourceFile_attribute attr, Void ignore) {
       
   511         println("SourceFile: \"" + getSourceFile(attr) + "\"");
       
   512         return null;
       
   513     }
       
   514 
       
   515     private String getSourceFile(SourceFile_attribute attr) {
       
   516         try {
       
   517             return attr.getSourceFile(constant_pool);
       
   518         } catch (ConstantPoolException e) {
       
   519             return report(e);
       
   520         }
       
   521     }
       
   522 
       
   523     public Void visitSourceID(SourceID_attribute attr, Void ignore) {
       
   524         constantWriter.write(attr.sourceID_index);
       
   525         return null;
       
   526     }
       
   527 
       
   528     public Void visitStackMap(StackMap_attribute attr, Void ignore) {
       
   529         println("StackMap: number_of_entries = " + attr.number_of_entries);
       
   530         indent(+1);
       
   531         StackMapTableWriter w = new StackMapTableWriter();
       
   532         for (StackMapTable_attribute.stack_map_frame entry : attr.entries) {
       
   533             w.write(entry);
       
   534         }
       
   535         indent(-1);
       
   536         return null;
       
   537     }
       
   538 
       
   539     public Void visitStackMapTable(StackMapTable_attribute attr, Void ignore) {
       
   540         println("StackMapTable: number_of_entries = " + attr.number_of_entries);
       
   541         indent(+1);
       
   542         StackMapTableWriter w = new StackMapTableWriter();
       
   543         for (StackMapTable_attribute.stack_map_frame entry : attr.entries) {
       
   544             w.write(entry);
       
   545         }
       
   546         indent(-1);
       
   547         return null;
       
   548     }
       
   549 
       
   550     class StackMapTableWriter // also handles CLDC StackMap attributes
       
   551             implements StackMapTable_attribute.stack_map_frame.Visitor<Void,Void> {
       
   552         public void write(StackMapTable_attribute.stack_map_frame frame) {
       
   553             frame.accept(this, null);
       
   554         }
       
   555 
       
   556         public Void visit_same_frame(StackMapTable_attribute.same_frame frame, Void p) {
       
   557             printHeader(frame, "/* same */");
       
   558             return null;
       
   559         }
       
   560 
       
   561         public Void visit_same_locals_1_stack_item_frame(StackMapTable_attribute.same_locals_1_stack_item_frame frame, Void p) {
       
   562             printHeader(frame, "/* same_locals_1_stack_item */");
       
   563             indent(+1);
       
   564             printMap("stack", frame.stack);
       
   565             indent(-1);
       
   566             return null;
       
   567         }
       
   568 
       
   569         public Void visit_same_locals_1_stack_item_frame_extended(StackMapTable_attribute.same_locals_1_stack_item_frame_extended frame, Void p) {
       
   570             printHeader(frame, "/* same_locals_1_stack_item_frame_extended */");
       
   571             indent(+1);
       
   572             println("offset_delta = " + frame.offset_delta);
       
   573             printMap("stack", frame.stack);
       
   574             indent(-1);
       
   575             return null;
       
   576         }
       
   577 
       
   578         public Void visit_chop_frame(StackMapTable_attribute.chop_frame frame, Void p) {
       
   579             printHeader(frame, "/* chop */");
       
   580             indent(+1);
       
   581             println("offset_delta = " + frame.offset_delta);
       
   582             indent(-1);
       
   583             return null;
       
   584         }
       
   585 
       
   586         public Void visit_same_frame_extended(StackMapTable_attribute.same_frame_extended frame, Void p) {
       
   587             printHeader(frame, "/* same_frame_extended */");
       
   588             indent(+1);
       
   589             println("offset_delta = " + frame.offset_delta);
       
   590             indent(-1);
       
   591             return null;
       
   592         }
       
   593 
       
   594         public Void visit_append_frame(StackMapTable_attribute.append_frame frame, Void p) {
       
   595             printHeader(frame, "/* append */");
       
   596             indent(+1);
       
   597             println("offset_delta = " + frame.offset_delta);
       
   598             printMap("locals", frame.locals);
       
   599             indent(-1);
       
   600             return null;
       
   601         }
       
   602 
       
   603         public Void visit_full_frame(StackMapTable_attribute.full_frame frame, Void p) {
       
   604             if (frame instanceof StackMap_attribute.stack_map_frame) {
       
   605                 printHeader(frame, "offset = " + frame.offset_delta);
       
   606                 indent(+1);
       
   607             } else {
       
   608                 printHeader(frame, "/* full_frame */");
       
   609                 indent(+1);
       
   610                 println("offset_delta = " + frame.offset_delta);
       
   611             }
       
   612             printMap("locals", frame.locals);
       
   613             printMap("stack", frame.stack);
       
   614             indent(-1);
       
   615             return null;
       
   616         }
       
   617 
       
   618         void printHeader(StackMapTable_attribute.stack_map_frame frame, String extra) {
       
   619             print("frame_type = " + frame.frame_type + " ");
       
   620             println(extra);
       
   621         }
       
   622 
       
   623         void printMap(String name, StackMapTable_attribute.verification_type_info[] map) {
       
   624             print(name + " = [");
       
   625             for (int i = 0; i < map.length; i++) {
       
   626                 StackMapTable_attribute.verification_type_info info = map[i];
       
   627                 int tag = info.tag;
       
   628                 switch (tag) {
       
   629                     case StackMapTable_attribute.verification_type_info.ITEM_Object:
       
   630                         print(" ");
       
   631                         constantWriter.write(((StackMapTable_attribute.Object_variable_info) info).cpool_index);
       
   632                         break;
       
   633                     case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized:
       
   634                         print(" " + mapTypeName(tag));
       
   635                         print(" " + ((StackMapTable_attribute.Uninitialized_variable_info) info).offset);
       
   636                         break;
       
   637                     default:
       
   638                         print(" " + mapTypeName(tag));
       
   639                 }
       
   640                 print(i == (map.length - 1) ? " " : ",");
       
   641             }
       
   642             println("]");
       
   643         }
       
   644 
       
   645         String mapTypeName(int tag) {
       
   646             switch (tag) {
       
   647             case StackMapTable_attribute.verification_type_info.ITEM_Top:
       
   648                 return "top";
       
   649 
       
   650             case StackMapTable_attribute.verification_type_info.ITEM_Integer:
       
   651                 return "int";
       
   652 
       
   653             case StackMapTable_attribute.verification_type_info.ITEM_Float:
       
   654                 return "float";
       
   655 
       
   656             case StackMapTable_attribute.verification_type_info.ITEM_Long:
       
   657                 return "long";
       
   658 
       
   659             case StackMapTable_attribute.verification_type_info.ITEM_Double:
       
   660                 return "double";
       
   661 
       
   662             case StackMapTable_attribute.verification_type_info.ITEM_Null:
       
   663                 return "null";
       
   664 
       
   665             case StackMapTable_attribute.verification_type_info.ITEM_UninitializedThis:
       
   666                 return "this";
       
   667 
       
   668             case StackMapTable_attribute.verification_type_info.ITEM_Object:
       
   669                 return "CP";
       
   670 
       
   671             case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized:
       
   672                 return "uninitialized";
       
   673 
       
   674             default:
       
   675                 report("unrecognized verification_type_info tag: " + tag);
       
   676                 return "[tag:" + tag + "]";
       
   677             }
       
   678         }
       
   679     }
       
   680 
       
   681     public Void visitSynthetic(Synthetic_attribute attr, Void ignore) {
       
   682         println("Synthetic: true");
       
   683         return null;
       
   684     }
       
   685 
       
   686     static String getJavaName(String name) {
       
   687         return name.replace('/', '.');
       
   688     }
       
   689 
       
   690     String toHex(byte b, int w) {
       
   691         return toHex(b & 0xff, w);
       
   692     }
       
   693 
       
   694     static String toHex(int i) {
       
   695         return StringUtils.toUpperCase(Integer.toString(i, 16));
       
   696     }
       
   697 
       
   698     static String toHex(int i, int w) {
       
   699         String s = StringUtils.toUpperCase(Integer.toHexString(i));
       
   700         while (s.length() < w)
       
   701             s = "0" + s;
       
   702         return StringUtils.toUpperCase(s);
       
   703     }
       
   704 
       
   705     private AnnotationWriter annotationWriter;
       
   706     private CodeWriter codeWriter;
       
   707     private ConstantWriter constantWriter;
       
   708     private Options options;
       
   709 
       
   710     private ConstantPool constant_pool;
       
   711     private Object owner;
       
   712 }