1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.bcel.internal.classfile; 23 24 25 import com.sun.org.apache.bcel.internal.Constants; 26 import java.io.*; 27 28 /** 29 * This class represents a table of line numbers for debugging 30 * purposes. This attribute is used by the <em>Code</em> attribute. It 31 * contains pairs of PCs and line numbers. 32 * 33 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> 34 * @see Code 35 * @see LineNumber 36 */ 37 public final class LineNumberTable extends Attribute { 38 private int line_number_table_length; 39 private LineNumber[] line_number_table; // Table of line/numbers pairs 40 41 /* 42 * Initialize from another object. Note that both objects use the same 43 * references (shallow copy). Use copy() for a physical copy. 44 */ 45 public LineNumberTable(LineNumberTable c) { 46 this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), 47 c.getConstantPool()); 48 } 49 50 /* 51 * @param name_index Index of name 52 * @param length Content length in bytes 53 * @param line_number_table Table of line/numbers pairs 54 * @param constant_pool Array of constants 55 */ 56 public LineNumberTable(int name_index, int length, 57 LineNumber[] line_number_table, 58 ConstantPool constant_pool) 59 { 60 super(Constants.ATTR_LINE_NUMBER_TABLE, name_index, length, constant_pool); 61 setLineNumberTable(line_number_table); 62 } 63 64 /** 65 * Construct object from file stream. 66 * @param name_index Index of name 67 * @param length Content length in bytes 68 * @param file Input stream 69 * @throws IOException 70 * @param constant_pool Array of constants 71 */ 72 LineNumberTable(int name_index, int length, DataInputStream file, 73 ConstantPool constant_pool) throws IOException 74 { 75 this(name_index, length, (LineNumber[])null, constant_pool); 76 line_number_table_length = (file.readUnsignedShort()); 77 line_number_table = new LineNumber[line_number_table_length]; 78 79 for(int i=0; i < line_number_table_length; i++) 80 line_number_table[i] = new LineNumber(file); 81 } 82 /** 83 * Called by objects that are traversing the nodes of the tree implicitely 84 * defined by the contents of a Java class. I.e., the hierarchy of methods, 85 * fields, attributes, etc. spawns a tree of objects. 86 * 87 * @param v Visitor object 88 */ 89 public void accept(Visitor v) { 90 v.visitLineNumberTable(this); 91 } 92 /** 93 * Dump line number table attribute to file stream in binary format. 94 * 95 * @param file Output file stream 96 * @throws IOException 97 */ 98 public final void dump(DataOutputStream file) throws IOException 99 { 100 super.dump(file); 101 file.writeShort(line_number_table_length); 102 for(int i=0; i < line_number_table_length; i++) 103 line_number_table[i].dump(file); 104 } 105 106 /** 107 * @return Array of (pc offset, line number) pairs. 108 */ 109 public final LineNumber[] getLineNumberTable() { return line_number_table; } 110 111 /** 112 * @param line_number_table. 113 */ 114 public final void setLineNumberTable(LineNumber[] line_number_table) { 115 this.line_number_table = line_number_table; 116 117 line_number_table_length = (line_number_table == null)? 0 : 118 line_number_table.length; 119 } 120 121 /** 122 * @return String representation. 123 */ 124 public final String toString() { 125 StringBuffer buf = new StringBuffer(); 126 StringBuffer line = new StringBuffer(); 127 128 for(int i=0; i < line_number_table_length; i++) { 129 line.append(line_number_table[i].toString()); 130 131 if(i < line_number_table_length - 1) 132 line.append(", "); 133 134 if(line.length() > 72) { 135 line.append('\n'); 136 buf.append(line); 137 line.setLength(0); 138 } 139 } 140 141 buf.append(line); 142 143 return buf.toString(); 144 } 145 146 /** 147 * Map byte code positions to source code lines. 148 * 149 * @param pos byte code offset 150 * @return corresponding line in source code 151 */ 152 public int getSourceLine(int pos) { 153 int l = 0, r = line_number_table_length-1; 154 155 if(r < 0) // array is empty 156 return -1; 157 158 int min_index = -1, min=-1; 159 160 /* Do a binary search since the array is ordered. 161 */ 162 do { 163 int i = (l + r) / 2; 164 int j = line_number_table[i].getStartPC(); 165 166 if(j == pos) 167 return line_number_table[i].getLineNumber(); 168 else if(pos < j) // else constrain search area 169 r = i - 1; 170 else // pos > j 171 l = i + 1; 172 173 /* If exact match can't be found (which is the most common case) 174 * return the line number that corresponds to the greatest index less 175 * than pos. 176 */ 177 if(j < pos && j > min) { 178 min = j; 179 min_index = i; 180 } 181 } while(l <= r); 182 183 /* It's possible that we did not find any valid entry for the bytecode 184 * offset we were looking for. 185 */ 186 if (min_index < 0) 187 return -1; 188 189 return line_number_table[min_index].getLineNumber(); 190 } 191 192 /** 193 * @return deep copy of this attribute 194 */ 195 public Attribute copy(ConstantPool constant_pool) { 196 LineNumberTable c = (LineNumberTable)clone(); 197 198 c.line_number_table = new LineNumber[line_number_table_length]; 199 for(int i=0; i < line_number_table_length; i++) 200 c.line_number_table[i] = line_number_table[i].copy(); 201 202 c.constant_pool = constant_pool; 203 return c; 204 } 205 206 public final int getTableLength() { return line_number_table_length; } 207 }