KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > go > trove > classfile > CodeAssemblerPrinter


1 /* ====================================================================
2  * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group
3  * ====================================================================
4  * The Tea Software License, Version 1.1
5  *
6  * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Walt Disney Internet Group (http://opensource.go.com/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact opensource@dig.com.
31  *
32  * 5. Products derived from this software may not be called "Tea",
33  * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34  * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35  * written permission of the Walt Disney Internet Group.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * For more information about Tea, please see http://opensource.go.com/.
51  */

52
53 package com.go.trove.classfile;
54
55 import java.util.*;
56 import java.io.PrintWriter JavaDoc;
57
58 /******************************************************************************
59  * CodeAssembler implementation that prints out instructions using a Java-like
60  * syntax that matches the methods of CodeAssembler. When used in conjunction
61  * with a {@link CodeDisassembler}, this class makes it easier to understand
62  * how to use a CodeAssembler.
63  *
64  * @author Brian S O'Neill
65  * @version
66  * <!--$$Revision:--> 1 <!-- $-->, <!--$$JustDate:--> 00/11/27 <!-- $-->
67  */

68 public class CodeAssemblerPrinter implements CodeAssembler {
69     private TypeDescriptor[] mParamTypes;
70     private boolean mIsStatic;
71     private PrintWriter JavaDoc mWriter;
72     private String JavaDoc mLinePrefix;
73     private String JavaDoc mLineSuffix;
74
75     private int mLocalCounter;
76     private int mLabelCounter;
77
78     private int mTypeDescriptorCounter;
79     // Maps TypeDescriptor objects to String variable names.
80
private Map mTypeDescriptorNames;
81
82     private int mTypeDescriptorArrayCounter;
83     // Maps TypeDescriptor arrays to String variable names.
84
private Map mTypeDescriptorArrayNames;
85
86     public CodeAssemblerPrinter(TypeDescriptor[] paramTypes, boolean isStatic,
87                               PrintWriter JavaDoc writer)
88     {
89         this(paramTypes, isStatic, writer, null, null);
90     }
91
92     public CodeAssemblerPrinter(TypeDescriptor[] paramTypes, boolean isStatic,
93                                 PrintWriter JavaDoc writer,
94                                 String JavaDoc linePrefix, String JavaDoc lineSuffix)
95     {
96         mParamTypes = paramTypes;
97         mIsStatic = isStatic;
98         mWriter = writer;
99         mLinePrefix = linePrefix;
100         mLineSuffix = lineSuffix;
101         mTypeDescriptorNames = new HashMap();
102         mTypeDescriptorArrayNames = new HashMap();
103     }
104
105     public LocalVariable[] getParameters() {
106         LocalVariable[] vars = new LocalVariable[mParamTypes.length];
107
108         int varNum = (mIsStatic) ? 0 : 1;
109         for (int i = 0; i<mParamTypes.length; i++) {
110             String JavaDoc varName = "var_" + (++mLocalCounter);
111             println("LocalVariable " + varName +
112                     " = getParameters()[" + i + ']');
113             LocalVariable localVar =
114                 new NamedLocal(varName, mParamTypes[i], varNum);
115             varNum += (localVar.isDoubleWord() ? 2 : 1);
116             vars[i] = localVar;
117         }
118         
119         return vars;
120     }
121
122     public LocalVariable createLocalVariable(String JavaDoc name,
123                                              TypeDescriptor type) {
124         String JavaDoc varName = "var_" + (++mLocalCounter);
125         if (name != null) {
126             name = '"' + name + '"';
127         }
128         println("LocalVariable " + varName +
129                 " = createLocalVariable(" + name +
130                 ", " + getTypeDescriptorName(type) + ')');
131         return new NamedLocal(varName, type, -1);
132     }
133
134     public Label createLabel() {
135         String JavaDoc name = "label_" + (++mLabelCounter);
136         println("Label " + name + " = createLabel()");
137         return new NamedLabel(name);
138     }
139
140     public void exceptionHandler(Location startLocation,
141                                  Location endLocation,
142                                  String JavaDoc catchClassName) {
143         println("exceptionHandler(" +
144                 getLabelName(startLocation) + ", " +
145                 getLabelName(endLocation) + ", " +
146                 catchClassName + ')');
147     }
148     
149     public void mapLineNumber(int lineNumber) {
150         println("mapLineNumber(" + lineNumber + ')');
151     }
152
153     public void loadConstant(String JavaDoc value) {
154         if (value == null) {
155             println("loadConstant(null)");
156         }
157         else {
158             println("loadConstant(\"" + escape(value) + "\")");
159         }
160     }
161
162     public void loadConstant(boolean value) {
163         println("loadConstant(" + value + ')');
164     }
165
166     public void loadConstant(int value) {
167         println("loadConstant(" + value + ')');
168     }
169
170     public void loadConstant(long value) {
171         println("loadConstant(" + value + "L)");
172     }
173
174     public void loadConstant(float value) {
175         println("loadConstant(" + value + "f)");
176     }
177
178     public void loadConstant(double value) {
179         println("loadConstant(" + value + "d)");
180     }
181
182     public void loadLocal(LocalVariable local) {
183         println("loadLocal(" + local.getName() + ')');
184     }
185
186     public void loadThis() {
187         println("loadThis()");
188     }
189
190     public void storeLocal(LocalVariable local) {
191         println("storeLocal(" + local.getName() + ')');
192     }
193
194     public void loadFromArray(Class JavaDoc type) {
195         println("loadFromArray(" + generateClassLiteral(type) + ')');
196     }
197
198     public void storeToArray(Class JavaDoc type) {
199         println("storeToArray(" + generateClassLiteral(type) + ')');
200     }
201
202     public void loadField(String JavaDoc fieldName,
203                           TypeDescriptor type) {
204         println("loadField(\"" + fieldName + "\", " +
205                 getTypeDescriptorName(type) + ')');
206     }
207
208     public void loadField(String JavaDoc className,
209                           String JavaDoc fieldName,
210                           TypeDescriptor type) {
211         println("loadField(\"" + className + "\", \"" + fieldName + "\", " +
212                 getTypeDescriptorName(type) + ')');
213     }
214
215     public void loadStaticField(String JavaDoc fieldName,
216                                 TypeDescriptor type) {
217         println("loadStaticField(\"" + fieldName + "\", " +
218                 getTypeDescriptorName(type) + ')');
219     }
220
221     public void loadStaticField(String JavaDoc className,
222                                 String JavaDoc fieldName,
223                                 TypeDescriptor type) {
224         println("loadStaticField(\"" + className + "\", \"" +
225                 fieldName + "\", " +
226                 getTypeDescriptorName(type) + ')');
227     }
228
229     public void storeField(String JavaDoc fieldName,
230                            TypeDescriptor type) {
231         println("storeField(\"" + fieldName + "\", " +
232                 getTypeDescriptorName(type) + ')');
233     }
234
235     public void storeField(String JavaDoc className,
236                            String JavaDoc fieldName,
237                            TypeDescriptor type) {
238         println("storeField(\"" + className + "\", \"" + fieldName + "\", " +
239                 getTypeDescriptorName(type) + ')');
240     }
241
242     public void storeStaticField(String JavaDoc fieldName,
243                                  TypeDescriptor type) {
244         println("storeStaticField(\"" + fieldName + "\", " +
245                 getTypeDescriptorName(type) + ')');
246     }
247
248     public void storeStaticField(String JavaDoc className,
249                                  String JavaDoc fieldName,
250                                  TypeDescriptor type) {
251         println("storeStaticField(\"" + className + "\", \"" +
252                 fieldName + "\", " +
253                 getTypeDescriptorName(type) + ')');
254     }
255
256     public void returnVoid() {
257         println("returnVoid()");
258     }
259
260     public void returnValue(Class JavaDoc type) {
261         println("returnValue(" + generateClassLiteral(type) + ')');
262     }
263
264     public void convert(Class JavaDoc fromType, Class JavaDoc toType) {
265         println("convert(" +
266                 generateClassLiteral(fromType) + ", " +
267                 generateClassLiteral(toType) + ')');
268     }
269
270     public void invokeVirtual(String JavaDoc methodName,
271                               TypeDescriptor ret,
272                               TypeDescriptor[] params) {
273         println("invokeVirtual(\"" + methodName + "\", " +
274                 getTypeDescriptorName(ret) + ", " +
275                 getTypeDescriptorArrayName(params) + ')');
276     }
277
278     public void invokeVirtual(String JavaDoc className,
279                               String JavaDoc methodName,
280                               TypeDescriptor ret,
281                               TypeDescriptor[] params) {
282         println("invokeVirtual(\"" + className + "\", \"" +
283                 methodName + "\", " +
284                 getTypeDescriptorName(ret) + ", " +
285                 getTypeDescriptorArrayName(params) + ')');
286     }
287
288     public void invokeStatic(String JavaDoc methodName,
289                              TypeDescriptor ret,
290                              TypeDescriptor[] params) {
291         println("invokeStatic(\"" + methodName + "\", " +
292                 getTypeDescriptorName(ret) + ", " +
293                 getTypeDescriptorArrayName(params) + ')');
294     }
295
296     public void invokeStatic(String JavaDoc className,
297                              String JavaDoc methodName,
298                              TypeDescriptor ret,
299                              TypeDescriptor[] params) {
300         println("invokeStatic(\"" + className + ", " +
301                 methodName + ", " +
302                 getTypeDescriptorName(ret) + ", " +
303                 getTypeDescriptorArrayName(params) + ')');
304     }
305
306     public void invokeInterface(String JavaDoc className,
307                                 String JavaDoc methodName,
308                                 TypeDescriptor ret,
309                                 TypeDescriptor[] params) {
310         println("invokeInterface(\"" + className + "\", \"" +
311                 methodName + "\", " +
312                 getTypeDescriptorName(ret) + ", " +
313                 getTypeDescriptorArrayName(params) + ')');
314     }
315
316     public void invokePrivate(String JavaDoc methodName,
317                               TypeDescriptor ret,
318                               TypeDescriptor[] params) {
319         println("invokePrivate(\"" + methodName + "\", " +
320                 getTypeDescriptorName(ret) + ", " +
321                 getTypeDescriptorArrayName(params) + ')');
322     }
323
324     public void invokeSuper(String JavaDoc superClassName,
325                             String JavaDoc methodName,
326                             TypeDescriptor ret,
327                             TypeDescriptor[] params) {
328         println("invokeSuper(\"" + superClassName + "\", \"" +
329                 methodName + "\", " +
330                 getTypeDescriptorName(ret) + ", " +
331                 getTypeDescriptorArrayName(params) + ')');
332     }
333
334     public void invokeConstructor(TypeDescriptor[] params) {
335         println("invokeConstructor(" +
336                 getTypeDescriptorArrayName(params) + ')');
337     }
338
339     public void invokeConstructor(String JavaDoc className, TypeDescriptor[] params) {
340         println("invokeConstructor(\"" + className + "\", " +
341                 getTypeDescriptorArrayName(params) + ')');
342     }
343
344     public void invokeSuperConstructor(TypeDescriptor[] params) {
345         println("invokeSuperConstructor(" +
346                 getTypeDescriptorArrayName(params) + ')');
347     }
348
349     public void newObject(TypeDescriptor type) {
350         println("newObject(" + getTypeDescriptorName(type) + ')');
351     }
352
353     public void dup() {
354         println("dup()");
355     }
356
357     public void dupX1() {
358         println("dupX1()");
359     }
360
361     public void dupX2() {
362         println("dupX2()");
363     }
364
365     public void dup2() {
366         println("dup2()");
367     }
368
369     public void dup2X1() {
370         println("dup2X1()");
371     }
372
373     public void dup2X2() {
374         println("dup2X2()");
375     }
376
377     public void pop() {
378         println("pop()");
379     }
380
381     public void pop2() {
382         println("pop2()");
383     }
384
385     public void swap() {
386         println("swap()");
387     }
388
389     public void swap2() {
390         println("swap2()");
391     }
392
393     public void branch(Location location) {
394         println("branch(" + getLabelName(location) + ')');
395     }
396
397     public void ifNullBranch(Location location, boolean choice) {
398         println("ifNullBranch(" +
399                 getLabelName(location) + ", " + choice + ')');
400     }
401
402     public void ifEqualBranch(Location location, boolean choice) {
403         println("ifEqualBranch(" +
404                 getLabelName(location) + ", " + choice + ')');
405     }
406
407     public void ifZeroComparisonBranch(Location location, String JavaDoc choice) {
408         println("ifZeroComparisonBranch(" +
409                 getLabelName(location) + ", \"" + choice + "\")");
410     }
411
412     public void ifComparisonBranch(Location location, String JavaDoc choice) {
413         println("ifComparisonBranch(" +
414                 getLabelName(location) + ", \"" + choice + "\")");
415     }
416
417     public void switchBranch(int[] cases,
418                              Location[] locations, Location defaultLocation) {
419
420         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(cases.length * 15);
421
422         buf.append("switchBranch(");
423
424         buf.append("new int[] {");
425         for (int i=0; i<cases.length; i++) {
426             if (i > 0) {
427                 buf.append(", ");
428             }
429             buf.append(cases[i]);
430         }
431         buf.append("}");
432
433         buf.append(", ");
434
435         buf.append("new Location[] {");
436         for (int i=0; i<locations.length; i++) {
437             if (i > 0) {
438                 buf.append(", ");
439             }
440             buf.append(getLabelName(locations[i]));
441         }
442         buf.append("}");
443
444         buf.append(", ");
445         buf.append(getLabelName(defaultLocation));
446         buf.append(')');
447
448         println(buf.toString());
449     }
450
451     public void jsr(Location location) {
452         println("jsr(" + getLabelName(location) + ')');
453     }
454
455     public void ret(LocalVariable local) {
456         println("ret(" + local.getName() + ')');
457     }
458
459     public void math(byte opcode) {
460         println
461             ("math(Opcode." + Opcode.getMnemonic(opcode).toUpperCase() + ')');
462     }
463
464     public void arrayLength() {
465         println("arrayLength()");
466     }
467
468     public void throwObject() {
469         println("throwObject()");
470     }
471
472     public void checkCast(TypeDescriptor type) {
473         println("checkCast(" + getTypeDescriptorName(type) + ')');
474     }
475
476     public void instanceOf(TypeDescriptor type) {
477         println("instanceOf(" + getTypeDescriptorName(type) + ')');
478     }
479
480     public void integerIncrement(LocalVariable local, int amount) {
481         println("integerIncrement(" + local.getName() + ", " + amount + ')');
482     }
483
484     public void monitorEnter() {
485         println("monitorEnter()");
486     }
487
488     public void monitorExit() {
489         println("monitorExit()");
490     }
491
492     public void nop() {
493         println("nop()");
494     }
495
496     public void breakpoint() {
497         println("breakpoint()");
498     }
499
500     private void println(String JavaDoc str) {
501         if (mLinePrefix != null) {
502             mWriter.print(mLinePrefix);
503         }
504         if (mLineSuffix == null) {
505             mWriter.println(str);
506         }
507         else {
508             mWriter.print(str);
509             mWriter.println(mLineSuffix);
510         }
511     }
512
513     private String JavaDoc generateClassLiteral(Class JavaDoc type) {
514         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
515
516         int dim = 0;
517         while (type.isArray()) {
518             dim++;
519             type = type.getComponentType();
520         }
521         
522         if (!type.isPrimitive()) {
523             buf.append(type.getName());
524         }
525         else {
526             if (type == int.class) {
527                 buf.append("int");
528             }
529             else if (type == char.class) {
530                 buf.append("char");
531             }
532             else if (type == boolean.class) {
533                 buf.append("boolean");
534             }
535             else if (type == double.class) {
536                 buf.append("double");
537             }
538             else if (type == float.class) {
539                 buf.append("float");
540             }
541             else if (type == long.class) {
542                 buf.append("long");
543             }
544             else if (type == byte.class) {
545                 buf.append("byte");
546             }
547             else if (type == short.class) {
548                 buf.append("short");
549             }
550             else {
551                 buf.append("void");
552             }
553         }
554         
555         while (dim-- > 0) {
556             buf.append('[');
557             buf.append(']');
558         }
559
560         buf.append(".class");
561
562         return buf.toString();
563     }
564
565     private String JavaDoc getLabelName(Location location) {
566         if (location instanceof NamedLabel) {
567             return ((NamedLabel)location).mName;
568         }
569         else {
570             return ((NamedLabel)createLabel()).mName;
571         }
572     }
573
574     private String JavaDoc getTypeDescriptorName(TypeDescriptor type) {
575         if (type == null) {
576             return "null";
577         }
578
579         String JavaDoc name = (String JavaDoc)mTypeDescriptorNames.get(type);
580
581         if (name == null) {
582             name = "type_" + (++mTypeDescriptorCounter);
583             mTypeDescriptorNames.put(type, name);
584
585             StringBuffer JavaDoc buf = new StringBuffer JavaDoc("TypeDescriptor ");
586             buf.append(name);
587             buf.append(" = new TypeDescriptor(");
588
589             TypeDescriptor componentType = type.getComponentType();
590             if (componentType != null) {
591                 buf.append(getTypeDescriptorName(componentType));
592                 buf.append(", ");
593                 buf.append(type.getSpecifiedDimensions());
594             }
595             else {
596                 Class JavaDoc clazz = type.getClassArg();
597                 if (clazz != null) {
598                     buf.append(generateClassLiteral(clazz));
599                 }
600                 else {
601                     buf.append('"');
602                     buf.append(type.getClassName());
603                     buf.append('"');
604                 }
605             }
606
607             buf.append(')');
608
609             println(buf.toString());
610         }
611
612         return name;
613     }
614
615     private String JavaDoc getTypeDescriptorArrayName(TypeDescriptor[] types) {
616         if (types == null) {
617             return "null";
618         }
619
620         Object JavaDoc key = Arrays.asList(types);
621         String JavaDoc name = (String JavaDoc)mTypeDescriptorArrayNames.get(key);
622
623         if (name == null) {
624             name = "params_" + (++mTypeDescriptorArrayCounter);
625             mTypeDescriptorArrayNames.put(key, name);
626
627             StringBuffer JavaDoc buf = new StringBuffer JavaDoc("TypeDescriptor[] ");
628             buf.append(name);
629             buf.append(" = new TypeDescriptor[] {");
630
631             for (int i=0; i<types.length; i++) {
632                 if (i > 0) {
633                     buf.append(", ");
634                 }
635                 buf.append(getTypeDescriptorName(types[i]));
636             }
637
638             buf.append('}');
639
640             println(buf.toString());
641         }
642
643         return name;
644     }
645
646     private String JavaDoc escape(String JavaDoc value) {
647         int length = value.length();
648         int i = 0;
649         for (; i < length; i++) {
650             char c = value.charAt(i);
651             if (c < 32 || c > 126 || c == '"' || c == '\\') {
652                 break;
653             }
654         }
655
656         if (i >= length) {
657             return value;
658         }
659
660         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(length + 16);
661         for (i=0; i<length; i++) {
662             char c = value.charAt(i);
663             if (c >= 32 && c <= 126 && c != '"' && c != '\\') {
664                 buf.append(c);
665                 continue;
666             }
667
668             switch (c) {
669             case '\0':
670                 buf.append("\\0");
671                 break;
672             case '"':
673                 buf.append("\\\"");
674                 break;
675             case '\\':
676                 buf.append("\\\\");
677                 break;
678             case '\b':
679                 buf.append("\\b");
680                 break;
681             case '\f':
682                 buf.append("\\f");
683                 break;
684             case '\n':
685                 buf.append("\\n");
686                 break;
687             case '\r':
688                 buf.append("\\r");
689                 break;
690             case '\t':
691                 buf.append("\\t");
692                 break;
693             default:
694                 String JavaDoc u = Integer.toHexString(c).toLowerCase();
695                 buf.append("\\u");
696                 for (int len = u.length(); len < 4; len++) {
697                     buf.append('0');
698                 }
699                 buf.append(u);
700                 break;
701             }
702         }
703
704         return buf.toString();
705     }
706
707     private class NamedLocal implements LocalVariable {
708         private String JavaDoc mName;
709         private TypeDescriptor mType;
710         private boolean mIsDoubleWord;
711         private int mNumber;
712
713         public NamedLocal(String JavaDoc name, TypeDescriptor type, int number) {
714             mName = name;
715             mType = type;
716             Class JavaDoc clazz = type.getClassArg();
717             mIsDoubleWord = clazz == long.class || clazz == double.class;
718             mNumber = number;
719         }
720
721         public String JavaDoc getName() {
722             return mName;
723         }
724         
725         public void setName(String JavaDoc name) {
726             println(mName + ".setName(" + name + ')');
727         }
728         
729         public TypeDescriptor getType() {
730             return mType;
731         }
732         
733         public boolean isDoubleWord() {
734             return mIsDoubleWord;
735         }
736         
737         public int getNumber() {
738             return mNumber;
739         }
740         
741         public Location getStartLocation() {
742             return null;
743         }
744         
745         public Location getEndLocation() {
746             return null;
747         }
748
749         public SortedSet getLocationRangeSet() {
750             return null;
751         }
752     }
753
754     private class NamedLabel implements Label {
755         public final String JavaDoc mName;
756
757         public NamedLabel(String JavaDoc name) {
758             mName = name;
759         }
760
761         public Label setLocation() {
762             println(mName + ".setLocation()");
763             return this;
764         }
765         
766         public int getLocation() {
767             return -1;
768         }
769
770         public int compareTo(Object JavaDoc obj) {
771             return 0;
772         }
773     }
774 }
775
Popular Tags