169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.DataInputStream;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Map;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>LocalVariableTable_attribute</code>.
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class LocalVariableAttribute extends AttributeInfo {
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The name of this attribute <code>"LocalVariableTable"</code>.
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String tag = "LocalVariableTable";
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The name of the attribute <code>"LocalVariableTypeTable"</code>.
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String typeTag = "LocalVariableTypeTable";
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs an empty LocalVariableTable.
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public LocalVariableAttribute(ConstPool cp) {
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, tag, new byte[2]);
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ByteArray.write16bit(0, info, 0);
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs an empty LocalVariableTable.
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param name      the attribute name.
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  <code>LocalVariableAttribute.tag</code> or
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  <code>LocalVariableAttribute.typeTag</code>.
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #tag
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #typeTag
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.1
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @deprecated
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public LocalVariableAttribute(ConstPool cp, String name) {
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, name, new byte[2]);
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ByteArray.write16bit(0, info, 0);
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    LocalVariableAttribute(ConstPool cp, int n, DataInputStream in)
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws IOException
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, n, in);
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    LocalVariableAttribute(ConstPool cp, String name, byte[] i) {
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, name, i);
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Appends a new entry to <code>local_variable_table</code>.
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param startPc           <code>start_pc</code>
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param length            <code>length</code>
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param nameIndex         <code>name_index</code>
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param descriptorIndex   <code>descriptor_index</code>
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param index             <code>index</code>
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addEntry(int startPc, int length, int nameIndex,
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                         int descriptorIndex, int index) {
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int size = info.length;
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] newInfo = new byte[size + 10];
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ByteArray.write16bit(tableLength() + 1, newInfo, 0);
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 2; i < size; ++i)
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            newInfo[i] = info[i];
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ByteArray.write16bit(startPc, newInfo, size);
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ByteArray.write16bit(length, newInfo, size + 2);
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ByteArray.write16bit(nameIndex, newInfo, size + 4);
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ByteArray.write16bit(descriptorIndex, newInfo, size + 6);
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ByteArray.write16bit(index, newInfo, size + 8);
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        info = newInfo;
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void renameClass(String oldname, String newname) {
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = getConstPool();
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = tableLength();
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pos = i * 10 + 2;
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int index = ByteArray.readU16bit(info, pos + 6);
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (index != 0) {
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                String desc = cp.getUtf8Info(index);
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                desc = renameEntry(desc, oldname, newname);
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ByteArray.write16bit(cp.addUtf8Info(desc), info, pos + 6);
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    String renameEntry(String desc, String oldname, String newname) {
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return Descriptor.rename(desc, oldname, newname);
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void renameClass(Map classnames) {
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = getConstPool();
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = tableLength();
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pos = i * 10 + 2;
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int index = ByteArray.readU16bit(info, pos + 6);
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (index != 0) {
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                String desc = cp.getUtf8Info(index);
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                desc = renameEntry(desc, classnames);
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ByteArray.write16bit(cp.addUtf8Info(desc), info, pos + 6);
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    String renameEntry(String desc, Map classnames) {
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return Descriptor.rename(desc, classnames);
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * For each <code>local_variable_table[i].index</code>,
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * this method increases <code>index</code> by <code>delta</code>.
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param lessThan      the index does not change if it
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                      is less than this value.
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void shiftIndex(int lessThan, int delta) {
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int size = info.length;
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 2; i < size; i += 10){
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int org = ByteArray.readU16bit(info, i + 8);
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (org >= lessThan)
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ByteArray.write16bit(org + delta, info, i + 8);
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>local_variable_table_length</code>.
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This represents the number of entries in the table.
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int tableLength() {
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return ByteArray.readU16bit(info, 0);
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>local_variable_table[i].start_pc</code>.
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This represents the index into the code array from which the local
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * variable is effective.
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param i         the i-th entry.
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int startPc(int i) {
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return ByteArray.readU16bit(info, i * 10 + 2);
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>local_variable_table[i].length</code>.
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This represents the length of the code region in which the local
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * variable is effective.
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param i         the i-th entry.
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int codeLength(int i) {
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return ByteArray.readU16bit(info, i * 10 + 4);
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Adjusts start_pc and length if bytecode is inserted in a method body.
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void shiftPc(int where, int gapLength, boolean exclusive) {
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = tableLength();
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pos = i * 10 + 2;
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pc = ByteArray.readU16bit(info, pos);
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int len = ByteArray.readU16bit(info, pos + 2);
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            /* if pc == 0, then the local variable is a method parameter.
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal             */
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (pc > where || (exclusive && pc == where && pc != 0))
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ByteArray.write16bit(pc + gapLength, info, pos);
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (pc + len > where || (exclusive && pc + len == where))
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ByteArray.write16bit(len + gapLength, info, pos + 2);
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the value of <code>local_variable_table[i].name_index</code>.
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This represents the name of the local variable.
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param i         the i-th entry.
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int nameIndex(int i) {
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return ByteArray.readU16bit(info, i * 10 + 6);
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the name of the local variable
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * specified by <code>local_variable_table[i].name_index</code>.
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param i         the i-th entry.
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String variableName(int i) {
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return getConstPool().getUtf8Info(nameIndex(i));
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the value of
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>local_variable_table[i].descriptor_index</code>.
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This represents the type descriptor of the local variable.
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If this attribute represents a LocalVariableTypeTable attribute,
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * this method returns the value of
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>local_variable_type_table[i].signature_index</code>.
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It represents the type of the local variable.
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param i         the i-th entry.
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int descriptorIndex(int i) {
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return ByteArray.readU16bit(info, i * 10 + 8);
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method is equivalent to <code>descriptorIndex()</code>.
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If this attribute represents a LocalVariableTypeTable attribute,
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * this method should be used instead of <code>descriptorIndex()</code>
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * since the method name is more appropriate.
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param i         the i-th entry.
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #descriptorIndex(int)
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see SignatureAttribute#toFieldSignature(String)
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int signatureIndex(int i) {
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return descriptorIndex(i);
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the type descriptor of the local variable
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * specified by <code>local_variable_table[i].descriptor_index</code>.
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If this attribute represents a LocalVariableTypeTable attribute,
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * this method returns the type signature of the local variable
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * specified by <code>local_variable_type_table[i].signature_index</code>.
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal      *
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param i         the i-th entry.
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String descriptor(int i) {
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return getConstPool().getUtf8Info(descriptorIndex(i));
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method is equivalent to <code>descriptor()</code>.
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If this attribute represents a LocalVariableTypeTable attribute,
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * this method should be used instead of <code>descriptor()</code>
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * since the method name is more appropriate.
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>To parse the string, call <code>toFieldSignature(String)</code>
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * in <code>SignatureAttribute</code>.
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param i         the i-th entry.
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #descriptor(int)
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see SignatureAttribute#toFieldSignature(String)
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String signature(int i) {
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return descriptor(i);
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>local_variable_table[i].index</code>.
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This represents the index of the local variable.
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param i         the i-th entry.
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int index(int i) {
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return ByteArray.readU16bit(info, i * 10 + 10);
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes a copy.
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param newCp     the constant pool table used by the new copy.
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param classnames        should be null.
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public AttributeInfo copy(ConstPool newCp, Map classnames) {
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] src = get();
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] dest = new byte[src.length];
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = getConstPool();
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LocalVariableAttribute attr = makeThisAttr(newCp, dest);
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = ByteArray.readU16bit(src, 0);
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ByteArray.write16bit(n, dest, 0);
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int j = 2;
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int start = ByteArray.readU16bit(src, j);
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int len = ByteArray.readU16bit(src, j + 2);
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int name = ByteArray.readU16bit(src, j + 4);
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int type = ByteArray.readU16bit(src, j + 6);
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int index = ByteArray.readU16bit(src, j + 8);
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ByteArray.write16bit(start, dest, j);
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ByteArray.write16bit(len, dest, j + 2);
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (name != 0)
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                name = cp.copy(name, newCp, null);
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ByteArray.write16bit(name, dest, j + 4);
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (type != 0)  {
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                String sig = cp.getUtf8Info(type);
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sig = Descriptor.rename(sig, classnames);
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                type = newCp.addUtf8Info(sig);
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ByteArray.write16bit(type, dest, j + 6);
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ByteArray.write16bit(index, dest, j + 8);
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            j += 10;
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return attr;
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    // LocalVariableTypeAttribute overrides this method.
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    LocalVariableAttribute makeThisAttr(ConstPool cp, byte[] dest) {
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return new LocalVariableAttribute(cp, tag, dest);
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
334