FileDocCategorySizeDatePackage
LineNumberTableAttribute.javaAPI DocJ2ME CLDC 1.19004Wed Feb 05 15:56:04 GMT 2003kdp.classparser.attributes

LineNumberTableAttribute.java

/*
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package kdp.classparser.attributes;

import kdp.Log;
import kdp.classparser.attributes.*;
import kdp.classparser.constantpoolclasses.*;

import java.io.*;

/**
 * Encapsulates a LineNumberTable attribute of a Java class file.
 *
 * @author        Aaron Dietrich
 * @version       $Id: LineNumberTableAttribute.java,v 1.1.1.1 2000/07/07 13:34:24 jrv Exp $
 *
 * Revision History
 *   $Log: LineNumberTableAttribute.java,v $
 *   Revision 1.1.1.1  2000/07/07 13:34:24  jrv
 *   Initial import of kdp code
 *
 *   Revision 1.1.1.1  2000/05/31 19:14:47  ritsun
 *   Initial import of kvmdt to CVS
 *
 *   Revision 1.1  2000/04/25 00:30:39  ritsun
 *   Initial revision
 *
 */
public class LineNumberTableAttribute extends Attribute
  {
    /** index into the constant pool table containing the name 
         of this class */
    private int                attributeNameIndex;
    /** length of this attribute in bytes */
    private int                attributeLength;
    /** number of elements in the line number table array */
    private int                lineNumberTableLength;
    /** each entry indicates that the line number in the original 
         source file changes at a given point in the code array. */
    private LineNumberTable    lineNumberTable[];
    
    /**
     * Constructor.  Reads the LineNumberTableAttribute attribute from
     * the class file.
     *
     * @param    iStream           the input stream on which to
     *                             read the class file
     * @param    attributeNameIndex     attributeNameIndex member of
     *                                  attribute structure.
     * @param    attributeLength     attributeLength member of
     *                               attribute structure.
     *
     * @exception    IOException         pass IOExceptions up
     */
    public LineNumberTableAttribute (DataInputStream iStream,
        int attributeNameIndex, int attributeLength) throws IOException
      {
        this.attributeNameIndex = attributeNameIndex;
        this.attributeLength = attributeLength;

        //read in the length of the LineNumberTable array
        lineNumberTableLength = iStream.readUnsignedShort ();

        //allocate space for the LineNumberTable array and read in the data
        lineNumberTable = new LineNumberTable[lineNumberTableLength];
        for (int lcv = 0; lcv < lineNumberTableLength; ++lcv)
          {
           lineNumberTable[lcv] = new LineNumberTable ();
           lineNumberTable[lcv].startPC = iStream.readUnsignedShort ();
           lineNumberTable[lcv].lineNumber = iStream.readUnsignedShort ();
          }
      }

    public int[][] getLineNumbersAndIndicesAsArray ()
      {
        int      lineArray[][] = new int[lineNumberTableLength][2];

        for (int lcv = 0; lcv < lineNumberTableLength; ++lcv)
          {
           lineArray[lcv][0] = lineNumberTable[lcv].lineNumber;
           lineArray[lcv][1] = lineNumberTable[lcv].startPC;
          }

        return lineArray;
      }

    /**
     * Returns the first code index associated with the specified source
     * file line number.
     *
     * @param        lineNumber          source file line number
     *
     * @return       int                 index into code array of
     *                                   first bytecode of this instruction
     *                                   If the line number does not map to
     *                                   a code array index then return -1
     */
    public int getCodeIndexBySourceLineNumber (int lineNumber)
      {
        boolean       found = false;
        int           index = 0;

        //loop through line number table until we find an entry with the
        //specified source file line number or run out of entries
        while ((!found) && (index < lineNumberTableLength))
          {
           if (lineNumber == lineNumberTable[index].lineNumber)
             found = true;
           else
             ++index;
          }

        //if an entry was found return the code array index associated with it
        if (found)
          return (lineNumberTable[index].startPC);
        else
          return -1; //no entry found so return -1
      }

    /**
     * Determine if this lineNumber table contains the specified source file
     * line number.
     *
     * @param        lineNumber          source file line number
     *
     * @return       boolean             true if line number was found, false
     *                                   otherwise
     */
    public boolean containsLine (int lineNumber)
      {
        boolean       found = false;
        int           index = 0;

        //loop through each entry in the line number table until
        //the specified line number is found or there are no
        //entries left
        while ((!found) && (index < lineNumberTableLength))
          {
           if (lineNumber == lineNumberTable[index].lineNumber)
             found = true;
           else
             ++index;
          }
        return found;
      }

    /**
     * Returns the line that this opcode offset lies on
     *
     */
    private int getIndexThatContainsOpcode(long offset) {

         for (int i=0; i < lineNumberTableLength - 1; i++) {
             if (offset >= lineNumberTable[ i ].startPC && 
                  offset < lineNumberTable[ i + 1 ].startPC) {
                 return i;
             }
         }
         if (offset >= lineNumberTable[ lineNumberTableLength - 1 ].startPC)
             return lineNumberTableLength - 1;

         return -1; // lineNumberTable[ 0 ].lineNumber;

    }

    public int getDupCurrentExecutableLineCodeIndex(long offset) {

    int firstIndex = getNextExecutableLineCodeIndex(offset, false);
    if (firstIndex == -1)
        return -1;
    firstIndex--;
    return getOtherLineIndex(firstIndex);
    }

    public long getOffsetofDupNextLine(int index) {
    if (index == -1 || index == lineNumberTableLength - 1)
        return -1;
    return lineNumberTable[index + 1].startPC;
    }

    private int getOtherLineIndex(int index) {
         for (int i=0; i < lineNumberTableLength; i++) {
             if (i == index) continue;
             if (lineNumberTable[ i ].lineNumber == 
                  lineNumberTable[ index ].lineNumber) {
                 return i;
             }
         }
         return -1;

    }

    public int getCurrentLineCodeIndex(long offset) {

        int currentIndex = getIndexThatContainsOpcode(offset);
        Log.LOGN(3,  "getCurrent: index=" + currentIndex);
        return currentIndex;
    }

    public int getNextExecutableLineCodeIndex(long offset) {
    return getNextExecutableLineCodeIndex(offset, true);
    }

    private int getNextExecutableLineCodeIndex(long offset, boolean logging) {

         int firstIndex = getIndexThatContainsOpcode(offset);
         if (logging)
             Log.LOGN(3,  "getNext: firstIndex=" + firstIndex);
         int otherIndex; 
         if ((otherIndex = getOtherLineIndex(firstIndex)) != -1) {
             if (logging)
                 Log.LOGN(3,  "getNext: otherIndex=" + otherIndex);
             if (otherIndex < firstIndex) {
                 if (logging)
            Log.LOGN(3,  "getNext: otherIndex < firstIndex");
        return otherIndex + 1;
             } else {
                 if (logging)
            Log.LOGN(3,  "getNext: otherIndex > firstIndex");
        return firstIndex + 1;
             }
         }
 
         if (firstIndex+1 < lineNumberTableLength)
             return firstIndex + 1;
         else
             return -1;
    }

    public long getStartPCFromIndex(int index) {
        if (index == -1)
            return -1;
        return lineNumberTable[index].startPC;
    }

    public int getLineNumberFromIndex(int index) {
        if (index == -1 || index == lineNumberTableLength - 1)
            return (-1);
        return lineNumberTable[index].lineNumber;
    }

    /**
     * Returns the LineNumberTableAttribute attribute in a nice easy to
     * read format as a string.
     *
     * @param        constantPool        constant pool of the class file
     *
     * @return         String            the attribute as a nice easy to
     *                            read String
     */
    public String toString (final ConstantPoolInfo[] constantPool)
      {
        ConstantUtf8Info            utf8Info;
        String                        s = new String ("");

        utf8Info = (ConstantUtf8Info) constantPool[attributeNameIndex];
        s = s + "\t" + utf8Info.toString ();
 /*
        for (int lcv = 0; lcv < lineNumberTableLength; ++lcv)
          {
           s = s + "\n\t\t\t\tStart PC=  " + lineNumberTable[lcv].startPC;
           s = s + "\tLine Number=  " + lineNumberTable[lcv].lineNumber;
          }
 */       
        return s;
      }
  }