Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

LineNumberTable.java

00001 package de.fub.bytecode.classfile;
00002 
00003 import  de.fub.bytecode.Constants;
00004 import  java.io.*;
00005 
00006 /**
00007  * This class is derived from <em>Attribute</em> and represents a table of 
00008  * line numbers for debugging purposes. This attribute is used by the 
00009  * <em>Code</em> attribute. It contains pairs of PCs and line numbers.
00010  *
00011  * @version $Id: LineNumberTable.java,v 1.1.1.1 2002/01/24 03:41:37 pserver Exp $
00012  * @author  <A HREF="http://www.inf.fu-berlin.de/~dahm">M. Dahm</A>
00013  * @see     Code
00014  * @see     LineNumber
00015  */
00016 public final class LineNumberTable extends Attribute {
00017   private int          line_number_table_length;
00018   private LineNumber[] line_number_table; // Table of line/numbers pairs
00019 
00020   /*
00021    * @param name_index Index of name
00022    * @param length Content length in bytes
00023    * @param line_number_table Table of line/numbers pairs
00024    * @param constant_pool Array of constants
00025    */
00026   public LineNumberTable(int name_index, int length,
00027              LineNumber[] line_number_table,
00028              ConstantPool constant_pool)
00029   {
00030     super(Constants.ATTR_LINE_NUMBER_TABLE, name_index, length, constant_pool);
00031     setLineNumberTable(line_number_table);
00032   }  
00033   /**
00034    * Construct object from file stream.
00035    * @param name_index Index of name
00036    * @param length Content length in bytes
00037    * @param file Input stream
00038    * @throw IOException
00039    * @param constant_pool Array of constants
00040    */
00041   LineNumberTable(int name_index, int length, DataInputStream file,
00042           ConstantPool constant_pool) throws IOException
00043   {
00044     this(name_index, length, (LineNumber[])null, constant_pool);
00045     line_number_table_length = (file.readUnsignedShort());
00046     line_number_table = new LineNumber[line_number_table_length];
00047 
00048     for(int i=0; i < line_number_table_length; i++)
00049       line_number_table[i] = new LineNumber(file);
00050   }  
00051   /*
00052    * Initialize from another object. Note that both objects use the same
00053    * references (shallow copy). Use clone() for a physical copy.
00054    */
00055   public LineNumberTable(LineNumberTable c) {
00056     this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(),
00057      c.getConstantPool());
00058   }  
00059   /**
00060    * Called by objects that are traversing the nodes of the tree implicitely
00061    * defined by the contents of a Java class. I.e., the hierarchy of methods,
00062    * fields, attributes, etc. spawns a tree of objects.
00063    *
00064    * @param v Visitor object
00065    */
00066   public void accept(Visitor v) {
00067     v.visitLineNumberTable(this);
00068   }  
00069   /**
00070    * @return deep copy of this attribute
00071    */
00072   public Attribute copy(ConstantPool constant_pool) {
00073     LineNumberTable c = (LineNumberTable)clone();
00074 
00075     c.line_number_table = new LineNumber[line_number_table_length];
00076     for(int i=0; i < line_number_table_length; i++)
00077       c.line_number_table[i] = line_number_table[i].copy();
00078 
00079     c.constant_pool = constant_pool;
00080     return c;
00081   }  
00082   /**
00083    * Dump line number table attribute to file stream in binary format.
00084    *
00085    * @param file Output file stream
00086    * @throw IOException
00087    */ 
00088   public final void dump(DataOutputStream file) throws IOException
00089   {
00090     super.dump(file);
00091     file.writeShort(line_number_table_length);
00092     for(int i=0; i < line_number_table_length; i++)
00093       line_number_table[i].dump(file);
00094   }  
00095   /**
00096    * @return Array of (pc offset, line number) pairs.
00097    */  
00098   public final LineNumber[] getLineNumberTable() { return line_number_table; }  
00099   /**
00100    * Map byte code positions to source code lines.
00101    *
00102    * @param pos byte code offset
00103    * @return corresponding line in source code
00104    */
00105   public int getSourceLine(int pos) {
00106     int l = 0, r = line_number_table_length-1;
00107 
00108     if(r < 0) // array is empty
00109       return -1;
00110 
00111     int min_index = -1, min=-1;
00112     
00113     /* Do a binary search since the array is ordered.
00114      */
00115     do {
00116       int i = (l + r) / 2;
00117       int j = line_number_table[i].getStartPC();
00118 
00119       if(j == pos)
00120     return line_number_table[i].getLineNumber();
00121       else if(pos < j) // else constrain search area
00122     r = i - 1;
00123       else // pos > j
00124     l = i + 1;
00125 
00126       /* If exact match can't be found (which is the most common case)
00127        * return the line number that corresponds to the greatest index less
00128        * than pos.
00129        */
00130       if(j < pos && j > min) {
00131         min       = j;
00132         min_index = i;
00133       }
00134     } while(l <= r);
00135 
00136     return line_number_table[min_index].getLineNumber();
00137   }  
00138   public final int getTableLength() { return line_number_table_length; }  
00139   /**
00140    * @param line_number_table.
00141    */
00142   public final void setLineNumberTable(LineNumber[] line_number_table) {
00143     this.line_number_table = line_number_table;
00144 
00145     line_number_table_length = (line_number_table == null)? 0 :
00146       line_number_table.length;
00147   }  
00148   /**
00149    * @return String representation.
00150    */ 
00151   public final String toString() {
00152     StringBuffer buf  = new StringBuffer();
00153     StringBuffer line = new StringBuffer();
00154 
00155     for(int i=0; i < line_number_table_length; i++) {
00156       line.append(line_number_table[i].toString());
00157 
00158       if(i < line_number_table_length - 1)
00159     line.append(", ");
00160 
00161       if(line.length() > 72) {
00162     line.append('\n');
00163     buf.append(line);
00164     line.setLength(0);
00165       }
00166     }
00167 
00168     buf.append(line);
00169 
00170     return buf.toString();    
00171   }  
00172 }

Generated at Thu Feb 7 06:49:37 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001