rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeParser.java
author Lubomir Nerad <lubomir.nerad@oracle.com>
Fri, 12 Apr 2013 18:48:48 +0200
branchclosure
changeset 967 f19f17f8f8dc
parent 810 9eb750594b15
child 1085 6a4ef883e233
permissions -rw-r--r--
Introduced Exported annotation
     1 /*
     2  * Copyright (c) 2002, 2004, 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 package org.apidesign.vm4brwsr;
    26 
    27 import java.io.ByteArrayInputStream;
    28 import java.io.DataInputStream;
    29 import java.io.IOException;
    30 import java.io.InputStream;
    31 import org.apidesign.bck2brwsr.core.JavaScriptBody;
    32 import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
    33 
    34 /** This is a byte code parser heavily based on original code of JavaP utility.
    35  * As such I decided to keep the original Oracle's GPLv2 header.
    36  *
    37  * @author Jaroslav Tulach <jtulach@netbeans.org>
    38  */
    39 final class ByteCodeParser {
    40     private ByteCodeParser() {
    41     }
    42     /* Signature Characters */
    43     public static final char   SIGC_VOID                  = 'V';
    44     public static final String SIG_VOID                   = "V";
    45     public static final char   SIGC_BOOLEAN               = 'Z';
    46     public static final String SIG_BOOLEAN                = "Z";
    47     public static final char   SIGC_BYTE                  = 'B';
    48     public static final String SIG_BYTE                   = "B";
    49     public static final char   SIGC_CHAR                  = 'C';
    50     public static final String SIG_CHAR                   = "C";
    51     public static final char   SIGC_SHORT                 = 'S';
    52     public static final String SIG_SHORT                  = "S";
    53     public static final char   SIGC_INT                   = 'I';
    54     public static final String SIG_INT                    = "I";
    55     public static final char   SIGC_LONG                  = 'J';
    56     public static final String SIG_LONG                   = "J";
    57     public static final char   SIGC_FLOAT                 = 'F';
    58     public static final String SIG_FLOAT                  = "F";
    59     public static final char   SIGC_DOUBLE                = 'D';
    60     public static final String SIG_DOUBLE                 = "D";
    61     public static final char   SIGC_ARRAY                 = '[';
    62     public static final String SIG_ARRAY                  = "[";
    63     public static final char   SIGC_CLASS                 = 'L';
    64     public static final String SIG_CLASS                  = "L";
    65     public static final char   SIGC_METHOD                = '(';
    66     public static final String SIG_METHOD                 = "(";
    67     public static final char   SIGC_ENDCLASS              = ';';
    68     public static final String SIG_ENDCLASS               = ";";
    69     public static final char   SIGC_ENDMETHOD             = ')';
    70     public static final String SIG_ENDMETHOD              = ")";
    71     public static final char   SIGC_PACKAGE               = '/';
    72     public static final String SIG_PACKAGE                = "/";
    73 
    74     /* Class File Constants */
    75     public static final int JAVA_MAGIC                   = 0xcafebabe;
    76     public static final int JAVA_VERSION                 = 45;
    77     public static final int JAVA_MINOR_VERSION           = 3;
    78 
    79     /* Constant table */
    80     public static final int CONSTANT_UTF8                = 1;
    81     public static final int CONSTANT_UNICODE             = 2;
    82     public static final int CONSTANT_INTEGER             = 3;
    83     public static final int CONSTANT_FLOAT               = 4;
    84     public static final int CONSTANT_LONG                = 5;
    85     public static final int CONSTANT_DOUBLE              = 6;
    86     public static final int CONSTANT_CLASS               = 7;
    87     public static final int CONSTANT_STRING              = 8;
    88     public static final int CONSTANT_FIELD               = 9;
    89     public static final int CONSTANT_METHOD              = 10;
    90     public static final int CONSTANT_INTERFACEMETHOD     = 11;
    91     public static final int CONSTANT_NAMEANDTYPE         = 12;
    92 
    93     /* Access Flags */
    94     public static final int ACC_PUBLIC                   = 0x00000001;
    95     public static final int ACC_PRIVATE                  = 0x00000002;
    96     public static final int ACC_PROTECTED                = 0x00000004;
    97     public static final int ACC_STATIC                   = 0x00000008;
    98     public static final int ACC_FINAL                    = 0x00000010;
    99     public static final int ACC_SYNCHRONIZED             = 0x00000020;
   100     public static final int ACC_SUPER                        = 0x00000020;
   101     public static final int ACC_VOLATILE                 = 0x00000040;
   102     public static final int ACC_TRANSIENT                = 0x00000080;
   103     public static final int ACC_NATIVE                   = 0x00000100;
   104     public static final int ACC_INTERFACE                = 0x00000200;
   105     public static final int ACC_ABSTRACT                 = 0x00000400;
   106     public static final int ACC_STRICT                   = 0x00000800;
   107     public static final int ACC_EXPLICIT                 = 0x00001000;
   108     public static final int ACC_SYNTHETIC                = 0x00010000; // actually, this is an attribute
   109 
   110     /* Type codes */
   111     public static final int T_CLASS                      = 0x00000002;
   112     public static final int T_BOOLEAN                    = 0x00000004;
   113     public static final int T_CHAR                       = 0x00000005;
   114     public static final int T_FLOAT                      = 0x00000006;
   115     public static final int T_DOUBLE                     = 0x00000007;
   116     public static final int T_BYTE                       = 0x00000008;
   117     public static final int T_SHORT                      = 0x00000009;
   118     public static final int T_INT                        = 0x0000000a;
   119     public static final int T_LONG                       = 0x0000000b;
   120 
   121     /* Type codes for StackMap attribute */
   122     public static final int ITEM_Bogus      =0; // an unknown or uninitialized value
   123     public static final int ITEM_Integer    =1; // a 32-bit integer
   124     public static final int ITEM_Float      =2; // not used
   125     public static final int ITEM_Double     =3; // not used
   126     public static final int ITEM_Long       =4; // a 64-bit integer
   127     public static final int ITEM_Null       =5; // the type of null
   128     public static final int ITEM_InitObject =6; // "this" in constructor
   129     public static final int ITEM_Object     =7; // followed by 2-byte index of class name
   130     public static final int ITEM_NewObject  =8; // followed by 2-byte ref to "new"
   131 
   132     /* Constants used in StackMapTable attribute */
   133     public static final int SAME_FRAME_BOUND                  = 64;
   134     public static final int SAME_LOCALS_1_STACK_ITEM_BOUND    = 128;
   135     public static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
   136     public static final int SAME_FRAME_EXTENDED               = 251;
   137     public static final int FULL_FRAME                        = 255;
   138 
   139     /* Opcodes */
   140     public static final int opc_dead                     = -2;
   141     public static final int opc_label                    = -1;
   142     public static final int opc_nop                      = 0;
   143     public static final int opc_aconst_null              = 1;
   144     public static final int opc_iconst_m1                = 2;
   145     public static final int opc_iconst_0                 = 3;
   146     public static final int opc_iconst_1                 = 4;
   147     public static final int opc_iconst_2                 = 5;
   148     public static final int opc_iconst_3                 = 6;
   149     public static final int opc_iconst_4                 = 7;
   150     public static final int opc_iconst_5                 = 8;
   151     public static final int opc_lconst_0                 = 9;
   152     public static final int opc_lconst_1                 = 10;
   153     public static final int opc_fconst_0                 = 11;
   154     public static final int opc_fconst_1                 = 12;
   155     public static final int opc_fconst_2                 = 13;
   156     public static final int opc_dconst_0                 = 14;
   157     public static final int opc_dconst_1                 = 15;
   158     public static final int opc_bipush                   = 16;
   159     public static final int opc_sipush                   = 17;
   160     public static final int opc_ldc                      = 18;
   161     public static final int opc_ldc_w                    = 19;
   162     public static final int opc_ldc2_w                   = 20;
   163     public static final int opc_iload                    = 21;
   164     public static final int opc_lload                    = 22;
   165     public static final int opc_fload                    = 23;
   166     public static final int opc_dload                    = 24;
   167     public static final int opc_aload                    = 25;
   168     public static final int opc_iload_0                  = 26;
   169     public static final int opc_iload_1                  = 27;
   170     public static final int opc_iload_2                  = 28;
   171     public static final int opc_iload_3                  = 29;
   172     public static final int opc_lload_0                  = 30;
   173     public static final int opc_lload_1                  = 31;
   174     public static final int opc_lload_2                  = 32;
   175     public static final int opc_lload_3                  = 33;
   176     public static final int opc_fload_0                  = 34;
   177     public static final int opc_fload_1                  = 35;
   178     public static final int opc_fload_2                  = 36;
   179     public static final int opc_fload_3                  = 37;
   180     public static final int opc_dload_0                  = 38;
   181     public static final int opc_dload_1                  = 39;
   182     public static final int opc_dload_2                  = 40;
   183     public static final int opc_dload_3                  = 41;
   184     public static final int opc_aload_0                  = 42;
   185     public static final int opc_aload_1                  = 43;
   186     public static final int opc_aload_2                  = 44;
   187     public static final int opc_aload_3                  = 45;
   188     public static final int opc_iaload                   = 46;
   189     public static final int opc_laload                   = 47;
   190     public static final int opc_faload                   = 48;
   191     public static final int opc_daload                   = 49;
   192     public static final int opc_aaload                   = 50;
   193     public static final int opc_baload                   = 51;
   194     public static final int opc_caload                   = 52;
   195     public static final int opc_saload                   = 53;
   196     public static final int opc_istore                   = 54;
   197     public static final int opc_lstore                   = 55;
   198     public static final int opc_fstore                   = 56;
   199     public static final int opc_dstore                   = 57;
   200     public static final int opc_astore                   = 58;
   201     public static final int opc_istore_0                 = 59;
   202     public static final int opc_istore_1                 = 60;
   203     public static final int opc_istore_2                 = 61;
   204     public static final int opc_istore_3                 = 62;
   205     public static final int opc_lstore_0                 = 63;
   206     public static final int opc_lstore_1                 = 64;
   207     public static final int opc_lstore_2                 = 65;
   208     public static final int opc_lstore_3                 = 66;
   209     public static final int opc_fstore_0                 = 67;
   210     public static final int opc_fstore_1                 = 68;
   211     public static final int opc_fstore_2                 = 69;
   212     public static final int opc_fstore_3                 = 70;
   213     public static final int opc_dstore_0                 = 71;
   214     public static final int opc_dstore_1                 = 72;
   215     public static final int opc_dstore_2                 = 73;
   216     public static final int opc_dstore_3                 = 74;
   217     public static final int opc_astore_0                 = 75;
   218     public static final int opc_astore_1                 = 76;
   219     public static final int opc_astore_2                 = 77;
   220     public static final int opc_astore_3                 = 78;
   221     public static final int opc_iastore                  = 79;
   222     public static final int opc_lastore                  = 80;
   223     public static final int opc_fastore                  = 81;
   224     public static final int opc_dastore                  = 82;
   225     public static final int opc_aastore                  = 83;
   226     public static final int opc_bastore                  = 84;
   227     public static final int opc_castore                  = 85;
   228     public static final int opc_sastore                  = 86;
   229     public static final int opc_pop                      = 87;
   230     public static final int opc_pop2                     = 88;
   231     public static final int opc_dup                      = 89;
   232     public static final int opc_dup_x1                   = 90;
   233     public static final int opc_dup_x2                   = 91;
   234     public static final int opc_dup2                     = 92;
   235     public static final int opc_dup2_x1                  = 93;
   236     public static final int opc_dup2_x2                  = 94;
   237     public static final int opc_swap                     = 95;
   238     public static final int opc_iadd                     = 96;
   239     public static final int opc_ladd                     = 97;
   240     public static final int opc_fadd                     = 98;
   241     public static final int opc_dadd                     = 99;
   242     public static final int opc_isub                     = 100;
   243     public static final int opc_lsub                     = 101;
   244     public static final int opc_fsub                     = 102;
   245     public static final int opc_dsub                     = 103;
   246     public static final int opc_imul                     = 104;
   247     public static final int opc_lmul                     = 105;
   248     public static final int opc_fmul                     = 106;
   249     public static final int opc_dmul                     = 107;
   250     public static final int opc_idiv                     = 108;
   251     public static final int opc_ldiv                     = 109;
   252     public static final int opc_fdiv                     = 110;
   253     public static final int opc_ddiv                     = 111;
   254     public static final int opc_irem                     = 112;
   255     public static final int opc_lrem                     = 113;
   256     public static final int opc_frem                     = 114;
   257     public static final int opc_drem                     = 115;
   258     public static final int opc_ineg                     = 116;
   259     public static final int opc_lneg                     = 117;
   260     public static final int opc_fneg                     = 118;
   261     public static final int opc_dneg                     = 119;
   262     public static final int opc_ishl                     = 120;
   263     public static final int opc_lshl                     = 121;
   264     public static final int opc_ishr                     = 122;
   265     public static final int opc_lshr                     = 123;
   266     public static final int opc_iushr                    = 124;
   267     public static final int opc_lushr                    = 125;
   268     public static final int opc_iand                     = 126;
   269     public static final int opc_land                     = 127;
   270     public static final int opc_ior                      = 128;
   271     public static final int opc_lor                      = 129;
   272     public static final int opc_ixor                     = 130;
   273     public static final int opc_lxor                     = 131;
   274     public static final int opc_iinc                     = 132;
   275     public static final int opc_i2l                      = 133;
   276     public static final int opc_i2f                      = 134;
   277     public static final int opc_i2d                      = 135;
   278     public static final int opc_l2i                      = 136;
   279     public static final int opc_l2f                      = 137;
   280     public static final int opc_l2d                      = 138;
   281     public static final int opc_f2i                      = 139;
   282     public static final int opc_f2l                      = 140;
   283     public static final int opc_f2d                      = 141;
   284     public static final int opc_d2i                      = 142;
   285     public static final int opc_d2l                      = 143;
   286     public static final int opc_d2f                      = 144;
   287     public static final int opc_i2b                      = 145;
   288     public static final int opc_int2byte                 = 145;
   289     public static final int opc_i2c                      = 146;
   290     public static final int opc_int2char                 = 146;
   291     public static final int opc_i2s                      = 147;
   292     public static final int opc_int2short                = 147;
   293     public static final int opc_lcmp                     = 148;
   294     public static final int opc_fcmpl                    = 149;
   295     public static final int opc_fcmpg                    = 150;
   296     public static final int opc_dcmpl                    = 151;
   297     public static final int opc_dcmpg                    = 152;
   298     public static final int opc_ifeq                     = 153;
   299     public static final int opc_ifne                     = 154;
   300     public static final int opc_iflt                     = 155;
   301     public static final int opc_ifge                     = 156;
   302     public static final int opc_ifgt                     = 157;
   303     public static final int opc_ifle                     = 158;
   304     public static final int opc_if_icmpeq                = 159;
   305     public static final int opc_if_icmpne                = 160;
   306     public static final int opc_if_icmplt                = 161;
   307     public static final int opc_if_icmpge                = 162;
   308     public static final int opc_if_icmpgt                = 163;
   309     public static final int opc_if_icmple                = 164;
   310     public static final int opc_if_acmpeq                = 165;
   311     public static final int opc_if_acmpne                = 166;
   312     public static final int opc_goto                     = 167;
   313     public static final int opc_jsr                      = 168;
   314     public static final int opc_ret                      = 169;
   315     public static final int opc_tableswitch              = 170;
   316     public static final int opc_lookupswitch             = 171;
   317     public static final int opc_ireturn                  = 172;
   318     public static final int opc_lreturn                  = 173;
   319     public static final int opc_freturn                  = 174;
   320     public static final int opc_dreturn                  = 175;
   321     public static final int opc_areturn                  = 176;
   322     public static final int opc_return                   = 177;
   323     public static final int opc_getstatic                = 178;
   324     public static final int opc_putstatic                = 179;
   325     public static final int opc_getfield                 = 180;
   326     public static final int opc_putfield                 = 181;
   327     public static final int opc_invokevirtual            = 182;
   328     public static final int opc_invokenonvirtual         = 183;
   329     public static final int opc_invokespecial            = 183;
   330     public static final int opc_invokestatic             = 184;
   331     public static final int opc_invokeinterface          = 185;
   332 //    public static final int opc_xxxunusedxxx             = 186;
   333     public static final int opc_new                      = 187;
   334     public static final int opc_newarray                 = 188;
   335     public static final int opc_anewarray                = 189;
   336     public static final int opc_arraylength              = 190;
   337     public static final int opc_athrow                   = 191;
   338     public static final int opc_checkcast                = 192;
   339     public static final int opc_instanceof               = 193;
   340     public static final int opc_monitorenter             = 194;
   341     public static final int opc_monitorexit              = 195;
   342     public static final int opc_wide                     = 196;
   343     public static final int opc_multianewarray           = 197;
   344     public static final int opc_ifnull                   = 198;
   345     public static final int opc_ifnonnull                = 199;
   346     public static final int opc_goto_w                   = 200;
   347     public static final int opc_jsr_w                    = 201;
   348         /* Pseudo-instructions */
   349     public static final int opc_bytecode                 = 203;
   350     public static final int opc_try                      = 204;
   351     public static final int opc_endtry                   = 205;
   352     public static final int opc_catch                    = 206;
   353     public static final int opc_var                      = 207;
   354     public static final int opc_endvar                   = 208;
   355     public static final int opc_localsmap                = 209;
   356     public static final int opc_stackmap                 = 210;
   357         /* PicoJava prefixes */
   358     public static final int opc_nonpriv                  = 254;
   359     public static final int opc_priv                     = 255;
   360 
   361         /* Wide instructions */
   362     public static final int opc_iload_w         = (opc_wide<<8)|opc_iload;
   363     public static final int opc_lload_w         = (opc_wide<<8)|opc_lload;
   364     public static final int opc_fload_w         = (opc_wide<<8)|opc_fload;
   365     public static final int opc_dload_w         = (opc_wide<<8)|opc_dload;
   366     public static final int opc_aload_w         = (opc_wide<<8)|opc_aload;
   367     public static final int opc_istore_w        = (opc_wide<<8)|opc_istore;
   368     public static final int opc_lstore_w        = (opc_wide<<8)|opc_lstore;
   369     public static final int opc_fstore_w        = (opc_wide<<8)|opc_fstore;
   370     public static final int opc_dstore_w        = (opc_wide<<8)|opc_dstore;
   371     public static final int opc_astore_w        = (opc_wide<<8)|opc_astore;
   372     public static final int opc_ret_w           = (opc_wide<<8)|opc_ret;
   373     public static final int opc_iinc_w          = (opc_wide<<8)|opc_iinc;
   374 
   375     /* Opcode Names */
   376   public static final String opcNamesTab[] = {
   377         "nop",
   378         "aconst_null",
   379         "iconst_m1",
   380         "iconst_0",
   381         "iconst_1",
   382         "iconst_2",
   383         "iconst_3",
   384         "iconst_4",
   385         "iconst_5",
   386         "lconst_0",
   387         "lconst_1",
   388         "fconst_0",
   389         "fconst_1",
   390         "fconst_2",
   391         "dconst_0",
   392         "dconst_1",
   393         "bipush",
   394         "sipush",
   395         "ldc",
   396         "ldc_w",
   397         "ldc2_w",
   398         "iload",
   399         "lload",
   400         "fload",
   401         "dload",
   402         "aload",
   403         "iload_0",
   404         "iload_1",
   405         "iload_2",
   406         "iload_3",
   407         "lload_0",
   408         "lload_1",
   409         "lload_2",
   410         "lload_3",
   411         "fload_0",
   412         "fload_1",
   413         "fload_2",
   414         "fload_3",
   415         "dload_0",
   416         "dload_1",
   417         "dload_2",
   418         "dload_3",
   419         "aload_0",
   420         "aload_1",
   421         "aload_2",
   422         "aload_3",
   423         "iaload",
   424         "laload",
   425         "faload",
   426         "daload",
   427         "aaload",
   428         "baload",
   429         "caload",
   430         "saload",
   431         "istore",
   432         "lstore",
   433         "fstore",
   434         "dstore",
   435         "astore",
   436         "istore_0",
   437         "istore_1",
   438         "istore_2",
   439         "istore_3",
   440         "lstore_0",
   441         "lstore_1",
   442         "lstore_2",
   443         "lstore_3",
   444         "fstore_0",
   445         "fstore_1",
   446         "fstore_2",
   447         "fstore_3",
   448         "dstore_0",
   449         "dstore_1",
   450         "dstore_2",
   451         "dstore_3",
   452         "astore_0",
   453         "astore_1",
   454         "astore_2",
   455         "astore_3",
   456         "iastore",
   457         "lastore",
   458         "fastore",
   459         "dastore",
   460         "aastore",
   461         "bastore",
   462         "castore",
   463         "sastore",
   464         "pop",
   465         "pop2",
   466         "dup",
   467         "dup_x1",
   468         "dup_x2",
   469         "dup2",
   470         "dup2_x1",
   471         "dup2_x2",
   472         "swap",
   473         "iadd",
   474         "ladd",
   475         "fadd",
   476         "dadd",
   477         "isub",
   478         "lsub",
   479         "fsub",
   480         "dsub",
   481         "imul",
   482         "lmul",
   483         "fmul",
   484         "dmul",
   485         "idiv",
   486         "ldiv",
   487         "fdiv",
   488         "ddiv",
   489         "irem",
   490         "lrem",
   491         "frem",
   492         "drem",
   493         "ineg",
   494         "lneg",
   495         "fneg",
   496         "dneg",
   497         "ishl",
   498         "lshl",
   499         "ishr",
   500         "lshr",
   501         "iushr",
   502         "lushr",
   503         "iand",
   504         "land",
   505         "ior",
   506         "lor",
   507         "ixor",
   508         "lxor",
   509         "iinc",
   510         "i2l",
   511         "i2f",
   512         "i2d",
   513         "l2i",
   514         "l2f",
   515         "l2d",
   516         "f2i",
   517         "f2l",
   518         "f2d",
   519         "d2i",
   520         "d2l",
   521         "d2f",
   522         "i2b",
   523         "i2c",
   524         "i2s",
   525         "lcmp",
   526         "fcmpl",
   527         "fcmpg",
   528         "dcmpl",
   529         "dcmpg",
   530         "ifeq",
   531         "ifne",
   532         "iflt",
   533         "ifge",
   534         "ifgt",
   535         "ifle",
   536         "if_icmpeq",
   537         "if_icmpne",
   538         "if_icmplt",
   539         "if_icmpge",
   540         "if_icmpgt",
   541         "if_icmple",
   542         "if_acmpeq",
   543         "if_acmpne",
   544         "goto",
   545         "jsr",
   546         "ret",
   547         "tableswitch",
   548         "lookupswitch",
   549         "ireturn",
   550         "lreturn",
   551         "freturn",
   552         "dreturn",
   553         "areturn",
   554         "return",
   555         "getstatic",
   556         "putstatic",
   557         "getfield",
   558         "putfield",
   559         "invokevirtual",
   560         "invokespecial", //     was "invokenonvirtual",
   561         "invokestatic",
   562         "invokeinterface",
   563         "bytecode 186", //"xxxunusedxxx",
   564         "new",
   565         "newarray",
   566         "anewarray",
   567         "arraylength",
   568         "athrow",
   569         "checkcast",
   570         "instanceof",
   571         "monitorenter",
   572         "monitorexit",
   573          null, // "wide",
   574         "multianewarray",
   575         "ifnull",
   576         "ifnonnull",
   577         "goto_w",
   578         "jsr_w",
   579         "bytecode 202", // "breakpoint",
   580         "bytecode",
   581         "try",
   582         "endtry",
   583         "catch",
   584         "var",
   585         "endvar",
   586         "locals_map",
   587         "stack_map"
   588   };
   589 
   590     /* Opcode Lengths */
   591   public static final int opcLengthsTab[] = {
   592         1,
   593         1,
   594         1,
   595         1,
   596         1,
   597         1,
   598         1,
   599         1,
   600         1,
   601         1,
   602         1,
   603         1,
   604         1,
   605         1,
   606         1,
   607         1,
   608         2,
   609         3,
   610         2,
   611         3,
   612         3,
   613         2,
   614         2,
   615         2,
   616         2,
   617         2,
   618         1,
   619         1,
   620         1,
   621         1,
   622         1,
   623         1,
   624         1,
   625         1,
   626         1,
   627         1,
   628         1,
   629         1,
   630         1,
   631         1,
   632         1,
   633         1,
   634         1,
   635         1,
   636         1,
   637         1,
   638         1,
   639         1,
   640         1,
   641         1,
   642         1,
   643         1,
   644         1,
   645         1,
   646         2,
   647         2,
   648         2,
   649         2,
   650         2,
   651         1,
   652         1,
   653         1,
   654         1,
   655         1,
   656         1,
   657         1,
   658         1,
   659         1,
   660         1,
   661         1,
   662         1,
   663         1,
   664         1,
   665         1,
   666         1,
   667         1,
   668         1,
   669         1,
   670         1,
   671         1,
   672         1,
   673         1,
   674         1,
   675         1,
   676         1,
   677         1,
   678         1,
   679         1,
   680         1,
   681         1,
   682         1,
   683         1,
   684         1,
   685         1,
   686         1,
   687         1,
   688         1,
   689         1,
   690         1,
   691         1,
   692         1,
   693         1,
   694         1,
   695         1,
   696         1,
   697         1,
   698         1,
   699         1,
   700         1,
   701         1,
   702         1,
   703         1,
   704         1,
   705         1,
   706         1,
   707         1,
   708         1,
   709         1,
   710         1,
   711         1,
   712         1,
   713         1,
   714         1,
   715         1,
   716         1,
   717         1,
   718         1,
   719         1,
   720         1,
   721         1,
   722         1,
   723         1,
   724         3,
   725         1,
   726         1,
   727         1,
   728         1,
   729         1,
   730         1,
   731         1,
   732         1,
   733         1,
   734         1,
   735         1,
   736         1,
   737         1,
   738         1,
   739         1,
   740         1,
   741         1,
   742         1,
   743         1,
   744         1,
   745         3,
   746         3,
   747         3,
   748         3,
   749         3,
   750         3,
   751         3,
   752         3,
   753         3,
   754         3,
   755         3,
   756         3,
   757         3,
   758         3,
   759         3,
   760         3,
   761         2,
   762         99,
   763         99,
   764         1,
   765         1,
   766         1,
   767         1,
   768         1,
   769         1,
   770         3,
   771         3,
   772         3,
   773         3,
   774         3,
   775         3,
   776         3,
   777         5,
   778         0,
   779         3,
   780         2,
   781         3,
   782         1,
   783         1,
   784         3,
   785         3,
   786         1,
   787         1,
   788         0, // wide
   789         4,
   790         3,
   791         3,
   792         5,
   793         5,
   794         1,
   795         1, 0, 0, 0, 0, 0 // pseudo
   796   };
   797 
   798      /**
   799      * End of input
   800      */
   801     public static final int EOF = -1;
   802 
   803    /*
   804      * Flags
   805      */
   806     public static final int F_VERBOSE           = 1 << 0;
   807     public static final int F_DUMP              = 1 << 1;
   808     public static final int F_WARNINGS          = 1 << 2;
   809     public static final int F_DEBUG             = 1 << 3;
   810     public static final int F_OPTIMIZE          = 1 << 4;
   811     public static final int F_DEPENDENCIES      = 1 << 5;
   812 
   813     /*
   814      * Type codes
   815      */
   816     public static final int TC_BOOLEAN   = 0;
   817     public static final int TC_BYTE      = 1;
   818     public static final int TC_CHAR      = 2;
   819     public static final int TC_SHORT     = 3;
   820     public static final int TC_INT       = 4;
   821     public static final int TC_LONG      = 5;
   822     public static final int TC_FLOAT     = 6;
   823     public static final int TC_DOUBLE    = 7;
   824     public static final int TC_NULL      = 8;
   825     public static final int TC_ARRAY     = 9;
   826     public static final int TC_CLASS     = 10;
   827     public static final int TC_VOID      = 11;
   828     public static final int TC_METHOD    = 12;
   829     public static final int TC_ERROR     = 13;
   830 
   831     /*
   832      * Type Masks
   833      */
   834     public static final int TM_NULL      = 1 << TC_NULL;
   835     public static final int TM_VOID      = 1 << TC_VOID;
   836     public static final int TM_BOOLEAN   = 1 << TC_BOOLEAN;
   837     public static final int TM_BYTE      = 1 << TC_BYTE;
   838     public static final int TM_CHAR      = 1 << TC_CHAR;
   839     public static final int TM_SHORT     = 1 << TC_SHORT;
   840     public static final int TM_INT       = 1 << TC_INT;
   841     public static final int TM_LONG      = 1 << TC_LONG;
   842     public static final int TM_FLOAT     = 1 << TC_FLOAT;
   843     public static final int TM_DOUBLE    = 1 << TC_DOUBLE;
   844     public static final int TM_ARRAY     = 1 << TC_ARRAY;
   845     public static final int TM_CLASS     = 1 << TC_CLASS;
   846     public static final int TM_METHOD    = 1 << TC_METHOD;
   847     public static final int TM_ERROR     = 1 << TC_ERROR;
   848 
   849     public static final int TM_INT32     = TM_BYTE | TM_SHORT | TM_CHAR | TM_INT;
   850     public static final int TM_NUM32     = TM_INT32 | TM_FLOAT;
   851     public static final int TM_NUM64     = TM_LONG | TM_DOUBLE;
   852     public static final int TM_INTEGER   = TM_INT32 | TM_LONG;
   853     public static final int TM_REAL      = TM_FLOAT | TM_DOUBLE;
   854     public static final int TM_NUMBER    = TM_INTEGER | TM_REAL;
   855     public static final int TM_REFERENCE = TM_ARRAY | TM_CLASS | TM_NULL;
   856 
   857     /*
   858      * Class status
   859      */
   860     public static final int CS_UNDEFINED        = 0;
   861     public static final int CS_UNDECIDED        = 1;
   862     public static final int CS_BINARY           = 2;
   863     public static final int CS_SOURCE           = 3;
   864     public static final int CS_PARSED           = 4;
   865     public static final int CS_COMPILED         = 5;
   866     public static final int CS_NOTFOUND         = 6;
   867 
   868     /*
   869      * Attributes
   870      */
   871     public static final int ATT_ALL             = -1;
   872     public static final int ATT_CODE            = 1;
   873 
   874     /*
   875      * Number of bits used in file offsets
   876      */
   877     public static final int OFFSETBITS          = 19;
   878     public static final int MAXFILESIZE         = (1 << OFFSETBITS) - 1;
   879     public static final int MAXLINENUMBER       = (1 << (32 - OFFSETBITS)) - 1;
   880 
   881     /*
   882      * Operators
   883      */
   884     public final int COMMA              = 0;
   885     public final int ASSIGN             = 1;
   886 
   887     public final int ASGMUL             = 2;
   888     public final int ASGDIV             = 3;
   889     public final int ASGREM             = 4;
   890     public final int ASGADD             = 5;
   891     public final int ASGSUB             = 6;
   892     public final int ASGLSHIFT          = 7;
   893     public final int ASGRSHIFT          = 8;
   894     public final int ASGURSHIFT         = 9;
   895     public final int ASGBITAND          = 10;
   896     public final int ASGBITOR           = 11;
   897     public final int ASGBITXOR          = 12;
   898 
   899     public final int COND               = 13;
   900     public final int OR                 = 14;
   901     public final int AND                = 15;
   902     public final int BITOR              = 16;
   903     public final int BITXOR             = 17;
   904     public final int BITAND             = 18;
   905     public final int NE                 = 19;
   906     public final int EQ                 = 20;
   907     public final int GE                 = 21;
   908     public final int GT                 = 22;
   909     public final int LE                 = 23;
   910     public final int LT                 = 24;
   911     public final int INSTANCEOF         = 25;
   912     public final int LSHIFT             = 26;
   913     public final int RSHIFT             = 27;
   914     public final int URSHIFT            = 28;
   915     public final int ADD                = 29;
   916     public final int SUB                = 30;
   917     public final int DIV                = 31;
   918     public final int REM                = 32;
   919     public final int MUL                = 33;
   920     public final int CAST               = 34;           // (x)y
   921     public final int POS                = 35;           // +x
   922     public final int NEG                = 36;           // -x
   923     public final int NOT                = 37;
   924     public final int BITNOT             = 38;
   925     public final int PREINC             = 39;           // ++x
   926     public final int PREDEC             = 40;           // --x
   927     public final int NEWARRAY           = 41;
   928     public final int NEWINSTANCE        = 42;
   929     public final int NEWFROMNAME        = 43;
   930     public final int POSTINC            = 44;           // x++
   931     public final int POSTDEC            = 45;           // x--
   932     public final int FIELD              = 46;
   933     public final int METHOD             = 47;           // x(y)
   934     public final int ARRAYACCESS        = 48;           // x[y]
   935     public final int NEW                = 49;
   936     public final int INC                = 50;
   937     public final int DEC                = 51;
   938 
   939     public final int CONVERT            = 55;           // implicit conversion
   940     public final int EXPR               = 56;           // (x)
   941     public final int ARRAY              = 57;           // {x, y, ...}
   942     public final int GOTO               = 58;
   943 
   944     /*
   945      * Value tokens
   946      */
   947     public final int IDENT              = 60;
   948     public final int BOOLEANVAL         = 61;
   949     public final int BYTEVAL            = 62;
   950     public final int CHARVAL            = 63;
   951     public final int SHORTVAL           = 64;
   952     public final int INTVAL                     = 65;
   953     public final int LONGVAL            = 66;
   954     public final int FLOATVAL           = 67;
   955     public final int DOUBLEVAL          = 68;
   956     public final int STRINGVAL          = 69;
   957 
   958     /*
   959      * Type keywords
   960      */
   961     public final int BYTE               = 70;
   962     public final int CHAR               = 71;
   963     public final int SHORT              = 72;
   964     public final int INT                = 73;
   965     public final int LONG               = 74;
   966     public final int FLOAT              = 75;
   967     public final int DOUBLE             = 76;
   968     public final int VOID               = 77;
   969     public final int BOOLEAN            = 78;
   970 
   971     /*
   972      * Expression keywords
   973      */
   974     public final int TRUE               = 80;
   975     public final int FALSE              = 81;
   976     public final int THIS               = 82;
   977     public final int SUPER              = 83;
   978     public final int NULL               = 84;
   979 
   980     /*
   981      * Statement keywords
   982      */
   983     public final int IF                 = 90;
   984     public final int ELSE               = 91;
   985     public final int FOR                = 92;
   986     public final int WHILE              = 93;
   987     public final int DO                 = 94;
   988     public final int SWITCH             = 95;
   989     public final int CASE               = 96;
   990     public final int DEFAULT            = 97;
   991     public final int BREAK              = 98;
   992     public final int CONTINUE           = 99;
   993     public final int RETURN             = 100;
   994     public final int TRY                = 101;
   995     public final int CATCH              = 102;
   996     public final int FINALLY            = 103;
   997     public final int THROW              = 104;
   998     public final int STAT               = 105;
   999     public final int EXPRESSION         = 106;
  1000     public final int DECLARATION        = 107;
  1001     public final int VARDECLARATION     = 108;
  1002 
  1003     /*
  1004      * Declaration keywords
  1005      */
  1006     public final int IMPORT             = 110;
  1007     public final int CLASS              = 111;
  1008     public final int EXTENDS            = 112;
  1009     public final int IMPLEMENTS         = 113;
  1010     public final int INTERFACE          = 114;
  1011     public final int PACKAGE            = 115;
  1012 
  1013     /*
  1014      * Modifier keywords
  1015      */
  1016     public final int PRIVATE    = 120;
  1017     public final int PUBLIC             = 121;
  1018     public final int PROTECTED  = 122;
  1019     public final int CONST              = 123;
  1020     public final int STATIC             = 124;
  1021     public final int TRANSIENT          = 125;
  1022     public final int SYNCHRONIZED       = 126;
  1023     public final int NATIVE             = 127;
  1024     public final int FINAL              = 128;
  1025     public final int VOLATILE   = 129;
  1026     public final int ABSTRACT   = 130;
  1027     public final int STRICT             = 165;
  1028 
  1029     /*
  1030      * Punctuation
  1031      */
  1032     public final int SEMICOLON  = 135;
  1033     public final int COLON              = 136;
  1034     public final int QUESTIONMARK       = 137;
  1035     public final int LBRACE             = 138;
  1036     public final int RBRACE             = 139;
  1037     public final int LPAREN             = 140;
  1038     public final int RPAREN             = 141;
  1039     public final int LSQBRACKET = 142;
  1040     public final int RSQBRACKET = 143;
  1041     public final int THROWS     = 144;
  1042 
  1043     /*
  1044      * Special tokens
  1045      */
  1046     public final int ERROR              = 145;          // an error
  1047     public final int COMMENT    = 146;          // not used anymore.
  1048     public final int TYPE               = 147;
  1049     public final int LENGTH             = 148;
  1050     public final int INLINERETURN       = 149;
  1051     public final int INLINEMETHOD       = 150;
  1052     public final int INLINENEWINSTANCE  = 151;
  1053 
  1054     /*
  1055      * Added for jasm
  1056      */
  1057         public final int METHODREF      = 152;
  1058         public final int FIELDREF       = 153;
  1059     public final int STACK              = 154;
  1060     public final int LOCAL              = 155;
  1061     public final int CPINDEX    = 156;
  1062     public final int CPNAME             = 157;
  1063     public final int SIGN               = 158;
  1064     public final int BITS               = 159;
  1065     public final int INF                = 160;
  1066     public final int NAN                = 161;
  1067     public final int INNERCLASS = 162;
  1068     public final int OF         = 163;
  1069     public final int SYNTHETIC          = 164;
  1070 // last used=165;
  1071 
  1072    /*
  1073      * Operator precedence
  1074      */
  1075     public static final int opPrecedence[] = {
  1076         10,     11,     11,     11,     11,     11,     11,     11,     11,     11,
  1077         11,     11,     11,     12,     13,     14,     15,     16,     17,     18,
  1078         18,     19,     19,     19,     19,     19,     20,     20,     20,     21,
  1079         21,     22,     22,     22,     23,     24,     24,     24,     24,     24,
  1080         24,     25,     25,     26,     26,     26,     26,     26,     26
  1081     };
  1082 
  1083     /*
  1084      * Operator names
  1085      */
  1086     public static final String opNames[] = {
  1087         ",",            "=",            "*=",           "/=",           "%=",
  1088         "+=",           "-=",           "<<=",          ">>=",          "<<<=",
  1089         "&=",           "|=",           "^=",           "?:",           "||",
  1090         "&&",           "|",            "^",            "&",            "!=",
  1091         "==",           ">=",           ">",            "<=",           "<",
  1092         "instanceof",   "<<",           ">>",           "<<<",          "+",
  1093         "-",            "/",            "%",            "*",            "cast",
  1094         "+",            "-",            "!",            "~",            "++",
  1095         "--",           "new",          "new",          "new",          "++",
  1096         "--",           "field",        "method",       "[]",           "new",
  1097         "++",           "--",           null,           null,           null,
  1098 
  1099         "convert",      "expr",         "array",        "goto",         null,
  1100 
  1101         "Identifier",   "Boolean",      "Byte",         "Char",         "Short",
  1102         "Integer",              "Long",         "Float",        "Double",       "String",
  1103 
  1104         "byte",         "char",         "short",        "int",          "long",
  1105         "float",        "double",       "void",         "boolean",      null,
  1106 
  1107         "true",         "false",        "this",         "super",        "null",
  1108         null,           null,           null,           null,           null,
  1109 
  1110         "if",           "else",         "for",          "while",        "do",
  1111         "switch",       "case",         "default",      "break",        "continue",
  1112         "return",       "try",          "catch",        "finally",      "throw",
  1113         "stat",         "expression",   "declaration",  "declaration",  null,
  1114 
  1115         "import",       "class",        "extends",      "implements",   "interface",
  1116         "package",      null,           null,           null,           null,
  1117 
  1118         "private",      "public",       "protected",    "const",        "static",
  1119         "transient",    "synchronized", "native",       "final",        "volatile",
  1120         "abstract",     null,           null,           null,           null,
  1121 
  1122         ";",            ":",            "?",            "{",            "}",
  1123         "(",            ")",            "[",            "]",            "throws",
  1124         "error",        "comment",      "type",         "length",       "inline-return",
  1125         "inline-method", "inline-new",
  1126         "method", "field", "stack", "locals", "CPINDEX", "CPName", "SIGN",
  1127         "bits", "INF", "NaN", "InnerClass", "of", "synthetic"
  1128     };
  1129     
  1130     static class AnnotationParser {
  1131 
  1132         private final boolean textual;
  1133         private final boolean iterateArray;
  1134 
  1135         protected AnnotationParser(boolean textual, boolean iterateArray) {
  1136             this.textual = textual;
  1137             this.iterateArray = iterateArray;
  1138         }
  1139 
  1140         protected void visitAnnotationStart(String type, boolean top) throws IOException {
  1141         }
  1142 
  1143         protected void visitAnnotationEnd(String type, boolean top) throws IOException {
  1144         }
  1145 
  1146         protected void visitValueStart(String attrName, char type) throws IOException {
  1147         }
  1148 
  1149         protected void visitValueEnd(String attrName, char type) throws IOException {
  1150         }
  1151 
  1152         protected void visitAttr(
  1153             String annoType, String attr, String attrType, String value) throws IOException {
  1154         }
  1155 
  1156         protected void visitEnumAttr(
  1157             String annoType, String attr, String attrType, String value) throws IOException {
  1158             visitAttr(annoType, attr, attrType, value);
  1159         }
  1160 
  1161         /**
  1162          * Initialize the parsing with constant pool from
  1163          * <code>cd</code>.
  1164          *
  1165          * @param attr the attribute defining annotations
  1166          * @param cd constant pool
  1167          * @throws IOException in case I/O fails
  1168          */
  1169         public final void parse(byte[] attr, ClassData cd) throws IOException {
  1170             ByteArrayInputStream is = new ByteArrayInputStream(attr);
  1171             DataInputStream dis = new DataInputStream(is);
  1172             try {
  1173                 read(dis, cd);
  1174             } finally {
  1175                 is.close();
  1176             }
  1177         }
  1178 
  1179         private void read(DataInputStream dis, ClassData cd) throws IOException {
  1180             int cnt = dis.readUnsignedShort();
  1181             for (int i = 0; i < cnt; i++) {
  1182                 readAnno(dis, cd, true);
  1183             }
  1184         }
  1185 
  1186         private void readAnno(DataInputStream dis, ClassData cd, boolean top) throws IOException {
  1187             int type = dis.readUnsignedShort();
  1188             String typeName = cd.StringValue(type);
  1189             visitAnnotationStart(typeName, top);
  1190             int cnt = dis.readUnsignedShort();
  1191             for (int i = 0; i < cnt; i++) {
  1192                 String attrName = cd.StringValue(dis.readUnsignedShort());
  1193                 readValue(dis, cd, typeName, attrName);
  1194             }
  1195             visitAnnotationEnd(typeName, top);
  1196             if (cnt == 0) {
  1197                 visitAttr(typeName, null, null, null);
  1198             }
  1199         }
  1200 
  1201         private void readValue(
  1202             DataInputStream dis, ClassData cd, String typeName, String attrName) throws IOException {
  1203             char type = (char) dis.readByte();
  1204             visitValueStart(attrName, type);
  1205             if (type == '@') {
  1206                 readAnno(dis, cd, false);
  1207             } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
  1208                 int primitive = dis.readUnsignedShort();
  1209                 String val = cd.stringValue(primitive, textual);
  1210                 String attrType;
  1211                 if (type == 's') {
  1212                     attrType = "Ljava_lang_String_2";
  1213                     if (textual) {
  1214                         val = '"' + val + '"';
  1215                     }
  1216                 } else {
  1217                     attrType = "" + type;
  1218                 }
  1219                 visitAttr(typeName, attrName, attrType, val);
  1220             } else if (type == 'c') {
  1221                 int cls = dis.readUnsignedShort();
  1222             } else if (type == '[') {
  1223                 int cnt = dis.readUnsignedShort();
  1224                 for (int i = 0; i < cnt; i++) {
  1225                     readValue(dis, cd, typeName, iterateArray ? attrName : null);
  1226                 }
  1227             } else if (type == 'e') {
  1228                 int enumT = dis.readUnsignedShort();
  1229                 String attrType = cd.stringValue(enumT, textual);
  1230                 int enumN = dis.readUnsignedShort();
  1231                 String val = cd.stringValue(enumN, textual);
  1232                 visitEnumAttr(typeName, attrName, attrType, val);
  1233             } else {
  1234                 throw new IOException("Unknown type " + type);
  1235             }
  1236             visitValueEnd(attrName, type);
  1237         }
  1238     }
  1239     
  1240     /**
  1241      * Reads and stores attribute information.
  1242      *
  1243      * @author Sucheta Dambalkar (Adopted code from jdis)
  1244      */
  1245     private static class AttrData {
  1246 
  1247         ClassData cls;
  1248         int name_cpx;
  1249         int datalen;
  1250         byte data[];
  1251 
  1252         public AttrData(ClassData cls) {
  1253             this.cls = cls;
  1254         }
  1255 
  1256         /**
  1257          * Reads unknown attribute.
  1258          */
  1259         public void read(int name_cpx, DataInputStream in) throws IOException {
  1260             this.name_cpx = name_cpx;
  1261             datalen = in.readInt();
  1262             data = new byte[datalen];
  1263             in.readFully(data);
  1264         }
  1265 
  1266         /**
  1267          * Reads just the name of known attribute.
  1268          */
  1269         public void read(int name_cpx) {
  1270             this.name_cpx = name_cpx;
  1271         }
  1272 
  1273         /**
  1274          * Returns attribute name.
  1275          */
  1276         public String getAttrName() {
  1277             return cls.getString(name_cpx);
  1278         }
  1279 
  1280         /**
  1281          * Returns attribute data.
  1282          */
  1283         public byte[] getData() {
  1284             return data;
  1285         }
  1286     }
  1287 
  1288     /**
  1289      * Stores constant pool entry information with one field.
  1290      *
  1291      * @author Sucheta Dambalkar (Adopted code from jdis)
  1292      */
  1293     private static class CPX {
  1294 
  1295         int cpx;
  1296 
  1297         CPX(int cpx) {
  1298             this.cpx = cpx;
  1299         }
  1300     }
  1301 
  1302     /**
  1303      * Stores constant pool entry information with two fields.
  1304      *
  1305      * @author Sucheta Dambalkar (Adopted code from jdis)
  1306      */
  1307     private static class CPX2 {
  1308 
  1309         int cpx1, cpx2;
  1310 
  1311         CPX2(int cpx1, int cpx2) {
  1312             this.cpx1 = cpx1;
  1313             this.cpx2 = cpx2;
  1314         }
  1315     }
  1316 
  1317     /**
  1318      * Central data repository of the Java Disassembler. Stores all the
  1319      * information in java class file.
  1320      *
  1321      * @author Sucheta Dambalkar (Adopted code from jdis)
  1322      */
  1323     static final class ClassData {
  1324 
  1325         private int magic;
  1326         private int minor_version;
  1327         private int major_version;
  1328         private int cpool_count;
  1329         private Object cpool[];
  1330         private int access;
  1331         private int this_class = 0;
  1332         private int super_class;
  1333         private int interfaces_count;
  1334         private int[] interfaces = new int[0];
  1335         private int fields_count;
  1336         private FieldData[] fields;
  1337         private int methods_count;
  1338         private MethodData[] methods;
  1339         private InnerClassData[] innerClasses;
  1340         private int attributes_count;
  1341         private AttrData[] attrs;
  1342         private String classname;
  1343         private String superclassname;
  1344         private int source_cpx = 0;
  1345         private byte tags[];
  1346         private Hashtable indexHashAscii = new Hashtable();
  1347         private String pkgPrefix = "";
  1348         private int pkgPrefixLen = 0;
  1349 
  1350         /**
  1351          * Read classfile to disassemble.
  1352          */
  1353         public ClassData(InputStream infile) throws IOException {
  1354             this.read(new DataInputStream(infile));
  1355         }
  1356 
  1357         /**
  1358          * Reads and stores class file information.
  1359          */
  1360         public void read(DataInputStream in) throws IOException {
  1361             // Read the header
  1362             magic = in.readInt();
  1363             if (magic != JAVA_MAGIC) {
  1364                 throw new ClassFormatError("wrong magic: "
  1365                     + toHex(magic) + ", expected "
  1366                     + toHex(JAVA_MAGIC));
  1367             }
  1368             minor_version = in.readShort();
  1369             major_version = in.readShort();
  1370             if (major_version != JAVA_VERSION) {
  1371             }
  1372 
  1373             // Read the constant pool
  1374             readCP(in);
  1375             access = in.readUnsignedShort();
  1376             this_class = in.readUnsignedShort();
  1377             super_class = in.readUnsignedShort();
  1378 
  1379             //Read interfaces.
  1380             interfaces_count = in.readUnsignedShort();
  1381             if (interfaces_count > 0) {
  1382                 interfaces = new int[interfaces_count];
  1383             }
  1384             for (int i = 0; i < interfaces_count; i++) {
  1385                 interfaces[i] = in.readShort();
  1386             }
  1387 
  1388             // Read the fields
  1389             readFields(in);
  1390 
  1391             // Read the methods
  1392             readMethods(in);
  1393 
  1394             // Read the attributes
  1395             attributes_count = in.readUnsignedShort();
  1396             attrs = new AttrData[attributes_count];
  1397             for (int k = 0; k < attributes_count; k++) {
  1398                 int name_cpx = in.readUnsignedShort();
  1399                 if (getTag(name_cpx) == CONSTANT_UTF8
  1400                     && getString(name_cpx).equals("SourceFile")) {
  1401                     if (in.readInt() != 2) {
  1402                         throw new ClassFormatError("invalid attr length");
  1403                     }
  1404                     source_cpx = in.readUnsignedShort();
  1405                     AttrData attr = new AttrData(this);
  1406                     attr.read(name_cpx);
  1407                     attrs[k] = attr;
  1408 
  1409                 } else if (getTag(name_cpx) == CONSTANT_UTF8
  1410                     && getString(name_cpx).equals("InnerClasses")) {
  1411                     int length = in.readInt();
  1412                     int num = in.readUnsignedShort();
  1413                     if (2 + num * 8 != length) {
  1414                         throw new ClassFormatError("invalid attr length");
  1415                     }
  1416                     innerClasses = new InnerClassData[num];
  1417                     for (int j = 0; j < num; j++) {
  1418                         InnerClassData innerClass = new InnerClassData(this);
  1419                         innerClass.read(in);
  1420                         innerClasses[j] = innerClass;
  1421                     }
  1422                     AttrData attr = new AttrData(this);
  1423                     attr.read(name_cpx);
  1424                     attrs[k] = attr;
  1425                 } else {
  1426                     AttrData attr = new AttrData(this);
  1427                     attr.read(name_cpx, in);
  1428                     attrs[k] = attr;
  1429                 }
  1430             }
  1431             in.close();
  1432         } // end ClassData.read()
  1433 
  1434         /**
  1435          * Reads and stores constant pool info.
  1436          */
  1437         void readCP(DataInputStream in) throws IOException {
  1438             cpool_count = in.readUnsignedShort();
  1439             tags = new byte[cpool_count];
  1440             cpool = new Object[cpool_count];
  1441             for (int i = 1; i < cpool_count; i++) {
  1442                 byte tag = in.readByte();
  1443 
  1444                 switch (tags[i] = tag) {
  1445                     case CONSTANT_UTF8:
  1446                         String str = in.readUTF();
  1447                         indexHashAscii.put(cpool[i] = str, new Integer(i));
  1448                         break;
  1449                     case CONSTANT_INTEGER:
  1450                         cpool[i] = new Integer(in.readInt());
  1451                         break;
  1452                     case CONSTANT_FLOAT:
  1453                         cpool[i] = new Float(in.readFloat());
  1454                         break;
  1455                     case CONSTANT_LONG:
  1456                         cpool[i++] = new Long(in.readLong());
  1457                         break;
  1458                     case CONSTANT_DOUBLE:
  1459                         cpool[i++] = new Double(in.readDouble());
  1460                         break;
  1461                     case CONSTANT_CLASS:
  1462                     case CONSTANT_STRING:
  1463                         cpool[i] = new CPX(in.readUnsignedShort());
  1464                         break;
  1465 
  1466                     case CONSTANT_FIELD:
  1467                     case CONSTANT_METHOD:
  1468                     case CONSTANT_INTERFACEMETHOD:
  1469                     case CONSTANT_NAMEANDTYPE:
  1470                         cpool[i] = new CPX2(in.readUnsignedShort(), in.readUnsignedShort());
  1471                         break;
  1472 
  1473                     case 0:
  1474                     default:
  1475                         throw new ClassFormatError("invalid constant type: " + (int) tags[i]);
  1476                 }
  1477             }
  1478         }
  1479 
  1480         /**
  1481          * Reads and strores field info.
  1482          */
  1483         protected void readFields(DataInputStream in) throws IOException {
  1484             int fields_count = in.readUnsignedShort();
  1485             fields = new FieldData[fields_count];
  1486             for (int k = 0; k < fields_count; k++) {
  1487                 FieldData field = new FieldData(this);
  1488                 field.read(in);
  1489                 fields[k] = field;
  1490             }
  1491         }
  1492 
  1493         /**
  1494          * Reads and strores Method info.
  1495          */
  1496         protected void readMethods(DataInputStream in) throws IOException {
  1497             int methods_count = in.readUnsignedShort();
  1498             methods = new MethodData[methods_count];
  1499             for (int k = 0; k < methods_count; k++) {
  1500                 MethodData method = new MethodData(this);
  1501                 method.read(in);
  1502                 methods[k] = method;
  1503             }
  1504         }
  1505 
  1506         /**
  1507          * get a string
  1508          */
  1509         public String getString(int n) {
  1510             if (n == 0) {
  1511                 return null;
  1512             } else {
  1513                 return (String) cpool[n];
  1514             }
  1515         }
  1516 
  1517         /**
  1518          * get the type of constant given an index
  1519          */
  1520         public byte getTag(int n) {
  1521             try {
  1522                 return tags[n];
  1523             } catch (ArrayIndexOutOfBoundsException e) {
  1524                 return (byte) 100;
  1525             }
  1526         }
  1527         static final String hexString = "0123456789ABCDEF";
  1528         public static char hexTable[] = hexString.toCharArray();
  1529 
  1530         static String toHex(long val, int width) {
  1531             StringBuffer s = new StringBuffer();
  1532             for (int i = width - 1; i >= 0; i--) {
  1533                 s.append(hexTable[((int) (val >> (4 * i))) & 0xF]);
  1534             }
  1535             return "0x" + s.toString();
  1536         }
  1537 
  1538         static String toHex(long val) {
  1539             int width;
  1540             for (width = 16; width > 0; width--) {
  1541                 if ((val >> (width - 1) * 4) != 0) {
  1542                     break;
  1543                 }
  1544             }
  1545             return toHex(val, width);
  1546         }
  1547 
  1548         static String toHex(int val) {
  1549             int width;
  1550             for (width = 8; width > 0; width--) {
  1551                 if ((val >> (width - 1) * 4) != 0) {
  1552                     break;
  1553                 }
  1554             }
  1555             return toHex(val, width);
  1556         }
  1557 
  1558         /**
  1559          * Returns the name of this class.
  1560          */
  1561         public String getClassName() {
  1562             String res = null;
  1563             if (this_class == 0) {
  1564                 return res;
  1565             }
  1566             int tcpx;
  1567             try {
  1568                 if (tags[this_class] != CONSTANT_CLASS) {
  1569                     return res; //"<CP["+cpx+"] is not a Class> ";
  1570                 }
  1571                 tcpx = ((CPX) cpool[this_class]).cpx;
  1572             } catch (ArrayIndexOutOfBoundsException e) {
  1573                 return res; // "#"+cpx+"// invalid constant pool index";
  1574             } catch (Throwable e) {
  1575                 return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
  1576             }
  1577 
  1578             try {
  1579                 return (String) (cpool[tcpx]);
  1580             } catch (ArrayIndexOutOfBoundsException e) {
  1581                 return res; // "class #"+scpx+"// invalid constant pool index";
  1582             } catch (ClassCastException e) {
  1583                 return res; // "class #"+scpx+"// invalid constant pool reference";
  1584             } catch (Throwable e) {
  1585                 return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
  1586             }
  1587 
  1588         }
  1589 
  1590         /**
  1591          * Returns the name of class at perticular index.
  1592          */
  1593         public String getClassName(int cpx) {
  1594             String res = "#" + cpx;
  1595             if (cpx == 0) {
  1596                 return res;
  1597             }
  1598             int scpx;
  1599             try {
  1600                 if (tags[cpx] != CONSTANT_CLASS) {
  1601                     return res; //"<CP["+cpx+"] is not a Class> ";
  1602                 }
  1603                 scpx = ((CPX) cpool[cpx]).cpx;
  1604             } catch (ArrayIndexOutOfBoundsException e) {
  1605                 return res; // "#"+cpx+"// invalid constant pool index";
  1606             } catch (Throwable e) {
  1607                 return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
  1608             }
  1609             res = "#" + scpx;
  1610             try {
  1611                 return (String) (cpool[scpx]);
  1612             } catch (ArrayIndexOutOfBoundsException e) {
  1613                 return res; // "class #"+scpx+"// invalid constant pool index";
  1614             } catch (ClassCastException e) {
  1615                 return res; // "class #"+scpx+"// invalid constant pool reference";
  1616             } catch (Throwable e) {
  1617                 return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
  1618             }
  1619         }
  1620 
  1621         public int getAccessFlags() {
  1622             return access;
  1623         }
  1624 
  1625         /**
  1626          * Returns true if it is a class
  1627          */
  1628         public boolean isClass() {
  1629             if ((access & ACC_INTERFACE) == 0) {
  1630                 return true;
  1631             }
  1632             return false;
  1633         }
  1634 
  1635         /**
  1636          * Returns true if it is a interface.
  1637          */
  1638         public boolean isInterface() {
  1639             if ((access & ACC_INTERFACE) != 0) {
  1640                 return true;
  1641             }
  1642             return false;
  1643         }
  1644 
  1645         /**
  1646          * Returns true if this member is public, false otherwise.
  1647          */
  1648         public boolean isPublic() {
  1649             return (access & ACC_PUBLIC) != 0;
  1650         }
  1651 
  1652         /**
  1653          * Returns the access of this class or interface.
  1654          */
  1655         public String[] getAccess() {
  1656             Vector v = new Vector();
  1657             if ((access & ACC_PUBLIC) != 0) {
  1658                 v.addElement("public");
  1659             }
  1660             if ((access & ACC_FINAL) != 0) {
  1661                 v.addElement("final");
  1662             }
  1663             if ((access & ACC_ABSTRACT) != 0) {
  1664                 v.addElement("abstract");
  1665             }
  1666             String[] accflags = new String[v.size()];
  1667             v.copyInto(accflags);
  1668             return accflags;
  1669         }
  1670 
  1671         /**
  1672          * Returns list of innerclasses.
  1673          */
  1674         public InnerClassData[] getInnerClasses() {
  1675             return innerClasses;
  1676         }
  1677 
  1678         /**
  1679          * Returns list of attributes.
  1680          */
  1681         final AttrData[] getAttributes() {
  1682             return attrs;
  1683         }
  1684 
  1685         public byte[] findAnnotationData(boolean classRetention) {
  1686             String n = classRetention
  1687                 ? "RuntimeInvisibleAnnotations" : // NOI18N
  1688                 "RuntimeVisibleAnnotations"; // NOI18N
  1689             return findAttr(n, attrs);
  1690         }
  1691 
  1692         /**
  1693          * Returns true if superbit is set.
  1694          */
  1695         public boolean isSuperSet() {
  1696             if ((access & ACC_SUPER) != 0) {
  1697                 return true;
  1698             }
  1699             return false;
  1700         }
  1701 
  1702         /**
  1703          * Returns super class name.
  1704          */
  1705         public String getSuperClassName() {
  1706             String res = null;
  1707             if (super_class == 0) {
  1708                 return res;
  1709             }
  1710             int scpx;
  1711             try {
  1712                 if (tags[super_class] != CONSTANT_CLASS) {
  1713                     return res; //"<CP["+cpx+"] is not a Class> ";
  1714                 }
  1715                 scpx = ((CPX) cpool[super_class]).cpx;
  1716             } catch (ArrayIndexOutOfBoundsException e) {
  1717                 return res; // "#"+cpx+"// invalid constant pool index";
  1718             } catch (Throwable e) {
  1719                 return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
  1720             }
  1721 
  1722             try {
  1723                 return (String) (cpool[scpx]);
  1724             } catch (ArrayIndexOutOfBoundsException e) {
  1725                 return res; // "class #"+scpx+"// invalid constant pool index";
  1726             } catch (ClassCastException e) {
  1727                 return res; // "class #"+scpx+"// invalid constant pool reference";
  1728             } catch (Throwable e) {
  1729                 return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
  1730             }
  1731         }
  1732 
  1733         /**
  1734          * Returns list of super interfaces.
  1735          */
  1736         public String[] getSuperInterfaces() {
  1737             String interfacenames[] = new String[interfaces.length];
  1738             int interfacecpx = -1;
  1739             for (int i = 0; i < interfaces.length; i++) {
  1740                 interfacecpx = ((CPX) cpool[interfaces[i]]).cpx;
  1741                 interfacenames[i] = (String) (cpool[interfacecpx]);
  1742             }
  1743             return interfacenames;
  1744         }
  1745 
  1746         /**
  1747          * Returns string at prticular constant pool index.
  1748          */
  1749         public String getStringValue(int cpoolx) {
  1750             try {
  1751                 return ((String) cpool[cpoolx]);
  1752             } catch (ArrayIndexOutOfBoundsException e) {
  1753                 return "//invalid constant pool index:" + cpoolx;
  1754             } catch (ClassCastException e) {
  1755                 return "//invalid constant pool ref:" + cpoolx;
  1756             }
  1757         }
  1758 
  1759         /**
  1760          * Returns list of field info.
  1761          */
  1762         public FieldData[] getFields() {
  1763             return fields;
  1764         }
  1765 
  1766         /**
  1767          * Returns list of method info.
  1768          */
  1769         public MethodData[] getMethods() {
  1770             return methods;
  1771         }
  1772 
  1773         /**
  1774          * Returns constant pool entry at that index.
  1775          */
  1776         public CPX2 getCpoolEntry(int cpx) {
  1777             return ((CPX2) (cpool[cpx]));
  1778         }
  1779 
  1780         public Object getCpoolEntryobj(int cpx) {
  1781             return (cpool[cpx]);
  1782         }
  1783 
  1784         /**
  1785          * Returns index of this class.
  1786          */
  1787         public int getthis_cpx() {
  1788             return this_class;
  1789         }
  1790 
  1791         /**
  1792          * Returns string at that index.
  1793          */
  1794         public String StringValue(int cpx) {
  1795             return stringValue(cpx, false);
  1796         }
  1797 
  1798         public String stringValue(int cpx, boolean textual) {
  1799             return stringValue(cpx, textual, null);
  1800         }
  1801 
  1802         public String stringValue(int cpx, String[] classRefs) {
  1803             return stringValue(cpx, true, classRefs);
  1804         }
  1805 
  1806         private String stringValue(int cpx, boolean textual, String[] refs) {
  1807             if (cpx == 0) {
  1808                 return "#0";
  1809             }
  1810             int tag;
  1811             Object x;
  1812             String suffix = "";
  1813             try {
  1814                 tag = tags[cpx];
  1815                 x = cpool[cpx];
  1816             } catch (IndexOutOfBoundsException e) {
  1817                 return "<Incorrect CP index:" + cpx + ">";
  1818             }
  1819 
  1820             if (x == null) {
  1821                 return "<NULL>";
  1822             }
  1823             switch (tag) {
  1824                 case CONSTANT_UTF8: {
  1825                     if (!textual) {
  1826                         return (String) x;
  1827                     }
  1828                     StringBuilder sb = new StringBuilder();
  1829                     String s = (String) x;
  1830                     for (int k = 0; k < s.length(); k++) {
  1831                         char c = s.charAt(k);
  1832                         switch (c) {
  1833                             case '\\':
  1834                                 sb.append('\\').append('\\');
  1835                                 break;
  1836                             case '\t':
  1837                                 sb.append('\\').append('t');
  1838                                 break;
  1839                             case '\n':
  1840                                 sb.append('\\').append('n');
  1841                                 break;
  1842                             case '\r':
  1843                                 sb.append('\\').append('r');
  1844                                 break;
  1845                             case '\"':
  1846                                 sb.append('\\').append('\"');
  1847                                 break;
  1848                             default:
  1849                                 sb.append(c);
  1850                         }
  1851                     }
  1852                     return sb.toString();
  1853                 }
  1854                 case CONSTANT_DOUBLE: {
  1855                     Double d = (Double) x;
  1856                     String sd = d.toString();
  1857                     if (textual) {
  1858                         return sd;
  1859                     }
  1860                     return sd + "d";
  1861                 }
  1862                 case CONSTANT_FLOAT: {
  1863                     Float f = (Float) x;
  1864                     String sf = (f).toString();
  1865                     if (textual) {
  1866                         return sf;
  1867                     }
  1868                     return sf + "f";
  1869                 }
  1870                 case CONSTANT_LONG: {
  1871                     Long ln = (Long) x;
  1872                     if (textual) {
  1873                         return ln.toString();
  1874                     }
  1875                     return ln.toString() + 'l';
  1876                 }
  1877                 case CONSTANT_INTEGER: {
  1878                     Integer in = (Integer) x;
  1879                     return in.toString();
  1880                 }
  1881                 case CONSTANT_CLASS:
  1882                     String jn = getClassName(cpx);
  1883                     if (textual) {
  1884                         if (refs != null) {
  1885                             refs[0] = jn;
  1886                         }
  1887                         return jn;
  1888                     }
  1889                     return javaName(jn);
  1890                 case CONSTANT_STRING:
  1891                     String sv = stringValue(((CPX) x).cpx, textual);
  1892                     if (textual) {
  1893                         return '"' + sv + '"';
  1894                     } else {
  1895                         return sv;
  1896                     }
  1897                 case CONSTANT_FIELD:
  1898                 case CONSTANT_METHOD:
  1899                 case CONSTANT_INTERFACEMETHOD:
  1900                     //return getShortClassName(((CPX2)x).cpx1)+"."+StringValue(((CPX2)x).cpx2);
  1901                     return javaName(getClassName(((CPX2) x).cpx1)) + "." + StringValue(((CPX2) x).cpx2);
  1902 
  1903                 case CONSTANT_NAMEANDTYPE:
  1904                     return getName(((CPX2) x).cpx1) + ":" + StringValue(((CPX2) x).cpx2);
  1905                 default:
  1906                     return "UnknownTag"; //TBD
  1907             }
  1908         }
  1909 
  1910         /**
  1911          * Returns resolved java type name.
  1912          */
  1913         public String javaName(String name) {
  1914             if (name == null) {
  1915                 return "null";
  1916             }
  1917             int len = name.length();
  1918             if (len == 0) {
  1919                 return "\"\"";
  1920             }
  1921             int cc = '/';
  1922             fullname:
  1923             { // xxx/yyy/zzz
  1924                 int cp;
  1925                 for (int k = 0; k < len; k += Character.charCount(cp)) {
  1926                     cp = name.codePointAt(k);
  1927                     if (cc == '/') {
  1928                         if (!isJavaIdentifierStart(cp)) {
  1929                             break fullname;
  1930                         }
  1931                     } else if (cp != '/') {
  1932                         if (!isJavaIdentifierPart(cp)) {
  1933                             break fullname;
  1934                         }
  1935                     }
  1936                     cc = cp;
  1937                 }
  1938                 return name;
  1939             }
  1940             return "\"" + name + "\"";
  1941         }
  1942 
  1943         public String getName(int cpx) {
  1944             String res;
  1945             try {
  1946                 return javaName((String) cpool[cpx]); //.replace('/','.');
  1947             } catch (ArrayIndexOutOfBoundsException e) {
  1948                 return "<invalid constant pool index:" + cpx + ">";
  1949             } catch (ClassCastException e) {
  1950                 return "<invalid constant pool ref:" + cpx + ">";
  1951             }
  1952         }
  1953 
  1954         /**
  1955          * Returns unqualified class name.
  1956          */
  1957         public String getShortClassName(int cpx) {
  1958             String classname = javaName(getClassName(cpx));
  1959             pkgPrefixLen = classname.lastIndexOf("/") + 1;
  1960             if (pkgPrefixLen != 0) {
  1961                 pkgPrefix = classname.substring(0, pkgPrefixLen);
  1962                 if (classname.startsWith(pkgPrefix)) {
  1963                     return classname.substring(pkgPrefixLen);
  1964                 }
  1965             }
  1966             return classname;
  1967         }
  1968 
  1969         /**
  1970          * Returns source file name.
  1971          */
  1972         public String getSourceName() {
  1973             return getName(source_cpx);
  1974         }
  1975 
  1976         /**
  1977          * Returns package name.
  1978          */
  1979         public String getPkgName() {
  1980             String classname = getClassName(this_class);
  1981             pkgPrefixLen = classname.lastIndexOf("/") + 1;
  1982             if (pkgPrefixLen != 0) {
  1983                 pkgPrefix = classname.substring(0, pkgPrefixLen);
  1984                 return /* ("package  " + */ pkgPrefix.substring(0, pkgPrefixLen - 1) /* + ";\n") */;
  1985             } else {
  1986                 return null;
  1987             }
  1988         }
  1989 
  1990         /**
  1991          * Returns total constant pool entry count.
  1992          */
  1993         public int getCpoolCount() {
  1994             return cpool_count;
  1995         }
  1996 
  1997         /**
  1998          * Returns minor version of class file.
  1999          */
  2000         public int getMinor_version() {
  2001             return minor_version;
  2002         }
  2003 
  2004         /**
  2005          * Returns major version of class file.
  2006          */
  2007         public int getMajor_version() {
  2008             return major_version;
  2009         }
  2010 
  2011         private boolean isJavaIdentifierStart(int cp) {
  2012             return ('a' <= cp && cp <= 'z') || ('A' <= cp && cp <= 'Z');
  2013         }
  2014 
  2015         private boolean isJavaIdentifierPart(int cp) {
  2016             return isJavaIdentifierStart(cp) || ('0' <= cp && cp <= '9');
  2017         }
  2018 
  2019         public String[] getNameAndType(int indx) {
  2020             return getNameAndType(indx, 0, new String[2]);
  2021         }
  2022 
  2023         private String[] getNameAndType(int indx, int at, String[] arr) {
  2024             CPX2 c2 = getCpoolEntry(indx);
  2025             arr[at] = StringValue(c2.cpx1);
  2026             arr[at + 1] = StringValue(c2.cpx2);
  2027             return arr;
  2028         }
  2029 
  2030         public String[] getFieldInfoName(int indx) {
  2031             CPX2 c2 = getCpoolEntry(indx);
  2032             String[] arr = new String[3];
  2033             arr[0] = getClassName(c2.cpx1);
  2034             return getNameAndType(c2.cpx2, 1, arr);
  2035         }
  2036 
  2037         static byte[] findAttr(String n, AttrData[] attrs) {
  2038             for (AttrData ad : attrs) {
  2039                 if (n.equals(ad.getAttrName())) {
  2040                     return ad.getData();
  2041                 }
  2042             }
  2043             return null;
  2044         }
  2045     }
  2046 
  2047     /**
  2048      * Strores field data informastion.
  2049      *
  2050      * @author Sucheta Dambalkar (Adopted code from jdis)
  2051      */
  2052     static class FieldData {
  2053 
  2054         ClassData cls;
  2055         int access;
  2056         int name_index;
  2057         int descriptor_index;
  2058         int attributes_count;
  2059         int value_cpx = 0;
  2060         boolean isSynthetic = false;
  2061         boolean isDeprecated = false;
  2062         Vector attrs;
  2063 
  2064         public FieldData(ClassData cls) {
  2065             this.cls = cls;
  2066         }
  2067 
  2068         /**
  2069          * Read and store field info.
  2070          */
  2071         public void read(DataInputStream in) throws IOException {
  2072             access = in.readUnsignedShort();
  2073             name_index = in.readUnsignedShort();
  2074             descriptor_index = in.readUnsignedShort();
  2075             // Read the attributes
  2076             int attributes_count = in.readUnsignedShort();
  2077             attrs = new Vector(attributes_count);
  2078             for (int i = 0; i < attributes_count; i++) {
  2079                 int attr_name_index = in.readUnsignedShort();
  2080                 if (cls.getTag(attr_name_index) != CONSTANT_UTF8) {
  2081                     continue;
  2082                 }
  2083                 String attr_name = cls.getString(attr_name_index);
  2084                 if (attr_name.equals("ConstantValue")) {
  2085                     if (in.readInt() != 2) {
  2086                         throw new ClassFormatError("invalid ConstantValue attr length");
  2087                     }
  2088                     value_cpx = in.readUnsignedShort();
  2089                     AttrData attr = new AttrData(cls);
  2090                     attr.read(attr_name_index);
  2091                     attrs.addElement(attr);
  2092                 } else if (attr_name.equals("Synthetic")) {
  2093                     if (in.readInt() != 0) {
  2094                         throw new ClassFormatError("invalid Synthetic attr length");
  2095                     }
  2096                     isSynthetic = true;
  2097                     AttrData attr = new AttrData(cls);
  2098                     attr.read(attr_name_index);
  2099                     attrs.addElement(attr);
  2100                 } else if (attr_name.equals("Deprecated")) {
  2101                     if (in.readInt() != 0) {
  2102                         throw new ClassFormatError("invalid Synthetic attr length");
  2103                     }
  2104                     isDeprecated = true;
  2105                     AttrData attr = new AttrData(cls);
  2106                     attr.read(attr_name_index);
  2107                     attrs.addElement(attr);
  2108                 } else {
  2109                     AttrData attr = new AttrData(cls);
  2110                     attr.read(attr_name_index, in);
  2111                     attrs.addElement(attr);
  2112                 }
  2113             }
  2114 
  2115         }  // end read
  2116 
  2117         public boolean isStatic() {
  2118             return (access & ACC_STATIC) != 0;
  2119         }
  2120 
  2121         /**
  2122          * Returns access of a field.
  2123          */
  2124         public String[] getAccess() {
  2125             Vector v = new Vector();
  2126             if ((access & ACC_PUBLIC) != 0) {
  2127                 v.addElement("public");
  2128             }
  2129             if ((access & ACC_PRIVATE) != 0) {
  2130                 v.addElement("private");
  2131             }
  2132             if ((access & ACC_PROTECTED) != 0) {
  2133                 v.addElement("protected");
  2134             }
  2135             if ((access & ACC_STATIC) != 0) {
  2136                 v.addElement("static");
  2137             }
  2138             if ((access & ACC_FINAL) != 0) {
  2139                 v.addElement("final");
  2140             }
  2141             if ((access & ACC_VOLATILE) != 0) {
  2142                 v.addElement("volatile");
  2143             }
  2144             if ((access & ACC_TRANSIENT) != 0) {
  2145                 v.addElement("transient");
  2146             }
  2147             String[] accflags = new String[v.size()];
  2148             v.copyInto(accflags);
  2149             return accflags;
  2150         }
  2151 
  2152         /**
  2153          * Returns name of a field.
  2154          */
  2155         public String getName() {
  2156             return cls.getStringValue(name_index);
  2157         }
  2158 
  2159         /**
  2160          * Returns internal signature of a field
  2161          */
  2162         public String getInternalSig() {
  2163             return cls.getStringValue(descriptor_index);
  2164         }
  2165 
  2166         /**
  2167          * Returns true if field is synthetic.
  2168          */
  2169         public boolean isSynthetic() {
  2170             return isSynthetic;
  2171         }
  2172 
  2173         /**
  2174          * Returns true if field is deprecated.
  2175          */
  2176         public boolean isDeprecated() {
  2177             return isDeprecated;
  2178         }
  2179 
  2180         /**
  2181          * Returns index of constant value in cpool.
  2182          */
  2183         public int getConstantValueIndex() {
  2184             return (value_cpx);
  2185         }
  2186 
  2187         /**
  2188          * Returns list of attributes of field.
  2189          */
  2190         public Vector getAttributes() {
  2191             return attrs;
  2192         }
  2193 
  2194         public byte[] findAnnotationData(boolean classRetention) {
  2195             String n = classRetention
  2196                 ? "RuntimeInvisibleAnnotations" : // NOI18N
  2197                 "RuntimeVisibleAnnotations"; // NOI18N
  2198             AttrData[] arr = new AttrData[attrs.size()];
  2199             attrs.copyInto(arr);
  2200             return ClassData.findAttr(n, arr);
  2201         }
  2202     }
  2203 
  2204     /**
  2205      * A JavaScript optimized replacement for Hashtable.
  2206      *
  2207      * @author Jaroslav Tulach <jtulach@netbeans.org>
  2208      */
  2209     private static final class Hashtable {
  2210 
  2211         private Object[] keys;
  2212         private Object[] values;
  2213 
  2214         Hashtable(int i) {
  2215             this();
  2216         }
  2217 
  2218         Hashtable(int i, double d) {
  2219             this();
  2220         }
  2221 
  2222         Hashtable() {
  2223         }
  2224 
  2225         synchronized void put(Object key, Object val) {
  2226             int[] where = {-1, -1};
  2227             Object found = get(key, where);
  2228             if (where[0] != -1) {
  2229                 // key exists
  2230                 values[where[0]] = val;
  2231             } else {
  2232                 if (where[1] != -1) {
  2233                     // null found
  2234                     keys[where[1]] = key;
  2235                     values[where[1]] = val;
  2236                 } else {
  2237                     if (keys == null) {
  2238                         keys = new Object[11];
  2239                         values = new Object[11];
  2240                         keys[0] = key;
  2241                         values[0] = val;
  2242                     } else {
  2243                         Object[] newKeys = new Object[keys.length * 2];
  2244                         Object[] newValues = new Object[values.length * 2];
  2245                         for (int i = 0; i < keys.length; i++) {
  2246                             newKeys[i] = keys[i];
  2247                             newValues[i] = values[i];
  2248                         }
  2249                         newKeys[keys.length] = key;
  2250                         newValues[keys.length] = val;
  2251                         keys = newKeys;
  2252                         values = newValues;
  2253                     }
  2254                 }
  2255             }
  2256         }
  2257 
  2258         Object get(Object key) {
  2259             return get(key, null);
  2260         }
  2261 
  2262         private synchronized Object get(Object key, int[] foundAndNull) {
  2263             if (keys == null) {
  2264                 return null;
  2265             }
  2266             for (int i = 0; i < keys.length; i++) {
  2267                 if (keys[i] == null) {
  2268                     if (foundAndNull != null) {
  2269                         foundAndNull[1] = i;
  2270                     }
  2271                 } else if (keys[i].equals(key)) {
  2272                     if (foundAndNull != null) {
  2273                         foundAndNull[0] = i;
  2274                     }
  2275                     return values[i];
  2276                 }
  2277             }
  2278             return null;
  2279         }
  2280     }
  2281 
  2282     /**
  2283      * Strores InnerClass data informastion.
  2284      *
  2285      * @author Sucheta Dambalkar (Adopted code from jdis)
  2286      */
  2287     private static class InnerClassData {
  2288 
  2289         ClassData cls;
  2290         int inner_class_info_index, outer_class_info_index, inner_name_index, access;
  2291 
  2292         public InnerClassData(ClassData cls) {
  2293             this.cls = cls;
  2294 
  2295         }
  2296 
  2297         /**
  2298          * Read Innerclass attribute data.
  2299          */
  2300         public void read(DataInputStream in) throws IOException {
  2301             inner_class_info_index = in.readUnsignedShort();
  2302             outer_class_info_index = in.readUnsignedShort();
  2303             inner_name_index = in.readUnsignedShort();
  2304             access = in.readUnsignedShort();
  2305         }  // end read
  2306 
  2307         /**
  2308          * Returns the access of this class or interface.
  2309          */
  2310         public String[] getAccess() {
  2311             Vector v = new Vector();
  2312             if ((access & ACC_PUBLIC) != 0) {
  2313                 v.addElement("public");
  2314             }
  2315             if ((access & ACC_FINAL) != 0) {
  2316                 v.addElement("final");
  2317             }
  2318             if ((access & ACC_ABSTRACT) != 0) {
  2319                 v.addElement("abstract");
  2320             }
  2321             String[] accflags = new String[v.size()];
  2322             v.copyInto(accflags);
  2323             return accflags;
  2324         }
  2325     } // end InnerClassData
  2326 
  2327     /**
  2328      * Strores LineNumberTable data information.
  2329      *
  2330      * @author Sucheta Dambalkar (Adopted code from jdis)
  2331      */
  2332     private static class LineNumData {
  2333 
  2334         short start_pc, line_number;
  2335 
  2336         public LineNumData() {
  2337         }
  2338 
  2339         /**
  2340          * Read LineNumberTable attribute.
  2341          */
  2342         public LineNumData(DataInputStream in) throws IOException {
  2343             start_pc = in.readShort();
  2344             line_number = in.readShort();
  2345 
  2346         }
  2347     }
  2348 
  2349     /**
  2350      * Strores LocalVariableTable data information.
  2351      *
  2352      * @author Sucheta Dambalkar (Adopted code from jdis)
  2353      */
  2354     private static class LocVarData {
  2355 
  2356         short start_pc, length, name_cpx, sig_cpx, slot;
  2357 
  2358         public LocVarData() {
  2359         }
  2360 
  2361         /**
  2362          * Read LocalVariableTable attribute.
  2363          */
  2364         public LocVarData(DataInputStream in) throws IOException {
  2365             start_pc = in.readShort();
  2366             length = in.readShort();
  2367             name_cpx = in.readShort();
  2368             sig_cpx = in.readShort();
  2369             slot = in.readShort();
  2370 
  2371         }
  2372     }
  2373     /**
  2374      * Strores method data informastion.
  2375      *
  2376      * @author Sucheta Dambalkar (Adopted code from jdis)
  2377      */
  2378     static class MethodData {
  2379 
  2380         ClassData cls;
  2381         int access;
  2382         int name_index;
  2383         int descriptor_index;
  2384         int attributes_count;
  2385         byte[] code;
  2386         Vector exception_table = new Vector(0);
  2387         Vector lin_num_tb = new Vector(0);
  2388         Vector loc_var_tb = new Vector(0);
  2389         StackMapTableData[] stackMapTable;
  2390         StackMapData[] stackMap;
  2391         int[] exc_index_table = null;
  2392         Vector attrs = new Vector(0);
  2393         Vector code_attrs = new Vector(0);
  2394         int max_stack, max_locals;
  2395         boolean isSynthetic = false;
  2396         boolean isDeprecated = false;
  2397 
  2398         public MethodData(ClassData cls) {
  2399             this.cls = cls;
  2400         }
  2401 
  2402         /**
  2403          * Read method info.
  2404          */
  2405         public void read(DataInputStream in) throws IOException {
  2406             access = in.readUnsignedShort();
  2407             name_index = in.readUnsignedShort();
  2408             descriptor_index = in.readUnsignedShort();
  2409             int attributes_count = in.readUnsignedShort();
  2410             for (int i = 0; i < attributes_count; i++) {
  2411                 int attr_name_index = in.readUnsignedShort();
  2412 
  2413                 readAttr:
  2414                 {
  2415                     if (cls.getTag(attr_name_index) == CONSTANT_UTF8) {
  2416                         String attr_name = cls.getString(attr_name_index);
  2417                         if (attr_name.equals("Code")) {
  2418                             readCode(in);
  2419                             AttrData attr = new AttrData(cls);
  2420                             attr.read(attr_name_index);
  2421                             attrs.addElement(attr);
  2422                             break readAttr;
  2423                         } else if (attr_name.equals("Exceptions")) {
  2424                             readExceptions(in);
  2425                             AttrData attr = new AttrData(cls);
  2426                             attr.read(attr_name_index);
  2427                             attrs.addElement(attr);
  2428                             break readAttr;
  2429                         } else if (attr_name.equals("Synthetic")) {
  2430                             if (in.readInt() != 0) {
  2431                                 throw new ClassFormatError("invalid Synthetic attr length");
  2432                             }
  2433                             isSynthetic = true;
  2434                             AttrData attr = new AttrData(cls);
  2435                             attr.read(attr_name_index);
  2436                             attrs.addElement(attr);
  2437                             break readAttr;
  2438                         } else if (attr_name.equals("Deprecated")) {
  2439                             if (in.readInt() != 0) {
  2440                                 throw new ClassFormatError("invalid Synthetic attr length");
  2441                             }
  2442                             isDeprecated = true;
  2443                             AttrData attr = new AttrData(cls);
  2444                             attr.read(attr_name_index);
  2445                             attrs.addElement(attr);
  2446                             break readAttr;
  2447                         }
  2448                     }
  2449                     AttrData attr = new AttrData(cls);
  2450                     attr.read(attr_name_index, in);
  2451                     attrs.addElement(attr);
  2452                 }
  2453             }
  2454         }
  2455 
  2456         /**
  2457          * Read code attribute info.
  2458          */
  2459         public void readCode(DataInputStream in) throws IOException {
  2460 
  2461             int attr_length = in.readInt();
  2462             max_stack = in.readUnsignedShort();
  2463             max_locals = in.readUnsignedShort();
  2464             int codelen = in.readInt();
  2465 
  2466             code = new byte[codelen];
  2467             int totalread = 0;
  2468             while (totalread < codelen) {
  2469                 totalread += in.read(code, totalread, codelen - totalread);
  2470             }
  2471             //      in.read(code, 0, codelen);
  2472             int clen = 0;
  2473             readExceptionTable(in);
  2474             int code_attributes_count = in.readUnsignedShort();
  2475 
  2476             for (int k = 0; k < code_attributes_count; k++) {
  2477                 int table_name_index = in.readUnsignedShort();
  2478                 int table_name_tag = cls.getTag(table_name_index);
  2479                 AttrData attr = new AttrData(cls);
  2480                 if (table_name_tag == CONSTANT_UTF8) {
  2481                     String table_name_tstr = cls.getString(table_name_index);
  2482                     if (table_name_tstr.equals("LineNumberTable")) {
  2483                         readLineNumTable(in);
  2484                         attr.read(table_name_index);
  2485                     } else if (table_name_tstr.equals("LocalVariableTable")) {
  2486                         readLocVarTable(in);
  2487                         attr.read(table_name_index);
  2488                     } else if (table_name_tstr.equals("StackMapTable")) {
  2489                         readStackMapTable(in);
  2490                         attr.read(table_name_index);
  2491                     } else if (table_name_tstr.equals("StackMap")) {
  2492                         readStackMap(in);
  2493                         attr.read(table_name_index);
  2494                     } else {
  2495                         attr.read(table_name_index, in);
  2496                     }
  2497                     code_attrs.addElement(attr);
  2498                     continue;
  2499                 }
  2500 
  2501                 attr.read(table_name_index, in);
  2502                 code_attrs.addElement(attr);
  2503             }
  2504         }
  2505 
  2506         /**
  2507          * Read exception table info.
  2508          */
  2509         void readExceptionTable(DataInputStream in) throws IOException {
  2510             int exception_table_len = in.readUnsignedShort();
  2511             exception_table = new Vector(exception_table_len);
  2512             for (int l = 0; l < exception_table_len; l++) {
  2513                 exception_table.addElement(new TrapData(in, l));
  2514             }
  2515         }
  2516 
  2517         /**
  2518          * Read LineNumberTable attribute info.
  2519          */
  2520         void readLineNumTable(DataInputStream in) throws IOException {
  2521             int attr_len = in.readInt(); // attr_length
  2522             int lin_num_tb_len = in.readUnsignedShort();
  2523             lin_num_tb = new Vector(lin_num_tb_len);
  2524             for (int l = 0; l < lin_num_tb_len; l++) {
  2525                 lin_num_tb.addElement(new LineNumData(in));
  2526             }
  2527         }
  2528 
  2529         /**
  2530          * Read LocalVariableTable attribute info.
  2531          */
  2532         void readLocVarTable(DataInputStream in) throws IOException {
  2533             int attr_len = in.readInt(); // attr_length
  2534             int loc_var_tb_len = in.readUnsignedShort();
  2535             loc_var_tb = new Vector(loc_var_tb_len);
  2536             for (int l = 0; l < loc_var_tb_len; l++) {
  2537                 loc_var_tb.addElement(new LocVarData(in));
  2538             }
  2539         }
  2540 
  2541         /**
  2542          * Read Exception attribute info.
  2543          */
  2544         public void readExceptions(DataInputStream in) throws IOException {
  2545             int attr_len = in.readInt(); // attr_length in prog
  2546             int num_exceptions = in.readUnsignedShort();
  2547             exc_index_table = new int[num_exceptions];
  2548             for (int l = 0; l < num_exceptions; l++) {
  2549                 int exc = in.readShort();
  2550                 exc_index_table[l] = exc;
  2551             }
  2552         }
  2553 
  2554         /**
  2555          * Read StackMapTable attribute info.
  2556          */
  2557         void readStackMapTable(DataInputStream in) throws IOException {
  2558             int attr_len = in.readInt();  //attr_length
  2559             int stack_map_tb_len = in.readUnsignedShort();
  2560             stackMapTable = new StackMapTableData[stack_map_tb_len];
  2561             for (int i = 0; i < stack_map_tb_len; i++) {
  2562                 stackMapTable[i] = StackMapTableData.getInstance(in, this);
  2563             }
  2564         }
  2565 
  2566         /**
  2567          * Read StackMap attribute info.
  2568          */
  2569         void readStackMap(DataInputStream in) throws IOException {
  2570             int attr_len = in.readInt();  //attr_length
  2571             int stack_map_len = in.readUnsignedShort();
  2572             stackMap = new StackMapData[stack_map_len];
  2573             for (int i = 0; i < stack_map_len; i++) {
  2574                 stackMap[i] = new StackMapData(in, this);
  2575             }
  2576         }
  2577 
  2578         /**
  2579          * Return access of the method.
  2580          */
  2581         public int getAccess() {
  2582             return access;
  2583         }
  2584 
  2585         /**
  2586          * Return name of the method.
  2587          */
  2588         public String getName() {
  2589             return cls.getStringValue(name_index);
  2590         }
  2591 
  2592         /**
  2593          * Return internal siganature of the method.
  2594          */
  2595         public String getInternalSig() {
  2596             return cls.getStringValue(descriptor_index);
  2597         }
  2598 
  2599         /**
  2600          * Return code attribute data of a method.
  2601          */
  2602         public byte[] getCode() {
  2603             return code;
  2604         }
  2605 
  2606         /**
  2607          * Return LineNumberTable size.
  2608          */
  2609         public int getnumlines() {
  2610             return lin_num_tb.size();
  2611         }
  2612 
  2613         /**
  2614          * Return LineNumberTable
  2615          */
  2616         public Vector getlin_num_tb() {
  2617             return lin_num_tb;
  2618         }
  2619 
  2620         /**
  2621          * Return LocalVariableTable size.
  2622          */
  2623         public int getloc_var_tbsize() {
  2624             return loc_var_tb.size();
  2625         }
  2626 
  2627         /**
  2628          * Return LocalVariableTable.
  2629          */
  2630         public Vector getloc_var_tb() {
  2631             return loc_var_tb;
  2632         }
  2633 
  2634         /**
  2635          * Return StackMap.
  2636          */
  2637         public StackMapData[] getStackMap() {
  2638             return stackMap;
  2639         }
  2640 
  2641         /**
  2642          * Return StackMapTable.
  2643          */
  2644         public StackMapTableData[] getStackMapTable() {
  2645             return stackMapTable;
  2646         }
  2647 
  2648         public StackMapIterator createStackMapIterator() {
  2649             return new StackMapIterator(this);
  2650         }
  2651 
  2652         /**
  2653          * Return true if method is static
  2654          */
  2655         public boolean isStatic() {
  2656             if ((access & ACC_STATIC) != 0) {
  2657                 return true;
  2658             }
  2659             return false;
  2660         }
  2661 
  2662         /**
  2663          * Return max depth of operand stack.
  2664          */
  2665         public int getMaxStack() {
  2666             return max_stack;
  2667         }
  2668 
  2669         /**
  2670          * Return number of local variables.
  2671          */
  2672         public int getMaxLocals() {
  2673             return max_locals;
  2674         }
  2675 
  2676         /**
  2677          * Return exception index table in Exception attribute.
  2678          */
  2679         public int[] get_exc_index_table() {
  2680             return exc_index_table;
  2681         }
  2682 
  2683         /**
  2684          * Return exception table in code attributre.
  2685          */
  2686         public TrapDataIterator getTrapDataIterator() {
  2687             return new TrapDataIterator(exception_table);
  2688         }
  2689 
  2690         /**
  2691          * Return method attributes.
  2692          */
  2693         public Vector getAttributes() {
  2694             return attrs;
  2695         }
  2696 
  2697         /**
  2698          * Return code attributes.
  2699          */
  2700         public Vector getCodeAttributes() {
  2701             return code_attrs;
  2702         }
  2703 
  2704         /**
  2705          * Return true if method id synthetic.
  2706          */
  2707         public boolean isSynthetic() {
  2708             return isSynthetic;
  2709         }
  2710 
  2711         /**
  2712          * Return true if method is deprecated.
  2713          */
  2714         public boolean isDeprecated() {
  2715             return isDeprecated;
  2716         }
  2717 
  2718         public byte[] findAnnotationData(boolean classRetention) {
  2719             String n = classRetention
  2720                 ? "RuntimeInvisibleAnnotations" : // NOI18N
  2721                 "RuntimeVisibleAnnotations"; // NOI18N
  2722             AttrData[] arr = new AttrData[attrs.size()];
  2723             attrs.copyInto(arr);
  2724             return ClassData.findAttr(n, arr);
  2725         }
  2726 
  2727         public boolean isConstructor() {
  2728             return "<init>".equals(getName());
  2729         }
  2730     }
  2731 
  2732     /* represents one entry of StackMap attribute
  2733      */
  2734     private static class StackMapData {
  2735 
  2736         final int offset;
  2737         final int[] locals;
  2738         final int[] stack;
  2739 
  2740         StackMapData(int offset, int[] locals, int[] stack) {
  2741             this.offset = offset;
  2742             this.locals = locals;
  2743             this.stack = stack;
  2744         }
  2745 
  2746         StackMapData(DataInputStream in, MethodData method) throws IOException {
  2747             offset = in.readUnsignedShort();
  2748             int local_size = in.readUnsignedShort();
  2749             locals = readTypeArray(in, local_size, method);
  2750             int stack_size = in.readUnsignedShort();
  2751             stack = readTypeArray(in, stack_size, method);
  2752         }
  2753 
  2754         static final int[] readTypeArray(DataInputStream in, int length, MethodData method) throws IOException {
  2755             int[] types = new int[length];
  2756             for (int i = 0; i < length; i++) {
  2757                 types[i] = readType(in, method);
  2758             }
  2759             return types;
  2760         }
  2761 
  2762         static final int readType(DataInputStream in, MethodData method) throws IOException {
  2763             int type = in.readUnsignedByte();
  2764             if (type == ITEM_Object || type == ITEM_NewObject) {
  2765                 type = type | (in.readUnsignedShort() << 8);
  2766             }
  2767             return type;
  2768         }
  2769     }
  2770 
  2771     static final class StackMapIterator {
  2772 
  2773         private final StackMapTableData[] stackMapTable;
  2774         private final TypeArray argTypes;
  2775         private final TypeArray localTypes;
  2776         private final TypeArray stackTypes;
  2777         private int nextFrameIndex;
  2778         private int lastFrameByteCodeOffset;
  2779         private int byteCodeOffset;
  2780 
  2781         StackMapIterator(final MethodData methodData) {
  2782             this(methodData.getStackMapTable(),
  2783                 methodData.getInternalSig(),
  2784                 methodData.isStatic());
  2785         }
  2786 
  2787         StackMapIterator(final StackMapTableData[] stackMapTable,
  2788             final String methodSignature,
  2789             final boolean isStaticMethod) {
  2790             this.stackMapTable = (stackMapTable != null)
  2791                 ? stackMapTable
  2792                 : new StackMapTableData[0];
  2793 
  2794             argTypes = getArgTypes(methodSignature, isStaticMethod);
  2795             localTypes = new TypeArray();
  2796             stackTypes = new TypeArray();
  2797 
  2798             localTypes.addAll(argTypes);
  2799 
  2800             lastFrameByteCodeOffset = -1;
  2801             advanceBy(0);
  2802         }
  2803 
  2804         public String getFrameAsString() {
  2805             return (nextFrameIndex == 0)
  2806                 ? StackMapTableData.toString("INITIAL", 0, null, null)
  2807                 : stackMapTable[nextFrameIndex - 1].toString();
  2808         }
  2809 
  2810         public int getFrameIndex() {
  2811             return nextFrameIndex;
  2812         }
  2813 
  2814         public TypeArray getFrameStack() {
  2815             return stackTypes;
  2816         }
  2817 
  2818         public TypeArray getFrameLocals() {
  2819             return localTypes;
  2820         }
  2821 
  2822         public TypeArray getArguments() {
  2823             return argTypes;
  2824         }
  2825 
  2826         public void advanceBy(final int numByteCodes) {
  2827             if (numByteCodes < 0) {
  2828                 throw new IllegalStateException("Forward only iterator");
  2829             }
  2830 
  2831             byteCodeOffset += numByteCodes;
  2832             while ((nextFrameIndex < stackMapTable.length)
  2833                 && ((byteCodeOffset - lastFrameByteCodeOffset)
  2834                 >= (stackMapTable[nextFrameIndex].offsetDelta
  2835                 + 1))) {
  2836                 final StackMapTableData nextFrame = stackMapTable[nextFrameIndex];
  2837 
  2838                 lastFrameByteCodeOffset += nextFrame.offsetDelta + 1;
  2839                 nextFrame.applyTo(localTypes, stackTypes);
  2840 
  2841                 ++nextFrameIndex;
  2842             }
  2843         }
  2844 
  2845         public void advanceTo(final int nextByteCodeOffset) {
  2846             advanceBy(nextByteCodeOffset - byteCodeOffset);
  2847         }
  2848 
  2849         private static TypeArray getArgTypes(final String methodSignature,
  2850             final boolean isStaticMethod) {
  2851             final TypeArray argTypes = new TypeArray();
  2852 
  2853             if (!isStaticMethod) {
  2854                 argTypes.add(ITEM_Object);
  2855             }
  2856 
  2857             if (methodSignature.charAt(0) != '(') {
  2858                 throw new IllegalArgumentException("Invalid method signature");
  2859             }
  2860 
  2861             final int length = methodSignature.length();
  2862             boolean skipType = false;
  2863             int argType;
  2864             for (int i = 1; i < length; ++i) {
  2865                 switch (methodSignature.charAt(i)) {
  2866                     case 'B':
  2867                     case 'C':
  2868                     case 'S':
  2869                     case 'Z':
  2870                     case 'I':
  2871                         argType = ITEM_Integer;
  2872                         break;
  2873                     case 'J':
  2874                         argType = ITEM_Long;
  2875                         break;
  2876                     case 'F':
  2877                         argType = ITEM_Float;
  2878                         break;
  2879                     case 'D':
  2880                         argType = ITEM_Double;
  2881                         break;
  2882                     case 'L': {
  2883                         i = methodSignature.indexOf(';', i + 1);
  2884                         if (i == -1) {
  2885                             throw new IllegalArgumentException(
  2886                                 "Invalid method signature");
  2887                         }
  2888                         argType = ITEM_Object;
  2889                         break;
  2890                     }
  2891                     case ')':
  2892                         // not interested in the return value type
  2893                         return argTypes;
  2894                     case '[':
  2895                         if (!skipType) {
  2896                             argTypes.add(ITEM_Object);
  2897                             skipType = true;
  2898                         }
  2899                         continue;
  2900 
  2901                     default:
  2902                         throw new IllegalArgumentException(
  2903                             "Invalid method signature");
  2904                 }
  2905 
  2906                 if (!skipType) {
  2907                     argTypes.add(argType);
  2908                 } else {
  2909                     skipType = false;
  2910                 }
  2911             }
  2912 
  2913             return argTypes;
  2914         }
  2915     }
  2916     /* represents one entry of StackMapTable attribute
  2917      */
  2918 
  2919     private static abstract class StackMapTableData {
  2920 
  2921         final int frameType;
  2922         int offsetDelta;
  2923 
  2924         StackMapTableData(int frameType) {
  2925             this.frameType = frameType;
  2926         }
  2927 
  2928         abstract void applyTo(TypeArray localTypes, TypeArray stackTypes);
  2929 
  2930         protected static String toString(
  2931             final String frameType,
  2932             final int offset,
  2933             final int[] localTypes,
  2934             final int[] stackTypes) {
  2935             final StringBuilder sb = new StringBuilder(frameType);
  2936 
  2937             sb.append("(off: +").append(offset);
  2938             if (localTypes != null) {
  2939                 sb.append(", locals: ");
  2940                 appendTypes(sb, localTypes);
  2941             }
  2942             if (stackTypes != null) {
  2943                 sb.append(", stack: ");
  2944                 appendTypes(sb, stackTypes);
  2945             }
  2946             sb.append(')');
  2947 
  2948             return sb.toString();
  2949         }
  2950 
  2951         private static void appendTypes(final StringBuilder sb, final int[] types) {
  2952             sb.append('[');
  2953             if (types.length > 0) {
  2954                 sb.append(TypeArray.typeString(types[0]));
  2955                 for (int i = 1; i < types.length; ++i) {
  2956                     sb.append(", ");
  2957                     sb.append(TypeArray.typeString(types[i]));
  2958                 }
  2959             }
  2960             sb.append(']');
  2961         }
  2962 
  2963         private static class SameFrame extends StackMapTableData {
  2964 
  2965             SameFrame(int frameType, int offsetDelta) {
  2966                 super(frameType);
  2967                 this.offsetDelta = offsetDelta;
  2968             }
  2969 
  2970             @Override
  2971             void applyTo(TypeArray localTypes, TypeArray stackTypes) {
  2972                 stackTypes.clear();
  2973             }
  2974 
  2975             @Override
  2976             public String toString() {
  2977                 return toString("SAME" + ((frameType == SAME_FRAME_EXTENDED)
  2978                     ? "_FRAME_EXTENDED" : ""),
  2979                     offsetDelta,
  2980                     null, null);
  2981             }
  2982         }
  2983 
  2984         private static class SameLocals1StackItem extends StackMapTableData {
  2985 
  2986             final int[] stack;
  2987 
  2988             SameLocals1StackItem(int frameType, int offsetDelta, int[] stack) {
  2989                 super(frameType);
  2990                 this.offsetDelta = offsetDelta;
  2991                 this.stack = stack;
  2992             }
  2993 
  2994             @Override
  2995             void applyTo(TypeArray localTypes, TypeArray stackTypes) {
  2996                 stackTypes.setAll(stack);
  2997             }
  2998 
  2999             @Override
  3000             public String toString() {
  3001                 return toString(
  3002                     "SAME_LOCALS_1_STACK_ITEM"
  3003                     + ((frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED)
  3004                     ? "_EXTENDED" : ""),
  3005                     offsetDelta,
  3006                     null, stack);
  3007             }
  3008         }
  3009 
  3010         private static class ChopFrame extends StackMapTableData {
  3011 
  3012             ChopFrame(int frameType, int offsetDelta) {
  3013                 super(frameType);
  3014                 this.offsetDelta = offsetDelta;
  3015             }
  3016 
  3017             @Override
  3018             void applyTo(TypeArray localTypes, TypeArray stackTypes) {
  3019                 localTypes.setSize(localTypes.getSize()
  3020                     - (SAME_FRAME_EXTENDED - frameType));
  3021                 stackTypes.clear();
  3022             }
  3023 
  3024             @Override
  3025             public String toString() {
  3026                 return toString("CHOP", offsetDelta, null, null);
  3027             }
  3028         }
  3029 
  3030         private static class AppendFrame extends StackMapTableData {
  3031 
  3032             final int[] locals;
  3033 
  3034             AppendFrame(int frameType, int offsetDelta, int[] locals) {
  3035                 super(frameType);
  3036                 this.offsetDelta = offsetDelta;
  3037                 this.locals = locals;
  3038             }
  3039 
  3040             @Override
  3041             void applyTo(TypeArray localTypes, TypeArray stackTypes) {
  3042                 localTypes.addAll(locals);
  3043                 stackTypes.clear();
  3044             }
  3045 
  3046             @Override
  3047             public String toString() {
  3048                 return toString("APPEND", offsetDelta, locals, null);
  3049             }
  3050         }
  3051 
  3052         private static class FullFrame extends StackMapTableData {
  3053 
  3054             final int[] locals;
  3055             final int[] stack;
  3056 
  3057             FullFrame(int offsetDelta, int[] locals, int[] stack) {
  3058                 super(FULL_FRAME);
  3059                 this.offsetDelta = offsetDelta;
  3060                 this.locals = locals;
  3061                 this.stack = stack;
  3062             }
  3063 
  3064             @Override
  3065             void applyTo(TypeArray localTypes, TypeArray stackTypes) {
  3066                 localTypes.setAll(locals);
  3067                 stackTypes.setAll(stack);
  3068             }
  3069 
  3070             @Override
  3071             public String toString() {
  3072                 return toString("FULL", offsetDelta, locals, stack);
  3073             }
  3074         }
  3075 
  3076         static StackMapTableData getInstance(DataInputStream in, MethodData method)
  3077             throws IOException {
  3078             int frameType = in.readUnsignedByte();
  3079 
  3080             if (frameType < SAME_FRAME_BOUND) {
  3081                 // same_frame
  3082                 return new SameFrame(frameType, frameType);
  3083             } else if (SAME_FRAME_BOUND <= frameType && frameType < SAME_LOCALS_1_STACK_ITEM_BOUND) {
  3084                 // same_locals_1_stack_item_frame
  3085                 // read additional single stack element
  3086                 return new SameLocals1StackItem(frameType,
  3087                     (frameType - SAME_FRAME_BOUND),
  3088                     StackMapData.readTypeArray(in, 1, method));
  3089             } else if (frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
  3090                 // same_locals_1_stack_item_extended
  3091                 return new SameLocals1StackItem(frameType,
  3092                     in.readUnsignedShort(),
  3093                     StackMapData.readTypeArray(in, 1, method));
  3094             } else if (SAME_LOCALS_1_STACK_ITEM_EXTENDED < frameType && frameType < SAME_FRAME_EXTENDED) {
  3095                 // chop_frame or same_frame_extended
  3096                 return new ChopFrame(frameType, in.readUnsignedShort());
  3097             } else if (frameType == SAME_FRAME_EXTENDED) {
  3098                 // chop_frame or same_frame_extended
  3099                 return new SameFrame(frameType, in.readUnsignedShort());
  3100             } else if (SAME_FRAME_EXTENDED < frameType && frameType < FULL_FRAME) {
  3101                 // append_frame
  3102                 return new AppendFrame(frameType, in.readUnsignedShort(),
  3103                     StackMapData.readTypeArray(in, frameType - SAME_FRAME_EXTENDED, method));
  3104             } else if (frameType == FULL_FRAME) {
  3105                 // full_frame
  3106                 int offsetDelta = in.readUnsignedShort();
  3107                 int locals_size = in.readUnsignedShort();
  3108                 int[] locals = StackMapData.readTypeArray(in, locals_size, method);
  3109                 int stack_size = in.readUnsignedShort();
  3110                 int[] stack = StackMapData.readTypeArray(in, stack_size, method);
  3111                 return new FullFrame(offsetDelta, locals, stack);
  3112             } else {
  3113                 throw new ClassFormatError("unrecognized frame_type in StackMapTable");
  3114             }
  3115         }
  3116     }
  3117 
  3118     /**
  3119      * Stores exception table data in code attribute.
  3120      *
  3121      * @author Sucheta Dambalkar (Adopted code from jdis)
  3122      */
  3123     static final class TrapData {
  3124 
  3125         public final short start_pc;
  3126         public final short end_pc;
  3127         public final short handler_pc;
  3128         public final short catch_cpx;
  3129         final int num;
  3130 
  3131         /**
  3132          * Read and store exception table data in code attribute.
  3133          */
  3134         TrapData(DataInputStream in, int num) throws IOException {
  3135             this.num = num;
  3136             start_pc = in.readShort();
  3137             end_pc = in.readShort();
  3138             handler_pc = in.readShort();
  3139             catch_cpx = in.readShort();
  3140         }
  3141 
  3142         /**
  3143          * returns recommended identifier
  3144          */
  3145         public String ident() {
  3146             return "t" + num;
  3147         }
  3148     }
  3149     /**
  3150      *
  3151      * @author Jaroslav Tulach <jtulach@netbeans.org>
  3152      */
  3153     static final class TrapDataIterator {
  3154 
  3155         private final Hashtable exStart = new Hashtable();
  3156         private final Hashtable exStop = new Hashtable();
  3157         private TrapData[] current = new TrapData[10];
  3158         private int currentCount;
  3159 
  3160         TrapDataIterator(Vector exceptionTable) {
  3161             for (int i = 0; i < exceptionTable.size(); i++) {
  3162                 final TrapData td = (TrapData) exceptionTable.elementAt(i);
  3163                 put(exStart, td.start_pc, td);
  3164                 put(exStop, td.end_pc, td);
  3165             }
  3166         }
  3167 
  3168         private static void put(Hashtable h, short key, TrapData td) {
  3169             Short s = Short.valueOf((short) key);
  3170             Vector v = (Vector) h.get(s);
  3171             if (v == null) {
  3172                 v = new Vector(1);
  3173                 h.put(s, v);
  3174             }
  3175             v.add(td);
  3176         }
  3177 
  3178         private boolean processAll(Hashtable h, Short key, boolean add) {
  3179             boolean change = false;
  3180             Vector v = (Vector) h.get(key);
  3181             if (v != null) {
  3182                 int s = v.size();
  3183                 for (int i = 0; i < s; i++) {
  3184                     TrapData td = (TrapData) v.elementAt(i);
  3185                     if (add) {
  3186                         add(td);
  3187                         change = true;
  3188                     } else {
  3189                         remove(td);
  3190                         change = true;
  3191                     }
  3192                 }
  3193             }
  3194             return change;
  3195         }
  3196 
  3197         public boolean advanceTo(int i) {
  3198             Short s = Short.valueOf((short) i);
  3199             boolean ch1 = processAll(exStart, s, true);
  3200             boolean ch2 = processAll(exStop, s, false);
  3201             return ch1 || ch2;
  3202         }
  3203 
  3204         public boolean useTry() {
  3205             return currentCount > 0;
  3206         }
  3207 
  3208         public TrapData[] current() {
  3209             TrapData[] copy = new TrapData[currentCount];
  3210             for (int i = 0; i < currentCount; i++) {
  3211                 copy[i] = current[i];
  3212             }
  3213             return copy;
  3214         }
  3215 
  3216         private void add(TrapData e) {
  3217             if (currentCount == current.length) {
  3218                 TrapData[] data = new TrapData[currentCount * 2];
  3219                 for (int i = 0; i < currentCount; i++) {
  3220                     data[i] = current[i];
  3221                 }
  3222                 current = data;
  3223             }
  3224             current[currentCount++] = e;
  3225         }
  3226 
  3227         private void remove(TrapData e) {
  3228             if (currentCount == 0) {
  3229                 return;
  3230             }
  3231             int from = 0;
  3232             while (from < currentCount) {
  3233                 if (e == current[from++]) {
  3234                     break;
  3235                 }
  3236             }
  3237             while (from < currentCount) {
  3238                 current[from - 1] = current[from];
  3239                 current[from] = null;
  3240                 from++;
  3241             }
  3242             currentCount--;
  3243         }
  3244     }
  3245     static final class TypeArray {
  3246 
  3247         private static final int CAPACITY_INCREMENT = 16;
  3248         private int[] types;
  3249         private int size;
  3250 
  3251         public TypeArray() {
  3252         }
  3253 
  3254         public TypeArray(final TypeArray initialTypes) {
  3255             setAll(initialTypes);
  3256         }
  3257 
  3258         public void add(final int newType) {
  3259             ensureCapacity(size + 1);
  3260             types[size++] = newType;
  3261         }
  3262 
  3263         public void addAll(final TypeArray newTypes) {
  3264             addAll(newTypes.types, 0, newTypes.size);
  3265         }
  3266 
  3267         public void addAll(final int[] newTypes) {
  3268             addAll(newTypes, 0, newTypes.length);
  3269         }
  3270 
  3271         public void addAll(final int[] newTypes,
  3272             final int offset,
  3273             final int count) {
  3274             if (count > 0) {
  3275                 ensureCapacity(size + count);
  3276                 arraycopy(newTypes, offset, types, size, count);
  3277                 size += count;
  3278             }
  3279         }
  3280 
  3281         public void set(final int index, final int newType) {
  3282             types[index] = newType;
  3283         }
  3284 
  3285         public void setAll(final TypeArray newTypes) {
  3286             setAll(newTypes.types, 0, newTypes.size);
  3287         }
  3288 
  3289         public void setAll(final int[] newTypes) {
  3290             setAll(newTypes, 0, newTypes.length);
  3291         }
  3292 
  3293         public void setAll(final int[] newTypes,
  3294             final int offset,
  3295             final int count) {
  3296             if (count > 0) {
  3297                 ensureCapacity(count);
  3298                 arraycopy(newTypes, offset, types, 0, count);
  3299                 size = count;
  3300             } else {
  3301                 clear();
  3302             }
  3303         }
  3304 
  3305         public void setSize(final int newSize) {
  3306             if (size != newSize) {
  3307                 ensureCapacity(newSize);
  3308 
  3309                 for (int i = size; i < newSize; ++i) {
  3310                     types[i] = 0;
  3311                 }
  3312                 size = newSize;
  3313             }
  3314         }
  3315 
  3316         public void clear() {
  3317             size = 0;
  3318         }
  3319 
  3320         public int getSize() {
  3321             return size;
  3322         }
  3323 
  3324         public int get(final int index) {
  3325             return types[index];
  3326         }
  3327 
  3328         public static String typeString(final int type) {
  3329             switch (type & 0xff) {
  3330                 case ITEM_Bogus:
  3331                     return "_top_";
  3332                 case ITEM_Integer:
  3333                     return "_int_";
  3334                 case ITEM_Float:
  3335                     return "_float_";
  3336                 case ITEM_Double:
  3337                     return "_double_";
  3338                 case ITEM_Long:
  3339                     return "_long_";
  3340                 case ITEM_Null:
  3341                     return "_null_";
  3342                 case ITEM_InitObject: // UninitializedThis
  3343                     return "_init_";
  3344                 case ITEM_Object:
  3345                     return "_object_";
  3346                 case ITEM_NewObject: // Uninitialized
  3347                     return "_new_";
  3348                 default:
  3349                     throw new IllegalArgumentException("Unknown type");
  3350             }
  3351         }
  3352 
  3353         @Override
  3354         public String toString() {
  3355             final StringBuilder sb = new StringBuilder("[");
  3356             if (size > 0) {
  3357                 sb.append(typeString(types[0]));
  3358                 for (int i = 1; i < size; ++i) {
  3359                     sb.append(", ");
  3360                     sb.append(typeString(types[i]));
  3361                 }
  3362             }
  3363 
  3364             return sb.append(']').toString();
  3365         }
  3366 
  3367         private void ensureCapacity(final int minCapacity) {
  3368             if ((minCapacity == 0)
  3369                 || (types != null) && (minCapacity <= types.length)) {
  3370                 return;
  3371             }
  3372 
  3373             final int newCapacity =
  3374                 ((minCapacity + CAPACITY_INCREMENT - 1) / CAPACITY_INCREMENT)
  3375                 * CAPACITY_INCREMENT;
  3376             final int[] newTypes = new int[newCapacity];
  3377 
  3378             if (size > 0) {
  3379                 arraycopy(types, 0, newTypes, 0, size);
  3380             }
  3381 
  3382             types = newTypes;
  3383         }
  3384 
  3385         // no System.arraycopy
  3386         private void arraycopy(final int[] src, final int srcPos,
  3387             final int[] dest, final int destPos,
  3388             final int length) {
  3389             for (int i = 0; i < length; ++i) {
  3390                 dest[destPos + i] = src[srcPos + i];
  3391             }
  3392         }
  3393     }
  3394     /**
  3395      * A JavaScript ready replacement for java.util.Vector
  3396      *
  3397      * @author Jaroslav Tulach <jtulach@netbeans.org>
  3398      */
  3399     @JavaScriptPrototype(prototype = "new Array")
  3400     private static final class Vector {
  3401 
  3402         private Object[] arr;
  3403 
  3404         Vector() {
  3405         }
  3406 
  3407         Vector(int i) {
  3408         }
  3409 
  3410         void add(Object objectType) {
  3411             addElement(objectType);
  3412         }
  3413 
  3414         @JavaScriptBody(args = {"obj"}, body =
  3415             "this.push(obj);")
  3416         void addElement(Object obj) {
  3417             final int s = size();
  3418             setSize(s + 1);
  3419             setElementAt(obj, s);
  3420         }
  3421 
  3422         @JavaScriptBody(args = {}, body =
  3423             "return this.length;")
  3424         int size() {
  3425             return arr == null ? 0 : arr.length;
  3426         }
  3427 
  3428         @JavaScriptBody(args = {"newArr"}, body =
  3429             "for (var i = 0; i < this.length; i++) {\n"
  3430             + "  newArr[i] = this[i];\n"
  3431             + "}\n")
  3432         void copyInto(Object[] newArr) {
  3433             if (arr == null) {
  3434                 return;
  3435             }
  3436             int min = Math.min(newArr.length, arr.length);
  3437             for (int i = 0; i < min; i++) {
  3438                 newArr[i] = arr[i];
  3439             }
  3440         }
  3441 
  3442         @JavaScriptBody(args = {"index"}, body =
  3443             "return this[index];")
  3444         Object elementAt(int index) {
  3445             return arr[index];
  3446         }
  3447 
  3448         private void setSize(int len) {
  3449             Object[] newArr = new Object[len];
  3450             copyInto(newArr);
  3451             arr = newArr;
  3452         }
  3453 
  3454         @JavaScriptBody(args = {"val", "index"}, body =
  3455             "this[index] = val;")
  3456         void setElementAt(Object val, int index) {
  3457             arr[index] = val;
  3458         }
  3459     }
  3460     
  3461 }