javap/src/main/java/sun/tools/javap/ClassData.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 10 Nov 2012 19:01:28 +0100
branchjavap
changeset 149 32653a09f0db
parent 144 b06660b614db
child 151 40f95fe90cdc
permissions -rw-r--r--
Compiling javap against the emul package. Still need impl for our copy of Hashtable and Vector
jtulach@144
     1
/*
jtulach@144
     2
 * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
jtulach@144
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jtulach@144
     4
 *
jtulach@144
     5
 * This code is free software; you can redistribute it and/or modify it
jtulach@144
     6
 * under the terms of the GNU General Public License version 2 only, as
jtulach@144
     7
 * published by the Free Software Foundation.  Oracle designates this
jtulach@144
     8
 * particular file as subject to the "Classpath" exception as provided
jtulach@144
     9
 * by Oracle in the LICENSE file that accompanied this code.
jtulach@144
    10
 *
jtulach@144
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
jtulach@144
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jtulach@144
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
jtulach@144
    14
 * version 2 for more details (a copy is included in the LICENSE file that
jtulach@144
    15
 * accompanied this code).
jtulach@144
    16
 *
jtulach@144
    17
 * You should have received a copy of the GNU General Public License version
jtulach@144
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
jtulach@144
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jtulach@144
    20
 *
jtulach@144
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jtulach@144
    22
 * or visit www.oracle.com if you need additional information or have any
jtulach@144
    23
 * questions.
jtulach@144
    24
 */
jtulach@144
    25
jtulach@144
    26
jtulach@144
    27
package sun.tools.javap;
jtulach@144
    28
jtulach@144
    29
import java.util.*;
jtulach@144
    30
import java.io.*;
jtulach@144
    31
jtulach@144
    32
/**
jtulach@144
    33
 * Central data repository of the Java Disassembler.
jtulach@144
    34
 * Stores all the information in java class file.
jtulach@144
    35
 *
jtulach@144
    36
 * @author  Sucheta Dambalkar (Adopted code from jdis)
jtulach@144
    37
 */
jtulach@144
    38
