KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jasmin > ClassFile


1 /* --- Copyright Jonathan Meyer 1997. All rights reserved. -----------------
2  > File: jasmin/src/jasmin/ClassFile.java
3  > Purpose: Uses a parser and the JAS package to create Java class files
4  > Author: Jonathan Meyer, 10 July 1996
5  */

6
7 package jasmin;
8
9
10 /*
11  * This class is a bit monolithic, and should probably be converted into
12  * several smaller classes. However, for this specific application,
13  * its acceptable.
14  *
15  */

16
17
18
19 import jas.*;
20 import java.io.InputStream JavaDoc;
21 import java.io.OutputStream JavaDoc;
22 import java.io.DataOutputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.util.*;
25
26 /**
27  * A ClassFile object is used to represent the binary data that makes up a
28  * Java class file - it also serves as the public
29  * API to the Jasmin assembler, though users should beware: the API
30  * is likely to change in future versions (though its such a small API
31  * at the moment that changes are likely to have only a small impact).<p>
32  *
33  * To assemble a file, you first construct a jasmin.ClassFile object, then
34  * call readJasmin() to read in the contents of a Jasmin assembly file, then
35  * call write() to write out the binary representation of the class file.<p>
36  *
37  * There are a few other utility methods as well. See Main.java for an example
38  * which uses all of the public methods provided in ClassFile.
39  *
40  * @author Jonathan Meyer
41  * @version 1.05, 8 Feb 1997
42  */

