1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2009 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 */
21package proguard.classfile.attribute;
22
23import proguard.classfile.*;
24import proguard.classfile.attribute.visitor.*;
25import proguard.classfile.instruction.*;
26import proguard.classfile.instruction.visitor.InstructionVisitor;
27
28/**
29 * This Attribute represents a code attribute.
30 *
31 * @author Eric Lafortune
32 */
33public class CodeAttribute extends Attribute
34{
35    public int             u2maxStack;
36    public int             u2maxLocals;
37    public int             u4codeLength;
38    public byte[]          code;
39    public int             u2exceptionTableLength;
40    public ExceptionInfo[] exceptionTable;
41    public int             u2attributesCount;
42    public Attribute[]     attributes;
43
44
45    /**
46     * Creates an uninitialized CodeAttribute.
47     */
48    public CodeAttribute()
49    {
50    }
51
52
53    /**
54     * Creates an initialized CodeAttribute.
55     */
56    public CodeAttribute(int             u2attributeNameIndex,
57                         int             u2maxStack,
58                         int             u2maxLocals,
59                         int             u4codeLength,
60                         byte[]          code,
61                         int             u2exceptionTableLength,
62                         ExceptionInfo[] exceptionTable,
63                         int             u2attributesCount,
64                         Attribute[]     attributes)
65    {
66        super(u2attributeNameIndex);
67
68        this.u2maxStack             = u2maxStack;
69        this.u2maxLocals            = u2maxLocals;
70        this.u4codeLength           = u4codeLength;
71        this.code                   = code;
72        this.u2exceptionTableLength = u2exceptionTableLength;
73        this.exceptionTable         = exceptionTable;
74        this.u2attributesCount      = u2attributesCount;
75        this.attributes             = attributes;
76    }
77
78
79    /**
80     * Returns the (first) attribute with the given name.
81     */
82    public Attribute getAttribute(Clazz clazz, String name)
83    {
84        for (int index = 0; index < u2attributesCount; index++)
85        {
86            Attribute attribute = attributes[index];
87            if (attribute.getAttributeName(clazz).equals(name))
88            {
89                return attribute;
90            }
91        }
92
93        return null;
94    }
95
96
97    // Implementations for Attribute.
98
99    public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
100    {
101        attributeVisitor.visitCodeAttribute(clazz, method, this);
102    }
103
104
105    /**
106     * Applies the given instruction visitor to all instructions.
107     */
108    public void instructionsAccept(Clazz clazz, Method method, InstructionVisitor instructionVisitor)
109    {
110        instructionsAccept(clazz, method, 0, u4codeLength, instructionVisitor);
111    }
112
113
114    /**
115     * Applies the given instruction visitor to the instruction at the specified
116     * offset.
117     */
118    public void instructionAccept(Clazz clazz, Method method, int offset, InstructionVisitor instructionVisitor)
119    {
120        Instruction instruction = InstructionFactory.create(code, offset);
121        instruction.accept(clazz, method, this, offset, instructionVisitor);
122    }
123
124
125    /**
126     * Applies the given instruction visitor to all instructions in the
127     * specified range of offsets.
128     */
129    public void instructionsAccept(Clazz clazz, Method method, int startOffset, int endOffset, InstructionVisitor instructionVisitor)
130    {
131        int offset = startOffset;
132
133        while (offset < endOffset)
134        {
135            // Note that the instruction is only volatile.
136            Instruction instruction = InstructionFactory.create(code, offset);
137            int instructionLength = instruction.length(offset);
138            instruction.accept(clazz, method, this, offset, instructionVisitor);
139            offset += instructionLength;
140        }
141    }
142
143
144    /**
145     * Applies the given exception visitor to all exceptions.
146     */
147    public void exceptionsAccept(Clazz clazz, Method method, ExceptionInfoVisitor exceptionInfoVisitor)
148    {
149        for (int index = 0; index < u2exceptionTableLength; index++)
150        {
151            // We don't need double dispatching here, since there is only one
152            // type of ExceptionInfo.
153            exceptionInfoVisitor.visitExceptionInfo(clazz, method, this, exceptionTable[index]);
154        }
155    }
156
157
158    /**
159     * Applies the given exception visitor to all exceptions that are applicable
160     * to the instruction at the specified offset.
161     */
162    public void exceptionsAccept(Clazz clazz, Method method, int offset, ExceptionInfoVisitor exceptionInfoVisitor)
163    {
164        for (int index = 0; index < u2exceptionTableLength; index++)
165        {
166            ExceptionInfo exceptionInfo = exceptionTable[index];
167            if (exceptionInfo.isApplicable(offset))
168            {
169                exceptionInfoVisitor.visitExceptionInfo(clazz, method, this, exceptionInfo);
170            }
171        }
172    }
173
174
175    /**
176     * Applies the given exception visitor to all exceptions that are applicable
177     * to any of the instructions in the specified range of offsets.
178     */
179    public void exceptionsAccept(Clazz clazz, Method method, int startOffset, int endOffset, ExceptionInfoVisitor exceptionInfoVisitor)
180    {
181        for (int index = 0; index < u2exceptionTableLength; index++)
182        {
183            ExceptionInfo exceptionInfo = exceptionTable[index];
184            if (exceptionInfo.isApplicable(startOffset, endOffset))
185            {
186                exceptionInfoVisitor.visitExceptionInfo(clazz, method, this, exceptionInfo);
187            }
188        }
189    }
190
191
192    /**
193     * Applies the given attribute visitor to all attributes.
194     */
195    public void attributesAccept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
196    {
197        for (int index = 0; index < u2attributesCount; index++)
198        {
199            attributes[index].accept(clazz, method, this, attributeVisitor);
200        }
201    }
202}
203