001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package com.uwyn.rife.asm.util;
030:
031: import com.uwyn.rife.asm.AnnotationVisitor;
032: import com.uwyn.rife.asm.MethodVisitor;
033: import com.uwyn.rife.asm.Label;
034: import com.uwyn.rife.asm.Opcodes;
035:
036: import java.util.HashMap;
037:
038: /**
039: * A {@link MethodVisitor} that prints the ASM code that generates the methods
040: * it visits.
041: *
042: * @author Eric Bruneton
043: * @author Eugene Kuleshov
044: */
045: public class ASMifierMethodVisitor extends ASMifierAbstractVisitor
046: implements MethodVisitor {
047:
048: /**
049: * Constructs a new {@link ASMifierMethodVisitor} object.
050: */
051: public ASMifierMethodVisitor() {
052: super ("mv");
053: this .labelNames = new HashMap();
054: }
055:
056: public AnnotationVisitor visitAnnotationDefault() {
057: buf.setLength(0);
058: buf.append("{\n")
059: .append("av0 = mv.visitAnnotationDefault();\n");
060: text.add(buf.toString());
061: ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
062: text.add(av.getText());
063: text.add("}\n");
064: return av;
065: }
066:
067: public AnnotationVisitor visitParameterAnnotation(
068: final int parameter, final String desc,
069: final boolean visible) {
070: buf.setLength(0);
071: buf.append("{\n").append("av0 = mv.visitParameterAnnotation(")
072: .append(parameter).append(", ");
073: appendConstant(desc);
074: buf.append(", ").append(visible).append(");\n");
075: text.add(buf.toString());
076: ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
077: text.add(av.getText());
078: text.add("}\n");
079: return av;
080: }
081:
082: public void visitCode() {
083: text.add("mv.visitCode();\n");
084: }
085:
086: public void visitInsn(final int opcode) {
087: buf.setLength(0);
088: buf.append("mv.visitInsn(").append(OPCODES[opcode]).append(
089: ");\n");
090: text.add(buf.toString());
091: }
092:
093: public void visitIntInsn(final int opcode, final int operand) {
094: buf.setLength(0);
095: buf.append("mv.visitIntInsn(").append(OPCODES[opcode]).append(
096: ", ").append(
097: opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
098: .toString(operand)).append(");\n");
099: text.add(buf.toString());
100: }
101:
102: public void visitVarInsn(final int opcode, final int var) {
103: buf.setLength(0);
104: buf.append("mv.visitVarInsn(").append(OPCODES[opcode]).append(
105: ", ").append(var).append(");\n");
106: text.add(buf.toString());
107: }
108:
109: public void visitTypeInsn(final int opcode, final String desc) {
110: buf.setLength(0);
111: buf.append("mv.visitTypeInsn(").append(OPCODES[opcode]).append(
112: ", ");
113: appendConstant(desc);
114: buf.append(");\n");
115: text.add(buf.toString());
116: }
117:
118: public void visitFieldInsn(final int opcode, final String owner,
119: final String name, final String desc) {
120: buf.setLength(0);
121: buf.append("mv.visitFieldInsn(").append(OPCODES[opcode])
122: .append(", ");
123: appendConstant(owner);
124: buf.append(", ");
125: appendConstant(name);
126: buf.append(", ");
127: appendConstant(desc);
128: buf.append(");\n");
129: text.add(buf.toString());
130: }
131:
132: public void visitMethodInsn(final int opcode, final String owner,
133: final String name, final String desc) {
134: buf.setLength(0);
135: buf.append("mv.visitMethodInsn(").append(OPCODES[opcode])
136: .append(", ");
137: appendConstant(owner);
138: buf.append(", ");
139: appendConstant(name);
140: buf.append(", ");
141: appendConstant(desc);
142: buf.append(");\n");
143: text.add(buf.toString());
144: }
145:
146: public void visitJumpInsn(final int opcode, final Label label) {
147: buf.setLength(0);
148: declareLabel(label);
149: buf.append("mv.visitJumpInsn(").append(OPCODES[opcode]).append(
150: ", ");
151: appendLabel(label);
152: buf.append(");\n");
153: text.add(buf.toString());
154: }
155:
156: public void visitLabel(final Label label) {
157: buf.setLength(0);
158: declareLabel(label);
159: buf.append("mv.visitLabel(");
160: appendLabel(label);
161: buf.append(");\n");
162: text.add(buf.toString());
163: }
164:
165: public void visitLdcInsn(final Object cst) {
166: buf.setLength(0);
167: buf.append("mv.visitLdcInsn(");
168: appendConstant(cst);
169: buf.append(");\n");
170: text.add(buf.toString());
171: }
172:
173: public void visitIincInsn(final int var, final int increment) {
174: buf.setLength(0);
175: buf.append("mv.visitIincInsn(").append(var).append(", ")
176: .append(increment).append(");\n");
177: text.add(buf.toString());
178: }
179:
180: public void visitTableSwitchInsn(final int min, final int max,
181: final Label dflt, final Label labels[]) {
182: buf.setLength(0);
183: for (int i = 0; i < labels.length; ++i) {
184: declareLabel(labels[i]);
185: }
186: declareLabel(dflt);
187:
188: buf.append("mv.visitTableSwitchInsn(").append(min).append(", ")
189: .append(max).append(", ");
190: appendLabel(dflt);
191: buf.append(", new Label[] {");
192: for (int i = 0; i < labels.length; ++i) {
193: buf.append(i == 0 ? " " : ", ");
194: appendLabel(labels[i]);
195: }
196: buf.append(" });\n");
197: text.add(buf.toString());
198: }
199:
200: public void visitLookupSwitchInsn(final Label dflt,
201: final int keys[], final Label labels[]) {
202: buf.setLength(0);
203: for (int i = 0; i < labels.length; ++i) {
204: declareLabel(labels[i]);
205: }
206: declareLabel(dflt);
207:
208: buf.append("mv.visitLookupSwitchInsn(");
209: appendLabel(dflt);
210: buf.append(", new int[] {");
211: for (int i = 0; i < keys.length; ++i) {
212: buf.append(i == 0 ? " " : ", ").append(keys[i]);
213: }
214: buf.append(" }, new Label[] {");
215: for (int i = 0; i < labels.length; ++i) {
216: buf.append(i == 0 ? " " : ", ");
217: appendLabel(labels[i]);
218: }
219: buf.append(" });\n");
220: text.add(buf.toString());
221: }
222:
223: public void visitMultiANewArrayInsn(final String desc,
224: final int dims) {
225: buf.setLength(0);
226: buf.append("mv.visitMultiANewArrayInsn(");
227: appendConstant(desc);
228: buf.append(", ").append(dims).append(");\n");
229: text.add(buf.toString());
230: }
231:
232: public void visitTryCatchBlock(final Label start, final Label end,
233: final Label handler, final String type) {
234: buf.setLength(0);
235: declareLabel(start);
236: declareLabel(end);
237: declareLabel(handler);
238: buf.append("mv.visitTryCatchBlock(");
239: appendLabel(start);
240: buf.append(", ");
241: appendLabel(end);
242: buf.append(", ");
243: appendLabel(handler);
244: buf.append(", ");
245: appendConstant(type);
246: buf.append(");\n");
247: text.add(buf.toString());
248: }
249:
250: public void visitLocalVariable(final String name,
251: final String desc, final String signature,
252: final Label start, final Label end, final int index) {
253: buf.setLength(0);
254: buf.append("mv.visitLocalVariable(");
255: appendConstant(name);
256: buf.append(", ");
257: appendConstant(desc);
258: buf.append(", ");
259: appendConstant(signature);
260: buf.append(", ");
261: appendLabel(start);
262: buf.append(", ");
263: appendLabel(end);
264: buf.append(", ").append(index).append(");\n");
265: text.add(buf.toString());
266: }
267:
268: public void visitLineNumber(final int line, final Label start) {
269: buf.setLength(0);
270: buf.append("mv.visitLineNumber(").append(line).append(", ");
271: appendLabel(start);
272: buf.append(");\n");
273: text.add(buf.toString());
274: }
275:
276: public void visitMaxs(final int maxStack, final int maxLocals) {
277: buf.setLength(0);
278: buf.append("mv.visitMaxs(").append(maxStack).append(", ")
279: .append(maxLocals).append(");\n");
280: text.add(buf.toString());
281: }
282:
283: /**
284: * Appends a declaration of the given label to {@link #buf buf}. This
285: * declaration is of the form "Label lXXX = new Label();". Does nothing if
286: * the given label has already been declared.
287: *
288: * @param l a label.
289: */
290: private void declareLabel(final Label l) {
291: String name = (String) labelNames.get(l);
292: if (name == null) {
293: name = "l" + labelNames.size();
294: labelNames.put(l, name);
295: buf.append("Label ").append(name).append(
296: " = new Label();\n");
297: }
298: }
299:
300: /**
301: * Appends the name of the given label to {@link #buf buf}. The given label
302: * <i>must</i> already have a name. One way to ensure this is to always
303: * call {@link #declareLabel declared} before calling this method.
304: *
305: * @param l a label.
306: */
307: private void appendLabel(final Label l) {
308: buf.append((String) labelNames.get(l));
309: }
310: }
|