43 public class ClassFile {
44
45     // state info for the class being built
46
String JavaDoc filename;
47     ClassEnv class_env;
48     String JavaDoc class_name;
49     String JavaDoc source_name;
50     Scanner scanner;
51
52     // state info for the current method being defined
53
String JavaDoc method_name;
54     String JavaDoc method_signature;
55     short method_access;
56     ExceptAttr except_attr;
57     Catchtable catch_table;
58     LocalVarTableAttr var_table;
59     LineTableAttr line_table;
60     CodeAttr code;
61     InnerClassAttr inner_class_attr;
62     Hashtable labels;
63     boolean methSynth;
64     boolean methDepr;
65     String JavaDoc methSigAttr;
66     VisibilityAnnotationAttr methAnnotAttr;
67     ParameterVisibilityAnnotationAttr methParamAnnotAttr;
68     ElemValPair methAnnotDef;
69     
70     int line_label_count, line_num;
71     boolean auto_number;
72
73     // state info for lookupswitch and tableswitch instructions
74
Vector switch_vec;
75     int low_value;
76     int high_value;
77
78     int lastInstSize;
79     Method currentMethod;
80     Var currentField;
81
82     VisibilityAnnotationAttr vis_annot_attr;
83     
84     public void addSootCodeAttr(String JavaDoc name, String JavaDoc value)
85     {
86     class_env.addCPItem(new AsciiCP(name));
87     code.addSootCodeAttr(name, value);
88     }
89     
90     public void addGenericAttrToMethod(String JavaDoc name, byte[] value)
91     {
92     if(currentMethod == null)
93         System.err.println("Error: no field in scope to add attribute onto.");
94     else {
95         class_env.addCPItem(new AsciiCP(name));
96         currentMethod.addGenericAttr(new GenericAttr(name, value));
97     }
98     }
99
100     public void addGenericAttrToField(String JavaDoc name, byte[] value)
101     {
102     if(currentField == null)
103         System.err.println("Error: no field in scope to add attribute onto.");
104     else {
105         class_env.addCPItem(new AsciiCP(name));
106         currentField.addGenericAttr(new GenericAttr(name, value));
107     }
108     }
109
110     public void addDeprecatedToField(){
111         if (currentField == null){
112             System.err.println("Error: no field in scope to add deprecated attribute onto");
113         }
114         else {
115             //System.out.println("adding deprec to field" );
116
currentField.addDeprecatedAttr(new DeprecatedAttr());
117         }
118     }
119
120     public void addGenericAttrToClass(GenericAttr g)
121     {
122     class_env.addGenericAttr(g);
123     }
124
125     static final String JavaDoc BGN_METHOD = "bgnmethod:";
126     static final String JavaDoc END_METHOD = "endmethod:";
127
128     // number of errors reported in a file.
129
int errors;
130
131     //
132
// Error reporting method
133
//
134
void report_error(String JavaDoc msg) {
135         // Print out filename/linenumber/message
136
System.err.print(filename + ":");
137         System.err.print(scanner.line_num);
138         System.err.println(": " + msg + ".");
139         if (scanner.char_num >= 0) {
140             System.err.println(scanner.line.toString());
141
142             // Print out where on the line the scanner got to
143
int i;
144             for (i = 0; i < scanner.char_num; i++) {
145                 if (scanner.line.charAt(i) == '\t') {
146                     System.err.print("\t");
147                 } else {
148                     System.err.print(" ");
149                 }
150             }
151             System.err.println("^");
152         }
153         errors++;
154     }
155
156     //
157
// called by the .source directive
158
//
159
void setSource(String JavaDoc name) {
160         source_name = name;
161     }
162
163     //
164
// called by the .class directive
165
//
166
void setClass(String JavaDoc name, short acc) {
167         class_name = name;
168         class_env.setClass(new ClassCP(name));
169         class_env.setClassAccess(acc);
170     }
171
172     //
173
// called by the .super directive
174
//
175
void setSuperClass(String JavaDoc name) {
176         class_env.setSuperClass(new ClassCP(name));
177     }
178
179     //
180
// called by the .no_super directive
181
// (for java.lang.Object only)
182
void setNoSuperClass() {
183         class_env.setNoSuperClass();
184     }
185
186     //
187
// called by the .implements directive
188
//
189
void addInterface(String JavaDoc name) {
190         class_env.addInterface(new ClassCP(name));
191     }
192
193     void addClassDeprAttr(Object JavaDoc res){
194         if (res != null){
195             class_env.setClassDepr(new DeprecatedAttr());
196         }
197     }
198     
199     void addClassSigAttr(Object JavaDoc res){
200         if (res != null){
201             class_env.setClassSigAttr(new SignatureAttr((String JavaDoc)res));
202         }
203     }
204     
205     void addClassAnnotAttr(Object JavaDoc res){
206         if (res != null){
207             class_env.setClassAnnotAttr((VisibilityAnnotationAttr)res);
208         }
209     }
210     
211     void addField(short access, String JavaDoc name, String JavaDoc sig, Object JavaDoc value, Object JavaDoc dep_attr, Object JavaDoc sig_attr, Object JavaDoc vis_annot_attr){
212         addField(access, name, sig, value, null, dep_attr, sig_attr, vis_annot_attr);
213     }
214
215     //
216
// called by the .field directive
217
//
218
void addField(short access, String JavaDoc name,
219                                 String JavaDoc sig, Object JavaDoc value, String JavaDoc synth, Object JavaDoc dep_attr, Object JavaDoc sig_attr, Object JavaDoc vis_annot_attr) {
220
221
222         if (value == null) {
223             // defining a field which doesn't have an initial value
224
if (synth == null){
225                 currentField = new Var(access, new AsciiCP(name), new AsciiCP(sig), null);
226             }
227             else {
228                 currentField = new Var(access, new AsciiCP(name), new AsciiCP(sig), null, new SyntheticAttr());
229             }
230         if(dep_attr != null){
231             currentField.addDeprecatedAttr(new DeprecatedAttr());
232         }
233         if(sig_attr != null){
234             currentField.addSignatureAttr(new SignatureAttr((String JavaDoc)sig_attr));
235         }
236         if (vis_annot_attr != null){
237             currentField.addVisibilityAnnotationAttr((VisibilityAnnotationAttr)vis_annot_attr);
238         }
239             
240         /*currentField =
241         new Var(access, new AsciiCP(name),
242             new AsciiCP(sig), null);*/

243         class_env.addField(currentField);
244
245         } else {
246             // defining a field with an initial value...
247

248             // create a constant pool entry for the initial value
249
CP cp = null;
250
251             // correctness patch due to Brian Demsky (bdemsky@mit.edu)
252
// it's strange that Soot doesn't trigger this bug.
253
if (sig.equals("I")||sig.equals("Z")||sig.equals("C")||sig.equals("B")||sig.equals("S")) {
254                 cp = new IntegerCP(((Number JavaDoc)value).intValue());
255             } else if (sig.equals("F")) {
256                 cp = new FloatCP(((Number JavaDoc)value).floatValue());
257             } else if (sig.equals("D")) {
258                 cp = new DoubleCP(((Number JavaDoc)value).doubleValue());
259             } else if (sig.equals("J")) {
260                 cp = new LongCP(((Number JavaDoc)value).longValue());
261             } else if (sig.equals("Ljava/lang/String;")) {
262                cp = new StringCP((String JavaDoc)value);
263             }
264
265             // add the field
266
if (synth == null){
267         currentField =
268             new Var(access, new AsciiCP(name),
269                                new AsciiCP(sig), new ConstAttr(cp));
270             }
271             else {
272         currentField =
273             new Var(access, new AsciiCP(name),
274                                new AsciiCP(sig), new ConstAttr(cp), new SyntheticAttr());
275             }
276         if(dep_attr != null){
277             currentField.addDeprecatedAttr(new DeprecatedAttr());
278         }
279         if(sig_attr != null){
280             currentField.addSignatureAttr(new SignatureAttr((String JavaDoc)sig_attr));
281         }
282         class_env.addField(currentField);
283         }
284     }
285
286     //
287
// called by the .method directive to start the definition for a method
288
//
289
void newMethod(String JavaDoc name, String JavaDoc signature, int access) {
290         // set method state variables
291

292         labels = new Hashtable();
293         method_name = name;
294         code = null;
295         except_attr = null;
296         catch_table = null;
297         var_table = null;
298         line_table = null;
299         line_label_count = 0;
300         method_signature = signature;
301         method_access = (short)access;
302         methSynth = false;
303         methDepr = false;
304         methSigAttr = null;
305         methAnnotAttr = null;
306         methParamAnnotAttr = null;
307         methAnnotDef = null;
308     }
309
310     //
311
// called by the .end method directive to end the definition for a method
312
//
313
void endMethod() throws jasError {
314
315         if (code != null) {
316
317             plantLabel(END_METHOD);
318
319             if (catch_table != null) {
320                 code.setCatchtable(catch_table);
321             }
322             if (var_table != null) {
323                 code.setLocalVarTable(var_table);
324             }
325             if (line_table != null) {
326                 code.setLineTable(line_table);
327             }
328        
329         code.setLabelTable(labels);
330         }
331     
332         if (!methSynth){
333     currentMethod = new Method(method_access, new AsciiCP(method_name),
334                         new AsciiCP(method_signature), code, except_attr);
335         }
336         else {
337     currentMethod = new Method(method_access, new AsciiCP(method_name),
338                         new AsciiCP(method_signature), code, except_attr, new SyntheticAttr());
339         }
340
341         if (methDepr){
342             currentMethod.addDeprecatedAttr(new DeprecatedAttr());
343         }
344         if (methSigAttr != null){
345             currentMethod.addSignatureAttr(new SignatureAttr(methSigAttr));
346         }
347         if (methAnnotAttr != null){
348             currentMethod.addAnnotationAttr(methAnnotAttr);
349         }
350         if (methParamAnnotAttr != null){
351             currentMethod.addParamAnnotationAttr(methParamAnnotAttr);
352         }
353         if (methAnnotDef != null){
354             methAnnotDef.setNoName();
355             currentMethod.addAnnotationDef(new AnnotationDefaultAttr(methAnnotDef));
356         }
357     class_env.addMethod( currentMethod);
358     
359     
360     
361         // clear method state variables
362
code = null;
363         labels = null;
364         method_name = null;
365         code = null;
366         except_attr = null;
367         catch_table = null;
368         line_table = null;
369         var_table = null;
370         methSynth = false;
371         methDepr = false;
372         methSigAttr = null;
373         methAnnotAttr = null;
374         methParamAnnotAttr = null;
375         methAnnotDef = null;
376
377
378     }
379
380     
381
382     //
383
// plant routines - these use addInsn to add instructions to the
384
// code for the current method.
385
//
386

387     //
388
// used for instructions that take no arguments
389
//
390
void plant(String JavaDoc name) throws jasError {
391         InsnInfo insn = InsnInfo.get(name);
392         autoNumber();
393         if (insn.args.equals("")) {
394         Insn inst = new Insn(insn.opcode);
395
396
397             _getCode().addInsn(inst);
398         } else if (insn.name.equals("wide")) {
399             // don't do anything for this one...
400
} else {
401             throw new jasError("Missing arguments for instruction " + name);
402         }
403     }
404
405     //
406
// used for iinc
407
//
408
void plant(String JavaDoc name, int v1, int v2) throws jasError {
409         autoNumber();
410         if (name.equals("iinc")) {
411         Insn inst = new IincInsn(v1, v2);
412
413             _getCode().addInsn(inst);
414         } else {
415             throw new jasError("Bad arguments for instruction " + name);
416         }
417     }
418
419     //
420
// used for instructions that take an integer parameter
421
//
422
void plant(String JavaDoc name, int val) throws jasError {
423         InsnInfo insn = InsnInfo.get(name);
424         CodeAttr code = _getCode();
425         autoNumber();
426     
427     Insn inst = null;
428         if (insn.args.equals("i")) {
429             inst = new Insn(insn.opcode, val);
430         } else if (insn.args.equals("constant")) {
431             inst = new Insn(insn.opcode, new IntegerCP(val));
432         } else if (insn.args.equals("bigconstant")) {
433             inst = new Insn(insn.opcode, new LongCP(val));
434         } else {
435             throw new jasError("Bad arguments for instruction " + name);
436         }
437     
438     code.addInsn(inst);
439
440     }
441
442     //
443
// used for ldc and other instructions that take a numeric argument
444
//
445
void plant(String JavaDoc name, Number JavaDoc val) throws jasError {
446         InsnInfo insn = InsnInfo.get(name);
447         CodeAttr code = _getCode();
448         autoNumber();
449     
450     Insn inst = null;
451         if (insn.args.equals("i") && (val instanceof Integer JavaDoc)) {
452             inst = new Insn(insn.opcode, val.intValue());
453         } else if (insn.args.equals("constant")) {
454             if (val instanceof Integer JavaDoc || val instanceof Long JavaDoc) {
455                 inst = new Insn(insn.opcode,
456                              new IntegerCP(val.intValue()));
457             } else if (val instanceof Float JavaDoc || val instanceof Double JavaDoc) {
458                 inst = new Insn(insn.opcode,
459                              new FloatCP(val.floatValue()));
460             }
461         } else if (insn.args.equals("bigconstant")) {
462             if (val instanceof Integer JavaDoc || val instanceof Long JavaDoc) {
463                 inst = new Insn(insn.opcode,
464                              new LongCP(val.longValue()));
465             } else if (val instanceof Float JavaDoc || val instanceof Double JavaDoc) {
466                 inst = new Insn(insn.opcode,
467                              new DoubleCP(val.doubleValue()));
468             }
469         } else {
470             throw new jasError("Bad arguments for instruction " + name);
471         }
472     _getCode().addInsn(inst);
473
474     }
475
476     //
477
// used for ldc <quoted-string>
478
//
479
void plantString(String JavaDoc name, String JavaDoc val) throws jasError {
480         //System.out.println("plant string");
481
InsnInfo insn = InsnInfo.get(name);
482         autoNumber();
483     Insn inst = null;
484         if (insn.args.equals("constant")) {
485             inst = new Insn(insn.opcode, new StringCP(val));
486         } else {
487             throw new jasError("Bad arguments for instruction " + name);
488         }
489     
490     code.addInsn(inst);
491
492     }
493
494     //
495
// used for invokeinterface and multianewarray
496
//
497
void plant(String JavaDoc name, String JavaDoc val, int nargs)
498             throws jasError
499     {
500         InsnInfo insn = InsnInfo.get(name);
501         CodeAttr code = _getCode();
502         autoNumber();
503     Insn inst = null;
504         if (insn.args.equals("interface")) {
505             String JavaDoc split[] = ScannerUtils.splitClassMethodSignature(val);
506             inst = new InvokeinterfaceInsn(
507                          new InterfaceCP(split[0], split[1],
508                          split[2]), nargs);
509
510         } else if (insn.args.equals("marray")) {
511             inst = new MultiarrayInsn(new ClassCP(val), nargs);
512         } else {
513             throw new jasError("Bad arguments for instruction " + name);
514         }
515
516     code.addInsn(inst);
517
518     }
519
520     //
521
// used for instructions that take a word as a parameter
522
// (e.g. branches, newarray, invokemethod)
523
//
524
void plant(String JavaDoc name, String JavaDoc val) throws jasError {
525         //System.out.println("plant name, val: "+val);
526
InsnInfo insn = InsnInfo.get(name);
527         CodeAttr code = _getCode();
528         autoNumber();
529     Insn inst = null;
530         if (insn.args.equals("method")) {
531             String JavaDoc split[] = ScannerUtils.splitClassMethodSignature(val);
532             inst = new Insn(insn.opcode,
533                          new MethodCP(split[0], split[1], split[2]));
534         } else if (insn.args.equals("constant")) {
535             //System.out.println("constant");
536
inst = new Insn(insn.opcode, new ClassCP(val));
537         } else if (insn.args.equals("atype")) {
538             int atype = 0;
539             if (val.equals("boolean")) {
540                 atype = 4;
541             } else if (val.equals("char")) {
542                 atype = 5;
543             } else if (val.equals("float")) {
544                 atype = 6;
545             } else if (val.equals("double")) {
546                 atype = 7;
547             } else if (val.equals("byte")) {
548                 atype = 8;
549             } else if (val.equals("short")) {
550                 atype = 9;
551             } else if (val.equals("int")) {
552                 atype = 10;
553             } else if (val.equals("long")) {
554                 atype = 11;
555             } else {
556                 throw new jasError("Bad array type: " + name);
557             }
558             inst = new Insn(insn.opcode, atype);
559         } else if (insn.args.equals("label")) {
560             inst = new Insn(insn.opcode, getLabel(val));
561         } else if (insn.args.equals("class")) {
562             inst = new Insn(insn.opcode, new ClassCP(val));
563         } else {
564             throw new jasError("Bad arguments for instruction " + name);
565         }
566
567
568     code.addInsn(inst);
569
570     }
571
572     //
573
// used for instructions that take a field and a signature as parameters
574
// (e.g. getstatic, putstatic)
575
//
576
void plant(String JavaDoc name, String JavaDoc v1, String JavaDoc v2)
577             throws jasError
578     {
579         InsnInfo info = InsnInfo.get(name);
580         CodeAttr code = _getCode();
581         autoNumber();
582     Insn inst = null;
583         if (info.args.equals("field")) {
584             String JavaDoc split[] = ScannerUtils.splitClassField(v1);
585             inst = new Insn(info.opcode,
586                 new FieldCP(split[0], split[1], v2));
587         } else {
588             throw new jasError("Bad arguments for instruction " + name);
589         }
590
591     code.addInsn(inst);
592
593     }
594
595     //
596
// Lookupswitch instruction
597
//
598
void newLookupswitch() throws jasError {
599         switch_vec = new Vector();
600         autoNumber();
601     };
602
603     void addLookupswitch(int val, String JavaDoc label)
604             throws jasError {
605         switch_vec.addElement(new Integer JavaDoc(val));
606         switch_vec.addElement(getLabel(label));
607     };
608
609     void endLookupswitch(String JavaDoc deflabel) throws jasError {
610         int n = switch_vec.size() >> 1;
611         int offsets[] = new int[n];
612         Label labels[] = new Label[n];
613         Enumeration e = switch_vec.elements();
614         int i = 0;
615         while (e.hasMoreElements()) {
616             offsets[i] = ((Integer JavaDoc)e.nextElement()).intValue();
617             labels[i] = (Label)e.nextElement();
618             i++;
619         }
620         _getCode().addInsn(new LookupswitchInsn(getLabel(deflabel),
621                           offsets, labels));
622     }
623
624     //
625
// Tableswitch instruction
626
//
627
void newTableswitch(int lowval) throws jasError {
628         newTableswitch(lowval, -1);
629     };
630
631     void newTableswitch(int lowval, int hival) throws jasError {
632         switch_vec = new Vector();
633         low_value = lowval;
634         high_value = hival;
635         autoNumber();
636     };
637
638     void addTableswitch(String JavaDoc label) throws jasError {
639         switch_vec.addElement(getLabel(label));
640     };
641
642     void endTableswitch(String JavaDoc deflabel) throws jasError {
643         int n = switch_vec.size();
644         Label labels[] = new Label[n];
645         Enumeration e = switch_vec.elements();
646         int i = 0;
647         while (e.hasMoreElements()) {
648             labels[i] = (Label)e.nextElement();
649             i++;
650         }
651         if (high_value != -1 && (high_value != low_value + n - 1)) {
652             report_error("tableswitch - given incorrect value for <high>");
653
654         }
655         _getCode().addInsn(new TableswitchInsn(low_value, low_value + n - 1,
656                           getLabel(deflabel), labels));
657
658     }
659
660
661     // Used by the parser to tell ClassFile what the line number
662
// for the next statement is. ClassFile's autoNumber mechanism
663
// uses this info.
664
void setLine(int l) { line_num = l; }
665
666     //
667
// If auto_number is true, output debugging line number table
668
// for Jasmin assembly instructions.
669
//
670
void autoNumber() throws jasError {
671         if (auto_number) {
672             // use the line number of the last token
673
addLineInfo(line_num);
674         }
675     }
676
677     //
678
// Label management
679
//
680

681     //
682
// gets the Label object for a label, creating it if it doesn't exist
683
//
684
Label getLabel(String JavaDoc name) throws jasError {
685
686         // check that we are inside of a method definition
687
if (method_name == null) {
688             throw new jasError( "illegal use of label outside of method definition");
689         }
690
691         Label lab = (Label)labels.get(name);
692         if (lab == null) {
693             lab = new Label(name);
694             labels.put(name, lab);
695         }
696         return lab;
697     }
698
699     //
700
// defines a label
701
//
702
void plantLabel(String JavaDoc name) throws jasError {
703         // unsure what happens if you use a label twice?
704
_getCode().addInsn(getLabel(name));
705     }
706
707     //
708
// used by the .var directive
709
//
710
void addVar(String JavaDoc startLab, String JavaDoc endLab,
711                               String JavaDoc name, String JavaDoc sig, int var_num)
712                throws jasError {
713         if (startLab == null) {
714             startLab = BGN_METHOD;
715         }
716
717         if (endLab == null) {
718             endLab = END_METHOD;
719         }
720         Label slab, elab;
721         slab = getLabel(startLab);
722         elab = getLabel(endLab);
723
724         if (var_table == null) {
725             var_table = new LocalVarTableAttr();
726         }
727
728         var_table.addEntry(new LocalVarEntry(slab, elab, name, sig, var_num));
729     }
730
731     //
732
// used by .line directive
733
//
734
void addLineInfo(int line_num) throws jasError {
735         String JavaDoc l = "L:" + (line_label_count++);
736         if (line_table == null) {
737             line_table = new LineTableAttr();
738         }
739         plantLabel(l);
740         line_table.addEntry(getLabel(l), line_num);
741     }
742
743     void addLine(int line_num) throws jasError {
744         if (!auto_number) {
745             addLineInfo(line_num);
746         }
747     }
748
749     //
750
// used by the .throws directive
751
//
752
void addThrow(String JavaDoc name) throws jasError {
753
754         // check that we are inside of a method definition
755
if (method_name == null) {
756             throw new jasError( "illegal use of .throw outside of method definition");
757         }
758
759         if (except_attr == null) {
760             except_attr = new ExceptAttr();
761         }
762         except_attr.addException(new ClassCP(name));
763     }
764
765     //
766
// used by the .catch directive
767
//
768
void addCatch(String JavaDoc name, String JavaDoc start_lab, String JavaDoc end_lab,
769                                 String JavaDoc branch_lab) throws jasError {
770         ClassCP class_cp;
771
772         // check that we are inside of a method definition
773
if (method_name == null) {
774             throw new jasError( "illegal use of .catch outside of method definition");
775         }
776
777         if (catch_table == null) {
778             catch_table = new Catchtable();
779         }
780
781         if (name.equals("all")) {
782             class_cp = null;
783         } else {
784             class_cp = new ClassCP(name);
785         }
786
787         catch_table.addEntry(getLabel(start_lab), getLabel(end_lab),
788                              getLabel(branch_lab), class_cp);
789     }
790
791     //
792
// used by the .limit stack directive
793
//
794
void setStackSize(short v) throws jasError {
795         _getCode().setStackSize(v);
796     }
797
798     //
799
// used by the .limit vars directive
800
//
801
void setVarSize(short v) throws jasError {
802         _getCode().setVarSize(v);
803     }
804
805     // --- Private stuff ---
806

807
808     //
809
// returns the code block, creating it if it doesn't exist
810
//
811
CodeAttr _getCode() throws jasError {
812
813         // check that we are inside of a method definition
814
if (method_name == null) {
815             throw new jasError( "illegal use of instruction outside of method definition");
816         }
817
818         if (code == null) {
819             code = new CodeAttr();
820             plantLabel(BGN_METHOD);
821         }
822
823         return (code);
824     }
825
826
827     void addInnerClassAttr(){
828     }
829
830     void addInnerClassSpec(String JavaDoc inner_class_name, String JavaDoc outer_class_name, String JavaDoc inner_name, short access){
831         if (inner_class_attr == null){
832             inner_class_attr = new InnerClassAttr();
833         }
834         //inner_class_attr.addInnerClassSpec(new InnerClassSpecAttr(new ClassCP(inner_class_name), new ClassCP(outer_class_name), new AsciiCP(inner_name), access));
835
inner_class_attr.addInnerClassSpec(new InnerClassSpecAttr(inner_class_name, outer_class_name, inner_name, access));
836         
837     }
838    
839     void endInnerClassAttr(){
840         class_env.finishInnerClassAttr(inner_class_attr);
841     }
842     
843     void addClassSynthAttr(){
844         class_env.setClassSynth(true);
845     }
846
847     void addMethSynthAttr(){
848         methSynth = true;
849     }
850    
851     void addMethDeprAttr(){
852          methDepr = true;
853     }
854    
855     void addMethSigAttr(String JavaDoc s){
856         methSigAttr = s;
857     }
858    
859     void addEnclMethAttr(String JavaDoc cls, String JavaDoc meth, String JavaDoc sig){
860         class_env.addEnclMethAttr(new EnclMethAttr(cls, meth, sig));
861     }
862    
863     void addMethAnnotAttr(Object JavaDoc attr){
864         methAnnotAttr = (VisibilityAnnotationAttr)attr;
865     }
866    
867     void addMethParamAnnotAttr(Object JavaDoc attr){
868         methParamAnnotAttr = (ParameterVisibilityAnnotationAttr)attr;
869     }
870    
871     void addMethAnnotDefault(Object JavaDoc attr){
872         methAnnotDef = (ElemValPair)attr;
873     }
874    
875     
876     VisibilityAnnotationAttr makeVisibilityAnnotation(Object JavaDoc tval, Object JavaDoc list){
877         return new VisibilityAnnotationAttr((String JavaDoc)tval, (ArrayList)list);
878     }
879     
880     ParameterVisibilityAnnotationAttr makeParameterVisibilityAnnotation(Object JavaDoc kind, Object JavaDoc list){
881         return new ParameterVisibilityAnnotationAttr((String JavaDoc)kind+"Parameter", (ArrayList)list);
882     }
883     
884
885     void endVisibilityAnnotation(){
886     }
887
888     /*void addAnnotAttrToField(){
889         System.out.println("curr Field: "+currentField);
890         if (currentField != null){
891             currentField.addVisibilityAnnotationAttr(vis_annot_attr, class_env);
892         }
893     }*/

894    
895     AnnotationAttr currAnn = null;
896   
897     ArrayList makeNewAnnotAttrList(Object JavaDoc annot){
898         ArrayList list = new ArrayList();
899         list.add(annot);
900         return (ArrayList)list;
901     }
902
903     ArrayList mergeNewAnnotAttr(Object JavaDoc list, Object JavaDoc elem){
904         ((ArrayList)list).add(elem);
905         return (ArrayList)list;
906     }
907     
908     ArrayList makeNewAnnotationList(Object JavaDoc elem){
909         ArrayList list = new ArrayList();
910         list.add(elem);
911         return (ArrayList)list;
912     }
913
914     ArrayList mergeNewAnnotation(Object JavaDoc list, Object JavaDoc elem){
915         ((ArrayList)list).add(elem);
916         return (ArrayList)list;
917     }
918     
919     AnnotationAttr makeAnnotation(String JavaDoc type, Object JavaDoc elems){
920         return new AnnotationAttr(type, (ArrayList)elems);
921     }
922
923     void endAnnotation(){
924         if (vis_annot_attr == null){
925             vis_annot_attr = new VisibilityAnnotationAttr();
926         }
927         vis_annot_attr.addAnnotation(currAnn);
928     }
929
930     ArrayList makeNewElemValPairList(Object JavaDoc elem){
931         ArrayList list = new ArrayList();
932         list.add(elem);
933         return list;
934     }
935
936     ArrayList mergeNewElemValPair(Object JavaDoc list, Object JavaDoc elem){
937         ((ArrayList)list).add(elem);
938         return (ArrayList)list;
939     }
940     
941     ElemValPair makeConstantElem(String JavaDoc name, char kind, Object JavaDoc val){
942         //System.out.println("making constant elem val pair: "+val);
943
ElemValPair result = null;
944         //System.out.println("val: "+val);
945
switch(kind){
946             case 'S' : {
947                        }
948             case 'B' : {
949                        }
950             case 'Z' : {
951                        }
952             case 'C' : {
953                        }
954             case 'I' : {
955                            result = new IntElemValPair(name, kind, ((Integer JavaDoc)val).intValue());
956                            break;
957                        }
958             case 'J' : {
959                            result = new LongElemValPair(name, kind, ((Number JavaDoc)val).longValue());
960                            break;
961                        }
962             case 'F' : {
963                            result = new FloatElemValPair(name, kind, ((Number JavaDoc)val).floatValue());
964                            break;
965                        }
966             case 'D' : {
967                            result = new DoubleElemValPair(name, kind, ((Number JavaDoc)val).doubleValue());
968                            break;
969                        }
970             case 's' : {
971                            result = new StringElemValPair(name, kind, (String JavaDoc)val);
972                            break;
973                        }
974                 
975         }
976         return result;
977     }
978    
979     ElemValPair makeEnumElem(String JavaDoc name, char kind, String JavaDoc tval, String JavaDoc cval){
980         return new EnumElemValPair(name, kind, tval, cval);
981     }
982
983     ElemValPair makeClassElem(String JavaDoc name, char kind, String JavaDoc cval){
984         return new ClassElemValPair(name, kind, cval);
985     }
986
987     ElemValPair makeAnnotElem(String JavaDoc name, char kind, Object JavaDoc attr){
988         return new AnnotElemValPair(name, kind, (AnnotationAttr)attr);
989     }
990     
991     ElemValPair makeArrayElem(String JavaDoc name, char kind, Object JavaDoc list){
992         ArrayElemValPair elem = new ArrayElemValPair(name, kind, (ArrayList)list);
993         elem.setNoName();
994         return elem;
995     }
996     
997     void endAnnotElem(){
998     }
999
1000    void endArrayElem(){
1001        
1002    }
1003    // PUBLIC API TO JASMIN:
1004

1005    /** Makes a new ClassFile object, used to represent a Java class file.
1006      * You can then use readJasmin to read in a class file stored in
1007      * Jasmin assembly format.
1008      */

1009
1010    public ClassFile() { }
1011
1012    /**
1013      * Parses a Jasmin file, converting it internally into a binary
1014      * representation.
1015      * If something goes wrong, this throws one of
1016      * an IOException, or a jasError, or one of a few other exceptions.
1017      * I'll tie this down more formally in the next version.
1018      *
1019      * @param input is the stream containing the Jasmin assembly code for the
1020      * class.
1021      *
1022      * @param name is the name of the stream. This name will be
1023      * concatenated to error messages printed to System.err.
1024      *
1025      * @param numberLines true if you want Jasmin to generate line
1026      * numbers automatically, based on the assembly source, or
1027      * false if you are using the ".line" directive and don't
1028      * want Jasmin to help out.
1029      */

1030    public void readJasmin(InputStream JavaDoc input, String JavaDoc name,
1031                           boolean numberLines)
1032                   throws IOException JavaDoc, Exception JavaDoc {
1033        // initialize variables for error reporting
1034
errors = 0;
1035        filename = name;
1036    source_name = name;
1037
1038        // if numberLines is true, we output LineTableAttr's that indicate what line
1039
// numbers the Jasmin code falls on.
1040
auto_number = numberLines;
1041
1042        // Parse the input file
1043
class_env = new ClassEnv();
1044
1045    scanner = new Scanner(input);
1046        parser parse_obj = new parser(this, scanner);
1047
1048        if (false) {
1049            // for debugging
1050
// parse_obj.debug_parse();
1051
} else {
1052            parse_obj.parse();
1053        }
1054    }
1055
1056    /**
1057     * Returns the number of warnings/errors encountered while parsing a file.
1058     * 0 if everything went OK.
1059     */

1060    public int errorCount() {
1061        return errors;
1062    }
1063
1064    /**
1065     * Returns the name of the class in the file (i.e. the string given to
1066     * the .class parameter in Jasmin)
1067     *
1068     */

1069    public String JavaDoc getClassName() {
1070        return class_name;
1071    }
1072
1073    /**
1074     * Writes the binary data for the class represented by this ClassFile
1075     * object to the specified
1076     * output stream, using the Java Class File format. Throws either an
1077     * IOException or a jasError if something goes wrong.
1078     */

1079    public void write(OutputStream JavaDoc outp) throws IOException JavaDoc, jasError {
1080        class_env.setSource(source_name);
1081        class_env.write(new DataOutputStream JavaDoc(outp));
1082    }
1083};
1084
1085/* --- Revision History ---------------------------------------------------
1086--- Jonathan Meyer, April 11 1997
1087    Fixed bug where source_name was not being set in class_env.
1088--- Jonathan Meyer, Mar 1 1997
1089    Renamed "Jasmin" class "ClassFile".
1090--- Jonathan Meyer, Feb 8 1997
1091    Converted to non-static. Made a public API. Split off InsnInfo to a
1092    separate file.
1093--- Jonathan Meyer, Oct 1 1996
1094    Added addInterface method, used by the .implements directive.
1095--- Jonathan Meyer, July 25 1996
1096    Added setLine and line_num, to fix problem with autoNumber.
1097    Added report_error method.
1098--- Jonathan Meyer, July 24 1996 added version constant.
1099*/

1100
Popular Tags