2
0

ClassDesc.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /**********************************************************************/
  2. /* Class Descriptor class for j2cps */
  3. /* */
  4. /* (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017 */
  5. /**********************************************************************/
  6. package j2cps;
  7. import java.io.*;
  8. import java.util.ArrayList;
  9. import java.util.HashMap;
  10. import java.util.Iterator;
  11. public class ClassDesc extends TypeDesc {
  12. // private static final int MAJOR_VERSION = 45;
  13. // private static final int MINOR_VERSION = 3;
  14. private static HashMap<String,ClassDesc> classMap = new HashMap<>();
  15. private static final String jlString = "java.lang.String";
  16. private static final String jlObject = "java.lang.Object";
  17. private static final int noAtt = 0; // no record attribute in cp
  18. private static final int absR = 1; // ABSTRACT record in cp
  19. private static final int limR = 2; // LIMITED record in cp
  20. // No equivalent in java!
  21. private static final int extR = 3; // EXTENSIBLE record in cp
  22. private static final int iFace = 4; // JAVA interface
  23. public static boolean useJar = false;
  24. public static boolean verbose = false;
  25. public static boolean VERBOSE = false;
  26. public static boolean summary = false;
  27. public static boolean nocpsym = false;
  28. @Override
  29. public String toString() {
  30. if (this.name != null)
  31. return this.name;
  32. else
  33. return "anon-ClassDesc";
  34. }
  35. ConstantPool cp;
  36. ClassDesc superClass;
  37. int access, outBaseTypeNum=0, superNum=0, numInts=0, intNums[];
  38. public String
  39. /**
  40. * Qualified name of the class e.g. java/lang/Object
  41. */
  42. qualName,
  43. /**
  44. * Java language name of the class e.g. java.lang.Object
  45. */
  46. javaName,
  47. /**
  48. * Unqualified name of the class e.g. Object
  49. */
  50. objName;
  51. ClassDesc[] interfaces;
  52. boolean
  53. isInterface = false,
  54. read = false,
  55. done = false;
  56. public boolean hasNoArgConstructor = false;
  57. /**
  58. * Packages imported by this class
  59. */
  60. public ArrayList<PackageDesc> imports = new ArrayList<>();
  61. /**
  62. * Fields declared in this class
  63. */
  64. public ArrayList<FieldInfo> fieldList = new ArrayList<>();
  65. /**
  66. * Methods defined in this class
  67. */
  68. public ArrayList<MethodInfo> methodList = new ArrayList<>();
  69. /**
  70. * HashMap of members declared locally in this class.
  71. */
  72. HashMap<String,MemberInfo> scope = new HashMap<>();
  73. public ClassDesc() {
  74. typeOrd = TypeDesc.classT;
  75. }
  76. /**
  77. * Find an existing ClassDescriptor object with the given
  78. * string name, or create one in the supplied package.
  79. * <p>
  80. * If the pack parameter is null, the package is found (or
  81. * created) based on the prefix of the string class name.
  82. * @param name the full name of the class
  83. * @param pack the package descriptor, or null if not known
  84. * @return the (possibly newly created) class descriptor
  85. */
  86. public static ClassDesc GetClassDesc(String name, PackageDesc pack) {
  87. if (name.indexOf(Util.JAVADOT) != -1) {
  88. name = name.replace(Util.JAVADOT,Util.FWDSLSH);
  89. }
  90. ClassDesc aClass = (ClassDesc)classMap.get(name);
  91. if (aClass == null) {
  92. aClass = ClassDesc.MakeNewClassDesc(name,pack);
  93. }
  94. return aClass;
  95. }
  96. /**
  97. * Create a new class descriptor with the given name, and added to
  98. * the given package descriptor.
  99. * <p>
  100. * If the pack parameter is null, create a new package descriptor
  101. * with a name inferred from the full class name, add the new package
  102. * to the package list, add the new class to the new package.
  103. * @param name the full name of the new class
  104. * @param pack the package to which the new class belongs, or null
  105. * @return the newly created class descriptor.
  106. */
  107. public static ClassDesc MakeNewClassDesc(String name, PackageDesc pack) {
  108. ClassDesc desc = new ClassDesc(name, pack);
  109. desc.MakeJavaName();
  110. classMap.put(desc.qualName, desc);
  111. return desc;
  112. }
  113. private ClassDesc(String thisName, PackageDesc pack) {
  114. this.typeOrd = TypeDesc.classT;
  115. this.qualName = thisName;
  116. if (pack == null) {
  117. this.parentPkg = PackageDesc.getClassPackage(this.qualName);
  118. } else {
  119. this.parentPkg = pack;
  120. }
  121. }
  122. public ClassDesc(int inNum) { this.inBaseTypeNum = inNum; }
  123. @Override
  124. public String getTypeMnemonic() {
  125. switch (javaName) {
  126. case jlString:
  127. return "S";
  128. case jlObject:
  129. return "O";
  130. default:
  131. return "o";
  132. }
  133. }
  134. /**
  135. * Read the details of the class.
  136. * <p>
  137. * Parse the class file attached to the DataInputStream,
  138. * creating new type, class and package descriptors for newly
  139. * identified type names.
  140. * @param stream The input data stream. Could be either
  141. * a FileStream or a zip stream from a jar file.
  142. * @return true if parse was successful.
  143. * @throws IOException
  144. */
  145. private boolean ReadClassFileDetails(DataInputStream stream)
  146. throws IOException {
  147. read = true;
  148. int count;
  149. ClassRef tmp;
  150. /* read and check the magic number */
  151. if (stream.readInt() != 0xCAFEBABE) {
  152. System.out.println("Bad magic number");
  153. System.exit(0);
  154. }
  155. /* read and check the minor and major version numbers */
  156. int minorVersion = stream.readUnsignedShort();
  157. // /* if (minorVersion > MINOR_VERSION) {
  158. // System.out.println("Unsupported Java minor version " +
  159. // String.valueOf(minorVersion));
  160. // System.exit(0);
  161. // }
  162. //*/
  163. int majorVersion = stream.readUnsignedShort();
  164. // /* if (majorVersion != MAJOR_VERSION) {
  165. // System.out.println("Unsupported Java major version " +
  166. // String.valueOf(majorVersion));
  167. // System.exit(0);
  168. // }
  169. //*/
  170. cp = new ConstantPool(stream);
  171. access = stream.readUnsignedShort();
  172. // Experimental code to only transform packages that
  173. // are reachable from classes that are not private.
  174. // Under consideration for next version, controlled
  175. // by a command line option.
  176. PackageDesc.tot++;
  177. if (!ConstantPool.isPublic(access) && !ConstantPool.isProtected(access)) {
  178. cp.EmptyConstantPool();
  179. PackageDesc.pub++;
  180. return true;
  181. }
  182. // End experimental code
  183. String clName = ((ClassRef) cp.Get(stream.readUnsignedShort())).GetName();
  184. if (!qualName.equals(clName)) {
  185. if (clName.startsWith(parentPkg.name)) {
  186. if (verbose) { System.out.println(clName + " IS PART OF PACKAGE " +
  187. parentPkg.name + " but name is not "
  188. + qualName); }
  189. } else {
  190. System.err.println(clName + " IS NOT PART OF PACKAGE " +
  191. parentPkg.name + " qualName = " + qualName);
  192. parentPkg = PackageDesc.getClassPackage(qualName);
  193. return false;
  194. }
  195. classMap.remove(qualName);
  196. qualName = clName;
  197. this.MakeJavaName();
  198. ClassDesc put = classMap.put(qualName,this);
  199. }
  200. isInterface = ConstantPool.isInterface(access);
  201. int superIx = stream.readUnsignedShort();
  202. if (superIx > 0) {
  203. tmp = (ClassRef) cp.Get(superIx);
  204. superClass = tmp.GetClassDesc();
  205. //
  206. // If superclass is not from the current package
  207. // mark the superclass package as needed for API.
  208. //
  209. if (superClass.parentPkg != this.parentPkg) {
  210. //superClass.parentPkg.set(Util.APINEEDS);
  211. superClass.blame = this;
  212. this.AddImportToClass(superClass);
  213. }
  214. }
  215. /* get the interfaces implemented by this class */
  216. count = stream.readUnsignedShort();
  217. interfaces = new ClassDesc[count];
  218. for (int i = 0; i < count; i++) {
  219. tmp = (ClassRef) cp.Get(stream.readUnsignedShort());
  220. ClassDesc theInterface = tmp.GetClassDesc();
  221. //theInterface.parentPkg.set(Util.APINEEDS);
  222. this.AddImportToClass(theInterface);
  223. interfaces[i] = theInterface;
  224. }
  225. /* get the fields for this class */
  226. count = stream.readUnsignedShort();
  227. if (verbose)
  228. System.out.println(count != 1 ?
  229. "There are " + count + " fields" :
  230. "There is one field");
  231. for (int i = 0; i < count; i++ ) {
  232. FieldInfo fInfo = new FieldInfo(cp,stream,this);
  233. //
  234. // The package to which this class belongs
  235. // must place the package of this field's type
  236. // on the import list IFF:
  237. // * the field is public or protected AND
  238. // * the field's package is not that of thisClass
  239. //
  240. if (fInfo.isExported()) {
  241. this.fieldList.add(fInfo);
  242. if (fInfo.type.parentPkg != this.parentPkg) {
  243. fInfo.type.blame = fInfo;
  244. this.TryImport(fInfo.type);
  245. }
  246. }
  247. }
  248. /* get the methods for this class */
  249. count = stream.readUnsignedShort();
  250. if (verbose)
  251. System.out.println(count != 1 ?
  252. "There are " + count + " methods" :
  253. "There is one method");
  254. for (int i = 0; i < count; i++ ) {
  255. MethodInfo mInfo = new MethodInfo(cp,stream,this);
  256. if (mInfo.isExported())
  257. this.methodList.add(mInfo);
  258. }
  259. /* ignore the rest of the classfile (ie. the attributes) */
  260. if (verbose) { System.out.println("Finished reading class file"); }
  261. if (VERBOSE) { /*PrintClassFile();*/ Diag(); }
  262. this.AddImportToParentImports();
  263. cp.EmptyConstantPool();
  264. cp = null;
  265. return true;
  266. }
  267. public void TryImport(TypeDesc type){
  268. if (type instanceof ClassDesc) {
  269. this.AddImportToClass((ClassDesc)type);
  270. }
  271. else if (type instanceof ArrayDesc) {
  272. ((ArrayDesc)type).elemType.blame = type.blame;
  273. this.TryImport(((ArrayDesc)type).elemType); // Recursive!
  274. }
  275. else if (type instanceof PtrDesc) {
  276. ((PtrDesc)type).AddImportToPtr(this);
  277. }
  278. }
  279. public void AddImportToClass(ClassDesc aClass) {
  280. if ((aClass != this) && (aClass.parentPkg != this.parentPkg) &&
  281. (!this.imports.contains(aClass.parentPkg))) {
  282. aClass.parentPkg.set(Util.APINEEDS);
  283. this.imports.add(aClass.parentPkg);
  284. aClass.parentPkg.blame = aClass.blame;
  285. /*
  286. if (aClass.parentPkg.cpName.contains("sun"))
  287. System.err.println(aClass.parentPkg.cpName);
  288. */
  289. }
  290. }
  291. public void AddImportToParentImports() {
  292. PackageDesc myPkg = this.parentPkg;
  293. for (PackageDesc pkg : this.imports) {
  294. if (!myPkg.pkgImports.contains(pkg)) {
  295. myPkg.pkgImports.add(pkg);// pkg should have been already blamed?
  296. if (VERBOSE)
  297. System.out.printf(
  298. "Adding %s to import list of package %s, blame %s\n",
  299. pkg.name, myPkg.name,
  300. pkg.blameStr());
  301. //pkg.blame == null? "null" : pkg.blame.toString());
  302. }
  303. }
  304. }
  305. public boolean ReadPkgClassFile(File cFile) throws IOException {
  306. boolean result;
  307. try (DataInputStream in = new DataInputStream(new FileInputStream(cFile))) {
  308. if (verbose) {
  309. System.out.println("Reading Pkg Class File <"+this.javaName+">");
  310. }
  311. this.parentPkg.set(Util.CURRENT);
  312. result = this.ReadClassFileDetails(in);
  313. if (result)
  314. this.parentPkg.set(Util.FROMCLS);
  315. }
  316. return result;
  317. }
  318. public boolean ReadJarClassFile(InputStream stream) throws IOException {
  319. boolean result;
  320. try (DataInputStream in = new DataInputStream(stream)) {
  321. if (verbose) {
  322. System.out.println("Reading Jar Class File <"+qualName+">");
  323. }
  324. this.parentPkg.set(Util.CURRENT);
  325. result = this.ReadClassFileDetails(in);
  326. if (result)
  327. this.parentPkg.set(Util.FROMJAR);
  328. this.parentPkg.clear(Util.CURRENT);
  329. }
  330. return result;
  331. }
  332. public void PrintClassFile() {
  333. int i;
  334. System.out.println("ClassFile for " + qualName);
  335. cp.PrintConstantPool();
  336. System.out.print("THIS CLASS = ");
  337. System.out.print(ConstantPool.GetAccessString(access));
  338. System.out.println(qualName);
  339. if (superClass != null) {
  340. System.out.println("SUPERCLASS = " + superClass.qualName);
  341. }
  342. System.out.println("INTERFACES IMPLEMENTED");
  343. for (i = 0; i < interfaces.length; i++) {
  344. System.out.println(" " + interfaces[i].qualName);
  345. }
  346. System.out.println("FIELDS");
  347. this.fieldList.forEach((fInfo) -> {
  348. System.out.println(" " + fInfo.toString() + ";");
  349. });
  350. System.out.println("METHODS");
  351. this.methodList.forEach((mInfo) -> {
  352. System.out.println(" " + mInfo.toString());
  353. });
  354. System.out.println();
  355. }
  356. public void Diag() {
  357. System.out.println("CLASSDESC");
  358. System.out.println("name = " + name);
  359. System.out.println("javaName = " + javaName);
  360. System.out.println("qualName = " + qualName);
  361. System.out.println();
  362. }
  363. private static void AddField(FieldInfo f,HashMap<String,MemberInfo> scope) throws IOException {
  364. int fNo = 1;
  365. String origName = f.name;
  366. while (scope.containsKey(f.name)) {
  367. f.name = origName + String.valueOf(fNo);
  368. fNo++;
  369. }
  370. scope.put(f.name,f);
  371. }
  372. private static void MakeMethodName(MethodInfo meth) {
  373. if (meth.isInitProc) {
  374. meth.userName = "Init";
  375. } else {
  376. meth.userName = meth.name;
  377. }
  378. }
  379. private static void AddMethod(MethodInfo meth, HashMap<String,MemberInfo> scope)
  380. throws IOException {
  381. int methNo = 1;
  382. if (meth.userName == null) { MakeMethodName(meth); }
  383. String origName = meth.userName;
  384. while (scope.containsKey(meth.userName)) {
  385. meth.userName = origName + String.valueOf(methNo);
  386. methNo++;
  387. }
  388. scope.put(meth.userName,meth);
  389. }
  390. public void MakeJavaName() {
  391. this.javaName = qualName.replace(Util.FWDSLSH,Util.JAVADOT); // '/' --> '.'
  392. this.objName = javaName.substring(javaName.lastIndexOf(Util.JAVADOT)+1);
  393. this.name = javaName.replace(Util.JAVADOT,Util.LOWLINE); // '.' --> '_'
  394. }
  395. private void AddInterfaceImports(ClassDesc aClass) {
  396. // if (interfaces.length > 0) {
  397. if (interfaces != null && interfaces.length > 0) {
  398. for (ClassDesc intf : interfaces) {
  399. aClass.AddImportToClass(intf);
  400. intf.AddInterfaceImports(aClass);
  401. }
  402. }
  403. }
  404. public void GetSuperImports() {
  405. if (done) {
  406. return;
  407. }
  408. if (verbose) {
  409. System.out.println("GetSuperImports of " + javaName);
  410. }
  411. if (isInterface) {
  412. AddInterfaceImports(this);
  413. }
  414. if (this.superClass != null) {
  415. if (!this.superClass.done) {
  416. this.superClass.GetSuperImports();
  417. }
  418. }
  419. if (this.methodList.size() > 0) { // guard added
  420. for (MethodInfo mth : methodList) {
  421. MakeMethodName(mth);
  422. if (mth.isExported() && !mth.deprecated) {
  423. if ((!mth.isInitProc) && (!mth.isStatic())) {
  424. MethodInfo meth = GetOverridden(mth, mth.owner);
  425. if (meth != null) {
  426. mth.overridding = true;
  427. }
  428. }
  429. }
  430. }
  431. }
  432. done = true;
  433. }
  434. public void GetSuperFields(HashMap jScope) throws IOException {
  435. if (done) { return; }
  436. if (verbose) {
  437. System.out.println("GetSuperFields of " + this.javaName);
  438. }
  439. if (this.isInterface) {
  440. this.AddInterfaceImports(this);
  441. }
  442. if (this.superClass != null) {
  443. if (!this.superClass.done) {
  444. this.superClass.GetSuperFields(jScope); }
  445. Iterator<String> enum1 = superClass.scope.keySet().iterator();
  446. while (enum1.hasNext()) {
  447. String methName = (String)enum1.next();
  448. this.scope.put(methName, this.superClass.scope.get(methName));
  449. }
  450. }
  451. for (FieldInfo f : this.fieldList) {
  452. if (f.isExported()) {
  453. AddField((FieldInfo)f,scope);
  454. }
  455. }
  456. HashMap<String,MemberInfo> superScope = new HashMap<>();
  457. for (MethodInfo mth : this.methodList) {
  458. this.MakeMethodName(mth);
  459. if (mth.isExported() && !mth.deprecated) {
  460. if (mth.isInitProc) {
  461. AddMethod(mth,superScope);
  462. } else if (mth.isStatic()) {
  463. AddMethod(mth,scope);
  464. } else {
  465. if (this.scope.containsKey(mth.userName)) {
  466. MethodInfo meth = GetOverridden(mth,mth.owner);
  467. if (meth != null) {
  468. mth.overridding = true;
  469. mth.userName = meth.userName;
  470. this.scope.remove(mth.userName);
  471. this.scope.put(mth.userName,mth);
  472. } else {
  473. AddMethod(mth,this.scope);
  474. }
  475. } else {
  476. AddMethod(mth,this.scope);
  477. }
  478. }
  479. }
  480. }
  481. done = true;
  482. }
  483. private static MethodInfo GetOverridden(MethodInfo meth,ClassDesc thisClass) {
  484. ClassDesc aClass = thisClass;
  485. while (aClass.superClass != null) {
  486. aClass = aClass.superClass;
  487. if (aClass.methodList.isEmpty()) { // new guard
  488. for (MethodInfo method : aClass.methodList) {
  489. if (method.name.equals(meth.name)) {
  490. if ((method.signature != null) && (meth.signature != null)) {
  491. if (method.signature.equals(meth.signature)) {
  492. return method;
  493. }
  494. } else if (method.parTypes.length == meth.parTypes.length) {
  495. boolean ok = true;
  496. for (int j = 0; (j < method.parTypes.length) & ok; j++) {
  497. ok = method.parTypes[j] == meth.parTypes[j];
  498. }
  499. if (ok) {
  500. return method;
  501. }
  502. }
  503. }
  504. }
  505. }
  506. }
  507. return null;
  508. }
  509. public void CheckAccess() {
  510. if (ConstantPool.isAbstract(access)) {
  511. System.out.println(" is abstract ");
  512. } else if (ConstantPool.isFinal(access)) {
  513. System.out.println(" is final ");
  514. } else {
  515. System.out.println(" is default");
  516. }
  517. }
  518. public void setRecAtt(int recAtt) {
  519. if (recAtt >= 8) { recAtt -= 8; } else { hasNoArgConstructor = true; }
  520. if (recAtt == absR) {
  521. if (!ConstantPool.isAbstract(access)) {
  522. access = access + ConstantPool.ACC_ABSTRACT;
  523. }
  524. } else if (recAtt == noAtt) {
  525. if (!ConstantPool.isFinal(access)) {
  526. access = access + ConstantPool.ACC_FINAL;
  527. }
  528. }
  529. }
  530. /** Write a class definition to the typelist section of a symbol file
  531. * <p>
  532. * If the <code>writeDetails</code> flag is not true, or the
  533. * class belongs to a different package, then only the type
  534. * ordinal is written. Otherwise a full class API is emitted.
  535. *
  536. * @param out the symbol file output stream
  537. * @param thisPack the package which this symbol file describes
  538. * @throws IOException
  539. */
  540. @Override
  541. public void writeType(DataOutputStream out, PackageDesc thisPack)
  542. throws IOException {
  543. if (objName == null) {
  544. this.MakeJavaName();
  545. }
  546. if (this.parentPkg != thisPack) {
  547. out.writeByte(SymbolFile.fromS);
  548. // Diagnostic error message
  549. if (this.parentPkg.impNum < 0) {
  550. System.err.println("thisPack is " + thisPack.javaName);
  551. System.err.println("impNum is " + this.parentPkg.impNum);
  552. System.err.println("packageDesc " + this.parentPkg.javaName);
  553. System.err.println("objName " + objName);
  554. this.parentPkg.impNum = 0;
  555. }
  556. //
  557. SymbolFile.writeOrd(out, this.parentPkg.impNum);
  558. SymbolFile.writeName(out, access, objName);
  559. } else if (!ConstantPool.isPublic(access)) {
  560. out.writeByte(SymbolFile.fromS);
  561. SymbolFile.writeOrd(out, 0);
  562. SymbolFile.writeName(out, access, objName);
  563. }
  564. if (!this.writeDetails || (this.parentPkg != thisPack)) {
  565. return;
  566. }
  567. out.writeByte(SymbolFile.ptrSy);
  568. SymbolFile.writeOrd(out, outBaseTypeNum);
  569. out.writeByte(SymbolFile.tDefS);
  570. SymbolFile.writeOrd(out, outBaseTypeNum);
  571. out.writeByte(SymbolFile.recSy);
  572. int recAtt = 0;
  573. if (!hasNoArgConstructor) {
  574. recAtt = 8;
  575. }
  576. if (ConstantPool.isFinal(access)) {
  577. out.writeByte(noAtt + recAtt);
  578. } else if (isInterface) {
  579. out.writeByte(iFace + recAtt);
  580. } else if (ConstantPool.isAbstract(access)) {
  581. out.writeByte(absR + recAtt);
  582. } else {
  583. out.writeByte(extR + recAtt);
  584. }
  585. if (isInterface) {
  586. out.writeByte(SymbolFile.truSy);
  587. } else {
  588. out.writeByte(SymbolFile.falSy);
  589. }
  590. if (superClass != null) {
  591. out.writeByte(SymbolFile.basSy);
  592. SymbolFile.writeTypeOrd(out, superClass);
  593. }
  594. //if (interfaces.length > 0) {
  595. if (interfaces != null && interfaces.length > 0) {
  596. out.writeByte(SymbolFile.iFcSy);
  597. for (ClassDesc intf : interfaces) {
  598. out.writeByte(SymbolFile.basSy);
  599. SymbolFile.writeTypeOrd(out, intf);
  600. }
  601. }
  602. if (!this.fieldList.isEmpty()) {
  603. for (FieldInfo field : this.fieldList) {
  604. if (field.isExported() && !field.isStatic()) {
  605. SymbolFile.writeName(out, field.accessFlags, field.name);
  606. SymbolFile.writeTypeOrd(out, field.type);
  607. }
  608. }
  609. }
  610. if (!this.methodList.isEmpty()) {
  611. for (MethodInfo method : this.methodList) {
  612. if (method.isExported() && !method.deprecated
  613. && !method.isStatic() && !method.isInitProc
  614. && !method.isCLInitProc) {
  615. out.writeByte(SymbolFile.mthSy);
  616. // --------------------
  617. // if (methods[i].userName == null) {
  618. // System.out.println("packageDesc " + this.packageDesc.javaName);
  619. // System.out.println("objName " + objName);
  620. // for (int j=0; j < methods.length; j++) {
  621. // System.out.println("Method " + j +
  622. // (methods[i].userName == null ? " null" : methods[j].userName));
  623. // }
  624. // }
  625. // --------------------
  626. SymbolFile.writeName(out, method.accessFlags, method.userName);
  627. int attr = 0;
  628. if (!method.overridding) {
  629. attr = 1;
  630. }
  631. if (method.isAbstract()) {
  632. attr += 2;
  633. } else if (!method.isFinal()) {
  634. attr += 6;
  635. }
  636. out.writeByte(attr);
  637. out.writeByte(0);
  638. /* all java receivers are value mode */
  639. SymbolFile.writeOrd(out, outTypeNum);
  640. SymbolFile.writeString(out, method.name);
  641. SymbolFile.WriteFormalType(method, out);
  642. }
  643. }
  644. }
  645. if (!this.fieldList.isEmpty()) {
  646. for (FieldInfo field : this.fieldList) {
  647. if (field.isConstant()) {
  648. out.writeByte(SymbolFile.conSy);
  649. SymbolFile.writeName(out, field.accessFlags, field.name);
  650. SymbolFile.writeLiteral(out, field.GetConstVal());
  651. } else if (field.isExported() && field.isStatic()) {
  652. out.writeByte(SymbolFile.varSy);
  653. SymbolFile.writeName(out, field.accessFlags, field.name);
  654. SymbolFile.writeTypeOrd(out, field.type);
  655. }
  656. }
  657. }
  658. if (!this.methodList.isEmpty()) {
  659. for (MethodInfo method : this.methodList) {
  660. if (method.isExported() && !method.deprecated
  661. && method.isStatic() && !method.isCLInitProc) {
  662. out.writeByte(SymbolFile.prcSy);
  663. SymbolFile.writeName(out, method.accessFlags, method.userName);
  664. SymbolFile.writeString(out, method.name);
  665. if (method.isInitProc) {
  666. out.writeByte(SymbolFile.truSy);
  667. }
  668. SymbolFile.WriteFormalType(method, out);
  669. }
  670. }
  671. }
  672. out.writeByte(SymbolFile.endRc);
  673. }
  674. }