001 /* Copyright (c) 2005-2008, Torbjorn Ekman 002 * All rights reserved. 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * 1. Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 010 * 2. Redistributions in binary form must reproduce the above copyright notice, 011 * this list of conditions and the following disclaimer in the documentation 012 * and/or other materials provided with the distribution. 013 * 014 * 3. Neither the name of the copyright holder nor the names of its 015 * contributors may be used to endorse or promote products derived from this 016 * software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 028 * POSSIBILITY OF SUCH DAMAGE. 029 */ 030 031 import java.io.*; 032 033 aspect Attributes { 034 035 class Attribute { 036 int attribute_name_index; 037 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 038 DataOutputStream output = new DataOutputStream(buf); 039 040 public Attribute(ConstantPool cp, String name) { 041 attribute_name_index = cp.addUtf8(name); 042 } 043 044 public void emit(DataOutputStream out) throws IOException { 045 out.writeChar(attribute_name_index); 046 out.writeInt(buf.size()); 047 buf.writeTo(out); 048 output.close(); 049 buf.close(); 050 } 051 public int size() { return buf.size(); } 052 public void u1(int v) { try { output.writeByte(v); } catch(IOException e) {} } 053 public void u2(int v) { try { output.writeChar(v); } catch(IOException e) {} } 054 public void u4(int v) { try { output.writeInt(v); } catch(IOException e) {} } 055 public void append(byte[] data) { try { output.write(data, 0, data.length); } catch(IOException e) {} } 056 public void append(Attribute attribute) { try { attribute.emit(output); } catch(IOException e) {} } 057 } 058 059 class SourceFileAttribute extends Attribute { 060 public SourceFileAttribute(ConstantPool p, String sourcefile) { 061 super(p, "SourceFile"); 062 u2(p.addUtf8(sourcefile)); 063 } 064 } 065 066 class SyntheticAttribute extends Attribute { 067 public SyntheticAttribute(ConstantPool p) { 068 super(p, "Synthetic"); 069 } 070 } 071 072 class ConstantValueAttribute extends Attribute { 073 public ConstantValueAttribute(ConstantPool p, FieldDeclaration f) { 074 super(p, "ConstantValue"); 075 int constantvalue_index = f.type().addConstant(p, f.getInit().constant()); 076 u2(constantvalue_index); 077 } 078 } 079 080 public int TypeDecl.addConstant(ConstantPool p, Constant c) { 081 if (isString()) { 082 return p.addConstant(c.stringValue()); 083 } 084 throw new Error("Not supported"); 085 } 086 public int BooleanType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.booleanValue() ? 1 : 0); } 087 public int IntegralType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.intValue()); } 088 public int LongType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.longValue()); } 089 public int FloatType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.floatValue()); } 090 public int DoubleType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.doubleValue()); } 091 092 class InnerClassesAttribute extends Attribute { 093 public InnerClassesAttribute(TypeDecl typeDecl) { 094 super(typeDecl.constantPool(), "InnerClasses"); 095 ConstantPool c = typeDecl.constantPool(); 096 Collection list = typeDecl.innerClassesAttributeEntries(); 097 u2(list.size()); 098 for (Iterator iter = list.iterator(); iter.hasNext(); ) { 099 TypeDecl type = (TypeDecl) iter.next(); 100 u2(c.addClass(type.constantPoolName())); // inner_class_info_index 101 u2(type.isMemberType() ? c.addClass(type.enclosingType().constantPoolName()) : 0); // outer_class_info_index 102 u2(type.isAnonymous() ? 0 : c.addUtf8(type.name())); // inner_name_index 103 u2(type.isInterfaceDecl() ? (type.flags() | Modifiers.ACC_INTERFACE) : type.flags()); // inner_class_access_flags 104 } 105 } 106 } 107 syn lazy Collection TypeDecl.innerClassesAttributeEntries() { 108 HashSet list = new HashSet(); 109 if (isNestedType()) { 110 list.add(this); 111 } 112 for (Iterator iter = nestedTypes.iterator(); iter.hasNext(); ) { 113 list.add(iter.next()); 114 } 115 for (Iterator iter = usedNestedTypes.iterator(); iter.hasNext(); ) { 116 list.add(iter.next()); 117 } 118 return list; 119 } 120 121 class LocalVariableTableAttribute extends Attribute { 122 public LocalVariableTableAttribute(CodeGeneration gen) { 123 super(gen.constantPool(), "LocalVariableTable"); 124 u2(gen.localVariableTable.size()); 125 for (Iterator iter = gen.localVariableTable.iterator(); iter.hasNext(); ) { 126 CodeGeneration.LocalVariableEntry e = (CodeGeneration.LocalVariableEntry)iter.next(); 127 u2(e.start_pc); 128 u2(e.length); 129 u2(e.name_index); 130 u2(e.descriptor_index); 131 u2(e.index); 132 } 133 } 134 } 135 136 class LineNumberTableAttribute extends Attribute { 137 public LineNumberTableAttribute(CodeGeneration gen) { 138 super(gen.constantPool(), "LineNumberTable"); 139 u2(gen.lineNumberTable.size()); 140 for (Iterator iter = gen.lineNumberTable.iterator(); iter.hasNext(); ) { 141 CodeGeneration.LineNumberEntry e = (CodeGeneration.LineNumberEntry)iter.next(); 142 u2(e.start_pc); 143 u2(e.line_number); 144 } 145 } 146 } 147 148 class CodeAttribute extends Attribute { 149 public CodeAttribute(CodeGeneration codeGen, MethodDecl m) { 150 super(codeGen.constantPool(), "Code"); 151 u2(codeGen.maxStackDepth()); 152 u2(codeGen.maxLocals()); 153 u4(codeGen.pos()); // code_length 154 append(codeGen.toArray()); 155 u2(codeGen.exceptions.size()); 156 for (Iterator iter = codeGen.exceptions.iterator(); iter.hasNext(); ) { 157 CodeGeneration.ExceptionEntry e = (CodeGeneration.ExceptionEntry)iter.next(); 158 u2(e.start_pc); 159 u2(e.end_pc); 160 u2(e.handlerPC()); 161 u2(e.catch_type); 162 } 163 164 if (m == null || !m.getModifiers().isSynthetic()) { 165 u2(2); // Attribute count 166 append(new LineNumberTableAttribute(codeGen)); 167 append(new LocalVariableTableAttribute(codeGen)); 168 } else { 169 u2(0); // Attribute count 170 } 171 } 172 } 173 174 interface ExceptionHolder { 175 public int getNumException(); 176 public Access getException(int i); 177 } 178 MethodDecl implements ExceptionHolder; 179 ConstructorDecl implements ExceptionHolder; 180 181 class ExceptionsAttribute extends Attribute { 182 public ExceptionsAttribute(CodeGeneration gen, ExceptionHolder m) { 183 super(gen.constantPool(), "Exceptions"); 184 u2(m.getNumException()); 185 for (int i = 0; i < m.getNumException(); i++) { 186 u2(gen.constantPool().addClass(m.getException(i).type().constantPoolName())); 187 } 188 } 189 } 190 191 syn lazy Collection TypeDecl.attributes() { 192 Collection c = new ArrayList(); 193 if (!innerClassesAttributeEntries().isEmpty()) { 194 c.add(new InnerClassesAttribute(this)); 195 } 196 if (isSynthetic()) { 197 c.add(new SyntheticAttribute(constantPool())); 198 } 199 if (compilationUnit().fromSource()) { 200 String relativeName = compilationUnit().relativeName(); 201 if (relativeName != null) { 202 String splitToken = java.io.File.separator; 203 if (splitToken.equals("\\")) { 204 splitToken = "\\\\"; 205 } 206 String[] strings = relativeName.split(splitToken); 207 c.add(new SourceFileAttribute(constantPool(), strings[strings.length-1])); 208 } 209 } 210 return c; 211 } 212 syn lazy Collection BodyDecl.attributes() = new ArrayList(); 213 eq FieldDeclaration.attributes() { 214 ArrayList l = new ArrayList(); 215 if (isFinal() && isConstant() && (type().isPrimitive() || type().isString())) { 216 l.add(new ConstantValueAttribute(hostType().constantPool(), this)); 217 } 218 return l; 219 } 220 221 eq MethodDecl.attributes() { 222 ArrayList l = new ArrayList(); 223 CodeGeneration bytecodes = bytecodes(hostType().constantPool()); 224 l.add(new ExceptionsAttribute(bytecodes, this)); 225 if (isAbstract() || isNative()) { 226 return l; 227 } else { 228 l.add(new CodeAttribute(bytecodes, this)); 229 if (getModifiers().isSynthetic()) { 230 l.add(new SyntheticAttribute(hostType().constantPool())); 231 } 232 return l; 233 } 234 } 235 236 eq ConstructorDecl.attributes() { 237 ArrayList l = new ArrayList(); 238 CodeGeneration bytecodes = bytecodes(hostType().constantPool()); 239 l.add(new CodeAttribute(bytecodes, null)); 240 l.add(new ExceptionsAttribute(bytecodes, this)); 241 if (getModifiers().isSynthetic()) { 242 l.add(new SyntheticAttribute(hostType().constantPool())); 243 } 244 return l; 245 } 246 247 syn lazy Collection TypeDecl.clinit_attributes() { 248 ArrayList l = new ArrayList(); 249 l.add(new CodeAttribute(bytecodes(constantPool()), null)); 250 return l; 251 } 252 }