1 package serp.bytecode;
2
3 import java.io.*;
4 import java.util.*;
5
6 import serp.bytecode.visitor.*;
7
8
9
10
11
12
13
14
15
16 public class LineNumberTable extends Attribute implements InstructionPtr {
17 private List _lineNumbers = new ArrayList();
18
19 LineNumberTable(int nameIndex, Attributes owner) {
20 super(nameIndex, owner);
21 }
22
23
24
25
26 public LineNumber[] getLineNumbers() {
27 Collections.sort(_lineNumbers);
28 return (LineNumber[]) _lineNumbers.toArray
29 (new LineNumber[_lineNumbers.size()]);
30 }
31
32
33
34
35 public LineNumber getLineNumber(int pc) {
36 for (int i = _lineNumbers.size() - 1; i >= 0; i--)
37 if (((LineNumber) _lineNumbers.get(i))._target.getByteIndex() <= pc)
38 return (LineNumber) _lineNumbers.get(i);
39 return null;
40 }
41
42
43
44
45 public LineNumber getLineNumber(Instruction ins) {
46 if (ins == null)
47 return null;
48 return getLineNumber(ins.getByteIndex());
49 }
50
51
52
53
54
55 public void setLineNumbers(LineNumber[] lines) {
56 clear();
57 if (lines != null)
58 for (int i = 0; i < lines.length; i++)
59 addLineNumber(lines[i]);
60 }
61
62
63
64
65
66
67 public LineNumber addLineNumber(LineNumber ln) {
68 LineNumber line = addLineNumber();
69 line.setStartPc(ln.getStartPc());
70 line.setLine(ln.getLine());
71 return line;
72 }
73
74
75
76
77 public LineNumber addLineNumber() {
78 LineNumber ln = new LineNumber(this);
79 _lineNumbers.add(ln);
80 return ln;
81 }
82
83
84
85
86 public LineNumber addLineNumber(int startPc, int line) {
87 LineNumber ln = addLineNumber();
88 ln.setStartPc(startPc);
89 ln.setLine(line);
90 return ln;
91 }
92
93
94
95
96 public LineNumber addLineNumber(Instruction start, int line) {
97 LineNumber ln = addLineNumber();
98 ln.setStart(start);
99 ln.setLine(line);
100 return ln;
101 }
102
103
104
105
106 public void clear() {
107 for (int i = 0; i < _lineNumbers.size(); i++)
108 ((LineNumber) _lineNumbers.get(i)).invalidate();
109 _lineNumbers.clear();
110 }
111
112
113
114
115
116
117 public boolean removeLineNumber(LineNumber ln) {
118 if (ln == null || !_lineNumbers.remove(ln))
119 return false;
120 ln.invalidate();
121 return true;
122 }
123
124
125
126
127
128
129 public boolean removeLineNumber(int pc) {
130 return removeLineNumber(getLineNumber(pc));
131 }
132
133
134
135
136
137
138 public boolean removeLineNumber(Instruction ins) {
139 return removeLineNumber(getLineNumber(ins));
140 }
141
142 public void updateTargets() {
143 for (int i = 0; i < _lineNumbers.size(); i++)
144 ((LineNumber) _lineNumbers.get(i)).updateTargets();
145 }
146
147 public void replaceTarget(Instruction oldTarget, Instruction newTarget) {
148 for (int i = 0; i < _lineNumbers.size(); i++)
149 ((LineNumber) _lineNumbers.get(i)).replaceTarget(oldTarget,
150 newTarget);
151 }
152
153 public void acceptVisit(BCVisitor visit) {
154 visit.enterLineNumberTable(this);
155 LineNumber[] lines = getLineNumbers();
156 for (int i = 0; i < lines.length; i++)
157 lines[i].acceptVisit(visit);
158 visit.exitLineNumberTable(this);
159 }
160
161 int getLength() {
162 return 2 + (4 * _lineNumbers.size());
163 }
164
165 void read(Attribute other) {
166 setLineNumbers(((LineNumberTable) other).getLineNumbers());
167 }
168
169 void read(DataInput in, int length) throws IOException {
170 clear();
171 int numLines = in.readUnsignedShort();
172 LineNumber lineNumber;
173 for (int i = 0; i < numLines; i++) {
174 lineNumber = addLineNumber();
175 lineNumber.read(in);
176 }
177 }
178
179 void write(DataOutput out, int length) throws IOException {
180 LineNumber[] lines = getLineNumbers();
181 out.writeShort(lines.length);
182 for (int i = 0; i < lines.length; i++)
183 lines[i].write(out);
184 }
185
186 public Code getCode() {
187 return (Code) getOwner();
188 }
189 }