ソースを参照

New J2cps version with jar-handling code

k-john-gough 8 年 前
コミット
6efea84c53

+ 73 - 43
J2CPS/ArrayDesc.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*                Array Descriptor class for J2CPS                    */
+/*                Array Descriptor class for j2cps                    */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -13,9 +13,19 @@ public class ArrayDesc extends TypeDesc {
   static ArrayDesc[] arrayTypes = new ArrayDesc[10];
   static int numArrayTypes = 0;
 
+  /**
+   *  The type-descriptor of the element type of this array type
+   */
   TypeDesc elemType;
+  /**
+   * The type-descriptor of the type that is a pointer to this array type
+   */
   PtrDesc ptrType;
   int dim = 1;
+  /**
+   *  The type-descriptor of the elements of this
+   *  (possibly multi-dimensional) array type.
+   */
   TypeDesc ultimateElemType;
   public int elemTypeFixUp = 0;
 
@@ -26,65 +36,76 @@ public class ArrayDesc extends TypeDesc {
     writeDetails = true;
   }
 
-  public ArrayDesc (int dimNum,TypeDesc eType,boolean makePtr) {
-    name = "ARRAY OF ";
-    writeDetails = true;
-    for (int i=1; i < dimNum; i++) {
-      name = name + "ARRAY OF ";
-    }
-    name = name + eType.name;
-    typeOrd = TypeDesc.arrT;
-    dim = dimNum;
-    elemType = eType;
-    ultimateElemType = eType; 
-    if (makePtr) {
-      ptrType = new PtrDesc(this);
+    public ArrayDesc(int dimNum,TypeDesc eType,boolean makePtr) {
+        this.name = "ARRAY OF ";
+        this.writeDetails = true;
+        for (int i=1; i < dimNum; i++) {
+            this.name += "ARRAY OF ";
+        }
+        this.name += eType.name;
+        this.typeOrd = TypeDesc.arrT;
+        this.dim = dimNum;
+        this.elemType = (dimNum == 1 ? eType : null);
+        this.ultimateElemType = eType; 
+        if (makePtr) {
+            this.ptrType = new PtrDesc(this);
+        }
     }
-  }
 
   public void SetPtrType(PtrDesc ptrTy) {
     ptrType = ptrTy;
   }
 
-  public static TypeDesc GetArrayType(String sig,int start,boolean getPtr) {
+  public static TypeDesc GetArrayTypeFromSig(
+          String sig,int start,boolean getPtr) {
     TypeDesc uEType;
     if (sig.charAt(start) != '[') {
-      System.out.println(sig.substring(start) + " is not an array type!");
-      System.exit(1);
+        System.out.println(sig.substring(start) + " is not an array type!");
+        System.exit(1);
     }
     int dimCount = 0, ix = start;
-    while (sig.charAt(ix) == '[') { ix++; dimCount++; }
+    while (sig.charAt(ix) == '[') { 
+        ix++; dimCount++; 
+    }
     uEType = TypeDesc.GetType(sig,ix);
-    ArrayDesc thisArr = FindArrayType(dimCount,uEType,getPtr);
-    dimCount--;
+    ArrayDesc thisArr = FindOrCreateArrayType(dimCount,uEType,getPtr);
+    
     ArrayDesc arrD = thisArr;
-    while (dimCount > 1) {
-      arrD.elemType = FindArrayType(dimCount,uEType,true);
-      if (arrD.elemType instanceof ArrayDesc) {
-        arrD = (ArrayDesc)arrD.elemType;
-      }
-      dimCount--; 
+    while (--dimCount >= 1) {
+        arrD.elemType = FindOrCreateArrayType(dimCount,uEType,true);
+        if (arrD.elemType instanceof ArrayDesc) {
+          arrD = (ArrayDesc)arrD.elemType;
+        }
     }
     arrD.elemType = uEType;
-    if (getPtr) { return thisArr.ptrType; } else { return thisArr; }
+    if (getPtr)
+        return thisArr.ptrType;
+    else
+        return thisArr;
   }
 
-  public static ArrayDesc FindArrayType(int dimNum, TypeDesc eType,
-                                                               boolean mkPtr) {
+  public static ArrayDesc FindOrCreateArrayType(
+          int dimNum, TypeDesc eType, boolean mkPtr) {
+    //
+    //  Try to find existing, identical array descriptor 
+    //
     for (int i=0; i < numArrayTypes; i++) {
-      if ((arrayTypes[i].dim == dimNum) && 
-          (arrayTypes[i].ultimateElemType == eType))  {
-        if (mkPtr && arrayTypes[i].ptrType == null) { 
-          arrayTypes[i].ptrType = new PtrDesc(arrayTypes[i]);
+        if ((arrayTypes[i].dim == dimNum) && 
+            (arrayTypes[i].ultimateElemType == eType))  
+        {
+            if (mkPtr && arrayTypes[i].ptrType == null) 
+                arrayTypes[i].ptrType = new PtrDesc(arrayTypes[i]);
+            return arrayTypes[i];
         }
-        return arrayTypes[i];
-      }
     }
+    //
+    //  Otherwise allocate a new array descriptor
+    //
     arrayTypes[numArrayTypes++] = new ArrayDesc(dimNum,eType,mkPtr);
     if (numArrayTypes == arrayTypes.length) {
-      ArrayDesc[] temp = arrayTypes;
-      arrayTypes = new ArrayDesc[numArrayTypes * 2];
-      System.arraycopy(temp, 0, arrayTypes, 0, numArrayTypes);
+        ArrayDesc[] temp = arrayTypes;
+        arrayTypes = new ArrayDesc[numArrayTypes * 2];
+        System.arraycopy(temp, 0, arrayTypes, 0, numArrayTypes);
     }
     return arrayTypes[numArrayTypes-1];
   }
@@ -94,6 +115,15 @@ public class ArrayDesc extends TypeDesc {
     return 'a' + elemType.getTypeMnemonic();
   }
 
+  /** Write an array definition the typelist section of a symbol file
+   * <p>
+   * An array type declaration consists of only an array marker
+   * followed by the type-ordinal of the element type.
+   * 
+   * @param out  the symbol file output stream
+   * @param thisPack the package which this symbol file describes
+   * @throws IOException 
+   */
   @Override
   public void writeType(DataOutputStream out, PackageDesc thisPack) 
                                                           throws IOException {
@@ -103,9 +133,9 @@ public class ArrayDesc extends TypeDesc {
     out.writeByte(SymbolFile.endAr); 
   }
 
-  public void AddImport(ClassDesc thisClass) {
+  public void AddImportToArray(ClassDesc thisClass) {
     if (ultimateElemType instanceof ClassDesc) {
-      thisClass.AddImport((ClassDesc)ultimateElemType);
+      thisClass.AddImportToClass((ClassDesc)ultimateElemType);
     }
   }
 

+ 13 - 13
J2CPS/CPWords.java

@@ -1,27 +1,27 @@
 /**********************************************************************/
 /*      Class defining the Component Pascal reserved words            */ 
 /*                                                                    */
-/*                    (c) copyright QUT                               */
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.util.HashMap;
 
 public class CPWords {
 
-  private static final String[] reservedWords = 
-    {"ARRAY","BEGIN","BY","CASE","CLOSE","CONST","DIV","DO","ELSE",
-     "ELSIF","END","EXIT","FOR","IF","IMPORT","IN","IS","LOOP","MOD",
-     "MODULE","NIL","OF","OR","OUT","POINTER","PROCEDURE","RECORD",
-     "REPEAT","RETURN","THEN","TO","TYPE","UNTIL","VAR","WHILE","WITH"};
+    private static final String[] reservedWords = 
+      {"ARRAY","BEGIN","BY","CASE","CLOSE","CONST","DIV","DO","ELSE",
+       "ELSIF","END","EXIT","FOR","IF","IMPORT","IN","IS","LOOP","MOD",
+       "MODULE","NIL","OF","OR","OUT","POINTER","PROCEDURE","RECORD",
+       "REPEAT","RETURN","THEN","TO","TYPE","UNTIL","VAR","WHILE","WITH"};
 
-  public static HashMap<String,String> InitResWords() {
-    HashMap<String,String> hTable = new HashMap<String,String>();
-    for (int i=0; i < reservedWords.length; i++) {
-      hTable.put(reservedWords[i],reservedWords[i]);
+    public static HashMap<String,String> InitResWords() {
+        HashMap<String,String> hTable = new HashMap<>();
+            for (String reservedWord : reservedWords) {
+                hTable.put(reservedWord, reservedWord);
+            }
+        return hTable;
     }
-    return hTable;
-  }
 
 
 }

+ 576 - 416
J2CPS/ClassDesc.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*                Class Descriptor class for J2CPS                    */
+/*                Class Descriptor class for j2cps                    */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.io.*;
 import java.util.ArrayList;
@@ -12,206 +12,353 @@ import java.util.Iterator;
 
 public class ClassDesc extends TypeDesc  {
 
-  private static final int MAJOR_VERSION = 45;
-  private static final int MINOR_VERSION = 3;
-  private static final char qSepCh = '/';
-  private static final char jSepCh = '.';
-  private static final char nSepCh = '_';
-  private static HashMap<String,ClassDesc> classList = new HashMap<String,ClassDesc>();
-  private static final String jlString = "java.lang.String";
-  private static final String jlObject = "java.lang.Object";
+    // private static final int MAJOR_VERSION = 45;
+    // private static final int MINOR_VERSION = 3;
+    
+    private static HashMap<String,ClassDesc> classMap = new HashMap<>();
+    private static final String jlString = "java.lang.String";
+    private static final String jlObject = "java.lang.Object";
 
-  private static final int noAtt = 0;  // no record attribute in cp
-  private static final int absR  = 1;  // ABSTRACT record in cp
-  private static final int limR  = 2;  // LIMITED record in cp
-  private static final int extR  = 3;  // EXTENSIBLE record in cp
-  private static final int iFace = 4;  // JAVA interface 
-  private static HashMap<String,String> resWords = CPWords.InitResWords();
+    private static final int noAtt = 0;  // no record attribute in cp
+    private static final int absR  = 1;  // ABSTRACT record in cp
+    private static final int limR  = 2;  // LIMITED record in cp
+                                         // No equivalent in java!
+    private static final int extR  = 3;  // EXTENSIBLE record in cp
+    private static final int iFace = 4;  // JAVA interface 
 
-  public static boolean verbose = false;
-  public static boolean overloadedNames = true;
+    public static boolean useJar = false;
+    public static boolean verbose = false;
+    public static boolean VERBOSE = false;
+    public static boolean summary = false;
+    public static boolean nocpsym = false;
 
+    @Override
+    public String toString() {    
+        if (this.name != null)
+            return this.name;
+        else
+            return "anon-ClassDesc";
+    }
+    
+    ConstantPool cp;
+    ClassDesc superClass;
+    int access, outBaseTypeNum=0, superNum=0, numInts=0, intNums[];
+    public String 
+            /**
+             * Qualified name of the class e.g. java/lang/Object
+             */
+            qualName, 
+            /**
+             * Java language name of the class e.g. java.lang.Object
+             */
+            javaName,
+            /**
+             *  Unqualified name of the class e.g. Object
+             */
+            objName;
+    
+    ClassDesc[] interfaces;
+    
+    boolean 
+            isInterface = false, 
+            read = false, 
+            done = false;
+    
+    public boolean hasNoArgConstructor = false;
+    
+    /**
+     *  Packages imported by this class
+     */
+    public ArrayList<PackageDesc> imports = new ArrayList<>();
+    
+    /**
+     *  Fields declared in this class
+     */
+    public ArrayList<FieldInfo> fieldList = new ArrayList<>();
+    
+    /**
+     *  Methods defined in this class
+     */
+    public ArrayList<MethodInfo> methodList = new ArrayList<>();
+    
+    /**
+     *  HashMap of members declared locally in this class.
+     */
+    HashMap<String,MemberInfo> scope = new HashMap<>();
 
-  ConstantPool cp;
-  ClassDesc superClass;
-  int access, outBaseTypeNum=0, superNum=0, numInts=0, intNums[];
-  public String qualName, javaName, objName;
-  ClassDesc interfaces[];
-  FieldInfo fields[];
-  MethodInfo methods[];
-  boolean isInterface = false, read = false, done = false;
-  public boolean hasNoArgConstructor = false;
-  public ArrayList imports = new ArrayList();
-  public ArrayList fieldList = new ArrayList();
-  public ArrayList methodList = new ArrayList();
-  HashMap scope = new HashMap();
-
-  public ClassDesc() {
-    typeOrd = TypeDesc.classT;
-  }
-
+    public ClassDesc() {
+      typeOrd = TypeDesc.classT;
+    }
+    
+    /**
+     * Find an existing ClassDescriptor object with the given
+     * string name, or create one in the supplied package.
+     * <p>
+     * If the pack parameter is null, the package is found (or 
+     * created) based on the prefix of the string class name.
+     * @param name the full name of the class  
+     * @param pack the package descriptor, or null if not known
+     * @return     the (possibly newly created) class descriptor
+     */
     public static ClassDesc GetClassDesc(String name, PackageDesc pack) {
-    if (name.indexOf(jSepCh) != -1) { name = name.replace(jSepCh,qSepCh); }
-    ClassDesc aClass = (ClassDesc)classList.get(name);
-    if (aClass == null) {
+        if (name.indexOf(Util.JAVADOT) != -1) { 
+            name = name.replace(Util.JAVADOT,Util.FWDSLSH); 
+        }
+        ClassDesc aClass = (ClassDesc)classMap.get(name);
+        if (aClass == null) {
             aClass = ClassDesc.MakeNewClassDesc(name,pack);
         } 
-    return aClass;
-  }
+        return aClass;
+    }
 
-  public static ClassDesc MakeNewClassDesc(String name, PackageDesc pack) {
-      ClassDesc desc = new ClassDesc(name, pack);
-      desc.MakeJavaName();
-      classList.put(desc.qualName, desc);
-      return desc;
-  }
-  
-  private ClassDesc(String thisName, PackageDesc pack) {
-    typeOrd = TypeDesc.classT;
-    qualName = thisName;
-    if (pack == null) {
-          packageDesc = PackageDesc.getClassPackage(qualName);
-      }
-    else {
-          packageDesc = pack;
-      } 
-  }
+    /**
+     * Create a new class descriptor with the given name, and added to
+     * the given package descriptor.
+     * <p>
+     * If the pack parameter is null, create a new package descriptor 
+     * with a name inferred from the full class name, add the new package
+     * to the package list, add the new class to the new package.
+     * @param name the full name of the new class
+     * @param pack the package to which the new class belongs, or null
+     * @return the newly created class descriptor.
+     */
+    public static ClassDesc MakeNewClassDesc(String name, PackageDesc pack) {
+        ClassDesc desc = new ClassDesc(name, pack);
+        desc.MakeJavaName();
+        classMap.put(desc.qualName, desc);
+        return desc;
+    }
 
-  public ClassDesc(int inNum) {
-    inBaseTypeNum = inNum; 
-  }
+    private ClassDesc(String thisName, PackageDesc pack) {
+        this.typeOrd = TypeDesc.classT;
+        this.qualName = thisName;
+        if (pack == null) {
+            this.parentPkg = PackageDesc.getClassPackage(this.qualName);
+        } else {
+            this.parentPkg = pack;
+        } 
+    }
+
+    public ClassDesc(int inNum) { this.inBaseTypeNum = inNum; }
 
     @Override
-  public String getTypeMnemonic() {
-    if (javaName.equals(jlString)) {
-      return "S";
-    } else if (javaName.equals(jlObject)) {
-      return "O";
-    } else {
-      return "o";
+    public String getTypeMnemonic() {
+        switch (javaName) {
+            case jlString:
+                return "S";
+            case jlObject:
+                return "O";
+            default:
+                return "o";
+        }
     }
-  }
 
-  private boolean ReadClassFileDetails(DataInputStream stream)
-                                                       throws IOException {
-    read = true;
-    int count;
-    ClassRef tmp;
-    /* read and check the magic number */
-    if (stream.readInt() != 0xCAFEBABE) {
-      System.out.println("Bad magic number");
-      System.exit(0);
-    }
-    /* read and check the minor and major version numbers  */
-    int minorVersion = stream.readUnsignedShort();
-//   /* if (minorVersion > MINOR_VERSION) {
-//	System.out.println("Unsupported Java minor version " +
-//				String.valueOf(minorVersion));
-//	System.exit(0);
-//    }
-//*/
-    int majorVersion = stream.readUnsignedShort();
-// /*   if (majorVersion != MAJOR_VERSION) {
-//      System.out.println("Unsupported Java major version " + 
-//			 String.valueOf(majorVersion));
-//      System.exit(0);
-//    }
-//*/
-    cp = new ConstantPool(stream);
-    access = stream.readUnsignedShort();
-    // Experimental code to only transform packages that
-    // are reachable from classes that are not private.
-    // Under consideration for next version, controlled 
-    // by a command line option.
-//    if (!ConstantPool.isPublic(access) && !ConstantPool.isProtected(access)) {
-//        cp.EmptyConstantPool();
-//        return true;
-//    }
-    // End experimental code
-    ClassRef thisClass = (ClassRef) cp.Get(stream.readUnsignedShort());
-    String clName = thisClass.GetName();
-    if (!qualName.equals(clName)) {
-      if (clName.startsWith(packageDesc.name)) {
-        if (verbose) { System.out.println(clName + " IS PART OF PACKAGE " + 
-                                          packageDesc.name + " but name is not "
-                                          + qualName); }
-      } else {
-        if (verbose) { System.out.println(clName + " IS NOT PART OF PACKAGE " + 
-                         packageDesc.name + "  qualName = " + qualName); }
-        packageDesc = PackageDesc.getClassPackage(qualName);
-        return false;
-      } 
-      classList.remove(qualName);
-      qualName = clName;
-      this.MakeJavaName();
-      classList.put(qualName,this);
-    }
-    isInterface = ConstantPool.isInterface(access);
-    int superIx = stream.readUnsignedShort();
-    if (superIx > 0) {
-      tmp = (ClassRef) cp.Get(superIx);
-      superClass = tmp.GetClassDesc();
-    }
-    /* get the interfaces implemented by this class */
-    count = stream.readUnsignedShort();
-    interfaces = new ClassDesc[count];
-    for (int i = 0; i < count; i++) {
-      tmp = (ClassRef) cp.Get(stream.readUnsignedShort());
-      interfaces[i] = tmp.GetClassDesc();
-      AddImport(interfaces[i]);
-    }
-    /* get the fields for this class */ 
-    count = stream.readUnsignedShort();
-    if (verbose) {System.out.println("There are " + count + " fields");}
-    fields = new FieldInfo[count];
-    for (int i = 0; i < count; i++) {
-      fields[i] = new FieldInfo(cp,stream,this);
-    }
-    /* get the methods for this class */ 
-    count = stream.readUnsignedShort();
-    if (verbose) { System.out.println("There are " + count + " methods"); }
-    methods = new MethodInfo[count];
-    for (int i = 0; i < count; i++) {
-      methods[i] = new MethodInfo(cp,stream,this);
-    }
-    /* ignore the rest of the classfile (ie. the attributes) */ 
-    if (verbose) { System.out.println("Finished reading class file"); }
-    if (verbose) { PrintClassFile(); Diag(); }
-    cp.EmptyConstantPool();
-    cp = null;
-    return true;
-  }
-  
-  public void TryImport(TypeDesc type){
-      if (type instanceof ClassDesc) {
-          this.AddImport((ClassDesc)type);
+    /**
+     *  Read the details of the class.
+     *  <p> 
+     *  Parse the class file attached to the DataInputStream,
+     *  creating new type, class and package descriptors for newly
+     *  identified type names.
+     * @param stream The input data stream. Could be either
+     *               a FileStream or a zip stream from a jar file.
+     * @return true if parse was successful.
+     * @throws IOException 
+     */
+    private boolean ReadClassFileDetails(DataInputStream stream)
+                                                         throws IOException {
+      read = true;
+      int count;
+      ClassRef tmp;
+      /* read and check the magic number */
+      if (stream.readInt() != 0xCAFEBABE) {
+        System.out.println("Bad magic number");
+        System.exit(0);
       }
-      else if (type instanceof ArrayDesc) {
-          this.TryImport(((ArrayDesc)type).elemType);
+      /* read and check the minor and major version numbers  */
+      int minorVersion = stream.readUnsignedShort();
+  //   /* if (minorVersion > MINOR_VERSION) {
+  //	System.out.println("Unsupported Java minor version " +
+  //				String.valueOf(minorVersion));
+  //	System.exit(0);
+  //    }
+  //*/
+      int majorVersion = stream.readUnsignedShort();
+  // /*   if (majorVersion != MAJOR_VERSION) {
+  //      System.out.println("Unsupported Java major version " + 
+  //			 String.valueOf(majorVersion));
+  //      System.exit(0);
+  //    }
+  //*/
+      cp = new ConstantPool(stream);
+      access = stream.readUnsignedShort();
+      // Experimental code to only transform packages that
+      // are reachable from classes that are not private.
+      // Under consideration for next version, controlled 
+      // by a command line option.
+      PackageDesc.tot++;
+      if (!ConstantPool.isPublic(access) && !ConstantPool.isProtected(access)) {
+         cp.EmptyConstantPool();
+         PackageDesc.pub++;
+         return true;
       }
-      else if (type instanceof PtrDesc) {
-          ((PtrDesc)type).AddImport(this);
+      // End experimental code
+
+      String clName = ((ClassRef) cp.Get(stream.readUnsignedShort())).GetName();
+      if (!qualName.equals(clName)) {
+        if (clName.startsWith(parentPkg.name)) {
+          if (verbose) { System.out.println(clName + " IS PART OF PACKAGE " + 
+                                            parentPkg.name + " but name is not "
+                                            + qualName); }
+        } else {
+            System.err.println(clName + " IS NOT PART OF PACKAGE " + 
+                           parentPkg.name + "  qualName = " + qualName);
+            parentPkg = PackageDesc.getClassPackage(qualName);
+            return false;
+        } 
+        classMap.remove(qualName);
+        qualName = clName;
+        this.MakeJavaName();
+        ClassDesc put = classMap.put(qualName,this);
       }
-      
-  }
+      isInterface = ConstantPool.isInterface(access);
+      int superIx = stream.readUnsignedShort();
+      if (superIx > 0) {
+        tmp = (ClassRef) cp.Get(superIx);
+        superClass = tmp.GetClassDesc();
+        //
+        //  If superclass is not from the current package
+        //  mark the superclass package as needed for API.
+        //
+        if (superClass.parentPkg != this.parentPkg) {
+            //superClass.parentPkg.set(Util.APINEEDS);
+            superClass.blame = this;
+            this.AddImportToClass(superClass);
+        }
+      }
+      /* get the interfaces implemented by this class */
+      count = stream.readUnsignedShort();
+      interfaces = new ClassDesc[count];
+      for (int i = 0; i < count; i++) {
+        tmp = (ClassRef) cp.Get(stream.readUnsignedShort());
+        ClassDesc theInterface = tmp.GetClassDesc();
+        //theInterface.parentPkg.set(Util.APINEEDS);
+        this.AddImportToClass(theInterface);
+        interfaces[i] = theInterface;
+      }
+      /* get the fields for this class */ 
+      count = stream.readUnsignedShort();
+      if (verbose) 
+          System.out.println(count != 1 ?
+                  "There are " + count + " fields" :
+                  "There is one field");
+      for (int i = 0; i < count; i++ ) {
+        FieldInfo fInfo = new FieldInfo(cp,stream,this);
+        // 
+        //  The package to which this class belongs
+        //  must place the package of this field's type
+        //  on the import list IFF:
+        //   *  the field is public or protected AND
+        //   *  the field's package is not that of thisClass
+        //
+        if (fInfo.isExported()) {
+            this.fieldList.add(fInfo);
+            if (fInfo.type.parentPkg != this.parentPkg) {
+                fInfo.type.blame = fInfo;
+                this.TryImport(fInfo.type);
+            }
+        }
+      }
+      /* get the methods for this class */ 
+      count = stream.readUnsignedShort();
+      if (verbose) 
+          System.out.println(count != 1 ?
+                  "There are " + count + " methods" :
+                  "There is one method");
+      for (int i = 0; i < count; i++ ) {
+        MethodInfo mInfo = new MethodInfo(cp,stream,this);
+        if (mInfo.isExported())
+            this.methodList.add(mInfo);
+      }
+      /* ignore the rest of the classfile (ie. the attributes) */ 
+      if (verbose) { System.out.println("Finished reading class file"); }
+      if (VERBOSE) { /*PrintClassFile();*/ Diag(); }
+      this.AddImportToParentImports();
+      cp.EmptyConstantPool();
+      cp = null;
+      return true;
+    }
+
+    public void TryImport(TypeDesc type){ 
+        if (type instanceof ClassDesc) {
+            this.AddImportToClass((ClassDesc)type);
+        }
+        else if (type instanceof ArrayDesc) {
+            ((ArrayDesc)type).elemType.blame = type.blame;
+            this.TryImport(((ArrayDesc)type).elemType); // Recursive!
+        }
+        else if (type instanceof PtrDesc) {
+            ((PtrDesc)type).AddImportToPtr(this);
+        }
 
-  public void AddImport(ClassDesc aClass) {
-   if ((aClass != this) && (aClass.packageDesc != this.packageDesc) &&
-        (!imports.contains(aClass.packageDesc))) {
-      imports.add(aClass.packageDesc);
     }
-  }
 
-  public boolean ReadClassFile(File cFile) throws IOException {
-    boolean result;
-    DataInputStream in = new DataInputStream(new FileInputStream(cFile));
-    if (verbose) { System.out.println("Reading Class File <"+qualName+">"); }
-    result = ReadClassFileDetails(in);
-    // close the file or run out of file handles!
-    in.close();
-    return result;
-  }
+    public void AddImportToClass(ClassDesc aClass) {
+     if ((aClass != this) && (aClass.parentPkg != this.parentPkg) &&
+          (!this.imports.contains(aClass.parentPkg))) {
+        aClass.parentPkg.set(Util.APINEEDS);
+        this.imports.add(aClass.parentPkg);
+        aClass.parentPkg.blame = aClass.blame;
+        /*        
+        if (aClass.parentPkg.cpName.contains("sun"))
+            System.err.println(aClass.parentPkg.cpName);
+        */
+        }
+    }
+    
+    public void AddImportToParentImports() {
+        PackageDesc myPkg = this.parentPkg;
+        for (PackageDesc pkg : this.imports) {
+            if (!myPkg.pkgImports.contains(pkg)) {
+                myPkg.pkgImports.add(pkg);// pkg should have been already blamed?
+                if (VERBOSE)
+                    System.out.printf(
+                            "Adding %s to import list of package %s, blame %s\n",
+                            pkg.name, myPkg.name,
+                            pkg.blameStr());
+                            //pkg.blame == null? "null" : pkg.blame.toString());
+            }
+        }
+    }
 
+    public boolean ReadPkgClassFile(File cFile) throws IOException {
+        boolean result;
+        try (DataInputStream in = new DataInputStream(new FileInputStream(cFile))) {
+            if (verbose) { 
+                System.out.println("Reading Pkg Class File <"+this.javaName+">"); 
+            }
+            this.parentPkg.set(Util.CURRENT);
+            result = this.ReadClassFileDetails(in);
+            if (result)
+                this.parentPkg.set(Util.FROMCLS);
+        }
+        return result;
+    }
+  
+    public boolean ReadJarClassFile(InputStream stream) throws IOException {
+        boolean result;
+        try (DataInputStream in = new DataInputStream(stream)) {
+            if (verbose) { 
+                System.out.println("Reading Jar Class File <"+qualName+">"); 
+            }
+            this.parentPkg.set(Util.CURRENT);
+            result = this.ReadClassFileDetails(in);
+            if (result)
+                this.parentPkg.set(Util.FROMJAR);
+            this.parentPkg.clear(Util.CURRENT);
+        }    
+        return result;      
+    }
+  
   public void PrintClassFile() {
     int i;
     System.out.println("ClassFile for " + qualName);
@@ -227,13 +374,13 @@ public class ClassDesc extends TypeDesc  {
       System.out.println("  " + interfaces[i].qualName);
     }
     System.out.println("FIELDS");
-    for (i=0; i < fields.length; i++) {
-      System.out.println("  " + fields[i].toString() + ";");
-    }
+    this.fieldList.forEach((fInfo) -> {
+            System.out.println("  " + fInfo.toString() + ";");
+        });
     System.out.println("METHODS");
-    for (i=0; i < methods.length; i++) {
-      System.out.println("  " + methods[i].toString());
-    }
+    this.methodList.forEach((mInfo) -> {
+            System.out.println("  " + mInfo.toString());
+        });
     System.out.println();
   }
 
@@ -245,7 +392,7 @@ public class ClassDesc extends TypeDesc  {
     System.out.println();
   }
 
-  private static void AddField(FieldInfo f,HashMap scope) throws IOException {
+  private static void AddField(FieldInfo f,HashMap<String,MemberInfo> scope) throws IOException {
     int fNo = 1;
     String origName = f.name;
     while (scope.containsKey(f.name)) {
@@ -255,44 +402,15 @@ public class ClassDesc extends TypeDesc  {
     scope.put(f.name,f);
   }
 
-  private static int HashSignature(MethodInfo meth) {
-    int tot=0, sum=0, parNum = 1, end = meth.signature.indexOf(')');
-    boolean inPar = false;
-    for (int i=1; i < end; i++) {
-      char c = meth.signature.charAt(i);
-      sum += sum;
-      if (sum < 0) { sum++; }
-      sum += parNum * (int)c;
-      if (!inPar) {
-        if (c == 'L') { inPar = true; }
-        else if (c != '[')  { parNum++; tot += sum; } 
-      } else if (c == ';')  { inPar = false; parNum++; tot += sum; }
-    }
-    int hash = tot % 4099;
-    if (hash < 0) { hash = -hash; }
-    return hash;
-  }
-
   private static void MakeMethodName(MethodInfo meth) {
-    boolean needHash = false;
-    if (meth.isInitProc) { meth.userName = "Init";
+    if (meth.isInitProc) { 
+        meth.userName = "Init";
     } else {
       meth.userName = meth.name;
     }
-    if (overloadedNames) { return; }
-    if (meth.parTypes.length > 0) { meth.userName += "_"; }
-    for (int i=0; i < meth.parTypes.length; i++) {
-      String next = meth.parTypes[i].getTypeMnemonic();
-      if (next.endsWith("o")) { needHash = true; }
-      meth.userName += next;
-    }
-    if (needHash) {
-      int hash = HashSignature(meth);
-      meth.userName += ("_" + String.valueOf(hash)); 
-    }
   }
 
-  private static void AddMethod(MethodInfo meth, HashMap<String,MethodInfo> scope) 
+  private static void AddMethod(MethodInfo meth, HashMap<String,MemberInfo> scope) 
                                                           throws IOException {
     int methNo = 1;
     if (meth.userName == null) { MakeMethodName(meth); }
@@ -305,111 +423,124 @@ public class ClassDesc extends TypeDesc  {
   }
 
   public void MakeJavaName() {
-    javaName = qualName.replace(qSepCh,jSepCh);
-    objName = javaName.substring(javaName.lastIndexOf(jSepCh)+1);
-    name = javaName.replace(jSepCh,nSepCh);
+    this.javaName = qualName.replace(Util.FWDSLSH,Util.JAVADOT); // '/' --> '.'
+    this.objName = javaName.substring(javaName.lastIndexOf(Util.JAVADOT)+1);
+    this.name = javaName.replace(Util.JAVADOT,Util.LOWLINE); // '.' --> '_'
   }
 
   private void AddInterfaceImports(ClassDesc aClass) {
     // if (interfaces.length > 0) {
     if (interfaces != null && interfaces.length > 0) {
-      for (int i=0; i < interfaces.length; i++) {
-        aClass.AddImport(interfaces[i]);
-        interfaces[i].AddInterfaceImports(aClass);
-      }
+        for (ClassDesc intf : interfaces) {
+            aClass.AddImportToClass(intf);
+            intf.AddInterfaceImports(aClass);
+        }
     }
   }
 
-  public void GetSuperImports() {
-    if (done) { return; }
-    if (verbose) { System.out.println("GetSuperImports of " + javaName); }
-    if (isInterface) { AddInterfaceImports(this); }
-    if (superClass != null) {
-      if (!superClass.done) { superClass.GetSuperImports(); }
-    }
-    if (methods != null) { // guard added
-      for (int i=0; i < methods.length; i++) {
-        MethodInfo mth = methods[i];
-        MakeMethodName(mth);
-        if (mth.isExported() && !mth.deprecated) {
-          if ((!mth.isInitProc) && (!mth.isStatic())) {
-            MethodInfo meth = GetOverridden(mth,mth.owner);
-            if (meth != null) { mth.overridding = true; }
-          }
+    public void GetSuperImports() {
+        if (done) {
+            return;
         }
-      }
+        if (verbose) {
+            System.out.println("GetSuperImports of " + javaName);
+        }
+        if (isInterface) {
+            AddInterfaceImports(this);
+        }
+        if (this.superClass != null) {
+            if (!this.superClass.done) {
+                this.superClass.GetSuperImports();
+            }
+        }
+        if (this.methodList.size() > 0) { // guard added
+            for (MethodInfo mth : methodList) {
+                MakeMethodName(mth);
+                if (mth.isExported() && !mth.deprecated) {
+                    if ((!mth.isInitProc) && (!mth.isStatic())) {
+                        MethodInfo meth = GetOverridden(mth, mth.owner);
+                        if (meth != null) {
+                            mth.overridding = true;
+                        }
+                    }
+                }
+            }
+        }
+        done = true;
     }
-    done = true;
-  }
 
-  public void GetSuperFields(HashMap jScope) throws IOException {
-    if (done) { return; }
-    if (verbose) { System.out.println("GetSuperFields of " + javaName); }
-    if (isInterface) { AddInterfaceImports(this); }
-    if (superClass != null) {
-      if (!superClass.done) { superClass.GetSuperFields(jScope); }
-      Iterator<String> enum1 = superClass.scope.keySet().iterator();
-      while (enum1.hasNext()) {
-        String methName = (String)enum1.next();
-        scope.put(methName, superClass.scope.get(methName));
-      }
-    }
-    for (int i=0; i < fields.length; i++) {
-      FieldInfo f = fields[i];
-      if (f.isExported()) { 
-        AddField(f,scope); 
-      }
-    } 
-    HashMap<String,MethodInfo> iScope = new HashMap<String,MethodInfo>();
-    for (int i=0; i < methods.length; i++) {
-      MethodInfo mth = methods[i];
-      MakeMethodName(mth);
-      if (mth.isExported() && !mth.deprecated) {
-        if (mth.isInitProc) {
-          AddMethod(mth,iScope); 
-        } else if (mth.isStatic()) {
-          AddMethod(mth,scope);
-        } else {
-          //if (scope.containsKey(mth.name)) {
-          if (scope.containsKey(mth.userName)) {
-            MethodInfo meth = GetOverridden(mth,mth.owner);
-            if (meth != null) {
-              mth.overridding = true;
-              mth.userName = meth.userName;
-              scope.remove(mth.userName);
-              scope.put(mth.userName,mth); 
-            } else {
-              AddMethod(mth,scope);
-            }
-          } else { 
-            AddMethod(mth,scope); 
+    public void GetSuperFields(HashMap jScope) throws IOException {
+        if (done) { return; }
+        if (verbose) { 
+            System.out.println("GetSuperFields of " + this.javaName); 
+        }
+        if (this.isInterface) { 
+            this.AddInterfaceImports(this); 
+        }
+        if (this.superClass != null) {
+          if (!this.superClass.done) { 
+              this.superClass.GetSuperFields(jScope); }
+          Iterator<String> enum1 = superClass.scope.keySet().iterator();
+          while (enum1.hasNext()) {
+            String methName = (String)enum1.next();
+            this.scope.put(methName, this.superClass.scope.get(methName));
           }
         }
-      }
-    } 
-    done = true;
-  }
+        for (FieldInfo f : this.fieldList) {
+            if (f.isExported()) {
+                AddField((FieldInfo)f,scope);
+            } 
+        }
+        HashMap<String,MemberInfo> superScope = new HashMap<>();
+        for (MethodInfo mth : this.methodList) {
+            this.MakeMethodName(mth);
+            if (mth.isExported() && !mth.deprecated) {
+                if (mth.isInitProc) {
+                    AddMethod(mth,superScope);
+                } else if (mth.isStatic()) {
+                    AddMethod(mth,scope);
+                } else {
+                    if (this.scope.containsKey(mth.userName)) {
+                        MethodInfo meth = GetOverridden(mth,mth.owner);
+                        if (meth != null) {
+                            mth.overridding = true;
+                            mth.userName = meth.userName;
+                            this.scope.remove(mth.userName);
+                            this.scope.put(mth.userName,mth);
+                        } else {
+                            AddMethod(mth,this.scope);
+                        }
+                    } else {
+                        AddMethod(mth,this.scope);
+                    } 
+                }
+            }
+        }
+        done = true;
+    }
 
   private static MethodInfo GetOverridden(MethodInfo meth,ClassDesc thisClass) {
     ClassDesc aClass = thisClass;
     while (aClass.superClass != null) {
       aClass = aClass.superClass;
-      if (aClass.methods != null) { // new guard
-        for (int i=0; i < aClass.methods.length; i++) {
-          if (aClass.methods[i].name.equals(meth.name)) {
-            if ((aClass.methods[i].signature != null)&&(meth.signature != null)){
-              if (aClass.methods[i].signature.equals(meth.signature)) {
-                return aClass.methods[i];
-              }
-            } else if (aClass.methods[i].parTypes.length == meth.parTypes.length){
-              boolean ok = true;
-              for (int j=0; (j < aClass.methods[i].parTypes.length)& ok; j++){
-                ok = aClass.methods[i].parTypes[j] == meth.parTypes[j]; 
+      if (aClass.methodList.isEmpty()) { // new guard
+          for (MethodInfo method : aClass.methodList) {
+              if (method.name.equals(meth.name)) {
+                  if ((method.signature != null) && (meth.signature != null)) {
+                      if (method.signature.equals(meth.signature)) {
+                          return method;
+                      }
+                  } else if (method.parTypes.length == meth.parTypes.length) {
+                      boolean ok = true;
+                      for (int j = 0; (j < method.parTypes.length) & ok; j++) {
+                          ok = method.parTypes[j] == meth.parTypes[j];
+                      }
+                      if (ok) {
+                          return method;
+                      }
+                  }
               }
-              if (ok) { return aClass.methods[i]; }
-            }
           }
-        }
       }
     }  
     return null;
@@ -438,119 +569,148 @@ public class ClassDesc extends TypeDesc  {
     }
   }
 
+  /** Write a class definition to the typelist section of a symbol file
+   * <p>
+   * If the <code>writeDetails</code> flag is not true, or the
+   * class belongs to a different package, then only the type 
+   * ordinal is written. Otherwise a full class API is emitted.
+   * 
+   * @param out  the symbol file output stream
+   * @param thisPack the package which this symbol file describes
+   * @throws IOException 
+   */
     @Override
-  public void writeType(DataOutputStream out,PackageDesc thisPack) 
-                                                           throws IOException {
-    if (objName == null)  { this.MakeJavaName(); }
-    if (this.packageDesc != thisPack) {
-      out.writeByte(SymbolFile.fromS);
-// ------------
-//      if (this.packageDesc.impNum < 0) {
-//        System.out.println("impNum is " + this.packageDesc.impNum);
-//        System.out.println("packageDesc " + this.packageDesc.javaName);
-//        System.out.println("objName " + objName);
-//        this.packageDesc.impNum = 0;
-//      }
-// ------------
-      SymbolFile.writeOrd(out,this.packageDesc.impNum);
-      SymbolFile.writeName(out,access,objName);
-    } else if (!ConstantPool.isPublic(access)) {
-      out.writeByte(SymbolFile.fromS);
-      SymbolFile.writeOrd(out,0);
-      SymbolFile.writeName(out,access,objName);
-    }
-    if (!writeDetails) { return; }
-    out.writeByte(SymbolFile.ptrSy);
-    SymbolFile.writeOrd(out,outBaseTypeNum);
-    out.writeByte(SymbolFile.tDefS);
-    SymbolFile.writeOrd(out,outBaseTypeNum);
-    out.writeByte(SymbolFile.recSy);
-    int recAtt = 0;
-    if (!hasNoArgConstructor) { recAtt = 8; } 
-    if (ConstantPool.isFinal(access)) { 
-      out.writeByte(noAtt+recAtt); }
-    else if (isInterface) { 
-      out.writeByte(iFace+recAtt); }
-    else if (ConstantPool.isAbstract(access)) { 
-      out.writeByte(absR+recAtt); }
-    else { 
-      out.writeByte(extR+recAtt); }
-    if (isInterface) { out.writeByte(SymbolFile.truSy); } 
-    else { out.writeByte(SymbolFile.falSy); }
-    if (superClass != null) { 
-      out.writeByte(SymbolFile.basSy);
-      SymbolFile.writeTypeOrd(out,superClass); 
-    }
-    //if (interfaces.length > 0) {
-    if (interfaces != null && interfaces.length > 0) {
-      out.writeByte(SymbolFile.iFcSy);
-      for (int i = 0; i < interfaces.length; i++) {
-        out.writeByte(SymbolFile.basSy);
-        SymbolFile.writeTypeOrd(out,interfaces[i]); 
-      }
-    }
-    if (fields != null && fields.length > 0) {
-      for (int i=0; i < fields.length; i++) {
-        if (fields[i].isExported() && !fields[i].isStatic()) {
-            SymbolFile.writeName(out,fields[i].accessFlags,fields[i].name);
-            SymbolFile.writeTypeOrd(out,fields[i].type);
+    public void writeType(DataOutputStream out, PackageDesc thisPack)
+            throws IOException {
+        if (objName == null) {
+            this.MakeJavaName();
         }
-      }
-    }
-    if (methods != null && methods.length > 0) {
-      for (int i=0; i < methods.length; i++) {
-        if (methods[i].isExported() && !methods[i].deprecated &&
-            !methods[i].isStatic() && !methods[i].isInitProc &&
-            !methods[i].isCLInitProc) {
-            out.writeByte(SymbolFile.mthSy);
-    // --------------------
-    //        if (methods[i].userName == null) {
-    //          System.out.println("packageDesc " + this.packageDesc.javaName);
-    //          System.out.println("objName " + objName);
-    //          for (int j=0; j < methods.length; j++) {
-    //            System.out.println("Method " + j +  
-    //                (methods[i].userName == null ? " null" : methods[j].userName));
-    //          }
-    //        }
-    // --------------------
-            SymbolFile.writeName(out,methods[i].accessFlags,methods[i].userName);
-            int attr = 0;
-            if (!methods[i].overridding) { attr = 1; }
-            if (methods[i].isAbstract()) { attr += 2; }
-            else if (!methods[i].isFinal()){ attr += 6; } 
-            out.writeByte(attr); 
-            out.writeByte(0); /* all java receivers are value mode */
-            SymbolFile.writeOrd(out,outTypeNum);
-            SymbolFile.writeString(out,methods[i].name);
-            SymbolFile.WriteFormalType(methods[i],out);
+        if (this.parentPkg != thisPack) {
+            out.writeByte(SymbolFile.fromS);
+            // Diagnostic error message
+            if (this.parentPkg.impNum < 0) {
+                System.err.println("thisPack is " + thisPack.javaName);
+                System.err.println("impNum is " + this.parentPkg.impNum);
+                System.err.println("packageDesc " + this.parentPkg.javaName);
+                System.err.println("objName " + objName);
+                this.parentPkg.impNum = 0;
+            }
+            //
+            SymbolFile.writeOrd(out, this.parentPkg.impNum);
+            SymbolFile.writeName(out, access, objName);
+        } else if (!ConstantPool.isPublic(access)) {
+            out.writeByte(SymbolFile.fromS);
+            SymbolFile.writeOrd(out, 0);
+            SymbolFile.writeName(out, access, objName);
         }
-      }
-    }
-    if (fields != null && fields.length > 0) {
-      for (int i=0; i < fields.length; i++) {
-        if (fields[i].isConstant()) {
-            out.writeByte(SymbolFile.conSy);
-            SymbolFile.writeName(out,fields[i].accessFlags,fields[i].name);
-            SymbolFile.writeLiteral(out,fields[i].GetConstVal());
-        } else if (fields[i].isExported() && fields[i].isStatic()) {
-            out.writeByte(SymbolFile.varSy);
-            SymbolFile.writeName(out,fields[i].accessFlags,fields[i].name);
-            SymbolFile.writeTypeOrd(out,fields[i].type);
+        if (!this.writeDetails || (this.parentPkg != thisPack)) {
+            return;
         }
-      }
-    }
-    if (methods != null && methods.length > 0) {
-      for (int i=0; i < methods.length; i++) {
-        if (methods[i].isExported() && !methods[i].deprecated &&
-            methods[i].isStatic() && !methods[i].isCLInitProc) {
-            out.writeByte(SymbolFile.prcSy);
-            SymbolFile.writeName(out,methods[i].accessFlags,methods[i].userName);
-            SymbolFile.writeString(out,methods[i].name);
-            if (methods[i].isInitProc) { out.writeByte(SymbolFile.truSy); }
-            SymbolFile.WriteFormalType(methods[i],out);
+        out.writeByte(SymbolFile.ptrSy);
+        SymbolFile.writeOrd(out, outBaseTypeNum);
+        out.writeByte(SymbolFile.tDefS);
+        SymbolFile.writeOrd(out, outBaseTypeNum);
+        out.writeByte(SymbolFile.recSy);
+        int recAtt = 0;
+        if (!hasNoArgConstructor) {
+            recAtt = 8;
         }
-      }
+        if (ConstantPool.isFinal(access)) {
+            out.writeByte(noAtt + recAtt);
+        } else if (isInterface) {
+            out.writeByte(iFace + recAtt);
+        } else if (ConstantPool.isAbstract(access)) {
+            out.writeByte(absR + recAtt);
+        } else {
+            out.writeByte(extR + recAtt);
+        }
+        if (isInterface) {
+            out.writeByte(SymbolFile.truSy);
+        } else {
+            out.writeByte(SymbolFile.falSy);
+        }
+        if (superClass != null) {
+            out.writeByte(SymbolFile.basSy);
+            SymbolFile.writeTypeOrd(out, superClass);
+        }
+        //if (interfaces.length > 0) {
+        if (interfaces != null && interfaces.length > 0) {
+            out.writeByte(SymbolFile.iFcSy);
+            for (ClassDesc intf : interfaces) {
+                out.writeByte(SymbolFile.basSy);
+                SymbolFile.writeTypeOrd(out, intf);
+            }
+        }
+        if (!this.fieldList.isEmpty()) {
+            for (FieldInfo field : this.fieldList) {
+                if (field.isExported() && !field.isStatic()) {
+                    SymbolFile.writeName(out, field.accessFlags, field.name);
+                    SymbolFile.writeTypeOrd(out, field.type);
+                }
+            }
+        }
+        if (!this.methodList.isEmpty()) {
+            for (MethodInfo method : this.methodList) {
+                if (method.isExported() && !method.deprecated
+                        && !method.isStatic() && !method.isInitProc
+                        && !method.isCLInitProc) {
+                    out.writeByte(SymbolFile.mthSy);
+                    // --------------------
+                    //        if (methods[i].userName == null) {
+                    //          System.out.println("packageDesc " + this.packageDesc.javaName);
+                    //          System.out.println("objName " + objName);
+                    //          for (int j=0; j < methods.length; j++) {
+                    //            System.out.println("Method " + j +
+                    //                (methods[i].userName == null ? " null" : methods[j].userName));
+                    //          }
+                    //        }
+                    // --------------------
+                    SymbolFile.writeName(out, method.accessFlags, method.userName);
+                    int attr = 0;
+                    if (!method.overridding) {
+                        attr = 1;
+                    }
+                    if (method.isAbstract()) {
+                        attr += 2;
+                    } else if (!method.isFinal()) {
+                        attr += 6;
+                    }
+                    out.writeByte(attr);
+                    out.writeByte(0);
+                    /* all java receivers are value mode */
+                    SymbolFile.writeOrd(out, outTypeNum);
+                    SymbolFile.writeString(out, method.name);
+                    SymbolFile.WriteFormalType(method, out);
+                }
+            }
+        }
+        if (!this.fieldList.isEmpty()) {
+            for (FieldInfo field : this.fieldList) {
+                if (field.isConstant()) {
+                    out.writeByte(SymbolFile.conSy);
+                    SymbolFile.writeName(out, field.accessFlags, field.name);
+                    SymbolFile.writeLiteral(out, field.GetConstVal());
+                } else if (field.isExported() && field.isStatic()) {
+                    out.writeByte(SymbolFile.varSy);
+                    SymbolFile.writeName(out, field.accessFlags, field.name);
+                    SymbolFile.writeTypeOrd(out, field.type);
+                }
+            }
+        }
+        if (!this.methodList.isEmpty()) {
+            for (MethodInfo method : this.methodList) {
+                if (method.isExported() && !method.deprecated
+                        && method.isStatic() && !method.isCLInitProc) {
+                    out.writeByte(SymbolFile.prcSy);
+                    SymbolFile.writeName(out, method.accessFlags, method.userName);
+                    SymbolFile.writeString(out, method.name);
+                    if (method.isInitProc) {
+                        out.writeByte(SymbolFile.truSy);
+                    }
+                    SymbolFile.WriteFormalType(method, out);
+                }
+            }
+        }
+        out.writeByte(SymbolFile.endRc);
     }
-    out.writeByte(SymbolFile.endRc);
-  }
 }

+ 3 - 3
J2CPS/ClassRef.java

@@ -1,9 +1,9 @@
 /*************************************************************************/
-/*                Class Reference class for J2CPS                        */
+/*                Class Reference class for j2cps                        */
 /* Represents the class references in the constant pool of a class file  */   
-/*                      (c) copyright QUT                                */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017       */ 
 /*************************************************************************/
-package J2CPS;
+package j2cps;
 
 public class ClassRef {
 

+ 35 - 13
J2CPS/ConstantPool.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*                  ConstantPool class for J2CPS                      */
+/*                  ConstantPool class for j2cps                      */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.io.DataInputStream;
 import java.io.IOException;
@@ -16,7 +16,7 @@ public class ConstantPool {
 
   /* Tags for constant pool entries */
   public final static int CONSTANT_Utf8               = 1;
-  public static final int CONSTANT_Unicode            = 2;
+  //public static final int CONSTANT_Unicode            = 2;
   public final static int CONSTANT_Integer            = 3;
   public final static int CONSTANT_Float              = 4;
   public final static int CONSTANT_Long               = 5;
@@ -27,7 +27,10 @@ public class ConstantPool {
   public final static int CONSTANT_Methodref          = 10;
   public final static int CONSTANT_InterfaceMethodref = 11;
   public final static int CONSTANT_NameAndType        = 12;
-  public final static int CONSTANT_Unknown            = 13;
+  //public final static int CONSTANT_Unknown            = 13;
+  public final static int CONSTANT_MethodHandle       = 15;
+  public final static int CONSTANT_MethodType         = 16;
+  public final static int CONSTANT_InvokeDynamic      = 18;
 
   /* access flags */
   public static final int ACC_PUBLIC       = 0x0001;
@@ -69,20 +72,19 @@ public class ConstantPool {
     pool = null;
   }
 
-  private Object ReadConstant(DataInputStream stream) 
-                                                            throws IOException {
+  private Object ReadConstant(DataInputStream stream) throws IOException {
     int tag = stream.readUnsignedByte();
     switch (tag) {
     case CONSTANT_Utf8:
       return stream.readUTF();
     case CONSTANT_Integer: 
-      return new Integer(stream.readInt());
+      return stream.readInt();
     case CONSTANT_Float: 
-      return new Float(stream.readFloat());
+      return stream.readFloat();
     case CONSTANT_Long: 
-      return new Long(stream.readLong());
+      return stream.readLong();
     case CONSTANT_Double: 
-      return new Double(stream.readDouble());
+      return stream.readDouble();
     case CONSTANT_Class: 
       return new ClassRef(this,stream.readUnsignedShort());
     case CONSTANT_String:
@@ -99,12 +101,26 @@ public class ConstantPool {
     case CONSTANT_NameAndType:
       return new NameAndType(this,stream.readUnsignedShort(), 
                              stream.readUnsignedShort());
+    case CONSTANT_MethodHandle:
+        return SkipInfo(this,tag,stream.readUnsignedByte(),
+                    stream.readUnsignedShort());
+    case CONSTANT_MethodType:
+        return SkipInfo(this,tag,stream.readUnsignedShort(),0);
+    case CONSTANT_InvokeDynamic:
+        return SkipInfo(this,tag,stream.readUnsignedShort(),
+                    stream.readUnsignedShort());
     default:
       System.out.println("Unrecognized constant type: "+String.valueOf(tag));
-	return null;
+	throw new IOException("Unrecognized constant in constant pool");
     }
   }
   
+  private Object SkipInfo(ConstantPool cp, int tag, int I, int II) {
+      return null;
+  }
+  
+  
+  
   public final Object Get(int index) {
     return pool[index];
   }
@@ -154,6 +170,7 @@ public class ConstantPool {
   }
 
   /** Check if a flag has the public bit set */
+  
   public static boolean isPublic(int flags) {
     return (flags & ACC_PUBLIC) != 0;
   }
@@ -162,6 +179,10 @@ public class ConstantPool {
   public static boolean isPrivate(int flags) {
     return (flags & ACC_PRIVATE) != 0;
   }
+  
+  public static boolean isPublicOrProtected(int flags) {
+      return (flags & ACC_PUBLIC) != 0 || (flags & ACC_PROTECTED) != 0;
+  }
 
   /** Check if a flag has the protected bit set */
   public static boolean isProtected(int flags) {
@@ -203,7 +224,8 @@ public class ConstantPool {
     return (flags & ACC_VOLATILE) != 0;
   }
 
-  /** Check if a flag has the transient bit set */
+
+  /** Check if the flag has the transient bit set */
   public static boolean isTransient(int flags) {
     return (flags & ACC_TRANSIENT) != 0;
   }

+ 26 - 0
J2CPS/ExtFilter.java

@@ -0,0 +1,26 @@
+/* 
+ * Copyright John Gough 2016-2017
+ */
+package j2cps;
+
+import java.io.File;
+
+/**
+ *
+ * @author john
+ */
+public class ExtFilter implements java.io.FilenameFilter {
+    
+    private final String dotExtn;
+
+    private ExtFilter(String dotExtn) { this.dotExtn = dotExtn; }
+
+    public static ExtFilter NewExtFilter(String dotExtn) {
+        return new ExtFilter(dotExtn);
+    }
+
+    @Override
+    public boolean accept (File dir, String name) {
+        return name.endsWith(this.dotExtn); 
+    }
+}

+ 32 - 34
J2CPS/FieldInfo.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*                    FieldInfo class for J2CPS                       */
+/*                    FieldInfo class for j2cps                       */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.io.DataInputStream;
 import java.io.IOException;
@@ -11,48 +11,46 @@ import java.io.IOException;
 
 public class FieldInfo extends MemberInfo {
   
-  Object constVal;
-  public TypeDesc type;
-  public int typeFixUp = 0;
+    Object constVal;
+    public TypeDesc type;
+    public int typeFixUp = 0;
 
-  public FieldInfo(ConstantPool cp, DataInputStream stream,
-                   ClassDesc thisClass) throws IOException {
-    
-    super(cp,stream,thisClass);
-    type = TypeDesc.GetType(signature,0);
-    thisClass.TryImport(type);
-  }
+    public FieldInfo(ConstantPool cp, DataInputStream stream,
+                   ClassDesc thisClass) throws IOException {    
+        super(cp,stream,thisClass);
+        this.type = TypeDesc.GetType(this.signature,0);
+    }
 
-  public FieldInfo(ClassDesc cl,int acc,String nam,TypeDesc typ,Object cVal) {
-    super(cl,acc,nam);
-    type = typ;
-    constVal = cVal;
-  }
+    public FieldInfo(ClassDesc cl,int acc,String nam,TypeDesc typ,Object cVal) {
+        super(cl,acc,nam);
+        this.type = typ;
+        this.constVal = cVal;
+    }
 
 //  @Override
 //  public void AddImport(ClassDesc thisClass) {
 //    if (type instanceof ClassDesc) { thisClass.AddImport((ClassDesc)type); }
 //  }
 
-  public void GetConstValueAttribute (ConstantPool cp, DataInputStream stream) 
-                                                            throws IOException {
-    int attLen = stream.readInt();
-    constVal = cp.Get(stream.readUnsignedShort()); 
-    if (constVal instanceof StringRef) {
-      constVal = ((StringRef)constVal).GetString();
+    public void GetConstValueAttribute (ConstantPool cp, DataInputStream stream) 
+                                                              throws IOException {
+        int attLen = stream.readInt();
+        constVal = cp.Get(stream.readUnsignedShort()); 
+        if (constVal instanceof StringRef) {
+            constVal = ((StringRef)constVal).GetString();
+        }
     }
-  }
 
-  public Object GetConstVal() {
-    return constVal;
-  }
+    public Object GetConstVal() {
+        return constVal;
+    }
 
-  public boolean isConstant() {
-    return ((constVal != null) && ConstantPool.isFinal(accessFlags) &&
-            ConstantPool.isStatic(accessFlags) && 
-            (ConstantPool.isPublic(accessFlags) ||
-             ConstantPool.isProtected(accessFlags)));
-  }
+    public boolean isConstant() {
+        return ((constVal != null) && ConstantPool.isFinal(accessFlags) &&
+                ConstantPool.isStatic(accessFlags) && 
+                (ConstantPool.isPublic(accessFlags) || 
+                ConstantPool.isProtected(accessFlags)));
+    }
 
   @Override
   public String toString() {

+ 3 - 1
J2CPS/FieldRef.java

@@ -1,4 +1,6 @@
-package J2CPS;
+/*  (c) copyright John Gough, 2012-2017    */ 
+
+package j2cps;
 
 public class FieldRef extends Reference {
 

+ 3 - 3
J2CPS/InterfaceMethodRef.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*          Interface Method Reference class for J2CPS                */
+/*          Interface Method Reference class for j2cps                */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 public class InterfaceMethodRef extends Reference {
 

+ 138 - 46
J2CPS/J2CPS.java

@@ -1,76 +1,168 @@
 /**********************************************************************/
-/*                      Main class for J2CPS                          */
+/*                      Main class for j2cps                          */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.io.IOException;
+import java.util.jar.JarFile;
+import j2cpsfiles.j2cpsfiles;
 
-public class J2CPS {
+public class j2cps {
 
+    static String argString;
   /**
    * Main program. Takes a package name as a parameter, produces the 
-   * Component Pascal symbol file.
+   * Component Pascal symbol file.  The class-files of the package must
+   * be nested in a directory with the package name.
+   * In the case of the -jar option the last argument is the path from
+   * the current working directory to the target jar file.
    */
   public static void main(String args[]) { 
     int argLen = args.length;
+    String argStr = null;
     boolean anonPack = false;
-    J2CPSFiles.GetPaths();
-    String filename = null;
+    boolean seenParg = false;
+    MkArgString(args);
     TypeDesc.InitTypes();
     if (argLen == 0) {
-      System.err.println("J2CPS version 1.3.13.2 (August 2012)");
-      System.err.println("Usage: java J2CPS [options] packagename");
-      System.err.println("Options may be in any order.");
-      System.err.println("  -d dir  symbol file directory");
-      System.err.println("  -u      use unique names");
-      System.err.println("  -v      verbose diagnostic messages");
-      System.exit(0);
+        System.err.println("j2cps version 1.4.0.2 (March 2017)");
+        System.err.println("Usage:");
+        System.err.println("java [VM-opts] j2cps.j2cps [options] PackageNameOrJarFile");
+        System.err.println("java [VM-opts] -jar j2cps.jar [options] PackageNameOrJarFile");
+        System.err.println("J2cps options may be in any order.");
+        System.err.println("  -d[st] dir => symbol file destination directory");
+        System.err.println("  -p[kg] dir => package-root directory");
+        System.err.println("  -jar       => process the named jar file");
+        System.err.println("  -s[ummary] => summary of progress");
+        System.err.println("  -v[erbose] => verbose diagnostic messages");
+        System.err.println("  -nocpsym   => only use sym-files from destination,");
+        System.err.println("                (overrides any CPSYM path setting)");
+        System.exit(0);
     }
     else {
-      int argIx = 0;
-      filename = args[argIx];
-      while (filename.startsWith("-")) { 
-        /* parse options here */
-        if (filename.charAt(1) == 'v') { 
-          ClassDesc.verbose = true; 
-        } else if (filename.charAt(1) == 'f') { 
-          System.out.println("Class not package");
-          anonPack = true; 
-        } else if (filename.charAt(1) == 'u') { 
-          System.out.println("Using unique names");
-          ClassDesc.overloadedNames = false; 
-        } else if (filename.charAt(1) == 'd') {
-          if (argIx + 1 < argLen) {
-            filename = args[++argIx];
-            J2CPSFiles.SetSymDir(filename); 
-          } else {
-            System.err.println("-d option is missing directory name");
-          }
-        } else { 
-          System.err.println("Unknown option " + filename); 
+        int argIx = 0;
+        argStr = args[argIx];
+        while (argStr.startsWith("-")) {
+            String optString = argStr.substring(1);
+            /* parse options here */
+            switch (argStr.charAt(1)) {
+                case 'V':
+                    if ("VERBOSE".startsWith(optString)) {
+                        ClassDesc.VERBOSE = true;
+                        ClassDesc.verbose = true;
+                        ClassDesc.summary = true;
+                    } else
+                        BadOption(argStr);  
+                    break;
+                case 'v':
+                    if ("verbose".startsWith(optString)) {
+                        ClassDesc.verbose = true;
+                        ClassDesc.summary = true;
+                        j2cpsfiles.SetVerbose( true );
+                        j2cpsfiles.SetSummary( true );
+                    } else
+                        BadOption(argStr);
+                    break;
+                case 's':
+                    if ("summary".startsWith(optString)) {
+                        ClassDesc.summary = true;
+                        j2cpsfiles.SetSummary( true );
+                    } else
+                        BadOption(argStr);
+                    break;
+                case 'd':
+                    if (!"dst".startsWith(optString))
+                        BadOption(argStr);
+                    else if (argIx + 1 < argLen) {
+                        argStr = args[++argIx];
+                        j2cpsfiles.SetDstDir(argStr);
+                    } else
+                        System.err.println(
+                            "-d option is missing symfile destination directory name");     
+                    break;
+                case 'p':
+                    if (!"pkg".startsWith(optString))
+                        BadOption(argStr);
+                    else if (argIx + 1 < argLen) {
+                        seenParg = true;
+                        argStr = args[++argIx];
+                        j2cpsfiles.SetPackageRootDir(argStr);
+                    } else
+                        System.err.println(
+                            "-p option is missing package-root directory name");    
+                    break;
+                case 'j':
+                    if (optString.equalsIgnoreCase("jar")) {
+                        ClassDesc.useJar = true;
+                    } else
+                        BadOption(argStr);
+                    break;
+                case 'n':
+                    if (optString.equalsIgnoreCase("nocpsym")) {
+                        ClassDesc.nocpsym = true;
+                    } else
+                        BadOption(argStr);
+                    break;
+                default:
+                    BadOption(argStr);
+                    break;
+            }
+            if (argIx + 1 < argLen) {
+                argStr = args[++argIx];
+            } else {
+                System.err.println("No package-name or jar filename given, terminating");
+                System.exit(1);
+            }
         }
-        if (argIx + 1 < argLen) {
-          filename = args[++argIx]; 
-        } else {
-          System.err.println("No package name given, terminating");
-          System.exit(1);
+        //
+        // Consistency checks ...
+        //
+        if (ClassDesc.useJar && seenParg) {
+            System.out.println("Cannot use both -jar and -p. Ignoring -p");
         }
-      }
+        if (ClassDesc.summary)
+            System.out.println(argString);
+        j2cpsfiles.GetPaths(ClassDesc.nocpsym);
     }
     try {
-      PackageDesc thisPackage = PackageDesc.MakeNewPackageDesc(filename, anonPack);
-      PackageDesc.ReadPackages();
-      PackageDesc.WriteSymbolFiles();
+        if (ClassDesc.useJar) {
+            if (ClassDesc.useJar && !argStr.toLowerCase().endsWith(".jar")) {
+                System.err.println("After -jar, filename must end \".jar\"");
+                System.exit(1);
+            }
+            JarFile jf = new JarFile(argStr);
+            JarHandler jh = new JarHandler();
+            jh.ProcessJar(jf);
+            PackageDesc.ProcessJarDependencies();           
+        } else {
+            PackageDesc.MakeRootPackageDescriptor(argStr, anonPack);
+            PackageDesc.ProcessPkgWorklist();
+        }
+        PackageDesc.WriteSymbolFiles();
     }
     catch (IOException e) {
 	System.err.println("IOException occurs while reading input file.");
+	System.err.println( e.getMessage() );
 	System.err.println("Aborting...");
+        e.printStackTrace(System.err);
 	System.exit(1);
     }
   }
-}
-
+  
+  static private void BadOption(String s) {
+      System.err.println("Unknown option " + s);
+  }
+   
+  static void MkArgString( String[] args ) {
+      StringBuilder bldr = new StringBuilder( "J2cps args>");
+      for (String arg : args) {
+          bldr.append(' ');
+          bldr.append(arg);
+      }
+      argString = bldr.toString();
+  }
 
+}
 

+ 141 - 109
J2CPS/J2CPSFiles.java

@@ -1,125 +1,157 @@
-/**********************************************************************/
-/*                  J2CPS Files class for J2CPS                       */
-/*                                                                    */   
-/*                      (c) copyright QUT                             */ 
-/**********************************************************************/
-package J2CPS;
-
-import java.io.*;
-
-public class J2CPSFiles implements FilenameFilter {
-
-  private static final String classExt = ".class";
-  private static final String symExt = ".cps";
-  private static final String intExt = ".cp";
-  private static final String dbName = "index.dbi";
-  private static final String sepCh = System.getProperty("file.separator");
+/*
+ * Copyright (c) John Gough 2016-2017
+ */
+package j2cpsfiles;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.FileOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+
+/**
+ *
+ * @author john
+ */
+public class j2cpsfiles /*implements FilenameFilter*/ {
+
+  private static final String CLASSEXT = ".class";
+  private static final String SYMFILEXT = ".cps";
+  // private static final String CPEXT = ".cp";
+  // private static final String dbName = "index.dbi";
   private static final char EOF = '\0';
   private static final char CR  = '\r';
   private static final char LF  = '\n';
   private static final char SP  = ' ';
   private static final char TAB  = '\t';
-  private static String currDir = System.getProperty("user.dir");
-  private static String symDir;
+  private static final String CURRDIR = 
+          System.getProperty("user.dir");
+  private static final String FILESEP = 
+          System.getProperty("file.separator");
+  private static final String PATHSEPSTRING = 
+           System.getProperty("path.separator");
+  private static final char PATHSEP = 
+          PATHSEPSTRING.charAt(0);
+ 
+  /**
+   *  Destination directory for symbol files.
+   */
+  private static String dstDir = ".";
+  
+  /**
+   *  The installation root directory.
+   */
+  private static String rootName = ".";
+  
+  /**
+   *  The root of the package class-file tree.
+   */
+  private static File pkgRoot = new File(CURRDIR);
+  
   private static String[] classPath;
+  
+  /**
+   *  Locations to search for symbol files.
+   */
   private static String[] symPath;
-  private static final char pathSep = 
-                            System.getProperty("path.separator").charAt(0);
-
-
-/* 
- * Method for FilenameFilter
- */
-
-  @Override
-  public boolean accept (File dir, String name) {
-    return name.endsWith(classExt); 
-  }
+  
+  private static boolean verbose = false;
+  private static boolean summary = false;
+ 
+  public static void SetVerbose( boolean v ) { verbose = v; }
+  public static void SetSummary( boolean v ) { summary = v; }
+
+    public static void SetDstDir(String sDir) {
+        if (!sDir.equals("."))
+            dstDir = "." + FILESEP + sDir;
+    }
 
-  public static void SetSymDir(String sDir) {
-    symDir = sDir;
-    if (symDir == null) {
-      symDir = symPath[0];
+    public static void SetPackageRootDir(String rDir) {
+        rootName = "." + FILESEP + rDir;
+        pkgRoot = new File(CURRDIR, rDir);
     }
-  }
 
-  public static void GetPaths() {
-    classPath = GetPath("java.class.path");
-    symPath = GetPath("CPSYM");
-  }
+    /**
+     *  This method is called after all arguments have been parsed.
+     */
+    public static void GetPaths(boolean ignoreCpsym) {
+        if (summary) {
+            System.out.printf("Current directory \".\" is <%s>\n", CURRDIR);
+            if (!rootName.equals("."))
+                System.out.printf(
+                    "Using <%s> as package-root directory\n", rootName);
+            if (!dstDir.equals("."))
+                System.out.printf("Using <%s> as symbol destination directory\n", dstDir);
+        }      
+        classPath = GetPathArray("java.class.path");
+        if (ignoreCpsym) {
+            symPath = new String[] { dstDir };
+        } else {
+            String[] tmp = GetPathArray("CPSYM");
+            symPath = new String[tmp.length + 1];
+            symPath[0] = dstDir;
+            for (int i = 0; i < tmp.length; i++)
+                symPath[i+1] = tmp[i];
+        }
+    }
 
   private static String GetPathFromProperty(String str) {
-    String path = System.getProperty(str);
-    //if (path != null)
-    //  System.out.println("Property " + str + " = " + path); 
+    String path = System.getProperty(str); 
     return path;
   }
 
   private static String GetPathFromEnvVar(String str) {
     String path = System.getenv(str);
-    //if (path != null)
-    //  System.out.println("Env. variable " + str + " = " + path); 
     return path;
   }
 
-  private static String[] GetPath(String prop) {
-    String paths[];
+  private static String[] GetPathArray(String prop) {
     // First look for the system property (preferred source)
     String cPath = GetPathFromProperty(prop);
     if (cPath == null)
       cPath = GetPathFromEnvVar(prop);
 
     if (cPath == null) {
-      System.out.println("No variable for \"" + prop + "\", using \".\""); 
-      cPath = ".";
-    } else 
-      System.out.println("Using \"" + prop + "\" path \"" + cPath + "\""); 
-      
-    int i,count=1,start,end;
-    for (i=0; i > -1 ; i++ ) {
-      i = cPath.indexOf(pathSep,i); 
-      if (i > -1) { count++; } else { i--; } 
-    }
-    paths = new String[count+1];
-    paths[0] = currDir;
-    start = 0; i = 1; 
-    while (start < cPath.length()) {
-      end = cPath.indexOf(pathSep,start);
-      if (end == -1) { 
-        end = cPath.length()+1; 
-        paths[i] = cPath.substring(start);
-      } else {
-        paths[i] = cPath.substring(start,end);
-      }
-      if (paths[i].equals(".")) { paths[i] = currDir; }
-      i++;
-      start = end+1;
-    }
-    return paths;
+        System.err.println("No variable for \"" + prop + "\", using \".\""); 
+        cPath = ".";
+    } else if (summary) 
+        System.out.println("Using \"" + prop + "\" path \"" + cPath + "\""); 
+    
+    String[] splits = cPath.split(PATHSEPSTRING);
+    return splits;
   }
 
-  public static File getPackageFile(String name) {
-    File inFile = new File(currDir,name);
+  public static File getPackageFile(String name) { 
+    File inFile = new File(pkgRoot,name);
     if (!inFile.exists()) {
-      boolean found = false;
-      for (int i=0; (i < classPath.length) && (!found); i++) {
-        if (ClassDesc.verbose) {
-          System.out.println("<" + classPath[i] + sepCh + name + ">");
+        boolean found = false;
+        for (int i=0; (i < classPath.length) && (!found); i++) {
+            if (verbose) {
+                System.out.println("<" + classPath[i] + FILESEP + name + ">");
+            }
+            inFile = new File(classPath[i],name);
+            found = inFile.exists();
         }
-        inFile = new File(classPath[i],name);
-        found = inFile.exists();
-      }
-      if (!found) {
-        System.err.println("Cannot open class directory <" + name + ">");
-        System.exit(0);
-      }
+        if (!found) {
+          System.err.println(
+                  "Cannot open package directory <" + name + ">, quitting");
+          // 
+          // Is this too severe?
+          //
+          System.exit(0);
+        }
+    } else {
+        System.out.print("INFO: opened package directory <" + name + ">");
+        if (summary)
+            System.out.print(" from package-root <" + rootName + ">");
+        System.out.println();
     }
     return inFile;
   }
 
   public static File OpenClassFile(String name) {
-    if (!name.endsWith(classExt)) { name = name.concat(classExt); }
-    File inFile = new File(currDir,name);
+    if (!name.endsWith(CLASSEXT)) { name = name.concat(CLASSEXT); }
+    File inFile = new File(CURRDIR,name);
     if (!inFile.exists()) {
       inFile = FindClassFile(name);
     }
@@ -135,7 +167,7 @@ public class J2CPSFiles implements FilenameFilter {
     File inFile = new File(dir,fName);
     if (!inFile.exists()) {
       System.err.println("Cannot open class file <" + dir.getName() +
-                                                 sepCh + fName + ">");
+                                                 FILESEP + fName + ">");
       System.exit(0);
     }
     return inFile;
@@ -145,17 +177,17 @@ public class J2CPSFiles implements FilenameFilter {
   public static File FindClassFile(String name) {
     File inFile = null;
     boolean found = false;
-    if (!name.endsWith(classExt)) { name = name.concat(classExt); }
+    if (!name.endsWith(CLASSEXT)) { name = name.concat(CLASSEXT); }
     for (int i=0; (i < classPath.length) && (!found); i++) {
-      if (ClassDesc.verbose) {
-        System.out.println("<" + classPath[i] + sepCh + name + ">");
+      if (verbose) {
+        System.out.println("<" + classPath[i] + FILESEP + name + ">");
       }
       inFile = new File(classPath[i],name);
       found = inFile.exists();
     }
     if (!found) {
       System.err.println("Cannot open class file <" + name + ">");
-      System.exit(0);
+      System.exit(1);
     }
     return inFile;
   }
@@ -164,34 +196,34 @@ public class J2CPSFiles implements FilenameFilter {
                                     throws FileNotFoundException, IOException {
     File inFile = null;
     boolean found = false;
-    if (!name.endsWith(symExt)) { name = name.concat(symExt); }
+    if (!name.endsWith(SYMFILEXT)) { 
+        name = name.concat(SYMFILEXT); 
+    }
     for (int i=0; (i < symPath.length) && (!found); i++) {
-      if (ClassDesc.verbose) {
-        System.out.println("<" + symPath[i] + sepCh + name + ">");
+      if (verbose) {
+        System.out.println("Seeking <" + symPath[i] + FILESEP + name + ">");
       }
       inFile = new File(symPath[i],name);
       found = inFile.exists();
     }
     if (!found) {
-      if (ClassDesc.verbose) 
-        { System.out.println("Cannot find symbol file <" + name + ">"); }
+      if (verbose) {
+        System.out.println("Cannot find symbol file <" + name + ">");
+      }
       return null;
+    } else {
+        return inFile;
     }
-    return inFile;
   }
 
   public static DataOutputStream CreateSymFile(String fileName) 
                                                           throws IOException {
-    String dirName;
-    if (symDir == null) { dirName = currDir; } else { dirName = symDir; }
-    if (ClassDesc.verbose) {  
-      System.out.println("Creating symbolfile " + fileName + symExt +
-                         " in directory " + dirName);
-    }
+    String dirName = (dstDir == null ? CURRDIR : dstDir);
+    System.out.print("INFO: Creating symbolfile <" + fileName + SYMFILEXT + ">");
+    if (summary) 
+        System.out.print(" in directory <" + dirName + ">");
+    System.out.println();
     return new DataOutputStream(new FileOutputStream(
-                                new File(dirName,fileName + symExt)));
-  }
+                                new File(dirName,fileName + SYMFILEXT)));
+  }    
 }
-
-
-

+ 57 - 0
J2CPS/JarHandler.java

@@ -0,0 +1,57 @@
+/*
+ *  (c) copyright John Gough, 2012-2017   
+ */
+package j2cps;
+
+import java.io.InputStream;
+import java.io.IOException;
+//import java.util.HashMap;
+//import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.jar.JarFile;
+import java.util.jar.JarEntry;
+
+/**
+ *
+ * @author john
+ */
+public class JarHandler {
+    
+    public JarHandler( ) { }
+    
+    public void ProcessJar( JarFile jf ){
+        System.out.printf("INFO: opened jar file <%s>\n", jf.getName());
+        Enumeration<JarEntry> entries = jf.entries();
+        String classFileName;
+        String className;
+        while (entries.hasMoreElements()) {
+            JarEntry entry = entries.nextElement();
+            classFileName = entry.getName();
+            //System.out.println(entryName);
+            if (classFileName.toLowerCase().endsWith(".class")) {
+                className = classFileName.substring(0, classFileName.length() - 6);
+                try {
+                    ClassDesc desc = ClassDesc.MakeNewClassDesc(className, null);
+                    desc.parentPkg.myClasses.add(desc);
+                    desc.parentPkg.processed = true;
+                    InputStream classStream = jf.getInputStream( entry );
+                    boolean ok = desc.ReadJarClassFile(classStream);
+                    if (ClassDesc.verbose)
+                        System.out.printf( "Read jar class %s ... %s\n", className, (ok ? "OK" : "error"));
+                } catch (IOException x) {
+                    // Message
+                    System.err.println( "ProcessJar threw IOException");
+                    System.err.println( x.getMessage() );
+                    // x.printStackTrace();
+                    System.exit(1);                    
+                }
+            }
+        }
+        //
+        //  At this point all the class files in the jar have
+        //  been processed, and all packages listed in the todo
+        //  collection. However, dependent packages have not been
+        //  processed. 
+        //
+    } 
+}

+ 4 - 4
J2CPS/MemberInfo.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*                  Member Info class for J2CPS                       */
+/*                  Member Info class for j2cps                       */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.io.DataInputStream;
 import java.io.IOException;
@@ -50,7 +50,7 @@ public class MemberInfo {
            ConstantPool.isPublic(accessFlags);
   }
 
-  public boolean isExported() {
+  public final boolean isExported() {
     return (ConstantPool.isPublic(accessFlags) ||
             ConstantPool.isProtected(accessFlags)); 
   }

+ 65 - 49
J2CPS/MethodInfo.java

@@ -1,72 +1,88 @@
 /**********************************************************************/
-/*                  Method Info class for J2CPS                       */
+/*                  Method Info class for j2cps                       */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.io.DataInputStream;
 import java.io.IOException;
 
 public class MethodInfo extends MemberInfo {
 
-  public TypeDesc[] parTypes;
-  public TypeDesc retType;
-  public String userName;
-  public boolean deprecated = false;
-  public int retTypeFixUp = 0;
-  public int[] parFixUps;
-  public boolean overridding = false;
-  public boolean isInitProc = false;
-  public boolean isCLInitProc = false;
+    public TypeDesc[] parTypes;
+    public TypeDesc retType;
+    public String userName;
+    public boolean deprecated = false;
+    public int retTypeFixUp = 0;
+    public int[] parFixUps;
+    public boolean overridding = false;
+    public boolean isInitProc = false;
+    public boolean isCLInitProc = false;
 
-  public MethodInfo(ConstantPool cp,DataInputStream stream,
-                    ClassDesc thisClass) throws IOException {
-    super(cp,stream,thisClass);
-    parTypes = TypeDesc.GetParTypes(signature);
-    retType = TypeDesc.GetType(signature,signature.indexOf(')')+1);
-    if (name.equals("<init>")) { 
-      userName = "Init"; 
-      isInitProc = true;
-      if (!ConstantPool.isStatic(accessFlags)) {
-        accessFlags = (accessFlags + ConstantPool.ACC_STATIC);
-      }
-      if ((parTypes.length == 0) && (!ConstantPool.isPrivate(accessFlags))) { 
-        thisClass.hasNoArgConstructor = true; 
-      }
-      retType = thisClass;
-    } else if (name.equals("<clinit>")) {
-      userName="CLInit"; 
-      isCLInitProc = true;
-    }
-    if (ClassDesc.verbose) { 
-      System.out.println("Method has " + parTypes.length + " parameters");
+    public MethodInfo(ConstantPool cp,DataInputStream stream,
+                      ClassDesc thisClass) throws IOException {
+        super(cp,stream,thisClass);
+        this.parTypes = TypeDesc.GetParTypes(signature);
+        this.retType = TypeDesc.GetType(signature,signature.indexOf(')')+1);
+        if (this.name.equals("<init>")) { 
+            this.userName = "Init"; 
+            this.isInitProc = true;
+            if (!ConstantPool.isStatic(accessFlags)) {
+              this.accessFlags = (this.accessFlags + ConstantPool.ACC_STATIC);
+            }
+            if ((this.parTypes.length == 0) && 
+                    (!ConstantPool.isPrivate(this.accessFlags))) { 
+              thisClass.hasNoArgConstructor = true; 
+            }
+            this.retType = thisClass;
+        } else if (this.name.equals("<clinit>")) {
+            this.userName="CLInit"; 
+            this.isCLInitProc = true;
+        } else {
+            this.userName=this.name;
+        }
+        if (ClassDesc.VERBOSE) {
+            int parNm = this.parTypes.length;
+            System.out.printf("Method %s has %d %s",
+                    this.name, parNm, (parNm != 1 ?
+                        "parameters" : "parameter"));
+        }
+        if (this.isExported()) {
+            for (TypeDesc parType : this.parTypes) {
+                // 
+                //  The package of this type must be placed on 
+                //  this package's import list iff:
+                //   *  the par type is public or protected AND
+                //   *  the method's package is not CURRENT.
+                //
+                if (parType.parentPkg != thisClass.parentPkg) {
+                    parType.blame = this;
+                    thisClass.TryImport(parType);
+                }
+            }
+            if (this.retType.parentPkg != thisClass.parentPkg) {
+                this.retType.blame = this;
+                thisClass.TryImport(this.retType);
+            }
+        }
     }
-    //AddImport(thisClass);
-    for (int i=0; i < parTypes.length; i++)
-        thisClass.TryImport(parTypes[i]);
-    thisClass.TryImport(retType);
-  }
 
   public MethodInfo(ClassDesc thisClass,String name,String jName,int acc) {
     super(thisClass,acc,jName);
-    userName = name;
+    this.userName = name;
     if (name.equals("<init>")) { 
-      if (userName == null) { userName = "Init";}
-      isInitProc = true; 
+      if (userName == null) { 
+          this.userName = "Init";
+      }
+      this.isInitProc = true; 
     }
   }
 
-//  public void AddImport(ClassDesc thisClass) {
-//    for (int i=0; i < parTypes.length; i++)
-//        thisClass.TryImport(parTypes[i]);
-//    thisClass.TryImport(retType);
-//  }
-
     @Override
   public String toString() {
-    return ConstantPool.GetAccessString(accessFlags) + " " + name + " " + 
-           signature;
+    return ConstantPool.GetAccessString(this.accessFlags) + " " + 
+            this.name + " " + this.signature;
   }
 
 }

+ 3 - 3
J2CPS/MethodRef.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*                Method Reference class for J2CPS                    */
+/*                Method Reference class for j2cps                    */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 public class MethodRef extends Reference {
 

+ 3 - 3
J2CPS/NameAndType.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*               NameAndType Reference class for J2CPS                */
+/*               NameAndType Reference class for j2cps                */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 public class NameAndType {
 

+ 288 - 117
J2CPS/PackageDesc.java

@@ -1,184 +1,355 @@
 /**********************************************************************/
-/*                Package Desscriptor class for J2CPS                 */
+/*                Package Desscriptor class for j2cps                 */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import j2cpsfiles.j2cpsfiles;
 
 public class PackageDesc {
+  
+    public static int pub = 0;
+    public static int tot = 0;
+    
+    static final ExtFilter classFilter = ExtFilter.NewExtFilter(".class");
+    /**
+     *  Work-list of all the packages encountered during this
+     *  invocation of <code>j2cps</code>, either directly or through reference.
+     */
+    static final ArrayList<PackageDesc> toDo = new ArrayList<>(2);
+    
+    /**
+     *  List of packages that will be emitted as symbol files.
+     */
+    static final ArrayList<PackageDesc> syms = new ArrayList<>(2);
+    
+    /**
+     *  Dictionary of packages known to this invocation of <code>j2cps</code>.
+     */
+    static final HashMap<String,PackageDesc> packageList = new HashMap<>();
+    
+    /**
+     *  The file associated with this package.
+     */
+    File theFile;
+    
+    int status = Util.PRISTINE;
 
-  private static final char qSepCh = '/';
-  private static final char fSepCh = 
-                             System.getProperty("file.separator").charAt(0);
-  private static final char jSepCh = '.';
-  private static final char nSepCh = '_';
-  private static ArrayList<PackageDesc> toDo = new ArrayList<PackageDesc>(2);
-  private static ArrayList<PackageDesc> syms = new ArrayList<PackageDesc>(2);
-  private static HashMap<String,PackageDesc> packageList = new HashMap<String,PackageDesc>();
-  private File packageFile;
+    /**
+     *  This list contains all the classes defined in this package.
+     */
+    public ArrayList<ClassDesc> myClasses;
+    
+    /**
+     *  The name of the package with <code>qSepCh</code> separators
+     */
+    public String name;
+            
+    /**
+     *  The name of the package converted to a legal
+     *  Component Pascal module identifier.
+     */
+    public String cpName;
+            
+    /**
+     *  Package name in java language (dotted) format.
+     */
+    public String javaName;
+            
+    /**
+     *  Directory name relative to class file hierarchy root with
+     *  notation corrected for environment-specific file separators
+     */
+    public String dirName;
+    
+    /**
+     *  List of imports into this package.
+     */
+    public ArrayList<PackageDesc> pkgImports = new ArrayList<>();
+    Object blame;
 
-  public ClassDesc[] classes;
-  public String name, cpName, javaName, dirName;
-  public ArrayList<PackageDesc> imports = new ArrayList<PackageDesc>();
-  public int impNum = -1;
-  public boolean anonPackage = false;
+        
+    public int impNum = -1;
+    public boolean anonPackage = false;
+    
+    /**
+     *  Boolean true indicates that this package has been
+     *  processed, and (if not just <i> referenced</i>) has
+     *  been added to the <code>syms</code> list.
+     */
+    public boolean processed = false;
+    
+    public String blameStr() {
+        if (this.blame == null)
+            return "no-blame";
+        else if (this.blame instanceof MemberInfo) {
+            MemberInfo f = (MemberInfo)this.blame;
+            return f.owner.objName + "::" + f.name;
+        }
+        else if (this.blame instanceof ClassDesc) {
+            ClassDesc c = (ClassDesc)this.blame;
+            return "ClassDesc " + c.name;
+        }
+        else
+            return this.blame.toString();
+    }
 
-  public static PackageDesc MakeNewPackageDesc(String pName, boolean anon) {
+    /** 
+     * Adds another package to the <code>toDo</code>
+     * and package lists.
+     * @param pName the full name of the package without file-extension
+     * @param anon indicates if this package is the anonymous package
+     * @return 
+     */
+    static PackageDesc MakeNewPackageDesc(String pName, boolean anon) {
+        PackageDesc desc = new PackageDesc(pName, anon);
+        if (!anon) {
+            // Add to package list
+            packageList.put(desc.name, desc);
+            desc.set(Util.ONLIST);
+        }
+        // Add to toDo worklist
+        toDo.add(desc);
+        /*
+        if (pName.startsWith("com") || pName.startsWith("sun"))
+        System.err.println(pName);
+        */
+        desc.set(Util.ONTODO);
+        return desc;
+    }
+  
+    /**
+     * Creates a new package descriptor, which will be the root 
+     * (and element-zero) of the work-list for non-jar based
+     * invocations.
+     * <p>
+     * Adds another package to the <code>toDo</code>
+     * and package lists.
+     * @param pName the full name of the package without file-extension
+     * @param anon indicates if this package is the anonymous package
+     */
+    public static void MakeRootPackageDescriptor(String pName, boolean anon) {
       PackageDesc desc = new PackageDesc(pName, anon);
-      if (!anon)
+      if (!anon) { // Then insert in HashMap
           packageList.put(desc.name, desc);
+          desc.set(Util.ONLIST);
+      }
+      // And in any case put on the worklist
       toDo.add(desc);
-      return desc;
-  }
+      /*        
+      if (pName.startsWith("com") || pName.startsWith("sun"))
+      System.err.println(pName);
+      */
+      desc.set(Util.ONTODO);
+    }
   
-  private PackageDesc(String pName, boolean anon) {
-    if (anon) {
-      name = pName;
-      cpName = pName;
-      javaName = pName;
-      anonPackage = true;
-    } else {
-      MakeName(pName); 
+    private PackageDesc(String pName, boolean anon) {
+        if (anon) {
+          this.name = pName;
+          this.cpName = pName;
+          this.javaName = pName;
+          this.anonPackage = true;
+        } else {
+          MakeName(pName); 
+        }
+        this.myClasses = new ArrayList<>();
     }
-  }
 
-  private void MakeName(String pName) {
-    name = pName.replace(jSepCh,qSepCh);
-    name = name.replace(fSepCh,qSepCh);  /* name is now .../... */
-    cpName = name.replace(qSepCh,nSepCh);
-    javaName = name.replace(qSepCh,jSepCh);
-    if (qSepCh != fSepCh) {
-      dirName = name.replace(qSepCh,fSepCh);
-    } else {
-      dirName = name;
+    private void MakeName(String pName) {
+        this.name = pName.replace(Util.JAVADOT,Util.FWDSLSH);
+        this.name = this.name.replace(Util.FILESEP,Util.FWDSLSH);  /* name is now .../... */
+        this.cpName = this.name.replace(Util.FWDSLSH,Util.LOWLINE);
+        this.javaName = this.name.replace(Util.FWDSLSH,Util.JAVADOT);
+        if (Util.FWDSLSH != Util.FILESEP) {
+            this.dirName = this.name.replace(Util.FWDSLSH,Util.FILESEP);
+        } else {
+            this.dirName = this.name;
+        }
     }
-  }
  
+    /** Create or fetch package descriptor by name */
   public static PackageDesc getPackage(String packName) {
-    packName = packName.replace(jSepCh,qSepCh); 
+    packName = packName.replace(Util.JAVADOT,Util.FWDSLSH); 
     PackageDesc pack = (PackageDesc)packageList.get(packName);
-    if (pack == null) { pack = PackageDesc.MakeNewPackageDesc(packName,false); }
+    if (pack == null) { 
+        pack = PackageDesc.MakeNewPackageDesc(packName,false); 
+    }
     return pack;
   }
 
+
+  /**
+   * Create or fetch the package descriptor object for the class 
+   * with the given java (dotted) name.  In the case that the 
+   * package has not been previously seen, the name of the newly
+   * created package descriptor is the prefix of the className.
+   * @param className the full java-name of the class.
+   * @return the package descriptor to which the corresponding 
+   * class descriptor should be added.
+   */
   public static PackageDesc getClassPackage(String className) {
-    className = className.replace(jSepCh,qSepCh); 
-    String pName = className.substring(0,className.lastIndexOf(qSepCh));
+    className = className.replace(Util.JAVADOT,Util.FWDSLSH); 
+    String pName = className.substring(0,className.lastIndexOf(Util.FWDSLSH));
     PackageDesc pack = (PackageDesc)packageList.get(pName);
-    if (pack == null) { pack = PackageDesc.MakeNewPackageDesc(pName,false); }
+    if (pack == null) { 
+        pack = PackageDesc.MakeNewPackageDesc(pName,false);
+    }
     return pack;
   }
 
-  public void AddImport(TypeDesc ty) {
+  public void AddPkgImport(TypeDesc ty) {
     if (ty instanceof ClassDesc) {
       ClassDesc aClass = (ClassDesc)ty;
-      if (aClass.packageDesc == null) {
-        System.err.println("ERROR: Class "+aClass.qualName+" has no package");
+      if (aClass.parentPkg == null) {
+        System.err.println("ERROR: Class <"+aClass.javaName+"> has no package");
         System.exit(0);
       } 
-      if ((this!=aClass.packageDesc)&&(!imports.contains(aClass.packageDesc))){ 
-        imports.add(aClass.packageDesc); 
+      if ((this!=aClass.parentPkg)&&
+              (!this.pkgImports.contains(aClass.parentPkg))){ 
+        this.pkgImports.add(aClass.parentPkg); 
       }
     } 
   }
  
   public void AddImport(PackageDesc pack) {
-    if ((this != pack) && (!imports.contains(pack))){ 
-      boolean ok = imports.add(pack); 
+    if ((this != pack) && (!this.pkgImports.contains(pack))){ 
+      boolean ignoreMe = this.pkgImports.add(pack); 
     }
   }
 
   public void ResetImports() {
-    for (int i=0; i < imports.size(); i++) {
-      imports.get(i).impNum = -1;
+    for (int i=0; i < this.pkgImports.size(); i++) {
+      this.pkgImports.get(i).impNum = -1;
     }
   }
 
   private void AddImportList(ArrayList impList) {
     for (int i=0; i < impList.size(); i++) {
-      AddImport((PackageDesc)impList.get(i));
+      // this.AddImport((PackageDesc)impList.get(i));
+      PackageDesc p = (PackageDesc)impList.get(i);
+      this.AddImport(p);
+      System.out.printf("package %s, adding import %s, with APINEEDS=%s\n", 
+              this.cpName, p.cpName, (p.has(Util.APINEEDS) ? "true" : "false"));
     }
   }
 
   public void ReadPackage() throws IOException, FileNotFoundException {
-    boolean ok = syms.add(this);
-    if (anonPackage) {
-      classes = new ClassDesc[1];
-      classes[0] = ClassDesc.GetClassDesc(name,this);
-      boolean ok2 = classes[0].ReadClassFile(J2CPSFiles.OpenClassFile(name));
-      return;
-    } 
-    packageFile = J2CPSFiles.getPackageFile(dirName);
-    String[] classFiles = packageFile.list(new J2CPSFiles());
-    classes = new ClassDesc[classFiles.length];
-    for (int i = 0; i < classFiles.length; i++) {
-      String cName = name + qSepCh + 
-                     classFiles[i].substring(0,classFiles[i].lastIndexOf('.'));
-      ClassDesc nextClass = ClassDesc.GetClassDesc(cName,this);
-      if (nextClass.ReadClassFile(J2CPSFiles.OpenClassFile(packageFile, 
-                                                        classFiles[i]))) {
-        classes[i] = nextClass;
-      }
-    } 
+    boolean ignoreMe;
+    this.processed = true;
+    ignoreMe = syms.add(this);
+    if (this.anonPackage) {
+        ClassDesc newClass;
+        // this.classes = new ClassDesc[1];
+        //
+        // Create a new class descriptor with the given name
+        // in the anonomous package represented by "this".
+        // Then read the class file with the given name.
+        //
+        newClass = ClassDesc.GetClassDesc(this.name,this);
+        this.myClasses.add( newClass );
+        //
+        // this.classes[0] = newClass;
+        // 
+        ignoreMe = newClass.ReadPkgClassFile(j2cpsfiles.OpenClassFile(this.name));
+    } else {
+        this.theFile = j2cpsfiles.getPackageFile(this.dirName);
+        //
+        //  classFilter gets files ending with ".class"
+        //
+        String[] clsNames = this.theFile.list(classFilter);
+        //
+        // Create a descriptor array and populate with the class
+        // descriptors corresponding to the class files in the
+        // directory for the current package.
+        //
+        // this.classes = new ClassDesc[clsNames.length];
+        for (int i = 0; i < clsNames.length; i++) {
+            String cName = name + Util.FWDSLSH + 
+                    clsNames[i].substring(0,clsNames[i].lastIndexOf('.'));
+            ClassDesc nextClass = ClassDesc.GetClassDesc(cName,this);
+            if (nextClass.ReadPkgClassFile(j2cpsfiles.OpenClassFile(this.theFile, clsNames[i]))) {
+                // this.classes[i] = nextClass;
+                this.myClasses.add(nextClass);
+            }
+        }
+    }
   }
 
-  public static void ReadPackages() throws IOException, FileNotFoundException {
+  public static void ProcessPkgWorklist() throws IOException, FileNotFoundException {
     int j = 0;
-    toDo.get(0).ReadPackage();
-
-    if (!ClassDesc.verbose)      // Lightweight progress indicator ...
-      System.out.println("INFO: reading dependents ");
-
+    {
+        PackageDesc pkg0 = toDo.get(0);
+        pkg0.ReadPackage();
+        if (ClassDesc.summary)      // Lightweight progress indicator ...
+          System.out.printf("INFO: locating dependencies of package <%s>\n", pkg0.name);
+    }
+    //
+    //  Reading package pkg0 may have added to the toDo list
+    //
     for (int i=1; i < toDo.size(); i++) {
-      PackageDesc pack = toDo.get(i);
+      PackageDesc pkgDesc = toDo.get(i);
+      if (!pkgDesc.has(Util.APINEEDS)) {
+          if (ClassDesc.verbose)
+              System.out.println("Non API package skipped " + pkgDesc.cpName);
+          continue;
+      }          
       /* look for symbol file first */
-      pack.packageFile = J2CPSFiles.FindSymbolFile(pack.cpName);
-      if (pack.packageFile == null) {
-        pack.ReadPackage();
-        if (!ClassDesc.verbose) { System.out.print('+'); j++; }
-      } else {
-        if (ClassDesc.verbose)  {
-          System.out.println("Reading Symbol File <" + 
-                                             pack.packageFile.getPath() + ">");
+      pkgDesc.theFile = j2cpsfiles.FindSymbolFile(pkgDesc.cpName);
+      if (pkgDesc.theFile == null) { // No symbol file, look for package
+        pkgDesc.ReadPackage();
+      } else { // Symbol file was found ==> Read it.
+        pkgDesc.set(Util.FOUNDCPS);
+        if (ClassDesc.summary)  {
+            System.out.println("Found Symbol file for dependency <" + pkgDesc.cpName + ">");
+            if (ClassDesc.verbose)
+                System.out.println("    Symbol file " + pkgDesc.theFile.getPath());
         }
-        SymbolFile.ReadSymbolFile(pack.packageFile,pack);
-        if (!ClassDesc.verbose) { System.out.print('-'); j++; }
       }
-      if (j >= 79) { System.out.println(); j = 0; }
     }
-    if (!ClassDesc.verbose && j > 0) System.out.println();
   }
+  
+    public static void ProcessJarDependencies() throws IOException, FileNotFoundException  {
+        for (PackageDesc desc : toDo) {
+            if (desc.processed) {
+                syms.add(desc);
+            } else {
+                desc.theFile = j2cpsfiles.FindSymbolFile(desc.cpName);
+                System.out.println("INFO: Searching for imported package " + desc.javaName);
+                if (desc.theFile == null)
+                    System.err.printf(
+                        "       Symbolfile %s not found on CPSYM path\n", desc.cpName);
+                else if (ClassDesc.summary)
+                    System.out.println(
+                        "Found symbol file for dependency <" + desc.cpName  + ">");
+                                
+            }
+        }
+    }
 
-  public static void WriteSymbolFiles() throws IOException {
-    for (int i=0; i < syms.size(); i++) {
-      HashMap<String,MethodInfo> pScope = new HashMap<String,MethodInfo>();
-      PackageDesc nextPack = syms.get(i);
-      for (int j=0; j < nextPack.classes.length; j++) {
-        if (nextPack.classes[j] != null) {
-          if (ClassDesc.overloadedNames) {
-            nextPack.classes[j].GetSuperImports(); 
-          } else {
-            nextPack.classes[j].GetSuperFields(pScope); 
-          }
-          nextPack.AddImportList(nextPack.classes[j].imports);
-          ClassDesc superCl = nextPack.classes[j].superClass;
-          while (superCl != null) {
-            nextPack.AddImport(superCl);
-            nextPack.AddImportList(superCl.imports);
-            superCl = superCl.superClass;
-          }
+    public static void WriteSymbolFiles() throws IOException {
+        for (PackageDesc nextPack : syms) {
+            SymbolFile.WriteSymbolFile(nextPack);
         }
-      }
     }
-    for (int i=0; i < syms.size(); i++) {
-      PackageDesc nextPack = syms.get(i);
-      SymbolFile.WriteSymbolFile(nextPack);
+    
+    public boolean has(int tag) {
+        return (this.status & tag) != Util.PRISTINE;
     }
-  }
-}
+    
+    public void clear(int tag) {
+        this.status ^= tag;
+    }
+    
+    public void set(int tag) {
+        this.status |= tag;
+        int mask = Util.FROMJAR | Util.FROMCLS;
+        if (( this.status & mask) == mask)
+            throw new IllegalArgumentException();
+    }
+}

+ 32 - 19
J2CPS/PtrDesc.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*                Pointer Descriptor class for J2CPS                  */
+/*                Pointer Descriptor class for j2cps                  */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -13,41 +13,54 @@ public class PtrDesc extends TypeDesc {
   TypeDesc boundType;
 
   public PtrDesc(TypeDesc baseType) {
-    typeOrd = TypeDesc.arrPtr;
-    boundType = baseType;
-    if (boundType != null) { 
-        name = "POINTER TO " + boundType.name; 
+    this.typeOrd = TypeDesc.arrPtr;
+    this.boundType = baseType;
+    if (this.boundType != null) { 
+        this.name = "POINTER TO " + this.boundType.name; 
     }
   }
 
   public PtrDesc(int inNum, int baseNum) {
-    typeOrd = TypeDesc.arrPtr;
-    inTypeNum = inNum;
-    inBaseTypeNum = baseNum;
+    this.typeOrd = TypeDesc.arrPtr;
+    this.inTypeNum = inNum;
+    this.inBaseTypeNum = baseNum;
   }
   
   public void Init(TypeDesc baseType) {
-    boundType = baseType;
-    if (boundType != null) { setName(); }
+    this.boundType = baseType;
+    if (this.boundType != null) { setName(); }
   }
 
-  public void AddImport(ClassDesc thisClass) {
-    if (boundType instanceof ClassDesc) {
-      thisClass.AddImport((ClassDesc)boundType);
-    } else if (boundType instanceof ArrayDesc) {
-      ((ArrayDesc)boundType).AddImport(thisClass);
+  public void AddImportToPtr(ClassDesc thisClass) {
+    if (this.boundType instanceof ClassDesc) {
+        ((ClassDesc)this.boundType).blame = this.blame;
+        thisClass.AddImportToClass((ClassDesc)this.boundType);
+    } else if (this.boundType instanceof ArrayDesc) {
+        ((ArrayDesc)this.boundType).blame = this.blame;
+        ((ArrayDesc)this.boundType).AddImportToArray(thisClass);
     }
   }
 
   public void setName() {
-    name = "POINTER TO " + boundType.name;
+    this.name = "POINTER TO " + this.boundType.name;
   }
+  
+  /** Write a pointer type definition to the typelist section of a symbol file.
+   * <p>
+   * A pointer type declaration consists of only an array marker
+   * followed by the type-ordinal of the bound type.
+   * 
+   * @param out  the symbol file output stream
+   * @param thisPack the package which this symbol file describes
+   * @throws IOException 
+   */
+  
 
     @Override
   public void writeType(DataOutputStream out, PackageDesc thisPack) 
                                                            throws IOException {
     out.writeByte(SymbolFile.ptrSy);
-    SymbolFile.writeTypeOrd(out,boundType); 
+    SymbolFile.writeTypeOrd(out,this.boundType); 
   }
 
 

+ 3 - 3
J2CPS/Reference.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*                   Reference class for J2CPS                        */
+/*                   Reference class for j2cps                        */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 public class Reference {
 

+ 3 - 3
J2CPS/StringRef.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*                 String Reference class for J2CPS                   */
+/*                 String Reference class for j2cps                   */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 public class StringRef {
 

+ 544 - 399
J2CPS/SymbolFile.java

@@ -1,12 +1,13 @@
 /**********************************************************************/
-/*                  Symbol File class for J2CPS                       */
+/*                  Symbol File class for j2cps                       */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.io.*;
 import java.util.ArrayList;
+import j2cpsfiles.j2cpsfiles;
 
 class SymbolFile {
  
@@ -22,11 +23,24 @@ class SymbolFile {
   // Import     = impSy Name [String] Key.
   // Constant   = conSy Name Literal.
   // Variable   = varSy Name TypeOrd.
+  // -------- Note --------
+  //  The Type syntax is used to declare the type ordinals 
+  //  that are used for all references to this module's types.
+  // ----------------------
   // Type       = typSy Name TypeOrd.
   // Procedure  = prcSy Name [String] [truSy] FormalType.
   // Method     = mthSy Name Byte Byte TypeOrd [String] FormalType.
   // FormalType = [retSy TypeOrd] frmSy {parSy Byte TypeOrd} endFm.
   // TypeOrd    = ordinal.
+  // -------- Note --------
+  //  TypeHeaders are used in the symbol file format to 
+  //  denote a type that is defined here or is imported.
+  //  For types defined here, the ordinal is that declard
+  //  in the definition section of this symbol file.
+  //  For imported types the first ordinal is the ordinal
+  //  declared in the definition section, the second ordinal
+  //  is the index into the package import list.
+  // ----------------------
   // TypeHeader = tDefS Ord [fromS Ord Name].
   // TypeList   = start {Array | Record | Pointer | ProcType | 
   //                     NamedType | Enum} close.
@@ -67,9 +81,8 @@ class SymbolFile {
   static final String[] mark = {"", "*", "-", "!"};
   static final String[] varMark = {"", "IN", "OUT", "VAR"};
 
-  private static final String spaces = "         ";
-  private static final String recEndSpace = "      "; 
-  private static final char qSepCh = '/';
+  //private static final String spaces = "         ";
+  //private static final String recEndSpace = "      "; 
 
   static final int modSy = (int) 'H';
   static final int namSy = (int) '$';
@@ -129,15 +142,29 @@ class SymbolFile {
   private static char cVal;
   private static double dVal;
   private static DataInputStream in;
-
-// Symbol file writing 
+  
+  private static int count = 0;
+  private static PackageDesc target = null;
+  private static ArrayList<PackageDesc> imps = null;
+  
+// Symbol file writing
 
   static void writeName(DataOutputStream out,int access, String name) 
                                                             throws IOException{
     out.writeByte(namSy);
-    if (ConstantPool.isPublic(access))   { out.writeByte(pubMode); }
-    else if (ConstantPool.isProtected(access)) { out.writeByte(protect); }
-    else /* if (ConstantPool.isPrivate(access)) */ { out.writeByte(prvMode); }
+    if (ConstantPool.isPublic(access))   { 
+        out.writeByte(pubMode); 
+    }
+    else if (ConstantPool.isProtected(access)) { 
+        out.writeByte(protect); 
+    }
+    else /* if (ConstantPool.isPrivate(access)) */ { 
+        out.writeByte(prvMode); 
+    }
+    if (name == null) {
+        name = "DUMMY" + count++;
+        System.err.println( name );
+    }
     out.writeUTF(name);
   }
 
@@ -154,13 +181,13 @@ class SymbolFile {
       out.writeLong(((Integer)val).longValue());
     } else if (val instanceof Long) {
       out.writeByte(numSy);
-      out.writeLong(((Long)val).longValue());
+      out.writeLong(((Long)val));
     } else if (val instanceof Float) {
       out.writeByte(fltSy);
       out.writeDouble(((Float)val).doubleValue());
     } else if (val instanceof Double) {
       out.writeByte(fltSy);
-      out.writeDouble(((Double)val).doubleValue());
+      out.writeDouble(((Double)val));
     } else {
       System.out.println("Unknown constant type");
       System.exit(1);
@@ -170,19 +197,19 @@ class SymbolFile {
   public static void writeOrd(DataOutputStream out,int i) throws IOException {
     // DIAGNOSTIC
     if (i < 0)
-      throw new IOException(); 
+        throw new IOException(); 
     // DIAGNOSTIC
     if (i <= 0x7f) {
-      out.writeByte(i);
+        out.writeByte(i);
     } else if (i <= 0x7fff) {
-      out.writeByte(128 + i % 128);  
-      out.writeByte(i / 128);
+        out.writeByte(128 + i % 128);  
+        out.writeByte(i / 128);
     } else {
-      throw new IOException(); 
+        throw new IOException(); 
     }
   }
 
-  private static void InsertType(TypeDesc ty) {
+  private static void InsertTypeInTypeList(TypeDesc ty) {
     if (ty.outTypeNum > 0) { return; }
     ty.outTypeNum = nextType++;
     if (tListIx >= typeList.length) {
@@ -190,53 +217,91 @@ class SymbolFile {
       System.arraycopy(typeList, 0, tmp, 0, typeList.length);
       typeList = tmp;
     }
+    // Temporary diagnostic code
+    if (ClassDesc.VERBOSE && (ty.name != null)) {
+        System.out.printf("Inserting %s at ix %d\n", ty.name, tListIx);
+        if (ty instanceof ClassDesc 
+                && target != ((ClassDesc)ty).parentPkg
+                && !imps.contains(((ClassDesc)ty).parentPkg)) {
+            System.err.println(ty.name + " not on import list");
+        }
+    }
     typeList[tListIx++] = ty;
   }
 
-  public static void AddType(TypeDesc ty) {
-    InsertType(ty); 
-    if (!ty.writeDetails) { return; }
+  public static void AddTypeToTypeList(TypeDesc ty) {
+    InsertTypeInTypeList(ty); 
+    if (!ty.writeDetails) { 
+        return; 
+    }
     if (ty instanceof ClassDesc) {
-      ClassDesc aClass = (ClassDesc)ty;
-      if (aClass.outBaseTypeNum > 0) { return; }
-      aClass.outBaseTypeNum = nextType++;
-      if (aClass.superClass != null) {
-        aClass.superClass.writeDetails = true; 
-        AddType(aClass.superClass); 
-      }
-      if (aClass.isInterface) {
-        for (int i=0; i < aClass.interfaces.length; i++) {
-          aClass.interfaces[i].writeDetails = true;
-          AddType(aClass.interfaces[i]);
+        ClassDesc aClass = (ClassDesc)ty;
+        if (aClass.outBaseTypeNum > 0) { 
+            return; 
+        }
+        aClass.outBaseTypeNum = nextType++;
+        if (aClass.superClass != null) {
+            aClass.superClass.writeDetails = true; 
+            AddTypeToTypeList(aClass.superClass); 
+        }
+        if (aClass.isInterface) {
+            for (ClassDesc intf : aClass.interfaces) {
+                intf.writeDetails = true;
+                AddTypeToTypeList(intf); // Recurse
+            }
         }
-      }
     } else if (ty instanceof PtrDesc) { 
         ty = ((PtrDesc)ty).boundType; 
-        if (ty.outTypeNum == 0) { AddType(ty); }
+        if (ty.outTypeNum == 0) { 
+            AddTypeToTypeList(ty); 
+        }
     } else if (ty instanceof ArrayDesc) {
-      ty = ((ArrayDesc)ty).elemType;
-      while (ty instanceof ArrayDesc) {
-        ArrayDesc aTy = (ArrayDesc)ty;
-        if (aTy.ptrType.outTypeNum == 0) { InsertType(aTy.ptrType); }
-        if (aTy.outTypeNum == 0) { InsertType(aTy); }
-        ty = aTy.elemType;
-      }                   
-      if (ty.outTypeNum == 0) { InsertType(ty); }
+        ty = ((ArrayDesc)ty).elemType;
+        while (ty instanceof ArrayDesc) {
+            ArrayDesc aTy = (ArrayDesc)ty;
+            if (aTy.ptrType.outTypeNum == 0) { 
+                InsertTypeInTypeList(aTy.ptrType); 
+            }
+            if (aTy.outTypeNum == 0) { 
+                InsertTypeInTypeList(aTy); 
+            }
+            ty = aTy.elemType;
+        }                   
+        if (ty.outTypeNum == 0) { 
+            InsertTypeInTypeList(ty); 
+        }
     }
   }
 
-  static void writeTypeOrd(DataOutputStream out,TypeDesc ty)throws IOException {
-    if (ty.typeOrd < TypeDesc.ordT) { 
-      out.writeByte(ty.typeOrd); 
-    } else {
-      if (ty.outTypeNum == 0) { AddType(ty); }
-      if (ty.outTypeNum == 0) { 
-        System.out.println("ERROR: type has number 0 for type " + ty.name); 
-        System.exit(1); 
-      }
-      writeOrd(out,ty.outTypeNum);
+    /**
+     * Writes out the ordinal number of the type denoted by this
+     * <code>TypeDesc</code> object. If a descriptor does not have
+     * a ordinal already allocated this implies that the type has
+     * not yet been added to the type-list. In this case the type
+     * is added to the list and an ordinal allocated.
+     * <p>
+     * Builtin types have pre-allocated type ordinal, less than 
+     * <code>TypeDesc.ordT</code>.
+     * @param out The data stream to which the symbol file is being written.
+     * @param ty The <code>TypeDesc</code> whose type ordinal is required.
+     * @throws IOException 
+     */
+    static void writeTypeOrd(DataOutputStream out,TypeDesc ty)throws IOException {
+        if (ty.typeOrd < TypeDesc.ordT) { 
+            // ==> ty is a builtin type.
+            out.writeByte(ty.typeOrd); 
+        } else {
+            if (ty.outTypeNum == 0) { 
+              // ==> ty is a class type.
+              AddTypeToTypeList(ty); // blame ty
+            }
+            if (ty.outTypeNum == 0) { 
+                System.out.println("ERROR: type has number 0 for type " + ty.name); 
+                System.exit(1); 
+            }
+            writeOrd(out,ty.outTypeNum);
+        }
     }
-  }
 
   public static void WriteFormalType(MethodInfo m,DataOutputStream out) 
                                                      throws IOException {
@@ -245,52 +310,82 @@ class SymbolFile {
       writeTypeOrd(out,m.retType);
     } 
     out.writeByte(frmSy);
-    for (int i=0; i < m.parTypes.length; i++) {
-      out.writeByte(parSy);
-      if (m.parTypes[i] instanceof ArrayDesc) {
-        out.writeByte(1);   // array params are IN
-      } else {
-        out.writeByte(0);   // all other java parameters are value 
+      for (TypeDesc parType : m.parTypes) {
+          out.writeByte(parSy);
+          if (parType instanceof ArrayDesc) {
+              out.writeByte(1);   // array params are IN
+          } else {
+              out.writeByte(0);   // all other java parameters are value 
+          }
+          writeTypeOrd(out, parType);
       }
-      writeTypeOrd(out,m.parTypes[i]);
-    }
     out.writeByte(endFm);
   }
 
   public static void WriteSymbolFile(PackageDesc thisPack) throws IOException{
     ClearTypeList();
-    DataOutputStream out = J2CPSFiles.CreateSymFile(thisPack.cpName);
-
-    System.out.println("INFO:  Creating symbol file " + thisPack.cpName);
-
+    DataOutputStream out = j2cpsfiles.CreateSymFile(thisPack.cpName);
     out.writeInt(magic);
     out.writeByte(modSy);
     writeName(out,0,thisPack.cpName);
     writeString(out,thisPack.javaName);
     out.writeByte(falSy); /* package is not an interface */
-    for (int i=0; i < thisPack.imports.size(); i++) {
-      out.writeByte(impSy);
-      PackageDesc imp = (PackageDesc)thisPack.imports.get(i);
-      imp.impNum = i+1;
-      writeName(out,0,imp.cpName);
-      writeString(out,imp.javaName);
-      out.writeByte(keySy);
-      out.writeInt(0);
+    // #############################
+    imps = thisPack.pkgImports;
+    target = thisPack;
+    // #############################
+    //
+    //  Emit package import list
+    //    Import = impSy Name [String] Key.
+    //  Imports are given an index as they are listed.
+    //
+    for (int i=0; i < thisPack.pkgImports.size(); i++) {
+        out.writeByte(impSy);
+        PackageDesc imp = (PackageDesc)thisPack.pkgImports.get(i);
+        // -------------------
+        if (ClassDesc.VERBOSE)
+            System.out.printf("import %d %s %d\n", 
+                i, 
+               (imp.javaName == null ? "null" : imp.javaName), 
+                i+1);      
+        // -------------------
+        imp.impNum = i+1;
+        writeName(out,0,imp.cpName);
+        writeString(out,imp.javaName);
+        out.writeByte(keySy);
+        out.writeInt(0);
     }
-    for (int cNum=0; cNum < thisPack.classes.length; cNum++) {
-      ClassDesc thisClass = thisPack.classes[cNum];
-      if ((thisClass != null) && ConstantPool.isPublic(thisClass.access)) {
-        thisClass.writeDetails = true;
-        out.writeByte(typSy);
-        writeName(out,thisClass.access,thisClass.objName);
-        writeTypeOrd(out,thisClass);
-      }
+    for (ClassDesc thisClass : thisPack.myClasses) {
+        if ((thisClass != null) && ConstantPool.isPublic(thisClass.access)) {
+            // -------------------
+            if (ClassDesc.verbose)
+                System.out.printf("Member class %s\n", thisClass.javaName);   
+            // -------------------
+            // This class is a class of the package being
+            // emitted to this symbol file. Details are required.
+            // -------------------
+            thisClass.writeDetails = true;
+            out.writeByte(typSy);
+            writeName(out,thisClass.access,thisClass.objName);
+            writeTypeOrd(out,thisClass);
+        }
     }
+    //
+    //  Write out typelist
+    //
     out.writeByte(start);
     for (int i=0; i < tListIx; i++) {
-      out.writeByte(tDefS);
-      writeOrd(out,typeList[i].outTypeNum);
-      typeList[i].writeType(out,thisPack);
+        TypeDesc desc = typeList[i];
+        // -------------------
+        if (ClassDesc.VERBOSE) 
+            System.out.printf("typeList element %d (of %d) %s %d\n", 
+                i, tListIx,
+               (desc.name == null ? "null" : desc.name), 
+                desc.outTypeNum); 
+        // -------------------
+        out.writeByte(tDefS);
+        writeOrd(out,desc.outTypeNum);      
+        desc.writeType(out, thisPack);
     }
     out.writeByte(close);
     out.writeByte(keySy);
@@ -298,8 +393,9 @@ class SymbolFile {
     thisPack.ResetImports();
   }
 
-// Symbol file reading 
-
+  //
+  // Symbol file reading 
+  //
   private static void InsertType(int tNum,TypeDesc ty) {
     if (tNum >= typeList.length) {
       int newLen = 2 * typeList.length;
@@ -384,42 +480,57 @@ class SymbolFile {
 
   private static void SkipToEndRec(DataInputStream in) throws IOException {
     while (sSym != endRc) { 
-      if (sSym == mthSy) {
-        GetSym(); // name
-        in.readByte(); 
-        in.readByte();
-        readOrd();
-      } else if (sSym == varSy) {
-        GetSym(); // name
-        readOrd();
-      } else if (sSym == conSy) {
-        GetSym(); // name
-        GetSym(); // Literal
-      } else if (sSym == prcSy) {
-        GetSym(); // name
-      } else if (sSym == parSy) {
-        in.readByte();
-        readOrd();
-      } else if (sSym == namSy) {
-        readOrd();
-      } else {
-      }
+        switch (sSym) {
+            case mthSy:
+                GetSym(); // name
+                in.readByte();
+                in.readByte();
+                readOrd();
+                break;
+            case varSy:
+                GetSym(); // name
+                readOrd();
+                break;
+            case conSy:
+                GetSym(); // name
+                GetSym(); // Literal
+                break;
+            case prcSy:
+                GetSym(); // name
+                break;
+            case parSy:
+                in.readByte();
+                readOrd();
+                break;
+            case namSy:
+                readOrd();
+                break;
+            default:
+                break;
+        }
       GetSym(); 
     }
   }
 
   private static int GetAccess() {
-    if (acc == prvMode) { return ConstantPool.ACC_PRIVATE; }
-    else if (acc == pubMode) { return ConstantPool.ACC_PUBLIC; }
-    else if (acc == protect) { return ConstantPool.ACC_PROTECTED; }
+      switch (acc) {
+          case prvMode:
+              return ConstantPool.ACC_PRIVATE;
+          case pubMode:
+              return ConstantPool.ACC_PUBLIC;
+          case protect:
+              return ConstantPool.ACC_PROTECTED;
+          default:
+              break;
+      }
     return 0;
   }
 
   private static ClassDesc GetClassDesc(PackageDesc thisPack,String className) {
-    ClassDesc aClass = ClassDesc.GetClassDesc(thisPack.name + qSepCh + 
+    ClassDesc aClass = ClassDesc.GetClassDesc(thisPack.name + Util.FWDSLSH + 
                                               className,thisPack);
-    if (aClass.fieldList == null){ aClass.fieldList = new ArrayList(); }
-    if (aClass.methodList == null){ aClass.methodList = new ArrayList(); }
+    if (aClass.fieldList == null){ aClass.fieldList = new ArrayList<>(); }
+    if (aClass.methodList == null){ aClass.methodList = new ArrayList<>(); }
     return aClass;
   }
 
@@ -435,15 +546,15 @@ class SymbolFile {
     Expect(namSy); 
     switch (sSym) {
       case numSy : typ = TypeDesc.GetBasicType(TypeDesc.longT); 
-                   val = new Long(lVal); break;
+                   val = lVal; break;
       case strSy : typ = TypeDesc.GetBasicType(TypeDesc.strT);
-                   val = name; 
+                   val = name; break;
       case setSy : typ = TypeDesc.GetBasicType(TypeDesc.setT);
-                   val = new Integer(iVal); break;
+                   val = iVal; break;
       case chrSy : typ = TypeDesc.GetBasicType(TypeDesc.charT);
-                   val = new Character(cVal); break;
+                   val = cVal; break;
       case fltSy : typ = TypeDesc.GetBasicType(TypeDesc.dbleT);
-                   val = new Double(dVal); break;
+                   val = dVal; break;
       case falSy : typ = TypeDesc.GetBasicType(TypeDesc.boolT);
                    val = false; break;
       case truSy : typ = TypeDesc.GetBasicType(TypeDesc.boolT);
@@ -545,7 +656,9 @@ class SymbolFile {
     Expect(namSy); 
     if (sSym == strSy) { jName = name; GetSym();  }
     MethodInfo m = new MethodInfo(pClass,procName,jName,pAcc); 
-    if (sSym == truSy) { m.isInitProc = true; GetSym();  }
+    if (sSym == truSy) { 
+        m.isInitProc = true; GetSym();  
+    }
     GetFormalType(pClass,m);
     pClass.methodList.add(m);
   }
@@ -592,291 +705,323 @@ class SymbolFile {
     return typeList[num];
   } 
 
-  public static void ReadSymbolFile(File symFile,PackageDesc thisPack) 
-                                     throws FileNotFoundException, IOException {
-
-    if (ClassDesc.verbose)
-      System.out.println("INFO:  Reading symbol file " + symFile.getName());
-
-    ClearTypeList();
-    ClassDesc aClass, impClass;
-    int maxInNum = 0;
-    FileInputStream fIn = new FileInputStream(symFile);
-    in = new DataInputStream(fIn);
-    if (in.readInt() != magic) {
-      System.out.println(symFile.getName() + " is not a valid symbol file.");
-      System.exit(1);
-    }
-    GetSym();
-    Expect(modSy);
-    if (!thisPack.cpName.equals(name)) {
-      System.out.println("ERROR:  Symbol file " + symFile.getName() + 
-      " does not contain MODULE " + thisPack.cpName + ", it contains MODULE " +
-      name);
-      System.exit(1);
-    }
-    Expect(namSy);
-    if (sSym == strSy) { 
-      if (!name.equals(thisPack.javaName)) { 
-        System.out.println("Wrong name in symbol file.");
-        System.exit(1); 
-      }
-      GetSym();
-      if (sSym == truSy) {  
-        System.out.println("ERROR:  Java Package cannot be an interface.");
-        System.exit(1);
-      }
-      GetSym();
-    } else {
-      System.err.println("<" + symFile.getName() + 
-                         "> NOT A SYMBOL FILE FOR A JAVA PACKAGE!");
-      System.exit(1);
-    }
-    while (sSym != start) {
-      switch (sSym) {
-        case impSy : GetSym(); // name
-                     String iName = name;
-                     GetSym(); 
-                     if (sSym == strSy) { 
-                       PackageDesc pack = PackageDesc.getPackage(name);
-                       thisPack.imports.add(pack);
-                       GetSym(); 
-                     }
-                     Expect(keySy);  
-                     break;
-        case conSy : 
-        case varSy : 
-        case prcSy : System.out.println("Symbol File is not from a java class");
-                     System.exit(1);
-                     break;
-        case typSy : GetType(thisPack); break;
-      }
-    }
-    Expect(start);
-    while (sSym != close) {
-      PackageDesc impPack;
-      impClass = null;
-      String impModName = null;
-      int impAcc = 0, impModAcc = 0;
-      Check(tDefS); 
-      int tNum = tOrd; GetSym(); 
-      if (tNum > maxInNum) { maxInNum = tNum; }
-      if (sSym == fromS) {
-        int impNum = tOrd - 1;
-        GetSym(); 
-        Check(namSy);
-        String impName = name;
-        impAcc = acc; 
-        if (impNum < 0) {
-          impPack = thisPack;
-        } else {
-          impPack = (PackageDesc)thisPack.imports.get(impNum);
+    public static void ReadSymbolFile(File symFile, PackageDesc thisPack)
+            throws FileNotFoundException, IOException {
+        if (ClassDesc.verbose) {
+            System.out.println("INFO:  Reading symbol file " + symFile.getName());
         }
-        impClass = GetClassDesc(impPack,impName);
-        GetSym(); 
-      }
-      switch (sSym) { 
-        case arrSy : ArrayDesc newArr = null;
-                     int elemOrd = tOrd;
-                     GetSym();
-                     Expect(endAr);
-                     TypeDesc eTy = null;
-                     if (elemOrd < typeList.length) {
-                       if (elemOrd < TypeDesc.specT) { 
-                         eTy = TypeDesc.GetBasicType(elemOrd); 
-                       } else { 
-                         eTy = typeList[elemOrd]; 
-                       }
-                       if ((eTy != null) && (eTy instanceof PtrDesc) &&
-                          (((PtrDesc)eTy).boundType != null) && 
-                          (((PtrDesc)eTy).boundType instanceof ClassDesc)) {
-                         eTy = ((PtrDesc)eTy).boundType;   
-                       } 
-                     }
-                     if (eTy != null) {
-                       newArr = ArrayDesc.FindArrayType(1,eTy,true); 
-                     } else {
-                       newArr = new ArrayDesc(elemOrd); 
-                     }
-                     if ((tNum < typeList.length) && (typeList[tNum] != null)) {
-                       PtrDesc desc = (PtrDesc) typeList[tNum];
-                       if (desc.inBaseTypeNum != tNum) {
-                         System.out.println("WRONG BASE TYPE FOR POINTER!");
-                         System.exit(1);
-                       }
-                       desc.Init(newArr);
-                       newArr.SetPtrType(desc);
-                     }
-                     InsertType(tNum,newArr);
-                     break; 
-        case ptrSy : TypeDesc ty = null;
-                     if (impClass != null) { 
-                       InsertType(tNum,impClass);
-                       ty = impClass;
-                       ty.inTypeNum = tNum;
-                       ty.inBaseTypeNum = tOrd;
-                       InsertType(tOrd,ty);
-                     } else if ((tNum < typeList.length) && 
-                                (typeList[tNum] != null) &&
-                                (typeList[tNum] instanceof ClassDesc)) { 
-                       ty = typeList[tNum];
-                       ty.inTypeNum = tNum;
-                       ty.inBaseTypeNum = tOrd;
-                       InsertType(tOrd,ty);
-                     } else {
-                       ty = new PtrDesc(tNum,tOrd);
-                       InsertType(tNum,ty);
-                       if ((tOrd < typeList.length) && 
-                                (typeList[tOrd] != null)) { 
-                         ((PtrDesc)ty).Init(typeList[tOrd]);
-                       }
-                     }
-                     GetSym();
-                     break; 
-        case recSy : if ((tNum >= typeList.length) || (typeList[tNum] == null)||
-                         (!(typeList[tNum] instanceof ClassDesc))) {
-                     /* cannot have record type that is not a base type
-                        of a pointer in a java file                     */
-                       System.err.println(
-                         "RECORD TYPE " + tNum + " IS NOT POINTER BASE TYPE!");
-                       System.exit(1);
-                     }
-                     aClass = (ClassDesc) typeList[tNum];
-                     acc = in.readByte();
-                     aClass.setRecAtt(acc);
-                     if (aClass.read) { 
-                       GetSym();
-                       SkipToEndRec(in); 
-                       GetSym();
-                     } else {
-                       GetSym();
-                       if (sSym == truSy) { 
-                         aClass.isInterface = true; 
-                         GetSym();
-                       } else if (sSym == falSy) { 
-                         GetSym(); 
-                       }
-                       if (sSym == basSy) { 
-                         aClass.superNum = tOrd; 
-                         GetSym(); 
-                       }
-                       if (sSym == iFcSy) {
-                         GetSym();
-                         aClass.intNums = new int[10];
-                         aClass.numInts = 0;
-                         while (sSym == basSy) {
-                           if (aClass.numInts >= aClass.intNums.length) {
-                             int tmp[] = new int[aClass.intNums.length*2];
-                             System.arraycopy(aClass.intNums, 0, tmp, 0, aClass.intNums.length);
-                             aClass.intNums = tmp;
-                           }
-                           aClass.intNums[aClass.numInts] = tOrd;
-                           aClass.numInts++;
-                           GetSym();
-                         }
-                       }
-                       while (sSym == namSy) {
-                         FieldInfo f = new FieldInfo(aClass,GetAccess(),name,
-                                       null,null); 
-                         f.typeFixUp = readOrd(); 
-                         GetSym();
-                         boolean ok = aClass.fieldList.add(f);
-                         aClass.scope.put(f.name,f);
-                       } 
-                       while ((sSym == mthSy) || (sSym == prcSy) ||
-                              (sSym == varSy) || (sSym == conSy)) { 
-                         switch (sSym) {
-                           case mthSy : GetMethod(aClass); break; 
-                           case prcSy : GetProc(aClass); break;
-                           case varSy : GetVar(aClass); break;
-                           case conSy : GetConstant(aClass); break;
-                         }
-                       }
-                       Expect(endRc);
-                     }
-                     break; 
-        case pTpSy : System.out.println("CANNOT HAVE PROC TYPE IN JAVA FILE!"); 
-                     break;
-        case evtSy :System.out.println("CANNOT HAVE EVENT TYPE IN JAVA FILE!"); 
-                     break;
-        case eTpSy : System.out.println("CANNOT HAVE ENUM TYPE IN JAVA FILE!"); 
-                     break;
-        case tDefS : 
-        case close : InsertType(tNum,impClass);
-                     break;
-        default : char ch = (char) sSym; 
-                  System.out.println("UNRECOGNISED TYPE!" + sSym + "  " + ch); 
-                  System.exit(1);
-      }
-    }
-    Expect(close);
-    Check(keySy); 
-    fIn.close();
-    // do fix ups...
-    for (int i = TypeDesc.specT; i <= maxInNum; i++) {
-      if ((typeList[i] != null) && (typeList[i] instanceof ClassDesc)) {
-        if (!((ClassDesc)typeList[i]).read) {
-          aClass = (ClassDesc)typeList[i];
-          if (aClass.superNum != 0) {
-            aClass.superClass = (ClassDesc)typeList[aClass.superNum];
-          }
-          aClass.interfaces = new ClassDesc[aClass.numInts];
-          for (int j=0; j < aClass.numInts; j++) {
-            aClass.interfaces[j] = (ClassDesc) GetFixUpType(aClass.intNums[j]); 
-          }
-          int size;
-          if (aClass.fieldList == null) { 
-            size = 0; 
-          } else {
-            size = aClass.fieldList.size(); 
-          }
-          aClass.fields = new FieldInfo[size];
-          for (int j=0; j < size; j++) {
-            aClass.fields[j] = (FieldInfo)aClass.fieldList.get(j);
-            aClass.fields[j].type = GetFixUpType(aClass.fields[j].typeFixUp); 
-            if (aClass.fields[j].type instanceof ClassDesc) {
-              aClass.AddImport((ClassDesc)aClass.fields[j].type);
-            }  
-          }
-          aClass.fieldList = null;
-          if (aClass.methodList == null) { size = 0;
-          } else { size = aClass.methodList.size(); }
-          aClass.methods = new MethodInfo[size];
-          for (int k=0; k < size; k++) {
-            aClass.methods[k] = (MethodInfo)aClass.methodList.get(k);
-            aClass.methods[k].retType = GetFixUpType(
-                                        aClass.methods[k].retTypeFixUp); 
-            if (aClass.methods[k].retType instanceof ClassDesc) {
-              aClass.AddImport((ClassDesc)aClass.methods[k].retType);
-            }  
-            aClass.methods[k].parTypes = new TypeDesc[
-                                         aClass.methods[k].parFixUps.length];
-            for (int j=0; j < aClass.methods[k].parFixUps.length; j++) {
-              aClass.methods[k].parTypes[j] = GetFixUpType(
-                                              aClass.methods[k].parFixUps[j]);
-              if (aClass.methods[k].parTypes[j] instanceof ClassDesc) {
-                aClass.AddImport((ClassDesc)aClass.methods[k].parTypes[j]);
-              }  
+
+        ClearTypeList();
+        ClassDesc aClass, impClass;
+        int maxInNum = 0;
+        //
+        //  Read the symbol file and create descriptors
+        //
+        try (FileInputStream fIn = new FileInputStream(symFile)) {
+            in = new DataInputStream(fIn);
+            if (in.readInt() != magic) {
+                System.out.println(symFile.getName() + " is not a valid symbol file.");
+                System.exit(1);
             }
-          }
-          aClass.methodList = null;
-          aClass.read = true;
-          aClass.done = true;
+            GetSym();
+            Expect(modSy);
+            if (!thisPack.cpName.equals(name)) {
+                System.out.println("ERROR:  Symbol file " + symFile.getName()
+                        + " does not contain MODULE " + thisPack.cpName + ", it contains MODULE "
+                        + name);
+                System.exit(1);
+            }
+            Expect(namSy);
+            if (sSym == strSy) {
+                if (!name.equals(thisPack.javaName)) {
+                    System.out.println("Wrong name in symbol file.");
+                    System.exit(1);
+                }
+                GetSym();
+                if (sSym == truSy) {
+                    System.out.println("ERROR:  Java Package cannot be an interface.");
+                    System.exit(1);
+                }
+                GetSym();
+            } else {
+                System.err.println("<" + symFile.getName()
+                        + "> NOT A SYMBOL FILE FOR A JAVA PACKAGE!");
+                System.exit(1);
+            }
+            while (sSym != start) {
+                switch (sSym) {
+                    case impSy:
+                        GetSym(); // name
+                        String iName = name;
+                        GetSym();
+                        if (sSym == strSy) {
+                            PackageDesc pack = PackageDesc.getPackage(name);
+                            thisPack.pkgImports.add(pack);
+                            GetSym();
+                        }
+                        Expect(keySy);
+                        break;
+                    case conSy:
+                    case varSy:
+                    case prcSy:
+                        System.out.println("Symbol File is not from a java class");
+                        System.exit(1);
+                        break;
+                    case typSy:
+                        GetType(thisPack);
+                        break;
+                }
+            }
+            Expect(start);
+            while (sSym != close) {
+                PackageDesc impPack;
+                impClass = null;
+                String impModName = null;
+                int impAcc = 0,
+                        impModAcc = 0;
+                Check(tDefS);
+                int tNum = tOrd;
+                GetSym();
+                if (tNum > maxInNum) {
+                    maxInNum = tNum;
+                }
+                if (sSym == fromS) {
+                    int impNum = tOrd - 1;
+                    GetSym();
+                    Check(namSy);
+                    String impName = name;
+                    impAcc = acc;
+                    if (impNum < 0) {
+                        impPack = thisPack;
+                    } else {
+                        impPack = (PackageDesc) thisPack.pkgImports.get(impNum);
+                    }
+                    impClass = GetClassDesc(impPack, impName);
+                    GetSym();
+                }
+                switch (sSym) {
+                    case arrSy:
+                        ArrayDesc newArr;
+                        int elemOrd = tOrd;
+                        GetSym();
+                        Expect(endAr);
+                        TypeDesc eTy = null;
+                        if (elemOrd < typeList.length) {
+                            if (elemOrd < TypeDesc.specT) {
+                                eTy = TypeDesc.GetBasicType(elemOrd);
+                            } else {
+                                eTy = typeList[elemOrd];
+                            }
+                            if ((eTy != null) && (eTy instanceof PtrDesc)
+                                    && (((PtrDesc) eTy).boundType != null)
+                                    && (((PtrDesc) eTy).boundType instanceof ClassDesc)) {
+                                eTy = ((PtrDesc) eTy).boundType;
+                            }
+                        }
+                        if (eTy != null) {
+                            newArr = ArrayDesc.FindOrCreateArrayType(1, eTy, true);
+                        } else {
+                            newArr = new ArrayDesc(elemOrd);
+                        }
+                        if ((tNum < typeList.length) && (typeList[tNum] != null)) {
+                            PtrDesc desc = (PtrDesc) typeList[tNum];
+                            if (desc.inBaseTypeNum != tNum) {
+                                System.out.println("WRONG BASE TYPE FOR POINTER!");
+                                System.exit(1);
+                            }
+                            desc.Init(newArr);
+                            newArr.SetPtrType(desc);
+                        }
+                        InsertType(tNum, newArr);
+                        break;
+                    case ptrSy:
+                        TypeDesc ty;
+                        if (impClass != null) {
+                            InsertType(tNum, impClass);
+                            ty = impClass;
+                            ty.inTypeNum = tNum;
+                            ty.inBaseTypeNum = tOrd;
+                            InsertType(tOrd, ty);
+                        } else if ((tNum < typeList.length)
+                                && (typeList[tNum] != null)
+                                && (typeList[tNum] instanceof ClassDesc)) {
+                            ty = typeList[tNum];
+                            ty.inTypeNum = tNum;
+                            ty.inBaseTypeNum = tOrd;
+                            InsertType(tOrd, ty);
+                        } else {
+                            ty = new PtrDesc(tNum, tOrd);
+                            InsertType(tNum, ty);
+                            if ((tOrd < typeList.length)
+                                    && (typeList[tOrd] != null)) {
+                                ((PtrDesc) ty).Init(typeList[tOrd]);
+                            }
+                        }
+                        GetSym();
+                        break;
+                    case recSy:
+                        if ((tNum >= typeList.length) 
+                                || (typeList[tNum] == null)
+                                || (!(typeList[tNum] instanceof ClassDesc))) {
+                            /* cannot have record type that is not a base type
+                               of a pointer in a java file                     */
+                            System.err.println(
+                                    "RECORD TYPE " + tNum + " IS NOT POINTER BASE TYPE!");
+                            System.exit(1);
+                        }
+                        aClass = (ClassDesc) typeList[tNum];
+                        acc = in.readByte();
+                        aClass.setRecAtt(acc);
+                        if (aClass.read) {
+                            GetSym();
+                            SkipToEndRec(in);
+                            GetSym();
+                        } else {
+                            GetSym();
+                            if (sSym == truSy) {
+                                aClass.isInterface = true;
+                                GetSym();
+                            } else if (sSym == falSy) {
+                                GetSym();
+                            }
+                            if (sSym == basSy) {
+                                aClass.superNum = tOrd;
+                                GetSym();
+                            }
+                            if (sSym == iFcSy) {
+                                GetSym();
+                                aClass.intNums = new int[10];
+                                aClass.numInts = 0;
+                                while (sSym == basSy) {
+                                    if (aClass.numInts >= aClass.intNums.length) {
+                                        int tmp[] = new int[aClass.intNums.length * 2];
+                                        System.arraycopy(aClass.intNums, 0, tmp, 0, aClass.intNums.length);
+                                        aClass.intNums = tmp;
+                                    }
+                                    aClass.intNums[aClass.numInts] = tOrd;
+                                    aClass.numInts++;
+                                    GetSym();
+                                }
+                            }
+                            while (sSym == namSy) {
+                                FieldInfo f = new FieldInfo(aClass, GetAccess(), name,
+                                        null, null);
+                                f.typeFixUp = readOrd();
+                                GetSym();
+                                boolean ok = aClass.fieldList.add(f);
+                                aClass.scope.put(f.name, f);
+                            }
+                            while ((sSym == mthSy) || (sSym == prcSy)
+                                    || (sSym == varSy) || (sSym == conSy)) {
+                                switch (sSym) {
+                                    case mthSy:
+                                        GetMethod(aClass);
+                                        break;
+                                    case prcSy:
+                                        GetProc(aClass);
+                                        break;
+                                    case varSy:
+                                        GetVar(aClass);
+                                        break;
+                                    case conSy:
+                                        GetConstant(aClass);
+                                        break;
+                                }
+                            }
+                            Expect(endRc);
+                        }
+                        break;
+                    case pTpSy:
+                        System.out.println("CANNOT HAVE PROC TYPE IN JAVA FILE!");
+                        break;
+                    case evtSy:
+                        System.out.println("CANNOT HAVE EVENT TYPE IN JAVA FILE!");
+                        break;
+                    case eTpSy:
+                        System.out.println("CANNOT HAVE ENUM TYPE IN JAVA FILE!");
+                        break;
+                    case tDefS:
+                    case close:
+                        InsertType(tNum, impClass);
+                        break;
+                    default:
+                        char ch = (char) sSym;
+                        System.out.println("UNRECOGNISED TYPE!" + sSym + "  " + ch);
+                        System.exit(1);
+                }
+            }
+            Expect(close);
+            Check(keySy);
         }
-      } else if ((typeList[i] != null) && (typeList[i] instanceof ArrayDesc)) {
-        FixArrayElemType((ArrayDesc)typeList[i]);
-      } else if ((typeList[i] != null) && (typeList[i] instanceof PtrDesc)) {
-        PtrDesc ptr = (PtrDesc)typeList[i];
-        if (ptr.typeOrd == TypeDesc.arrPtr) { 
-          ptr.Init(typeList[ptr.inBaseTypeNum]);
+        //
+        //  Now do the type fixups
+        //
+        for (int i = TypeDesc.specT; i <= maxInNum; i++) {
+            if ((typeList[i] != null) && (typeList[i] instanceof ClassDesc)) {
+                if (!((ClassDesc) typeList[i]).read) {
+                    aClass = (ClassDesc) typeList[i];
+                    if (aClass.superNum != 0) {
+                        aClass.superClass = (ClassDesc) typeList[aClass.superNum];
+                    }
+                    aClass.interfaces = new ClassDesc[aClass.numInts];
+                    for (int j = 0; j < aClass.numInts; j++) {
+                        aClass.interfaces[j] = (ClassDesc) GetFixUpType(aClass.intNums[j]);
+                    }
+                    int size;
+                    if (aClass.fieldList == null) {
+                        size = 0;
+                    } else {
+                        size = aClass.fieldList.size();
+                    }
+                    //aClass.fields = new FieldInfo[size];
+                    for (int j = 0; j < size; j++) {
+                        FieldInfo fieldJ = (FieldInfo) aClass.fieldList.get(j);
+                        //aClass.fields[j] = fieldJ;
+                        fieldJ.type = GetFixUpType(fieldJ.typeFixUp);
+                        if (fieldJ.type instanceof ClassDesc) { // FIXME And is public?
+                            aClass.AddImportToClass((ClassDesc) fieldJ.type);
+                        }
+                    }
+                    aClass.fieldList = null;
+                    if (aClass.methodList == null) {
+                        size = 0;
+                    } else {
+                        size = aClass.methodList.size();
+                    }
+                    //aClass.methods = new MethodInfo[size];
+                    for (int k = 0; k < size; k++) {
+                        MethodInfo methodK = (MethodInfo) aClass.methodList.get(k);
+                        //aClass.methods[k] = methodK;
+                        methodK.retType = GetFixUpType(methodK.retTypeFixUp);
+                        if (methodK.retType instanceof ClassDesc) {
+                            aClass.AddImportToClass((ClassDesc) methodK.retType);
+                        }
+                        methodK.parTypes = new TypeDesc[methodK.parFixUps.length];
+                        for (int j = 0; j < methodK.parFixUps.length; j++) {
+                            methodK.parTypes[j] = GetFixUpType(methodK.parFixUps[j]);
+                            if (methodK.parTypes[j] instanceof ClassDesc) {
+                                aClass.AddImportToClass((ClassDesc) methodK.parTypes[j]);
+                            }
+                        }
+                    }
+                    aClass.methodList = null;
+                    aClass.read = true;
+                    aClass.done = true;
+                }
+            } else if ((typeList[i] != null) && (typeList[i] instanceof ArrayDesc)) {
+                FixArrayElemType((ArrayDesc) typeList[i]);
+            } else if ((typeList[i] != null) && (typeList[i] instanceof PtrDesc)) {
+                PtrDesc ptr = (PtrDesc) typeList[i];
+                if (ptr.typeOrd == TypeDesc.arrPtr) {
+                    ptr.Init(typeList[ptr.inBaseTypeNum]);
+                }
+            } else if (typeList[i] != null) {
+                System.out.println("Type " + i + " " + typeList[i].name
+                        + " is NOT array or class");
+                System.exit(0);
+            }
         }
-      } else if (typeList[i] != null) { 
-        System.out.println("Type " + i + " " + typeList[i].name + 
-                           " is NOT array or class"); 
-        System.exit(0);
-      }
     }
-  }
 }
 
 

+ 62 - 22
J2CPS/TypeDesc.java

@@ -1,9 +1,9 @@
 /**********************************************************************/
-/*                 Type Descriptor class for J2CPS                    */
+/*                 Type Descriptor class for j2cps                    */
 /*                                                                    */   
-/*                      (c) copyright QUT                             */ 
+/*  (c) copyright QUT, John Gough 2000-2012, John Gough, 2012-2017    */ 
 /**********************************************************************/
-package J2CPS;
+package j2cps;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -31,20 +31,47 @@ public class TypeDesc {
   public static final int arrT   = 17;
   public static final int classT = 18;
   public static final int arrPtr = 19;
+  
   public int typeFixUp = 0;
 
   private static final String[] typeStrArr = 
                               { "?","B","c","C","b","i","I","L","r","R",
                                 "?","?","?","?","?","?","?","a","O","?"};
+  
+  /**
+   *  Component Pascal version of java language name
+   */
   public String name;
+  
+  /**
+   *  If this boolean is true then the type is
+   *  dumped to the symbol file with full 
+   *  member information. If false just the 
+   *  name and type ordinal number is emitted.
+   */
   public boolean writeDetails = false;
-  public PackageDesc packageDesc = null;
+  
+  /**
+   *  This field holds the package descriptor
+   *  to which this type belongs.
+   */
+  public PackageDesc parentPkg = null;
+  
+    // ###########################
+    // Temporary code for finding rogue elements in imports lists.
+    // MethodInfo or FieldInfo that caused addition to import list.
+    Object blame = null;
+    // ###########################
+
 
   private static TypeDesc[] basicTypes = new TypeDesc[specT];
 
-  int inTypeNum=0, outTypeNum=0, inBaseTypeNum = 0;
-  int typeOrd = 0;
-  static ArrayList<TypeDesc> types = new ArrayList<TypeDesc>();
+  int   inTypeNum=0; 
+  int   outTypeNum=0; 
+  int   inBaseTypeNum = 0;
+  int   typeOrd = 0;
+  
+  static ArrayList<TypeDesc> types = new ArrayList<>();
 
   public TypeDesc() {
     inTypeNum = 0;
@@ -63,19 +90,21 @@ public class TypeDesc {
     return typeStrArr[typeOrd];
   }
 
+  
   public static TypeDesc GetBasicType(int index) {
     return basicTypes[index];
   }
 
   public static TypeDesc GetType(String sig,int start) {
     int tOrd = GetTypeOrd(sig,start);
-    if (tOrd == classT) {
-      return ClassDesc.GetClassDesc(GetClassName(sig,start),null);
-    } else if (tOrd == arrT) {
-      return ArrayDesc.GetArrayType(sig,start,true);
-    } else {
-      return basicTypes[tOrd]; 
-    }
+      switch (tOrd) {
+          case classT:
+              return ClassDesc.GetClassDesc(GetClassName(sig,start),null);
+          case arrT:
+              return ArrayDesc.GetArrayTypeFromSig(sig,start,true);
+          default:
+              return basicTypes[tOrd];
+      }
   }
   
   private static String GetClassName(String sig,int start) {
@@ -118,17 +147,28 @@ public class TypeDesc {
     int index = 1;
     while (sig.charAt(index) != ')') {
       if (sig.charAt(index) == '[') { 
-        types.add(ArrayDesc.GetArrayType(sig,index,false));  
+        types.add(ArrayDesc.GetArrayTypeFromSig(sig,index,false));  
       } else {
         types.add(GetType(sig,index));
       }
-      if (sig.charAt(index) == 'L') { 
-        index = sig.indexOf(';',index) + 1; 
-      } else if (sig.charAt(index) == '[') {
-        while (sig.charAt(index) == '[') { index++; }
-        if (sig.charAt(index) == 'L') { index = sig.indexOf(';',index) + 1;  
-        } else { index++; }
-      } else { index++; }
+        switch (sig.charAt(index)) {
+            case 'L':
+                index = sig.indexOf(';',index) + 1;
+                break;
+            case '[':
+                while (sig.charAt(index) == '[') { 
+                    index++; 
+                }
+                if (sig.charAt(index) == 'L') { 
+                    index = sig.indexOf(';',index) + 1;
+                } else { 
+                    index++; 
+                }
+                break;
+            default:
+                index++;
+                break;
+        }
     } 
     typeArr = new TypeDesc[types.size()]; 
     for (int i=0; i < types.size(); i++) {

+ 50 - 0
J2CPS/Util.java

@@ -0,0 +1,50 @@
+/*
+ * (c) copyright John Gough, 2016-2017
+ */
+package j2cps;
+
+// import java.util.function.Predicate;
+
+/**
+ *
+ * @author john
+ */
+public class Util {
+    //
+    // All these constants are package private
+    //
+    static final int PRISTINE = 0;
+    static final int ONLIST   = 0x1;
+    static final int ONTODO   = 0x2;
+    static final int ONSYMS   = 0x4;
+    static final int FROMJAR  = 0x8;
+    static final int FROMCLS  = 0x10;
+    static final int APINEEDS = 0x20;
+    static final int FOUNDCPS = 0x40;
+    static final int CURRENT  = 0x80;
+
+    static final char FWDSLSH = '/';
+    static final char FILESEP = 
+                    System.getProperty("file.separator").charAt(0);
+    static final char JAVADOT = '.';
+    static final char LOWLINE = '_';
+
+    public void Assert(boolean p) {
+        if (!p)
+            throw new IllegalArgumentException( "Assertion Failed"); 
+    }
+    
+    public static String Tag(int tag) {
+        switch (tag) {
+            case ONLIST: return "ONLIST,";
+            case ONTODO: return "ONTODO,";
+            case ONSYMS: return "ONSYMS,";
+            case FROMJAR: return "FROMJAR,";
+            case FROMCLS: return "FROMCLS,";
+            case APINEEDS: return "APINEEDS,";
+            case FOUNDCPS: return "FOUNDCPS,";
+            case CURRENT: return "CURRENT,";
+            default: return "unknown,";    
+        }
+    }
+}