langtools/src/share/classes/sun/tools/javap/JavapPrinter.java
changeset 2987 2e0ca9f4893d
parent 2986 5370c4ae4f6f
child 2988 094272984b53
equal deleted inserted replaced
2986:5370c4ae4f6f 2987:2e0ca9f4893d
     1 /*
       
     2  * Copyright 2002-2009 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 
       
    27 package sun.tools.javap;
       
    28 
       
    29 import java.util.*;
       
    30 import java.io.*;
       
    31 
       
    32 import static sun.tools.javap.RuntimeConstants.*;
       
    33 
       
    34 /**
       
    35  * Program to print information about class files
       
    36  *
       
    37  * @author  Sucheta Dambalkar
       
    38  */
       
    39 public class JavapPrinter {
       
    40     JavapEnvironment env;
       
    41     ClassData cls;
       
    42     byte[] code;
       
    43     String lP= "";
       
    44     PrintWriter out;
       
    45 
       
    46     public JavapPrinter(InputStream cname, PrintWriter out, JavapEnvironment env){
       
    47         this.out = out;
       
    48         this.cls =  new ClassData(cname);
       
    49         this.env = env;
       
    50     }
       
    51 
       
    52     /**
       
    53      *  Entry point to print class file information.
       
    54      */
       
    55     public void print(){
       
    56         printclassHeader();
       
    57         printfields();
       
    58         printMethods();
       
    59         printend();
       
    60     }
       
    61 
       
    62     /**
       
    63      * Print a description of the class (not members).
       
    64      */
       
    65     public void printclassHeader(){
       
    66         String srcName="";
       
    67         if ((srcName = cls.getSourceName()) != "null") // requires debug info
       
    68             out.println("Compiled from " + javaclassname(srcName));
       
    69 
       
    70         if(cls.isInterface())   {
       
    71             // The only useful access modifier of an interface is
       
    72             // public; interfaces are always marked as abstract and
       
    73             // cannot be final.
       
    74             out.print((cls.isPublic()?"public ":"") +
       
    75                       "interface "+ javaclassname(cls.getClassName()));
       
    76         }
       
    77         else if(cls.isClass()) {
       
    78             String []accflags =  cls.getAccess();
       
    79             printAccess(accflags);
       
    80             out.print("class "+ javaclassname(cls.getClassName()));
       
    81 
       
    82             if(cls.getSuperClassName() != null){
       
    83                 out.print(" extends " + javaclassname(cls.getSuperClassName()));
       
    84             }
       
    85         }
       
    86 
       
    87         String []interfacelist =  cls.getSuperInterfaces();
       
    88         if(interfacelist.length > 0){
       
    89             if(cls.isClass()) {
       
    90                 out.print(" implements ");
       
    91             }
       
    92             else if(cls.isInterface()){
       
    93                 out.print(" extends ");
       
    94             }
       
    95 
       
    96             for(int j = 0; j < interfacelist.length; j++){
       
    97                 out.print(javaclassname(interfacelist[j]));
       
    98 
       
    99                 if((j+1) < interfacelist.length) {
       
   100                     out.print(",");
       
   101                 }
       
   102             }
       
   103         }
       
   104 
       
   105         // Print class attribute information.
       
   106         if((env.showallAttr) || (env.showVerbose)){
       
   107             printClassAttributes();
       
   108         }
       
   109         // Print verbose output.
       
   110         if(env.showVerbose){
       
   111             printverbosecls();
       
   112         }
       
   113         out.println("{");
       
   114     }
       
   115 
       
   116     /**
       
   117      * Print verbose output.
       
   118      */
       
   119     public void printverbosecls(){
       
   120         out.println("  minor version: "+cls.getMinor_version());
       
   121         out.println("  major version: "+cls.getMajor_version());
       
   122         out.println("  Constant pool:");
       
   123         printcp();
       
   124         env.showallAttr = true;
       
   125     }
       
   126 
       
   127     /**
       
   128      * Print class attribute information.
       
   129      */
       
   130     public void printClassAttributes(){
       
   131         out.println();
       
   132         AttrData[] clsattrs = cls.getAttributes();
       
   133         for(int i = 0; i < clsattrs.length; i++){
       
   134             String clsattrname = clsattrs[i].getAttrName();
       
   135             if(clsattrname.equals("SourceFile")){
       
   136                 out.println("  SourceFile: "+ cls.getSourceName());
       
   137             }else if(clsattrname.equals("InnerClasses")){
       
   138                 printInnerClasses();
       
   139             }else {
       
   140                 printAttrData(clsattrs[i]);
       
   141             }
       
   142         }
       
   143     }
       
   144 
       
   145     /**
       
   146      * Print the fields
       
   147      */
       
   148     public void printfields(){
       
   149         FieldData[] fields = cls.getFields();
       
   150         for(int f = 0; f < fields.length; f++){
       
   151             String[] accflags = fields[f].getAccess();
       
   152             if(checkAccess(accflags)){
       
   153                 if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
       
   154                      ||  env.showInternalSigs || env.showallAttr)){
       
   155                     out.print("    ");
       
   156                 }
       
   157                 printAccess(accflags);
       
   158                 out.println(fields[f].getType()+" " +fields[f].getName()+";");
       
   159                 if (env.showInternalSigs) {
       
   160                     out.println("  Signature: " + (fields[f].getInternalSig()));
       
   161                 }
       
   162 
       
   163                 // print field attribute information.
       
   164                 if (env.showallAttr){
       
   165                     printFieldAttributes(fields[f]);
       
   166 
       
   167                 }
       
   168                 if((env.showDisassembled) || (env.showLineAndLocal)){
       
   169                     out.println();
       
   170                 }
       
   171             }
       
   172         }
       
   173     }
       
   174 
       
   175 
       
   176     /* print field attribute information. */
       
   177     public void printFieldAttributes(FieldData field){
       
   178         Vector<?> fieldattrs = field.getAttributes();
       
   179         for(int j = 0; j < fieldattrs.size(); j++){
       
   180             String fieldattrname = ((AttrData)fieldattrs.elementAt(j)).getAttrName();
       
   181             if(fieldattrname.equals("ConstantValue")){
       
   182                 printConstantValue(field);
       
   183             }else if (fieldattrname.equals("Deprecated")){
       
   184                 out.println("Deprecated: "+ field.isDeprecated());
       
   185             }else if (fieldattrname.equals("Synthetic")){
       
   186                 out.println("  Synthetic: "+ field.isSynthetic());
       
   187             }else {
       
   188                 printAttrData((AttrData)fieldattrs.elementAt(j));
       
   189             }
       
   190         }
       
   191         out.println();
       
   192     }
       
   193 
       
   194     /**
       
   195      * Print the methods
       
   196      */
       
   197     public void printMethods(){
       
   198         MethodData[] methods = cls.getMethods();
       
   199         for(int m = 0; m < methods.length; m++){
       
   200             String[] accflags = methods[m].getAccess();
       
   201             if(checkAccess(accflags)){
       
   202                 if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
       
   203                      ||  env.showInternalSigs || env.showallAttr)){
       
   204                     out.print("    ");
       
   205                 }
       
   206                 printMethodSignature(methods[m], accflags);
       
   207                 printExceptions(methods[m]);
       
   208                 out.println(";");
       
   209 
       
   210                 // Print internal signature of method.
       
   211                 if (env.showInternalSigs){
       
   212                     out.println("  Signature: " + (methods[m].getInternalSig()));
       
   213                 }
       
   214 
       
   215                 //Print disassembled code.
       
   216                 if(env.showDisassembled && ! env.showallAttr) {
       
   217                     printcodeSequence(methods[m]);
       
   218                     printExceptionTable(methods[m]);
       
   219                     out.println();
       
   220                 }
       
   221 
       
   222                 // Print line and local variable attribute information.
       
   223                 if (env.showLineAndLocal) {
       
   224                     printLineNumTable(methods[m]);
       
   225                     printLocVarTable(methods[m]);
       
   226                     out.println();
       
   227                 }
       
   228 
       
   229                 // Print  method attribute information.
       
   230                 if (env.showallAttr){
       
   231                     printMethodAttributes(methods[m]);
       
   232                 }
       
   233             }
       
   234         }
       
   235     }
       
   236 
       
   237     /**
       
   238      * Print method signature.
       
   239      */
       
   240     public void printMethodSignature(MethodData method, String[] accflags){
       
   241         printAccess(accflags);
       
   242 
       
   243         if((method.getName()).equals("<init>")){
       
   244             out.print(javaclassname(cls.getClassName()));
       
   245             out.print(method.getParameters());
       
   246         }else if((method.getName()).equals("<clinit>")){
       
   247             out.print("{}");
       
   248         }else{
       
   249             out.print(method.getReturnType()+" ");
       
   250             out.print(method.getName());
       
   251             out.print(method.getParameters());
       
   252         }
       
   253     }
       
   254 
       
   255     /**
       
   256      * print method attribute information.
       
   257      */
       
   258     public void printMethodAttributes(MethodData method){
       
   259         Vector<?> methodattrs = method.getAttributes();
       
   260         Vector<?> codeattrs =  method.getCodeAttributes();
       
   261         for(int k = 0; k < methodattrs.size(); k++){
       
   262             String methodattrname = ((AttrData)methodattrs.elementAt(k)).getAttrName();
       
   263             if(methodattrname.equals("Code")){
       
   264                 printcodeSequence(method);
       
   265                 printExceptionTable(method);
       
   266                 for(int c = 0; c < codeattrs.size(); c++){
       
   267                     String codeattrname = ((AttrData)codeattrs.elementAt(c)).getAttrName();
       
   268                     if(codeattrname.equals("LineNumberTable")){
       
   269                         printLineNumTable(method);
       
   270                     }else if(codeattrname.equals("LocalVariableTable")){
       
   271                         printLocVarTable(method);
       
   272                     }else if(codeattrname.equals("StackMapTable")) {
       
   273                         // Java SE JSR 202 stack map tables
       
   274                         printStackMapTable(method);
       
   275                     }else if(codeattrname.equals("StackMap")) {
       
   276                         // Java ME CLDC stack maps
       
   277                         printStackMap(method);
       
   278                     } else {
       
   279                         printAttrData((AttrData)codeattrs.elementAt(c));
       
   280                     }
       
   281                 }
       
   282             }else if(methodattrname.equals("Exceptions")){
       
   283                 out.println("  Exceptions: ");
       
   284                 printExceptions(method);
       
   285             }else if (methodattrname.equals("Deprecated")){
       
   286                 out.println("  Deprecated: "+ method.isDeprecated());
       
   287             }else if (methodattrname.equals("Synthetic")){
       
   288                 out.println("  Synthetic: "+ method.isSynthetic());
       
   289             }else {
       
   290                 printAttrData((AttrData)methodattrs.elementAt(k));
       
   291             }
       
   292         }
       
   293         out.println();
       
   294     }
       
   295 
       
   296     /**
       
   297      * Print exceptions.
       
   298      */
       
   299     public void printExceptions(MethodData method){
       
   300         int []exc_index_table = method.get_exc_index_table();
       
   301         if (exc_index_table != null) {
       
   302             if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
       
   303                  ||  env.showInternalSigs || env.showallAttr)){
       
   304                 out.print("    ");
       
   305             }
       
   306             out.print("   throws ");
       
   307             int k;
       
   308             int l = exc_index_table.length;
       
   309 
       
   310             for (k=0; k<l; k++) {
       
   311                 out.print(javaclassname(cls.getClassName(exc_index_table[k])));
       
   312                 if (k<l-1) out.print(", ");
       
   313             }
       
   314         }
       
   315     }
       
   316 
       
   317     /**
       
   318      * Print code sequence.
       
   319      */
       
   320     public void  printcodeSequence(MethodData method){
       
   321         code = method.getCode();
       
   322         if(code != null){
       
   323             out.println("  Code:");
       
   324             if(env.showVerbose){
       
   325                 printVerboseHeader(method);
       
   326             }
       
   327 
       
   328             for (int pc=0; pc < code.length; ) {
       
   329                 out.print("   "+pc+":\t");
       
   330                 pc=pc+printInstr(pc);
       
   331                 out.println();
       
   332             }
       
   333         }
       
   334     }
       
   335 
       
   336     /**
       
   337      * Print instructions.
       
   338      */
       
   339     public int printInstr(int pc){
       
   340         int opcode = getUbyte(pc);
       
   341         int opcode2;
       
   342         String mnem;
       
   343         switch (opcode) {
       
   344         case opc_nonpriv:
       
   345         case opc_priv:
       
   346             opcode2 = getUbyte(pc+1);
       
   347             mnem=Tables.opcName((opcode<<8)+opcode2);
       
   348             if (mnem==null)
       
   349                 // assume all (even nonexistent) priv and nonpriv instructions
       
   350                 // are 2 bytes long
       
   351                 mnem=Tables.opcName(opcode)+" "+opcode2;
       
   352             out.print(mnem);
       
   353             return 2;
       
   354         case opc_wide: {
       
   355             opcode2 = getUbyte(pc+1);
       
   356             mnem=Tables.opcName((opcode<<8)+opcode2);
       
   357             if (mnem==null) {
       
   358                 // nonexistent opcode - but we have to print something
       
   359                 out.print("bytecode "+opcode);
       
   360                 return 1;
       
   361             }
       
   362             out.print(mnem+" "+getUShort(pc+2));
       
   363             if (opcode2==opc_iinc) {
       
   364                 out.print(", "+getShort(pc+4));
       
   365                 return 6;
       
   366             }
       
   367             return 4;
       
   368         }
       
   369         }
       
   370         mnem=Tables.opcName(opcode);
       
   371         if (mnem==null) {
       
   372             // nonexistent opcode - but we have to print something
       
   373             out.print("bytecode "+opcode);
       
   374             return 1;
       
   375         }
       
   376         if (opcode>opc_jsr_w) {
       
   377             // pseudo opcodes should be printed as bytecodes
       
   378             out.print("bytecode "+opcode);
       
   379             return 1;
       
   380         }
       
   381         out.print(Tables.opcName(opcode));
       
   382         switch (opcode) {
       
   383         case opc_aload: case opc_astore:
       
   384         case opc_fload: case opc_fstore:
       
   385         case opc_iload: case opc_istore:
       
   386         case opc_lload: case opc_lstore:
       
   387         case opc_dload: case opc_dstore:
       
   388         case opc_ret:
       
   389             out.print("\t"+getUbyte(pc+1));
       
   390             return  2;
       
   391         case opc_iinc:
       
   392             out.print("\t"+getUbyte(pc+1)+", "+getbyte(pc+2));
       
   393             return  3;
       
   394         case opc_tableswitch:{
       
   395             int tb=align(pc+1);
       
   396             int default_skip = getInt(tb); /* default skip pamount */
       
   397             int low = getInt(tb+4);
       
   398             int high = getInt(tb+8);
       
   399             int count = high - low;
       
   400             out.print("{ //"+low+" to "+high);
       
   401             for (int i = 0; i <= count; i++)
       
   402                 out.print( "\n\t\t" + (i+low) + ": "+lP+(pc+getInt(tb+12+4*i))+";");
       
   403             out.print("\n\t\tdefault: "+lP+(default_skip + pc) + " }");
       
   404             return tb-pc+16+count*4;
       
   405         }
       
   406 
       
   407         case opc_lookupswitch:{
       
   408             int tb=align(pc+1);
       
   409             int default_skip = getInt(tb);
       
   410             int npairs = getInt(tb+4);
       
   411             out.print("{ //"+npairs);
       
   412             for (int i = 1; i <= npairs; i++)
       
   413                 out.print("\n\t\t"+getInt(tb+i*8)
       
   414                                  +": "+lP+(pc+getInt(tb+4+i*8))+";"
       
   415                                  );
       
   416             out.print("\n\t\tdefault: "+lP+(default_skip + pc) + " }");
       
   417             return tb-pc+(npairs+1)*8;
       
   418         }
       
   419         case opc_newarray:
       
   420             int type=getUbyte(pc+1);
       
   421             switch (type) {
       
   422             case T_BOOLEAN:out.print(" boolean");break;
       
   423             case T_BYTE:   out.print(" byte");   break;
       
   424             case T_CHAR:   out.print(" char");   break;
       
   425             case T_SHORT:  out.print(" short");  break;
       
   426             case T_INT:    out.print(" int");    break;
       
   427             case T_LONG:   out.print(" long");   break;
       
   428             case T_FLOAT:  out.print(" float");  break;
       
   429             case T_DOUBLE: out.print(" double"); break;
       
   430             case T_CLASS:  out.print(" class"); break;
       
   431             default:       out.print(" BOGUS TYPE:"+type);
       
   432             }
       
   433             return 2;
       
   434 
       
   435         case opc_anewarray: {
       
   436             int index =  getUShort(pc+1);
       
   437             out.print("\t#"+index+"; //");
       
   438             PrintConstant(index);
       
   439             return 3;
       
   440         }
       
   441 
       
   442         case opc_sipush:
       
   443             out.print("\t"+getShort(pc+1));
       
   444             return 3;
       
   445 
       
   446         case opc_bipush:
       
   447             out.print("\t"+getbyte(pc+1));
       
   448             return 2;
       
   449 
       
   450         case opc_ldc: {
       
   451             int index = getUbyte(pc+1);
       
   452             out.print("\t#"+index+"; //");
       
   453             PrintConstant(index);
       
   454             return 2;
       
   455         }
       
   456 
       
   457         case opc_ldc_w: case opc_ldc2_w:
       
   458         case opc_instanceof: case opc_checkcast:
       
   459         case opc_new:
       
   460         case opc_putstatic: case opc_getstatic:
       
   461         case opc_putfield: case opc_getfield:
       
   462         case opc_invokevirtual:
       
   463         case opc_invokespecial:
       
   464         case opc_invokestatic: {
       
   465             int index = getUShort(pc+1);
       
   466             out.print("\t#"+index+"; //");
       
   467             PrintConstant(index);
       
   468             return 3;
       
   469         }
       
   470 
       
   471         case opc_invokeinterface: {
       
   472             int index = getUShort(pc+1), nargs=getUbyte(pc+3);
       
   473             out.print("\t#"+index+",  "+nargs+"; //");
       
   474             PrintConstant(index);
       
   475             return 5;
       
   476         }
       
   477 
       
   478         case opc_invokedynamic: {
       
   479             int index = getUShort(pc+1);
       
   480             out.print("\t#"+index+"; //");
       
   481             PrintConstant(index);
       
   482             return 5;
       
   483         }
       
   484 
       
   485         case opc_multianewarray: {
       
   486             int index = getUShort(pc+1), dimensions=getUbyte(pc+3);
       
   487             out.print("\t#"+index+",  "+dimensions+"; //");
       
   488             PrintConstant(index);
       
   489             return 4;
       
   490         }
       
   491         case opc_jsr: case opc_goto:
       
   492         case opc_ifeq: case opc_ifge: case opc_ifgt:
       
   493         case opc_ifle: case opc_iflt: case opc_ifne:
       
   494         case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge:
       
   495         case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmplt:
       
   496         case opc_if_acmpeq: case opc_if_acmpne:
       
   497         case opc_ifnull: case opc_ifnonnull:
       
   498             out.print("\t"+lP+(pc + getShort(pc+1)) );
       
   499             return 3;
       
   500 
       
   501         case opc_jsr_w:
       
   502         case opc_goto_w:
       
   503             out.print("\t"+lP+(pc + getInt(pc+1)));
       
   504             return 5;
       
   505 
       
   506         default:
       
   507             return 1;
       
   508         }
       
   509     }
       
   510     /**
       
   511      * Print code attribute details.
       
   512      */
       
   513     public void printVerboseHeader(MethodData method) {
       
   514         int argCount = method.getArgumentlength();
       
   515         if (!method.isStatic())
       
   516             ++argCount;  // for 'this'
       
   517 
       
   518         out.println("   Stack=" + method.getMaxStack()
       
   519                            + ", Locals=" + method.getMaxLocals()
       
   520                            + ", Args_size=" + argCount);
       
   521 
       
   522     }
       
   523 
       
   524 
       
   525     /**
       
   526      * Print the exception table for this method code
       
   527      */
       
   528     void printExceptionTable(MethodData method){//throws IOException
       
   529         Vector<?> exception_table = method.getexception_table();
       
   530         if (exception_table.size() > 0) {
       
   531             out.println("  Exception table:");
       
   532             out.println("   from   to  target type");
       
   533             for (int idx = 0; idx < exception_table.size(); ++idx) {
       
   534                 TrapData handler = (TrapData)exception_table.elementAt(idx);
       
   535                 printFixedWidthInt(handler.start_pc, 6);
       
   536                 printFixedWidthInt(handler.end_pc, 6);
       
   537                 printFixedWidthInt(handler.handler_pc, 6);
       
   538                 out.print("   ");
       
   539                 int catch_cpx = handler.catch_cpx;
       
   540                 if (catch_cpx == 0) {
       
   541                     out.println("any");
       
   542                 }else {
       
   543                     out.print("Class ");
       
   544                     out.println(cls.getClassName(catch_cpx));
       
   545                     out.println("");
       
   546                 }
       
   547             }
       
   548         }
       
   549     }
       
   550 
       
   551     /**
       
   552      * Print LineNumberTable attribute information.
       
   553      */
       
   554     public void printLineNumTable(MethodData method) {
       
   555         int numlines = method.getnumlines();
       
   556         Vector<?> lin_num_tb = method.getlin_num_tb();
       
   557         if( lin_num_tb.size() > 0){
       
   558             out.println("  LineNumberTable: ");
       
   559             for (int i=0; i<numlines; i++) {
       
   560                 LineNumData linnumtb_entry=(LineNumData)lin_num_tb.elementAt(i);
       
   561                 out.println("   line " + linnumtb_entry.line_number + ": "
       
   562                                + linnumtb_entry.start_pc);
       
   563             }
       
   564         }
       
   565         out.println();
       
   566     }
       
   567 
       
   568     /**
       
   569      * Print LocalVariableTable attribute information.
       
   570      */
       
   571     public void printLocVarTable(MethodData method){
       
   572         int siz = method.getloc_var_tbsize();
       
   573         if(siz > 0){
       
   574             out.println("  LocalVariableTable: ");
       
   575             out.print("   ");
       
   576             out.println("Start  Length  Slot  Name   Signature");
       
   577         }
       
   578         Vector<?> loc_var_tb = method.getloc_var_tb();
       
   579 
       
   580         for (int i=0; i<siz; i++) {
       
   581             LocVarData entry=(LocVarData)loc_var_tb.elementAt(i);
       
   582 
       
   583             out.println("   "+entry.start_pc+"      "+entry.length+"      "+
       
   584                                entry.slot+"    "+cls.StringValue(entry.name_cpx)  +
       
   585                                "       "+cls.StringValue(entry.sig_cpx));
       
   586         }
       
   587         out.println();
       
   588     }
       
   589 
       
   590     /**
       
   591      * Print StackMap attribute information.
       
   592      */
       
   593     public void printStackMap(MethodData method) {
       
   594         StackMapData[] stack_map_tb = method.getStackMap();
       
   595         int number_of_entries = stack_map_tb.length;
       
   596         if (number_of_entries > 0) {
       
   597             out.println("  StackMap: number_of_entries = " + number_of_entries);
       
   598 
       
   599             for (StackMapData frame : stack_map_tb) {
       
   600                 frame.print(this);
       
   601             }
       
   602         }
       
   603        out.println();
       
   604     }
       
   605 
       
   606     /**
       
   607      * Print StackMapTable attribute information.
       
   608      */
       
   609     public void printStackMapTable(MethodData method) {
       
   610         StackMapTableData[] stack_map_tb = method.getStackMapTable();
       
   611         int number_of_entries = stack_map_tb.length;
       
   612         if (number_of_entries > 0) {
       
   613             out.println("  StackMapTable: number_of_entries = " + number_of_entries);
       
   614 
       
   615             for (StackMapTableData frame : stack_map_tb) {
       
   616                 frame.print(this);
       
   617             }
       
   618         }
       
   619         out.println();
       
   620     }
       
   621 
       
   622     void printMap(String name, int[] map) {
       
   623         out.print(name);
       
   624         for (int i=0; i<map.length; i++) {
       
   625             int fulltype = map[i];
       
   626             int type = fulltype & 0xFF;
       
   627             int argument = fulltype >> 8;
       
   628             switch (type) {
       
   629                 case ITEM_Object:
       
   630                     out.print(" ");
       
   631                     PrintConstant(argument);
       
   632                     break;
       
   633                 case ITEM_NewObject:
       
   634                     out.print(" " + Tables.mapTypeName(type));
       
   635                     out.print(" " + argument);
       
   636                     break;
       
   637                 default:
       
   638                     out.print(" " + Tables.mapTypeName(type));
       
   639             }
       
   640             out.print( (i==(map.length-1)? ' ' : ','));
       
   641         }
       
   642         out.println("]");
       
   643     }
       
   644 
       
   645     /**
       
   646      * Print ConstantValue attribute information.
       
   647      */
       
   648     public void printConstantValue(FieldData field){
       
   649         out.print("  Constant value: ");
       
   650         int cpx = (field.getConstantValueIndex());
       
   651         byte tag=0;
       
   652         try {
       
   653             tag=cls.getTag(cpx);
       
   654 
       
   655         } catch (IndexOutOfBoundsException e) {
       
   656             out.print("Error:");
       
   657             return;
       
   658         }
       
   659         switch (tag) {
       
   660         case CONSTANT_METHOD:
       
   661         case CONSTANT_INTERFACEMETHOD:
       
   662         case CONSTANT_FIELD: {
       
   663             CPX2 x = cls.getCpoolEntry(cpx);
       
   664             if (x.cpx1 == cls.getthis_cpx()) {
       
   665                 // don't print class part for local references
       
   666                 cpx=x.cpx2;
       
   667             }
       
   668         }
       
   669         }
       
   670         out.print(cls.TagString(tag)+" "+ cls.StringValue(cpx));
       
   671     }
       
   672 
       
   673     /**
       
   674      * Print InnerClass attribute information.
       
   675      */
       
   676     public void printInnerClasses(){//throws ioexception
       
   677 
       
   678         InnerClassData[] innerClasses = cls.getInnerClasses();
       
   679         if(innerClasses != null){
       
   680             if(innerClasses.length > 0){
       
   681                 out.print("  ");
       
   682                 out.println("InnerClass: ");
       
   683                 for(int i = 0 ; i < innerClasses.length; i++){
       
   684                     out.print("   ");
       
   685                     //access
       
   686                     String[] accflags = innerClasses[i].getAccess();
       
   687                     if(checkAccess(accflags)){
       
   688                         printAccess(accflags);
       
   689                         if (innerClasses[i].inner_name_index!=0) {
       
   690                             out.print("#"+innerClasses[i].inner_name_index+"= ");
       
   691                         }
       
   692                         out.print("#"+innerClasses[i].inner_class_info_index);
       
   693                         if (innerClasses[i].outer_class_info_index!=0) {
       
   694                             out.print(" of #"+innerClasses[i].outer_class_info_index);
       
   695                         }
       
   696                         out.print("; //");
       
   697                         if (innerClasses[i].inner_name_index!=0) {
       
   698                             out.print(cls.getName(innerClasses[i].inner_name_index)+"=");
       
   699                         }
       
   700                         PrintConstant(innerClasses[i].inner_class_info_index);
       
   701                         if (innerClasses[i].outer_class_info_index!=0) {
       
   702                             out.print(" of ");
       
   703                             PrintConstant(innerClasses[i].outer_class_info_index);
       
   704                         }
       
   705                         out.println();
       
   706                     }
       
   707                 }
       
   708 
       
   709             }
       
   710         }
       
   711     }
       
   712 
       
   713     /**
       
   714      * Print constant pool information.
       
   715      */
       
   716     public void printcp(){
       
   717         int cpx = 1 ;
       
   718 
       
   719         while (cpx < cls.getCpoolCount()) {
       
   720             out.print("const #"+cpx+" = ");
       
   721             cpx+=PrintlnConstantEntry(cpx);
       
   722         }
       
   723         out.println();
       
   724     }
       
   725 
       
   726     /**
       
   727      * Print constant pool entry information.
       
   728      */
       
   729     @SuppressWarnings("fallthrough")
       
   730     public int PrintlnConstantEntry(int cpx) {
       
   731         int size=1;
       
   732         byte tag=0;
       
   733         try {
       
   734             tag=cls.getTag(cpx);
       
   735         } catch (IndexOutOfBoundsException e) {
       
   736             out.println("  <Incorrect CP index>");
       
   737             return 1;
       
   738         }
       
   739         out.print(cls.StringTag(cpx)+"\t");
       
   740         Object x=cls.getCpoolEntryobj(cpx);
       
   741         if (x==null) {
       
   742             switch (tag) {
       
   743             case CONSTANT_LONG:
       
   744             case CONSTANT_DOUBLE:
       
   745                 size=2;
       
   746             }
       
   747             out.println("null;");
       
   748             return size;
       
   749         }
       
   750         String str=cls.StringValue(cpx);
       
   751 
       
   752         switch (tag) {
       
   753         case CONSTANT_CLASS:
       
   754         case CONSTANT_STRING:
       
   755             out.println("#"+(((CPX)x).cpx)+";\t//  "+str);
       
   756             break;
       
   757         case CONSTANT_FIELD:
       
   758         case CONSTANT_METHOD:
       
   759         case CONSTANT_INTERFACEMETHOD:
       
   760             out.println("#"+((CPX2)x).cpx1+".#"+((CPX2)x).cpx2+";\t//  "+str);
       
   761             break;
       
   762         case CONSTANT_NAMEANDTYPE:
       
   763             out.println("#"+((CPX2)x).cpx1+":#"+((CPX2)x).cpx2+";//  "+str);
       
   764             break;
       
   765         case CONSTANT_LONG:
       
   766         case CONSTANT_DOUBLE:
       
   767             size=2;
       
   768             // fall through
       
   769         default:
       
   770             out.println(str+";");
       
   771         }
       
   772         return size;
       
   773     }
       
   774 
       
   775     /**
       
   776      * Checks access of class, field or method.
       
   777      */
       
   778     public boolean checkAccess(String accflags[]){
       
   779 
       
   780         boolean ispublic = false;
       
   781         boolean isprotected = false;
       
   782         boolean isprivate = false;
       
   783         boolean ispackage = false;
       
   784 
       
   785         for(int i= 0; i < accflags.length; i++){
       
   786             if(accflags[i].equals("public")) ispublic = true;
       
   787             else if (accflags[i].equals("protected")) isprotected = true;
       
   788             else if (accflags[i].equals("private")) isprivate = true;
       
   789         }
       
   790 
       
   791         if(!(ispublic || isprotected || isprivate)) ispackage = true;
       
   792 
       
   793         if((env.showAccess == env.PUBLIC) && (isprotected || isprivate || ispackage)) return false;
       
   794         else if((env.showAccess == env.PROTECTED) && (isprivate || ispackage)) return false;
       
   795         else if((env.showAccess == env.PACKAGE) && (isprivate)) return false;
       
   796         else return true;
       
   797     }
       
   798 
       
   799     /**
       
   800      * Prints access of class, field or method.
       
   801      */
       
   802     public void printAccess(String []accflags){
       
   803         for(int j = 0; j < accflags.length; j++){
       
   804             out.print(accflags[j]+" ");
       
   805         }
       
   806     }
       
   807 
       
   808     /**
       
   809      * Print an integer so that it takes 'length' characters in
       
   810      * the output.  Temporary until formatting code is stable.
       
   811      */
       
   812     public void printFixedWidthInt(long x, int length) {
       
   813         CharArrayWriter baStream = new CharArrayWriter();
       
   814         PrintWriter pStream = new PrintWriter(baStream);
       
   815         pStream.print(x);
       
   816         String str = baStream.toString();
       
   817         for (int cnt = length - str.length(); cnt > 0; --cnt)
       
   818             out.print(' ');
       
   819         out.print(str);
       
   820     }
       
   821 
       
   822     protected int getbyte (int pc) {
       
   823         return code[pc];
       
   824     }
       
   825 
       
   826     protected int getUbyte (int pc) {
       
   827         return code[pc]&0xFF;
       
   828     }
       
   829 
       
   830     int getShort (int pc) {
       
   831         return (code[pc]<<8) | (code[pc+1]&0xFF);
       
   832     }
       
   833 
       
   834     int getUShort (int pc) {
       
   835         return ((code[pc]<<8) | (code[pc+1]&0xFF))&0xFFFF;
       
   836     }
       
   837 
       
   838     protected int getInt (int pc) {
       
   839         return (getShort(pc)<<16) | (getShort(pc+2)&0xFFFF);
       
   840     }
       
   841 
       
   842     /**
       
   843      * Print constant value at that index.
       
   844      */
       
   845     void PrintConstant(int cpx) {
       
   846         if (cpx==0) {
       
   847             out.print("#0");
       
   848             return;
       
   849         }
       
   850         byte tag=0;
       
   851         try {
       
   852             tag=cls.getTag(cpx);
       
   853 
       
   854         } catch (IndexOutOfBoundsException e) {
       
   855             out.print("#"+cpx);
       
   856             return;
       
   857         }
       
   858         switch (tag) {
       
   859         case CONSTANT_METHOD:
       
   860         case CONSTANT_INTERFACEMETHOD:
       
   861         case CONSTANT_FIELD: {
       
   862             // CPX2 x=(CPX2)(cpool[cpx]);
       
   863             CPX2 x = cls.getCpoolEntry(cpx);
       
   864             if (x.cpx1 == cls.getthis_cpx()) {
       
   865                 // don't print class part for local references
       
   866                 cpx=x.cpx2;
       
   867             }
       
   868         }
       
   869         }
       
   870         out.print(cls.TagString(tag)+" "+ cls.StringValue(cpx));
       
   871     }
       
   872 
       
   873     protected static int  align (int n) {
       
   874         return (n+3) & ~3 ;
       
   875     }
       
   876 
       
   877     public void printend(){
       
   878         out.println("}");
       
   879         out.println();
       
   880     }
       
   881 
       
   882     public String javaclassname(String name){
       
   883         return name.replace('/','.');
       
   884     }
       
   885 
       
   886     /**
       
   887      * Print attribute data in hex.
       
   888      */
       
   889     public void printAttrData(AttrData attr){
       
   890         byte []data = attr.getData();
       
   891         int i = 0;
       
   892         int j = 0;
       
   893         out.print("  "+attr.getAttrName()+": ");
       
   894         out.println("length = " + cls.toHex(attr.datalen));
       
   895 
       
   896         out.print("   ");
       
   897 
       
   898 
       
   899         while (i < data.length){
       
   900             String databytestring = cls.toHex(data[i]);
       
   901             if(databytestring.equals("0x")) out.print("00");
       
   902             else if(databytestring.substring(2).length() == 1){
       
   903                 out.print("0"+databytestring.substring(2));
       
   904             } else{
       
   905                 out.print(databytestring.substring(2));
       
   906             }
       
   907 
       
   908              j++;
       
   909             if(j == 16) {
       
   910                 out.println();
       
   911                 out.print("   ");
       
   912                 j = 0;
       
   913             }
       
   914             else out.print(" ");
       
   915             i++;
       
   916         }
       
   917         out.println();
       
   918     }
       
   919 }