/* * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered * by the modified BSD License. You should have received a copy of the * modified BSD license with this compiler. * * Copyright (c) 2005-2008, Torbjorn Ekman * All rights reserved. */ aspect BytecodeDescriptor { class FieldDescriptor { private BytecodeParser p; String typeDescriptor; public FieldDescriptor(BytecodeParser parser, String name) { p = parser; int descriptor_index = p.u2(); typeDescriptor = ((CONSTANT_Utf8_Info) p.constantPool[descriptor_index]).string(); if(BytecodeParser.VERBOSE) p.println(" Field: " + name + ", " + typeDescriptor); } public Access type() { return new TypeDescriptor(p, typeDescriptor).type(); } public boolean isBoolean() { return new TypeDescriptor(p, typeDescriptor).isBoolean(); } } class FieldInfo { private BytecodeParser p; String name; int flags; private FieldDescriptor fieldDescriptor; private Attributes attributes; public FieldInfo(BytecodeParser parser) { p = parser; flags = p.u2(); if(BytecodeParser.VERBOSE) p.print("Flags: " + flags); int name_index = p.u2(); name = ((CONSTANT_Utf8_Info) p.constantPool[name_index]).string(); fieldDescriptor = new FieldDescriptor(p, name); attributes = new Attributes(p); } public BodyDecl bodyDecl() { FieldDeclaration f = new FieldDeclaration( BytecodeParser.modifiers(flags), fieldDescriptor.type(), name, new Opt() ); if(attributes.constantValue() != null) if(fieldDescriptor.isBoolean()) { f.setInit(attributes.constantValue().exprAsBoolean()); } else { f.setInit(attributes.constantValue().expr()); } return f; } public boolean isSynthetic() { return attributes.isSynthetic(); } } class MethodDescriptor { private BytecodeParser p; private String parameterDescriptors; private String typeDescriptor; public MethodDescriptor(BytecodeParser parser, String name) { p = parser; int descriptor_index = p.u2(); String descriptor = ((CONSTANT_Utf8_Info) p.constantPool[descriptor_index]).string(); if(BytecodeParser.VERBOSE) p.println(" Method: " + name + ", " + descriptor); //String[] strings = descriptor.substring(1).split("\\)"); //parameterDescriptors = strings[0]; //typeDescriptor = strings[1]; int pos = descriptor.indexOf(')'); parameterDescriptors = descriptor.substring(1, pos); typeDescriptor = descriptor.substring(pos+1, descriptor.length()); } public List parameterList() { TypeDescriptor d = new TypeDescriptor(p, parameterDescriptors); return d.parameterList(); } public List parameterListSkipFirst() { TypeDescriptor d = new TypeDescriptor(p, parameterDescriptors); return d.parameterListSkipFirst(); } public Access type() { TypeDescriptor d = new TypeDescriptor(p, typeDescriptor); return d.type(); } } class MethodInfo { private BytecodeParser p; String name; int flags; private MethodDescriptor methodDescriptor; private Attributes attributes; public MethodInfo(BytecodeParser parser) { p = parser; flags = p.u2(); if(BytecodeParser.VERBOSE) p.print(" Flags: " + Integer.toBinaryString(flags)); int name_index = p.u2(); CONSTANT_Info info = p.constantPool[name_index]; if(info == null || !(info instanceof CONSTANT_Utf8_Info)) { System.err.println("Expected CONSTANT_Utf8_Info but found: " + info.getClass().getName()); //if(info instanceof CONSTANT_Class_Info) { // System.err.println(" found CONSTANT_Class_Info: " + ((CONSTANT_Class_Info)info).name()); // name = ((CONSTANT_Class_Info)info).name(); //} } name = ((CONSTANT_Utf8_Info)info).string(); methodDescriptor = new MethodDescriptor(p, name); attributes = new Attributes(p); } public BodyDecl bodyDecl() { if(isConstructor()) { return new ConstructorDecl( BytecodeParser.modifiers(flags), name, methodDescriptor.parameterList(), attributes.exceptionList(), new Opt(), new Block() ); } else { return new MethodDecl( BytecodeParser.modifiers(flags), methodDescriptor.type(), name, methodDescriptor.parameterList(), attributes.exceptionList(), new Opt(new Block()) ); } } private boolean isConstructor() { return name.equals(""); } public boolean isSynthetic() { return attributes.isSynthetic() || (flags & 0x1000) != 0; } }class TypeDescriptor { private BytecodeParser p; private String descriptor; public TypeDescriptor(BytecodeParser parser, String descriptor) { p = parser; this.descriptor = descriptor; } public boolean isBoolean() { return descriptor.charAt(0) == 'Z'; } public Access type() { return type(descriptor); } public Access type(String s) { char c = s.charAt(0); switch (c) { case 'B': return new PrimitiveTypeAccess("byte"); case 'C': return new PrimitiveTypeAccess("char"); case 'D': return new PrimitiveTypeAccess("double"); case 'F': return new PrimitiveTypeAccess("float"); case 'I': return new PrimitiveTypeAccess("int"); case 'J': return new PrimitiveTypeAccess("long"); case 'S': return new PrimitiveTypeAccess("short"); case 'Z': return new PrimitiveTypeAccess("boolean"); case 'L': return this.p.fromClassName(s.substring(1, s.length() - 1)); case '[': return new ArrayTypeAccess(type(s.substring(1))); case 'V': return new PrimitiveTypeAccess("void"); default: this.p.println("Error: unknown type in TypeDescriptor"); throw new Error("Error: unknown Type in TypeDescriptor: " + s); } //return null; } public List parameterList() { List list = new List(); String s = descriptor; while(!s.equals("")) { s = typeList(s, list); } return list; } public List parameterListSkipFirst() { List list = new List(); String s = descriptor; if(!s.equals("")) s = typeList(s, new List()); // skip first while(!s.equals("")) { s = typeList(s, list); } return list; } public String typeList(String s, List l) { char c = s.charAt(0); switch (c) { case 'B': l.add(new ParameterDeclaration(new Modifiers(), new PrimitiveTypeAccess("byte"), "p" + l.getNumChild())); return s.substring(1); case 'C': l.add(new ParameterDeclaration(new Modifiers(), new PrimitiveTypeAccess("char"), "p" + l.getNumChild())); return s.substring(1); case 'D': l.add(new ParameterDeclaration(new Modifiers(), new PrimitiveTypeAccess("double"), "p" + l.getNumChild())); return s.substring(1); case 'F': l.add(new ParameterDeclaration(new Modifiers(), new PrimitiveTypeAccess("float"), "p" + l.getNumChild())); return s.substring(1); case 'I': l.add(new ParameterDeclaration(new Modifiers(), new PrimitiveTypeAccess("int"), "p" + l.getNumChild())); return s.substring(1); case 'J': l.add(new ParameterDeclaration(new Modifiers(), new PrimitiveTypeAccess("long"), "p" + l.getNumChild())); return s.substring(1); case 'S': l.add(new ParameterDeclaration(new Modifiers(), new PrimitiveTypeAccess("short"), "p" + l.getNumChild())); return s.substring(1); case 'Z': l.add(new ParameterDeclaration(new Modifiers(), new PrimitiveTypeAccess("boolean"), "p" + l.getNumChild())); return s.substring(1); case 'L': int pos = s.indexOf(';'); String s1 = s.substring(1, pos); String s2 = s.substring(pos+1, s.length()); l.add(new ParameterDeclaration(new Modifiers(), this.p.fromClassName(s1), "p" + l.getNumChild())); return s2; case '[': int i = 1; while(s.charAt(i) == '[') i++; ArrayTypeAccess bottom = new ArrayTypeAccess(new ParseName("")); // dummy child will be replaced ArrayTypeAccess top = bottom; for(int j = 0; j < i - 1; j++) top = new ArrayTypeAccess(top); l.add(new ParameterDeclaration(new Modifiers(), top, "p" + l.getNumChild())); return arrayTypeList(s.substring(i), bottom); default: this.p.println("Error: unknown Type \"" + c + "\" in TypeDescriptor"); throw new Error("Error: unknown Type in TypeDescriptor: " + s); } //return ""; } public String arrayTypeList(String s, ArrayTypeAccess typeAccess) { char c = s.charAt(0); switch (c) { case 'B': typeAccess.setAccess(new PrimitiveTypeAccess("byte")); return s.substring(1); case 'C': typeAccess.setAccess(new PrimitiveTypeAccess("char")); return s.substring(1); case 'D': typeAccess.setAccess(new PrimitiveTypeAccess("double")); return s.substring(1); case 'F': typeAccess.setAccess(new PrimitiveTypeAccess("float")); return s.substring(1); case 'I': typeAccess.setAccess(new PrimitiveTypeAccess("int")); return s.substring(1); case 'J': typeAccess.setAccess(new PrimitiveTypeAccess("long")); return s.substring(1); case 'S': typeAccess.setAccess(new PrimitiveTypeAccess("short")); return s.substring(1); case 'Z': typeAccess.setAccess(new PrimitiveTypeAccess("boolean")); return s.substring(1); case 'L': //String[] strings = s.substring(1).split("\\;", 2); //typeAccess.setAccess(this.p.fromClassName(strings[0])); //return strings[1]; int pos = s.indexOf(';'); String s1 = s.substring(1, pos); String s2 = s.substring(pos+1, s.length()); typeAccess.setAccess(this.p.fromClassName(s1)); return s2; default: this.p.println("Error: unknown Type in TypeDescriptor"); throw new Error("Error: unknown Type in TypeDescriptor: " + s); } //return null; } } }