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 * '<init>' or '<clinit>'. 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