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>LineNumberTable_attribute</code>.
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class LineNumberAttribute extends AttributeInfo {
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The name of this attribute <code>"LineNumberTable"</code>.
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String tag = "LineNumberTable";
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    LineNumberAttribute(ConstPool cp, int n, DataInputStream in)
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws IOException
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, n, in);
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private LineNumberAttribute(ConstPool cp, byte[] i) {
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, tag, i);
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>line_number_table_length</code>.
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This represents the number of entries in the table.
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int tableLength() {
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return ByteArray.readU16bit(info, 0);
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>line_number_table[i].start_pc</code>.
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This represents the index into the code array at which the code
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * for a new line in the original source file begins.
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param i         the i-th entry.
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int startPc(int i) {
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return ByteArray.readU16bit(info, i * 4 + 2);
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>line_number_table[i].line_number</code>.
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This represents the corresponding line number in the original
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * source file.
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param i         the i-th entry.
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int lineNumber(int i) {
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return ByteArray.readU16bit(info, i * 4 + 4);
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the line number corresponding to the specified bytecode.
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param pc        the index into the code array.
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int toLineNumber(int pc) {
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = tableLength();
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i = 0;
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (; i < n; ++i)
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (pc < startPc(i))
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (i == 0)
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    return lineNumber(0);
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    break;
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return lineNumber(i - 1);
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the index into the code array at which the code for
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the specified line begins.
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param line      the line number.
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return          -1 if the specified line is not found.
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int toStartPc(int line) {
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = tableLength();
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i)
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (line == lineNumber(i))
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return startPc(i);
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return -1;
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Used as a return type of <code>toNearPc()</code>.
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static public class Pc {
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * The index into the code array.
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public int index;
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * The line number.
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public int line;
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the index into the code array at which the code for
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the specified line (or the nearest line after the specified one)
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * begins.
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param line      the line number.
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return          a pair of the index and the line number of the
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  bytecode at that index.
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Pc toNearPc(int line) {
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = tableLength();
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int nearPc = 0;
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int distance = 0;
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (n > 0) {
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            distance = lineNumber(0) - line;
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            nearPc = startPc(0);
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 1; i < n; ++i) {
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int d = lineNumber(i) - line;
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if ((d < 0 && d > distance)
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                || (d >= 0 && (d < distance || distance < 0))) {
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    distance = d;
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    nearPc = startPc(i);
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Pc res = new Pc();
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        res.index = nearPc;
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        res.line = line + distance;
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return res;
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes a copy.
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param newCp     the constant pool table used by the new copy.
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param classnames        should be null.
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public AttributeInfo copy(ConstPool newCp, Map classnames) {
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] src = info;
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int num = src.length;
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] dest = new byte[num];
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < num; ++i)
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            dest[i] = src[i];
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LineNumberAttribute attr = new LineNumberAttribute(newCp, dest);
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return attr;
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Adjusts start_pc if bytecode is inserted in a method body.
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void shiftPc(int where, int gapLength, boolean exclusive) {
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = tableLength();
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pos = i * 4 + 2;
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pc = ByteArray.readU16bit(info, pos);
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (pc > where || (exclusive && pc == where))
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ByteArray.write16bit(pc + gapLength, info, pos);
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
182