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    }