KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > bytecode > SourceDebugExtAttr


1 // Copyright (c) 2004 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.bytecode;
5
6 /**
7   * Represents the contents of a JSR-45 "SourceDebugExtension" attribute.
8   * We only support generating a single "stratum".
9   */

10
11 public class SourceDebugExtAttr extends Attribute
12 {
13   byte[] data;
14   int dlength;
15
16   private String JavaDoc outputFileName;
17   private String JavaDoc defaultStratumId;
18
19   /** Number of files in the <code>FileSection</code>. The active (used)
20    * length of the <code>fileNames</code> and <code>fileIDs</code> arrays. */

21   int fileCount;
22   /** For each entry in the <code>FileSection</code>:
23    * <code>2*id+with_path</code>.
24    * The <code>id</code> is the <code>FileID</code> written in the SMAP;
25    * the <code>with_path</code> is 1 if we also write the full path. */

26   int[] fileIDs;
27   /** For eachentry its <code>FileName</code>.
28    * If the <code>with_path</code> bit is set,
29    * <code>FileName '\n' AbsoluteFileName</code>. */

30   String JavaDoc[] fileNames;
31
32   int lineCount;
33   /** A table of LineInfo entries. */
34   int[] lines;
35
36   //int curMinLine; int curMaxLine; int curLineAdjust;
37
int curLineIndex = -1;
38   int curFileIndex = -1;
39   int maxFileID;
40   String JavaDoc curFileName;
41
42   private int fixLine (int sourceLine, int index)
43   {
44     int sourceMin = lines[index];
45     int repeat = lines[index+2];
46     if (sourceLine < sourceMin)
47       {
48     if (index > 0)
49       return -1;
50     int sourceMax = sourceMin + repeat - 1;
51     lines[index] = sourceLine;
52     lines[index+2] = sourceMax - sourceLine + 1;
53     lines[index+3] = sourceLine;
54     sourceMin = sourceLine;
55       }
56     int delta = lines[index+3] - sourceMin;
57     if (sourceLine < sourceMin + repeat)
58       return sourceLine + delta;
59     else if (index == 5 * (lineCount - 1)
60          || (index == 0 && sourceLine < lines[5+3]))
61       { // If last LineInfo entry, we can "extend" its range.
62
lines[index+2] = sourceLine - sourceMin + 1; // Fix RepeatCount.
63
return sourceLine + delta;
64       }
65     return -1;
66   }
67
68   int fixLine (int sourceLine)
69   {
70     int outLine;
71     if (curLineIndex >= 0)
72       {
73     outLine = fixLine(sourceLine, curLineIndex);
74     if (outLine >= 0)
75       return outLine;
76       }
77     int i5 = 0;
78     int findex = curFileIndex;
79     for (int i = 0; i < lineCount; i++)
80       {
81     if (i5 != curLineIndex && findex == lines[i5+1])
82       {
83         outLine = fixLine(sourceLine, i5);
84         if (outLine >= 0)
85           {
86         curLineIndex = i5;
87         return outLine;
88           }
89       }
90     i5 += 5;
91       }
92     if (lines == null)
93       lines = new int[20];
94     else if (i5 >= lines.length)
95       {
96     int[] newLines = new int[2 * i5];
97     System.arraycopy(lines, 0, newLines, 0, i5);
98     lines = newLines;
99       }
100     int outputStartLine;
101     int inputStartLine = sourceLine;
102     if (i5 == 0)
103       outputStartLine = sourceLine;
104     else
105       {
106     outputStartLine = lines[i5-5+3] + lines[i5-5+2];
107     if (i5 == 5 && outputStartLine < 10000)
108       {
109         // Reserve the first 10k lines for the main file.
110
// This is for the sake of non-JSR-45-capable tools.
111
outputStartLine = 10000;
112       }
113     sourceLine = outputStartLine;
114       }
115     lines[i5] = inputStartLine;
116     lines[i5+1] = findex;
117     lines[i5+2] = 1;
118     lines[i5+3] = outputStartLine;
119     lines[i5+4] = 1;
120     curLineIndex = i5;
121     lineCount++;
122     return sourceLine;
123   }
124
125   void addFile (String JavaDoc fname)
126   {
127     if (curFileName == fname || (fname != null && fname.equals(curFileName)))
128       return;
129     curFileName = fname;
130     fname = SourceFileAttr.fixSourceFile(fname);
131     String JavaDoc fentry;
132     int slash = fname.lastIndexOf('/');
133     if (slash >= 0)
134       {
135     String JavaDoc fpath = fname;
136     fname = fname.substring(slash+1);
137     fentry = fname + '\n' + fpath;
138       }
139     else
140       fentry = fname;
141
142     if (curFileIndex >= 0 && fentry.equals(fileNames[curFileIndex]))
143       return;
144     
145     int n = fileCount;
146     for (int i = 0; i < n; i++)
147       {
148     if (i != curFileIndex && fentry.equals(fileNames[i]))
149       {
150         curFileIndex = i;
151         curLineIndex = -1;
152         return;
153       }
154       }
155
156     if (fileIDs == null)
157       {
158     fileIDs = new int[5];
159     fileNames = new String JavaDoc[5];
160       }
161     else if (n >= fileIDs.length)
162       {
163     int[] newIDs = new int[2 * n];
164     String JavaDoc[] newNames = new String JavaDoc[2 * n];
165     System.arraycopy(fileIDs, 0, newIDs, 0, n);
166     System.arraycopy(fileNames, 0, newNames, 0, n);
167     fileIDs = newIDs;
168     fileNames = newNames;
169       }
170
171
172     fileCount++;
173     int id = ++maxFileID;
174     id = id << 1;
175     if (slash >= 0)
176       id++;
177     fileNames[n] = fentry;
178     if (outputFileName == null)
179       outputFileName = fname;
180     fileIDs[n] = id;
181     curFileIndex = n;
182     curLineIndex = -1;
183   }
184
185   public void addStratum (String JavaDoc name)
186   {
187     defaultStratumId = name;
188   }
189
190   /** Add a new InnerClassesAttr to a ClassType. */
191   public SourceDebugExtAttr (ClassType cl)
192   {
193     super("SourceDebugExtension");
194     addToFrontOf(cl);
195   }
196
197   void nonAsteriskString(String JavaDoc str, StringBuffer JavaDoc sbuf)
198   {
199     if (str == null || str.length() == 0 || str.charAt(0) == '*')
200       sbuf.append(' ');
201     sbuf.append(str);
202   }
203
204   public void assignConstants (ClassType cl)
205   {
206     super.assignConstants(cl);
207
208     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
209     // Append SMAP Header:
210
sbuf.append("SMAP\n");
211     nonAsteriskString(outputFileName, sbuf); sbuf.append('\n');
212     String JavaDoc stratum = defaultStratumId == null ? "Java" : defaultStratumId;
213     nonAsteriskString(stratum, sbuf);
214     sbuf.append('\n');
215     // Append StratumSection.
216
sbuf.append("*S ");
217     sbuf.append(stratum);
218     sbuf.append('\n');
219     // Append FileSection:
220
sbuf.append("*F\n");
221     for (int i = 0; i < fileCount; i++)
222       {
223     int id = fileIDs[i];
224     boolean with_path = (id & 1) != 0;
225     id >>= 1;
226     if (with_path)
227       sbuf.append("+ ");
228     sbuf.append(id); sbuf.append(' ');
229     sbuf.append(fileNames[i]); sbuf.append('\n');
230       }
231     // Append LineSection:
232
if (lineCount > 0)
233       {
234     int prevFileID = 0;
235     sbuf.append("*L\n");
236     int i = 0, i5 = 0;
237     do
238       {
239         int inputStartLine = lines[i5];
240         int lineFileID = fileIDs[lines[i5+1]] >> 1;
241         int repeatCount = lines[i5+2];
242         int outputStartLine = lines[i5+3];
243         int outputLineIncrement = lines[i5+4];
244         sbuf.append(inputStartLine);
245         if (lineFileID != prevFileID)
246           {
247         sbuf.append('#');
248         sbuf.append(lineFileID);
249         prevFileID = lineFileID;
250           }
251         if (repeatCount != 1)
252           {
253         sbuf.append(',');
254         sbuf.append(repeatCount);
255           }
256         sbuf.append(':');
257         sbuf.append(outputStartLine);
258         if (outputLineIncrement != 1)
259           {
260         sbuf.append(',');
261         sbuf.append(outputLineIncrement);
262           }
263         sbuf.append('\n');
264         i5 += 5;
265       }
266     while (++i < lineCount);
267       }
268     // Append EndSection:
269
sbuf.append("*E\n");
270     try
271       {
272     data = sbuf.toString().getBytes("UTF-8");
273       }
274     catch (Exception JavaDoc ex)
275       {
276     throw new RuntimeException JavaDoc(ex.toString());
277       }
278     dlength = data.length;
279   }
280
281   /** Return the length of the attribute in bytes.
282     * Does not include the 6-byte header (for the name_index and the length).*/

283     public int getLength() { return dlength; }
284
285   /** Write out the contents of the Attribute.
286     * Does not write the 6-byte attribute header. */

287   public void write (java.io.DataOutputStream JavaDoc dstr)
288     throws java.io.IOException JavaDoc
289   {
290     dstr.write(data, 0, dlength);
291   }
292
293   public void print (ClassTypeWriter dst)
294   {
295     dst.print("Attribute \"");
296     dst.print(getName());
297     dst.print("\", length:");
298     dst.println(dlength);
299     try
300       {
301     dst.print(new String JavaDoc(data, 0, dlength, "UTF-8"));
302       }
303     catch (Exception JavaDoc ex)
304       {
305     dst.print("(Caught "); dst.print(ex); dst.println(')');
306       }
307     if (dlength > 0 && data[dlength-1] != '\r' && data[dlength-1]!= '\n')
308       dst.println();
309   }
310 }
311
Popular Tags