1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/***
2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ASM: a very small and fast Java bytecode manipulation framework
3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Copyright (c) 2000-2007 INRIA, France Telecom
4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * All rights reserved.
5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Redistribution and use in source and binary forms, with or without
7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * modification, are permitted provided that the following conditions
8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * are met:
9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1. Redistributions of source code must retain the above copyright
10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *    notice, this list of conditions and the following disclaimer.
11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2. Redistributions in binary form must reproduce the above copyright
12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *    notice, this list of conditions and the following disclaimer in the
13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *    documentation and/or other materials provided with the distribution.
14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 3. Neither the name of the copyright holders nor the names of its
15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *    contributors may be used to endorse or promote products derived from
16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *    this software without specific prior written permission.
17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * THE POSSIBILITY OF SUCH DAMAGE.
29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */
30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpackage org.mockito.asm.util;
31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.AnnotationVisitor;
33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Attribute;
34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Label;
35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.MethodAdapter;
36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.MethodVisitor;
37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Opcodes;
38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Type;
39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.HashMap;
41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.Map;
42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/**
44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * A {@link MethodAdapter} that checks that its methods are properly used. More
45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * precisely this code adapter checks each instruction individually (i.e., each
46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * visit method checks some preconditions based <i>only</i> on its arguments -
47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * such as the fact that the given opcode is correct for a given visit method),
48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * but does <i>not</i> check the <i>sequence</i> of instructions. For example,
49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * in a method whose signature is <tt>void m ()</tt>, the invalid instruction
50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * IRETURN, or the invalid sequence IADD L2I will <i>not</i> be detected by
51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * this code adapter.
52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Eric Bruneton
54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */
55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpublic class CheckMethodAdapter extends MethodAdapter {
56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * <tt>true</tt> if the visitCode method has been called.
59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private boolean startCode;
61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * <tt>true</tt> if the visitMaxs method has been called.
64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private boolean endCode;
66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * <tt>true</tt> if the visitEnd method has been called.
69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private boolean endMethod;
71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The already visited labels. This map associate Integer values to Label
74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * keys.
75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private final Map labels;
77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Code of the visit method to be used for each opcode.
80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static final int[] TYPE;
82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static {
84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"
85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"
87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        TYPE = new int[s.length()];
89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (int i = 0; i < TYPE.length; ++i) {
90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            TYPE[i] = s.charAt(i) - 'A' - 1;
91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // code to generate the above string
95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // public static void main (String[] args) {
96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // int[] TYPE = new int[] {
97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //NOP
98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ACONST_NULL
99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ICONST_M1
100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ICONST_0
101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ICONST_1
102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ICONST_2
103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ICONST_3
104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ICONST_4
105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ICONST_5
106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LCONST_0
107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LCONST_1
108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FCONST_0
109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FCONST_1
110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FCONST_2
111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DCONST_0
112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DCONST_1
113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 1, //BIPUSH
114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 1, //SIPUSH
115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 7, //LDC
116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //LDC_W
117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //LDC2_W
118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 2, //ILOAD
119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 2, //LLOAD
120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 2, //FLOAD
121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 2, //DLOAD
122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 2, //ALOAD
123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ILOAD_0
124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ILOAD_1
125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ILOAD_2
126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ILOAD_3
127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //LLOAD_0
128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //LLOAD_1
129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //LLOAD_2
130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //LLOAD_3
131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //FLOAD_0
132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //FLOAD_1
133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //FLOAD_2
134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //FLOAD_3
135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //DLOAD_0
136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //DLOAD_1
137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //DLOAD_2
138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //DLOAD_3
139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ALOAD_0
140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ALOAD_1
141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ALOAD_2
142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ALOAD_3
143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //IALOAD
144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LALOAD
145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FALOAD
146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DALOAD
147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //AALOAD
148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //BALOAD
149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //CALOAD
150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //SALOAD
151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 2, //ISTORE
152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 2, //LSTORE
153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 2, //FSTORE
154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 2, //DSTORE
155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 2, //ASTORE
156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ISTORE_0
157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ISTORE_1
158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ISTORE_2
159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ISTORE_3
160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //LSTORE_0
161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //LSTORE_1
162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //LSTORE_2
163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //LSTORE_3
164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //FSTORE_0
165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //FSTORE_1
166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //FSTORE_2
167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //FSTORE_3
168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //DSTORE_0
169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //DSTORE_1
170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //DSTORE_2
171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //DSTORE_3
172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ASTORE_0
173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ASTORE_1
174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ASTORE_2
175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //ASTORE_3
176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //IASTORE
177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LASTORE
178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FASTORE
179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DASTORE
180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //AASTORE
181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //BASTORE
182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //CASTORE
183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //SASTORE
184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //POP
185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //POP2
186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DUP
187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DUP_X1
188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DUP_X2
189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DUP2
190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DUP2_X1
191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DUP2_X2
192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //SWAP
193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //IADD
194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LADD
195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FADD
196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DADD
197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ISUB
198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LSUB
199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FSUB
200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DSUB
201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //IMUL
202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LMUL
203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FMUL
204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DMUL
205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //IDIV
206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LDIV
207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FDIV
208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DDIV
209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //IREM
210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LREM
211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FREM
212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DREM
213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //INEG
214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LNEG
215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FNEG
216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DNEG
217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ISHL
218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LSHL
219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ISHR
220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LSHR
221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //IUSHR
222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LUSHR
223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //IAND
224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LAND
225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //IOR
226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LOR
227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //IXOR
228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LXOR
229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 8, //IINC
230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //I2L
231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //I2F
232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //I2D
233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //L2I
234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //L2F
235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //L2D
236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //F2I
237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //F2L
238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //F2D
239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //D2I
240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //D2L
241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //D2F
242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //I2B
243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //I2C
244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //I2S
245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LCMP
246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FCMPL
247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FCMPG
248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DCMPL
249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DCMPG
250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IFEQ
251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IFNE
252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IFLT
253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IFGE
254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IFGT
255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IFLE
256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IF_ICMPEQ
257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IF_ICMPNE
258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IF_ICMPLT
259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IF_ICMPGE
260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IF_ICMPGT
261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IF_ICMPLE
262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IF_ACMPEQ
263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IF_ACMPNE
264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //GOTO
265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //JSR
266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 2, //RET
267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 9, //TABLESWITCH
268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 10, //LOOKUPSWITCH
269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //IRETURN
270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //LRETURN
271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //FRETURN
272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //DRETURN
273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ARETURN
274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //RETURN
275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 4, //GETSTATIC
276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 4, //PUTSTATIC
277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 4, //GETFIELD
278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 4, //PUTFIELD
279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 5, //INVOKEVIRTUAL
280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 5, //INVOKESPECIAL
281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 5, //INVOKESTATIC
282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 5, //INVOKEINTERFACE
283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //UNUSED
284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 3, //NEW
285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 1, //NEWARRAY
286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 3, //ANEWARRAY
287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ARRAYLENGTH
288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //ATHROW
289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 3, //CHECKCAST
290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 3, //INSTANCEOF
291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //MONITORENTER
292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 0, //MONITOREXIT
293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //WIDE
294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 11, //MULTIANEWARRAY
295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IFNULL
296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // 6, //IFNONNULL
297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1, //GOTO_W
298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -1 //JSR_W
299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // };
300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // for (int i = 0; i < TYPE.length; ++i) {
301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // System.out.print((char)(TYPE[i] + 1 + 'A'));
302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // }
303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // System.out.println();
304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // }
305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Constructs a new {@link CheckMethodAdapter} object.
308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param cv the code visitor to which this adapter must delegate calls.
310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public CheckMethodAdapter(final MethodVisitor cv) {
312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        super(cv);
313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        this.labels = new HashMap();
314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public AnnotationVisitor visitAnnotation(
317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc,
318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final boolean visible)
319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndMethod();
321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkDesc(desc, false);
322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return new CheckAnnotationAdapter(mv.visitAnnotation(desc, visible));
323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public AnnotationVisitor visitAnnotationDefault() {
326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndMethod();
327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return new CheckAnnotationAdapter(mv.visitAnnotationDefault(), false);
328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
329674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
330674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public AnnotationVisitor visitParameterAnnotation(
331674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int parameter,
332674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc,
333674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final boolean visible)
334674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
335674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndMethod();
336674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkDesc(desc, false);
337674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return new CheckAnnotationAdapter(mv.visitParameterAnnotation(parameter,
338674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                desc,
339674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                visible));
340674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
341674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
342674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitAttribute(final Attribute attr) {
343674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndMethod();
344674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (attr == null) {
345674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid attribute (must not be null)");
346674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
347674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitAttribute(attr);
348674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
349674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
350674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitCode() {
351674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        startCode = true;
352674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitCode();
353674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
354674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
355674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitFrame(
356674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int type,
357674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int nLocal,
358674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Object[] local,
359674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int nStack,
360674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Object[] stack)
361674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
362674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int mLocal;
363674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int mStack;
364674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        switch (type) {
365674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case Opcodes.F_NEW:
366674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case Opcodes.F_FULL:
367674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                mLocal = Integer.MAX_VALUE;
368674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                mStack = Integer.MAX_VALUE;
369674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
370674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
371674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case Opcodes.F_SAME:
372674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                mLocal = 0;
373674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                mStack = 0;
374674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
375674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
376674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case Opcodes.F_SAME1:
377674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                mLocal = 0;
378674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                mStack = 1;
379674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
380674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
381674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case Opcodes.F_APPEND:
382674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case Opcodes.F_CHOP:
383674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                mLocal = 3;
384674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                mStack = 0;
385674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
386674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
387674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            default:
388674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                throw new IllegalArgumentException("Invalid frame type " + type);
389674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
390674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
391674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (nLocal > mLocal) {
392674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid nLocal=" + nLocal
393674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " for frame type " + type);
394674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
395674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (nStack > mStack) {
396674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid nStack=" + nStack
397674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " for frame type " + type);
398674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
399674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
400674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (type != Opcodes.F_CHOP) {
401674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (nLocal > 0 && (local == null || local.length < nLocal)) {
402674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                throw new IllegalArgumentException("Array local[] is shorter than nLocal");
403674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
404674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            for (int i = 0; i < nLocal; ++i) {
405674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                checkFrameValue(local[i]);
406674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
407674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
408674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (nStack > 0 && (stack == null || stack.length < nStack)) {
409674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Array stack[] is shorter than nStack");
410674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
411674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (int i = 0; i < nStack; ++i) {
412674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            checkFrameValue(stack[i]);
413674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
414674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
415674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitFrame(type, nLocal, local, nStack, stack);
416674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
417674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
418674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitInsn(final int opcode) {
419674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
420674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
421674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkOpcode(opcode, 0);
422674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitInsn(opcode);
423674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
424674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
425674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitIntInsn(final int opcode, final int operand) {
426674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
427674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
428674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkOpcode(opcode, 1);
429674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        switch (opcode) {
430674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case Opcodes.BIPUSH:
431674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                checkSignedByte(operand, "Invalid operand");
432674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
433674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case Opcodes.SIPUSH:
434674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                checkSignedShort(operand, "Invalid operand");
435674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
436674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // case Constants.NEWARRAY:
437674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            default:
438674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
439674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    throw new IllegalArgumentException("Invalid operand (must be an array type code T_...): "
440674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            + operand);
441674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
442674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
443674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitIntInsn(opcode, operand);
444674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
445674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
446674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitVarInsn(final int opcode, final int var) {
447674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
448674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
449674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkOpcode(opcode, 2);
450674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkUnsignedShort(var, "Invalid variable index");
451674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitVarInsn(opcode, var);
452674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
453674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
454674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitTypeInsn(final int opcode, final String type) {
455674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
456674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
457674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkOpcode(opcode, 3);
458674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkInternalName(type, "type");
459674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (opcode == Opcodes.NEW && type.charAt(0) == '[') {
460674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("NEW cannot be used to create arrays: "
461674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + type);
462674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
463674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitTypeInsn(opcode, type);
464674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
465674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
466674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitFieldInsn(
467674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int opcode,
468674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String owner,
469674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String name,
470674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc)
471674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
472674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
473674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
474674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkOpcode(opcode, 4);
475674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkInternalName(owner, "owner");
476674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkIdentifier(name, "name");
477674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkDesc(desc, false);
478674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitFieldInsn(opcode, owner, name, desc);
479674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
480674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
481674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitMethodInsn(
482674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int opcode,
483674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String owner,
484674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String name,
485674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc)
486674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
487674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
488674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
489674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkOpcode(opcode, 5);
490674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkMethodIdentifier(name, "name");
491674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkInternalName(owner, "owner");
492674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkMethodDesc(desc);
493674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitMethodInsn(opcode, owner, name, desc);
494674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
495674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
496674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitJumpInsn(final int opcode, final Label label) {
497674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
498674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
499674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkOpcode(opcode, 6);
500674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkLabel(label, false, "label");
501674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitJumpInsn(opcode, label);
502674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
503674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
504674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitLabel(final Label label) {
505674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
506674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
507674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkLabel(label, false, "label");
508674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (labels.get(label) != null) {
509674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Already visited label");
510674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
511674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        labels.put(label, new Integer(labels.size()));
512674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitLabel(label);
513674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
514674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
515674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitLdcInsn(final Object cst) {
516674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
517674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
518674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!(cst instanceof Type)) {
519674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            checkConstant(cst);
520674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
521674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitLdcInsn(cst);
522674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
523674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
524674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitIincInsn(final int var, final int increment) {
525674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
526674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
527674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkUnsignedShort(var, "Invalid variable index");
528674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkSignedShort(increment, "Invalid increment");
529674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitIincInsn(var, increment);
530674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
531674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
532674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitTableSwitchInsn(
533674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int min,
534674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int max,
535674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label dflt,
536674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label[] labels)
537674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
538674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
539674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
540674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (max < min) {
541674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Max = " + max
542674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " must be greater than or equal to min = " + min);
543674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
544674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkLabel(dflt, false, "default label");
545674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (labels == null || labels.length != max - min + 1) {
546674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("There must be max - min + 1 labels");
547674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
548674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (int i = 0; i < labels.length; ++i) {
549674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            checkLabel(labels[i], false, "label at index " + i);
550674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
551674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitTableSwitchInsn(min, max, dflt, labels);
552674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
553674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
554674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitLookupSwitchInsn(
555674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label dflt,
556674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int[] keys,
557674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label[] labels)
558674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
559674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
560674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
561674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkLabel(dflt, false, "default label");
562674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (keys == null || labels == null || keys.length != labels.length) {
563674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("There must be the same number of keys and labels");
564674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
565674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (int i = 0; i < labels.length; ++i) {
566674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            checkLabel(labels[i], false, "label at index " + i);
567674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
568674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitLookupSwitchInsn(dflt, keys, labels);
569674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
570674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
571674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitMultiANewArrayInsn(final String desc, final int dims) {
572674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
573674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
574674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkDesc(desc, false);
575674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (desc.charAt(0) != '[') {
576674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid descriptor (must be an array type descriptor): "
577674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + desc);
578674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
579674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (dims < 1) {
580674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid dimensions (must be greater than 0): "
581674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + dims);
582674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
583674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (dims > desc.lastIndexOf('[') + 1) {
584674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid dimensions (must not be greater than dims(desc)): "
585674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + dims);
586674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
587674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitMultiANewArrayInsn(desc, dims);
588674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
589674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
590674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitTryCatchBlock(
591674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label start,
592674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label end,
593674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label handler,
594674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String type)
595674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
596674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
597674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
598674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (type != null) {
599674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            checkInternalName(type, "type");
600674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
601674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitTryCatchBlock(start, end, handler, type);
602674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
603674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
604674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitLocalVariable(
605674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String name,
606674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc,
607674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String signature,
608674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label start,
609674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label end,
610674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int index)
611674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
612674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
613674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
614674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkIdentifier(name, "name");
615674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkDesc(desc, false);
616674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkLabel(start, true, "start label");
617674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkLabel(end, true, "end label");
618674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkUnsignedShort(index, "Invalid variable index");
619674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int s = ((Integer) labels.get(start)).intValue();
620674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int e = ((Integer) labels.get(end)).intValue();
621674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (e < s) {
622674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid start and end labels (end must be greater than start)");
623674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
624674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitLocalVariable(name, desc, signature, start, end, index);
625674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
626674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
627674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitLineNumber(final int line, final Label start) {
628674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
629674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
630674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkUnsignedShort(line, "Invalid line number");
631674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkLabel(start, true, "start label");
632674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitLineNumber(line, start);
633674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
634674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
635674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitMaxs(final int maxStack, final int maxLocals) {
636674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkStartCode();
637674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndCode();
638674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        endCode = true;
639674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkUnsignedShort(maxStack, "Invalid max stack");
640674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkUnsignedShort(maxLocals, "Invalid max locals");
641674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitMaxs(maxStack, maxLocals);
642674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
643674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
644674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitEnd() {
645674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkEndMethod();
646674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        endMethod = true;
647674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        mv.visitEnd();
648674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
649674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
650674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // -------------------------------------------------------------------------
651674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
652674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
653674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the visitCode method has been called.
654674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
655674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    void checkStartCode() {
656674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!startCode) {
657674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalStateException("Cannot visit instructions before visitCode has been called.");
658674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
659674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
660674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
661674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
662674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the visitMaxs method has not been called.
663674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
664674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    void checkEndCode() {
665674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (endCode) {
666674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalStateException("Cannot visit instructions after visitMaxs has been called.");
667674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
668674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
669674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
670674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
671674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the visitEnd method has not been called.
672674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
673674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    void checkEndMethod() {
674674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (endMethod) {
675674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalStateException("Cannot visit elements after visitEnd has been called.");
676674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
677674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
678674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
679674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
680674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks a stack frame value.
681674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
682674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param value the value to be checked.
683674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
684674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkFrameValue(final Object value) {
685674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (value == Opcodes.TOP || value == Opcodes.INTEGER
686674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                || value == Opcodes.FLOAT || value == Opcodes.LONG
687674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                || value == Opcodes.DOUBLE || value == Opcodes.NULL
688674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                || value == Opcodes.UNINITIALIZED_THIS)
689674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        {
690674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return;
691674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
692674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (value instanceof String) {
693674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            checkInternalName((String) value, "Invalid stack frame value");
694674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return;
695674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
696674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!(value instanceof Label)) {
697674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid stack frame value: "
698674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + value);
699674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
700674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
701674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
702674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
703674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the type of the given opcode is equal to the given type.
704674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
705674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param opcode the opcode to be checked.
706674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param type the expected opcode type.
707674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
708674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkOpcode(final int opcode, final int type) {
709674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
710674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid opcode: " + opcode);
711674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
712674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
713674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
714674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
715674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given value is a signed byte.
716674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
717674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param value the value to be checked.
718674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param msg an message to be used in case of error.
719674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
720674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkSignedByte(final int value, final String msg) {
721674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
722674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException(msg
723674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " (must be a signed byte): " + value);
724674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
725674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
726674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
727674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
728674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given value is a signed short.
729674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
730674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param value the value to be checked.
731674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param msg an message to be used in case of error.
732674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
733674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkSignedShort(final int value, final String msg) {
734674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
735674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException(msg
736674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " (must be a signed short): " + value);
737674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
738674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
739674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
740674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
741674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given value is an unsigned short.
742674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
743674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param value the value to be checked.
744674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param msg an message to be used in case of error.
745674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
746674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkUnsignedShort(final int value, final String msg) {
747674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (value < 0 || value > 65535) {
748674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException(msg
749674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " (must be an unsigned short): " + value);
750674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
751674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
752674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
753674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
754674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given value is an {@link Integer}, a{@link Float}, a
755674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * {@link Long}, a {@link Double} or a {@link String}.
756674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
757674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param cst the value to be checked.
758674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
759674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkConstant(final Object cst) {
760674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!(cst instanceof Integer) && !(cst instanceof Float)
761674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                && !(cst instanceof Long) && !(cst instanceof Double)
762674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                && !(cst instanceof String))
763674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        {
764674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid constant: " + cst);
765674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
766674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
767674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
768674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
769674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given string is a valid Java identifier.
770674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
771674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param name the string to be checked.
772674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param msg a message to be used in case of error.
773674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
774674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkIdentifier(final String name, final String msg) {
775674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        checkIdentifier(name, 0, -1, msg);
776674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
777674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
778674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
779674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given substring is a valid Java identifier.
780674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
781674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param name the string to be checked.
782674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param start index of the first character of the identifier (inclusive).
783674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param end index of the last character of the identifier (exclusive). -1
784674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        is equivalent to <tt>name.length()</tt> if name is not
785674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        <tt>null</tt>.
786674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param msg a message to be used in case of error.
787674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
788674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkIdentifier(
789674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String name,
790674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int start,
791674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int end,
792674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String msg)
793674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
794674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (name == null || (end == -1 ? name.length() <= start : end <= start))
795674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        {
796674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid " + msg
797674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " (must not be null or empty)");
798674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
799674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!Character.isJavaIdentifierStart(name.charAt(start))) {
800674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid " + msg
801674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " (must be a valid Java identifier): " + name);
802674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
803674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int max = end == -1 ? name.length() : end;
804674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (int i = start + 1; i < max; ++i) {
805674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
806674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                throw new IllegalArgumentException("Invalid " + msg
807674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        + " (must be a valid Java identifier): " + name);
808674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
809674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
810674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
811674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
812674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
813674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given string is a valid Java identifier or is equal to
814674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * '&lt;init&gt;' or '&lt;clinit&gt;'.
815674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
816674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param name the string to be checked.
817674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param msg a message to be used in case of error.
818674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
819674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkMethodIdentifier(final String name, final String msg) {
820674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (name == null || name.length() == 0) {
821674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid " + msg
822674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " (must not be null or empty)");
823674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
824674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ("<init>".equals(name) || "<clinit>".equals(name)) {
825674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return;
826674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
827674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!Character.isJavaIdentifierStart(name.charAt(0))) {
828674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid "
829674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + msg
830674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " (must be a '<init>', '<clinit>' or a valid Java identifier): "
831674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + name);
832674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
833674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (int i = 1; i < name.length(); ++i) {
834674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
835674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                throw new IllegalArgumentException("Invalid "
836674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        + msg
837674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        + " (must be '<init>' or '<clinit>' or a valid Java identifier): "
838674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        + name);
839674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
840674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
841674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
842674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
843674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
844674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given string is a valid internal class name.
845674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
846674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param name the string to be checked.
847674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param msg a message to be used in case of error.
848674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
849674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkInternalName(final String name, final String msg) {
850674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (name == null || name.length() == 0) {
851674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid " + msg
852674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " (must not be null or empty)");
853674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
854674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (name.charAt(0) == '[') {
855674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            checkDesc(name, false);
856674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
857674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            checkInternalName(name, 0, -1, msg);
858674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
859674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
860674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
861674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
862674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given substring is a valid internal class name.
863674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
864674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param name the string to be checked.
865674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param start index of the first character of the identifier (inclusive).
866674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param end index of the last character of the identifier (exclusive). -1
867674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        is equivalent to <tt>name.length()</tt> if name is not
868674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        <tt>null</tt>.
869674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param msg a message to be used in case of error.
870674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
871674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkInternalName(
872674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String name,
873674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int start,
874674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int end,
875674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String msg)
876674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
877674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int max = end == -1 ? name.length() : end;
878674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        try {
879674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int begin = start;
880674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int slash;
881674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            do {
882674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                slash = name.indexOf('/', begin + 1);
883674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (slash == -1 || slash > max) {
884674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    slash = max;
885674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
886674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                checkIdentifier(name, begin, slash, null);
887674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                begin = slash + 1;
888674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } while (slash != max);
889674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } catch (IllegalArgumentException _) {
890674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid "
891674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + msg
892674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " (must be a fully qualified class name in internal form): "
893674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + name);
894674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
895674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
896674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
897674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
898674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given string is a valid type descriptor.
899674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
900674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param desc the string to be checked.
901674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
902674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
903674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkDesc(final String desc, final boolean canBeVoid) {
904674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int end = checkDesc(desc, 0, canBeVoid);
905674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (end != desc.length()) {
906674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid descriptor: " + desc);
907674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
908674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
909674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
910674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
911674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that a the given substring is a valid type descriptor.
912674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
913674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param desc the string to be checked.
914674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param start index of the first character of the identifier (inclusive).
915674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
916674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the index of the last character of the type decriptor, plus one.
917674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
918674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static int checkDesc(
919674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc,
920674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int start,
921674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final boolean canBeVoid)
922674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
923674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (desc == null || start >= desc.length()) {
924674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid type descriptor (must not be null or empty)");
925674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
926674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int index;
927674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        switch (desc.charAt(start)) {
928674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'V':
929674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (canBeVoid) {
930674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    return start + 1;
931674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } else {
932674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    throw new IllegalArgumentException("Invalid descriptor: "
933674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            + desc);
934674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
935674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'Z':
936674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'C':
937674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'B':
938674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'S':
939674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'I':
940674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'F':
941674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'J':
942674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'D':
943674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return start + 1;
944674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case '[':
945674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                index = start + 1;
946674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (index < desc.length() && desc.charAt(index) == '[') {
947674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    ++index;
948674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
949674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (index < desc.length()) {
950674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    return checkDesc(desc, index, false);
951674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } else {
952674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    throw new IllegalArgumentException("Invalid descriptor: "
953674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            + desc);
954674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
955674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'L':
956674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                index = desc.indexOf(';', start);
957674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (index == -1 || index - start < 2) {
958674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    throw new IllegalArgumentException("Invalid descriptor: "
959674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            + desc);
960674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
961674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                try {
962674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    checkInternalName(desc, start + 1, index, null);
963674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } catch (IllegalArgumentException _) {
964674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    throw new IllegalArgumentException("Invalid descriptor: "
965674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            + desc);
966674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
967674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return index + 1;
968674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            default:
969674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                throw new IllegalArgumentException("Invalid descriptor: "
970674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        + desc);
971674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
972674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
973674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
974674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
975674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given string is a valid method descriptor.
976674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
977674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param desc the string to be checked.
978674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
979674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkMethodDesc(final String desc) {
980674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (desc == null || desc.length() == 0) {
981674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid method descriptor (must not be null or empty)");
982674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
983674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (desc.charAt(0) != '(' || desc.length() < 3) {
984674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid descriptor: " + desc);
985674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
986674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int start = 1;
987674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (desc.charAt(start) != ')') {
988674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            do {
989674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (desc.charAt(start) == 'V') {
990674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    throw new IllegalArgumentException("Invalid descriptor: "
991674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            + desc);
992674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
993674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                start = checkDesc(desc, start, false);
994674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } while (start < desc.length() && desc.charAt(start) != ')');
995674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
996674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        start = checkDesc(desc, start + 1, true);
997674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (start != desc.length()) {
998674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid descriptor: " + desc);
999674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1000674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1001674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1002674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1003674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks a class signature.
1004674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1005674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1006674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1007674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkClassSignature(final String signature) {
1008674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // ClassSignature:
1009674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*
1010674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1011674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int pos = 0;
1012674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (getChar(signature, 0) == '<') {
1013674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkFormalTypeParameters(signature, pos);
1014674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1015674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkClassTypeSignature(signature, pos);
1016674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (getChar(signature, pos) == 'L') {
1017674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkClassTypeSignature(signature, pos);
1018674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1019674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (pos != signature.length()) {
1020674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException(signature + ": error at index "
1021674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + pos);
1022674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1023674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1024674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1025674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1026674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks a method signature.
1027674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1028674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1029674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1030674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkMethodSignature(final String signature) {
1031674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // MethodTypeSignature:
1032674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (
1033674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // ^ClassTypeSignature | ^TypeVariableSignature )*
1034674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1035674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int pos = 0;
1036674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (getChar(signature, 0) == '<') {
1037674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkFormalTypeParameters(signature, pos);
1038674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1039674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkChar('(', signature, pos);
1040674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
1041674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkTypeSignature(signature, pos);
1042674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1043674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkChar(')', signature, pos);
1044674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (getChar(signature, pos) == 'V') {
1045674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++pos;
1046674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
1047674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkTypeSignature(signature, pos);
1048674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1049674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (getChar(signature, pos) == '^') {
1050674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++pos;
1051674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (getChar(signature, pos) == 'L') {
1052674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                pos = checkClassTypeSignature(signature, pos);
1053674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
1054674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                pos = checkTypeVariableSignature(signature, pos);
1055674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1056674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1057674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (pos != signature.length()) {
1058674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException(signature + ": error at index "
1059674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + pos);
1060674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1061674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1062674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1063674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1064674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks a field signature.
1065674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1066674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1067674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1068674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void checkFieldSignature(final String signature) {
1069674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int pos = checkFieldTypeSignature(signature, 0);
1070674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (pos != signature.length()) {
1071674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException(signature + ": error at index "
1072674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + pos);
1073674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1074674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1075674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1076674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1077674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks the formal type parameters of a class or method signature.
1078674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1079674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1080674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param pos index of first character to be checked.
1081674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the index of the first character after the checked part.
1082674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1083674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static int checkFormalTypeParameters(final String signature, int pos)
1084674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1085674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // FormalTypeParameters:
1086674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // < FormalTypeParameter+ >
1087674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1088674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkChar('<', signature, pos);
1089674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkFormalTypeParameter(signature, pos);
1090674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (getChar(signature, pos) != '>') {
1091674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkFormalTypeParameter(signature, pos);
1092674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1093674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return pos + 1;
1094674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1095674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1096674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1097674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks a formal type parameter of a class or method signature.
1098674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1099674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param pos index of first character to be checked.
1101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the index of the first character after the checked part.
1102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static int checkFormalTypeParameter(final String signature, int pos)
1104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // FormalTypeParameter:
1106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Identifier : FieldTypeSignature? (: FieldTypeSignature)*
1107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkIdentifier(signature, pos);
1109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkChar(':', signature, pos);
1110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ("L[T".indexOf(getChar(signature, pos)) != -1) {
1111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkFieldTypeSignature(signature, pos);
1112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (getChar(signature, pos) == ':') {
1114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkFieldTypeSignature(signature, pos + 1);
1115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return pos;
1117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks a field type signature.
1121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param pos index of first character to be checked.
1124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the index of the first character after the checked part.
1125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static int checkFieldTypeSignature(final String signature, int pos)
1127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // FieldTypeSignature:
1129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature
1130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        //
1131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // ArrayTypeSignature:
1132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // [ TypeSignature
1133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        switch (getChar(signature, pos)) {
1135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'L':
1136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return checkClassTypeSignature(signature, pos);
1137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case '[':
1138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return checkTypeSignature(signature, pos + 1);
1139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            default:
1140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return checkTypeVariableSignature(signature, pos);
1141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks a class type signature.
1146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param pos index of first character to be checked.
1149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the index of the first character after the checked part.
1150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static int checkClassTypeSignature(final String signature, int pos)
1152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // ClassTypeSignature:
1154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // L Identifier ( / Identifier )* TypeArguments? ( . Identifier
1155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // TypeArguments? )* ;
1156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkChar('L', signature, pos);
1158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkIdentifier(signature, pos);
1159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (getChar(signature, pos) == '/') {
1160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkIdentifier(signature, pos + 1);
1161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (getChar(signature, pos) == '<') {
1163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkTypeArguments(signature, pos);
1164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (getChar(signature, pos) == '.') {
1166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkIdentifier(signature, pos + 1);
1167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (getChar(signature, pos) == '<') {
1168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                pos = checkTypeArguments(signature, pos);
1169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return checkChar(';', signature, pos);
1172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks the type arguments in a class type signature.
1176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param pos index of first character to be checked.
1179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the index of the first character after the checked part.
1180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static int checkTypeArguments(final String signature, int pos) {
1182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // TypeArguments:
1183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // < TypeArgument+ >
1184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkChar('<', signature, pos);
1186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkTypeArgument(signature, pos);
1187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (getChar(signature, pos) != '>') {
1188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos = checkTypeArgument(signature, pos);
1189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return pos + 1;
1191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks a type argument in a class type signature.
1195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param pos index of first character to be checked.
1198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the index of the first character after the checked part.
1199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static int checkTypeArgument(final String signature, int pos) {
1201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // TypeArgument:
1202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // * | ( ( + | - )? FieldTypeSignature )
1203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        char c = getChar(signature, pos);
1205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (c == '*') {
1206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return pos + 1;
1207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else if (c == '+' || c == '-') {
1208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            pos++;
1209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return checkFieldTypeSignature(signature, pos);
1211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks a type variable signature.
1215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param pos index of first character to be checked.
1218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the index of the first character after the checked part.
1219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static int checkTypeVariableSignature(
1221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String signature,
1222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int pos)
1223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // TypeVariableSignature:
1225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // T Identifier ;
1226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkChar('T', signature, pos);
1228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        pos = checkIdentifier(signature, pos);
1229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return checkChar(';', signature, pos);
1230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks a type signature.
1234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param pos index of first character to be checked.
1237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the index of the first character after the checked part.
1238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static int checkTypeSignature(final String signature, int pos) {
1240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // TypeSignature:
1241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Z | C | B | S | I | F | J | D | FieldTypeSignature
1242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        switch (getChar(signature, pos)) {
1244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'Z':
1245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'C':
1246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'B':
1247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'S':
1248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'I':
1249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'F':
1250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'J':
1251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case 'D':
1252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return pos + 1;
1253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            default:
1254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return checkFieldTypeSignature(signature, pos);
1255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks an identifier.
1260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param pos index of first character to be checked.
1263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the index of the first character after the checked part.
1264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static int checkIdentifier(final String signature, int pos) {
1266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {
1267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException(signature
1268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + ": identifier expected at index " + pos);
1269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        ++pos;
1271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (Character.isJavaIdentifierPart(getChar(signature, pos))) {
1272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++pos;
1273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return pos;
1275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks a single character.
1279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a string containing the signature that must be checked.
1281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param pos index of first character to be checked.
1282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the index of the first character after the checked part.
1283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static int checkChar(final char c, final String signature, int pos)
1285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (getChar(signature, pos) == c) {
1287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return pos + 1;
1288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        throw new IllegalArgumentException(signature + ": '" + c
1290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                + "' expected at index " + pos);
1291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Returns the signature car at the given index.
1295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature a signature.
1297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param pos an index in signature.
1298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the character at the given index, or 0 if there is no such
1299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *         character.
1300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static char getChar(final String signature, int pos) {
1302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return pos < signature.length() ? signature.charAt(pos) : (char) 0;
1303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks that the given label is not null. This method can also check that
1307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * the label has been visited.
1308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param label the label to be checked.
1310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param checkVisited <tt>true</tt> to check that the label has been
1311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        visited.
1312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param msg a message to be used in case of error.
1313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    void checkLabel(
1315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label label,
1316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final boolean checkVisited,
1317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String msg)
1318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (label == null) {
1320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid " + msg
1321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " (must not be null)");
1322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (checkVisited && labels.get(label) == null) {
1324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Invalid " + msg
1325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    + " (must be visited first)");
1326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen}
1329