$(JAVAC) -d build $(sources)
test: $(classes)
- java -cp build org.ibex.classgen.ClassGen
+ java -cp build org.ibex.classgen.ClassFile
clean:
rm -rf build/*
void dump(DataOutput o) throws IOException { o.writeByte(tag); }
String debugToString() { return toString(); } // so we can remove this method when not debugging
- abstract Object key() throws ClassGen.ClassReadExn; // be careful using this, it drags in a bunch of code
+ abstract Object key() throws ClassFile.ClassReadExn; // be careful using this, it drags in a bunch of code
}
class IntEnt extends Ent {
}
private String fixme() { throw new Error("fixme"); }
- Object key() throws ClassGen.ClassReadExn {
+ Object key() throws ClassFile.ClassReadExn {
switch(tag) {
case 7: return Type.instance(((Utf8Ent)e1).s);
case 8: return (((Utf8Ent)e1).s);
case 9: {
NameAndTypeKey nt = (NameAndTypeKey) e2.key();
Type t = Type.instance(nt.type);
- if(t == null) throw new ClassGen.ClassReadExn("invalid type descriptor");
+ if(t == null) throw new ClassFile.ClassReadExn("invalid type descriptor");
return new FieldRef((Type.Class)e1.key(), nt.name, t);
}
case 10: case 11: {
return ent.n;
}
- public final Type getType(int index) throws ClassGen.ClassReadExn {
+ public final Type getType(int index) throws ClassFile.ClassReadExn {
Ent e = getByIndex(index);
if (e instanceof Utf8Ent) return Type.instance(((Utf8Ent)e).s);
else return (Type)e.key();
ce.e1 = addUtf8(key.name);
ce.e2 = addUtf8(key.type);
ent = ce;
- } else if(o instanceof ClassGen.FieldOrMethodRef) {
- ClassGen.FieldOrMethodRef key = (ClassGen.FieldOrMethodRef) o;
+ } else if(o instanceof MemberRef) {
+ MemberRef key = (MemberRef) o;
int tag = o instanceof FieldRef ? 9 : o instanceof MethodRef ? 10 : o instanceof MethodRef.I ? 11 : 0;
if(tag == 0) throw new Error("should never happen");
CPRefEnt ce = new CPRefEnt(tag);
}
int spaces = ent instanceof LongEnt ? 2 : 1;
- if(usedSlots + spaces > 65536) throw new ClassGen.Exn("constant pool full");
+ if(usedSlots + spaces > 65536) throw new ClassFile.Exn("constant pool full");
ent.n = state == OPEN ? 1 : usedSlots; // refcount or index
}
}
- CPGen(DataInput in) throws ClassGen.ClassReadExn, IOException {
+ CPGen(DataInput in) throws ClassFile.ClassReadExn, IOException {
usedSlots = in.readUnsignedShort();
- if(usedSlots==0) throw new ClassGen.ClassReadExn("invalid used slots");
+ if(usedSlots==0) throw new ClassFile.ClassReadExn("invalid used slots");
// these are to remember the CPRefEnt e1 and e2s we have to fix up
int[] e1s = new int[usedSlots];
break;
}
default:
- throw new ClassGen.ClassReadExn("invalid cp ent tag");
+ throw new ClassFile.ClassReadExn("invalid cp ent tag");
}
entriesByIndex[index] = e;
if (e instanceof LongEnt) index++;
}
if (!(e instanceof CPRefEnt)) continue;
CPRefEnt ce = (CPRefEnt) e;
- if(e1s[i] == 0 || e1s[i] >= usedSlots) throw new ClassGen.ClassReadExn("invalid cp index");
+ if(e1s[i] == 0 || e1s[i] >= usedSlots) throw new ClassFile.ClassReadExn("invalid cp index");
ce.e1 = entriesByIndex[e1s[i]];
- if(ce.e1 == null) throw new ClassGen.ClassReadExn("invalid cp index");
+ if(ce.e1 == null) throw new ClassFile.ClassReadExn("invalid cp index");
if(ce.tag != 7 && ce.tag != 8) {
- if(e2s[i] == 0 || e2s[i] >= usedSlots) throw new ClassGen.ClassReadExn("invalid cp index");
+ if(e2s[i] == 0 || e2s[i] >= usedSlots) throw new ClassFile.ClassReadExn("invalid cp index");
ce.e2 = entriesByIndex[e2s[i]];
- if(ce.e2 == null) throw new ClassGen.ClassReadExn("invalid cp index");
+ if(ce.e2 == null) throw new ClassFile.ClassReadExn("invalid cp index");
}
switch(ce.tag) {
case 7:
case 8:
- if(!(ce.e1 instanceof Utf8Ent)) throw new ClassGen.ClassReadExn("expected a utf8 ent");
+ if(!(ce.e1 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent");
break;
case 9:
case 10:
case 11:
if(!(ce.e1 instanceof CPRefEnt) || ((CPRefEnt)ce.e1).tag != 7)
- throw new ClassGen.ClassReadExn("expected a type ent");
+ throw new ClassFile.ClassReadExn("expected a type ent");
if(!(ce.e2 instanceof CPRefEnt) || ((CPRefEnt)ce.e2).tag != 12)
- throw new ClassGen.ClassReadExn("expected a name and type ent");
+ throw new ClassFile.ClassReadExn("expected a name and type ent");
break;
case 12:
- if(!(ce.e1 instanceof Utf8Ent)) throw new ClassGen.ClassReadExn("expected a utf8 ent");
- if(!(ce.e2 instanceof Utf8Ent)) throw new ClassGen.ClassReadExn("expected a utf8 ent");
+ if(!(ce.e1 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent");
+ if(!(ce.e2 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent");
break;
}
}
import java.io.*;
/** Class generation object representing the whole classfile */
-public class ClassGen implements CGConst {
+public class ClassFile implements CGConst {
private final Type.Class thisType;
private final Type.Class superType;
private final Type.Class[] interfaces;
sb.append("}");
}
- /** @see #ClassGen(Type.Class, Type.Class, int) */
- public ClassGen(String name, String superName, int flags) {
+ /** @see #ClassFile(Type.Class, Type.Class, int) */
+ public ClassFile(String name, String superName, int flags) {
this(Type.instance(name).asClass(), Type.instance(superName).asClass(), flags);
}
- /** @see #ClassGen(Type.Class, Type.Class, int, Type.Class[]) */
- public ClassGen(Type.Class thisType, Type.Class superType, int flags) {
+ /** @see #ClassFile(Type.Class, Type.Class, int, Type.Class[]) */
+ public ClassFile(Type.Class thisType, Type.Class superType, int flags) {
this(thisType, superType, flags, null);
}
- /** Creates a new ClassGen object
+ /** Creates a new ClassFile object
@param thisType The type of the class to generate
@param superType The superclass of the generated class (commonly Type.OBJECT)
@param flags The access flags for this class (ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, and ACC_ABSTRACT)
*/
- public ClassGen(Type.Class thisType, Type.Class superType, int flags, Type.Class[] interfaces) {
+ public ClassFile(Type.Class thisType, Type.Class superType, int flags, Type.Class[] interfaces) {
if((flags & ~(ACC_PUBLIC|ACC_FINAL|ACC_SUPER|ACC_INTERFACE|ACC_ABSTRACT)) != 0)
throw new IllegalArgumentException("invalid flags");
this.thisType = thisType;
public void setSourceFile(String sourceFile) { this.sourceFile = sourceFile; }
/** Writes the classfile data to the file specifed
- @see ClassGen#dump(OutputStream)
+ @see ClassFile#dump(OutputStream)
*/
public void dump(String file) throws IOException { dump(new File(file)); }
/** Writes the classfile data to the file specified
If <i>f</i> is a directory directory components under it are created for the package the class is in (like javac's -d option)
- @see ClassGen#dump(OutputStream)
+ @see ClassFile#dump(OutputStream)
*/
public void dump(File f) throws IOException {
if(f.isDirectory()) {
attributes.dump(o); // attributes
}
- public ClassGen read(File f) throws ClassReadExn, IOException {
+ public ClassFile read(File f) throws ClassReadExn, IOException {
InputStream is = new FileInputStream(f);
- ClassGen ret = read(is);
+ ClassFile ret = read(is);
is.close();
return ret;
}
- public ClassGen read(InputStream is) throws ClassReadExn, IOException {
- return new ClassGen(new DataInputStream(new BufferedInputStream(is)));
+ public ClassFile read(InputStream is) throws ClassReadExn, IOException {
+ return new ClassFile(new DataInputStream(new BufferedInputStream(is)));
}
- ClassGen(DataInput i) throws ClassReadExn, IOException {
+ ClassFile(DataInput i) throws ClassReadExn, IOException {
int magic = i.readInt();
if (magic != 0xcafebabe) throw new ClassReadExn("invalid magic: " + Long.toString(0xffffffffL & magic, 16));
minor = i.readShort();
public ClassReadExn(String s) { super(s); }
}
- /** A class representing a field or method reference. This is used as an argument to the INVOKE*, GET*, and PUT* bytecodes
- @see MethodRef
- @see FieldRef
- @see MethodRef.I
- @see FieldRef
- */
- public static abstract class FieldOrMethodRef {
- Type.Class klass;
- String name;
- String descriptor;
-
- FieldOrMethodRef(Type.Class klass, String name, String descriptor) { this.klass = klass; this.name = name; this.descriptor = descriptor; }
- FieldOrMethodRef(FieldOrMethodRef o) { this.klass = o.klass; this.name = o.name; this.descriptor = o.descriptor; }
- public boolean equals(Object o_) {
- if(!(o_ instanceof FieldOrMethodRef)) return false;
- FieldOrMethodRef o = (FieldOrMethodRef) o_;
- return o.klass.equals(klass) && o.name.equals(name) && o.descriptor.equals(descriptor);
- }
- public int hashCode() { return klass.hashCode() ^ name.hashCode() ^ descriptor.hashCode(); }
- }
-
static class AttrGen {
private final CPGen cp;
private final Hashtable ht = new Hashtable();
public static void main(String[] args) throws Exception {
if (args.length==1) {
if (args[0].endsWith(".class")) {
- System.out.println(new ClassGen(new DataInputStream(new FileInputStream(args[0]))));
+ System.out.println(new ClassFile(new DataInputStream(new FileInputStream(args[0]))));
} else {
InputStream is = Class.forName(args[0]).getClassLoader().getResourceAsStream(args[0].replace('.', '/')+".class");
- System.out.println(new ClassGen(new DataInputStream(is)));
+ System.out.println(new ClassFile(new DataInputStream(is)));
}
} else {
/*
Type.Class me = new Type.Class("Test");
- ClassGen cg = new ClassGen("Test", "java.lang.Object", ACC_PUBLIC|ACC_SUPER|ACC_FINAL);
+ ClassFile cg = new ClassFile("Test", "java.lang.Object", ACC_PUBLIC|ACC_SUPER|ACC_FINAL);
FieldGen fg = cg.addField("foo", Type.INT, ACC_PUBLIC|ACC_STATIC);
MethodGen mg = cg.addMethod("main", Type.VOID, new Type[]{Type.arrayType(Type.STRING)}, ACC_STATIC|ACC_PUBLIC);
import java.io.*;
/** Class representing a field in a generated classfile
- @see ClassGen#addField */
+ @see ClassFile#addField */
public class FieldGen implements CGConst {
private final CPGen cp;
private final String name;
private final Type type;
private final int flags;
- private final ClassGen.AttrGen attrs;
+ private final ClassFile.AttrGen attrs;
private Object constantValue;
public String toString() { StringBuffer sb = new StringBuffer(); toString(sb); return sb.toString(); }
public void toString(StringBuffer sb) {
- sb.append(ClassGen.flagsToString(flags));
+ sb.append(ClassFile.flagsToString(flags));
sb.append(type);
sb.append(" ");
sb.append(name);
flags = in.readShort();
name = cp.getUtf8ByIndex(in.readShort());
type = cp.getType(in.readShort());
- attrs = new ClassGen.AttrGen(cp, in);
+ attrs = new ClassFile.AttrGen(cp, in);
}
- FieldGen(ClassGen owner, String name, Type type, int flags) {
+ FieldGen(ClassFile owner, String name, Type type, int flags) {
if((flags & ~(ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED|ACC_VOLATILE|ACC_TRANSIENT|ACC_STATIC|ACC_FINAL)) != 0)
throw new IllegalArgumentException("invalid flags");
this.cp = owner.cp;
this.name = name;
this.type = type;
this.flags = flags;
- this.attrs = new ClassGen.AttrGen(cp);
+ this.attrs = new ClassFile.AttrGen(cp);
cp.addUtf8(name);
cp.addUtf8(type.getDescriptor());
@see CGConst#GETSTATIC
@see CGConst#PUTSTATIC
*/
-public class FieldRef extends ClassGen.FieldOrMethodRef {
+public class FieldRef extends MemberRef {
/** Create a reference to field <i>name</i> of class <i>c</i> with the type <i>t</i> */
public FieldRef(Type.Class c, String name, Type t) { super(c, name, t.getDescriptor()); }
/** Equivalent to FieldRef(new Type.Class(s), ...)
--- /dev/null
+package org.ibex.classgen;
+
+import java.util.*;
+import java.io.*;
+
+/** A class representing a field or method reference. This is used as an argument to the INVOKE*, GET*, and PUT* bytecodes
+ @see MethodRef
+ @see FieldRef
+ @see MethodRef.I
+ @see FieldRef
+*/
+public abstract class MemberRef {
+ Type.Class klass;
+ String name;
+ String descriptor;
+
+ MemberRef(Type.Class klass, String name, String descriptor) { this.klass = klass; this.name = name; this.descriptor = descriptor; }
+ MemberRef(MemberRef o) { this.klass = o.klass; this.name = o.name; this.descriptor = o.descriptor; }
+ public boolean equals(Object o_) {
+ if(!(o_ instanceof MemberRef)) return false;
+ MemberRef o = (MemberRef) o_;
+ return o.klass.equals(klass) && o.name.equals(name) && o.descriptor.equals(descriptor);
+ }
+ public int hashCode() { return klass.hashCode() ^ name.hashCode() ^ descriptor.hashCode(); }
+}
+
import java.util.*;
/** A class representing a method in a generated classfile
- @see ClassGen#addMethod */
+ @see ClassFile#addMethod */
public class MethodGen implements CGConst {
private final static boolean EMIT_NOPS = false;
private final Type ret;
private final Type[] args;
private final int flags;
- private final ClassGen.AttrGen attrs;
- private final ClassGen.AttrGen codeAttrs;
+ private final ClassFile.AttrGen attrs;
+ private final ClassFile.AttrGen codeAttrs;
private final Hashtable exnTable = new Hashtable();
private final Hashtable thrownExceptions = new Hashtable();
public String toString() { StringBuffer sb = new StringBuffer(); toString(sb, "<init>"); return sb.toString(); }
public void toString(StringBuffer sb, String constructorName) {
- sb.append(ClassGen.flagsToString(flags));
+ sb.append(ClassFile.flagsToString(flags));
sb.append(ret);
sb.append(" ");
//String args = descriptor.substring(1, descriptor.indexOf(')'));
args = new Type[0]; // FIXME
codeAttrs = null;
- attrs = new ClassGen.AttrGen(cp, in);
+ attrs = new ClassFile.AttrGen(cp, in);
}
- MethodGen(ClassGen owner, String name, Type ret, Type[] args, int flags) {
+ MethodGen(ClassFile owner, String name, Type ret, Type[] args, int flags) {
if((flags & ~(ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE|ACC_ABSTRACT|ACC_STRICT)) != 0)
throw new IllegalArgumentException("invalid flags");
this.cp = owner.cp;
this.args = args;
this.flags = flags;
- attrs = new ClassGen.AttrGen(cp);
- codeAttrs = new ClassGen.AttrGen(cp);
+ attrs = new ClassFile.AttrGen(cp);
+ codeAttrs = new ClassFile.AttrGen(cp);
cp.addUtf8(name);
cp.addUtf8(getDescriptor());
}
int codeSize = p;
- if(codeSize >= 65536) throw new ClassGen.Exn("method too large in size");
+ if(codeSize >= 65536) throw new ClassFile.Exn("method too large in size");
o.writeShort(maxStack);
o.writeShort(maxLocals);
switch(op) {
case IINC: {
Pair pair = (Pair) arg;
- if(pair.i1 > 255 || pair.i2 < -128 || pair.i2 > 127) throw new ClassGen.Exn("overflow of iinc arg");
+ if(pair.i1 > 255 || pair.i2 < -128 || pair.i2 > 127) throw new ClassFile.Exn("overflow of iinc arg");
o.writeByte(pair.i1);
o.writeByte(pair.i2);
break;
if((opdata & OP_BRANCH_FLAG) != 0) {
int v = pc[((Integer)arg).intValue()] - pc[i];
if(argLength == 2) {
- if(v < -32768 || v > 32767) throw new ClassGen.Exn("overflow of s2 offset");
+ if(v < -32768 || v > 32767) throw new ClassFile.Exn("overflow of s2 offset");
o.writeShort(v);
} else if(argLength == 4) {
o.writeInt(v);
} else {
int iarg = ((Integer)arg).intValue();
if(argLength == 1) {
- if(iarg < -128 || iarg >= 256) throw new ClassGen.Exn("overflow of s/u1 option");
+ if(iarg < -128 || iarg >= 256) throw new ClassFile.Exn("overflow of s/u1 option");
o.writeByte(iarg);
} else if(argLength == 2) {
- if(iarg < -32768 || iarg >= 65536) throw new ClassGen.Exn("overflow of s/u2 option");
+ if(iarg < -32768 || iarg >= 65536) throw new ClassFile.Exn("overflow of s/u2 option");
o.writeShort(iarg);
} else {
throw new Error("should never happen");
@see CGConst#INVOKESPECIAL
@see CGConst#INVOKEINTERFACE
*/
-public class MethodRef extends ClassGen.FieldOrMethodRef {
+public class MethodRef extends MemberRef {
/** Create a reference to method <i>name</i> of class <i>c</i> with the return type <i>ret</i> and the
arguments <i>args</i> */
public MethodRef(Type.Class c, String name, Type ret, Type[] args) {