001: /*
002: * Javassist, a Java-bytecode translator toolkit.
003: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
004: *
005: * The contents of this file are subject to the Mozilla Public License Version
006: * 1.1 (the "License"); you may not use this file except in compliance with
007: * the License. Alternatively, the contents of this file may be used under
008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
009: *
010: * Software distributed under the License is distributed on an "AS IS" basis,
011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012: * for the specific language governing rights and limitations under the
013: * License.
014: */
015:
016: package javassist.bytecode;
017:
018: import java.io.DataInputStream;
019: import java.io.IOException;
020: import java.util.Map;
021:
022: /**
023: * <code>LineNumberTable_attribute</code>.
024: */
025: public class LineNumberAttribute extends AttributeInfo {
026: /**
027: * The name of this attribute <code>"LineNumberTable"</code>.
028: */
029: public static final String tag = "LineNumberTable";
030:
031: LineNumberAttribute(ConstPool cp, int n, DataInputStream in)
032: throws IOException {
033: super (cp, n, in);
034: }
035:
036: private LineNumberAttribute(ConstPool cp, byte[] i) {
037: super (cp, tag, i);
038: }
039:
040: /**
041: * Returns <code>line_number_table_length</code>.
042: * This represents the number of entries in the table.
043: */
044: public int tableLength() {
045: return ByteArray.readU16bit(info, 0);
046: }
047:
048: /**
049: * Returns <code>line_number_table[i].start_pc</code>.
050: * This represents the index into the code array at which the code
051: * for a new line in the original source file begins.
052: *
053: * @param i the i-th entry.
054: */
055: public int startPc(int i) {
056: return ByteArray.readU16bit(info, i * 4 + 2);
057: }
058:
059: /**
060: * Returns <code>line_number_table[i].line_number</code>.
061: * This represents the corresponding line number in the original
062: * source file.
063: *
064: * @param i the i-th entry.
065: */
066: public int lineNumber(int i) {
067: return ByteArray.readU16bit(info, i * 4 + 4);
068: }
069:
070: /**
071: * Returns the line number corresponding to the specified bytecode.
072: *
073: * @param pc the index into the code array.
074: */
075: public int toLineNumber(int pc) {
076: int n = tableLength();
077: int i = 0;
078: for (; i < n; ++i)
079: if (pc < startPc(i))
080: if (i == 0)
081: return lineNumber(0);
082: else
083: break;
084:
085: return lineNumber(i - 1);
086: }
087:
088: /**
089: * Returns the index into the code array at which the code for
090: * the specified line begins.
091: *
092: * @param line the line number.
093: * @return -1 if the specified line is not found.
094: */
095: public int toStartPc(int line) {
096: int n = tableLength();
097: for (int i = 0; i < n; ++i)
098: if (line == lineNumber(i))
099: return startPc(i);
100:
101: return -1;
102: }
103:
104: /**
105: * Used as a return type of <code>toNearPc()</code>.
106: */
107: static public class Pc {
108: /**
109: * The index into the code array.
110: */
111: public int index;
112: /**
113: * The line number.
114: */
115: public int line;
116: }
117:
118: /**
119: * Returns the index into the code array at which the code for
120: * the specified line (or the nearest line after the specified one)
121: * begins.
122: *
123: * @param line the line number.
124: * @return a pair of the index and the line number of the
125: * bytecode at that index.
126: */
127: public Pc toNearPc(int line) {
128: int n = tableLength();
129: int nearPc = 0;
130: int distance = 0;
131: if (n > 0) {
132: distance = lineNumber(0) - line;
133: nearPc = startPc(0);
134: }
135:
136: for (int i = 1; i < n; ++i) {
137: int d = lineNumber(i) - line;
138: if ((d < 0 && d > distance)
139: || (d >= 0 && (d < distance || distance < 0))) {
140: distance = d;
141: nearPc = startPc(i);
142: }
143: }
144:
145: Pc res = new Pc();
146: res.index = nearPc;
147: res.line = line + distance;
148: return res;
149: }
150:
151: /**
152: * Makes a copy.
153: *
154: * @param newCp the constant pool table used by the new copy.
155: * @param classnames should be null.
156: */
157: public AttributeInfo copy(ConstPool newCp, Map classnames) {
158: byte[] src = info;
159: int num = src.length;
160: byte[] dest = new byte[num];
161: for (int i = 0; i < num; ++i)
162: dest[i] = src[i];
163:
164: LineNumberAttribute attr = new LineNumberAttribute(newCp, dest);
165: return attr;
166: }
167:
168: /**
169: * Adjusts start_pc if bytecode is inserted in a method body.
170: */
171: void shiftPc(int where, int gapLength, boolean exclusive) {
172: int n = tableLength();
173: for (int i = 0; i < n; ++i) {
174: int pos = i * 4 + 2;
175: int pc = ByteArray.readU16bit(info, pos);
176: if (pc > where || (exclusive && pc == where))
177: ByteArray.write16bit(pc + gapLength, info, pos);
178: }
179: }
180: }
|