001    /* Copyright (c) 2005-2008, Torbjorn Ekman
002     *                    2013, Jesper Öqvist <jesper.oqvist@cs.lth.se>
003     * All rights reserved.
004     *
005     * Redistribution and use in source and binary forms, with or without
006     * modification, are permitted provided that the following conditions are met:
007     *
008     * 1. Redistributions of source code must retain the above copyright notice,
009     * this list of conditions and the following disclaimer.
010     *
011     * 2. Redistributions in binary form must reproduce the above copyright notice,
012     * this list of conditions and the following disclaimer in the documentation
013     * and/or other materials provided with the distribution.
014     *
015     * 3. Neither the name of the copyright holder nor the names of its
016     * contributors may be used to endorse or promote products derived from this
017     * software without specific prior written permission.
018     *
019     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
023     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
024     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
025     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
026     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
027     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
029     * POSSIBILITY OF SUCH DAMAGE.
030     */
031    
032    import java.util.*;
033    import java.io.*;
034    
035    aspect ConstantPool {
036      syn lazy ConstantPool TypeDecl.constantPool() = new ConstantPool(this);
037    
038      public class ConstantPool {
039        public TypeDecl typeDecl;
040        public ConstantPool(TypeDecl typeDecl) {
041          this.typeDecl = typeDecl;
042        }
043    
044        public static final byte CONSTANT_Class              = 7;
045        public static final byte CONSTANT_Fieldref           = 9;
046        public static final byte CONSTANT_Methodref          = 10;
047        public static final byte CONSTANT_InterfaceMethodref = 11;
048        public static final byte CONSTANT_String             = 8;
049        public static final byte CONSTANT_Integer            = 3;
050        public static final byte CONSTANT_Float              = 4;
051        public static final byte CONSTANT_Long               = 5;
052        public static final byte CONSTANT_Double             = 6;
053        public static final byte CONSTANT_NameAndType        = 12;
054        public static final byte CONSTANT_Utf8               = 1;
055    
056        private int posCounter = 1;
057    
058        private ArrayList list = new ArrayList();
059    
060        private void addCPInfo(CPInfo info) {
061          info.pos = posCounter;
062          posCounter += info.size();
063          if (posCounter > 0xFFFF) {
064            throw new Error("Too many constants in class!");
065          }
066          list.add(info);
067        }
068    
069        // for debugging purposes
070        public int numElements() {
071          return list.size();
072        }
073        public String toString() {
074          StringBuffer s = new StringBuffer();
075          for(Iterator iter = list.iterator(); iter.hasNext(); ) {
076            s.append(iter.next().toString());
077            s.append("\n");
078          }
079          return s.toString();
080        }
081    
082        public void emit(DataOutputStream out) throws IOException {
083          out.writeChar(posCounter);
084          for(Iterator iter = list.iterator(); iter.hasNext(); ) {
085            CPInfo info = (CPInfo)iter.next();
086            info.emit(out);
087          }
088        }
089    
090        private int labelCounter = 1;
091        public int newLabel() {
092          return labelCounter++;
093        }
094    
095        private HashMap classConstants = new HashMap();
096        public int addClass(String name) {
097          Map map = classConstants;
098          Object key = name;
099          if(!map.containsKey(key)) {
100            CPInfo info = new ConstantClass(addUtf8(name.replace('.', '/')));
101            addCPInfo(info);
102            map.put(key, info);
103            String s = info.toString();
104            return info.pos;
105          }
106          CPInfo info = (CPInfo)map.get(key);
107          return info.pos;
108        }
109    
110        private HashMap fieldrefConstants = new HashMap();
111        public int addFieldref(String classname, String name, String type) {
112          Map map = fieldrefConstants;
113          Object key = classname + name + type;
114          if(!map.containsKey(key)) {
115            CPInfo info = new ConstantFieldref(addClass(classname), addNameAndType(name, type));
116            addCPInfo(info);
117            map.put(key, info);
118            String s = info.toString();
119            return info.pos;
120          }
121          CPInfo info = (CPInfo)map.get(key);
122          return info.pos;
123        }
124    
125        private HashMap methodrefConstants = new HashMap();
126        public int addMethodref(String classname, String name, String desc) {
127          Map map = methodrefConstants;
128          Object key = classname + name + desc;
129          if(!map.containsKey(key)) {
130            CPInfo info = new ConstantMethodref(addClass(classname), addNameAndType(name, desc));
131            addCPInfo(info);
132            map.put(key, info);
133            String s = info.toString();
134            return info.pos;
135          }
136          CPInfo info = (CPInfo)map.get(key);
137          return info.pos;
138        }
139    
140        private HashMap interfaceMethodrefConstants = new HashMap();
141        public int addInterfaceMethodref(String classname, String name, String desc) {
142          Map map = interfaceMethodrefConstants;
143          Object key = classname + name + desc;
144          if(!map.containsKey(key)) {
145            CPInfo info = new ConstantInterfaceMethodref(addClass(classname), addNameAndType(name, desc));
146            addCPInfo(info);
147            map.put(key, info);
148            String s = info.toString();
149            return info.pos;
150          }
151          CPInfo info = (CPInfo)map.get(key);
152          return info.pos;
153        }
154    
155        private HashMap nameAndTypeConstants = new HashMap();
156        public int addNameAndType(String name, String type) {
157          Map map = nameAndTypeConstants;
158          Object key = name + type;
159          if(!map.containsKey(key)) {
160            CPInfo info = new ConstantNameAndType(addUtf8(name), addUtf8(type));
161            addCPInfo(info);
162            map.put(key, info);
163            String s = info.toString();
164            return info.pos;
165          }
166          CPInfo info = (CPInfo)map.get(key);
167          return info.pos;
168        }
169    
170        private HashMap utf8Constants = new HashMap();
171        public int addUtf8(String name) {
172          Map map = utf8Constants;
173          Object key = name;
174          if(!map.containsKey(key)) {
175            CPInfo info = new ConstantUtf8(name);
176            addCPInfo(info);
177            map.put(key, info);
178            String s = info.toString();
179            return info.pos;
180          }
181          CPInfo info = (CPInfo)map.get(key);
182          return info.pos;
183        }
184    
185        private HashMap stringConstants = new HashMap();
186    
187        /**
188         * Add value to constant pool.
189         * @return index of value in constant pool
190         */
191        public int addConstant(String val) {
192          Map map = stringConstants;
193          Object key = val;
194          if(!map.containsKey(key)) {
195            CPInfo info = new ConstantString(addUtf8(val));
196            addCPInfo(info);
197            map.put(key, info);
198            String s = info.toString();
199            return info.pos;
200          }
201          CPInfo info = (CPInfo)map.get(key);
202          return info.pos;
203        }
204    
205        private HashMap intConstants = new HashMap();
206    
207        /**
208         * Add value to constant pool.
209         * @return index of value in constant pool
210         */
211        public int addConstant(int val) {
212          Map map = intConstants;
213          Object key = new Integer(val);
214          if(!map.containsKey(key)) {
215            CPInfo info = new ConstantInteger(val);
216            addCPInfo(info);
217            map.put(key, info);
218            return info.pos;
219          }
220          CPInfo info = (CPInfo)map.get(key);
221          return info.pos;
222        }
223    
224        private HashMap floatConstants = new HashMap();
225    
226        /**
227         * Add value to constant pool.
228         * @return index of value in constant pool
229         */
230        public int addConstant(float val) {
231          Map map = floatConstants;
232          Object key = new Float(val);
233          if(!map.containsKey(key)) {
234            CPInfo info = new ConstantFloat(val);
235            addCPInfo(info);
236            map.put(key, info);
237            return info.pos;
238          }
239          CPInfo info = (CPInfo)map.get(key);
240          return info.pos;
241        }
242    
243        private HashMap longConstants = new HashMap();
244    
245        /**
246         * Add value to constant pool.
247         * @return index of value in constant pool
248         */
249        public int addConstant(long val) {
250          Map map = longConstants;
251          Object key = new Long(val);
252          if(!map.containsKey(key)) {
253            CPInfo info = new ConstantLong(val);
254            addCPInfo(info);
255            map.put(key, info);
256            return info.pos;
257          }
258          CPInfo info = (CPInfo)map.get(key);
259          return info.pos;
260        }
261    
262        private HashMap doubleConstants = new HashMap();
263    
264        /**
265         * Add value to constant pool.
266         * @return index of value in constant pool
267         */
268        public int addConstant(double val) {
269          Map map = doubleConstants;
270          Object key = new Double(val);
271          if(!map.containsKey(key)) {
272            CPInfo info = new ConstantDouble(val);
273            addCPInfo(info);
274            map.put(key, info);
275            return info.pos;
276          }
277          CPInfo info = (CPInfo)map.get(key);
278          return info.pos;
279        }
280      }
281    
282      public class CPInfo {
283        public void emit(DataOutputStream out) throws IOException {
284        }
285        public int size() {
286          return  1;
287        }
288        public int pos;
289      }
290    
291      public class ConstantClass extends CPInfo {
292        private int name;
293        public ConstantClass(int name) {
294          this.name = name;
295        }
296        public void emit(DataOutputStream out) throws IOException {
297          out.writeByte(ConstantPool.CONSTANT_Class);
298          out.writeChar(name);
299        }
300        public String toString() {
301          return pos + " ConstantClass: tag " + ConstantPool.CONSTANT_Class + ", name_index: " + name;
302        }
303      }
304    
305      public class ConstantFieldref extends CPInfo {
306        private int classname;
307        private int nameandtype;
308        public ConstantFieldref(int classname, int nameandtype) {
309          this.classname = classname;
310          this.nameandtype = nameandtype;
311        }
312        public void emit(DataOutputStream out) throws IOException {
313          out.writeByte(ConstantPool.CONSTANT_Fieldref);
314          out.writeChar(classname);
315          out.writeChar(nameandtype);
316        }
317        public String toString() {
318          return pos + " ConstantFieldref: tag " + ConstantPool.CONSTANT_Fieldref + ", class_index: " + classname + ", name_and_type_index: " + nameandtype;
319        }
320      }
321    
322      public class ConstantMethodref extends CPInfo {
323        private int classname;
324        private int nameandtype;
325        public ConstantMethodref(int classname, int nameandtype) {
326          this.classname = classname;
327          this.nameandtype = nameandtype;
328        }
329    
330        public void emit(DataOutputStream out) throws IOException {
331          out.writeByte(ConstantPool.CONSTANT_Methodref);
332          out.writeChar(classname);
333          out.writeChar(nameandtype);
334        }
335        public String toString() {
336          return pos + " ConstantMethodref: tag " + ConstantPool.CONSTANT_Methodref + ", class_index: " + classname + ", name_and_type_index: " + nameandtype;
337        }
338      }
339    
340      public class ConstantInterfaceMethodref extends CPInfo {
341        private int classname;
342        private int nameandtype;
343        public ConstantInterfaceMethodref(int classname, int nameandtype) {
344          this.classname = classname;
345          this.nameandtype = nameandtype;
346        }
347        public void emit(DataOutputStream out) throws IOException {
348          out.writeByte(ConstantPool.CONSTANT_InterfaceMethodref);
349          out.writeChar(classname);
350          out.writeChar(nameandtype);
351        }
352        public String toString() {
353          return pos + " ConstantInterfaceMethodref: tag " + ConstantPool.CONSTANT_InterfaceMethodref + ", class_index: " + classname + ", name_and_type_index: " + nameandtype;
354        }
355      }
356    
357      public class ConstantNameAndType extends CPInfo {
358        private int name;
359        private int type;
360        public ConstantNameAndType(int name, int type) {
361          this.name = name;
362          this.type = type;
363        }
364        public void emit(DataOutputStream out) throws IOException {
365          out.writeByte(ConstantPool.CONSTANT_NameAndType);
366          out.writeChar(name);
367          out.writeChar(type);
368        }
369        public String toString() {
370          return pos + " NameAndType: tag " + ConstantPool.CONSTANT_NameAndType + ", name_index: " + name + ", descriptor_index: " + type;
371        }
372      }
373    
374      public class ConstantUtf8 extends CPInfo {
375        private String name;
376        public ConstantUtf8(String name) {
377          this.name = name;
378        }
379        public void emit(DataOutputStream out) throws IOException {
380          out.writeByte(ConstantPool.CONSTANT_Utf8);
381          out.writeUTF(name);
382        }
383        public String toString() {
384          return pos + " ConstantUtf8: tag " + ConstantPool.CONSTANT_Utf8 + ", length: " + name.length() + ", bytes: " + name;
385        }
386      }
387    
388      public class ConstantString extends CPInfo {
389        private int name;
390        public ConstantString(int name) {
391          this.name = name;
392        }
393        public void emit(DataOutputStream out) throws IOException {
394          out.writeByte(ConstantPool.CONSTANT_String);
395          out.writeChar(name);
396        }
397        public String toString() {
398          return pos + " ConstantString: tag " + ConstantPool.CONSTANT_String + ", string_index: " + name;
399        }
400      }
401    
402      public class ConstantInteger extends CPInfo {
403        private int val;
404        public ConstantInteger(int val) {
405          this.val = val;
406        }
407        public void emit(DataOutputStream out) throws IOException {
408          out.writeByte(ConstantPool.CONSTANT_Integer);
409          out.writeInt(val);
410        }
411        public String toString() {
412          return pos + " ConstantInteger: tag " + ConstantPool.CONSTANT_Integer + ", bytes: " + val;
413        }
414      }
415    
416      public class ConstantFloat extends CPInfo {
417        private float val;
418        public ConstantFloat(float val) {
419          this.val = val;
420        }
421        public void emit(DataOutputStream out) throws IOException {
422          out.writeByte(ConstantPool.CONSTANT_Float);
423          out.writeFloat(val);
424        }
425        public String toString() {
426          return pos + " ConstantFloat: tag " + ConstantPool.CONSTANT_Float + ", bytes: " + val;
427        }
428      }
429    
430      public class ConstantLong extends CPInfo {
431        private long val;
432        public ConstantLong(long val) {
433          this.val = val;
434        }
435        public void emit(DataOutputStream out) throws IOException {
436          out.writeByte(ConstantPool.CONSTANT_Long);
437          out.writeLong(val);
438        }
439        public int size() {
440          return 2;
441        }
442        public String toString() {
443          return pos + " ConstantLong: tag " + ConstantPool.CONSTANT_Long + ", bytes: " + val;
444        }
445      }
446    
447      public class ConstantDouble extends CPInfo {
448        private double val;
449        public ConstantDouble(double val) {
450          this.val = val;
451        }
452        public void emit(DataOutputStream out) throws IOException {
453          out.writeByte(ConstantPool.CONSTANT_Double);
454          out.writeDouble(val);
455        }
456        public int size() {
457          return 2;
458        }
459        public String toString() {
460          return pos + " ConstantDouble: tag " + ConstantPool.CONSTANT_Double + ", bytes: " + val;
461        }
462      }
463    
464    }