* This method must be called after all the method that is being built has
* been visited. In particular, the {@link Label Label} objects used to
* construct the method are no longer valid after this method has been called.
*
* @param indexes current positions of the instructions to be resized. Each
* instruction must be designated by the index of its last byte,
* plus one (or, in other words, by the index of the first byte of
* the next instruction).
* @param sizes the number of bytes to be added to the above
* instructions. More precisely, for each i < len,
* sizes[i] bytes will be added at the end of the instruction
* designated by indexes[i] or, if sizes[i] is
* negative, the last |sizes[i]| bytes of the instruction
* will be removed (the instruction size must not become negative
* or null). The gaps introduced by this method must be filled in
* "manually" in the array returned by the {@link #getCode getCode}
* method.
* @param len the number of instruction to be resized. Must be smaller than or
* equal to indexes.length and sizes.length.
* @return the indexes array, which now contains the new positions of
* the resized instructions (designated as above).
*/
protected int[] resizeInstructions (
final int[] indexes,
final int[] sizes,
final int len)
{
byte[] b = code.data; // bytecode of the method
int u, v, label; // indexes in b
int i, j; // loop indexes
// 1st step:
// As explained above, resizing an instruction may require to resize another
// one, which may require to resize yet another one, and so on. The first
// step of the algorithm consists in finding all the instructions that
// need to be resized, without modifying the code. This is done by the
// following "fix point" algorithm:
// - parse the code to find the jump instructions whose offset will need
// more than 2 bytes to be stored (the future offset is computed from the
// current offset and from the number of bytes that will be inserted or
// removed between the source and target instructions). For each such
// instruction, adds an entry in (a copy of) the indexes and sizes arrays
// (if this has not already been done in a previous iteration!)
// - if at least one entry has been added during the previous step, go back
// to the beginning, otherwise stop.
// In fact the real algorithm is complicated by the fact that the size of
// TABLESWITCH and LOOKUPSWITCH instructions depends on their position in
// the bytecode (because of padding). In order to ensure the convergence of
// the algorithm, the number of bytes to be added or removed from these
// instructions is over estimated during the previous loop, and computed
// exactly only after the loop is finished (this requires another pass to
// parse the bytecode of the method).
int[] allIndexes = new int[len]; // copy of indexes
int[] allSizes = new int[len]; // copy of sizes
boolean[] resize; // instructions to be resized
int newOffset; // future offset of a jump instruction
System.arraycopy(indexes, 0, allIndexes, 0, len);
System.arraycopy(sizes, 0, allSizes, 0, len);
resize = new boolean[code.length];
int state = 3; // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done
do {
if (state == 3) {
state = 2;
}
u = 0;
while (u < b.length) {
int opcode = b[u] & 0xFF; // opcode of current instruction
int insert = 0; // bytes to be added after this instruction
switch (ClassWriter.TYPE[opcode]) {
case ClassWriter.NOARG_INSN:
case ClassWriter.IMPLVAR_INSN:
u += 1;
break;
case ClassWriter.LABEL_INSN:
if (opcode > 201) {
// converts temporary opcodes 202 to 217 (inclusive), 218 and 219
// to IFEQ ... JSR (inclusive), IFNULL and IFNONNULL
opcode = opcode < 218 ? opcode - 49 : opcode - 20;
label = u + readUnsignedShort(b, u + 1);
} else {
label = u + readShort(b, u + 1);
}
newOffset = getNewOffset(allIndexes, allSizes, u, label);
if (newOffset < Short.MIN_VALUE || newOffset > Short.MAX_VALUE) {
if (!resize[u]) {
if (opcode == Constants.GOTO || opcode == Constants.JSR) {
// two additional bytes will be required to replace this
// GOTO or JSR instruction with a GOTO_W or a JSR_W
insert = 2;
} else {
// five additional bytes will be required to replace this
// IFxxx
* Note: it is possible to have several entries for the same instruction
* in the indexes and sizes: two entries (index=a,size=b)
* and (index=a,size=b') are equivalent to a single entry (index=a,size=b+b').
*
* @param indexes current positions of the instructions to be resized. Each
* instruction must be designated by the index of its last byte,
* plus one (or, in other words, by the index of the first byte of
* the next instruction).
* @param sizes the number of bytes to be added to the above
* instructions. More precisely, for each i < len,
* sizes[i] bytes will be added at the end of the instruction
* designated by indexes[i] or, if sizes[i] is
* negative, the last |sizes[i]| bytes of the instruction
* will be removed (the instruction size must not become negative
* or null).
* @param begin index of the first byte of the source instruction.
* @param end index of the first byte of the target instruction.
* @return the future value of the given bytecode offset.
*/
static int getNewOffset (
final int[] indexes,
final int[] sizes,
final int begin,
final int end)
{
int offset = end - begin;
for (int i = 0; i < indexes.length; ++i) {
if (begin < indexes[i] && indexes[i] <= end) { // forward jump
offset += sizes[i];
} else if (end < indexes[i] && indexes[i] <= begin) { // backward jump
offset -= sizes[i];
}
}
return offset;
}
/**
* Returns the current size of the bytecode of this method. This size just
* includes the size of the bytecode instructions: it does not include the
* size of the Exceptions, LocalVariableTable, LineNumberTable, Synthetic
* and Deprecated attributes, if present.
*
* @return the current size of the bytecode of this method.
*/
protected int getCodeSize () {
return code.length;
}
/**
* Returns the current bytecode of this method. This bytecode only contains
* the instructions: it does not include the Exceptions, LocalVariableTable,
* LineNumberTable, Synthetic and Deprecated attributes, if present.
*
* @return the current bytecode of this method. The bytecode is contained
* between the index 0 (inclusive) and the index {@link #getCodeSize
* getCodeSize} (exclusive).
*/
protected byte[] getCode () {
return code.data;
}
}
bsh-2.0b4.orig/asm/src/bsh/org/objectweb/asm/Constants.java 0000644 0001750 0001750 00000022464 10243450010 022550 0 ustar wbaer wbaer /***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (C) 2000 INRIA, France Telecom
* Copyright (C) 2002 France Telecom
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package bsh.org.objectweb.asm;
/**
* Defines the JVM opcodes, access flags and array type codes. This interface
* does not define all the JVM opcodes because some opcodes are automatically
* handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
* by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n
* opcodes are therefore not defined in this interface. Likewise for LDC,
* automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
* JSR_W.
*/
public interface Constants {
// access flags
int ACC_PUBLIC = 1;
int ACC_PRIVATE = 2;
int ACC_PROTECTED = 4;
int ACC_STATIC = 8;
int ACC_FINAL = 16;
int ACC_SYNCHRONIZED = 32;
int ACC_VOLATILE = 64;
int ACC_TRANSIENT = 128;
int ACC_NATIVE = 256;
int ACC_INTERFACE = 512;
int ACC_ABSTRACT = 1024;
int ACC_STRICT = 2048;
int ACC_SUPER = 32;
int ACC_SYNTHETIC = 65536;
int ACC_DEPRECATED = 131072;
// types for NEWARRAY
int T_BOOLEAN = 4;
int T_CHAR = 5;
int T_FLOAT = 6;
int T_DOUBLE = 7;
int T_BYTE = 8;
int T_SHORT = 9;
int T_INT = 10;
int T_LONG = 11;
// opcodes // visit method (- = idem)
int NOP = 0; // visitInsn
int ACONST_NULL = 1; // -
int ICONST_M1 = 2; // -
int ICONST_0 = 3; // -
int ICONST_1 = 4; // -
int ICONST_2 = 5; // -
int ICONST_3 = 6; // -
int ICONST_4 = 7; // -
int ICONST_5 = 8; // -
int LCONST_0 = 9; // -
int LCONST_1 = 10; // -
int FCONST_0 = 11; // -
int FCONST_1 = 12; // -
int FCONST_2 = 13; // -
int DCONST_0 = 14; // -
int DCONST_1 = 15; // -
int BIPUSH = 16; // visitIntInsn
int SIPUSH = 17; // -
int LDC = 18; // visitLdcInsn
//int LDC_W = 19; // -
//int LDC2_W = 20; // -
int ILOAD = 21; // visitVarInsn
int LLOAD = 22; // -
int FLOAD = 23; // -
int DLOAD = 24; // -
int ALOAD = 25; // -
//int ILOAD_0 = 26; // -
//int ILOAD_1 = 27; // -
//int ILOAD_2 = 28; // -
//int ILOAD_3 = 29; // -
//int LLOAD_0 = 30; // -
//int LLOAD_1 = 31; // -
//int LLOAD_2 = 32; // -
//int LLOAD_3 = 33; // -
//int FLOAD_0 = 34; // -
//int FLOAD_1 = 35; // -
//int FLOAD_2 = 36; // -
//int FLOAD_3 = 37; // -
//int DLOAD_0 = 38; // -
//int DLOAD_1 = 39; // -
//int DLOAD_2 = 40; // -
//int DLOAD_3 = 41; // -
//int ALOAD_0 = 42; // -
//int ALOAD_1 = 43; // -
//int ALOAD_2 = 44; // -
//int ALOAD_3 = 45; // -
int IALOAD = 46; // visitInsn
int LALOAD = 47; // -
int FALOAD = 48; // -
int DALOAD = 49; // -
int AALOAD = 50; // -
int BALOAD = 51; // -
int CALOAD = 52; // -
int SALOAD = 53; // -
int ISTORE = 54; // visitVarInsn
int LSTORE = 55; // -
int FSTORE = 56; // -
int DSTORE = 57; // -
int ASTORE = 58; // -
//int ISTORE_0 = 59; // -
//int ISTORE_1 = 60; // -
//int ISTORE_2 = 61; // -
//int ISTORE_3 = 62; // -
//int LSTORE_0 = 63; // -
//int LSTORE_1 = 64; // -
//int LSTORE_2 = 65; // -
//int LSTORE_3 = 66; // -
//int FSTORE_0 = 67; // -
//int FSTORE_1 = 68; // -
//int FSTORE_2 = 69; // -
//int FSTORE_3 = 70; // -
//int DSTORE_0 = 71; // -
//int DSTORE_1 = 72; // -
//int DSTORE_2 = 73; // -
//int DSTORE_3 = 74; // -
//int ASTORE_0 = 75; // -
//int ASTORE_1 = 76; // -
//int ASTORE_2 = 77; // -
//int ASTORE_3 = 78; // -
int IASTORE = 79; // visitInsn
int LASTORE = 80; // -
int FASTORE = 81; // -
int DASTORE = 82; // -
int AASTORE = 83; // -
int BASTORE = 84; // -
int CASTORE = 85; // -
int SASTORE = 86; // -
int POP = 87; // -
int POP2 = 88; // -
int DUP = 89; // -
int DUP_X1 = 90; // -
int DUP_X2 = 91; // -
int DUP2 = 92; // -
int DUP2_X1 = 93; // -
int DUP2_X2 = 94; // -
int SWAP = 95; // -
int IADD = 96; // -
int LADD = 97; // -
int FADD = 98; // -
int DADD = 99; // -
int ISUB = 100; // -
int LSUB = 101; // -
int FSUB = 102; // -
int DSUB = 103; // -
int IMUL = 104; // -
int LMUL = 105; // -
int FMUL = 106; // -
int DMUL = 107; // -
int IDIV = 108; // -
int LDIV = 109; // -
int FDIV = 110; // -
int DDIV = 111; // -
int IREM = 112; // -
int LREM = 113; // -
int FREM = 114; // -
int DREM = 115; // -
int INEG = 116; // -
int LNEG = 117; // -
int FNEG = 118; // -
int DNEG = 119; // -
int ISHL = 120; // -
int LSHL = 121; // -
int ISHR = 122; // -
int LSHR = 123; // -
int IUSHR = 124; // -
int LUSHR = 125; // -
int IAND = 126; // -
int LAND = 127; // -
int IOR = 128; // -
int LOR = 129; // -
int IXOR = 130; // -
int LXOR = 131; // -
int IINC = 132; // visitIincInsn
int I2L = 133; // visitInsn
int I2F = 134; // -
int I2D = 135; // -
int L2I = 136; // -
int L2F = 137; // -
int L2D = 138; // -
int F2I = 139; // -
int F2L = 140; // -
int F2D = 141; // -
int D2I = 142; // -
int D2L = 143; // -
int D2F = 144; // -
int I2B = 145; // -
int I2C = 146; // -
int I2S = 147; // -
int LCMP = 148; // -
int FCMPL = 149; // -
int FCMPG = 150; // -
int DCMPL = 151; // -
int DCMPG = 152; // -
int IFEQ = 153; // visitJumpInsn
int IFNE = 154; // -
int IFLT = 155; // -
int IFGE = 156; // -
int IFGT = 157; // -
int IFLE = 158; // -
int IF_ICMPEQ = 159; // -
int IF_ICMPNE = 160; // -
int IF_ICMPLT = 161; // -
int IF_ICMPGE = 162; // -
int IF_ICMPGT = 163; // -
int IF_ICMPLE = 164; // -
int IF_ACMPEQ = 165; // -
int IF_ACMPNE = 166; // -
int GOTO = 167; // -
int JSR = 168; // -
int RET = 169; // visitVarInsn
int TABLESWITCH = 170; // visiTableSwitchInsn
int LOOKUPSWITCH = 171; // visitLookupSwitch
int IRETURN = 172; // visitInsn
int LRETURN = 173; // -
int FRETURN = 174; // -
int DRETURN = 175; // -
int ARETURN = 176; // -
int RETURN = 177; // -
int GETSTATIC = 178; // visitFieldInsn
int PUTSTATIC = 179; // -
int GETFIELD = 180; // -
int PUTFIELD = 181; // -
int INVOKEVIRTUAL = 182; // visitMethodInsn
int INVOKESPECIAL = 183; // -
int INVOKESTATIC = 184; // -
int INVOKEINTERFACE = 185; // -
//int UNUSED = 186; // NOT VISITED
int NEW = 187; // visitTypeInsn
int NEWARRAY = 188; // visitIntInsn
int ANEWARRAY = 189; // visitTypeInsn
int ARRAYLENGTH = 190; // visitInsn
int ATHROW = 191; // -
int CHECKCAST = 192; // visitTypeInsn
int INSTANCEOF = 193; // -
int MONITORENTER = 194; // visitInsn
int MONITOREXIT = 195; // -
//int WIDE = 196; // NOT VISITED
int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
int IFNULL = 198; // visitJumpInsn
int IFNONNULL = 199; // -
//int GOTO_W = 200; // -
//int JSR_W = 201; // -
}
bsh-2.0b4.orig/asm/src/bsh/org/objectweb/asm/Edge.java 0000644 0001750 0001750 00000003362 10243450010 021434 0 ustar wbaer wbaer /***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (C) 2000 INRIA, France Telecom
* Copyright (C) 2002 France Telecom
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package bsh.org.objectweb.asm;
/**
* An edge in the control flow graph of a method body. See {@link Label Label}.
*/
class Edge {
/**
* The (relative) stack size in the basic block from which this edge
* originates. This size is equal to the stack size at the "jump" instruction
* to which this edge corresponds, relatively to the stack size at the
* beginning of the originating basic block.
*/
int stackSize;
/**
* The successor block of the basic block from which this edge originates.
*/
Label successor;
/**
* The next edge in the list of successors of the originating basic block.
* See {@link Label#successors successors}.
*/
Edge next;
/**
* The next available edge in the pool. See {@link CodeWriter#pool pool}.
*/
Edge poolNext;
}
bsh-2.0b4.orig/asm/src/bsh/org/objectweb/asm/Item.java 0000644 0001750 0001750 00000014324 10243450010 021466 0 ustar wbaer wbaer /***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (C) 2000 INRIA, France Telecom
* Copyright (C) 2002 France Telecom
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package bsh.org.objectweb.asm;
/**
* A constant pool item. Constant pool items can be created with the 'newXXX'
* methods in the {@link ClassWriter} class.
*/
final class Item {
/**
* Index of this item in the constant pool.
*/
short index;
/**
* Type of this constant pool item. A single class is used to represent all
* constant pool item types, in order to minimize the bytecode size of this
* package. The value of this field is one of the constants defined in the
* {@link ClassWriter ClassWriter} class.
*/
int type;
/**
* Value of this item, for a {@link ClassWriter#INT INT} item.
*/
int intVal;
/**
* Value of this item, for a {@link ClassWriter#LONG LONG} item.
*/
long longVal;
/**
* Value of this item, for a {@link ClassWriter#FLOAT FLOAT} item.
*/
float floatVal;
/**
* Value of this item, for a {@link ClassWriter#DOUBLE DOUBLE} item.
*/
double doubleVal;
/**
* First part of the value of this item, for items that do not hold a
* primitive value.
*/
String strVal1;
/**
* Second part of the value of this item, for items that do not hold a
* primitive value.
*/
String strVal2;
/**
* Third part of the value of this item, for items that do not hold a
* primitive value.
*/
String strVal3;
/**
* The hash code value of this constant pool item.
*/
int hashCode;
/**
* Link to another constant pool item, used for collision lists in the
* constant pool's hash table.
*/
Item next;
/**
* Constructs an uninitialized {@link Item Item} object.
*/
Item () {
}
/**
* Constructs a copy of the given item.
*
* @param index index of the item to be constructed.
* @param i the item that must be copied into the item to be constructed.
*/
Item (final short index, final Item i) {
this.index = index;
type = i.type;
intVal = i.intVal;
longVal = i.longVal;
floatVal = i.floatVal;
doubleVal = i.doubleVal;
strVal1 = i.strVal1;
strVal2 = i.strVal2;
strVal3 = i.strVal3;
hashCode = i.hashCode;
}
/**
* Sets this item to an {@link ClassWriter#INT INT} item.
*
* @param intVal the value of this item.
*/
void set (final int intVal) {
this.type = ClassWriter.INT;
this.intVal = intVal;
this.hashCode = type + intVal;
}
/**
* Sets this item to a {@link ClassWriter#LONG LONG} item.
*
* @param longVal the value of this item.
*/
void set (final long longVal) {
this.type = ClassWriter.LONG;
this.longVal = longVal;
this.hashCode = type + (int)longVal;
}
/**
* Sets this item to a {@link ClassWriter#FLOAT FLOAT} item.
*
* @param floatVal the value of this item.
*/
void set (final float floatVal) {
this.type = ClassWriter.FLOAT;
this.floatVal = floatVal;
this.hashCode = type + (int)floatVal;
}
/**
* Sets this item to a {@link ClassWriter#DOUBLE DOUBLE} item.
*
* @param doubleVal the value of this item.
*/
void set (final double doubleVal) {
this.type = ClassWriter.DOUBLE;
this.doubleVal = doubleVal;
this.hashCode = type + (int)doubleVal;
}
/**
* Sets this item to an item that do not hold a primitive value.
*
* @param type the type of this item.
* @param strVal1 first part of the value of this item.
* @param strVal2 second part of the value of this item.
* @param strVal3 third part of the value of this item.
*/
void set (
final int type,
final String strVal1,
final String strVal2,
final String strVal3)
{
this.type = type;
this.strVal1 = strVal1;
this.strVal2 = strVal2;
this.strVal3 = strVal3;
switch (type) {
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.CLASS:
hashCode = type + strVal1.hashCode();
return;
case ClassWriter.NAME_TYPE:
hashCode = type + strVal1.hashCode()*strVal2.hashCode();
return;
//case ClassWriter.FIELD:
//case ClassWriter.METH:
//case ClassWriter.IMETH:
default:
hashCode = type + strVal1.hashCode()*strVal2.hashCode()*strVal3.hashCode();
return;
}
}
/**
* Indicates if the given item is equal to this one.
*
* @param i the item to be compared to this one.
* @return true if the given item if equal to this one,
* false otherwise.
*/
boolean isEqualTo (final Item i) {
if (i.type == type) {
switch (type) {
case ClassWriter.INT:
return i.intVal == intVal;
case ClassWriter.LONG:
return i.longVal == longVal;
case ClassWriter.FLOAT:
return i.floatVal == floatVal;
case ClassWriter.DOUBLE:
return i.doubleVal == doubleVal;
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.CLASS:
return i.strVal1.equals(strVal1);
case ClassWriter.NAME_TYPE:
return i.strVal1.equals(strVal1) &&
i.strVal2.equals(strVal2);
//case ClassWriter.FIELD:
//case ClassWriter.METH:
//case ClassWriter.IMETH:
default:
return i.strVal1.equals(strVal1) &&
i.strVal2.equals(strVal2) &&
i.strVal3.equals(strVal3);
}
}
return false;
}
}
bsh-2.0b4.orig/asm/src/bsh/org/objectweb/asm/Label.java 0000644 0001750 0001750 00000023145 10243450010 021610 0 ustar wbaer wbaer /***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (C) 2000 INRIA, France Telecom
* Copyright (C) 2002 France Telecom
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package bsh.org.objectweb.asm;
/**
* A label represents a position in the bytecode of a method. Labels are used
* for jump, goto, and switch instructions, and for try catch blocks.
*/
public class Label {
/**
* The code writer to which this label belongs, or null if unknown.
*/
CodeWriter owner;
/**
* Indicates if the position of this label is known.
*/
boolean resolved;
/**
* The position of this label in the code, if known.
*/
int position;
/**
* Number of forward references to this label, times two.
*/
private int referenceCount;
/**
* Informations about forward references. Each forward reference is described
* by two consecutive integers in this array: the first one is the position
* of the first byte of the bytecode instruction that contains the forward
* reference, while the second is the position of the first byte of the
* forward reference itself. In fact the sign of the first integer indicates
* if this reference uses 2 or 4 bytes, and its absolute value gives the
* position of the bytecode instruction.
*/
private int[] srcAndRefPositions;
// --------------------------------------------------------------------------
// Fields for the control flow graph analysis algorithm (used to compute the
// maximum stack size). A control flow graph contains one node per "basic
// block", and one edge per "jump" from one basic block to another. Each node
// (i.e., each basic block) is represented by the Label object that
// corresponds to the first instruction of this basic block. Each node also
// stores the list of it successors in the graph, as a linked list of Edge
// objects.
// --------------------------------------------------------------------------
/**
* The stack size at the beginning of this basic block.
* This size is initially unknown. It is computed by the control flow
* analysis algorithm (see {@link CodeWriter#visitMaxs visitMaxs}).
*/
int beginStackSize;
/**
* The (relative) maximum stack size corresponding to this basic block. This
* size is relative to the stack size at the beginning of the basic block,
* i.e., the true maximum stack size is equal to {@link #beginStackSize
* beginStackSize} + {@link #maxStackSize maxStackSize}.
*/
int maxStackSize;
/**
* The successors of this node in the control flow graph. These successors
* are stored in a linked list of {@link Edge Edge} objects, linked to each
* other by their {@link Edge#next} field.
*/
Edge successors;
/**
* The next basic block in the basic block stack.
* See {@link CodeWriter#visitMaxs visitMaxs}.
*/
Label next;
/**
* true if this basic block has been pushed in the basic block stack.
* See {@link CodeWriter#visitMaxs visitMaxs}.
*/
boolean pushed;
// --------------------------------------------------------------------------
// Constructor
// --------------------------------------------------------------------------
/**
* Constructs a new label.
*/
public Label () {
}
// --------------------------------------------------------------------------
// Methods to compute offsets and to manage forward references
// --------------------------------------------------------------------------
/**
* Puts a reference to this label in the bytecode of a method. If the position
* of the label is known, the offset is computed and written directly.
* Otherwise, a null offset is written and a new forward reference is declared
* for this label.
*
* @param owner the code writer that calls this method.
* @param out the bytecode of the method.
* @param source the position of first byte of the bytecode instruction that
* contains this label.
* @param wideOffset true if the reference must be stored in 4 bytes,
* or false if it must be stored with 2 bytes.
* @throws IllegalArgumentException if this label has not been created by the
* given code writer.
*/
void put (
final CodeWriter owner,
final ByteVector out,
final int source,
final boolean wideOffset)
{
if (CodeWriter.CHECK) {
if (this.owner == null) {
this.owner = owner;
} else if (this.owner != owner) {
throw new IllegalArgumentException();
}
}
if (resolved) {
if (wideOffset) {
out.put4(position - source);
} else {
out.put2(position - source);
}
} else {
if (wideOffset) {
addReference(-1 - source, out.length);
out.put4(-1);
} else {
addReference(source, out.length);
out.put2(-1);
}
}
}
/**
* Adds a forward reference to this label. This method must be called only for
* a true forward reference, i.e. only if this label is not resolved yet. For
* backward references, the offset of the reference can be, and must be,
* computed and stored directly.
*
* @param sourcePosition the position of the referencing instruction. This
* position will be used to compute the offset of this forward reference.
* @param referencePosition the position where the offset for this forward
* reference must be stored.
*/
private void addReference (
final int sourcePosition,
final int referencePosition)
{
if (srcAndRefPositions == null) {
srcAndRefPositions = new int[6];
}
if (referenceCount >= srcAndRefPositions.length) {
int[] a = new int[srcAndRefPositions.length + 6];
System.arraycopy(srcAndRefPositions, 0, a, 0, srcAndRefPositions.length);
srcAndRefPositions = a;
}
srcAndRefPositions[referenceCount++] = sourcePosition;
srcAndRefPositions[referenceCount++] = referencePosition;
}
/**
* Resolves all forward references to this label. This method must be called
* when this label is added to the bytecode of the method, i.e. when its
* position becomes known. This method fills in the blanks that where left in
* the bytecode by each forward reference previously added to this label.
*
* @param owner the code writer that calls this method.
* @param position the position of this label in the bytecode.
* @param data the bytecode of the method.
* @return true if a blank that was left for this label was to small
* to store the offset. In such a case the corresponding jump instruction
* is replaced with a pseudo instruction (using unused opcodes) using an
* unsigned two bytes offset. These pseudo instructions will need to be
* replaced with true instructions with wider offsets (4 bytes instead of
* 2). This is done in {@link CodeWriter#resizeInstructions}.
* @throws IllegalArgumentException if this label has already been resolved,
* or if it has not been created by the given code writer.
*/
boolean resolve (
final CodeWriter owner,
final int position,
final byte[] data)
{
if (CodeWriter.CHECK) {
if (this.owner == null) {
this.owner = owner;
}
if (resolved || this.owner != owner) {
throw new IllegalArgumentException();
}
}
boolean needUpdate = false;
this.resolved = true;
this.position = position;
int i = 0;
while (i < referenceCount) {
int source = srcAndRefPositions[i++];
int reference = srcAndRefPositions[i++];
int offset;
if (source >= 0) {
offset = position - source;
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
// changes the opcode of the jump instruction, in order to be able to
// find it later (see resizeInstructions in CodeWriter). These
// temporary opcodes are similar to jump instruction opcodes, except
// that the 2 bytes offset is unsigned (and can therefore represent
// values from 0 to 65535, which is sufficient since the size of a
// method is limited to 65535 bytes).
int opcode = data[reference - 1] & 0xFF;
if (opcode <= Constants.JSR) {
// changes IFEQ ... JSR to opcodes 202 to 217 (inclusive)
data[reference - 1] = (byte)(opcode + 49);
} else {
// changes IFNULL and IFNONNULL to opcodes 218 and 219 (inclusive)
data[reference - 1] = (byte)(opcode + 20);
}
needUpdate = true;
}
data[reference++] = (byte)(offset >>> 8);
data[reference] = (byte)offset;
} else {
offset = position + source + 1;
data[reference++] = (byte)(offset >>> 24);
data[reference++] = (byte)(offset >>> 16);
data[reference++] = (byte)(offset >>> 8);
data[reference] = (byte)offset;
}
}
return needUpdate;
}
}
bsh-2.0b4.orig/asm/src/bsh/org/objectweb/asm/Type.java 0000644 0001750 0001750 00000043524 10243450010 021515 0 ustar wbaer wbaer /***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (C) 2000 INRIA, France Telecom
* Copyright (C) 2002 France Telecom
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package bsh.org.objectweb.asm;
import java.lang.reflect.Method;
/**
* A Java type. This class can be used to make it easier to manipulate type
* and method descriptors.
*/
public class Type {
/**
* The sort of the void type. See {@link #getSort getSort}.
*/
public final static int VOID = 0;
/**
* The sort of the boolean type. See {@link #getSort getSort}.
*/
public final static int BOOLEAN = 1;
/**
* The sort of the char type. See {@link #getSort getSort}.
*/
public final static int CHAR = 2;
/**
* The sort of the byte type. See {@link #getSort getSort}.
*/
public final static int BYTE = 3;
/**
* The sort of the short type. See {@link #getSort getSort}.
*/
public final static int SHORT = 4;
/**
* The sort of the int type. See {@link #getSort getSort}.
*/
public final static int INT = 5;
/**
* The sort of the float type. See {@link #getSort getSort}.
*/
public final static int FLOAT = 6;
/**
* The sort of the long type. See {@link #getSort getSort}.
*/
public final static int LONG = 7;
/**
* The sort of the double type. See {@link #getSort getSort}.
*/
public final static int DOUBLE = 8;
/**
* The sort of array reference types. See {@link #getSort getSort}.
*/
public final static int ARRAY = 9;
/**
* The sort of object reference type. See {@link #getSort getSort}.
*/
public final static int OBJECT = 10;
/**
* The void type.
*/
public final static Type VOID_TYPE = new Type(VOID);
/**
* The boolean type.
*/
public final static Type BOOLEAN_TYPE = new Type(BOOLEAN);
/**
* The char type.
*/
public final static Type CHAR_TYPE = new Type(CHAR);
/**
* The byte type.
*/
public final static Type BYTE_TYPE = new Type(BYTE);
/**
* The short type.
*/
public final static Type SHORT_TYPE = new Type(SHORT);
/**
* The int type.
*/
public final static Type INT_TYPE = new Type(INT);
/**
* The float type.
*/
public final static Type FLOAT_TYPE = new Type(FLOAT);
/**
* The long type.
*/
public final static Type LONG_TYPE = new Type(LONG);
/**
* The double type.
*/
public final static Type DOUBLE_TYPE = new Type(DOUBLE);
// --------------------------------------------------------------------------
// Fields
// --------------------------------------------------------------------------
/**
* The sort of this Java type.
*/
private final int sort;
/**
* A buffer containing the descriptor of this Java type.
* This field is only used for reference types.
*/
private char[] buf;
/**
* The offset of the descriptor of this Java type in {@link #buf buf}.
* This field is only used for reference types.
*/
private int off;
/**
* The length of the descriptor of this Java type.
*/
private int len;
// --------------------------------------------------------------------------
// Constructors
// --------------------------------------------------------------------------
/**
* Constructs a primitive type.
*
* @param sort the sort of the primitive type to be constructed.
*/
private Type (final int sort) {
this.sort = sort;
this.len = 1;
}
/**
* Constructs a reference type.
*
* @param sort the sort of the reference type to be constructed.
* @param buf a buffer containing the descriptor of the previous type.
* @param off the offset of this descriptor in the previous buffer.
* @param len the length of this descriptor.
*/
private Type (
final int sort,
final char[] buf,
final int off,
final int len)
{
this.sort = sort;
this.buf = buf;
this.off = off;
this.len = len;
}
/**
* Returns the Java type corresponding to the given type descriptor.
*
* @param typeDescriptor a type descriptor.
* @return the Java type corresponding to the given type descriptor.
*/
public static Type getType (final String typeDescriptor) {
return getType(typeDescriptor.toCharArray(), 0);
}
/**
* Returns the Java type corresponding to the given class.
*
* @param c a class.
* @return the Java type corresponding to the given class.
*/
public static Type getType (final Class c) {
if (c.isPrimitive()) {
if (c == Integer.TYPE) {
return INT_TYPE;
} else if (c == Void.TYPE) {
return VOID_TYPE;
} else if (c == Boolean.TYPE) {
return BOOLEAN_TYPE;
} else if (c == Byte.TYPE) {
return BYTE_TYPE;
} else if (c == Character.TYPE) {
return CHAR_TYPE;
} else if (c == Short.TYPE) {
return SHORT_TYPE;
} else if (c == Double.TYPE) {
return DOUBLE_TYPE;
} else if (c == Float.TYPE) {
return FLOAT_TYPE;
} else /*if (c == Long.TYPE)*/ {
return LONG_TYPE;
}
} else {
return getType(getDescriptor(c));
}
}
/**
* Returns the Java types corresponding to the argument types of the given
* method descriptor.
*
* @param methodDescriptor a method descriptor.
* @return the Java types corresponding to the argument types of the given
* method descriptor.
*/
public static Type[] getArgumentTypes (final String methodDescriptor) {
char[] buf = methodDescriptor.toCharArray();
int off = 1;
int size = 0;
while (true) {
char car = buf[off++];
if (car == ')') {
break;
} else if (car == 'L') {
while (buf[off++] != ';') {
}
++size;
} else if (car != '[') {
++size;
}
}
Type[] args = new Type[size];
off = 1;
size = 0;
while (buf[off] != ')') {
args[size] = getType(buf, off);
off += args[size].len;
size += 1;
}
return args;
}
/**
* Returns the Java types corresponding to the argument types of the given
* method.
*
* @param method a method.
* @return the Java types corresponding to the argument types of the given
* method.
*/
public static Type[] getArgumentTypes (final Method method) {
Class[] classes = method.getParameterTypes();
Type[] types = new Type[classes.length];
for (int i = classes.length - 1; i >= 0; --i) {
types[i] = getType(classes[i]);
}
return types;
}
/**
* Returns the Java type corresponding to the return type of the given
* method descriptor.
*
* @param methodDescriptor a method descriptor.
* @return the Java type corresponding to the return type of the given
* method descriptor.
*/
public static Type getReturnType (final String methodDescriptor) {
char[] buf = methodDescriptor.toCharArray();
return getType(buf, methodDescriptor.indexOf(')') + 1);
}
/**
* Returns the Java type corresponding to the return type of the given
* method.
*
* @param method a method.
* @return the Java type corresponding to the return type of the given
* method.
*/
public static Type getReturnType (final Method method) {
return getType(method.getReturnType());
}
/**
* Returns the Java type corresponding to the given type descriptor.
*
* @param buf a buffer containing a type descriptor.
* @param off the offset of this descriptor in the previous buffer.
* @return the Java type corresponding to the given type descriptor.
*/
private static Type getType (final char[] buf, final int off) {
int len;
switch (buf[off]) {
case 'V': return VOID_TYPE;
case 'Z': return BOOLEAN_TYPE;
case 'C': return CHAR_TYPE;
case 'B': return BYTE_TYPE;
case 'S': return SHORT_TYPE;
case 'I': return INT_TYPE;
case 'F': return FLOAT_TYPE;
case 'J': return LONG_TYPE;
case 'D': return DOUBLE_TYPE;
case '[':
len = 1;
while (buf[off + len] == '[') {
++len;
}
if (buf[off + len] == 'L') {
++len;
while (buf[off + len] != ';') {
++len;
}
}
return new Type(ARRAY, buf, off, len + 1);
//case 'L':
default:
len = 1;
while (buf[off + len] != ';') {
++len;
}
return new Type(OBJECT, buf, off, len + 1);
}
}
// --------------------------------------------------------------------------
// Accessors
// --------------------------------------------------------------------------
/**
* Returns the sort of this Java type.
*
* @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},
* {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, {@link
* #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, {@link
* #ARRAY ARRAY} or {@link #OBJECT OBJECT}.
*/
public int getSort () {
return sort;
}
/**
* Returns the number of dimensions of this array type.
* This method should only be used for an array type.
*
* @return the number of dimensions of this array type.
*/
public int getDimensions () {
int i = 1;
while (buf[off + i] == '[') {
++i;
}
return i;
}
/**
* Returns the type of the elements of this array type.
* This method should only be used for an array type.
*
* @return Returns the type of the elements of this array type.
*/
public Type getElementType () {
return getType(buf, off + getDimensions());
}
/**
* Returns the name of the class corresponding to this object type.
* This method should only be used for an object type.
*
* @return the fully qualified name of the class corresponding to this object
* type.
*/
public String getClassName () {
return new String(buf, off + 1, len - 2).replace('/', '.');
}
/**
* Returns the internal name of the class corresponding to this object type.
* The internal name of a class is its fully qualified name, where '.' are
* replaced by '/'. * This method should only be used for an object type.
*
* @return the internal name of the class corresponding to this object type.
*/
public String getInternalName () {
return new String(buf, off + 1, len - 2);
}
// --------------------------------------------------------------------------
// Conversion to type descriptors
// --------------------------------------------------------------------------
/**
* Returns the descriptor corresponding to this Java type.
*
* @return the descriptor corresponding to this Java type.
*/
public String getDescriptor () {
StringBuffer buf = new StringBuffer();
getDescriptor(buf);
return buf.toString();
}
/**
* Returns the descriptor corresponding to the given argument and return
* types.
*
* @param returnType the return type of the method.
* @param argumentTypes the argument types of the method.
* @return the descriptor corresponding to the given argument and return
* types.
*/
public static String getMethodDescriptor (
final Type returnType,
final Type[] argumentTypes)
{
StringBuffer buf = new StringBuffer();
buf.append('(');
for (int i = 0; i < argumentTypes.length; ++i) {
argumentTypes[i].getDescriptor(buf);
}
buf.append(')');
returnType.getDescriptor(buf);
return buf.toString();
}
/**
* Appends the descriptor corresponding to this Java type to the given string
* buffer.
*
* @param buf the string buffer to which the descriptor must be appended.
*/
private void getDescriptor (final StringBuffer buf) {
switch (sort) {
case VOID: buf.append('V'); return;
case BOOLEAN: buf.append('Z'); return;
case CHAR: buf.append('C'); return;
case BYTE: buf.append('B'); return;
case SHORT: buf.append('S'); return;
case INT: buf.append('I'); return;
case FLOAT: buf.append('F'); return;
case LONG: buf.append('J'); return;
case DOUBLE: buf.append('D'); return;
//case ARRAY:
//case OBJECT:
default: buf.append(this.buf, off, len);
}
}
// --------------------------------------------------------------------------
// Direct conversion from classes to type descriptors,
// without intermediate Type objects
// --------------------------------------------------------------------------
/**
* Returns the internal name of the given class. The internal name of a class
* is its fully qualified name, where '.' are replaced by '/'.
*
* @param c an object class.
* @return the internal name of the given class.
*/
public static String getInternalName (final Class c) {
return c.getName().replace('.', '/');
}
/**
* Returns the descriptor corresponding to the given Java type.
*
* @param c an object class, a primitive class or an array class.
* @return the descriptor corresponding to the given class.
*/
public static String getDescriptor (final Class c) {
StringBuffer buf = new StringBuffer();
getDescriptor(buf, c);
return buf.toString();
}
/**
* Returns the descriptor corresponding to the given method.
*
* @param m a {@link Method Method} object.
* @return the descriptor of the given method.
*/
public static String getMethodDescriptor (final Method m) {
Class[] parameters = m.getParameterTypes();
StringBuffer buf = new StringBuffer();
buf.append('(');
for (int i = 0; i < parameters.length; ++i) {
getDescriptor(buf, parameters[i]);
}
buf.append(')');
getDescriptor(buf, m.getReturnType());
return buf.toString();
}
/**
* Appends the descriptor of the given class to the given string buffer.
*
* @param buf the string buffer to which the descriptor must be appended.
* @param c the class whose descriptor must be computed.
*/
private static void getDescriptor (final StringBuffer buf, final Class c) {
Class d = c;
while (true) {
if (d.isPrimitive()) {
char car;
if (d == Integer.TYPE) {
car = 'I';
} else if (d == Void.TYPE) {
car = 'V';
} else if (d == Boolean.TYPE) {
car = 'Z';
} else if (d == Byte.TYPE) {
car = 'B';
} else if (d == Character.TYPE) {
car = 'C';
} else if (d == Short.TYPE) {
car = 'S';
} else if (d == Double.TYPE) {
car = 'D';
} else if (d == Float.TYPE) {
car = 'F';
} else /*if (d == Long.TYPE)*/ {
car = 'J';
}
buf.append(car);
return;
} else if (d.isArray()) {
buf.append('[');
d = d.getComponentType();
} else {
buf.append('L');
String name = d.getName();
int len = name.length();
for (int i = 0; i < len; ++i) {
char car = name.charAt(i);
buf.append(car == '.' ? '/' : car);
}
buf.append(';');
return;
}
}
}
// --------------------------------------------------------------------------
// Corresponding size and opcodes
// --------------------------------------------------------------------------
/**
* Returns the size of values of this type.
*
* @return the size of values of this type, i.e., 2 for long and
* double, and 1 otherwise.
*/
public int getSize () {
return (sort == LONG || sort == DOUBLE ? 2 : 1);
}
/**
* Returns a JVM instruction opcode adapted to this Java type.
*
* @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
* ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
* ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
* @return an opcode that is similar to the given opcode, but adapted to this
* Java type. For example, if this type is float and
* opcode is IRETURN, this method returns FRETURN.
*/
public int getOpcode (final int opcode) {
if (opcode == Constants.IALOAD || opcode == Constants.IASTORE) {
switch (sort) {
case VOID:
return opcode + 5;
case BOOLEAN:
case BYTE:
return opcode + 6;
case CHAR:
return opcode + 7;
case SHORT:
return opcode + 8;
case INT:
return opcode;
case FLOAT:
return opcode + 2;
case LONG:
return opcode + 1;
case DOUBLE:
return opcode + 3;
//case ARRAY:
//case OBJECT:
default:
return opcode + 4;
}
} else {
switch (sort) {
case VOID:
return opcode + 5;
case BOOLEAN:
case CHAR:
case BYTE:
case SHORT:
case INT:
return opcode;
case FLOAT:
return opcode + 2;
case LONG:
return opcode + 1;
case DOUBLE:
return opcode + 3;
//case ARRAY:
//case OBJECT:
default:
return opcode + 4;
}
}
}
}
bsh-2.0b4.orig/asm/README-asm.txt 0000644 0001750 0001750 00000001011 10243450010 015310 0 ustar wbaer wbaer
These files are part of the org.objectweb.asm distribution.
(http://asm.objectweb.org) and are included under the terms of the LGPL license.
ASM is a very light weight, fast, visitor-pattern style Java byte code
reader / generator.
We have repackaged these classes under a "bsh." prefix for two reasons:
1) BeanShell uses the subset of ASM only for writing classes and
2) Since BeanShell is widely distributed we don't want to break the ability
of script writers to use updated versions of ASM in their scripts.
bsh-2.0b4.orig/bsf/ 0000755 0001750 0001750 00000000000 10243450010 013035 5 ustar wbaer wbaer bsh-2.0b4.orig/bsf/src/ 0000755 0001750 0001750 00000000000 10243450010 013624 5 ustar wbaer wbaer bsh-2.0b4.orig/bsf/src/bsh/ 0000755 0001750 0001750 00000000000 10243450010 014400 5 ustar wbaer wbaer bsh-2.0b4.orig/bsf/src/bsh/util/ 0000755 0001750 0001750 00000000000 10243450010 015355 5 ustar wbaer wbaer bsh-2.0b4.orig/bsf/src/bsh/util/BeanShellBSFEngine.java 0000644 0001750 0001750 00000016463 10243450010 021550 0 ustar wbaer wbaer package bsh.util;
/*
This file is associated with the BeanShell Java Scripting language
distribution (http://www.beanshell.org/).
This file is hereby placed into the public domain... You may copy,
modify, and redistribute it without restriction.
*/
import java.util.Vector;
import org.apache.bsf.*;
import org.apache.bsf.util.*;
import bsh.Interpreter;
import bsh.InterpreterError;
import bsh.EvalError;
import bsh.TargetError;
import bsh.Primitive;
/**
This is the BeanShell adapter for IBM's Bean Scripting Famework.
It is an implementation of the BSFEngine class, allowing BSF aware
applications to use BeanShell as a scripting language.
I believe this implementation is complete (with some hesitation about the
the usefullness of the compileXXX() style methods - provided by the base
utility class).