1 package classfile;
17
18 import java.util.Vector;
19 import java.io.*;
20 import util.*;
21 import jconst.*;
22 import attr.*;
23
24
25
26 ss classFileHeader extends dataRead {
41 private int magic;
42 private short minor_version;
43 private short major_version;
44
45 classFileHeader( DataInputStream dStream ) {
46 magic = readU4( dStream );
47 minor_version = (short)readU2( dStream );
48 major_version = (short)readU2( dStream );
49 }
51 void pr() {
52 System.out.println("magic number: 0x" + Integer.toHexString( magic ));
53 System.out.println("Java version " + major_version + "." + minor_version );
54 }
55
56 }
58
59
60
61 lass classDeclSec extends dataRead implements access_and_modifier_flags {
73 private int accessFlags = 0;
74 private constBase thisClass = null;
75 private constBase superClass = null;
76 private constBase interfaces[] = null;
77
78 classDeclSec( DataInputStream dStream, constPool constPoolSec ) {
79 int thisClassIx;
80 int superClassIx;
81 int interfaceCnt;
82
83 accessFlags = readU2( dStream );
84 thisClassIx = readU2( dStream );
85 superClassIx = readU2( dStream );
86
87 thisClass = constPoolSec.constPoolElem( thisClassIx );
88 superClass = constPoolSec.constPoolElem( superClassIx );
89
90 interfaceCnt = readU2( dStream );
91
92 if (interfaceCnt > 0) {
93 int ix;
94
95 interfaces = new constBase[ interfaceCnt ];
96 for (int i = 0; i < interfaceCnt; i++) {
97 ix = readU2( dStream );
98 interfaces[ i ] = constPoolSec.constPoolElem( ix );
99 }
100 }
101 }
103
104 String getClassName() {
105 String name = null;
106
107 if (thisClass != null) {
108 if (thisClass instanceof constClass_or_String) {
109 name = objNameFormat.toDotSeparator( thisClass.getString() );
110 }
111 }
112
113 return name;
114 }
116
119 private void pr_modifiers( int mod ) {
120 String modStr;
121
122 modStr = accString.toString( mod, false );
123 if (modStr != null) {
124 System.out.print( modStr );
125 }
126 }
128
129 void pr() {
130 pr_modifiers( accessFlags );
131 if ((accessFlags & ACC_INTERFACE) == 0) {
132 if (accessFlags > 0) {
133 System.out.print(" ");
134 }
135 System.out.print("class ");
136 }
137
138 System.out.print( getClassName() );
139
140 if (superClass != null) {
142 if (superClass instanceof constClass_or_String) {
143 if (superClass.getString().compareTo( "java/lang/Object" ) != 0) {
144 String superClassName;
145
146 superClassName = superClass.getString();
147 superClassName = objNameFormat.toDotSeparator(superClassName);
148 System.out.print(" extends " + superClassName );
149 }
150 }
151 }
152
153 if (interfaces != null) {
154 boolean firstName = true;
155
156 System.out.print(" implements ");
157
158 for (int i = 0; i < interfaces.length; i++) {
159 if (! firstName) {
160 System.out.print(", ");
161 }
162 else {
163 firstName = false;
164 }
165 if (interfaces[i] != null) {
166 if (interfaces[i] instanceof constClass_or_String) {
167 interfaces[i].prString();
168 }
169 else {
170 System.out.println(" classDeclSec: interfaces[" + i + "] is a " +
171 interfaces[i].getClass().getName() );
172 }
173 }
174 else {
175 System.out.print("<null>");
176 }
177 } }
179 System.out.println(" {");
180 }
182 }
184
185
186 s fieldInfo extends dataRead {
210 int access_flags = 0;
211 constUtf8 name = null;
212 constUtf8 descriptor = null;
213 attrInfo attributes[] = null;
214
215 fieldInfo( DataInputStream dStream, constPool constPoolSec ) {
216 int name_index;
217 int desc_index;
218 int attr_cnt;
219 constBase obj;
220
221 access_flags = readU2( dStream );
222 name_index = readU2( dStream );
223 desc_index = readU2( dStream );
224 attr_cnt = readU2( dStream );
225
226 obj = constPoolSec.constPoolElem( name_index );
227 if (obj != null && obj instanceof constUtf8) {
228 name = (constUtf8)obj;
229 }
230
231 obj = constPoolSec.constPoolElem( desc_index );
232 if (obj != null && obj instanceof constUtf8) {
233 descriptor = (constUtf8)obj;
234 }
235
236 if (attr_cnt > 0) {
237 attributes = new attrInfo[ attr_cnt ];
238 for (int i = 0; i < attr_cnt; i++) {
239 attributes[i] = attrFactory.allocAttr( dStream, constPoolSec );
240 if (attributes[i].getName().compareTo( "ConstantValue" ) != 0 &&
241 attributes[i].getName().compareTo( "Synthetic" ) != 0 &&
242 attributes[i].getName().compareTo( "Deprecated" ) != 0 ) {
243 errorMessage.errorPrint("fieldInfo: field info attribute expected");
244 errorMessage.errorPrint("fieldInfo: attr name = " +
245 attributes[i].getName() );
246 }
247 }
248 }
249 }
251
252
253 String fieldString() {
268 String modStr; String typeStr; StringBuffer fieldStr = new StringBuffer();
271
272 modStr = accString.toString( access_flags, false );
273 typeStr = typeDesc.decodeFieldDesc( descriptor.getString() );
274 if (modStr != null) {
275 fieldStr.append( modStr );
276 fieldStr.append(" ");
277 }
278 fieldStr.append( typeStr );
279 fieldStr.append(" ");
280 fieldStr.append( name.getString() );
281
282
285 boolean isSynthetic = false;
286 boolean isDeprecated = false;
287 constValueAttr constAttr;
288 constBase constVal;
289 boolean firstConst = true;
290 String initVal = null;
291 String tmp = null;
292
293 if (attributes != null) {
294 for (int i = 0; i < attributes.length; i++) {
295 if (attributes[i] instanceof constValueAttr) {
296 constAttr = (constValueAttr)attributes[i];
297 constVal = constAttr.getConstVal();
298 if (constVal instanceof constClass_or_String ) {
299 tmp = ((constClass_or_String)constVal).getPrintableString();
300 }
301 else {
302 tmp = constVal.getString();
303 }
304 if (firstConst) {
305 firstConst = false;
306 initVal = tmp;
307 }
308 else {
309 initVal = initVal + ", " + tmp;
310 }
311 }
312 else if (attributes[i] instanceof synthAttr) {
313 isSynthetic = true;
314 }
315 else if (attributes[i] instanceof deprecAttr) {
316 isDeprecated = true;
317 }
318 }
320 if (accData.isStatic( access_flags) && initVal != null) {
321 fieldStr.append(" = ");
322 fieldStr.append( initVal );
323 } fieldStr.append(";");
325 if (isSynthetic || isDeprecated )
326 fieldStr.append(" //");
327 if (isSynthetic) {
328 fieldStr.append(" Synthetic");
329 }
330 if (isDeprecated) {
331 fieldStr.append(", Deprecated");
332 }
333 } else
335 fieldStr.append(";");
336 return fieldStr.toString();
337 }
339
340
343 void pr() {
344 System.out.println( fieldString() );
345 }
347 }
349
350
351 ass classFieldSec extends dataRead {
365 private fieldInfo classFields[] = null;
366
367 classFieldSec( DataInputStream dStream, constPool constPoolSec ) {
368 int field_cnt;
369
370 field_cnt = readU2( dStream );
371 if (field_cnt > 0) {
372 classFields = new fieldInfo[ field_cnt ];
373 }
374
375 for (int i = 0; i < field_cnt; i++) {
377 classFields[i] = new fieldInfo( dStream, constPoolSec );
378 }
380 }
382
383
384
386 void pr() {
387 if (classFields != null) {
388 fieldInfo info;
389
390 for (int i = 0; i < classFields.length; i++) {
391 info = classFields[i];
392 System.out.print(" ");
393 if (info != null) {
394 info.pr();
395 }
396 else {
397 System.out.println("\nclassFieldSec: pr - null at classFields[" + i + "]");
398 }
399 }
400 }
401 }
403 }
405
406
407 methodInfo extends dataRead implements access_and_modifier_flags {
489 int access_flags = 0;
490 constUtf8 name = null;
491 String constructorName = null;
492 constUtf8 descriptor = null;
493 attrInfo attributes[] = null;
494 codeAttr codeAttribute = null;
495
496
497 methodInfo( DataInputStream dStream, constPool constPoolSec ) {
498 int name_index;
499 int desc_index;
500 int attr_cnt;
501 constBase obj;
502
503 access_flags = readU2( dStream );
504 name_index = readU2( dStream );
505 desc_index = readU2( dStream );
506 attr_cnt = readU2( dStream );
507
508 obj = constPoolSec.constPoolElem( name_index );
509 if (obj != null && obj instanceof constUtf8) {
510 name = (constUtf8)obj;
511 }
512
513 obj = constPoolSec.constPoolElem( desc_index );
514 if (obj != null && obj instanceof constUtf8) {
515 descriptor = (constUtf8)obj;
516 }
517
518 if (attr_cnt > 0) {
521 attributes = new attrInfo[ attr_cnt ];
522 for (int i = 0; i < attr_cnt; i++) {
523 attributes[i] = attrFactory.allocAttr( dStream, constPoolSec );
524 if (attributes[i] instanceof codeAttr)
525 codeAttribute = (codeAttr)attributes[i];
526 } }
528 }
530
531
535 public boolean isConstructor() {
536 return (name.getString().compareTo("<init>") == 0);
537 }
538
539
540
543 public void setConstructorName( String newName ) {
544 constructorName = newName;
545 }
546
547
548
551 public String getConstructorName() {
552 return constructorName;
553 }
554
555
556
562 private String commentString() {
563 String str = null;
564
565 if (attributes != null) {
566 for (int i = 0; i < attributes.length; i++) {
567 if (attributes[i] instanceof synthAttr) {
568 if (str == null)
569 str = "// ";
570 else
571 str = str + ", ";
572 str = str + "synthetic";
573 }
574 if (attributes[i] instanceof deprecAttr) {
575 if (str == null)
576 str = "// ";
577 else
578 str = str + ", ";
579 str = str + "deprecated";
580 }
581 }
582 }
583 return str;
584 }
586
587
597 private String exceptionString() {
598 String str = null;
599
600 if (attributes != null) {
601 String exceptList = null;
603 for (int i = 0; i < attributes.length; i++) {
604 if (attributes[i] instanceof exceptAttr) {
605 exceptAttr eAttr;
606 constClass_or_String exceptTab[];
607
608 eAttr = (exceptAttr)attributes[i];
609 exceptTab = eAttr.getExceptTab();
610 if (exceptTab != null && exceptTab.length > 0) {
611 String className;
612
613 for (int j = 0; j < exceptTab.length; j++) {
615 className = exceptTab[j].getString();
616 className = objNameFormat.toDotSeparator( className );
617 if (exceptList == null) {
618 exceptList = className;
619 }
620 else {
621 exceptList = exceptList + ", " + className;
622 }
623 } }
625 break;
626 }
627 } if (exceptList != null) {
629 str = "\n throws " + exceptList;
630 }
631 }
632 return str;
633 }
635
636 class methodTypes {
647 public StringBuffer argList;
648 public String returnType;
649
650 methodTypes() {
651 argList = new StringBuffer();
652 }
653 }
655
656 te methodTypes decodeMethodDesc( String methodDesc ) {
690 methodTypes types = null;
691
692 if (methodDesc != null) {
693 int len = methodDesc.length();
694 int ix = 0;
695
696 types = new methodTypes();
697
698 if (methodDesc.charAt(ix) == '(') {
699 String typeName;
700 char ch;
701 int dimCnt; boolean first_type = true;
703
704 for (ix++; ix < len && methodDesc.charAt(ix) != ')'; ix++) {
705 ch = methodDesc.charAt(ix);
706 dimCnt = 0;
707
708 while (ch == '[') {
710 dimCnt++;
711 ix++;
712 ch = methodDesc.charAt(ix);
713 }
714
715 if (ch == 'L') { String objName;
717 int jx;
718
719 ix++; for (jx = ix; jx < len && methodDesc.charAt(jx) != ';'; jx++)
723 ;
724
725 objName = methodDesc.substring(ix, jx);
726 typeName = objNameFormat.toDotSeparator( objName );
727 ix = jx; }
729 else if (typeDesc.isTypeChar( ch )) {
730 typeName = typeDesc.charToType( ch );
733 }
734 else {
735 errorMessage.errorPrint("decodeMethodDesc: unexpected char");
736 typeName = null;
737 }
738 for (int i = 0; i < dimCnt; i++) {
740 typeName = typeName + "[]";
741 }
742 if (typeName != null) {
743 if (first_type) {
744 first_type = false;
745 types.argList.append( typeName );
746 }
747 else {
748 types.argList.append(", ");
749 types.argList.append( typeName );
750 }
751 }
752 } if (ix < len && methodDesc.charAt(ix) == ')') {
754 ix++;
756
757 ch = methodDesc.charAt(ix);
758 if (ch == 'V') types.returnType = "void";
760 else if (ch == 'L') {
761 ix++;
762 typeName = methodDesc.substring( ix );
763 types.returnType = objNameFormat.toDotSeparator( typeName );
764 }
765 else if (typeDesc.isTypeChar( ch )) {
766 types.returnType = typeDesc.charToType( ch );
767 }
768 }
769 else
770 errorMessage.errorPrint("decodeMethodDesc: ')' expected");
771 }
772 else
773 errorMessage.errorPrint("decodeMethodDesc: '(' expected");
774 }
775
776 return types;
777 }
779
780 String methodString(String terminalStr ) {
791 StringBuffer methodBuf = new StringBuffer();
792
793 String modifiers = accString.toString( access_flags, true );
795 methodTypes types = decodeMethodDesc( descriptor.getString() );
796
797 if (modifiers != null) {
799 methodBuf.append( modifiers);
800 methodBuf.append(" ");
801 }
802
803 methodBuf.append( types.returnType);
806 methodBuf.append( " " );
807 if (constructorName == null)
808 methodBuf.append( name.getString() );
809 else
810 methodBuf.append( constructorName );
811 methodBuf.append( "(" );
812
813 if (types.argList != null) {
814 methodBuf.append( types.argList.toString() );
815 }
816
817 methodBuf.append(")");
818
819 String cmntStr = commentString();
821 String excptStr = exceptionString();
823
824 if (excptStr == null) { methodBuf.append( terminalStr );
826 }
827
828 if (cmntStr != null) {
830 methodBuf.append(" ");
831 methodBuf.append( cmntStr );
832 }
833
834 if (excptStr != null) {
839 methodBuf.append( excptStr );
840 methodBuf.append( terminalStr );
841 }
842
843 return methodBuf.toString();
844 }
846
847 void pr() {
853 final String indent1 = " ";
854 final String indent2 = " ";
855 boolean printed_header = false;
856
857 if (codeAttribute != null) { Vector localVarVec = codeAttribute.getLocalVarVec();
859
860 if (localVarVec != null) {
861 int len = localVarVec.size();
862 String localVar;
863
864 if (len > 0) {
865 System.out.println(indent1 + methodString( " {" ) );
866 printed_header = true;
867 }
868
869 for (int i = 0; i < len; i++) {
870 localVar = (String)localVarVec.elementAt( i );
871 System.out.println( indent2 + localVar);
872 }
873 }
874 }
875 if (! printed_header)
876 System.out.println(indent1 + methodString( ";" ) );
877 else
878 System.out.println( indent1 + "}" );
879 }
881 }
883
884 ass classMethodSec extends dataRead {
898 methodInfo classMethods[];
899
900 classMethodSec( DataInputStream dStream,
901 constPool constPoolSec,
902 String className ) {
903 int methodCnt;
904
905 methodCnt = readU2( dStream );
906 if (methodCnt > 0) {
907 classMethods = new methodInfo[ methodCnt ];
908 }
909
910 for (int i = 0; i < methodCnt; i++) {
911 classMethods[i] = new methodInfo( dStream, constPoolSec );
912 if (classMethods[i].isConstructor())
913 classMethods[i].setConstructorName( className );
914 }
915 }
917
918 void pr() {
919 if (classMethods != null) {
920 System.out.println();
922 for (int i = 0; i < classMethods.length; i++) {
923 classMethods[i].pr();
924 }
925 }
926 }
928 }
930
931
932
933 lass classAttrSec extends dataRead {
942 attrInfo classAttrTab[] = null;
943
944 classAttrSec( DataInputStream dStream, constPool constPoolSec ) {
945
946 int numAttr = readU2( dStream );
947
948 if (numAttr > 0) {
949 classAttrTab = new attrInfo[ numAttr ];
950 for (int i = 0; i < numAttr; i++) {
951 classAttrTab[i] = attrFactory.allocAttr( dStream, constPoolSec );
952 }
953 }
954 }
956 String getSrcFileName() {
966 String name = null;
967
968 if (classAttrTab != null) {
969 for (int i = 0; i < classAttrTab.length; i++) {
970 if (classAttrTab[i] instanceof srcFileAttr) {
971 srcFileAttr src;
972
973 src = (srcFileAttr)classAttrTab[i];
974 name = src.getFileName();
975 break;
976 }
977 } }
979
980 return name;
981 }
983 }
985
986
987
988
989 lic class classFile {
1022 classFileHeader header = null;
1023 constPool classConstPool = null;
1024 classDeclSec classDecl = null;
1025 classFieldSec classFields = null;
1026 classMethodSec classMethods = null;
1027 classAttrSec classAttrs = null;
1028 String className = null;
1029
1030
1031 public classFile(DataInputStream dStream) {
1044
1045 header = new classFileHeader( dStream );
1049
1050 classConstPool = new constPool( dStream );
1053
1054 classDecl = new classDeclSec( dStream, classConstPool );
1060
1061 classFields = new classFieldSec(dStream, classConstPool);
1064
1065 className = classDecl.getClassName();
1066
1067 classMethods = new classMethodSec(dStream, classConstPool, className );
1070
1071 classAttrs = new classAttrSec(dStream, classConstPool);
1074 }
1076 public void pr() {
1082 String srcFile;
1083
1084 srcFile = classAttrs.getSrcFileName();
1085 if (srcFile != null) {
1086 System.out.println("Compiled from " + srcFile + "\n");
1087 classDecl.pr();
1088 classFields.pr();
1089 classMethods.pr();
1090 System.out.println(" } // " + className + "\n");
1091 }
1092 }
1094 }