public class ClassData implements RuntimeConstants {
jtulach@144
    39
jtulach@144
    40
    private int magic;
jtulach@144
    41
    private int minor_version;
jtulach@144
    42
    private int major_version;
jtulach@144
    43
    private int cpool_count;
jtulach@144
    44
    private Object cpool[];
jtulach@144
    45
    private int access;
jtulach@144
    46
    private int this_class = 0;;
jtulach@144
    47
    private int super_class;
jtulach@144
    48
    private int interfaces_count;
jtulach@144
    49
    private int[] interfaces = new int[0];;
jtulach@144
    50
    private int fields_count;
jtulach@144
    51
    private FieldData[] fields;
jtulach@144
    52
    private int methods_count;
jtulach@144
    53
    private MethodData[] methods;
jtulach@144
    54
    private InnerClassData[] innerClasses;
jtulach@144
    55
    private int attributes_count;
jtulach@144
    56
    private AttrData[] attrs;
jtulach@144
    57
    private String classname;
jtulach@144
    58
    private String superclassname;
jtulach@144
    59
    private int source_cpx=0;
jtulach@144
    60
    private byte tags[];
jtulach@144
    61
    private Hashtable indexHashAscii = new Hashtable();
jtulach@144
    62
    private String pkgPrefix="";
jtulach@144
    63
    private int pkgPrefixLen=0;
jtulach@144
    64
jtulach@144
    65
    /**
jtulach@144
    66
     * Read classfile to disassemble.
jtulach@144
    67
     */
jaroslav@149
    68
    public ClassData(InputStream infile) throws IOException {
jaroslav@149
    69
        this.read(new DataInputStream(infile));
jtulach@144
    70
    }
jtulach@144
    71
jtulach@144
    72
    /**
jtulach@144
    73
     * Reads and stores class file information.
jtulach@144
    74
     */
jtulach@144
    75
    public void read(DataInputStream in) throws IOException {
jtulach@144
    76
        // Read the header
jtulach@144
    77
        magic = in.readInt();
jtulach@144
    78
        if (magic != JAVA_MAGIC) {
jtulach@144
    79
            throw new ClassFormatError("wrong magic: " +
jtulach@144
    80
                                       toHex(magic) + ", expected " +
jtulach@144
    81
                                       toHex(JAVA_MAGIC));
jtulach@144
    82
        }
jtulach@144
    83
        minor_version = in.readShort();
jtulach@144
    84
        major_version = in.readShort();
jtulach@144
    85
        if (major_version != JAVA_VERSION) {
jtulach@144
    86
        }
jtulach@144
    87
jtulach@144
    88
        // Read the constant pool
jtulach@144
    89
        readCP(in);
jtulach@144
    90
        access = in.readUnsignedShort();
jtulach@144
    91
        this_class = in.readUnsignedShort();
jtulach@144
    92
        super_class = in.readUnsignedShort();
jtulach@144
    93
jtulach@144
    94
        //Read interfaces.
jtulach@144
    95
        interfaces_count = in.readUnsignedShort();
jtulach@144
    96
        if(interfaces_count > 0){
jtulach@144
    97
            interfaces = new int[interfaces_count];
jtulach@144
    98
        }
jtulach@144
    99
        for (int i = 0; i < interfaces_count; i++) {
jtulach@144
   100
            interfaces[i]=in.readShort();
jtulach@144
   101
        }
jtulach@144
   102
jtulach@144
   103
        // Read the fields
jtulach@144
   104
        readFields(in);
jtulach@144
   105
jtulach@144
   106
        // Read the methods
jtulach@144
   107
        readMethods(in);
jtulach@144
   108
jtulach@144
   109
        // Read the attributes
jtulach@144
   110
        attributes_count = in.readUnsignedShort();
jtulach@144
   111
        attrs=new AttrData[attributes_count];
jtulach@144
   112
        for (int k = 0; k < attributes_count; k++) {
jtulach@144
   113
            int name_cpx=in.readUnsignedShort();
jtulach@144
   114
            if (getTag(name_cpx)==CONSTANT_UTF8
jtulach@144
   115
                && getString(name_cpx).equals("SourceFile")
jtulach@144
   116
                ){      if (in.readInt()!=2)
jtulach@144
   117
                    throw new ClassFormatError("invalid attr length");
jtulach@144
   118
                source_cpx=in.readUnsignedShort();
jtulach@144
   119
                AttrData attr=new AttrData(this);
jtulach@144
   120
                attr.read(name_cpx);
jtulach@144
   121
                attrs[k]=attr;
jtulach@144
   122
jtulach@144
   123
            } else if (getTag(name_cpx)==CONSTANT_UTF8
jtulach@144
   124
                       && getString(name_cpx).equals("InnerClasses")
jtulach@144
   125
                       ){       int length=in.readInt();
jtulach@144
   126
                       int num=in.readUnsignedShort();
jtulach@144
   127
                       if (2+num*8 != length)
jtulach@144
   128
                           throw new ClassFormatError("invalid attr length");
jtulach@144
   129
                       innerClasses=new InnerClassData[num];
jtulach@144
   130
                       for (int j = 0; j < num; j++) {
jtulach@144
   131
                           InnerClassData innerClass=new InnerClassData(this);
jtulach@144
   132
                           innerClass.read(in);
jtulach@144
   133
                           innerClasses[j]=innerClass;
jtulach@144
   134
                       }
jtulach@144
   135
                       AttrData attr=new AttrData(this);
jtulach@144
   136
                       attr.read(name_cpx);
jtulach@144
   137
                       attrs[k]=attr;
jtulach@144
   138
            } else {
jtulach@144
   139
                AttrData attr=new AttrData(this);
jtulach@144
   140
                attr.read(name_cpx, in);
jtulach@144
   141
                attrs[k]=attr;
jtulach@144
   142
            }
jtulach@144
   143
        }
jtulach@144
   144
        in.close();
jtulach@144
   145
    } // end ClassData.read()
jtulach@144
   146
jtulach@144
   147
    /**
jtulach@144
   148
     * Reads and stores constant pool info.
jtulach@144
   149
     */
jtulach@144
   150
    void readCP(DataInputStream in) throws IOException {
jtulach@144
   151
        cpool_count = in.readUnsignedShort();
jtulach@144
   152
        tags = new byte[cpool_count];
jtulach@144
   153
        cpool = new Object[cpool_count];
jtulach@144
   154
        for (int i = 1; i < cpool_count; i++) {
jtulach@144
   155
            byte tag = in.readByte();
jtulach@144
   156
jtulach@144
   157
            switch(tags[i] = tag) {
jtulach@144
   158
            case CONSTANT_UTF8:
jtulach@144
   159
                String str=in.readUTF();
jtulach@144
   160
                indexHashAscii.put(cpool[i] = str, new Integer(i));
jtulach@144
   161
                break;
jtulach@144
   162
            case CONSTANT_INTEGER:
jtulach@144
   163
                cpool[i] = new Integer(in.readInt());
jtulach@144
   164
                break;
jtulach@144
   165
            case CONSTANT_FLOAT:
jtulach@144
   166
                cpool[i] = new Float(in.readFloat());
jtulach@144
   167
                break;
jtulach@144
   168
            case CONSTANT_LONG:
jtulach@144
   169
                cpool[i++] = new Long(in.readLong());
jtulach@144
   170
                break;
jtulach@144
   171
            case CONSTANT_DOUBLE:
jtulach@144
   172
                cpool[i++] = new Double(in.readDouble());
jtulach@144
   173
                break;
jtulach@144
   174
            case CONSTANT_CLASS:
jtulach@144
   175
            case CONSTANT_STRING:
jtulach@144
   176
                cpool[i] = new CPX(in.readUnsignedShort());
jtulach@144
   177
                break;
jtulach@144
   178
jtulach@144
   179
            case CONSTANT_FIELD:
jtulach@144
   180
            case CONSTANT_METHOD:
jtulach@144
   181
            case CONSTANT_INTERFACEMETHOD:
jtulach@144
   182
            case CONSTANT_NAMEANDTYPE:
jtulach@144
   183
                cpool[i] = new CPX2(in.readUnsignedShort(), in.readUnsignedShort());
jtulach@144
   184
                break;
jtulach@144
   185
jtulach@144
   186
            case 0:
jtulach@144
   187
            default:
jtulach@144
   188
                throw new ClassFormatError("invalid constant type: " + (int)tags[i]);
jtulach@144
   189
            }
jtulach@144
   190
        }
jtulach@144
   191
    }
jtulach@144
   192
jtulach@144
   193
    /**
jtulach@144
   194
     * Reads and strores field info.
jtulach@144
   195
     */
jtulach@144
   196
    protected void readFields(DataInputStream in) throws IOException {
jtulach@144
   197
        int fields_count = in.readUnsignedShort();
jtulach@144
   198
        fields=new FieldData[fields_count];
jtulach@144
   199
        for (int k = 0; k < fields_count; k++) {
jtulach@144
   200
            FieldData field=new FieldData(this);
jtulach@144
   201
            field.read(in);
jtulach@144
   202
            fields[k]=field;
jtulach@144
   203
        }
jtulach@144
   204
    }
jtulach@144
   205
jtulach@144
   206
    /**
jtulach@144
   207
     * Reads and strores Method info.
jtulach@144
   208
     */
jtulach@144
   209
    protected void readMethods(DataInputStream in) throws IOException {
jtulach@144
   210
        int methods_count = in.readUnsignedShort();
jtulach@144
   211
        methods=new MethodData[methods_count];
jtulach@144
   212
        for (int k = 0; k < methods_count ; k++) {
jtulach@144
   213
            MethodData method=new MethodData(this);
jtulach@144
   214
            method.read(in);
jtulach@144
   215
            methods[k]=method;
jtulach@144
   216
        }
jtulach@144
   217
    }
jtulach@144
   218
jtulach@144
   219
    /**
jtulach@144
   220
     * get a string
jtulach@144
   221
     */
jtulach@144
   222
    public String getString(int n) {
jtulach@144
   223
        return (n == 0) ? null : (String)cpool[n];
jtulach@144
   224
    }
jtulach@144
   225
jtulach@144
   226
    /**
jtulach@144
   227
     * get the type of constant given an index
jtulach@144
   228
     */
jtulach@144
   229
    public byte getTag(int n) {
jtulach@144
   230
        try{
jtulach@144
   231
            return tags[n];
jtulach@144
   232
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   233
            return (byte)100;
jtulach@144
   234
        }
jtulach@144
   235
    }
jtulach@144
   236
jtulach@144
   237
    static final String hexString="0123456789ABCDEF";
jtulach@144
   238
jtulach@144
   239
    public static char hexTable[]=hexString.toCharArray();
jtulach@144
   240
jtulach@144
   241
    static String toHex(long val, int width) {
jtulach@144
   242
        StringBuffer s = new StringBuffer();
jtulach@144
   243
        for (int i=width-1; i>=0; i--)
jtulach@144
   244
            s.append(hexTable[((int)(val>>(4*i)))&0xF]);
jtulach@144
   245
        return "0x"+s.toString();
jtulach@144
   246
    }
jtulach@144
   247
jtulach@144
   248
    static String toHex(long val) {
jtulach@144
   249
        int width;
jtulach@144
   250
        for (width=16; width>0; width--) {
jtulach@144
   251
            if ((val>>(width-1)*4)!=0) break;
jtulach@144
   252
        }
jtulach@144
   253
        return toHex(val, width);
jtulach@144
   254
    }
jtulach@144
   255
jtulach@144
   256
    static String toHex(int val) {
jtulach@144
   257
        int width;
jtulach@144
   258
        for (width=8; width>0; width--) {
jtulach@144
   259
            if ((val>>(width-1)*4)!=0) break;
jtulach@144
   260
        }
jtulach@144
   261
        return toHex(val, width);
jtulach@144
   262
    }
jtulach@144
   263
jtulach@144
   264
    /**
jtulach@144
   265
     * Returns the name of this class.
jtulach@144
   266
     */
jtulach@144
   267
    public String getClassName() {
jtulach@144
   268
        String res=null;
jtulach@144
   269
        if (this_class==0) {
jtulach@144
   270
            return res;
jtulach@144
   271
        }
jtulach@144
   272
        int tcpx;
jtulach@144
   273
        try {
jtulach@144
   274
            if (tags[this_class]!=CONSTANT_CLASS) {
jtulach@144
   275
                return res; //"<CP["+cpx+"] is not a Class> ";
jtulach@144
   276
            }
jtulach@144
   277
            tcpx=((CPX)cpool[this_class]).cpx;
jtulach@144
   278
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   279
            return res; // "#"+cpx+"// invalid constant pool index";
jtulach@144
   280
        } catch (Throwable e) {
jtulach@144
   281
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   282
        }
jtulach@144
   283
jtulach@144
   284
        try {
jtulach@144
   285
            return (String)(cpool[tcpx]);
jtulach@144
   286
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   287
            return  res; // "class #"+scpx+"// invalid constant pool index";
jtulach@144
   288
        } catch (ClassCastException e) {
jtulach@144
   289
            return  res; // "class #"+scpx+"// invalid constant pool reference";
jtulach@144
   290
        } catch (Throwable e) {
jtulach@144
   291
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   292
        }
jtulach@144
   293
jtulach@144
   294
    }
jtulach@144
   295
jtulach@144
   296
    /**
jtulach@144
   297
     * Returns the name of class at perticular index.
jtulach@144
   298
     */
jtulach@144
   299
    public String getClassName(int cpx) {
jtulach@144
   300
        String res="#"+cpx;
jtulach@144
   301
        if (cpx==0) {
jtulach@144
   302
            return res;
jtulach@144
   303
        }
jtulach@144
   304
        int scpx;
jtulach@144
   305
        try {
jtulach@144
   306
            if (tags[cpx]!=CONSTANT_CLASS) {
jtulach@144
   307
                return res; //"<CP["+cpx+"] is not a Class> ";
jtulach@144
   308
            }
jtulach@144
   309
            scpx=((CPX)cpool[cpx]).cpx;
jtulach@144
   310
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   311
            return res; // "#"+cpx+"// invalid constant pool index";
jtulach@144
   312
        } catch (Throwable e) {
jtulach@144
   313
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   314
        }
jtulach@144
   315
        res="#"+scpx;
jtulach@144
   316
        try {
jtulach@144
   317
            return (String)(cpool[scpx]);
jtulach@144
   318
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   319
            return  res; // "class #"+scpx+"// invalid constant pool index";
jtulach@144
   320
        } catch (ClassCastException e) {
jtulach@144
   321
            return  res; // "class #"+scpx+"// invalid constant pool reference";
jtulach@144
   322
        } catch (Throwable e) {
jtulach@144
   323
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   324
        }
jtulach@144
   325
    }
jtulach@144
   326
jtulach@144
   327
    /**
jtulach@144
   328
     * Returns true if it is a class
jtulach@144
   329
     */
jtulach@144
   330
    public boolean isClass() {
jtulach@144
   331
        if((access & ACC_INTERFACE) == 0) return true;
jtulach@144
   332
        return false;
jtulach@144
   333
    }
jtulach@144
   334
jtulach@144
   335
    /**
jtulach@144
   336
     * Returns true if it is a interface.
jtulach@144
   337
     */
jtulach@144
   338
    public boolean isInterface(){
jtulach@144
   339
        if((access & ACC_INTERFACE) != 0) return true;
jtulach@144
   340
        return false;
jtulach@144
   341
    }
jtulach@144
   342
jtulach@144
   343
    /**
jtulach@144
   344
     * Returns true if this member is public, false otherwise.
jtulach@144
   345
     */
jtulach@144
   346
    public boolean isPublic(){
jtulach@144
   347
        return (access & ACC_PUBLIC) != 0;
jtulach@144
   348
    }
jtulach@144
   349
jtulach@144
   350
    /**
jtulach@144
   351
     * Returns the access of this class or interface.
jtulach@144
   352
     */
jtulach@144
   353
    public String[] getAccess(){
jtulach@144
   354
        Vector v = new Vector();
jtulach@144
   355
        if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
jtulach@144
   356
        if ((access & ACC_FINAL)    !=0) v.addElement("final");
jtulach@144
   357
        if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
jtulach@144
   358
        String[] accflags = new String[v.size()];
jtulach@144
   359
        v.copyInto(accflags);
jtulach@144
   360
        return accflags;
jtulach@144
   361
    }
jtulach@144
   362
jtulach@144
   363
    /**
jtulach@144
   364
     * Returns list of innerclasses.
jtulach@144
   365
     */
jtulach@144
   366
    public InnerClassData[] getInnerClasses(){
jtulach@144
   367
        return innerClasses;
jtulach@144
   368
    }
jtulach@144
   369
jtulach@144
   370
    /**
jtulach@144
   371
     * Returns list of attributes.
jtulach@144
   372
     */
jtulach@144
   373
    public AttrData[] getAttributes(){
jtulach@144
   374
        return attrs;
jtulach@144
   375
    }
jtulach@144
   376
jtulach@144
   377
    /**
jtulach@144
   378
     * Returns true if superbit is set.
jtulach@144
   379
     */
jtulach@144
   380
    public boolean isSuperSet(){
jtulach@144
   381
        if ((access & ACC_SUPER)   !=0) return true;
jtulach@144
   382
        return false;
jtulach@144
   383
    }
jtulach@144
   384
jtulach@144
   385
    /**
jtulach@144
   386
     * Returns super class name.
jtulach@144
   387
     */
jtulach@144
   388
    public String getSuperClassName(){
jtulach@144
   389
        String res=null;
jtulach@144
   390
        if (super_class==0) {
jtulach@144
   391
            return res;
jtulach@144
   392
        }
jtulach@144
   393
        int scpx;
jtulach@144
   394
        try {
jtulach@144
   395
            if (tags[super_class]!=CONSTANT_CLASS) {
jtulach@144
   396
                return res; //"<CP["+cpx+"] is not a Class> ";
jtulach@144
   397
            }
jtulach@144
   398
            scpx=((CPX)cpool[super_class]).cpx;
jtulach@144
   399
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   400
            return res; // "#"+cpx+"// invalid constant pool index";
jtulach@144
   401
        } catch (Throwable e) {
jtulach@144
   402
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   403
        }
jtulach@144
   404
jtulach@144
   405
        try {
jtulach@144
   406
            return (String)(cpool[scpx]);
jtulach@144
   407
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   408
            return  res; // "class #"+scpx+"// invalid constant pool index";
jtulach@144
   409
        } catch (ClassCastException e) {
jtulach@144
   410
            return  res; // "class #"+scpx+"// invalid constant pool reference";
jtulach@144
   411
        } catch (Throwable e) {
jtulach@144
   412
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   413
        }
jtulach@144
   414
    }
jtulach@144
   415
jtulach@144
   416
    /**
jtulach@144
   417
     * Returns list of super interfaces.
jtulach@144
   418
     */
jtulach@144
   419
    public String[] getSuperInterfaces(){
jtulach@144
   420
        String interfacenames[] = new String[interfaces.length];
jtulach@144
   421
        int interfacecpx = -1;
jtulach@144
   422
        for(int i = 0; i < interfaces.length; i++){
jtulach@144
   423
            interfacecpx=((CPX)cpool[interfaces[i]]).cpx;
jtulach@144
   424
            interfacenames[i] = (String)(cpool[interfacecpx]);
jtulach@144
   425
        }
jtulach@144
   426
        return interfacenames;
jtulach@144
   427
    }
jtulach@144
   428
jtulach@144
   429
    /**
jtulach@144
   430
     * Returns string at prticular constant pool index.
jtulach@144
   431
     */
jtulach@144
   432
    public String getStringValue(int cpoolx) {
jtulach@144
   433
        try {
jtulach@144
   434
            return ((String)cpool[cpoolx]);
jtulach@144
   435
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   436
            return "//invalid constant pool index:"+cpoolx;
jtulach@144
   437
        } catch (ClassCastException e) {
jtulach@144
   438
            return "//invalid constant pool ref:"+cpoolx;
jtulach@144
   439
        }
jtulach@144
   440
    }
jtulach@144
   441
jtulach@144
   442
    /**
jtulach@144
   443
     * Returns list of field info.
jtulach@144
   444
     */
jtulach@144
   445
    public  FieldData[] getFields(){
jtulach@144
   446
        return fields;
jtulach@144
   447
    }
jtulach@144
   448
jtulach@144
   449
    /**
jtulach@144
   450
     * Returns list of method info.
jtulach@144
   451
     */
jtulach@144
   452
    public  MethodData[] getMethods(){
jtulach@144
   453
        return methods;
jtulach@144
   454
    }
jtulach@144
   455
jtulach@144
   456
    /**
jtulach@144
   457
     * Returns constant pool entry at that index.
jtulach@144
   458
     */
jtulach@144
   459
    public CPX2 getCpoolEntry(int cpx){
jtulach@144
   460
        return ((CPX2)(cpool[cpx]));
jtulach@144
   461
    }
jtulach@144
   462
jtulach@144
   463
    public Object getCpoolEntryobj(int cpx){
jtulach@144
   464
        return (cpool[cpx]);
jtulach@144
   465
    }
jtulach@144
   466
jtulach@144
   467
    /**
jtulach@144
   468
     * Returns index of this class.
jtulach@144
   469
     */
jtulach@144
   470
    public int getthis_cpx(){
jtulach@144
   471
        return this_class;
jtulach@144
   472
    }
jtulach@144
   473
jtulach@144
   474
    public String TagString (int tag) {
jtulach@144
   475
        String res=Tables.tagName(tag);
jtulach@144
   476
        if (res==null)  return "BOGUS_TAG:"+tag;
jtulach@144
   477
        return res;
jtulach@144
   478
    }
jtulach@144
   479
jtulach@144
   480
    /**
jtulach@144
   481
     * Returns string at that index.
jtulach@144
   482
     */
jtulach@144
   483
    public String StringValue(int cpx) {
jtulach@144
   484
        if (cpx==0) return "#0";
jtulach@144
   485
        int tag;
jtulach@144
   486
        Object x;
jtulach@144
   487
        String suffix="";
jtulach@144
   488
        try {
jtulach@144
   489
            tag=tags[cpx];
jtulach@144
   490
            x=cpool[cpx];
jtulach@144
   491
        } catch (IndexOutOfBoundsException e) {
jtulach@144
   492
            return "<Incorrect CP index:"+cpx+">";
jtulach@144
   493
        }
jtulach@144
   494
jtulach@144
   495
        if (x==null) return "<NULL>";
jtulach@144
   496
        switch (tag) {
jtulach@144
   497
        case CONSTANT_UTF8: {
jtulach@144
   498
            StringBuffer sb=new StringBuffer();
jtulach@144
   499
            String s=(String)x;
jtulach@144
   500
            for (int k=0; k<s.length(); k++) {
jtulach@144
   501
                char c=s.charAt(k);
jtulach@144
   502
                switch (c) {
jtulach@144
   503
                case '\t': sb.append('\\').append('t'); break;
jtulach@144
   504
                case '\n': sb.append('\\').append('n'); break;
jtulach@144
   505
                case '\r': sb.append('\\').append('r'); break;
jtulach@144
   506
                case '\"': sb.append('\\').append('\"'); break;
jtulach@144
   507
                default: sb.append(c);
jtulach@144
   508
                }
jtulach@144
   509
            }
jtulach@144
   510
            return sb.toString();
jtulach@144
   511
        }
jtulach@144
   512
        case CONSTANT_DOUBLE: {
jtulach@144
   513
            Double d=(Double)x;
jtulach@144
   514
            String sd=d.toString();
jtulach@144
   515
            return sd+"d";
jtulach@144
   516
        }
jtulach@144
   517
        case CONSTANT_FLOAT: {
jtulach@144
   518
            Float f=(Float)x;
jtulach@144
   519
            String sf=(f).toString();
jtulach@144
   520
            return sf+"f";
jtulach@144
   521
        }
jtulach@144
   522
        case CONSTANT_LONG: {
jtulach@144
   523
            Long ln = (Long)x;
jtulach@144
   524
            return ln.toString()+'l';
jtulach@144
   525
        }
jtulach@144
   526
        case CONSTANT_INTEGER: {
jtulach@144
   527
            Integer in = (Integer)x;
jtulach@144
   528
            return in.toString();
jtulach@144
   529
        }
jtulach@144
   530
        case CONSTANT_CLASS:
jtulach@144
   531
            return javaName(getClassName(cpx));
jtulach@144
   532
        case CONSTANT_STRING:
jtulach@144
   533
            return StringValue(((CPX)x).cpx);
jtulach@144
   534
        case CONSTANT_FIELD:
jtulach@144
   535
        case CONSTANT_METHOD:
jtulach@144
   536
        case CONSTANT_INTERFACEMETHOD:
jtulach@144
   537
            //return getShortClassName(((CPX2)x).cpx1)+"."+StringValue(((CPX2)x).cpx2);
jtulach@144
   538
             return javaName(getClassName(((CPX2)x).cpx1))+"."+StringValue(((CPX2)x).cpx2);
jtulach@144
   539
jtulach@144
   540
        case CONSTANT_NAMEANDTYPE:
jtulach@144
   541
            return getName(((CPX2)x).cpx1)+":"+StringValue(((CPX2)x).cpx2);
jtulach@144
   542
        default:
jtulach@144
   543
            return "UnknownTag"; //TBD
jtulach@144
   544
        }
jtulach@144
   545
    }
jtulach@144
   546
jtulach@144
   547
    /**
jtulach@144
   548
     * Returns resolved java type name.
jtulach@144
   549
     */
jtulach@144
   550
    public String javaName(String name) {
jtulach@144
   551
        if( name==null) return "null";
jtulach@144
   552
        int len=name.length();
jtulach@144
   553
        if (len==0) return "\"\"";
jtulach@144
   554
        int cc='/';
jtulach@144
   555
    fullname: { // xxx/yyy/zzz
jtulach@144
   556
            int cp;
jtulach@144
   557
            for (int k=0; k<len; k += Character.charCount(cp)) {
jtulach@144
   558
                cp=name.codePointAt(k);
jtulach@144
   559
                if (cc=='/') {
jaroslav@149
   560
                    if (!isJavaIdentifierStart(cp)) break fullname;
jtulach@144
   561
                } else if (cp!='/') {
jaroslav@149
   562
                    if (!isJavaIdentifierPart(cp)) break fullname;
jtulach@144
   563
                }
jtulach@144
   564
                cc=cp;
jtulach@144
   565
            }
jtulach@144
   566
            return name;
jtulach@144
   567
        }
jtulach@144
   568
        return "\""+name+"\"";
jtulach@144
   569
    }
jtulach@144
   570
jtulach@144
   571
    public String getName(int cpx) {
jtulach@144
   572
        String res;
jtulach@144
   573
        try {
jtulach@144
   574
            return javaName((String)cpool[cpx]); //.replace('/','.');
jtulach@144
   575
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   576
            return "<invalid constant pool index:"+cpx+">";
jtulach@144
   577
        } catch (ClassCastException e) {
jtulach@144
   578
            return "<invalid constant pool ref:"+cpx+">";
jtulach@144
   579
        }
jtulach@144
   580
    }
jtulach@144
   581
jtulach@144
   582
    /**
jtulach@144
   583
     * Returns unqualified class name.
jtulach@144
   584
     */
jtulach@144
   585
    public String getShortClassName(int cpx) {
jtulach@144
   586
        String classname=javaName(getClassName(cpx));
jtulach@144
   587
        pkgPrefixLen=classname.lastIndexOf("/")+1;
jtulach@144
   588
        if (pkgPrefixLen!=0) {
jtulach@144
   589
            pkgPrefix=classname.substring(0,pkgPrefixLen);
jtulach@144
   590
            if (classname.startsWith(pkgPrefix)) {
jtulach@144
   591
                return classname.substring(pkgPrefixLen);
jtulach@144
   592
            }
jtulach@144
   593
        }
jtulach@144
   594
        return classname;
jtulach@144
   595
    }
jtulach@144
   596
jtulach@144
   597
    /**
jtulach@144
   598
     * Returns source file name.
jtulach@144
   599
     */
jtulach@144
   600
    public String getSourceName(){
jtulach@144
   601
        return getName(source_cpx);
jtulach@144
   602
    }
jtulach@144
   603
jtulach@144
   604
    /**
jtulach@144
   605
     * Returns package name.
jtulach@144
   606
     */
jtulach@144
   607
    public String getPkgName(){
jtulach@144
   608
        String classname=getClassName(this_class);
jtulach@144
   609
        pkgPrefixLen=classname.lastIndexOf("/")+1;
jtulach@144
   610
        if (pkgPrefixLen!=0) {
jtulach@144
   611
            pkgPrefix=classname.substring(0,pkgPrefixLen);
jtulach@144
   612
            return("package  "+pkgPrefix.substring(0,pkgPrefixLen-1)+";\n");
jtulach@144
   613
        }else return null;
jtulach@144
   614
    }
jtulach@144
   615
jtulach@144
   616
    /**
jtulach@144
   617
     * Returns total constant pool entry count.
jtulach@144
   618
     */
jtulach@144
   619
    public int getCpoolCount(){
jtulach@144
   620
        return cpool_count;
jtulach@144
   621
    }
jtulach@144
   622
jtulach@144
   623
    public String StringTag(int cpx) {
jtulach@144
   624
        byte tag=0;
jtulach@144
   625
        String str=null;
jtulach@144
   626
        try {
jtulach@144
   627
            if (cpx==0) throw new IndexOutOfBoundsException();
jtulach@144
   628
            tag=tags[cpx];
jtulach@144
   629
            return      TagString(tag);
jtulach@144
   630
        } catch (IndexOutOfBoundsException e) {
jtulach@144
   631
            str="Incorrect CP index:"+cpx;
jtulach@144
   632
        }
jtulach@144
   633
        return str;
jtulach@144
   634
    }
jtulach@144
   635
jtulach@144
   636
    /**
jtulach@144
   637
     * Returns minor version of class file.
jtulach@144
   638
     */
jtulach@144
   639
    public int getMinor_version(){
jtulach@144
   640
        return minor_version;
jtulach@144
   641
    }
jtulach@144
   642
jtulach@144
   643
    /**
jtulach@144
   644
     * Returns major version of class file.
jtulach@144
   645
     */
jtulach@144
   646
    public int getMajor_version(){
jtulach@144
   647
        return major_version;
jtulach@144
   648
    }
jaroslav@149
   649
jaroslav@149
   650
    private boolean isJavaIdentifierStart(int cp) {
jaroslav@149
   651
        return ('a' <= cp && cp <= 'z') || ('A' <= cp && cp <= 'Z');
jaroslav@149
   652
    }
jaroslav@149
   653
jaroslav@149
   654
    private boolean isJavaIdentifierPart(int cp) {
jaroslav@149
   655
        return isJavaIdentifierStart(cp) || ('0' <= cp && cp <= '9');
jaroslav@149
   656
    }
jtulach@144
   657
}