• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License.  Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later,
9  * or the Apache License Version 2.0.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  */
16 
17 package javassist.bytecode;
18 
19 import java.io.DataInputStream;
20 import java.io.IOException;
21 import java.util.Map;
22 
23 /**
24  * <code>LineNumberTable_attribute</code>.
25  */
26 public class LineNumberAttribute extends AttributeInfo {
27     /**
28      * The name of this attribute <code>"LineNumberTable"</code>.
29      */
30     public static final String tag = "LineNumberTable";
31 
LineNumberAttribute(ConstPool cp, int n, DataInputStream in)32     LineNumberAttribute(ConstPool cp, int n, DataInputStream in)
33         throws IOException
34     {
35         super(cp, n, in);
36     }
37 
LineNumberAttribute(ConstPool cp, byte[] i)38     private LineNumberAttribute(ConstPool cp, byte[] i) {
39         super(cp, tag, i);
40     }
41 
42     /**
43      * Returns <code>line_number_table_length</code>.
44      * This represents the number of entries in the table.
45      */
tableLength()46     public int tableLength() {
47         return ByteArray.readU16bit(info, 0);
48     }
49 
50     /**
51      * Returns <code>line_number_table[i].start_pc</code>.
52      * This represents the index into the code array at which the code
53      * for a new line in the original source file begins.
54      *
55      * @param i         the i-th entry.
56      */
startPc(int i)57     public int startPc(int i) {
58         return ByteArray.readU16bit(info, i * 4 + 2);
59     }
60 
61     /**
62      * Returns <code>line_number_table[i].line_number</code>.
63      * This represents the corresponding line number in the original
64      * source file.
65      *
66      * @param i         the i-th entry.
67      */
lineNumber(int i)68     public int lineNumber(int i) {
69         return ByteArray.readU16bit(info, i * 4 + 4);
70     }
71 
72     /**
73      * Returns the line number corresponding to the specified bytecode.
74      *
75      * @param pc        the index into the code array.
76      */
toLineNumber(int pc)77     public int toLineNumber(int pc) {
78         int n = tableLength();
79         int i = 0;
80         for (; i < n; ++i)
81             if (pc < startPc(i))
82                 if (i == 0)
83                     return lineNumber(0);
84                 else
85                     break;
86 
87         return lineNumber(i - 1);
88     }
89 
90     /**
91      * Returns the index into the code array at which the code for
92      * the specified line begins.
93      *
94      * @param line      the line number.
95      * @return          -1 if the specified line is not found.
96      */
toStartPc(int line)97     public int toStartPc(int line) {
98         int n = tableLength();
99         for (int i = 0; i < n; ++i)
100             if (line == lineNumber(i))
101                 return startPc(i);
102 
103         return -1;
104     }
105 
106     /**
107      * Used as a return type of <code>toNearPc()</code>.
108      */
109     static public class Pc {
110         /**
111          * The index into the code array.
112          */
113         public int index;
114         /**
115          * The line number.
116          */
117         public int line;
118     }
119 
120     /**
121      * Returns the index into the code array at which the code for
122      * the specified line (or the nearest line after the specified one)
123      * begins.
124      *
125      * @param line      the line number.
126      * @return          a pair of the index and the line number of the
127      *                  bytecode at that index.
128      */
toNearPc(int line)129     public Pc toNearPc(int line) {
130         int n = tableLength();
131         int nearPc = 0;
132         int distance = 0;
133         if (n > 0) {
134             distance = lineNumber(0) - line;
135             nearPc = startPc(0);
136         }
137 
138         for (int i = 1; i < n; ++i) {
139             int d = lineNumber(i) - line;
140             if ((d < 0 && d > distance)
141                 || (d >= 0 && (d < distance || distance < 0))) {
142                     distance = d;
143                     nearPc = startPc(i);
144             }
145         }
146 
147         Pc res = new Pc();
148         res.index = nearPc;
149         res.line = line + distance;
150         return res;
151     }
152 
153     /**
154      * Makes a copy.
155      *
156      * @param newCp     the constant pool table used by the new copy.
157      * @param classnames        should be null.
158      */
159     @Override
copy(ConstPool newCp, Map<String,String> classnames)160     public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) {
161         byte[] src = info;
162         int num = src.length;
163         byte[] dest = new byte[num];
164         for (int i = 0; i < num; ++i)
165             dest[i] = src[i];
166 
167         LineNumberAttribute attr = new LineNumberAttribute(newCp, dest);
168         return attr;
169     }
170 
171     /**
172      * Adjusts start_pc if bytecode is inserted in a method body.
173      */
shiftPc(int where, int gapLength, boolean exclusive)174     void shiftPc(int where, int gapLength, boolean exclusive) {
175         int n = tableLength();
176         for (int i = 0; i < n; ++i) {
177             int pos = i * 4 + 2;
178             int pc = ByteArray.readU16bit(info, pos);
179             if (pc > where || (exclusive && pc == where))
180                 ByteArray.write16bit(pc + gapLength, info, pos);
181         }
182     }
183 }
184