summaryrefslogtreecommitdiffstats
path: root/asm4/examples
diff options
context:
space:
mode:
authorYohann Roussel <yroussel@google.com>2014-02-06 15:24:30 +0100
committerYohann Roussel <yroussel@google.com>2014-02-06 18:32:39 +0100
commite991948d20515a04e46524dbe1bf17222e872889 (patch)
tree63c7abc9002ff6054700beff5680d206701244b7 /asm4/examples
parent1b0adcc591ba181dce100b0ca70d5a63eae43807 (diff)
downloadtoolchain_jill-e991948d20515a04e46524dbe1bf17222e872889.tar.gz
toolchain_jill-e991948d20515a04e46524dbe1bf17222e872889.tar.bz2
toolchain_jill-e991948d20515a04e46524dbe1bf17222e872889.zip
Jack initial import.
Change-Id: I8d1fc53d705d25429514842aac2368d9b87c8c6f
Diffstat (limited to 'asm4/examples')
-rw-r--r--asm4/examples/adapt/etc/execute.properties32
-rw-r--r--asm4/examples/adapt/src/Adapt.java196
-rw-r--r--asm4/examples/adapt/src/ArraySet.java94
-rw-r--r--asm4/examples/analysis/etc/execute.properties32
-rw-r--r--asm4/examples/analysis/src/Analysis.java182
-rw-r--r--asm4/examples/annotations/build.xml89
-rw-r--r--asm4/examples/annotations/etc/execute.properties32
-rw-r--r--asm4/examples/annotations/src/Annotations.java137
-rw-r--r--asm4/examples/annotations/src/NotNull.java36
-rw-r--r--asm4/examples/attributes/etc/execute.properties32
-rw-r--r--asm4/examples/attributes/src/Attributes.java144
-rw-r--r--asm4/examples/common/README.txt43
-rw-r--r--asm4/examples/common/build.xml97
-rw-r--r--asm4/examples/common/etc/build.properties68
-rw-r--r--asm4/examples/compile-indy/etc/execute.properties32
-rw-r--r--asm4/examples/compile-indy/src/IndyCompile.java368
-rw-r--r--asm4/examples/compile-indy/src/RT.java329
-rw-r--r--asm4/examples/compile/etc/execute.properties32
-rw-r--r--asm4/examples/compile/src/Compile.java293
-rw-r--r--asm4/examples/compile/src/Expression.java48
-rw-r--r--asm4/examples/dependencies/etc/execute.properties32
-rw-r--r--asm4/examples/dependencies/src/org/objectweb/asm/depend/DependencyTracker.java201
-rw-r--r--asm4/examples/dependencies/src/org/objectweb/asm/depend/DependencyVisitor.java356
-rw-r--r--asm4/examples/helloworld/etc/execute.properties32
-rw-r--r--asm4/examples/helloworld/src/Helloworld.java139
-rw-r--r--asm4/examples/jasmin/etc/execute.properties32
-rw-r--r--asm4/examples/jasmin/src/JasminifierClassAdapter.java900
-rw-r--r--asm4/examples/jasmin/test/JasminifierClassAdapterTest.java280
-rw-r--r--asm4/examples/jasmin/test/build.xml74
-rw-r--r--asm4/examples/jasmin/test/jasmin.jarbin0 -> 128766 bytes
-rw-r--r--asm4/examples/jbfc/etc/execute.properties32
-rw-r--r--asm4/examples/jbfc/src/jbfc.java86
-rw-r--r--asm4/examples/jbfc/src/org/objectweb/asm/jbfc/BFCompiler.java206
-rw-r--r--asm4/examples/jbfc/src/org/objectweb/asm/jbfc/BFCompilerTest.java174
-rw-r--r--asm4/examples/xml/annotate.xsl112
-rw-r--r--asm4/examples/xml/copy.xsl45
-rw-r--r--asm4/examples/xml/linenumbers.xsl70
-rw-r--r--asm4/examples/xml/profile.xsl103
-rw-r--r--asm4/examples/xml/readme.txt60
-rw-r--r--asm4/examples/xml/strip.xsl58
40 files changed, 5308 insertions, 0 deletions
diff --git a/asm4/examples/adapt/etc/execute.properties b/asm4/examples/adapt/etc/execute.properties
new file mode 100644
index 0000000..e7fea9d
--- /dev/null
+++ b/asm4/examples/adapt/etc/execute.properties
@@ -0,0 +1,32 @@
+###############################################################################
+#ASM: a very small and fast Java bytecode manipulation framework
+#Copyright (c) 2000-2011 INRIA, France Telecom
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+#THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################
+
+run.classname Adapt
+run.parameters ArraySet
diff --git a/asm4/examples/adapt/src/Adapt.java b/asm4/examples/adapt/src/Adapt.java
new file mode 100644
index 0000000..011f364
--- /dev/null
+++ b/asm4/examples/adapt/src/Adapt.java
@@ -0,0 +1,196 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+/**
+ * @author Eric Bruneton
+ */
+public class Adapt extends ClassLoader {
+
+ @Override
+ protected synchronized Class<?> loadClass(final String name,
+ final boolean resolve) throws ClassNotFoundException {
+ if (name.startsWith("java.")) {
+ System.err.println("Adapt: loading class '" + name
+ + "' without on the fly adaptation");
+ return super.loadClass(name, resolve);
+ } else {
+ System.err.println("Adapt: loading class '" + name
+ + "' with on the fly adaptation");
+ }
+
+ // gets an input stream to read the bytecode of the class
+ String resource = name.replace('.', '/') + ".class";
+ InputStream is = getResourceAsStream(resource);
+ byte[] b;
+
+ // adapts the class on the fly
+ try {
+ ClassReader cr = new ClassReader(is);
+ ClassWriter cw = new ClassWriter(0);
+ ClassVisitor cv = new TraceFieldClassAdapter(cw);
+ cr.accept(cv, 0);
+ b = cw.toByteArray();
+ } catch (Exception e) {
+ throw new ClassNotFoundException(name, e);
+ }
+
+ // optional: stores the adapted class on disk
+ try {
+ FileOutputStream fos = new FileOutputStream(resource + ".adapted");
+ fos.write(b);
+ fos.close();
+ } catch (IOException e) {
+ }
+
+ // returns the adapted class
+ return defineClass(name, b, 0, b.length);
+ }
+
+ public static void main(final String args[]) throws Exception {
+ // loads the application class (in args[0]) with an Adapt class loader
+ ClassLoader loader = new Adapt();
+ Class<?> c = loader.loadClass(args[0]);
+ // calls the 'main' static method of this class with the
+ // application arguments (in args[1] ... args[n]) as parameter
+ Method m = c.getMethod("main", new Class<?>[] { String[].class });
+ String[] applicationArgs = new String[args.length - 1];
+ System.arraycopy(args, 1, applicationArgs, 0, applicationArgs.length);
+ m.invoke(null, new Object[] { applicationArgs });
+ }
+}
+
+class TraceFieldClassAdapter extends ClassVisitor implements Opcodes {
+
+ private String owner;
+
+ public TraceFieldClassAdapter(final ClassVisitor cv) {
+ super(Opcodes.ASM4, cv);
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ owner = name;
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ FieldVisitor fv = super
+ .visitField(access, name, desc, signature, value);
+ if ((access & ACC_STATIC) == 0) {
+ Type t = Type.getType(desc);
+ int size = t.getSize();
+
+ // generates getter method
+ String gDesc = "()" + desc;
+ MethodVisitor gv = cv.visitMethod(ACC_PRIVATE, "_get" + name,
+ gDesc, null, null);
+ gv.visitFieldInsn(GETSTATIC, "java/lang/System", "err",
+ "Ljava/io/PrintStream;");
+ gv.visitLdcInsn("_get" + name + " called");
+ gv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
+ "(Ljava/lang/String;)V");
+ gv.visitVarInsn(ALOAD, 0);
+ gv.visitFieldInsn(GETFIELD, owner, name, desc);
+ gv.visitInsn(t.getOpcode(IRETURN));
+ gv.visitMaxs(1 + size, 1);
+ gv.visitEnd();
+
+ // generates setter method
+ String sDesc = "(" + desc + ")V";
+ MethodVisitor sv = cv.visitMethod(ACC_PRIVATE, "_set" + name,
+ sDesc, null, null);
+ sv.visitFieldInsn(GETSTATIC, "java/lang/System", "err",
+ "Ljava/io/PrintStream;");
+ sv.visitLdcInsn("_set" + name + " called");
+ sv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
+ "(Ljava/lang/String;)V");
+ sv.visitVarInsn(ALOAD, 0);
+ sv.visitVarInsn(t.getOpcode(ILOAD), 1);
+ sv.visitFieldInsn(PUTFIELD, owner, name, desc);
+ sv.visitInsn(RETURN);
+ sv.visitMaxs(1 + size, 1 + size);
+ sv.visitEnd();
+ }
+ return fv;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
+ exceptions);
+ return mv == null ? null : new TraceFieldCodeAdapter(mv, owner);
+ }
+}
+
+class TraceFieldCodeAdapter extends MethodVisitor implements Opcodes {
+
+ private String owner;
+
+ public TraceFieldCodeAdapter(final MethodVisitor mv, final String owner) {
+ super(Opcodes.ASM4, mv);
+ this.owner = owner;
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ if (owner.equals(this.owner)) {
+ if (opcode == GETFIELD) {
+ // replaces GETFIELD f by INVOKESPECIAL _getf
+ String gDesc = "()" + desc;
+ visitMethodInsn(INVOKESPECIAL, owner, "_get" + name, gDesc);
+ return;
+ } else if (opcode == PUTFIELD) {
+ // replaces PUTFIELD f by INVOKESPECIAL _setf
+ String sDesc = "(" + desc + ")V";
+ visitMethodInsn(INVOKESPECIAL, owner, "_set" + name, sDesc);
+ return;
+ }
+ }
+ super.visitFieldInsn(opcode, owner, name, desc);
+ }
+}
diff --git a/asm4/examples/adapt/src/ArraySet.java b/asm4/examples/adapt/src/ArraySet.java
new file mode 100644
index 0000000..3548cd6
--- /dev/null
+++ b/asm4/examples/adapt/src/ArraySet.java
@@ -0,0 +1,94 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @author Eric Bruneton
+ */
+public class ArraySet {
+
+ private int[] values = new int[3];
+
+ private int size;
+
+ public boolean contains(final int v) {
+ for (int i = 0; i < size; ++i) {
+ if (values[i] == v) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void add(final int v) {
+ if (!contains(v)) {
+ if (size == values.length) {
+ System.err.println("[enlarge]");
+ int[] newValues = new int[values.length + 3];
+ System.arraycopy(values, 0, newValues, 0, size);
+ values = newValues;
+ }
+ values[size++] = v;
+ }
+ }
+
+ public void remove(final int v) {
+ int i = 0;
+ int j = 0;
+ while (i < size) {
+ int u = values[i];
+ if (u != v) {
+ values[j++] = u;
+ }
+ ++i;
+ }
+ size = j;
+ }
+
+ // test method
+
+ public static void main(final String[] args) {
+ ArraySet s = new ArraySet();
+ System.err.println("add 1");
+ s.add(1);
+ System.err.println("add 1");
+ s.add(1);
+ System.err.println("add 2");
+ s.add(2);
+ System.err.println("add 4");
+ s.add(4);
+ System.err.println("add 8");
+ s.add(8);
+ System.err.println("contains 3 = " + s.contains(3));
+ System.err.println("contains 1 = " + s.contains(1));
+ System.err.println("remove 1");
+ s.remove(1);
+ System.err.println("contains 1 = " + s.contains(1));
+ }
+}
diff --git a/asm4/examples/analysis/etc/execute.properties b/asm4/examples/analysis/etc/execute.properties
new file mode 100644
index 0000000..b560b40
--- /dev/null
+++ b/asm4/examples/analysis/etc/execute.properties
@@ -0,0 +1,32 @@
+###############################################################################
+#ASM: a very small and fast Java bytecode manipulation framework
+#Copyright (c) 2000-2011 INRIA, France Telecom
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+#THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################
+
+run.classname Analysis
+run.parameters
diff --git a/asm4/examples/analysis/src/Analysis.java b/asm4/examples/analysis/src/Analysis.java
new file mode 100644
index 0000000..3e319eb
--- /dev/null
+++ b/asm4/examples/analysis/src/Analysis.java
@@ -0,0 +1,182 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.IincInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.VarInsnNode;
+import org.objectweb.asm.tree.analysis.Analyzer;
+import org.objectweb.asm.tree.analysis.BasicValue;
+import org.objectweb.asm.tree.analysis.BasicVerifier;
+import org.objectweb.asm.tree.analysis.Frame;
+import org.objectweb.asm.tree.analysis.SourceInterpreter;
+import org.objectweb.asm.tree.analysis.SourceValue;
+import org.objectweb.asm.util.TraceMethodVisitor;
+import org.objectweb.asm.util.Textifier;
+
+/**
+ * @author Eric Bruneton
+ */
+public class Analysis implements Opcodes {
+
+ public static void main(final String[] args) throws Exception {
+ ClassReader cr = new ClassReader("Analysis");
+ ClassNode cn = new ClassNode();
+ cr.accept(cn, ClassReader.SKIP_DEBUG);
+
+ List<MethodNode> methods = cn.methods;
+ for (int i = 0; i < methods.size(); ++i) {
+ MethodNode method = methods.get(i);
+ if (method.instructions.size() > 0) {
+ if (!analyze(cn, method)) {
+ Analyzer<?> a = new Analyzer<BasicValue>(
+ new BasicVerifier());
+ try {
+ a.analyze(cn.name, method);
+ } catch (Exception ignored) {
+ }
+ final Frame<?>[] frames = a.getFrames();
+
+ Textifier t = new Textifier() {
+ @Override
+ public void visitMaxs(final int maxStack,
+ final int maxLocals) {
+ for (int i = 0; i < text.size(); ++i) {
+ StringBuffer s = new StringBuffer(
+ frames[i] == null ? "null"
+ : frames[i].toString());
+ while (s.length() < Math.max(20, maxStack
+ + maxLocals + 1)) {
+ s.append(' ');
+ }
+ System.err.print(Integer.toString(i + 1000)
+ .substring(1)
+ + " "
+ + s
+ + " : "
+ + text.get(i));
+ }
+ System.err.println();
+ }
+ };
+ MethodVisitor mv = new TraceMethodVisitor(t);
+ for (int j = 0; j < method.instructions.size(); ++j) {
+ Object insn = method.instructions.get(j);
+ ((AbstractInsnNode) insn).accept(mv);
+ }
+ mv.visitMaxs(0, 0);
+ }
+ }
+ }
+ }
+
+ /*
+ * Detects unused xSTORE instructions, i.e. xSTORE instructions without at
+ * least one xLOAD corresponding instruction in their successor instructions
+ * (in the control flow graph).
+ */
+ public static boolean analyze(final ClassNode c, final MethodNode m)
+ throws Exception {
+ Analyzer<SourceValue> a = new Analyzer<SourceValue>(
+ new SourceInterpreter());
+ Frame<SourceValue>[] frames = a.analyze(c.name, m);
+
+ // for each xLOAD instruction, we find the xSTORE instructions that can
+ // produce the value loaded by this instruction, and we put them in
+ // 'stores'
+ Set<AbstractInsnNode> stores = new HashSet<AbstractInsnNode>();
+ for (int i = 0; i < m.instructions.size(); ++i) {
+ AbstractInsnNode insn = m.instructions.get(i);
+ int opcode = insn.getOpcode();
+ if ((opcode >= ILOAD && opcode <= ALOAD) || opcode == IINC) {
+ int var = opcode == IINC ? ((IincInsnNode) insn).var
+ : ((VarInsnNode) insn).var;
+ Frame<SourceValue> f = frames[i];
+ if (f != null) {
+ Set<AbstractInsnNode> s = f.getLocal(var).insns;
+ Iterator<AbstractInsnNode> j = s.iterator();
+ while (j.hasNext()) {
+ insn = j.next();
+ if (insn instanceof VarInsnNode) {
+ stores.add(insn);
+ }
+ }
+ }
+ }
+ }
+
+ // we then find all the xSTORE instructions that are not in 'stores'
+ boolean ok = true;
+ for (int i = 0; i < m.instructions.size(); ++i) {
+ AbstractInsnNode insn = m.instructions.get(i);
+ int opcode = insn.getOpcode();
+ if (opcode >= ISTORE && opcode <= ASTORE) {
+ if (!stores.contains(insn)) {
+ ok = false;
+ System.err.println("method " + m.name + ", instruction "
+ + i + ": useless store instruction");
+ }
+ }
+ }
+ return ok;
+ }
+
+ /*
+ * Test for the above method, with three useless xSTORE instructions.
+ */
+ public int test(int i, int j) {
+ i = i + 1; // ok, because i can be read after this point
+
+ if (j == 0) {
+ j = 1; // useless
+ } else {
+ try {
+ j = j - 1; // ok, because j can be accessed in the catch
+ int k = 0;
+ if (i > 0) {
+ k = i - 1;
+ }
+ return k;
+ } catch (Exception e) { // useless ASTORE (e is never used)
+ j = j + 1; // useless
+ }
+ }
+
+ return 0;
+ }
+}
diff --git a/asm4/examples/annotations/build.xml b/asm4/examples/annotations/build.xml
new file mode 100644
index 0000000..e149280
--- /dev/null
+++ b/asm4/examples/annotations/build.xml
@@ -0,0 +1,89 @@
+<!--
+ ! ASM: a very small and fast Java bytecode manipulation framework
+ ! Copyright (c) 2000-2011 INRIA, France Telecom
+ ! All rights reserved.
+ !
+ ! Redistribution and use in source and binary forms, with or without
+ ! modification, are permitted provided that the following conditions
+ ! are met:
+ ! 1. Redistributions of source code must retain the above copyright
+ ! notice, this list of conditions and the following disclaimer.
+ ! 2. Redistributions in binary form must reproduce the above copyright
+ ! notice, this list of conditions and the following disclaimer in the
+ ! documentation and/or other materials provided with the distribution.
+ ! 3. Neither the name of the copyright holders nor the names of its
+ ! contributors may be used to endorse or promote products derived from
+ ! this software without specific prior written permission.
+ !
+ ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ ! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ ! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ ! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ ! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ ! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ ! THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project name="Examples" default="compile">
+
+ <!-- directory definition -->
+
+ <property name="src" value="${basedir}/src"/>
+ <property name="build" value="${basedir}/build"/>
+
+ <property file="${basedir}/../etc/build.properties"/>
+ <property file="${basedir}/etc/build.properties"/>
+ <property file="${basedir}/etc/execute.properties"/>
+
+ <!-- Building of a path which contains external jars -->
+
+ <path id="classpath">
+ <pathelement path="${asm.path}"/>
+ <pathelement path="${asm.tree.path}"/>
+ <pathelement path="${asm.analysis.path}"/>
+ <pathelement path="${asm.attrs.path}"/>
+ <pathelement path="${asm.util.path}"/>
+ <fileset dir="${basedir}">
+ <include name="lib/**/*.jar"/>
+ </fileset>
+ <fileset dir="${basedir}/..">
+ <include name="lib/**/*.jar"/>
+ </fileset>
+ <pathelement location="${build}"/>
+ </path>
+
+ <!-- ================================== -->
+ <!-- EXECUTE -->
+ <!-- ================================== -->
+
+ <target name="execute" depends="compile">
+ <java classname="${run.classname}"
+ classpathref="classpath" fork="yes" failonerror="yes">
+ <arg line="${run.parameters}"/>
+ </java>
+ </target>
+
+ <!-- ================================== -->
+ <!-- COMPILE -->
+ <!-- ================================== -->
+
+ <target name="compile">
+ <mkdir dir="${build}"/>
+ <javac srcdir="${src}" destdir="${build}" debug="on" source="1.5" target="1.5">
+ <classpath refid="classpath"/>
+ <include name="**/*.java"/>
+ </javac>
+ </target>
+
+ <!-- ================================== -->
+ <!-- CLEAN -->
+ <!-- ================================== -->
+
+ <target name="clean">
+ <delete dir="${build}"/>
+ </target>
+</project>
diff --git a/asm4/examples/annotations/etc/execute.properties b/asm4/examples/annotations/etc/execute.properties
new file mode 100644
index 0000000..06d0dec
--- /dev/null
+++ b/asm4/examples/annotations/etc/execute.properties
@@ -0,0 +1,32 @@
+###############################################################################
+#ASM: a very small and fast Java bytecode manipulation framework
+#Copyright (c) 2000-2011 INRIA, France Telecom
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+#THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################
+
+run.classname Annotations
+run.parameters
diff --git a/asm4/examples/annotations/src/Annotations.java b/asm4/examples/annotations/src/Annotations.java
new file mode 100644
index 0000000..850b6f1
--- /dev/null
+++ b/asm4/examples/annotations/src/Annotations.java
@@ -0,0 +1,137 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+public class Annotations {
+
+ public static void foo(final @NotNull String arg) {
+ System.out.println(arg);
+ }
+
+ public static void main(final String[] args) throws Exception {
+ System.out
+ .println("Calling foo(null) results in a NullPointerException:");
+ try {
+ foo(null);
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ }
+
+ final String n = Annotations.class.getName();
+ final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ ClassReader cr = new ClassReader(n);
+ cr.accept(new ClassVisitor(Opcodes.ASM4, cw) {
+
+ @Override
+ public MethodVisitor visitMethod(final int access,
+ final String name, final String desc,
+ final String signature, final String[] exceptions) {
+ final Type[] args = Type.getArgumentTypes(desc);
+ MethodVisitor v = cv.visitMethod(access, name, desc, signature,
+ exceptions);
+ return new MethodVisitor(Opcodes.ASM4, v) {
+
+ private final List<Integer> params = new ArrayList<Integer>();
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter, final String desc,
+ final boolean visible) {
+ AnnotationVisitor av;
+ av = mv.visitParameterAnnotation(parameter, desc,
+ visible);
+ if (desc.equals("LNotNull;")) {
+ params.add(new Integer(parameter));
+ }
+ return av;
+ }
+
+ @Override
+ public void visitCode() {
+ int var = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
+ for (int p = 0; p < params.size(); ++p) {
+ int param = params.get(p).intValue();
+ for (int i = 0; i < param; ++i) {
+ var += args[i].getSize();
+ }
+ String c = "java/lang/IllegalArgumentException";
+ String d = "(Ljava/lang/String;)V";
+ Label end = new Label();
+ mv.visitVarInsn(Opcodes.ALOAD, var);
+ mv.visitJumpInsn(Opcodes.IFNONNULL, end);
+ mv.visitTypeInsn(Opcodes.NEW, c);
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitLdcInsn("Argument " + param
+ + " must not be null");
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, c,
+ "<init>", d);
+ mv.visitInsn(Opcodes.ATHROW);
+ mv.visitLabel(end);
+ }
+ }
+ };
+ }
+ }, 0);
+
+ Class<?> c = new ClassLoader() {
+ @Override
+ public Class<?> loadClass(final String name)
+ throws ClassNotFoundException {
+ if (name.equals(n)) {
+ byte[] b = cw.toByteArray();
+ return defineClass(name, b, 0, b.length);
+ }
+ return super.loadClass(name);
+ }
+ }.loadClass(n);
+
+ System.out.println();
+ System.out.println("Calling foo(null) on the transformed class results"
+ + " in an IllegalArgumentException:");
+ Method m = c.getMethod("foo", new Class<?>[] { String.class });
+ try {
+ m.invoke(null, new Object[] { null });
+ } catch (InvocationTargetException e) {
+ e.getCause().printStackTrace(System.out);
+ }
+ }
+}
diff --git a/asm4/examples/annotations/src/NotNull.java b/asm4/examples/annotations/src/NotNull.java
new file mode 100644
index 0000000..b16cf12
--- /dev/null
+++ b/asm4/examples/annotations/src/NotNull.java
@@ -0,0 +1,36 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.CLASS)
+public @interface NotNull {
+ String value() default "";
+}
diff --git a/asm4/examples/attributes/etc/execute.properties b/asm4/examples/attributes/etc/execute.properties
new file mode 100644
index 0000000..f2027d4
--- /dev/null
+++ b/asm4/examples/attributes/etc/execute.properties
@@ -0,0 +1,32 @@
+###############################################################################
+#ASM: a very small and fast Java bytecode manipulation framework
+#Copyright (c) 2000-2011 INRIA, France Telecom
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+#THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################
+
+run.classname Attributes
+run.parameters
diff --git a/asm4/examples/attributes/src/Attributes.java b/asm4/examples/attributes/src/Attributes.java
new file mode 100644
index 0000000..b833042
--- /dev/null
+++ b/asm4/examples/attributes/src/Attributes.java
@@ -0,0 +1,144 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.util.Map;
+
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ByteVector;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.util.Textifiable;
+import org.objectweb.asm.util.TraceClassVisitor;
+
+/**
+ * @author Eric Bruneton
+ */
+public class Attributes extends ClassLoader {
+
+ public static void main(final String args[]) throws Exception {
+ // loads the original class and adapts it
+ ClassReader cr = new ClassReader("CommentAttribute");
+ ClassWriter cw = new ClassWriter(0);
+ ClassVisitor cv = new AddCommentClassAdapter(cw);
+ cr.accept(cv, new Attribute[] { new CommentAttribute("") }, 0);
+ byte[] b = cw.toByteArray();
+
+ // stores the adapted class on disk
+ FileOutputStream fos = new FileOutputStream(
+ "CommentAttribute.class.new");
+ try {
+ fos.write(b);
+ } finally {
+ fos.close();
+ }
+
+ // "disassembles" the adapted class
+ cr = new ClassReader(b);
+ cv = new TraceClassVisitor(new PrintWriter(System.out));
+ cr.accept(cv, new Attribute[] { new CommentAttribute("") }, 0);
+ }
+}
+
+class AddCommentClassAdapter extends ClassVisitor implements Opcodes {
+
+ public AddCommentClassAdapter(final ClassVisitor cv) {
+ super(Opcodes.ASM4, cv);
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ super.visit(version, access, name, signature, superName, interfaces);
+ visitAttribute(new CommentAttribute("this is a class comment"));
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ FieldVisitor fv = super
+ .visitField(access, name, desc, signature, value);
+ fv.visitAttribute(new CommentAttribute("this is a field comment"));
+ return fv;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
+ exceptions);
+ if (mv != null) {
+ mv.visitAttribute(new CommentAttribute("this is a method comment"));
+ }
+ return mv;
+ }
+}
+
+class CommentAttribute extends Attribute implements Textifiable {
+
+ private String comment;
+
+ public CommentAttribute(final String comment) {
+ super("Comment");
+ this.comment = comment;
+ }
+
+ public String getComment() {
+ return comment;
+ }
+
+ @Override
+ public boolean isUnknown() {
+ return false;
+ }
+
+ @Override
+ protected Attribute read(final ClassReader cr, final int off,
+ final int len, final char[] buf, final int codeOff,
+ final Label[] labels) {
+ return new CommentAttribute(cr.readUTF8(off, buf));
+ }
+
+ @Override
+ protected ByteVector write(final ClassWriter cw, final byte[] code,
+ final int len, final int maxStack, final int maxLocals) {
+ return new ByteVector().putShort(cw.newUTF8(comment));
+ }
+
+ public void textify(StringBuffer buf, Map<Label, String> labelNames) {
+ buf.append(": " + comment + "\n");
+ }
+}
diff --git a/asm4/examples/common/README.txt b/asm4/examples/common/README.txt
new file mode 100644
index 0000000..164705d
--- /dev/null
+++ b/asm4/examples/common/README.txt
@@ -0,0 +1,43 @@
+*******************************************************************************
+* ASM: a very small and fast Java bytecode manipulation framework
+* Copyright (c) 2000-2011 INRIA, France Telecom
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* 3. Neither the name of the copyright holders nor the names of its
+* contributors may be used to endorse or promote products derived from
+* this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************
+
+This directory contains the examples of the product.
+It contains(*) the following items:
+
+- lib: jar files shared by all examples,
+- etc: configuration files shared by all examples,
+- README.txt: explains the organisation of the examples directory,
+- all other directories contain(*) the following items:
+ - README.txt file: describes the example and its configuration,
+ - lib: jar files needed by the example,
+ - etc: configuration files needed by the example,
+ - src: source code of the example.
+
+(*) some items may not be present, depending on the product or example. \ No newline at end of file
diff --git a/asm4/examples/common/build.xml b/asm4/examples/common/build.xml
new file mode 100644
index 0000000..950b028
--- /dev/null
+++ b/asm4/examples/common/build.xml
@@ -0,0 +1,97 @@
+<!--
+ ! ASM: a very small and fast Java bytecode manipulation framework
+ ! Copyright (c) 2000-2011 INRIA, France Telecom
+ ! All rights reserved.
+ !
+ ! Redistribution and use in source and binary forms, with or without
+ ! modification, are permitted provided that the following conditions
+ ! are met:
+ ! 1. Redistributions of source code must retain the above copyright
+ ! notice, this list of conditions and the following disclaimer.
+ ! 2. Redistributions in binary form must reproduce the above copyright
+ ! notice, this list of conditions and the following disclaimer in the
+ ! documentation and/or other materials provided with the distribution.
+ ! 3. Neither the name of the copyright holders nor the names of its
+ ! contributors may be used to endorse or promote products derived from
+ ! this software without specific prior written permission.
+ !
+ ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ ! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ ! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ ! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ ! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ ! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ ! THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project name="Examples" default="compile">
+
+ <!-- directory definition -->
+
+ <property name="src" value="${basedir}/src"/>
+ <property name="build" value="${basedir}/build"/>
+
+ <property file="${basedir}/../etc/build.properties"/>
+ <property file="${basedir}/etc/build.properties"/>
+ <property file="${basedir}/etc/execute.properties"/>
+
+ <!-- Building of a path which contains external jars -->
+
+ <path id="compile-classpath">
+ <pathelement path="${asm.debug.path}"/>
+ <fileset dir="${basedir}">
+ <include name="lib/*.jar"/>
+ </fileset>
+ <pathelement location="${build}"/>
+ </path>
+
+ <path id="runtime-classpath">
+ <pathelement path="${asm.path}"/>
+ <pathelement path="${asm.tree.path}"/>
+ <pathelement path="${asm.analysis.path}"/>
+ <pathelement path="${asm.attrs.path}"/>
+ <pathelement path="${asm.util.path}"/>
+ <pathelement path="${asm.commons.path}"/>
+ <fileset dir="${basedir}">
+ <include name="lib/*.jar"/>
+ </fileset>
+ <pathelement location="${build}"/>
+ </path>
+
+
+
+ <!-- ================================== -->
+ <!-- EXECUTE -->
+ <!-- ================================== -->
+
+ <target name="execute" depends="compile">
+ <java classname="${run.classname}"
+ classpathref="runtime-classpath" fork="yes" failonerror="yes">
+ <arg line="${run.parameters}"/>
+ </java>
+ </target>
+
+ <!-- ================================== -->
+ <!-- COMPILE -->
+ <!-- ================================== -->
+
+ <target name="compile">
+ <mkdir dir="${build}"/>
+ <javac srcdir="${src}" destdir="${build}" debug="on" source="1.5" target="1.5">
+ <classpath refid="compile-classpath"/>
+ <include name="**/*.java"/>
+ </javac>
+ </target>
+
+ <!-- ================================== -->
+ <!-- CLEAN -->
+ <!-- ================================== -->
+
+ <target name="clean">
+ <delete dir="${build}"/>
+ </target>
+</project>
diff --git a/asm4/examples/common/etc/build.properties b/asm4/examples/common/etc/build.properties
new file mode 100644
index 0000000..c3eb187
--- /dev/null
+++ b/asm4/examples/common/etc/build.properties
@@ -0,0 +1,68 @@
+###############################################################################
+#ASM: a very small and fast Java bytecode manipulation framework
+#Copyright (c) 2000-2011 INRIA, France Telecom
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+#THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################
+
+# Wich compiler do you want use ?
+
+# build.compiler jikes
+
+# Runtime class path for the ASM library (version @product.version@)
+# See http://asm.objectweb.org
+
+asm.path ../../lib/asm-@product.version@.jar
+
+# Runtime class path for the ASM tree library (version @product.version@)
+# See http://asm.objectweb.org
+
+asm.tree.path ../../lib/asm-tree-@product.version@.jar
+
+# Runtime class path for the ASM analysis library (version @product.version@)
+# See http://asm.objectweb.org
+
+asm.analysis.path ../../lib/asm-analysis-@product.version@.jar
+
+# Runtime class path for the ASM attrs library (version @product.version@)
+# See http://asm.objectweb.org
+
+asm.attrs.path ../../lib/asm-attrs-@product.version@.jar
+
+# Runtime class path for the ASM util library (version @product.version@)
+# See http://asm.objectweb.org
+
+asm.util.path ../../lib/asm-util-@product.version@.jar
+
+# Runtime class path for the ASM commons library (version @product.version@)
+# See http://asm.objectweb.org
+
+asm.commons.path ../../lib/asm-commons-@product.version@.jar
+
+# Compile time class path for the whole ASM library (version @product.version@)
+# See http://asm.objectweb.org
+
+asm.debug.path ../../lib/all/asm-debug-all-@product.version@.jar
diff --git a/asm4/examples/compile-indy/etc/execute.properties b/asm4/examples/compile-indy/etc/execute.properties
new file mode 100644
index 0000000..a22cb1d
--- /dev/null
+++ b/asm4/examples/compile-indy/etc/execute.properties
@@ -0,0 +1,32 @@
+###############################################################################
+#ASM: a very small and fast Java bytecode manipulation framework
+#Copyright (c) 2000-2011 INRIA, France Telecom
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+#THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################
+
+run.classname IndyCompile
+run.parameters
diff --git a/asm4/examples/compile-indy/src/IndyCompile.java b/asm4/examples/compile-indy/src/IndyCompile.java
new file mode 100644
index 0000000..cac146e
--- /dev/null
+++ b/asm4/examples/compile-indy/src/IndyCompile.java
@@ -0,0 +1,368 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * This example is adapted from the example that you can find in examples/compile
+ * and use invokedynamic to implement all operations.
+ *
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+import static org.objectweb.asm.Opcodes.ALOAD;
+import static org.objectweb.asm.Opcodes.ARETURN;
+import static org.objectweb.asm.Opcodes.DUP;
+import static org.objectweb.asm.Opcodes.H_INVOKESTATIC;
+import static org.objectweb.asm.Opcodes.IFEQ;
+import static org.objectweb.asm.Opcodes.IFNE;
+import static org.objectweb.asm.Opcodes.POP;
+import static org.objectweb.asm.Opcodes.V1_7;
+
+import java.io.FileOutputStream;
+import java.lang.reflect.Method;
+
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+
+/**
+ * @author Remi Forax
+ * @author Eric Bruneton
+ */
+public class IndyCompile extends ClassLoader {
+
+ public static void main(final String[] args) throws Throwable {
+ // creates the expression tree corresponding to
+ // exp(i) = i > 3 && 6 > i
+ Exp exp = new And(new GT(new Var(0), new Cst(3)), new GT(new Cst(6),
+ new Var(0)));
+
+ // compiles this expression into a generic static method in a class
+ IndyCompile main = new IndyCompile();
+ byte[] b = exp.compile("Example");
+ FileOutputStream fos = new FileOutputStream("Example.class");
+ fos.write(b);
+ fos.close();
+ Class<?> expClass = main.defineClass("Example", b, 0, b.length);
+ Method expMethod = expClass.getDeclaredMethods()[0];
+
+ // ... and use it to evaluate exp(0) to exp(9)
+ for (int i = 0; i < 10; ++i) {
+ boolean val = (Boolean) expMethod.invoke(null, i);
+ System.out.println(i + " > 3 && " + i + " < 6 = " + val);
+ }
+
+ // ... more fun, test with strings !!!
+ for (int i = 0; i < 10; ++i) {
+ boolean val = (Boolean) expMethod.invoke(null, Integer.toString(i));
+ System.out.println("\"" + i + "\" > 3 && 6 > \"" + i + "\" = "
+ + val);
+ }
+ }
+
+ /**
+ * An abstract expression.
+ */
+ static abstract class Exp {
+
+ static final Handle CST = getHandle("cst", "Ljava/lang/Object;");
+
+ static final Handle UNARY = getHandle("unary", "");
+
+ static final Handle BINARY = getHandle("binary", "");
+
+ /**
+ * Returns the maximum variable index used in this expression.
+ *
+ * @return the maximum variable index used in this expression, or -1 if
+ * no variable is used.
+ */
+ int getMaxVarIndex() {
+ return -1;
+ }
+
+ /*
+ * Returns the byte code of a class corresponding to this expression.
+ */
+ byte[] compile(final String name) {
+ // class header
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+ cw.visit(V1_7, ACC_PUBLIC, name, null, "java/lang/Object", null);
+
+ // eval method type
+ StringBuilder desc = new StringBuilder("(");
+ for (int i = 0; i <= getMaxVarIndex(); ++i) {
+ desc.append("Ljava/lang/Object;");
+ }
+ desc.append(")Ljava/lang/Object;");
+
+ // eval method
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "eval",
+ desc.toString(), null, null);
+ compile(mv);
+ mv.visitInsn(ARETURN);
+ // max stack and max locals automatically computed
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+ /*
+ * Compile this expression. This method must append to the given code
+ * writer the byte code that evaluates and pushes on the stack the value
+ * of this expression.
+ */
+ abstract void compile(MethodVisitor mv);
+
+ private static Handle getHandle(final String name, final String optArgs) {
+ return new Handle(
+ H_INVOKESTATIC,
+ "RT",
+ name,
+ "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;"
+ + optArgs + ")Ljava/lang/invoke/CallSite;");
+ }
+ }
+
+ /**
+ * A constant expression.
+ */
+ static class Cst extends Exp {
+
+ private final Object value;
+
+ Cst(final Object value) {
+ this.value = value;
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ if (value instanceof String) {
+ mv.visitLdcInsn(value);
+ return;
+ }
+
+ // instead of pushing the constant and then box it, we use
+ // invokedynamic with the constant as bootstrap argument. The
+ // boxing will be performed by the VM when calling the bootstrap
+ // method
+ mv.visitInvokeDynamicInsn("cst", "()Ljava/lang/Object;", CST, value);
+ }
+ }
+
+ /**
+ * A variable reference expression.
+ */
+ static class Var extends Exp {
+
+ final int index;
+
+ Var(final int index) {
+ this.index = index;
+ }
+
+ @Override
+ int getMaxVarIndex() {
+ return index;
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // pushes the 'index' local variable onto the stack
+ mv.visitVarInsn(ALOAD, index);
+ }
+ }
+
+ /**
+ * An abstract binary expression.
+ */
+ static abstract class BinaryExp extends Exp {
+
+ final Exp e1;
+
+ final Exp e2;
+
+ @Override
+ int getMaxVarIndex() {
+ return Math.max(e1.getMaxVarIndex(), e2.getMaxVarIndex());
+ }
+
+ BinaryExp(final Exp e1, final Exp e2) {
+ this.e1 = e1;
+ this.e2 = e2;
+ }
+ }
+
+ /**
+ * An addition expression.
+ */
+ static class Add extends BinaryExp {
+
+ Add(final Exp e1, final Exp e2) {
+ super(e1, e2);
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // compiles e1, e2, and adds an instruction to add the two values
+ e1.compile(mv);
+ e2.compile(mv);
+ mv.visitInvokeDynamicInsn("add",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
+ BINARY);
+ }
+ }
+
+ /**
+ * A multiplication expression.
+ */
+ static class Mul extends BinaryExp {
+
+ Mul(final Exp e1, final Exp e2) {
+ super(e1, e2);
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // compiles e1, e2, and adds an instruction to multiply the two
+ // values
+ e1.compile(mv);
+ e2.compile(mv);
+ mv.visitInvokeDynamicInsn("mul",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
+ BINARY);
+ }
+ }
+
+ /**
+ * A "greater than" expression.
+ */
+ static class GT extends BinaryExp {
+
+ GT(final Exp e1, final Exp e2) {
+ super(e1, e2);
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // compiles e1, e2, and adds the instructions to compare the two
+ // values
+ e1.compile(mv);
+ e2.compile(mv);
+ mv.visitInvokeDynamicInsn("gt",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
+ BINARY);
+ }
+ }
+
+ /**
+ * A logical "and" expression.
+ */
+ static class And extends BinaryExp {
+
+ And(final Exp e1, final Exp e2) {
+ super(e1, e2);
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // compiles e1
+ e1.compile(mv);
+ // tests if e1 is false
+ mv.visitInsn(DUP);
+ // convert to a boolean
+ mv.visitInvokeDynamicInsn("asBoolean", "(Ljava/lang/Object;)Z",
+ UNARY);
+
+ Label end = new Label();
+ mv.visitJumpInsn(IFEQ, end);
+ // case where e1 is true : e1 && e2 is equal to e2
+ mv.visitInsn(POP);
+ e2.compile(mv);
+
+ // if e1 is false, e1 && e2 is equal to e1:
+ // we jump directly to this label, without evaluating e2
+ mv.visitLabel(end);
+ }
+ }
+
+ /**
+ * A logical "or" expression.
+ */
+ static class Or extends BinaryExp {
+
+ Or(final Exp e1, final Exp e2) {
+ super(e1, e2);
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // compiles e1
+ e1.compile(mv);
+ // tests if e1 is true
+ mv.visitInsn(DUP);
+ // convert to a boolean
+ mv.visitInvokeDynamicInsn("asBoolean", "(Ljava/lang/Object;)Z",
+ UNARY);
+ Label end = new Label();
+ mv.visitJumpInsn(IFNE, end);
+ // case where e1 is false : e1 || e2 is equal to e2
+ mv.visitInsn(POP);
+ e2.compile(mv);
+ // if e1 is true, e1 || e2 is equal to e1:
+ // we jump directly to this label, without evaluating e2
+ mv.visitLabel(end);
+ }
+ }
+
+ /**
+ * A logical "not" expression.
+ */
+ static class Not extends Exp {
+
+ private final Exp e;
+
+ Not(final Exp e) {
+ this.e = e;
+ }
+
+ @Override
+ int getMaxVarIndex() {
+ return e.getMaxVarIndex();
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // compiles e, and applies 'not'
+ e.compile(mv);
+ mv.visitInvokeDynamicInsn("not",
+ "(Ljava/lang/Object;)Ljava/lang/Object;", UNARY);
+ }
+ }
+}
diff --git a/asm4/examples/compile-indy/src/RT.java b/asm4/examples/compile-indy/src/RT.java
new file mode 100644
index 0000000..fdf080a
--- /dev/null
+++ b/asm4/examples/compile-indy/src/RT.java
@@ -0,0 +1,329 @@
+/***
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.MutableCallSite;
+import java.util.HashMap;
+
+/**
+ * There are 3 bootstrap methods: - one for the constant that are initialized
+ * once the first time the bootstrap method is called and after always reuse the
+ * same constant. It's almost equivalent to an LDC but here the constant are
+ * stored in boxed form e.g a java.lang.Integer containing 0 instead of an int
+ * containing 0.
+ *
+ * - one for the unary operation 'not' and 'asBoolean', here the semantics is
+ * hard coded, all primitive value are transformed as object by applying this
+ * operation: (v == 0)? false: true
+ *
+ * - one for the binary operation 'add', 'mul' and 'gt', here the semantics can
+ * be changed by adding more static methods in {@link BinaryOps}. This bootstrap
+ * method is a little more complex because it creates an inlining cache to avoid
+ * to recompute the binary method to call if the type of the two arguments
+ * doesn't change. Also, if the expression is used a lot and trigger the JIT, it
+ * will be able to inline the code of the operation directly at callsite.
+ *
+ * @author Remi Forax
+ */
+public class RT {
+ /**
+ * bootstrap method for constant
+ */
+ public static CallSite cst(Lookup lookup, String name, MethodType type,
+ Object constant) {
+ return new ConstantCallSite(MethodHandles.constant(Object.class,
+ constant));
+ }
+
+ /**
+ * bootstrap method for unary operation 'asBoolean' and 'not'
+ */
+ public static CallSite unary(Lookup lookup, String name, MethodType type) {
+ MethodHandle target;
+ if (name.equals("asBoolean")) {
+ target = MethodHandles.explicitCastArguments(
+ MethodHandles.identity(Object.class),
+ MethodType.methodType(boolean.class, Object.class));
+ } else { // "not"
+ target = MethodHandles.explicitCastArguments(NOT,
+ MethodType.methodType(Object.class, Object.class));
+ }
+ return new ConstantCallSite(target);
+ }
+
+ /**
+ * bootstrap method for binary operation 'add', 'mul' and 'gt'
+ *
+ * This bootstrap method doesn't install the target method handle directly,
+ * because we want to install an inlining cache and we can't create an
+ * inlining cache without knowing the class of the arguments. So this method
+ * first installs a method handle that will call
+ * {@link BinaryOpCallSite#fallback(Object, Object)} and the fallback method
+ * will be called with the arguments and thus can install the inlining
+ * cache. Also, the fallback has to be bound to a specific callsite to be
+ * able to change its target after the first call, this part is done in the
+ * constructor of {@link BinaryOpCallSite}.
+ */
+ public static CallSite binary(Lookup lookup, String name, MethodType type) {
+ BinaryOpCallSite callSite = new BinaryOpCallSite(name, type);
+ callSite.setTarget(callSite.fallback);
+ return callSite;
+ }
+
+ /**
+ * Garbage class containing the method used to apply 'not' on a boolean. See
+ * {@link RT#unary(Lookup, String, MethodType)}
+ */
+ public static class UnayOps {
+
+ public static Object not(boolean b) {
+ return !b;
+ }
+ }
+
+ private static final MethodHandle NOT;
+
+ static {
+ try {
+ NOT = MethodHandles.publicLookup().findStatic(UnayOps.class, "not",
+ MethodType.methodType(Object.class, boolean.class));
+ } catch (ReflectiveOperationException e) {
+ throw new LinkageError(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * A specific callsite that will install an 'inlining cache'. Because we
+ * don't know until runtime which method handle to call, the lookup
+ * depending on the dynamic type of the argument will be done at runtime
+ * when the method {@link #fallback(Object, Object)} is called. To avoid to
+ * do this dynamic lookup at each call, the fallback install two guards in
+ * front of dispatch call that will check if the arguments class change or
+ * not. If the arguments class don't change, the previously computed method
+ * handle will be called again. Otherwise, a new method handle will be
+ * computed and two new guards will be installed.
+ */
+ static class BinaryOpCallSite extends MutableCallSite {
+
+ private final String opName;
+
+ final MethodHandle fallback;
+
+ public BinaryOpCallSite(String opName, MethodType type) {
+ super(type);
+ this.opName = opName;
+ this.fallback = FALLBACK.bindTo(this);
+ }
+
+ Object fallback(Object v1, Object v2) throws Throwable {
+ // when you debug with this message
+ // don't forget that && and || are lazy !!
+ // System.out.println("fallback called with "+opName+'('+v1.getClass()+','+v2.getClass()+')');
+
+ Class<? extends Object> class1 = v1.getClass();
+ Class<? extends Object> class2 = v2.getClass();
+ MethodHandle op = lookupBinaryOp(opName, class1, class2);
+
+ // convert arguments
+ MethodType type = type();
+ MethodType opType = op.type();
+ if (opType.parameterType(0) == String.class) {
+ if (opType.parameterType(1) == String.class) {
+ op = MethodHandles.filterArguments(op, 0, TO_STRING,
+ TO_STRING);
+ } else {
+ op = MethodHandles.filterArguments(op, 0, TO_STRING);
+ op = MethodHandles.explicitCastArguments(op, type);
+ }
+ } else {
+ if (opType.parameterType(1) == String.class) {
+ op = MethodHandles.filterArguments(op, 1, TO_STRING);
+ }
+ op = MethodHandles.explicitCastArguments(op, type);
+ }
+
+ // prepare guard
+ MethodHandle guard = MethodHandles.guardWithTest(TEST1
+ .bindTo(class1), MethodHandles.guardWithTest(
+ TEST2.bindTo(class2), op, fallback), fallback);
+
+ // install the inlining cache
+ setTarget(guard);
+ return op.invokeWithArguments(v1, v2);
+ }
+
+ public static boolean test1(Class<?> v1Class, Object v1, Object v2) {
+ return v1.getClass() == v1Class;
+ }
+
+ public static boolean test2(Class<?> v2Class, Object v1, Object v2) {
+ return v2.getClass() == v2Class;
+ }
+
+ private static final MethodHandle TO_STRING;
+
+ private static final MethodHandle TEST1;
+
+ private static final MethodHandle TEST2;
+
+ private static final MethodHandle FALLBACK;
+
+ static {
+ Lookup lookup = MethodHandles.lookup();
+ try {
+ TO_STRING = lookup.findVirtual(Object.class, "toString",
+ MethodType.methodType(String.class));
+ MethodType testType = MethodType.methodType(boolean.class,
+ Class.class, Object.class, Object.class);
+ TEST1 = lookup.findStatic(BinaryOpCallSite.class, "test1",
+ testType);
+ TEST2 = lookup.findStatic(BinaryOpCallSite.class, "test2",
+ testType);
+ FALLBACK = lookup.findVirtual(BinaryOpCallSite.class,
+ "fallback", MethodType.genericMethodType(2));
+ } catch (ReflectiveOperationException e) {
+ throw new LinkageError(e.getMessage(), e);
+ }
+ }
+ }
+
+ /**
+ * Garbage class that contains the raw operations used for binary
+ * operations. All methods must be static returns an Object and takes the
+ * same type for the two parameter types.
+ *
+ * See {@link RT#lookupBinaryOp(String, Class, Class)} for more info.
+ */
+ public static class BinaryOps {
+
+ public static Object add(int v1, int v2) {
+ return v1 + v2;
+ }
+
+ public static Object add(double v1, double v2) {
+ return v1 + v2;
+ }
+
+ public static Object add(String v1, String v2) {
+ return v1 + v2;
+ }
+
+ public static Object mul(int v1, int v2) {
+ return v1 * v2;
+ }
+
+ public static Object mul(double v1, double v2) {
+ return v1 * v2;
+ }
+
+ public static Object gt(int v1, int v2) {
+ return v1 > v2;
+ }
+
+ public static Object gt(double v1, double v2) {
+ return v1 > v2;
+ }
+
+ public static Object gt(String v1, String v2) {
+ return v1.compareTo(v2) > 0;
+ }
+ }
+
+ /**
+ * Select a most specific method among the ones defined in
+ * {@link RT.BinaryOps}. The algorithm first find the most specific subtype
+ * between class1 and class2. The order of the types is defined in
+ * {@link RT#RANK_MAP}: Boolean < Byte < Short < Character < Integer < Long
+ * < Float < Double < String then the algorithm lookup in
+ * {@link RT.BinaryOps} to find a method with the name opName taking as
+ * argument the primitive corresponding to the most specific subtype. If no
+ * such method exist, the algorithm retry but looking for a method with a
+ * more specific type (using the same order). The result of the lookup is
+ * cached in {@link RT#BINARY_CACHE} to avoid to avoid to do a lookup (a
+ * reflective call) on the same method twice.
+ */
+ static MethodHandle lookupBinaryOp(String opName, Class<?> class1,
+ Class<?> class2) {
+ int rank = Math.max(RANK_MAP.get(class1), RANK_MAP.get(class2));
+ String mangledName = opName + rank;
+ MethodHandle mh = BINARY_CACHE.get(mangledName);
+ if (mh != null) {
+ return mh;
+ }
+
+ for (; rank < PRIMITIVE_ARRAY.length;) {
+ Class<?> primitive = PRIMITIVE_ARRAY[rank];
+ try {
+ mh = MethodHandles.publicLookup().findStatic(
+ BinaryOps.class,
+ opName,
+ MethodType.methodType(Object.class, primitive,
+ primitive));
+ } catch (NoSuchMethodException e) {
+ rank = rank + 1;
+ continue;
+ } catch (IllegalAccessException e) {
+ throw new LinkageError(e.getMessage(), e);
+ }
+
+ BINARY_CACHE.put(mangledName, mh);
+ return mh;
+ }
+ throw new LinkageError("unknown operation " + opName + " ("
+ + class1.getName() + ',' + class2.getName() + ')');
+ }
+
+ private static final HashMap<Class<?>, Integer> RANK_MAP;
+
+ private static final Class<?>[] PRIMITIVE_ARRAY;
+
+ private static final HashMap<String, MethodHandle> BINARY_CACHE;
+
+ static {
+ Class<?>[] primitives = new Class<?>[] { boolean.class, byte.class,
+ short.class, char.class, int.class, long.class, float.class,
+ double.class, String.class };
+ Class<?>[] wrappers = new Class<?>[] { Boolean.class, Byte.class,
+ Short.class, Character.class, Integer.class, Long.class,
+ Float.class, Double.class, String.class };
+ HashMap<Class<?>, Integer> rankMap = new HashMap<Class<?>, Integer>();
+ for (int i = 0; i < wrappers.length; i++) {
+ rankMap.put(wrappers[i], i);
+ }
+
+ RANK_MAP = rankMap;
+ PRIMITIVE_ARRAY = primitives;
+ BINARY_CACHE = new HashMap<String, MethodHandle>();
+ }
+}
diff --git a/asm4/examples/compile/etc/execute.properties b/asm4/examples/compile/etc/execute.properties
new file mode 100644
index 0000000..43f5d75
--- /dev/null
+++ b/asm4/examples/compile/etc/execute.properties
@@ -0,0 +1,32 @@
+###############################################################################
+#ASM: a very small and fast Java bytecode manipulation framework
+#Copyright (c) 2000-2011 INRIA, France Telecom
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+#THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################
+
+run.classname Compile
+run.parameters
diff --git a/asm4/examples/compile/src/Compile.java b/asm4/examples/compile/src/Compile.java
new file mode 100644
index 0000000..7972867
--- /dev/null
+++ b/asm4/examples/compile/src/Compile.java
@@ -0,0 +1,293 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+import java.io.FileOutputStream;
+
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * @author Eric Bruneton
+ */
+public class Compile extends ClassLoader {
+
+ public static void main(final String[] args) throws Exception {
+ // creates the expression tree corresponding to
+ // exp(i) = i > 3 && 6 > i
+ Exp exp = new And(new GT(new Var(0), new Cst(3)), new GT(new Cst(6),
+ new Var(0)));
+ // compiles this expression into an Expression class
+ Compile main = new Compile();
+ byte[] b = exp.compile("Example");
+ FileOutputStream fos = new FileOutputStream("Example.class");
+ fos.write(b);
+ fos.close();
+ Class<?> expClass = main.defineClass("Example", b, 0, b.length);
+ // instantiates this compiled expression class...
+ Expression iexp = (Expression) expClass.newInstance();
+ // ... and uses it to evaluate exp(0) to exp(9)
+ for (int i = 0; i < 10; ++i) {
+ boolean val = iexp.eval(i, 0) == 1;
+ System.out.println(i + " > 3 && " + i + " < 6 = " + val);
+ }
+ }
+}
+
+/**
+ * An abstract expression.
+ *
+ * @author Eric Bruneton
+ */
+abstract class Exp implements Opcodes {
+
+ /*
+ * Returns the byte code of an Expression class corresponding to this
+ * expression.
+ */
+ byte[] compile(final String name) {
+ // class header
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ cw.visit(V1_1, ACC_PUBLIC, name, null, "java/lang/Object",
+ new String[] { Expression.class.getName() });
+
+ // default public constructor
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null,
+ null);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+
+ // eval method
+ mv = cw.visitMethod(ACC_PUBLIC, "eval", "(II)I", null, null);
+ compile(mv);
+ mv.visitInsn(IRETURN);
+ // max stack and max locals automatically computed
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+ /*
+ * Compile this expression. This method must append to the given code writer
+ * the byte code that evaluates and pushes on the stack the value of this
+ * expression.
+ */
+ abstract void compile(MethodVisitor mv);
+}
+
+/**
+ * A constant expression.
+ */
+class Cst extends Exp {
+
+ int value;
+
+ Cst(final int value) {
+ this.value = value;
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // pushes the constant's value onto the stack
+ mv.visitLdcInsn(new Integer(value));
+ }
+}
+
+/**
+ * A variable reference expression.
+ */
+class Var extends Exp {
+
+ int index;
+
+ Var(final int index) {
+ this.index = index + 1;
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // pushes the 'index' local variable onto the stack
+ mv.visitVarInsn(ILOAD, index);
+ }
+}
+
+/**
+ * An abstract binary expression.
+ */
+abstract class BinaryExp extends Exp {
+
+ Exp e1;
+
+ Exp e2;
+
+ BinaryExp(final Exp e1, final Exp e2) {
+ this.e1 = e1;
+ this.e2 = e2;
+ }
+}
+
+/**
+ * An addition expression.
+ */
+class Add extends BinaryExp {
+
+ Add(final Exp e1, final Exp e2) {
+ super(e1, e2);
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // compiles e1, e2, and adds an instruction to add the two values
+ e1.compile(mv);
+ e2.compile(mv);
+ mv.visitInsn(IADD);
+ }
+}
+
+/**
+ * A multiplication expression.
+ */
+class Mul extends BinaryExp {
+
+ Mul(final Exp e1, final Exp e2) {
+ super(e1, e2);
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // compiles e1, e2, and adds an instruction to multiply the two values
+ e1.compile(mv);
+ e2.compile(mv);
+ mv.visitInsn(IMUL);
+ }
+}
+
+/**
+ * A "greater than" expression.
+ */
+class GT extends BinaryExp {
+
+ GT(final Exp e1, final Exp e2) {
+ super(e1, e2);
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // compiles e1, e2, and adds the instructions to compare the two values
+ e1.compile(mv);
+ e2.compile(mv);
+ Label iftrue = new Label();
+ Label end = new Label();
+ mv.visitJumpInsn(IF_ICMPGT, iftrue);
+ // case where e1 <= e2 : pushes false and jump to "end"
+ mv.visitLdcInsn(new Integer(0));
+ mv.visitJumpInsn(GOTO, end);
+ // case where e1 > e2 : pushes true
+ mv.visitLabel(iftrue);
+ mv.visitLdcInsn(new Integer(1));
+ mv.visitLabel(end);
+ }
+}
+
+/**
+ * A logical "and" expression.
+ */
+class And extends BinaryExp {
+
+ And(final Exp e1, final Exp e2) {
+ super(e1, e2);
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // compiles e1
+ e1.compile(mv);
+ // tests if e1 is false
+ mv.visitInsn(DUP);
+ Label end = new Label();
+ mv.visitJumpInsn(IFEQ, end);
+ // case where e1 is true : e1 && e2 is equal to e2
+ mv.visitInsn(POP);
+ e2.compile(mv);
+ // if e1 is false, e1 && e2 is equal to e1:
+ // we jump directly to this label, without evaluating e2
+ mv.visitLabel(end);
+ }
+}
+
+/**
+ * A logical "or" expression.
+ */
+class Or extends BinaryExp {
+
+ Or(final Exp e1, final Exp e2) {
+ super(e1, e2);
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // compiles e1
+ e1.compile(mv);
+ // tests if e1 is true
+ mv.visitInsn(DUP);
+ Label end = new Label();
+ mv.visitJumpInsn(IFNE, end);
+ // case where e1 is false : e1 || e2 is equal to e2
+ mv.visitInsn(POP);
+ e2.compile(mv);
+ // if e1 is true, e1 || e2 is equal to e1:
+ // we jump directly to this label, without evaluating e2
+ mv.visitLabel(end);
+ }
+}
+
+/**
+ * A logical "not" expression.
+ */
+class Not extends Exp {
+
+ Exp e;
+
+ Not(final Exp e) {
+ this.e = e;
+ }
+
+ @Override
+ void compile(final MethodVisitor mv) {
+ // computes !e1 by evaluating 1 - e1
+ mv.visitLdcInsn(new Integer(1));
+ e.compile(mv);
+ mv.visitInsn(ISUB);
+ }
+}
diff --git a/asm4/examples/compile/src/Expression.java b/asm4/examples/compile/src/Expression.java
new file mode 100644
index 0000000..83d2eb2
--- /dev/null
+++ b/asm4/examples/compile/src/Expression.java
@@ -0,0 +1,48 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * An integer or boolean expression of at most two variables.
+ *
+ * @author Eric Bruneton
+ */
+public interface Expression {
+
+ /**
+ * Evaluates this expression.
+ *
+ * @param i
+ * the value of the first variable.
+ * @param j
+ * the value of the second variable.
+ * @return the value of this expression for the given variable values.
+ */
+ int eval(int i, int j);
+}
diff --git a/asm4/examples/dependencies/etc/execute.properties b/asm4/examples/dependencies/etc/execute.properties
new file mode 100644
index 0000000..345cc81
--- /dev/null
+++ b/asm4/examples/dependencies/etc/execute.properties
@@ -0,0 +1,32 @@
+###############################################################################
+#ASM: a very small and fast Java bytecode manipulation framework
+#Copyright (c) 2000-2011 INRIA, France Telecom
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+#THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################
+
+run.classname org.objectweb.asm.depend.DependencyTracker
+run.parameters ../../lib/asm-4.0.jar
diff --git a/asm4/examples/dependencies/src/org/objectweb/asm/depend/DependencyTracker.java b/asm4/examples/dependencies/src/org/objectweb/asm/depend/DependencyTracker.java
new file mode 100644
index 0000000..e20304c
--- /dev/null
+++ b/asm4/examples/dependencies/src/org/objectweb/asm/depend/DependencyTracker.java
@@ -0,0 +1,201 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.depend;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import javax.imageio.ImageIO;
+
+import org.objectweb.asm.ClassReader;
+
+/**
+ * DependencyTracker
+ *
+ * @author Eugene Kuleshov
+ *
+ * @see "http://www.onjava.com/pub/a/onjava/2005/08/17/asm3.html"
+ */
+public class DependencyTracker {
+
+ private static final int CELL_PAD = 1;
+
+ private static final int GRID_SIZE = 10;
+
+ private static final int CELLS_SIZE = 8;
+
+ private static final int LABEL_WIDTH = 200;
+
+ private static final String LABEL_FONT = "Tahoma-9";
+
+ public static void main(final String[] args) throws IOException {
+ DependencyVisitor v = new DependencyVisitor();
+
+ ZipFile f = new ZipFile(args[0]);
+
+ long l1 = System.currentTimeMillis();
+ Enumeration<? extends ZipEntry> en = f.entries();
+ while (en.hasMoreElements()) {
+ ZipEntry e = en.nextElement();
+ String name = e.getName();
+ if (name.endsWith(".class")) {
+ new ClassReader(f.getInputStream(e)).accept(v, 0);
+ }
+ }
+ long l2 = System.currentTimeMillis();
+
+ Map<String, Map<String, Integer>> globals = v.getGlobals();
+ Set<String> jarPackages = globals.keySet();
+ Set<String> classPackages = v.getPackages();
+ int size = classPackages.size();
+ System.err.println("time: " + (l2 - l1) / 1000f + " " + size);
+
+ String[] jarNames = jarPackages.toArray(new String[jarPackages.size()]);
+ String[] classNames = classPackages.toArray(new String[classPackages
+ .size()]);
+ Arrays.sort(jarNames);
+ Arrays.sort(classNames);
+
+ buildDiagram(jarNames, classNames, globals);
+ }
+
+ public static void buildDiagram(final String[] jarNames,
+ final String[] classNames,
+ final Map<String, Map<String, Integer>> globals) throws IOException {
+ // normalize
+ int max = 0;
+ for (int i = 0; i < classNames.length; i++) {
+ Map<String, Integer> map = globals.get(classNames[i]);
+ if (map == null) {
+ continue;
+ }
+ Integer maxCount = Collections.max(map.values());
+ if (maxCount > max) {
+ max = maxCount;
+ }
+ }
+
+ List<Color> colors = new ArrayList<Color>();
+ for (int i = LABEL_WIDTH; i >= 0; i--) {
+ colors.add(new Color(i, i, 255));
+ }
+ for (int i = 255; i >= 128; i--) {
+ colors.add(new Color(0, 0, i));
+ }
+ int maxcolor = colors.size() - 1;
+
+ int heigh = CELL_PAD + (CELLS_SIZE + CELL_PAD) * classNames.length;
+ int width = CELL_PAD + (CELLS_SIZE + CELL_PAD) * jarNames.length;
+
+ BufferedImage img = new BufferedImage(width + LABEL_WIDTH, heigh
+ + LABEL_WIDTH, BufferedImage.TYPE_INT_RGB);
+
+ Graphics2D g = img.createGraphics();
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, width + LABEL_WIDTH, heigh + LABEL_WIDTH);
+
+ // draw lines
+ g.setColor(Color.LIGHT_GRAY);
+ for (int y = GRID_SIZE; y < classNames.length; y += GRID_SIZE) {
+ g.drawLine(0, y * (CELLS_SIZE + CELL_PAD), width, y
+ * (CELLS_SIZE + CELL_PAD));
+ }
+ for (int x = GRID_SIZE; x < jarNames.length; x += GRID_SIZE) {
+ g.drawLine(x * (CELLS_SIZE + CELL_PAD), 0, x
+ * (CELLS_SIZE + CELL_PAD), heigh);
+ }
+
+ // draw diagram
+ for (int y = 0; y < classNames.length; y++) {
+ // System.err.println( y+" : "+classNames[ y]);
+
+ for (int x = 0; x < jarNames.length; x++) {
+ Map<String, Integer> map = globals.get(jarNames[x]);
+
+ Integer count = map == null ? null : map.get(classNames[y]);
+ if (count != null) {
+ int b = (int) ((float) count * maxcolor / max);
+
+ g.setColor(colors.get(b));
+ g.fillRect(CELL_PAD + x * (CELLS_SIZE + CELL_PAD), CELL_PAD
+ + y * (CELLS_SIZE + CELL_PAD), CELLS_SIZE,
+ CELLS_SIZE);
+ }
+ }
+ }
+
+ // draw labels
+ Font f = Font.decode(LABEL_FONT);
+ g.setFont(f);
+ // g.setColor( new Color( 70, 70, 255));
+ g.setColor(Color.GRAY);
+
+ for (int y = 0; y < classNames.length; y++) {
+ AffineTransform trans = g.getTransform();
+ g.transform(AffineTransform.getTranslateInstance(CELL_PAD * 2
+ + width, CELLS_SIZE + y * (CELLS_SIZE + CELL_PAD)));
+ g.transform(AffineTransform.getRotateInstance(Math.PI / 12));
+ g.drawString(classNames[y], 0, 0);
+ g.setTransform(trans);
+ }
+
+ for (int x = 0; x < jarNames.length; x++) {
+ AffineTransform trans = g.getTransform();
+ g.transform(AffineTransform.getTranslateInstance(CELL_PAD * 2 + x
+ * (CELLS_SIZE + CELL_PAD), heigh + CELL_PAD * 2));
+ g.transform(AffineTransform.getRotateInstance(Math.PI / 2.5));
+ g.drawString(jarNames[x], 0, 0);
+ g.setTransform(trans);
+ }
+
+ FileOutputStream fos = new FileOutputStream("test.png");
+ ImageIO.write(img, "png", fos);
+ fos.flush();
+ fos.close();
+ }
+}
diff --git a/asm4/examples/dependencies/src/org/objectweb/asm/depend/DependencyVisitor.java b/asm4/examples/dependencies/src/org/objectweb/asm/depend/DependencyVisitor.java
new file mode 100644
index 0000000..bd8d76e
--- /dev/null
+++ b/asm4/examples/dependencies/src/org/objectweb/asm/depend/DependencyVisitor.java
@@ -0,0 +1,356 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.depend;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.signature.SignatureReader;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+/**
+ * DependencyVisitor
+ *
+ * @author Eugene Kuleshov
+ */
+public class DependencyVisitor extends ClassVisitor {
+ Set<String> packages = new HashSet<String>();
+
+ Map<String, Map<String, Integer>> groups = new HashMap<String, Map<String, Integer>>();
+
+ Map<String, Integer> current;
+
+ public Map<String, Map<String, Integer>> getGlobals() {
+ return groups;
+ }
+
+ public Set<String> getPackages() {
+ return packages;
+ }
+
+ public DependencyVisitor() {
+ super(Opcodes.ASM4);
+ }
+
+ // ClassVisitor
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ String p = getGroupKey(name);
+ current = groups.get(p);
+ if (current == null) {
+ current = new HashMap<String, Integer>();
+ groups.put(p, current);
+ }
+
+ if (signature == null) {
+ if (superName != null) {
+ addInternalName(superName);
+ }
+ addInternalNames(interfaces);
+ } else {
+ addSignature(signature);
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ addDesc(desc);
+ return new AnnotationDependencyVisitor();
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ if (signature == null) {
+ addDesc(desc);
+ } else {
+ addTypeSignature(signature);
+ }
+ if (value instanceof Type) {
+ addType((Type) value);
+ }
+ return new FieldDependencyVisitor();
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ if (signature == null) {
+ addMethodDesc(desc);
+ } else {
+ addSignature(signature);
+ }
+ addInternalNames(exceptions);
+ return new MethodDependencyVisitor();
+ }
+
+ class AnnotationDependencyVisitor extends AnnotationVisitor {
+
+ public AnnotationDependencyVisitor() {
+ super(Opcodes.ASM4);
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ if (value instanceof Type) {
+ addType((Type) value);
+ }
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc,
+ final String value) {
+ addDesc(desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
+ addDesc(desc);
+ return this;
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ return this;
+ }
+ }
+
+ class FieldDependencyVisitor extends FieldVisitor {
+
+ public FieldDependencyVisitor() {
+ super(Opcodes.ASM4);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ addDesc(desc);
+ return new AnnotationDependencyVisitor();
+ }
+ }
+
+ class MethodDependencyVisitor extends MethodVisitor {
+
+ public MethodDependencyVisitor() {
+ super(Opcodes.ASM4);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ return new AnnotationDependencyVisitor();
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ addDesc(desc);
+ return new AnnotationDependencyVisitor();
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ addDesc(desc);
+ return new AnnotationDependencyVisitor();
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ addType(Type.getObjectType(type));
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ addInternalName(owner);
+ addDesc(desc);
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ addInternalName(owner);
+ addMethodDesc(desc);
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc,
+ Handle bsm, Object... bsmArgs) {
+ addMethodDesc(desc);
+ addConstant(bsm);
+ for (int i = 0; i < bsmArgs.length; i++) {
+ addConstant(bsmArgs[i]);
+ }
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ addConstant(cst);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ addDesc(desc);
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ addTypeSignature(signature);
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ if (type != null) {
+ addInternalName(type);
+ }
+ }
+ }
+
+ class SignatureDependencyVisitor extends SignatureVisitor {
+
+ String signatureClassName;
+
+ public SignatureDependencyVisitor() {
+ super(Opcodes.ASM4);
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ signatureClassName = name;
+ addInternalName(name);
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ signatureClassName = signatureClassName + "$" + name;
+ addInternalName(signatureClassName);
+ }
+ }
+
+ // ---------------------------------------------
+
+ private String getGroupKey(String name) {
+ int n = name.lastIndexOf('/');
+ if (n > -1) {
+ name = name.substring(0, n);
+ }
+ packages.add(name);
+ return name;
+ }
+
+ private void addName(final String name) {
+ if (name == null) {
+ return;
+ }
+ String p = getGroupKey(name);
+ if (current.containsKey(p)) {
+ current.put(p, current.get(p) + 1);
+ } else {
+ current.put(p, 1);
+ }
+ }
+
+ void addInternalName(final String name) {
+ addType(Type.getObjectType(name));
+ }
+
+ private void addInternalNames(final String[] names) {
+ for (int i = 0; names != null && i < names.length; i++) {
+ addInternalName(names[i]);
+ }
+ }
+
+ void addDesc(final String desc) {
+ addType(Type.getType(desc));
+ }
+
+ void addMethodDesc(final String desc) {
+ addType(Type.getReturnType(desc));
+ Type[] types = Type.getArgumentTypes(desc);
+ for (int i = 0; i < types.length; i++) {
+ addType(types[i]);
+ }
+ }
+
+ void addType(final Type t) {
+ switch (t.getSort()) {
+ case Type.ARRAY:
+ addType(t.getElementType());
+ break;
+ case Type.OBJECT:
+ addName(t.getInternalName());
+ break;
+ case Type.METHOD:
+ addMethodDesc(t.getDescriptor());
+ break;
+ }
+ }
+
+ private void addSignature(final String signature) {
+ if (signature != null) {
+ new SignatureReader(signature)
+ .accept(new SignatureDependencyVisitor());
+ }
+ }
+
+ void addTypeSignature(final String signature) {
+ if (signature != null) {
+ new SignatureReader(signature)
+ .acceptType(new SignatureDependencyVisitor());
+ }
+ }
+
+ void addConstant(final Object cst) {
+ if (cst instanceof Type) {
+ addType((Type) cst);
+ } else if (cst instanceof Handle) {
+ Handle h = (Handle) cst;
+ addInternalName(h.getOwner());
+ addMethodDesc(h.getDesc());
+ }
+ }
+}
diff --git a/asm4/examples/helloworld/etc/execute.properties b/asm4/examples/helloworld/etc/execute.properties
new file mode 100644
index 0000000..f735b79
--- /dev/null
+++ b/asm4/examples/helloworld/etc/execute.properties
@@ -0,0 +1,32 @@
+###############################################################################
+#ASM: a very small and fast Java bytecode manipulation framework
+#Copyright (c) 2000-2011 INRIA, France Telecom
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+#THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################
+
+run.classname Helloworld
+run.parameters
diff --git a/asm4/examples/helloworld/src/Helloworld.java b/asm4/examples/helloworld/src/Helloworld.java
new file mode 100644
index 0000000..dcc905a
--- /dev/null
+++ b/asm4/examples/helloworld/src/Helloworld.java
@@ -0,0 +1,139 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.GeneratorAdapter;
+import org.objectweb.asm.commons.Method;
+
+/**
+ * @author Eric Bruneton
+ */
+public class Helloworld extends ClassLoader implements Opcodes {
+
+ public static void main(final String args[]) throws Exception {
+
+ // Generates the bytecode corresponding to the following Java class:
+ //
+ // public class Example {
+ // public static void main (String[] args) {
+ // System.out.println("Hello world!");
+ // }
+ // }
+
+ // creates a ClassWriter for the Example public class,
+ // which inherits from Object
+ ClassWriter cw = new ClassWriter(0);
+ cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
+
+ // creates a MethodWriter for the (implicit) constructor
+ MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null,
+ null);
+ // pushes the 'this' variable
+ mw.visitVarInsn(ALOAD, 0);
+ // invokes the super class constructor
+ mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
+ mw.visitInsn(RETURN);
+ // this code uses a maximum of one stack element and one local variable
+ mw.visitMaxs(1, 1);
+ mw.visitEnd();
+
+ // creates a MethodWriter for the 'main' method
+ mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",
+ "([Ljava/lang/String;)V", null, null);
+ // pushes the 'out' field (of type PrintStream) of the System class
+ mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
+ "Ljava/io/PrintStream;");
+ // pushes the "Hello World!" String constant
+ mw.visitLdcInsn("Hello world!");
+ // invokes the 'println' method (defined in the PrintStream class)
+ mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
+ "(Ljava/lang/String;)V");
+ mw.visitInsn(RETURN);
+ // this code uses a maximum of two stack elements and two local
+ // variables
+ mw.visitMaxs(2, 2);
+ mw.visitEnd();
+
+ // gets the bytecode of the Example class, and loads it dynamically
+ byte[] code = cw.toByteArray();
+
+ FileOutputStream fos = new FileOutputStream("Example.class");
+ fos.write(code);
+ fos.close();
+
+ Helloworld loader = new Helloworld();
+ Class<?> exampleClass = loader.defineClass("Example", code, 0,
+ code.length);
+
+ // uses the dynamically generated class to print 'Helloworld'
+ exampleClass.getMethods()[0].invoke(null, new Object[] { null });
+
+ // ------------------------------------------------------------------------
+ // Same example with a GeneratorAdapter (more convenient but slower)
+ // ------------------------------------------------------------------------
+
+ cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
+
+ // creates a GeneratorAdapter for the (implicit) constructor
+ Method m = Method.getMethod("void <init> ()");
+ GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null,
+ cw);
+ mg.loadThis();
+ mg.invokeConstructor(Type.getType(Object.class), m);
+ mg.returnValue();
+ mg.endMethod();
+
+ // creates a GeneratorAdapter for the 'main' method
+ m = Method.getMethod("void main (String[])");
+ mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
+ mg.getStatic(Type.getType(System.class), "out",
+ Type.getType(PrintStream.class));
+ mg.push("Hello world!");
+ mg.invokeVirtual(Type.getType(PrintStream.class),
+ Method.getMethod("void println (String)"));
+ mg.returnValue();
+ mg.endMethod();
+
+ cw.visitEnd();
+
+ code = cw.toByteArray();
+ loader = new Helloworld();
+ exampleClass = loader.defineClass("Example", code, 0, code.length);
+
+ // uses the dynamically generated class to print 'Helloworld'
+ exampleClass.getMethods()[0].invoke(null, new Object[] { null });
+ }
+}
diff --git a/asm4/examples/jasmin/etc/execute.properties b/asm4/examples/jasmin/etc/execute.properties
new file mode 100644
index 0000000..3c53857
--- /dev/null
+++ b/asm4/examples/jasmin/etc/execute.properties
@@ -0,0 +1,32 @@
+###############################################################################
+#ASM: a very small and fast Java bytecode manipulation framework
+#Copyright (c) 2000-2011 INRIA, France Telecom
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+#THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################
+
+run.classname JasminifierClassAdapter
+run.parameters java.lang.Object
diff --git a/asm4/examples/jasmin/src/JasminifierClassAdapter.java b/asm4/examples/jasmin/src/JasminifierClassAdapter.java
new file mode 100644
index 0000000..45d9073
--- /dev/null
+++ b/asm4/examples/jasmin/src/JasminifierClassAdapter.java
@@ -0,0 +1,900 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.AnnotationNode;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.InnerClassNode;
+import org.objectweb.asm.tree.LabelNode;
+import org.objectweb.asm.tree.LocalVariableNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TryCatchBlockNode;
+import org.objectweb.asm.util.Printer;
+
+/**
+ * A {@link ClassVisitor} that prints a disassembled view of the classes it
+ * visits in Jasmin assembler format. This class visitor can be used alone (see
+ * the {@link #main main} method) to disassemble a class. It can also be used in
+ * the middle of class visitor chain to trace the class that is visited at a
+ * given point in this chain. This may be uselful for debugging purposes.
+ * <p>
+ * The trace printed when visiting the <tt>Hello</tt> class is the following:
+ * <p>
+ * <blockquote>
+ *
+ * <pre>
+ * .bytecode 45.3
+ * .class public Hello
+ * .super java/lang/Object
+ *
+ * .method public <init>()V
+ * aload 0
+ * invokespecial java/lang/Object/<init>()V
+ * return
+ * .limit locals 1
+ * .limit stack 1
+ * .end method
+ *
+ * .method public static main([Ljava/lang/String;)V
+ * getstatic java/lang/System/out Ljava/io/PrintStream;
+ * ldc "hello"
+ * invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
+ * return
+ * .limit locals 2
+ * .limit stack 2
+ * .end method
+ * </pre>
+ *
+ * </blockquote> where <tt>Hello</tt> is defined by:
+ * <p>
+ * <blockquote>
+ *
+ * <pre>
+ * public class Hello {
+ *
+ * public static void main(String[] args) {
+ * System.out.println(&quot;hello&quot;);
+ * }
+ * }
+ * </pre>
+ *
+ * </blockquote>
+ *
+ * @author Eric Bruneton
+ */
+public class JasminifierClassAdapter extends ClassVisitor {
+
+ /**
+ * The print writer to be used to print the class.
+ */
+ protected PrintWriter pw;
+
+ /**
+ * The label names. This map associate String values to Label keys.
+ */
+ protected final Map<Label, String> labelNames;
+
+ /**
+ * Prints a disassembled view of the given class in Jasmin assembler format
+ * to the standard output.
+ * <p>
+ * Usage: JasminifierClassAdapter [-debug] &lt;fully qualified class name or
+ * class file name &gt;
+ *
+ * @param args
+ * the command line arguments.
+ *
+ * @throws Exception
+ * if the class cannot be found, or if an IO exception occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ int i = 0;
+ int flags = ClassReader.SKIP_DEBUG;
+
+ boolean ok = true;
+ if (args.length < 1 || args.length > 2) {
+ ok = false;
+ }
+ if (ok && "-debug".equals(args[0])) {
+ i = 1;
+ flags = 0;
+ if (args.length != 2) {
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.err
+ .println("Prints a disassembled view of the given class.");
+ System.err.println("Usage: JasminifierClassAdapter [-debug] "
+ + "<fully qualified class name or class file name>");
+ return;
+ }
+ ClassReader cr;
+ if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
+ || args[i].indexOf('/') > -1) {
+ cr = new ClassReader(new FileInputStream(args[i]));
+ } else {
+ cr = new ClassReader(args[i]);
+ }
+ cr.accept(new JasminifierClassAdapter(
+ new PrintWriter(System.out, true), null), flags
+ | ClassReader.EXPAND_FRAMES);
+ }
+
+ /**
+ * Constructs a new {@link JasminifierClassAdapter}.
+ *
+ * @param pw
+ * the print writer to be used to print the class.
+ * @param cv
+ * the {@link ClassVisitor} to which this visitor delegates
+ * calls. May be <tt>null</tt>.
+ */
+ public JasminifierClassAdapter(final PrintWriter pw, final ClassVisitor cv) {
+ super(Opcodes.ASM4, new ClassNode() {
+ @Override
+ public void visitEnd() {
+ if (cv != null) {
+ accept(cv);
+ }
+ }
+ });
+ this.pw = pw;
+ labelNames = new HashMap<Label, String>();
+ }
+
+ @Override
+ public void visitEnd() {
+ ClassNode cn = (ClassNode) cv;
+ pw.print(".bytecode ");
+ pw.print(cn.version & 0xFFFF);
+ pw.print('.');
+ pw.println(cn.version >>> 16);
+ println(".source ", cn.sourceFile);
+ pw.print(".class");
+ pw.print(access(cn.access));
+ pw.print(' ');
+ pw.println(cn.name);
+ if (cn.superName == null) { // TODO Jasmin bug workaround
+ println(".super ", "java/lang/Object");
+ } else {
+ println(".super ", cn.superName);
+ }
+ for (int i = 0; i < cn.interfaces.size(); ++i) {
+ println(".implements ", cn.interfaces.get(i));
+ }
+ if (cn.signature != null)
+ println(".signature ", '"' + cn.signature + '"');
+ if (cn.outerClass != null) {
+ pw.print(".enclosing method ");
+ pw.print(cn.outerClass);
+ if (cn.outerMethod != null) {
+ pw.print('/');
+ pw.print(cn.outerMethod);
+ pw.println(cn.outerMethodDesc);
+ } else {
+ pw.println();
+ }
+ }
+ if ((cn.access & Opcodes.ACC_DEPRECATED) != 0) {
+ pw.println(".deprecated");
+ }
+ printAnnotations(cn.visibleAnnotations, 1);
+ printAnnotations(cn.invisibleAnnotations, 2);
+ println(".debug ", cn.sourceDebug == null ? null
+ : '"' + cn.sourceDebug + '"');
+
+ for (int i = 0; i < cn.innerClasses.size(); ++i) {
+ InnerClassNode in = cn.innerClasses.get(i);
+ pw.print(".inner class");
+ pw.print(access(in.access));
+ if (in.innerName != null) {
+ pw.print(' ');
+ pw.print(in.innerName);
+ }
+ if (in.name != null) {
+ pw.print(" inner ");
+ pw.print(in.name);
+ }
+ if (in.outerName != null) {
+ pw.print(" outer ");
+ pw.print(in.outerName);
+ }
+ pw.println();
+ }
+
+ for (int i = 0; i < cn.fields.size(); ++i) {
+ FieldNode fn = cn.fields.get(i);
+ boolean annotations = false;
+ if (fn.visibleAnnotations != null
+ && fn.visibleAnnotations.size() > 0) {
+ annotations = true;
+ }
+ if (fn.invisibleAnnotations != null
+ && fn.invisibleAnnotations.size() > 0) {
+ annotations = true;
+ }
+ boolean deprecated = (fn.access & Opcodes.ACC_DEPRECATED) != 0;
+ pw.print("\n.field");
+ pw.print(access(fn.access));
+ pw.print(" '");
+ pw.print(fn.name);
+ pw.print("' ");
+ pw.print(fn.desc);
+ if (fn.signature != null && (!deprecated && !annotations)) {
+ pw.print(" signature \"");
+ pw.print(fn.signature);
+ pw.print("\"");
+ }
+ if (fn.value instanceof String) {
+ StringBuffer buf = new StringBuffer();
+ Printer.appendString(buf, (String) fn.value);
+ pw.print(" = ");
+ pw.print(buf.toString());
+ } else if (fn.value != null) {
+ pw.print(" = ");
+ print(fn.value);
+ pw.println();
+ }
+ pw.println();
+ if (fn.signature != null && (deprecated || annotations)) {
+ pw.print(".signature \"");
+ pw.print(fn.signature);
+ pw.println("\"");
+ }
+ if (deprecated) {
+ pw.println(".deprecated");
+ }
+ printAnnotations(fn.visibleAnnotations, 1);
+ printAnnotations(fn.invisibleAnnotations, 2);
+ if (deprecated || annotations) {
+ pw.println(".end field");
+ }
+ }
+
+ for (int i = 0; i < cn.methods.size(); ++i) {
+ MethodNode mn = cn.methods.get(i);
+ pw.print("\n.method");
+ pw.print(access(mn.access));
+ pw.print(' ');
+ pw.print(mn.name);
+ pw.println(mn.desc);
+ if (mn.signature != null) {
+ pw.print(".signature \"");
+ pw.print(mn.signature);
+ pw.println("\"");
+ }
+ if (mn.annotationDefault != null) {
+ pw.println(".annotation default");
+ printAnnotationValue(mn.annotationDefault);
+ pw.println(".end annotation");
+ }
+ printAnnotations(mn.visibleAnnotations, 1);
+ printAnnotations(mn.invisibleAnnotations, 2);
+ if (mn.visibleParameterAnnotations != null) {
+ for (int j = 0; j < mn.visibleParameterAnnotations.length; ++j) {
+ printAnnotations(mn.visibleParameterAnnotations[j], 1);
+ }
+ }
+ if (mn.invisibleParameterAnnotations != null) {
+ for (int j = 0; j < mn.invisibleParameterAnnotations.length; ++j) {
+ printAnnotations(mn.invisibleParameterAnnotations[j], 2);
+ }
+ }
+ for (int j = 0; j < mn.exceptions.size(); ++j) {
+ println(".throws ", mn.exceptions.get(j));
+ }
+ if ((mn.access & Opcodes.ACC_DEPRECATED) != 0) {
+ pw.println(".deprecated");
+ }
+ if (mn.instructions.size() > 0) {
+ labelNames.clear();
+ for (int j = 0; j < mn.tryCatchBlocks.size(); ++j) {
+ TryCatchBlockNode tcb = mn.tryCatchBlocks.get(j);
+ pw.print(".catch ");
+ pw.print(tcb.type);
+ pw.print(" from ");
+ print(tcb.start);
+ pw.print(" to ");
+ print(tcb.end);
+ pw.print(" using ");
+ print(tcb.handler);
+ pw.println();
+ }
+ for (int j = 0; j < mn.instructions.size(); ++j) {
+ AbstractInsnNode in = mn.instructions.get(j);
+ in.accept(new MethodVisitor(Opcodes.ASM4) {
+
+ @Override
+ public void visitFrame(int type, int local,
+ Object[] locals, int stack, Object[] stacks) {
+ if (type != Opcodes.F_FULL && type != Opcodes.F_NEW) {
+ throw new RuntimeException(
+ "Compressed frames unsupported, use EXPAND_FRAMES option");
+ }
+ pw.println(".stack");
+ for (int i = 0; i < local; ++i) {
+ pw.print("locals ");
+ printFrameType(locals[i]);
+ pw.println();
+ }
+ for (int i = 0; i < stack; ++i) {
+ pw.print("stack ");
+ printFrameType(stacks[i]);
+ pw.println();
+ }
+ pw.println(".end stack");
+ }
+
+ @Override
+ public void visitInsn(int opcode) {
+ print(opcode);
+ pw.println();
+ }
+
+ @Override
+ public void visitIntInsn(int opcode, int operand) {
+ print(opcode);
+ if (opcode == Opcodes.NEWARRAY) {
+ switch (operand) {
+ case Opcodes.T_BOOLEAN:
+ pw.println(" boolean");
+ break;
+ case Opcodes.T_CHAR:
+ pw.println(" char");
+ break;
+ case Opcodes.T_FLOAT:
+ pw.println(" float");
+ break;
+ case Opcodes.T_DOUBLE:
+ pw.println(" double");
+ break;
+ case Opcodes.T_BYTE:
+ pw.println(" byte");
+ break;
+ case Opcodes.T_SHORT:
+ pw.println(" short");
+ break;
+ case Opcodes.T_INT:
+ pw.println(" int");
+ break;
+ case Opcodes.T_LONG:
+ default:
+ pw.println(" long");
+ break;
+ }
+ } else {
+ pw.print(' ');
+ pw.println(operand);
+ }
+ }
+
+ @Override
+ public void visitVarInsn(int opcode, int var) {
+ print(opcode);
+ pw.print(' ');
+ pw.println(var);
+ }
+
+ @Override
+ public void visitTypeInsn(int opcode, String type) {
+ print(opcode);
+ pw.print(' ');
+ pw.println(type);
+ }
+
+ @Override
+ public void visitFieldInsn(int opcode, String owner,
+ String name, String desc) {
+ print(opcode);
+ pw.print(' ');
+ pw.print(owner);
+ pw.print('/');
+ pw.print(name);
+ pw.print(' ');
+ pw.println(desc);
+ }
+
+ @Override
+ public void visitMethodInsn(int opcode, String owner,
+ String name, String desc) {
+ print(opcode);
+ pw.print(' ');
+ pw.print(owner);
+ pw.print('/');
+ pw.print(name);
+ pw.print(desc);
+ if (opcode == Opcodes.INVOKEINTERFACE) {
+ pw.print(' ');
+ pw.print((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1);
+ }
+ pw.println();
+ }
+
+ @Override
+ public void visitJumpInsn(int opcode, Label label) {
+ print(opcode);
+ pw.print(' ');
+ print(label);
+ pw.println();
+ }
+
+ @Override
+ public void visitLabel(Label label) {
+ print(label);
+ pw.println(':');
+ }
+
+ @Override
+ public void visitLdcInsn(Object cst) {
+ pw.print("ldc ");
+ if (cst instanceof Type) {
+ pw.print(((Type) cst).getInternalName());
+ } else {
+ print(cst);
+ }
+ pw.println();
+ }
+
+ @Override
+ public void visitIincInsn(int var, int increment) {
+ pw.print("iinc ");
+ pw.print(var);
+ pw.print(' ');
+ pw.println(increment);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(int min, int max,
+ Label dflt, Label... labels) {
+ pw.print("tableswitch ");
+ pw.println(min);
+ for (int i = 0; i < labels.length; ++i) {
+ print(labels[i]);
+ pw.println();
+ }
+ pw.print("default : ");
+ print(dflt);
+ pw.println();
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(Label dflt,
+ int[] keys, Label[] labels) {
+ if (keys.length == 0) {
+ pw.print("goto "); // TODO Jasmin bug
+ // workaround
+ print(dflt);
+ pw.println();
+ return;
+ }
+ pw.println("lookupswitch");
+ for (int i = 0; i < keys.length; ++i) {
+ pw.print(keys[i]);
+ pw.print(" : ");
+ print(labels[i]);
+ pw.println();
+ }
+ pw.print("default : ");
+ print(dflt);
+ pw.println();
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(String desc,
+ int dims) {
+ pw.print("multianewarray ");
+ pw.print(desc);
+ pw.print(' ');
+ pw.println(dims);
+ }
+
+ @Override
+ public void visitLineNumber(int line, Label start) {
+ pw.print(".line ");
+ pw.println(line);
+ }
+ });
+ }
+ for (int j = 0; j < mn.localVariables.size(); ++j) {
+ LocalVariableNode lv = mn.localVariables.get(j);
+ pw.print(".var ");
+ pw.print(lv.index);
+ pw.print(" is '");
+ pw.print(lv.name);
+ pw.print("' ");
+ pw.print(lv.desc);
+ if (lv.signature != null) {
+ pw.print(" signature \"");
+ pw.print(lv.signature);
+ pw.print("\"");
+ }
+ pw.print(" from ");
+ print(lv.start);
+ pw.print(" to ");
+ print(lv.end);
+ pw.println();
+ }
+ println(".limit locals ", Integer.toString(mn.maxLocals));
+ println(".limit stack ", Integer.toString(mn.maxStack));
+ }
+ pw.println(".end method");
+ }
+ super.visitEnd();
+ }
+
+ protected void println(final String directive, final String arg) {
+ if (arg != null) {
+ pw.print(directive);
+ pw.println(arg);
+ }
+ }
+
+ protected String access(final int access) {
+ StringBuffer b = new StringBuffer();
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ b.append(" public");
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ b.append(" private");
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ b.append(" protected");
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ b.append(" static");
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ b.append(" final");
+ }
+ if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+ b.append(" synchronized");
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0) {
+ b.append(" volatile");
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+ b.append(" transient");
+ }
+ if ((access & Opcodes.ACC_NATIVE) != 0) {
+ b.append(" native");
+ }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ b.append(" abstract");
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ b.append(" fpstrict");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ b.append(" synthetic");
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ b.append(" interface");
+ }
+ if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+ b.append(" annotation");
+ }
+ if ((access & Opcodes.ACC_ENUM) != 0) {
+ b.append(" enum");
+ }
+ return b.toString();
+ }
+
+ protected void print(final int opcode) {
+ pw.print(Printer.OPCODES[opcode].toLowerCase());
+ }
+
+ protected void print(final Object cst) {
+ if (cst instanceof String) {
+ StringBuffer buf = new StringBuffer();
+ Printer.appendString(buf, (String) cst);
+ pw.print(buf.toString());
+ } else if (cst instanceof Float) {
+ Float f = (Float) cst;
+ if (f.isNaN() || f.isInfinite()) {
+ pw.print("0.0"); // TODO Jasmin bug workaround
+ } else {
+ pw.print(f);
+ }
+ } else if (cst instanceof Double) {
+ Double d = (Double) cst;
+ if (d.isNaN() || d.isInfinite()) {
+ pw.print("0.0"); // TODO Jasmin bug workaround
+ } else {
+ pw.print(d);
+ }
+ } else {
+ pw.print(cst);
+ }
+ }
+
+ protected void print(final Label l) {
+ String name = labelNames.get(l);
+ if (name == null) {
+ name = "L" + labelNames.size();
+ labelNames.put(l, name);
+ }
+ pw.print(name);
+ }
+
+ protected void print(final LabelNode l) {
+ print(l.getLabel());
+ }
+
+ protected void printAnnotations(final List<AnnotationNode> annotations,
+ int visible) {
+ if (annotations != null) {
+ for (int j = 0; j < annotations.size(); ++j) {
+ printAnnotation(annotations.get(j), visible, -1);
+ }
+ }
+ }
+
+ protected void printAnnotation(final AnnotationNode n, final int visible,
+ final int param) {
+ pw.print(".annotation ");
+ if (visible > 0) {
+ if (param == -1) {
+ pw.print(visible == 1 ? "visible " : "invisible ");
+ } else {
+ pw.print(visible == 1 ? "visibleparam " : "invisibleparam ");
+ pw.print(param);
+ pw.print(' ');
+ }
+ pw.print(n.desc);
+ }
+ pw.println();
+ if (n.values != null) {
+ for (int i = 0; i < n.values.size(); i += 2) {
+ pw.print(n.values.get(i));
+ pw.print(' ');
+ printAnnotationValue(n.values.get(i + 1));
+ }
+ }
+ pw.println(".end annotation");
+ }
+
+ protected void printAnnotationValue(final Object value) {
+ if (value instanceof String[]) {
+ pw.print("e ");
+ pw.print(((String[]) value)[0]);
+ pw.print(" = ");
+ print(((String[]) value)[1]);
+ pw.println();
+ } else if (value instanceof AnnotationNode) {
+ pw.print("@ ");
+ pw.print(((AnnotationNode) value).desc);
+ pw.print(" = ");
+ printAnnotation((AnnotationNode) value, 0, -1);
+ } else if (value instanceof byte[]) {
+ pw.print("[B = ");
+ byte[] v = (byte[]) value;
+ for (int i = 0; i < v.length; i++) {
+ pw.print(v[i]);
+ pw.print(' ');
+ }
+ pw.println();
+ } else if (value instanceof boolean[]) {
+ pw.print("[Z = ");
+ boolean[] v = (boolean[]) value;
+ for (int i = 0; i < v.length; i++) {
+ pw.print(v[i] ? '1' : '0');
+ pw.print(' ');
+ }
+ pw.println();
+ } else if (value instanceof short[]) {
+ pw.print("[S = ");
+ short[] v = (short[]) value;
+ for (int i = 0; i < v.length; i++) {
+ pw.print(v[i]);
+ pw.print(' ');
+ }
+ pw.println();
+ } else if (value instanceof char[]) {
+ pw.print("[C = ");
+ char[] v = (char[]) value;
+ for (int i = 0; i < v.length; i++) {
+ pw.print(new Integer(v[i]));
+ pw.print(' ');
+ }
+ pw.println();
+ } else if (value instanceof int[]) {
+ pw.print("[I = ");
+ int[] v = (int[]) value;
+ for (int i = 0; i < v.length; i++) {
+ pw.print(v[i]);
+ pw.print(' ');
+ }
+ pw.println();
+ } else if (value instanceof long[]) {
+ pw.print("[J = ");
+ long[] v = (long[]) value;
+ for (int i = 0; i < v.length; i++) {
+ pw.print(v[i]);
+ pw.print(' ');
+ }
+ pw.println();
+ } else if (value instanceof float[]) {
+ pw.print("[F = ");
+ float[] v = (float[]) value;
+ for (int i = 0; i < v.length; i++) {
+ print(new Float(v[i]));
+ pw.print(' ');
+ }
+ pw.println();
+ } else if (value instanceof double[]) {
+ pw.print("[D = ");
+ double[] v = (double[]) value;
+ for (int i = 0; i < v.length; i++) {
+ print(new Double(v[i]));
+ pw.print(' ');
+ }
+ pw.println();
+ } else if (value instanceof List) {
+ List<?> l = (List<?>) value;
+ if (l.size() > 0) {
+ Object o = l.get(0);
+ if (o instanceof String[]) {
+ pw.print("[e ");
+ pw.print(((String[]) o)[0]);
+ pw.print(" = ");
+ } else if (o instanceof AnnotationNode) {
+ pw.print("[& ");
+ pw.print(((AnnotationNode) o).desc);
+ pw.print(" = ");
+ pw.print("[@ = ");
+ } else if (o instanceof String) {
+ pw.print("[s = ");
+ } else if (o instanceof Byte) {
+ pw.print("[B = ");
+ } else if (o instanceof Boolean) {
+ pw.print("[Z = ");
+ } else if (o instanceof Character) {
+ pw.print("[C = ");
+ } else if (o instanceof Short) {
+ pw.print("[S = ");
+ } else if (o instanceof Type) {
+ pw.print("[c = ");
+ } else if (o instanceof Integer) {
+ pw.print("[I = ");
+ } else if (o instanceof Float) {
+ pw.print("[F = ");
+ } else if (o instanceof Long) {
+ pw.print("[J = ");
+ } else if (o instanceof Double) {
+ pw.print("[D = ");
+ }
+ for (int j = 0; j < l.size(); ++j) {
+ printAnnotationArrayValue(l.get(j));
+ pw.print(' ');
+ }
+ } else {
+ pw.print("; empty array annotation value");
+ }
+ pw.println();
+ } else if (value instanceof String) {
+ pw.print("s = ");
+ print(value);
+ pw.println();
+ } else if (value instanceof Byte) {
+ pw.print("B = ");
+ pw.println(((Byte) value).intValue());
+ } else if (value instanceof Boolean) {
+ pw.print("Z = ");
+ pw.println(((Boolean) value).booleanValue() ? 1 : 0);
+ } else if (value instanceof Character) {
+ pw.print("C = ");
+ pw.println(new Integer(((Character) value).charValue()));
+ } else if (value instanceof Short) {
+ pw.print("S = ");
+ pw.println(((Short) value).intValue());
+ } else if (value instanceof Type) {
+ pw.print("c = ");
+ pw.println(((Type) value).getDescriptor());
+ } else if (value instanceof Integer) {
+ pw.print("I = ");
+ print(value);
+ pw.println();
+ } else if (value instanceof Float) {
+ pw.print("F = ");
+ print(value);
+ pw.println();
+ } else if (value instanceof Long) {
+ pw.print("J = ");
+ print(value);
+ pw.println();
+ } else if (value instanceof Double) {
+ pw.print("D = ");
+ print(value);
+ pw.println();
+ } else {
+ throw new RuntimeException();
+ }
+ }
+
+ protected void printAnnotationArrayValue(final Object value) {
+ if (value instanceof String[]) {
+ print(((String[]) value)[1]);
+ } else if (value instanceof AnnotationNode) {
+ printAnnotation((AnnotationNode) value, 0, -1);
+ } else if (value instanceof String) {
+ print(value);
+ } else if (value instanceof Byte) {
+ pw.print(((Byte) value).intValue());
+ } else if (value instanceof Boolean) {
+ pw.print(((Boolean) value).booleanValue() ? 1 : 0);
+ } else if (value instanceof Character) {
+ pw.print(new Integer(((Character) value).charValue()));
+ } else if (value instanceof Short) {
+ pw.print(((Short) value).intValue());
+ } else if (value instanceof Type) {
+ pw.print(((Type) value).getDescriptor());
+ } else {
+ print(value);
+ }
+ }
+
+ protected void printFrameType(final Object type) {
+ if (type == Opcodes.TOP) {
+ pw.print("Top");
+ } else if (type == Opcodes.INTEGER) {
+ pw.print("Integer");
+ } else if (type == Opcodes.FLOAT) {
+ pw.print("Float");
+ } else if (type == Opcodes.LONG) {
+ pw.print("Long");
+ } else if (type == Opcodes.DOUBLE) {
+ pw.print("Double");
+ } else if (type == Opcodes.NULL) {
+ pw.print("Null");
+ } else if (type == Opcodes.UNINITIALIZED_THIS) {
+ pw.print("UninitializedThis");
+ } else if (type instanceof Label) {
+ pw.print("Uninitialized ");
+ print((Label) type);
+ } else {
+ pw.print("Object ");
+ pw.print(type);
+ }
+ }
+}
diff --git a/asm4/examples/jasmin/test/JasminifierClassAdapterTest.java b/asm4/examples/jasmin/test/JasminifierClassAdapterTest.java
new file mode 100644
index 0000000..888ec0a
--- /dev/null
+++ b/asm4/examples/jasmin/test/JasminifierClassAdapterTest.java
@@ -0,0 +1,280 @@
+/***
+ * ASM tests
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import jas.jasError;
+import jasmin.ClassFile;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ByteVector;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.util.TraceClassVisitor;
+
+class ClassFilter extends ClassVisitor {
+
+ public ClassFilter() {
+ super(Opcodes.ASM4, null);
+ }
+
+ public void setNext(final ClassVisitor cv) {
+ this.cv = cv;
+ }
+}
+
+class Comment extends Attribute {
+
+ public Comment() {
+ super("Comment");
+ }
+
+ @Override
+ public boolean isUnknown() {
+ return false;
+ }
+
+ @Override
+ protected Attribute read(final ClassReader cr, final int off,
+ final int len, final char[] buf, final int codeOff,
+ final Label[] labels) {
+
+ return new Comment();
+ }
+
+ @Override
+ protected ByteVector write(final ClassWriter cw, final byte[] code,
+ final int len, final int maxStack, final int maxLocals) {
+ return new ByteVector();
+ }
+}
+
+class CodeComment extends Attribute {
+
+ public CodeComment() {
+ super("CodeComment");
+ }
+
+ @Override
+ public boolean isUnknown() {
+ return false;
+ }
+
+ @Override
+ public boolean isCodeAttribute() {
+ return true;
+ }
+
+ @Override
+ protected Attribute read(final ClassReader cr, final int off,
+ final int len, final char[] buf, final int codeOff,
+ final Label[] labels) {
+ return new CodeComment();
+ }
+
+ @Override
+ protected ByteVector write(final ClassWriter cw, final byte[] code,
+ final int len, final int maxStack, final int maxLocals) {
+ return new ByteVector();
+ }
+
+ @Override
+ protected Label[] getLabels() {
+ super.getLabels();
+ return new Label[] { new Label() };
+ }
+}
+
+/**
+ * JasminifierAdapterTest tests.
+ *
+ * @author Eric Bruneton
+ */
+public class JasminifierClassAdapterTest extends TestCase {
+
+ protected String n;
+
+ protected InputStream is;
+
+ public static TestSuite suite() throws Exception {
+ return new JasminifierClassAdapterTest().getSuite();
+ }
+
+ public JasminifierClassAdapterTest() {
+ super("test");
+ }
+
+ protected void init(final String n, final InputStream is) {
+ this.n = n;
+ this.is = is;
+ }
+
+ protected TestSuite getSuite() throws Exception {
+ TestSuite suite = new TestSuite(getClass().getName());
+ String files = System.getProperty("asm.test") + ",";
+ String clazz = System.getProperty("asm.test.class");
+ String partcount = System.getProperty("parts");
+ String partid = System.getProperty("part");
+ int parts = partcount == null ? 1 : Integer.parseInt(partcount);
+ int part = partid == null ? 0 : Integer.parseInt(partid);
+ int id = 0;
+ while (files.indexOf(',') != -1) {
+ String file = files.substring(0, files.indexOf(','));
+ files = files.substring(files.indexOf(',') + 1);
+ File f = new File(file);
+ if (f.isDirectory()) {
+ scanDirectory("", f, suite, clazz);
+ } else {
+ ZipFile zip = new ZipFile(file);
+ Enumeration<? extends ZipEntry> entries = zip.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry e = entries.nextElement();
+ String n = e.getName();
+ String p = n.replace('/', '.');
+ System.out.println(n + " " + clazz);
+ if (n.endsWith(".class")
+ && (clazz == null || p.indexOf(clazz) != -1)) {
+ n = p.substring(0, p.length() - 6);
+ if (id % parts == part) {
+ JasminifierClassAdapterTest t;
+ InputStream is = zip.getInputStream(e);
+ t = new JasminifierClassAdapterTest();
+ t.init(n, is);
+ suite.addTest(t);
+ }
+ ++id;
+ }
+ }
+ }
+ }
+ return suite;
+ }
+
+ private void scanDirectory(final String path, final File f,
+ final TestSuite suite, final String clazz) throws Exception {
+ File[] fs = f.listFiles();
+ for (int i = 0; i < fs.length; ++i) {
+ String n = fs[i].getName();
+ String qn = path.length() == 0 ? n : path + "." + n;
+ if (fs[i].isDirectory()) {
+ scanDirectory(qn, fs[i], suite, clazz);
+ } else if (qn.endsWith(".class")
+ && (clazz == null || qn.indexOf(clazz) != -1)) {
+ qn = qn.substring(0, qn.length() - 6);
+ InputStream is = new FileInputStream(fs[i]);
+ JasminifierClassAdapterTest t;
+ t = new JasminifierClassAdapterTest();
+ t.init(qn, is);
+ suite.addTest(t);
+ }
+ }
+ }
+
+ public void assertEquals(final ClassReader cr1, final ClassReader cr2)
+ throws Exception {
+ assertEquals(cr1, cr2, null, null);
+ }
+
+ public void assertEquals(final ClassReader cr1, final ClassReader cr2,
+ final ClassFilter filter1, final ClassFilter filter2)
+ throws Exception {
+ if (!Arrays.equals(cr1.b, cr2.b)) {
+ StringWriter sw1 = new StringWriter();
+ StringWriter sw2 = new StringWriter();
+ ClassVisitor cv1 = new TraceClassVisitor(new PrintWriter(sw1));
+ ClassVisitor cv2 = new TraceClassVisitor(new PrintWriter(sw2));
+ if (filter1 != null) {
+ filter1.setNext(cv1);
+ }
+ if (filter2 != null) {
+ filter2.setNext(cv2);
+ }
+ cr1.accept(filter1 == null ? cv1 : filter1, 0);
+ cr2.accept(filter2 == null ? cv2 : filter2, 0);
+ String s1 = sw1.toString();
+ String s2 = sw2.toString();
+ assertEquals("different data", s1, s2);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return super.getName() + ": " + n;
+ }
+
+ public void test() throws Exception {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ ClassReader cr = new ClassReader(is);
+ ClassWriter cw = new ClassWriter(0);
+ ClassVisitor cv = new JasminifierClassAdapter(pw, cw);
+ cr.accept(cv, new Attribute[] { new Comment(), new CodeComment() },
+ ClassReader.EXPAND_FRAMES);
+ pw.close();
+ String jasmin = sw.toString();
+
+ ClassFile cf = new ClassFile();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ cf.readJasmin(new StringReader(jasmin), "test", false);
+ if (cf.errorCount() != 0) {
+ throw new jasError();
+ }
+ cf.write(bos);
+ bos.close();
+
+ assertEquals(cr, new ClassReader(bos.toByteArray()), new ClassFilter() {
+
+ @Override
+ public void visit(int version, int access, String name,
+ String signature, String superName, String[] interfaces) {
+ access |= Opcodes.ACC_SUPER; // Jasmin bug workaround
+ super.visit(version, access, name, signature, superName,
+ interfaces);
+ }
+
+ }, null);
+ }
+}
diff --git a/asm4/examples/jasmin/test/build.xml b/asm4/examples/jasmin/test/build.xml
new file mode 100644
index 0000000..9ddf2a0
--- /dev/null
+++ b/asm4/examples/jasmin/test/build.xml
@@ -0,0 +1,74 @@
+<!--
+ ! ASM: a very small and fast Java bytecode manipulation framework
+ ! Copyright (c) 2000-2011 INRIA, France Telecom
+ ! All rights reserved.
+ !
+ ! Redistribution and use in source and binary forms, with or without
+ ! modification, are permitted provided that the following conditions
+ ! are met:
+ ! 1. Redistributions of source code must retain the above copyright
+ ! notice, this list of conditions and the following disclaimer.
+ ! 2. Redistributions in binary form must reproduce the above copyright
+ ! notice, this list of conditions and the following disclaimer in the
+ ! documentation and/or other materials provided with the distribution.
+ ! 3. Neither the name of the copyright holders nor the names of its
+ ! contributors may be used to endorse or promote products derived from
+ ! this software without specific prior written permission.
+ !
+ ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ ! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ ! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ ! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ ! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ ! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ ! THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project name="jasmin" default="test">
+
+ <condition property="asm.test" value="${java.home}/lib/rt.jar">
+ <not><isset property="asm.test"/></not>
+ </condition>
+
+ <condition property="asm.test.class" value="">
+ <not><isset property="asm.test.class"/></not>
+ </condition>
+
+ <path id="classpath">
+ <fileset dir="${basedir}/../../../lib">
+ <include name="*.jar"/>
+ </fileset>
+ <pathelement location="${basedir}/jasmin.jar"/>
+ <pathelement location="${basedir}/../build"/>
+ </path>
+
+ <target name="compile">
+ <javac srcdir="${basedir}" destdir="${basedir}" debug="on">
+ <classpath refid="classpath"/>
+ <include name="*.java"/>
+ </javac>
+ </target>
+
+ <target name="test" depends="compile">
+ <junit fork="yes"
+ printsummary="yes"
+ errorproperty="test.failed"
+ failureproperty="test.failed">
+ <batchtest fork="yes" todir="${basedir}">
+ <fileset dir="${basedir}">
+ <include name="JasminifierClassAdapterTest.java"/>
+ <include name="JasminifierClassAdapterUnitTest.java"/>
+ </fileset>
+ </batchtest>
+ <formatter type="xml"/>
+ <classpath refid="classpath"/>
+ <jvmarg value="-Dasm.test=${asm.test}"/>
+ <jvmarg value="-Dasm.test.class=${asm.test.class}"/>
+ </junit>
+ </target>
+
+</project>
diff --git a/asm4/examples/jasmin/test/jasmin.jar b/asm4/examples/jasmin/test/jasmin.jar
new file mode 100644
index 0000000..e276b1f
--- /dev/null
+++ b/asm4/examples/jasmin/test/jasmin.jar
Binary files differ
diff --git a/asm4/examples/jbfc/etc/execute.properties b/asm4/examples/jbfc/etc/execute.properties
new file mode 100644
index 0000000..bc81fc9
--- /dev/null
+++ b/asm4/examples/jbfc/etc/execute.properties
@@ -0,0 +1,32 @@
+###############################################################################
+#ASM: a very small and fast Java bytecode manipulation framework
+#Copyright (c) 2000-2011 INRIA, France Telecom
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+#THE POSSIBILITY OF SUCH DAMAGE.
+###############################################################################
+
+run.classname org.objectweb.asm.jbfc.BFCompilerTest
+run.parameters
diff --git a/asm4/examples/jbfc/src/jbfc.java b/asm4/examples/jbfc/src/jbfc.java
new file mode 100644
index 0000000..7a35504
--- /dev/null
+++ b/asm4/examples/jbfc/src/jbfc.java
@@ -0,0 +1,86 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.jbfc.BFCompiler;
+import org.objectweb.asm.util.TraceClassVisitor;
+
+/**
+ * A naive implementation of compiler for Brain**** language.
+ * http://www.muppetlabs.com/~breadbox/bf/ *
+ *
+ * @author Eugene Kuleshov
+ */
+public class jbfc {
+
+ public static void main(final String[] args) throws IOException {
+ if (args.length < 2) {
+ System.out
+ .println("Usage: jbfc [-v] <bf program file> <java class name>");
+ return;
+ }
+
+ boolean verbose = false;
+ String fileName = null;
+ String className = null;
+ for (int i = 0; i < args.length; i++) {
+ if ("-v".equals(args[i])) {
+ verbose = true;
+ } else {
+ fileName = args[i];
+ className = args[i + 1];
+ break;
+ }
+ }
+
+ FileReader r = new FileReader(fileName);
+
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ BFCompiler c = new BFCompiler();
+ if (verbose) {
+ c.compile(r, className, fileName, new TraceClassVisitor(cw,
+ new PrintWriter(System.out)));
+ } else {
+ c.compile(r, className, fileName, cw);
+ }
+
+ r.close();
+
+ FileOutputStream os = new FileOutputStream(className + ".class");
+ os.write(cw.toByteArray());
+ os.flush();
+ os.close();
+ }
+
+}
diff --git a/asm4/examples/jbfc/src/org/objectweb/asm/jbfc/BFCompiler.java b/asm4/examples/jbfc/src/org/objectweb/asm/jbfc/BFCompiler.java
new file mode 100644
index 0000000..be7a1f6
--- /dev/null
+++ b/asm4/examples/jbfc/src/org/objectweb/asm/jbfc/BFCompiler.java
@@ -0,0 +1,206 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.jbfc;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Stack;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * A naive implementation of compiler for Brain**** language.
+ * http://www.muppetlabs.com/~breadbox/bf/ *
+ *
+ * @author Eugene Kuleshov
+ */
+public class BFCompiler implements Opcodes {
+
+ private static final int V_IS = 0;
+
+ private static final int V_OS = 1;
+
+ private static final int V_P = 2;
+
+ private static final int V_D = 3;
+
+ public void compile(final Reader r, final String className,
+ final String sourceName, final ClassVisitor cv) throws IOException {
+ cv.visit(Opcodes.V1_3, ACC_PUBLIC, className.replace('.', '/'), null,
+ "java/lang/Object", null);
+ cv.visitSource(sourceName, null);
+
+ MethodVisitor mv;
+ {
+ mv = cv.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>",
+ "()V");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+
+ {
+ // Init local vars for BF environment:
+ // 0 InputStream
+ // 1 OutputStream
+ // 2 Data Pointer
+ // 3 Data Array (int[ 30000])
+
+ mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",
+ "([Ljava/lang/String;)V", null, null);
+ mv.visitCode();
+
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "in",
+ "Ljava/io/InputStream;");
+ mv.visitVarInsn(ASTORE, V_IS);
+
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
+ "Ljava/io/PrintStream;");
+ mv.visitVarInsn(ASTORE, V_OS);
+
+ mv.visitInsn(ICONST_0);
+ mv.visitVarInsn(ISTORE, V_P);
+
+ mv.visitIntInsn(SIPUSH, 30000);
+ mv.visitIntInsn(NEWARRAY, T_INT);
+ mv.visitVarInsn(ASTORE, V_D);
+
+ Stack<Label> labels = new Stack<Label>();
+
+ int d = 0;
+ int p = 0;
+
+ int c;
+ while ((c = r.read()) != -1) {
+ switch (c) {
+ case '>':
+ d = storeD(mv, d);
+ p++;
+ break;
+
+ case '<':
+ d = storeD(mv, d);
+ p--;
+ break;
+
+ case '+':
+ p = storeP(mv, p);
+ d++;
+ break;
+
+ case '-':
+ p = storeP(mv, p);
+ d--;
+ break;
+
+ case '.':
+ p = storeP(mv, p);
+ d = storeD(mv, d);
+
+ mv.visitVarInsn(ALOAD, V_OS);
+ mv.visitVarInsn(ALOAD, V_D);
+ mv.visitVarInsn(ILOAD, V_P);
+ mv.visitInsn(IALOAD);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/OutputStream",
+ "write", "(I)V");
+ break;
+
+ case ',':
+ p = storeP(mv, p);
+ d = storeD(mv, d);
+
+ mv.visitVarInsn(ALOAD, V_D);
+ mv.visitVarInsn(ILOAD, V_P);
+ mv.visitVarInsn(ALOAD, V_IS);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/InputStream",
+ "read", "()I");
+ mv.visitInsn(IASTORE);
+ break;
+
+ case '[':
+ p = storeP(mv, p);
+ d = storeD(mv, d);
+
+ Label ls = new Label();
+ Label le = new Label();
+ labels.push(ls);
+ labels.push(le);
+ mv.visitJumpInsn(GOTO, le);
+ mv.visitLabel(ls);
+ break;
+
+ case ']':
+ p = storeP(mv, p);
+ d = storeD(mv, d);
+
+ mv.visitLabel(labels.pop());
+ mv.visitVarInsn(ALOAD, V_D);
+ mv.visitVarInsn(ILOAD, V_P);
+ mv.visitInsn(IALOAD);
+ mv.visitJumpInsn(IFNE, labels.pop());
+ break;
+ }
+ }
+
+ mv.visitInsn(RETURN);
+
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+
+ }
+
+ private int storeD(final MethodVisitor mv, final int d) {
+ if (d != 0) {
+ mv.visitVarInsn(ALOAD, V_D);
+ mv.visitVarInsn(ILOAD, V_P);
+ mv.visitInsn(DUP2);
+ mv.visitInsn(IALOAD);
+ mv.visitIntInsn(SIPUSH, d);
+ mv.visitInsn(IADD);
+ mv.visitInsn(IASTORE);
+ }
+ return 0;
+ }
+
+ private int storeP(final MethodVisitor mv, final int p) {
+ if (p != 0) {
+ mv.visitIincInsn(V_P, p);
+ }
+ return 0;
+ }
+
+}
diff --git a/asm4/examples/jbfc/src/org/objectweb/asm/jbfc/BFCompilerTest.java b/asm4/examples/jbfc/src/org/objectweb/asm/jbfc/BFCompilerTest.java
new file mode 100644
index 0000000..3fc1ebd
--- /dev/null
+++ b/asm4/examples/jbfc/src/org/objectweb/asm/jbfc/BFCompilerTest.java
@@ -0,0 +1,174 @@
+/***
+ * ASM examples: examples showing how ASM can be used
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.jbfc;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.StringReader;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.objectweb.asm.ClassWriter;
+
+/**
+ * A naive implementation of compiler for Brain**** language.
+ * http://www.muppetlabs.com/~breadbox/bf/ *
+ *
+ * @author Eugene Kuleshov
+ */
+public class BFCompilerTest {
+
+ private BFCompiler bc;
+
+ private ClassWriter cw;
+
+ public static void main(String[] args) throws Throwable {
+ new BFCompilerTest().testCompileHelloWorld();
+ new BFCompilerTest().testCompileEcho();
+ new BFCompilerTest().testCompileYaPi();
+ new BFCompilerTest().testCompileTest1();
+ }
+
+ public BFCompilerTest() throws Exception {
+ bc = new BFCompiler();
+ cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ }
+
+ public void testCompileHelloWorld() throws Throwable {
+ assertEquals(
+ "Hello World!\n",
+ execute("Hello",
+ ">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]"
+ + "<.#>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++["
+ + "<++++>-]<+.[-]++++++++++.", ""));
+ }
+
+ public void testCompileEcho() throws Throwable {
+ assertEquals("AAA", execute("Echo", ",+[-.,+]", "AAA"));
+ }
+
+ public void testCompileYaPi() throws Throwable {
+ assertEquals("3.1415926\n", execute("YaPi",
+ ">+++++[<+++++++++>-]>>>>>>\r\n\r\n+++++ +++ (7 "
+ + "digits)\r\n\r\n[<<+>++++++++++>-]<<+>>+++<[->>+"
+ + "<-[>>>]>[[<+>-]>+>>]<<<<<]>[-]>[-]>[<+>-]<[>+<["
+ + "-\r\n>>>>>>>+<<<<<<<]>[->+>>>>>>+<<<<<<<]>>>>++"
+ + ">>-]>[-]<<<[<<<<<<<]<[->>>>>[>>>>>>>]<\r\n<<<<<"
+ + "<[>>>>[-]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<<[<<++"
+ + "++++++++>>-]>[<<<<[>+>>+<<<-\r\n]>>>[<<<+>>>-]>"
+ + "-]<<<<[>>++>+<<<-]>>->[<<<+>>>-]>[-]<<<[->>+<-["
+ + ">>>]>[[<+>-]>+>>]<\r\n<<<<]>[-]<<<<<<<<<]>+>>>>"
+ + ">>->>>>[<<<<<<<<+>>>>>>>>-]<<<<<<<[-]++++++++++"
+ + "<[->>+<-\r\n[>>>]>[[<+>-]>+>>]<<<<<]>[-]>[>>>>>"
+ + "+<<<<<-]>[<+>>+<-]>[<+>-]<<<+<+>>[-[-[-[-[-[-\r"
+ + "\n[-[-[-<->[-<+<->>[<<+>>[-]]]]]]]]]]]]<[+++++["
+ + "<<<<++++++++>>>>>++++++++<-]>+<<<<-\r\n>>[>+>-<"
+ + "<<<<+++++++++>>>-]<<<<[>>>>>>+<<<<<<-]<[>>>>>>>"
+ + ".<<<<<<<<[+.[-]]>>]>[<]<+\r\n>>>[<.>-]<[-]>>>>>"
+ + "[-]<[>>[<<<<<<<+>>>>>>>-]<<-]]>>[-]>+<<<<[-]<]+"
+ + "+++++++++.", ""));
+ }
+
+ public void testCompileTest1() throws Throwable {
+ assertEquals("H\n", execute("Test1",
+ "[]++++++++++[>++++++++++++++++++>+++++++>+<<<-]A;?@![#>>"
+ + "+<<]>[>++<[-]]>.>.", ""));
+ }
+
+ public static void assertEquals(String s1, String s2) {
+ if (!s1.equals(s2)) {
+ System.out.println("ERROR: expected '" + s1 + "' but got '" + s2
+ + "'");
+ }
+ }
+
+ private String execute(final String name, final String code,
+ final String input) throws Throwable {
+ bc.compile(new StringReader(code), name, name, cw);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ InputStream is = System.in;
+ PrintStream os = System.out;
+ System.setIn(new ByteArrayInputStream(input.getBytes()));
+ System.setOut(new PrintStream(bos));
+
+ try {
+ TestClassLoader cl = new TestClassLoader(getClass()
+ .getClassLoader(), name, cw.toByteArray());
+ Class<?> c = cl.loadClass(name);
+ Method m = c.getDeclaredMethod("main",
+ new Class<?>[] { String[].class });
+ m.invoke(null, new Object[] { new String[0] });
+
+ } catch (InvocationTargetException ex) {
+ throw ex.getCause();
+ } finally {
+ System.setIn(is);
+ System.setOut(os);
+ }
+
+ String output = new String(bos.toByteArray(), "ASCII");
+
+ System.out
+ .println(code + " WITH INPUT '" + input + "' GIVES " + output);
+
+ return output;
+ }
+
+ private static final class TestClassLoader extends ClassLoader {
+
+ private final String className;
+
+ private final ClassLoader cl;
+
+ private final byte[] bytecode;
+
+ public TestClassLoader(final ClassLoader cl, final String className,
+ final byte[] bytecode) {
+ super();
+ this.cl = cl;
+ this.className = className;
+ this.bytecode = bytecode;
+ }
+
+ @Override
+ public Class<?> loadClass(final String name)
+ throws ClassNotFoundException {
+ if (className.equals(name)) {
+ return super.defineClass(className, bytecode, 0,
+ bytecode.length);
+ }
+ return cl.loadClass(name);
+ }
+
+ }
+}
diff --git a/asm4/examples/xml/annotate.xsl b/asm4/examples/xml/annotate.xsl
new file mode 100644
index 0000000..82a5bf2
--- /dev/null
+++ b/asm4/examples/xml/annotate.xsl
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="ASCII"?>
+<!--
+ ASM XML Adapter examples.
+ Copyright (c) 2004-2011, Eugene Kuleshov
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+ XSL transformation for ASM XML document to add annotational comments to the local
+ variables (name, type and visibility) and labels (line number, try/catch info,
+ number of incoming calls)
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="xml" indent="yes" encoding="ASCII" />
+
+<!--
+ Annotate opcodes that are working with local variables
+-->
+<xsl:template match="//ILOAD | //LLOAD | //FLOAD | //DLOAD | //ALOAD | //ISTORE | //LSTORE | //FSTORE | //DSTORE | //ASTORE | //RET">
+ <xsl:variable name="n"><xsl:value-of select="@var"/></xsl:variable>
+
+ <xsl:apply-templates select="../LocalVar[@var=$n]" mode="localVar"/>
+
+ <xsl:element name="{name()}">
+ <xsl:attribute name="var"><xsl:value-of select="$n"/></xsl:attribute>
+ </xsl:element>
+</xsl:template>
+
+
+<xsl:template match="*" mode="localVar">
+ <xsl:comment><xsl:text> </xsl:text><xsl:value-of select="concat( @name, ' ', @desc, ' ', @start, ' - ', @end)"/><xsl:text> </xsl:text></xsl:comment>
+</xsl:template>
+
+
+<!--
+ Annotate labels
+-->
+<xsl:template match="//method/code/Label">
+ <xsl:variable name="n"><xsl:value-of select="@name"/></xsl:variable>
+
+ <xsl:apply-templates select="../LineNumber[@start=$n]" mode="lineNumber"/>
+ <xsl:apply-templates select="../TryCatch[@start=$n]" mode="tryStart"/>
+ <xsl:apply-templates select="../TryCatch[@end=$n]" mode="tryEnd"/>
+ <xsl:apply-templates select="../TryCatch[@handler=$n]" mode="catch"/>
+
+ <xsl:variable name="c">
+ <!-- this is the slowest part -->
+ <xsl:value-of select="count(../IFEQ[@label=$n] | ../IFNE[@label=$n] | ../IFLT[@label=$n] | ../IFGE[@label=$n] | ../IFGT[@label=$n] | ../IFLE[@label=$n] | ../IF_ICMPEQ[@label=$n] | ../IF_ICMPNE[@label=$n] | ../IF_ICMPLT[@label=$n] | ../IF_ICMPGE[@label=$n] | ../IF_ICMPGT[@label=$n] | ../IF_ICMPLE[@label=$n] | ../IF_ACMPEQ[@label=$n] | ../IF_ACMPNE[@label=$n] | ../GOTO[@label=$n] | ../JSR[@label=$n] | ../IFNULL[@label=$n] | ../IFNONNULL[@label=$n] | ../TABLESWITCHINSN[@dflt=$n] | ../TABLESWITCHINSN/label[@name=$n] | ../LOOKUPSWITCH[@dflt=$n] | ../LOOKUPSWITCH/label[@name=$n])"/>
+ </xsl:variable>
+ <xsl:if test="$c>0">
+ <xsl:comment><xsl:text> Incoming calls: </xsl:text><xsl:value-of select="$c"/><xsl:text> </xsl:text></xsl:comment>
+ </xsl:if>
+
+ <label><xsl:apply-templates select="@*"/></label>
+
+</xsl:template>
+
+
+<xsl:template match="*" mode="lineNumber">
+ <xsl:comment><xsl:text> Line: </xsl:text><xsl:value-of select="@line"/><xsl:text> </xsl:text></xsl:comment>
+</xsl:template>
+
+<xsl:template match="*" mode="tryStart">
+ <xsl:comment><xsl:text> try start </xsl:text></xsl:comment>
+</xsl:template>
+
+<xsl:template match="*" mode="tryEnd">
+ <xsl:comment><xsl:text> try end </xsl:text></xsl:comment>
+</xsl:template>
+
+<xsl:template match="*" mode="catch">
+ <xsl:comment>
+ <xsl:text> catch </xsl:text>
+ <xsl:if test="string-length(@type)>0">
+ <xsl:text>(</xsl:text><xsl:value-of select="@type"/><xsl:text>)</xsl:text>
+ </xsl:if>
+ </xsl:comment>
+</xsl:template>
+
+
+<!-- copy everything -->
+<xsl:template match="@*|*|text()|processing-instruction()">
+ <xsl:copy><xsl:apply-templates select="@*|*|text()|processing-instruction()"/></xsl:copy>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/asm4/examples/xml/copy.xsl b/asm4/examples/xml/copy.xsl
new file mode 100644
index 0000000..dae3de6
--- /dev/null
+++ b/asm4/examples/xml/copy.xsl
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ASCII"?>
+<!--
+ ASM XML Adapter examples.
+ Copyright (c) 2004-2011, Eugene Kuleshov
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+ Copy source document into target without changes.
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="xml" indent="yes" encoding="ASCII" />
+
+<!-- copy everything -->
+<xsl:template match="@*|*|text()|processing-instruction()">
+ <xsl:copy><xsl:apply-templates select="@*|*|text()|processing-instruction()"/></xsl:copy>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/asm4/examples/xml/linenumbers.xsl b/asm4/examples/xml/linenumbers.xsl
new file mode 100644
index 0000000..dd63825
--- /dev/null
+++ b/asm4/examples/xml/linenumbers.xsl
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="ASCII"?>
+<!--
+ ASM XML Adapter examples.
+ Copyright (c) 2004-2011, Eugene Kuleshov
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+ XSL transformation for ASM XML document to add the equivalent of following
+ Java code for each label that has source line number information.
+
+ System.err.println( "<class>.<method><desc> Line:<source line number>");
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="xml" indent="yes" encoding="ASCII" />
+
+<xsl:template match="//method/code/Label">
+ <xsl:variable name="n"><xsl:value-of select="@name"/></xsl:variable>
+ <xsl:variable name="c"><xsl:value-of select="../LineNumber[@start=$n]/@line"/></xsl:variable>
+
+ <label><xsl:apply-templates select="@*"/></label>
+
+ <xsl:if test="string-length($c)>0">
+ <xsl:comment>
+ <xsl:text> Line: </xsl:text><xsl:value-of select="$c"/><xsl:text> </xsl:text>
+ </xsl:comment>
+
+ <GETSTATIC desc="Ljava/io/PrintStream;" name="err" owner="java/lang/System"/>
+ <LDC desc="Ljava/lang/String;">
+ <xsl:attribute name="cst">
+ <xsl:value-of select="concat( /class/@name, '.' ,../../@name, ../../@desc, ' Line:', $c)"/>
+ </xsl:attribute>
+ </LDC>
+ <INVOKEVIRTUAL desc="(Ljava/lang/String;)V" name="println" owner="java/io/PrintStream"/>
+ </xsl:if>
+
+</xsl:template>
+
+
+<!-- copy everything -->
+<xsl:template match="@*|*|text()|processing-instruction()">
+ <xsl:copy><xsl:apply-templates select="@*|*|text()|processing-instruction()"/></xsl:copy>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/asm4/examples/xml/profile.xsl b/asm4/examples/xml/profile.xsl
new file mode 100644
index 0000000..100a268
--- /dev/null
+++ b/asm4/examples/xml/profile.xsl
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="ASCII"?>
+<!--
+ ASM XML Adapter examples.
+ Copyright (c) 2004-2011, Eugene Kuleshov
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+ XSL transformation for ASM XML document to add the code that will dump
+ an execution time for each method.
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="xml" indent="yes" encoding="ASCII"/>
+
+
+<xsl:template match="//method/code">
+ <code>
+ <!-- add attributes for code element -->
+ <xsl:apply-templates select="@*"/>
+
+ <!-- store start time into the max variable after method params -->
+ <INVOKESTATIC desc="()J" name="currentTimeMillis" owner="java/lang/System"/>
+ <LSTORE>
+ <xsl:attribute name="var">
+ <xsl:value-of select="./Max/@maxLocals"/>
+ </xsl:attribute>
+ </LSTORE>
+
+ <!-- process child elements -->
+ <xsl:apply-templates select="*"/>
+
+ </code>
+
+</xsl:template>
+
+
+<!--
+ Add print statement before return instructions
+ IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, RETURN,
+ ATHROW ??
+-->
+<xsl:template match="//IRETURN | //LRETURN | //FRETURN | //DRETURN | //ARETURN | //RETURN">
+ <GETSTATIC desc="Ljava/io/PrintStream;" name="err" owner="java/lang/System"/>
+
+ <NEW desc="java/lang/StringBuffer"/>
+ <DUP/>
+ <INVOKESPECIAL owner="java/lang/StringBuffer" name="&lt;init&gt;" desc="()V"/>
+
+ <INVOKESTATIC desc="()J" name="currentTimeMillis" owner="java/lang/System"/>
+ <LLOAD>
+ <xsl:attribute name="var">
+ <xsl:value-of select="../Max/@maxLocals"/>
+ </xsl:attribute>
+ </LLOAD>
+ <LSUB/>
+ <INVOKEVIRTUAL owner="java/lang/StringBuffer" name="append" desc="(J)Ljava/lang/StringBuffer;"/>
+
+ <LDC desc="Ljava/lang/String;">
+ <xsl:attribute name="cst">
+ <xsl:value-of select="concat( ' : ', ../../../@name, '.', ../../@name, ../../@desc)"/>
+ </xsl:attribute>
+ </LDC>
+ <INVOKEVIRTUAL owner="java/lang/StringBuffer" name="append" desc="(Ljava/lang/String;)Ljava/lang/StringBuffer;"/>
+ <INVOKEVIRTUAL owner="java/lang/StringBuffer" name="toString" desc="()Ljava/lang/String;"/>
+
+ <INVOKEVIRTUAL desc="(Ljava/lang/String;)V" name="println" owner="java/io/PrintStream"/>
+
+ <xsl:element name="{name()}"/>
+</xsl:template>
+
+
+<!-- copy everything -->
+<xsl:template match="@*|*|text()|processing-instruction()">
+ <xsl:copy><xsl:apply-templates select="@*|*|text()|processing-instruction()"/></xsl:copy>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/asm4/examples/xml/readme.txt b/asm4/examples/xml/readme.txt
new file mode 100644
index 0000000..b3da367
--- /dev/null
+++ b/asm4/examples/xml/readme.txt
@@ -0,0 +1,60 @@
+*******************************************************************************
+* ASM: a very small and fast Java bytecode manipulation framework
+* Copyright (c) 2000-2011 INRIA, France Telecom
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* 3. Neither the name of the copyright holders nor the names of its
+* contributors may be used to endorse or promote products derived from
+* this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************
+
+This directory contains sample XSL transformation templates that
+demonstrate features of org.objectweb.asm.xml package.
+
+
+copy.xsl
+ Copying source document into target without changes.
+
+strip.xsl
+ Strips all attribute values from the target XML.
+ Result document can't be used to generate bytecode.
+
+annotate.xsl
+ Adds comments for labels and variable instructions
+ to the target XML document.
+
+linenumbers.xsl
+ Adds code to dump source line numbers for the executing code to System.err
+
+profile.xsl
+ Adds code to dump execution time for each method to System.err
+
+
+You can use the following command to transform
+
+java -jar asm-xml-<version>.jar <in format> <out format>
+ [-in <input jar>] [-out <output jar>] [-xslt <xslt file>]
+
+ where <in format> and <out format> is one of code, xml or singlexml
+ when -in or -out is omitted sysin and sysout would be used
+
diff --git a/asm4/examples/xml/strip.xsl b/asm4/examples/xml/strip.xsl
new file mode 100644
index 0000000..b181996
--- /dev/null
+++ b/asm4/examples/xml/strip.xsl
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="ASCII"?>
+<!--
+ ASM XML Adapter examples.
+ Copyright (c) 2004-2011, Eugene Kuleshov
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+ Destructive transformation that removes values from all attributes.
+ Result bytecode will be invalid.
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="xml" encoding="ASCII" indent="yes"/>
+
+<!--
+ Class name must not be removed!
+-->
+<xsl:template match="//class/@name">
+ <xsl:attribute name="name"><xsl:value-of select="."/></xsl:attribute>
+</xsl:template>
+
+
+<xsl:template match="@*">
+ <xsl:attribute name="{name()}"/>
+</xsl:template>
+
+
+<!-- copy everything -->
+<xsl:template match="*|text()|processing-instruction()">
+ <xsl:copy><xsl:apply-templates select="@*|*|text()|processing-instruction()"/></xsl:copy>
+</xsl:template>
+
+</xsl:stylesheet>