1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This code is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 only, as
6  * published by the Free Software Foundation.  Oracle designates this
7  * particular file as subject to the "Classpath" exception as provided
8  * by Oracle in the LICENSE file that accompanied this code.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /*
26  * This file is available under and governed by the GNU General Public
27  * License version 2 only, as published by the Free Software Foundation.
28  * However, the following notice accompanied the original version of this
29  * file:
30  *
31  * ASM: a very small and fast Java bytecode manipulation framework
32  * Copyright (c) 2000-2011 INRIA, France Telecom
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  * 3. Neither the name of the copyright holders nor the names of its
44  *    contributors may be used to endorse or promote products derived from
45  *    this software without specific prior written permission.
46  *
47  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57  * THE POSSIBILITY OF SUCH DAMAGE.
58  */
59 package jdk.internal.org.objectweb.asm.util;
60 
61 import java.io.PrintWriter;
62 import java.util.ArrayList;
63 import java.util.List;
64 
65 import jdk.internal.org.objectweb.asm.Attribute;
66 import jdk.internal.org.objectweb.asm.Handle;
67 import jdk.internal.org.objectweb.asm.Label;
68 import jdk.internal.org.objectweb.asm.Opcodes;
69 import jdk.internal.org.objectweb.asm.TypePath;
70 
71 /**
72  * An abstract converter from visit events to text.
73  *
74  * @author Eric Bruneton
75  */
76 public abstract class Printer {
77 
78     /**
79      * The names of the Java Virtual Machine opcodes.
80      */
81     public static final String[] OPCODES;
82 
83     /**
84      * The names of the for <code>operand</code> parameter values of the
85      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitIntInsn} method when
86      * <code>opcode</code> is <code>NEWARRAY</code>.
87      */
88     public static final String[] TYPES;
89 
90     /**
91      * The names of the <code>tag</code> field values for
92      * {@link jdk.internal.org.objectweb.asm.Handle}.
93      */
94     public static final String[] HANDLE_TAG;
95 
96     static {
97         String s = "NOP,ACONST_NULL,ICONST_M1,ICONST_0,ICONST_1,ICONST_2,"
98                 + "ICONST_3,ICONST_4,ICONST_5,LCONST_0,LCONST_1,FCONST_0,"
99                 + "FCONST_1,FCONST_2,DCONST_0,DCONST_1,BIPUSH,SIPUSH,LDC,,,"
100                 + "ILOAD,LLOAD,FLOAD,DLOAD,ALOAD,,,,,,,,,,,,,,,,,,,,,IALOAD,"
101                 + "LALOAD,FALOAD,DALOAD,AALOAD,BALOAD,CALOAD,SALOAD,ISTORE,"
102                 + "LSTORE,FSTORE,DSTORE,ASTORE,,,,,,,,,,,,,,,,,,,,,IASTORE,"
103                 + "LASTORE,FASTORE,DASTORE,AASTORE,BASTORE,CASTORE,SASTORE,POP,"
104                 + "POP2,DUP,DUP_X1,DUP_X2,DUP2,DUP2_X1,DUP2_X2,SWAP,IADD,LADD,"
105                 + "FADD,DADD,ISUB,LSUB,FSUB,DSUB,IMUL,LMUL,FMUL,DMUL,IDIV,LDIV,"
106                 + "FDIV,DDIV,IREM,LREM,FREM,DREM,INEG,LNEG,FNEG,DNEG,ISHL,LSHL,"
107                 + "ISHR,LSHR,IUSHR,LUSHR,IAND,LAND,IOR,LOR,IXOR,LXOR,IINC,I2L,"
108                 + "I2F,I2D,L2I,L2F,L2D,F2I,F2L,F2D,D2I,D2L,D2F,I2B,I2C,I2S,LCMP,"
109                 + "FCMPL,FCMPG,DCMPL,DCMPG,IFEQ,IFNE,IFLT,IFGE,IFGT,IFLE,"
110                 + "IF_ICMPEQ,IF_ICMPNE,IF_ICMPLT,IF_ICMPGE,IF_ICMPGT,IF_ICMPLE,"
111                 + "IF_ACMPEQ,IF_ACMPNE,GOTO,JSR,RET,TABLESWITCH,LOOKUPSWITCH,"
112                 + "IRETURN,LRETURN,FRETURN,DRETURN,ARETURN,RETURN,GETSTATIC,"
113                 + "PUTSTATIC,GETFIELD,PUTFIELD,INVOKEVIRTUAL,INVOKESPECIAL,"
114                 + "INVOKESTATIC,INVOKEINTERFACE,INVOKEDYNAMIC,NEW,NEWARRAY,"
115                 + "ANEWARRAY,ARRAYLENGTH,ATHROW,CHECKCAST,INSTANCEOF,"
116                 + "MONITORENTER,MONITOREXIT,,MULTIANEWARRAY,IFNULL,IFNONNULL,";
117         OPCODES = new String[200];
118         int i = 0;
119         int j = 0;
120         int l;
121         while ((l = s.indexOf(',', j)) > 0) {
122             OPCODES[i++] = j + 1 == l ? null : s.substring(j, l);
123             j = l + 1;
124         }
125 
126         s = "T_BOOLEAN,T_CHAR,T_FLOAT,T_DOUBLE,T_BYTE,T_SHORT,T_INT,T_LONG,";
127         TYPES = new String[12];
128         j = 0;
129         i = 4;
130         while ((l = s.indexOf(',', j)) > 0) {
131             TYPES[i++] = s.substring(j, l);
132             j = l + 1;
133         }
134 
135         s = "H_GETFIELD,H_GETSTATIC,H_PUTFIELD,H_PUTSTATIC,"
136                 + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
137                 + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
138         HANDLE_TAG = new String[10];
139         j = 0;
140         i = 1;
141         while ((l = s.indexOf(',', j)) > 0) {
142             HANDLE_TAG[i++] = s.substring(j, l);
143             j = l + 1;
144         }
145     }
146 
147     /**
148      * The ASM API version implemented by this class. The value of this field
149      * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
150      */
151     protected final int api;
152 
153     /**
154      * A buffer that can be used to create strings.
155      */
156     protected final StringBuffer buf;
157 
158     /**
159      * The text to be printed. Since the code of methods is not necessarily
160      * visited in sequential order, one method after the other, but can be
161      * interlaced (some instructions from method one, then some instructions
162      * from method two, then some instructions from method one again...), it is
163      * not possible to print the visited instructions directly to a sequential
164      * stream. A class is therefore printed in a two steps process: a string
165      * tree is constructed during the visit, and printed to a sequential stream
166      * at the end of the visit. This string tree is stored in this field, as a
167      * string list that can contain other string lists, which can themselves
168      * contain other string lists, and so on.
169      */
170     public final List<Object> text;
171 
172     /**
173      * Constructs a new {@link Printer}.
174      */
Printer(final int api)175     protected Printer(final int api) {
176         this.api = api;
177         this.buf = new StringBuffer();
178         this.text = new ArrayList<Object>();
179     }
180 
181     /**
182      * Class header. See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visit}.
183      */
visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)184     public abstract void visit(final int version, final int access,
185             final String name, final String signature, final String superName,
186             final String[] interfaces);
187 
188     /**
189      * Class source. See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitSource}.
190      */
visitSource(final String file, final String debug)191     public abstract void visitSource(final String file, final String debug);
192 
193     /**
194      * Class outer class. See
195      * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitOuterClass}.
196      */
visitOuterClass(final String owner, final String name, final String desc)197     public abstract void visitOuterClass(final String owner, final String name,
198             final String desc);
199 
200     /**
201      * Class annotation. See
202      * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitAnnotation}.
203      */
visitClassAnnotation(final String desc, final boolean visible)204     public abstract Printer visitClassAnnotation(final String desc,
205             final boolean visible);
206 
207     /**
208      * Class type annotation. See
209      * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitTypeAnnotation}.
210      */
visitClassTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible)211     public Printer visitClassTypeAnnotation(final int typeRef,
212             final TypePath typePath, final String desc, final boolean visible) {
213         throw new RuntimeException("Must be overriden");
214     }
215 
216     /**
217      * Class attribute. See
218      * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitAttribute}.
219      */
visitClassAttribute(final Attribute attr)220     public abstract void visitClassAttribute(final Attribute attr);
221 
222     /**
223      * Class inner name. See
224      * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitInnerClass}.
225      */
visitInnerClass(final String name, final String outerName, final String innerName, final int access)226     public abstract void visitInnerClass(final String name,
227             final String outerName, final String innerName, final int access);
228 
229     /**
230      * Class field. See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitField}.
231      */
visitField(final int access, final String name, final String desc, final String signature, final Object value)232     public abstract Printer visitField(final int access, final String name,
233             final String desc, final String signature, final Object value);
234 
235     /**
236      * Class method. See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitMethod}.
237      */
visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions)238     public abstract Printer visitMethod(final int access, final String name,
239             final String desc, final String signature, final String[] exceptions);
240 
241     /**
242      * Class end. See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitEnd}.
243      */
visitClassEnd()244     public abstract void visitClassEnd();
245 
246     // ------------------------------------------------------------------------
247     // Annotations
248     // ------------------------------------------------------------------------
249 
250     /**
251      * Annotation value. See {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visit}.
252      */
visit(final String name, final Object value)253     public abstract void visit(final String name, final Object value);
254 
255     /**
256      * Annotation enum value. See
257      * {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visitEnum}.
258      */
visitEnum(final String name, final String desc, final String value)259     public abstract void visitEnum(final String name, final String desc,
260             final String value);
261 
262     /**
263      * Nested annotation value. See
264      * {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visitAnnotation}.
265      */
visitAnnotation(final String name, final String desc)266     public abstract Printer visitAnnotation(final String name, final String desc);
267 
268     /**
269      * Annotation array value. See
270      * {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visitArray}.
271      */
visitArray(final String name)272     public abstract Printer visitArray(final String name);
273 
274     /**
275      * Annotation end. See {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visitEnd}.
276      */
visitAnnotationEnd()277     public abstract void visitAnnotationEnd();
278 
279     // ------------------------------------------------------------------------
280     // Fields
281     // ------------------------------------------------------------------------
282 
283     /**
284      * Field annotation. See
285      * {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitAnnotation}.
286      */
visitFieldAnnotation(final String desc, final boolean visible)287     public abstract Printer visitFieldAnnotation(final String desc,
288             final boolean visible);
289 
290     /**
291      * Field type annotation. See
292      * {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitTypeAnnotation}.
293      */
visitFieldTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible)294     public Printer visitFieldTypeAnnotation(final int typeRef,
295             final TypePath typePath, final String desc, final boolean visible) {
296         throw new RuntimeException("Must be overriden");
297     }
298 
299     /**
300      * Field attribute. See
301      * {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitAttribute}.
302      */
visitFieldAttribute(final Attribute attr)303     public abstract void visitFieldAttribute(final Attribute attr);
304 
305     /**
306      * Field end. See {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitEnd}.
307      */
visitFieldEnd()308     public abstract void visitFieldEnd();
309 
310     // ------------------------------------------------------------------------
311     // Methods
312     // ------------------------------------------------------------------------
313 
314     /**
315      * Method parameter. See
316      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitParameter(String, int)}.
317      */
visitParameter(String name, int access)318     public void visitParameter(String name, int access) {
319         throw new RuntimeException("Must be overriden");
320     }
321 
322     /**
323      * Method default annotation. See
324      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitAnnotationDefault}.
325      */
visitAnnotationDefault()326     public abstract Printer visitAnnotationDefault();
327 
328     /**
329      * Method annotation. See
330      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitAnnotation}.
331      */
visitMethodAnnotation(final String desc, final boolean visible)332     public abstract Printer visitMethodAnnotation(final String desc,
333             final boolean visible);
334 
335     /**
336      * Method type annotation. See
337      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTypeAnnotation}.
338      */
visitMethodTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible)339     public Printer visitMethodTypeAnnotation(final int typeRef,
340             final TypePath typePath, final String desc, final boolean visible) {
341         throw new RuntimeException("Must be overriden");
342     }
343 
344     /**
345      * Method parameter annotation. See
346      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitParameterAnnotation}.
347      */
visitParameterAnnotation(final int parameter, final String desc, final boolean visible)348     public abstract Printer visitParameterAnnotation(final int parameter,
349             final String desc, final boolean visible);
350 
351     /**
352      * Method attribute. See
353      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitAttribute}.
354      */
visitMethodAttribute(final Attribute attr)355     public abstract void visitMethodAttribute(final Attribute attr);
356 
357     /**
358      * Method start. See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitCode}.
359      */
visitCode()360     public abstract void visitCode();
361 
362     /**
363      * Method stack frame. See
364      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitFrame}.
365      */
visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack)366     public abstract void visitFrame(final int type, final int nLocal,
367             final Object[] local, final int nStack, final Object[] stack);
368 
369     /**
370      * Method instruction. See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitInsn}
371      * .
372      */
visitInsn(final int opcode)373     public abstract void visitInsn(final int opcode);
374 
375     /**
376      * Method instruction. See
377      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitIntInsn}.
378      */
visitIntInsn(final int opcode, final int operand)379     public abstract void visitIntInsn(final int opcode, final int operand);
380 
381     /**
382      * Method instruction. See
383      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitVarInsn}.
384      */
visitVarInsn(final int opcode, final int var)385     public abstract void visitVarInsn(final int opcode, final int var);
386 
387     /**
388      * Method instruction. See
389      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTypeInsn}.
390      */
visitTypeInsn(final int opcode, final String type)391     public abstract void visitTypeInsn(final int opcode, final String type);
392 
393     /**
394      * Method instruction. See
395      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitFieldInsn}.
396      */
visitFieldInsn(final int opcode, final String owner, final String name, final String desc)397     public abstract void visitFieldInsn(final int opcode, final String owner,
398             final String name, final String desc);
399 
400     /**
401      * Method instruction. See
402      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMethodInsn}.
403      */
404     @Deprecated
visitMethodInsn(final int opcode, final String owner, final String name, final String desc)405     public void visitMethodInsn(final int opcode, final String owner,
406             final String name, final String desc) {
407         if (api >= Opcodes.ASM5) {
408             boolean itf = opcode == Opcodes.INVOKEINTERFACE;
409             visitMethodInsn(opcode, owner, name, desc, itf);
410             return;
411         }
412         throw new RuntimeException("Must be overriden");
413     }
414 
415     /**
416      * Method instruction. See
417      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMethodInsn}.
418      */
visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf)419     public void visitMethodInsn(final int opcode, final String owner,
420             final String name, final String desc, final boolean itf) {
421         if (api < Opcodes.ASM5) {
422             if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
423                 throw new IllegalArgumentException(
424                         "INVOKESPECIAL/STATIC on interfaces require ASM 5");
425             }
426             visitMethodInsn(opcode, owner, name, desc);
427             return;
428         }
429         throw new RuntimeException("Must be overriden");
430     }
431 
432     /**
433      * Method instruction. See
434      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitInvokeDynamicInsn}.
435      */
visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs)436     public abstract void visitInvokeDynamicInsn(String name, String desc,
437             Handle bsm, Object... bsmArgs);
438 
439     /**
440      * Method instruction. See
441      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitJumpInsn}.
442      */
visitJumpInsn(final int opcode, final Label label)443     public abstract void visitJumpInsn(final int opcode, final Label label);
444 
445     /**
446      * Method label. See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLabel}.
447      */
visitLabel(final Label label)448     public abstract void visitLabel(final Label label);
449 
450     /**
451      * Method instruction. See
452      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLdcInsn}.
453      */
visitLdcInsn(final Object cst)454     public abstract void visitLdcInsn(final Object cst);
455 
456     /**
457      * Method instruction. See
458      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitIincInsn}.
459      */
visitIincInsn(final int var, final int increment)460     public abstract void visitIincInsn(final int var, final int increment);
461 
462     /**
463      * Method instruction. See
464      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTableSwitchInsn}.
465      */
visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels)466     public abstract void visitTableSwitchInsn(final int min, final int max,
467             final Label dflt, final Label... labels);
468 
469     /**
470      * Method instruction. See
471      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLookupSwitchInsn}.
472      */
visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels)473     public abstract void visitLookupSwitchInsn(final Label dflt,
474             final int[] keys, final Label[] labels);
475 
476     /**
477      * Method instruction. See
478      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMultiANewArrayInsn}.
479      */
visitMultiANewArrayInsn(final String desc, final int dims)480     public abstract void visitMultiANewArrayInsn(final String desc,
481             final int dims);
482 
483     /**
484      * Instruction type annotation. See
485      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitInsnAnnotation}.
486      */
visitInsnAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible)487     public Printer visitInsnAnnotation(final int typeRef,
488             final TypePath typePath, final String desc, final boolean visible) {
489         throw new RuntimeException("Must be overriden");
490     }
491 
492     /**
493      * Method exception handler. See
494      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTryCatchBlock}.
495      */
visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type)496     public abstract void visitTryCatchBlock(final Label start, final Label end,
497             final Label handler, final String type);
498 
499     /**
500      * Try catch block type annotation. See
501      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTryCatchAnnotation}.
502      */
visitTryCatchAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible)503     public Printer visitTryCatchAnnotation(final int typeRef,
504             final TypePath typePath, final String desc, final boolean visible) {
505         throw new RuntimeException("Must be overriden");
506     }
507 
508     /**
509      * Method debug info. See
510      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLocalVariable}.
511      */
visitLocalVariable(final String name, final String desc, final String signature, final Label start, final Label end, final int index)512     public abstract void visitLocalVariable(final String name,
513             final String desc, final String signature, final Label start,
514             final Label end, final int index);
515 
516     /**
517      * Local variable type annotation. See
518      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTryCatchAnnotation}.
519      */
visitLocalVariableAnnotation(final int typeRef, final TypePath typePath, final Label[] start, final Label[] end, final int[] index, final String desc, final boolean visible)520     public Printer visitLocalVariableAnnotation(final int typeRef,
521             final TypePath typePath, final Label[] start, final Label[] end,
522             final int[] index, final String desc, final boolean visible) {
523         throw new RuntimeException("Must be overriden");
524     }
525 
526     /**
527      * Method debug info. See
528      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLineNumber}.
529      */
visitLineNumber(final int line, final Label start)530     public abstract void visitLineNumber(final int line, final Label start);
531 
532     /**
533      * Method max stack and max locals. See
534      * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMaxs}.
535      */
visitMaxs(final int maxStack, final int maxLocals)536     public abstract void visitMaxs(final int maxStack, final int maxLocals);
537 
538     /**
539      * Method end. See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitEnd}.
540      */
visitMethodEnd()541     public abstract void visitMethodEnd();
542 
543     /**
544      * Returns the text constructed by this visitor.
545      *
546      * @return the text constructed by this visitor.
547      */
getText()548     public List<Object> getText() {
549         return text;
550     }
551 
552     /**
553      * Prints the text constructed by this visitor.
554      *
555      * @param pw
556      *            the print writer to be used.
557      */
print(final PrintWriter pw)558     public void print(final PrintWriter pw) {
559         printList(pw, text);
560     }
561 
562     /**
563      * Appends a quoted string to a given buffer.
564      *
565      * @param buf
566      *            the buffer where the string must be added.
567      * @param s
568      *            the string to be added.
569      */
appendString(final StringBuffer buf, final String s)570     public static void appendString(final StringBuffer buf, final String s) {
571         buf.append('\"');
572         for (int i = 0; i < s.length(); ++i) {
573             char c = s.charAt(i);
574             if (c == '\n') {
575                 buf.append("\\n");
576             } else if (c == '\r') {
577                 buf.append("\\r");
578             } else if (c == '\\') {
579                 buf.append("\\\\");
580             } else if (c == '"') {
581                 buf.append("\\\"");
582             } else if (c < 0x20 || c > 0x7f) {
583                 buf.append("\\u");
584                 if (c < 0x10) {
585                     buf.append("000");
586                 } else if (c < 0x100) {
587                     buf.append("00");
588                 } else if (c < 0x1000) {
589                     buf.append('0');
590                 }
591                 buf.append(Integer.toString(c, 16));
592             } else {
593                 buf.append(c);
594             }
595         }
596         buf.append('\"');
597     }
598 
599     /**
600      * Prints the given string tree.
601      *
602      * @param pw
603      *            the writer to be used to print the tree.
604      * @param l
605      *            a string tree, i.e., a string list that can contain other
606      *            string lists, and so on recursively.
607      */
printList(final PrintWriter pw, final List<?> l)608     static void printList(final PrintWriter pw, final List<?> l) {
609         for (int i = 0; i < l.size(); ++i) {
610             Object o = l.get(i);
611             if (o instanceof List) {
612                 printList(pw, (List<?>) o);
613             } else {
614                 pw.print(o.toString());
615             }
616         }
617     }
618 }
619