001 package serp.bytecode;
002
003 import java.io.*;
004 import java.util.*;
005
006 import serp.bytecode.lowlevel.*;
007 import serp.bytecode.visitor.*;
008
009 /**
010 * A line number corresponds to a sequence of opcodes that map logically
011 * to a line of source code.
012 *
013 * @author Abe White
014 */
015 public class LineNumber implements Comparable, InstructionPtr, BCEntity,
016 VisitAcceptor {
017 private int _line = 0;
018 private LineNumberTable _owner = null;
019 InstructionPtrStrategy _target = new InstructionPtrStrategy(this);
020
021 LineNumber(LineNumberTable owner) {
022 _owner = owner;
023 }
024
025 LineNumber(LineNumberTable owner, int startPc) {
026 this(owner);
027 setStartPc(startPc);
028 }
029
030 /**
031 * Line numbers are stored in a {@link LineNumberTable}.
032 */
033 public LineNumberTable getTable() {
034 return _owner;
035 }
036
037 void invalidate() {
038 _owner = null;
039 }
040
041 /**
042 * Return source line number.
043 */
044 public int getLine() {
045 return _line;
046 }
047
048 /**
049 * Set the source line number.
050 */
051 public void setLine(int lineNumber) {
052 _line = lineNumber;
053 }
054
055 /**
056 * Return the instruction marking the beginning of this line.
057 */
058 public Instruction getStart() {
059 return _target.getTargetInstruction();
060 }
061
062 /**
063 * Return the index into the code byte array at which this line starts.
064 */
065 public int getStartPc() {
066 return _target.getByteIndex();
067 }
068
069 /**
070 * Set the index into the code byte array at which this line starts.
071 */
072 public void setStartPc(int startPc) {
073 _target.setByteIndex(startPc);
074 }
075
076 /**
077 * Set the {@link Instruction} marking the beginning this line.
078 * The instruction must already be a part of the method.
079 */
080 public void setStart(Instruction instruction) {
081 _target.setTargetInstruction(instruction);
082 }
083
084 public void updateTargets() {
085 _target.updateTargets();
086 }
087
088 public void replaceTarget(Instruction oldTarget, Instruction newTarget) {
089 _target.replaceTarget(oldTarget, newTarget);
090 }
091
092 public Project getProject() {
093 return _owner.getProject();
094 }
095
096 public ConstantPool getPool() {
097 return _owner.getPool();
098 }
099
100 public ClassLoader getClassLoader() {
101 return _owner.getClassLoader();
102 }
103
104 public boolean isValid() {
105 return _owner != null;
106 }
107
108 public void acceptVisit(BCVisitor visit) {
109 visit.enterLineNumber(this);
110 visit.exitLineNumber(this);
111 }
112
113 public int compareTo(Object other) {
114 if (!(other instanceof LineNumber))
115 return -1;
116
117 LineNumber ln = (LineNumber) other;
118 if (getStartPc() == ln.getStartPc())
119 return 0;
120 if (getStartPc() < ln.getStartPc())
121 return -1;
122 return 1;
123 }
124
125 void read(DataInput in) throws IOException {
126 setStartPc(in.readUnsignedShort());
127 setLine(in.readUnsignedShort());
128 }
129
130 void write(DataOutput out) throws IOException {
131 out.writeShort(getStartPc());
132 out.writeShort(getLine());
133 }
134
135 public Code getCode() {
136 return _owner.getCode();
137 }
138 }