1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  *    contributors may be used to endorse or promote products derived from
16  *    this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 package org.objectweb.asm.util;
31 
32 import org.objectweb.asm.AnnotationVisitor;
33 import org.objectweb.asm.MethodVisitor;
34 import org.objectweb.asm.Label;
35 import org.objectweb.asm.Opcodes;
36 
37 import java.util.HashMap;
38 
39 /**
40  * A {@link MethodVisitor} that prints the ASM code that generates the methods
41  * it visits.
42  *
43  * @author Eric Bruneton
44  * @author Eugene Kuleshov
45  */
46 public class ASMifierMethodVisitor extends ASMifierAbstractVisitor implements
47         MethodVisitor
48 {
49 
50     /**
51      * Constructs a new {@link ASMifierMethodVisitor} object.
52      */
ASMifierMethodVisitor()53     public ASMifierMethodVisitor() {
54         super("mv");
55         this.labelNames = new HashMap();
56     }
57 
visitAnnotationDefault()58     public AnnotationVisitor visitAnnotationDefault() {
59         buf.setLength(0);
60         buf.append("{\n").append("av0 = mv.visitAnnotationDefault();\n");
61         text.add(buf.toString());
62         ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
63         text.add(av.getText());
64         text.add("}\n");
65         return av;
66     }
67 
visitParameterAnnotation( final int parameter, final String desc, final boolean visible)68     public AnnotationVisitor visitParameterAnnotation(
69         final int parameter,
70         final String desc,
71         final boolean visible)
72     {
73         buf.setLength(0);
74         buf.append("{\n")
75                 .append("av0 = mv.visitParameterAnnotation(")
76                 .append(parameter)
77                 .append(", ");
78         appendConstant(desc);
79         buf.append(", ").append(visible).append(");\n");
80         text.add(buf.toString());
81         ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
82         text.add(av.getText());
83         text.add("}\n");
84         return av;
85     }
86 
visitCode()87     public void visitCode() {
88         text.add("mv.visitCode();\n");
89     }
90 
visitInsn(final int opcode)91     public void visitInsn(final int opcode) {
92         buf.setLength(0);
93         buf.append("mv.visitInsn(").append(OPCODES[opcode]).append(");\n");
94         text.add(buf.toString());
95     }
96 
visitIntInsn(final int opcode, final int operand)97     public void visitIntInsn(final int opcode, final int operand) {
98         buf.setLength(0);
99         buf.append("mv.visitIntInsn(")
100                 .append(OPCODES[opcode])
101                 .append(", ")
102                 .append(opcode == Opcodes.NEWARRAY
103                         ? TYPES[operand]
104                         : Integer.toString(operand))
105                 .append(");\n");
106         text.add(buf.toString());
107     }
108 
visitVarInsn(final int opcode, final int var)109     public void visitVarInsn(final int opcode, final int var) {
110         buf.setLength(0);
111         buf.append("mv.visitVarInsn(")
112                 .append(OPCODES[opcode])
113                 .append(", ")
114                 .append(var)
115                 .append(");\n");
116         text.add(buf.toString());
117     }
118 
visitTypeInsn(final int opcode, final String desc)119     public void visitTypeInsn(final int opcode, final String desc) {
120         buf.setLength(0);
121         buf.append("mv.visitTypeInsn(").append(OPCODES[opcode]).append(", ");
122         appendConstant(desc);
123         buf.append(");\n");
124         text.add(buf.toString());
125     }
126 
visitFieldInsn( final int opcode, final String owner, final String name, final String desc)127     public void visitFieldInsn(
128         final int opcode,
129         final String owner,
130         final String name,
131         final String desc)
132     {
133         buf.setLength(0);
134         buf.append("mv.visitFieldInsn(").append(OPCODES[opcode]).append(", ");
135         appendConstant(owner);
136         buf.append(", ");
137         appendConstant(name);
138         buf.append(", ");
139         appendConstant(desc);
140         buf.append(");\n");
141         text.add(buf.toString());
142     }
143 
visitMethodInsn( final int opcode, final String owner, final String name, final String desc)144     public void visitMethodInsn(
145         final int opcode,
146         final String owner,
147         final String name,
148         final String desc)
149     {
150         buf.setLength(0);
151         buf.append("mv.visitMethodInsn(").append(OPCODES[opcode]).append(", ");
152         appendConstant(owner);
153         buf.append(", ");
154         appendConstant(name);
155         buf.append(", ");
156         appendConstant(desc);
157         buf.append(");\n");
158         text.add(buf.toString());
159     }
160 
visitJumpInsn(final int opcode, final Label label)161     public void visitJumpInsn(final int opcode, final Label label) {
162         buf.setLength(0);
163         declareLabel(label);
164         buf.append("mv.visitJumpInsn(").append(OPCODES[opcode]).append(", ");
165         appendLabel(label);
166         buf.append(");\n");
167         text.add(buf.toString());
168     }
169 
visitLabel(final Label label)170     public void visitLabel(final Label label) {
171         buf.setLength(0);
172         declareLabel(label);
173         buf.append("mv.visitLabel(");
174         appendLabel(label);
175         buf.append(");\n");
176         text.add(buf.toString());
177     }
178 
visitLdcInsn(final Object cst)179     public void visitLdcInsn(final Object cst) {
180         buf.setLength(0);
181         buf.append("mv.visitLdcInsn(");
182         appendConstant(cst);
183         buf.append(");\n");
184         text.add(buf.toString());
185     }
186 
visitIincInsn(final int var, final int increment)187     public void visitIincInsn(final int var, final int increment) {
188         buf.setLength(0);
189         buf.append("mv.visitIincInsn(")
190                 .append(var)
191                 .append(", ")
192                 .append(increment)
193                 .append(");\n");
194         text.add(buf.toString());
195     }
196 
visitTableSwitchInsn( final int min, final int max, final Label dflt, final Label labels[])197     public void visitTableSwitchInsn(
198         final int min,
199         final int max,
200         final Label dflt,
201         final Label labels[])
202     {
203         buf.setLength(0);
204         for (int i = 0; i < labels.length; ++i) {
205             declareLabel(labels[i]);
206         }
207         declareLabel(dflt);
208 
209         buf.append("mv.visitTableSwitchInsn(")
210                 .append(min)
211                 .append(", ")
212                 .append(max)
213                 .append(", ");
214         appendLabel(dflt);
215         buf.append(", new Label[] {");
216         for (int i = 0; i < labels.length; ++i) {
217             buf.append(i == 0 ? " " : ", ");
218             appendLabel(labels[i]);
219         }
220         buf.append(" });\n");
221         text.add(buf.toString());
222     }
223 
visitLookupSwitchInsn( final Label dflt, final int keys[], final Label labels[])224     public void visitLookupSwitchInsn(
225         final Label dflt,
226         final int keys[],
227         final Label labels[])
228     {
229         buf.setLength(0);
230         for (int i = 0; i < labels.length; ++i) {
231             declareLabel(labels[i]);
232         }
233         declareLabel(dflt);
234 
235         buf.append("mv.visitLookupSwitchInsn(");
236         appendLabel(dflt);
237         buf.append(", new int[] {");
238         for (int i = 0; i < keys.length; ++i) {
239             buf.append(i == 0 ? " " : ", ").append(keys[i]);
240         }
241         buf.append(" }, new Label[] {");
242         for (int i = 0; i < labels.length; ++i) {
243             buf.append(i == 0 ? " " : ", ");
244             appendLabel(labels[i]);
245         }
246         buf.append(" });\n");
247         text.add(buf.toString());
248     }
249 
visitMultiANewArrayInsn(final String desc, final int dims)250     public void visitMultiANewArrayInsn(final String desc, final int dims) {
251         buf.setLength(0);
252         buf.append("mv.visitMultiANewArrayInsn(");
253         appendConstant(desc);
254         buf.append(", ").append(dims).append(");\n");
255         text.add(buf.toString());
256     }
257 
visitTryCatchBlock( final Label start, final Label end, final Label handler, final String type)258     public void visitTryCatchBlock(
259         final Label start,
260         final Label end,
261         final Label handler,
262         final String type)
263     {
264         buf.setLength(0);
265         declareLabel(start);
266         declareLabel(end);
267         declareLabel(handler);
268         buf.append("mv.visitTryCatchBlock(");
269         appendLabel(start);
270         buf.append(", ");
271         appendLabel(end);
272         buf.append(", ");
273         appendLabel(handler);
274         buf.append(", ");
275         appendConstant(type);
276         buf.append(");\n");
277         text.add(buf.toString());
278     }
279 
visitLocalVariable( final String name, final String desc, final String signature, final Label start, final Label end, final int index)280     public void visitLocalVariable(
281         final String name,
282         final String desc,
283         final String signature,
284         final Label start,
285         final Label end,
286         final int index)
287     {
288         buf.setLength(0);
289         buf.append("mv.visitLocalVariable(");
290         appendConstant(name);
291         buf.append(", ");
292         appendConstant(desc);
293         buf.append(", ");
294         appendConstant(signature);
295         buf.append(", ");
296         appendLabel(start);
297         buf.append(", ");
298         appendLabel(end);
299         buf.append(", ").append(index).append(");\n");
300         text.add(buf.toString());
301     }
302 
visitLineNumber(final int line, final Label start)303     public void visitLineNumber(final int line, final Label start) {
304         buf.setLength(0);
305         buf.append("mv.visitLineNumber(").append(line).append(", ");
306         appendLabel(start);
307         buf.append(");\n");
308         text.add(buf.toString());
309     }
310 
visitMaxs(final int maxStack, final int maxLocals)311     public void visitMaxs(final int maxStack, final int maxLocals) {
312         buf.setLength(0);
313         buf.append("mv.visitMaxs(")
314                 .append(maxStack)
315                 .append(", ")
316                 .append(maxLocals)
317                 .append(");\n");
318         text.add(buf.toString());
319     }
320 
321     /**
322      * Appends a declaration of the given label to {@link #buf buf}. This
323      * declaration is of the form "Label lXXX = new Label();". Does nothing if
324      * the given label has already been declared.
325      *
326      * @param l a label.
327      */
declareLabel(final Label l)328     private void declareLabel(final Label l) {
329         String name = (String) labelNames.get(l);
330         if (name == null) {
331             name = "l" + labelNames.size();
332             labelNames.put(l, name);
333             buf.append("Label ").append(name).append(" = new Label();\n");
334         }
335     }
336 
337     /**
338      * Appends the name of the given label to {@link #buf buf}. The given label
339      * <i>must</i> already have a name. One way to ensure this is to always
340      * call {@link #declareLabel declared} before calling this method.
341      *
342      * @param l a label.
343      */
appendLabel(final Label l)344     private void appendLabel(final Label l) {
345         buf.append((String) labelNames.get(l));
346     }
347 }
348