1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 package proguard.classfile.attribute;
22 
23 import proguard.classfile.*;
24 import proguard.classfile.attribute.visitor.*;
25 
26 /**
27  * This Attribute represents a line number table attribute.
28  *
29  * @author Eric Lafortune
30  */
31 public class LineNumberTableAttribute extends Attribute
32 {
33     public int              u2lineNumberTableLength;
34     public LineNumberInfo[] lineNumberTable;
35 
36 
37     /**
38      * Creates an uninitialized LineNumberTableAttribute.
39      */
LineNumberTableAttribute()40     public LineNumberTableAttribute()
41     {
42     }
43 
44 
45     /**
46      * Creates an initialized LineNumberTableAttribute.
47      */
LineNumberTableAttribute(int u2attributeNameIndex, int u2lineNumberTableLength, LineNumberInfo[] lineNumberTable)48     public LineNumberTableAttribute(int              u2attributeNameIndex,
49                                     int              u2lineNumberTableLength,
50                                     LineNumberInfo[] lineNumberTable)
51     {
52         super(u2attributeNameIndex);
53 
54         this.u2lineNumberTableLength = u2lineNumberTableLength;
55         this.lineNumberTable         = lineNumberTable;
56     }
57 
58 
59     /**
60      * Returns the line number corresponding to the given byte code program
61      * counter.
62      */
getLineNumber(int pc)63     public int getLineNumber(int pc)
64     {
65         for (int index = u2lineNumberTableLength-1 ; index >= 0 ; index--)
66         {
67             LineNumberInfo info = lineNumberTable[index];
68             if (pc >= info.u2startPC)
69             {
70                 return info.u2lineNumber;
71             }
72         }
73 
74         return u2lineNumberTableLength > 0 ?
75             lineNumberTable[0].u2lineNumber :
76             0;
77     }
78 
79 
80     /**
81      * Returns the lowest line number, or 0 if there aren't any line numbers.
82      */
getLowestLineNumber()83     public int getLowestLineNumber()
84     {
85         if (u2lineNumberTableLength == 0)
86         {
87             return 0;
88         }
89 
90         int lowestLineNumber = Integer.MAX_VALUE;
91 
92         for (int index = 0; index < u2lineNumberTableLength; index++)
93         {
94             int lineNumber = lineNumberTable[index].u2lineNumber;
95             if (lineNumber < lowestLineNumber)
96             {
97                 lowestLineNumber = lineNumber;
98             }
99         }
100 
101         return lowestLineNumber;
102     }
103 
104 
105     /**
106      * Returns the highest line number, or 0 if there aren't any line numbers.
107      */
getHighestLineNumber()108     public int getHighestLineNumber()
109     {
110         if (u2lineNumberTableLength == 0)
111         {
112             return 0;
113         }
114 
115         int highestLineNumber = Integer.MIN_VALUE;
116 
117         for (int index = 0; index < u2lineNumberTableLength; index++)
118         {
119             int lineNumber = lineNumberTable[index].u2lineNumber;
120             if (lineNumber > highestLineNumber)
121             {
122                 highestLineNumber = lineNumber;
123             }
124         }
125 
126         return highestLineNumber;
127     }
128 
129 
130     // Implementations for Attribute.
131 
accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)132     public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
133     {
134         attributeVisitor.visitLineNumberTableAttribute(clazz, method, codeAttribute, this);
135     }
136 
137 
138     /**
139      * Applies the given visitor to all line numbers.
140      */
lineNumbersAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfoVisitor lineNumberInfoVisitor)141     public void lineNumbersAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfoVisitor lineNumberInfoVisitor)
142     {
143         for (int index = 0; index < u2lineNumberTableLength; index++)
144         {
145             // We don't need double dispatching here, since there is only one
146             // type of LineNumberInfo.
147             lineNumberInfoVisitor.visitLineNumberInfo(clazz, method, codeAttribute, lineNumberTable[index]);
148         }
149     }
150 }
151