001 /* 002 * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered 003 * by the modified BSD License. You should have received a copy of the 004 * modified BSD license with this compiler. 005 * 006 * Copyright (c) 2005-2008, Torbjorn Ekman 007 * All rights reserved. 008 */ 009 010 import java.io.*; 011 aspect Attributes { 012 013 class Attribute { 014 int attribute_name_index; 015 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 016 DataOutputStream output = new DataOutputStream(buf); 017 018 public Attribute(ConstantPool cp, String name) { 019 attribute_name_index = cp.addUtf8(name); 020 } 021 022 public void emit(DataOutputStream out) throws IOException { 023 out.writeChar(attribute_name_index); 024 out.writeInt(buf.size()); 025 buf.writeTo(out); 026 output.close(); 027 buf.close(); 028 } 029 public int size() { return buf.size(); } 030 public void u1(int v) { try { output.writeByte(v); } catch(IOException e) {} } 031 public void u2(int v) { try { output.writeChar(v); } catch(IOException e) {} } 032 public void u4(int v) { try { output.writeInt(v); } catch(IOException e) {} } 033 public void append(byte[] data) { try { output.write(data, 0, data.length); } catch(IOException e) {} } 034 public void append(Attribute attribute) { try { attribute.emit(output); } catch(IOException e) {} } 035 } 036 037 class SourceFileAttribute extends Attribute { 038 public SourceFileAttribute(ConstantPool p, String sourcefile) { 039 super(p, "SourceFile"); 040 u2(p.addUtf8(sourcefile)); 041 } 042 } 043 044 class SyntheticAttribute extends Attribute { 045 public SyntheticAttribute(ConstantPool p) { 046 super(p, "Synthetic"); 047 } 048 } 049 050 class ConstantValueAttribute extends Attribute { 051 public ConstantValueAttribute(ConstantPool p, FieldDeclaration f) { 052 super(p, "ConstantValue"); 053 int constantvalue_index = f.type().addConstant(p, f.getInit().constant()); 054 u2(constantvalue_index); 055 } 056 } 057 058 public int TypeDecl.addConstant(ConstantPool p, Constant c) { 059 if(isString()) return p.addConstant(c.stringValue()); 060 throw new Error("Not supported"); 061 } 062 public int BooleanType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.booleanValue() ? 1 : 0); } 063 public int IntegralType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.intValue()); } 064 public int LongType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.longValue()); } 065 public int FloatType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.floatValue()); } 066 public int DoubleType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.doubleValue()); } 067 068 class InnerClassesAttribute extends Attribute { 069 public InnerClassesAttribute(TypeDecl typeDecl) { 070 super(typeDecl.constantPool(), "InnerClasses"); 071 ConstantPool c = typeDecl.constantPool(); 072 Collection list = typeDecl.innerClassesAttributeEntries(); 073 u2(list.size()); 074 for(Iterator iter = list.iterator(); iter.hasNext(); ) { 075 TypeDecl type = (TypeDecl)iter.next(); 076 u2(c.addClass(type.constantPoolName())); // inner_class_info_index 077 u2(type.isMemberType() ? c.addClass(type.enclosingType().constantPoolName()) : 0); // outer_class_info_index 078 u2(type.isAnonymous() ? 0 : c.addUtf8(type.name())); // inner_name_index 079 u2(type.isInterfaceDecl() ? (type.flags() | Modifiers.ACC_INTERFACE) : type.flags()); // inner_class_access_flags 080 } 081 } 082 } 083 syn lazy Collection TypeDecl.innerClassesAttributeEntries() { 084 HashSet list = new HashSet(); 085 if(isNestedType()) 086 list.add(this); 087 for(Iterator iter = nestedTypes().iterator(); iter.hasNext(); ) 088 list.add(iter.next()); 089 for(Iterator iter = usedNestedTypes().iterator(); iter.hasNext(); ) 090 list.add(iter.next()); 091 return list; 092 } 093 094 class LocalVariableTableAttribute extends Attribute { 095 public LocalVariableTableAttribute(CodeGeneration gen) { 096 super(gen.constantPool(), "LocalVariableTable"); 097 u2(gen.localVariableTable.size()); 098 for(Iterator iter = gen.localVariableTable.iterator(); iter.hasNext(); ) { 099 CodeGeneration.LocalVariableEntry e = (CodeGeneration.LocalVariableEntry)iter.next(); 100 u2(e.start_pc); 101 u2(e.length); 102 u2(e.name_index); 103 u2(e.descriptor_index); 104 u2(e.index); 105 } 106 } 107 } 108 109 class LineNumberTableAttribute extends Attribute { 110 public LineNumberTableAttribute(CodeGeneration gen) { 111 super(gen.constantPool(), "LineNumberTable"); 112 u2(gen.lineNumberTable.size()); 113 for(Iterator iter = gen.lineNumberTable.iterator(); iter.hasNext(); ) { 114 CodeGeneration.LineNumberEntry e = (CodeGeneration.LineNumberEntry)iter.next(); 115 u2(e.start_pc); 116 u2(e.line_number); 117 } 118 } 119 } 120 121 class CodeAttribute extends Attribute { 122 public CodeAttribute(CodeGeneration codeGen, MethodDecl m) { 123 super(codeGen.constantPool(), "Code"); 124 u2(codeGen.maxStackDepth()); 125 u2(codeGen.maxLocals()); 126 u4(codeGen.pos()); // code_length 127 append(codeGen.toArray()); 128 u2(codeGen.exceptions.size()); 129 for(Iterator iter = codeGen.exceptions.iterator(); iter.hasNext(); ) { 130 CodeGeneration.ExceptionEntry e = (CodeGeneration.ExceptionEntry)iter.next(); 131 u2(e.start_pc); 132 u2(e.end_pc); 133 u2(e.handler_pc); 134 u2(e.catch_type); 135 } 136 137 if(m == null || !m.getModifiers().isSynthetic()) { 138 u2(2); // Attribute count 139 append(new LineNumberTableAttribute(codeGen)); 140 append(new LocalVariableTableAttribute(codeGen)); 141 } 142 else { 143 u2(0); // Attribute count 144 } 145 } 146 } 147 148 interface ExceptionHolder { 149 public int getNumException(); 150 public Access getException(int i); 151 } 152 MethodDecl implements ExceptionHolder; 153 ConstructorDecl implements ExceptionHolder; 154 155 class ExceptionsAttribute extends Attribute { 156 public ExceptionsAttribute(CodeGeneration gen, ExceptionHolder m) { 157 super(gen.constantPool(), "Exceptions"); 158 u2(m.getNumException()); 159 for(int i = 0; i < m.getNumException(); i++) 160 u2(gen.constantPool().addClass(m.getException(i).type().constantPoolName())); 161 } 162 } 163 164 syn lazy Collection TypeDecl.attributes() { 165 Collection c = new ArrayList(); 166 if(!innerClassesAttributeEntries().isEmpty()) 167 c.add(new InnerClassesAttribute(this)); 168 if(isSynthetic()) 169 c.add(new SyntheticAttribute(constantPool())); 170 if(compilationUnit().fromSource()) { 171 String relativeName = compilationUnit().relativeName(); 172 if(relativeName != null) { 173 String splitToken = java.io.File.separator; 174 if(splitToken.equals("\\")) 175 splitToken = "\\\\"; 176 String[] strings = relativeName.split(splitToken); 177 c.add(new SourceFileAttribute(constantPool(), strings[strings.length-1])); 178 } 179 } 180 return c; 181 } 182 syn lazy Collection BodyDecl.attributes() = new ArrayList(); 183 eq FieldDeclaration.attributes() { 184 ArrayList l = new ArrayList(); 185 if(isFinal() && isConstant() && (type().isPrimitive() || type().isString())) 186 l.add(new ConstantValueAttribute(hostType().constantPool(), this)); 187 return l; 188 } 189 eq MethodDecl.attributes() { 190 ArrayList l = new ArrayList(); 191 l.add(new ExceptionsAttribute(bytecodes(hostType().constantPool()), this)); 192 if(isAbstract() || isNative()) return l; 193 l.add(new CodeAttribute(bytecodes(hostType().constantPool()), this)); 194 if(getModifiers().isSynthetic()) 195 l.add(new SyntheticAttribute(hostType().constantPool())); 196 return l; 197 } 198 eq ConstructorDecl.attributes() { 199 ArrayList l = new ArrayList(); 200 l.add(new CodeAttribute(bytecodes(hostType().constantPool()), null)); 201 l.add(new ExceptionsAttribute(bytecodes(hostType().constantPool()), this)); 202 if(getModifiers().isSynthetic()) 203 l.add(new SyntheticAttribute(hostType().constantPool())); 204 return l; 205 } 206 syn lazy Collection TypeDecl.clinit_attributes() { 207 ArrayList l = new ArrayList(); 208 l.add(new CodeAttribute(bytecodes(constantPool()), null)); 209 return l; 210 } 211 }