Quellcode durchsuchen

Merge pull request #3 from k-john-gough/jvm-asm

Jvm asm
John Gough vor 7 Jahren
Ursprung
Commit
56b19dc0ce
65 geänderte Dateien mit 7540 neuen und 4952 gelöschten Zeilen
  1. 73 43
      J2CPS/ArrayDesc.java
  2. 13 13
      J2CPS/CPWords.java
  3. 576 416
      J2CPS/ClassDesc.java
  4. 3 3
      J2CPS/ClassRef.java
  5. 35 13
      J2CPS/ConstantPool.java
  6. 26 0
      J2CPS/ExtFilter.java
  7. 32 34
      J2CPS/FieldInfo.java
  8. 3 1
      J2CPS/FieldRef.java
  9. 3 3
      J2CPS/InterfaceMethodRef.java
  10. 138 46
      J2CPS/J2CPS.java
  11. 141 109
      J2CPS/J2CPSFiles.java
  12. 57 0
      J2CPS/JarHandler.java
  13. 4 4
      J2CPS/MemberInfo.java
  14. 65 49
      J2CPS/MethodInfo.java
  15. 3 3
      J2CPS/MethodRef.java
  16. 3 3
      J2CPS/NameAndType.java
  17. 288 117
      J2CPS/PackageDesc.java
  18. 32 19
      J2CPS/PtrDesc.java
  19. 3 3
      J2CPS/Reference.java
  20. 3 3
      J2CPS/StringRef.java
  21. 544 399
      J2CPS/SymbolFile.java
  22. 62 22
      J2CPS/TypeDesc.java
  23. 50 0
      J2CPS/Util.java
  24. 118 0
      gpcp/AsmCodeSets.cp
  25. 38 0
      gpcp/AsmDefinitions.cp
  26. 1234 0
      gpcp/AsmFrames.cp
  27. 546 0
      gpcp/AsmHelpers.cp
  28. 1915 0
      gpcp/AsmUtil.cp
  29. 5 6
      gpcp/CPascal.cp
  30. 2 0
      gpcp/CPascalErrors.cp
  31. 12 13
      gpcp/CPascalP.cp
  32. 2 2
      gpcp/CPascalS.cp
  33. 7 0
      gpcp/ClassMaker.cp
  34. 90 17
      gpcp/ClassUtil.cp
  35. 112 61
      gpcp/CompState.cp
  36. 1 1
      gpcp/ExprDesc.cp
  37. 5 1
      gpcp/GPCPcopyright.cp
  38. 35 32
      gpcp/GPCPcopyright.rtf
  39. 1 1
      gpcp/Hello.cp
  40. 1 0
      gpcp/JVMcodes.cp
  41. 309 262
      gpcp/JavaMaker.cp
  42. 37 0
      gpcp/JavaTarget.cp
  43. 32 0
      gpcp/JavaTargetForCLR.cp
  44. 35 0
      gpcp/JavaTargetForJVM.cp
  45. 360 184
      gpcp/JavaUtil.cp
  46. 110 48
      gpcp/JsmnUtil.cp
  47. 29 1
      gpcp/LitValue.cp
  48. 2 2
      gpcp/MsilAsmForeign.cp
  49. 1 0
      gpcp/MsilMaker.cp
  50. 5 4
      gpcp/NewSymFileRW.cp
  51. 0 2045
      gpcp/OldSymFileRW.cp
  52. 11 938
      gpcp/PeUtil.cp
  53. 1 1
      gpcp/StatDesc.cp
  54. 5 0
      gpcp/Symbols.cp
  55. 1 12
      gpcp/Target.cp
  56. 5 5
      gpcp/TypeDesc.cp
  57. 208 0
      gpcp/build.xml
  58. 1 1
      gpcp/gpcp.cp
  59. 49 0
      j2cps/build.xml
  60. 6 11
      libs/csharp/RTS.cs
  61. 5 0
      libs/java/CPJrts.java
  62. 5 1
      libs/java/GPBinFiles.java
  63. 2 0
      libs/java/MakeAll.bat
  64. 35 0
      libs/java/MakeRTSjar.bat
  65. 5 0
      libs/java/ProgArgs.java

+ 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,";    
+        }
+    }
+}

+ 118 - 0
gpcp/AsmCodeSets.cp

@@ -0,0 +1,118 @@
+(* 
+ *  Code sets for ASM, to check for membership of
+ *  particular forbidden or permitted bytecode values.
+ *)
+MODULE AsmCodeSets;
+  IMPORT Jvm := JVMcodes;
+
+  TYPE ByteBitSet = ARRAY 8 OF SET;
+
+  VAR forbidden    : ByteBitSet; (* bytecodes not allowed by ASM5 *)
+  VAR deltaSpecial : ByteBitSet; (* bytecodes with variable delta *)
+
+
+(* ============================================================ *)
+(*               Handling of byte code bit maps                 *)
+(* ============================================================ *)
+
+  PROCEDURE Insert( VAR set : ByteBitSet; val : INTEGER );
+  BEGIN
+    IF (val < 0) OR (val > 255) THEN
+        THROW( "Illegal insert in bit set - " );
+    END;
+    INCL(set[val DIV 32], val MOD 32);
+  END Insert;
+
+(* -------------------- *)
+
+  PROCEDURE badCode*( code : INTEGER ) : BOOLEAN;
+  BEGIN
+    RETURN (code MOD 32) IN forbidden[code DIV 32];
+  END badCode;
+
+(* -------------------- *)
+
+  PROCEDURE badFix*( code : INTEGER ) : BOOLEAN;
+  BEGIN
+    RETURN (code MOD 32) IN deltaSpecial[code DIV 32];
+  END badFix;
+
+(* -------------------- *)
+
+  PROCEDURE isOk*( code : INTEGER ) : INTEGER;
+  BEGIN
+    IF (code MOD 32) IN forbidden[code DIV 32] THEN
+      THROW( "Illegal code called - " + Jvm.op[code] );
+     (* Permissive variant *)
+      (* Hlp.Msg( "Illegal code called - " + Jvm.op[code] ); *)
+    END;
+    RETURN code;
+  END isOk;
+
+(* ============================================================ *)
+(*               Initialization of module globals               *)
+(* ============================================================ *)
+BEGIN
+ (* -------------------------------------------- *)
+ (*       Initialize forbidden code set          *)
+ (* -------------------------------------------- *)
+  Insert( deltaSpecial, Jvm.opc_getstatic );
+  Insert( deltaSpecial, Jvm.opc_putstatic );
+  Insert( deltaSpecial, Jvm.opc_getfield );
+  Insert( deltaSpecial, Jvm.opc_putfield );
+  Insert( deltaSpecial, Jvm.opc_invokevirtual );
+  Insert( deltaSpecial, Jvm.opc_invokespecial );
+  Insert( deltaSpecial, Jvm.opc_invokestatic);
+  Insert( deltaSpecial, Jvm.opc_invokeinterface );
+  Insert( deltaSpecial, Jvm.opc_multianewarray );
+
+ (* -------------------------------------------- *)
+ (*       Initialize forbidden code set          *)
+ (* -------------------------------------------- *)
+  Insert( forbidden, Jvm.opc_iload_0 );
+  Insert( forbidden, Jvm.opc_iload_1 );
+  Insert( forbidden, Jvm.opc_iload_2 );
+  Insert( forbidden, Jvm.opc_iload_3 );
+  Insert( forbidden, Jvm.opc_aload_0 );
+  Insert( forbidden, Jvm.opc_aload_1 );
+  Insert( forbidden, Jvm.opc_aload_2 );
+  Insert( forbidden, Jvm.opc_aload_3 );
+  Insert( forbidden, Jvm.opc_lload_0 );
+  Insert( forbidden, Jvm.opc_lload_1 );
+  Insert( forbidden, Jvm.opc_lload_2 );
+  Insert( forbidden, Jvm.opc_lload_3 );
+  Insert( forbidden, Jvm.opc_fload_0 );
+  Insert( forbidden, Jvm.opc_fload_1 );
+  Insert( forbidden, Jvm.opc_fload_2 );
+  Insert( forbidden, Jvm.opc_fload_3 );
+  Insert( forbidden, Jvm.opc_dload_0 );
+  Insert( forbidden, Jvm.opc_dload_1 );
+  Insert( forbidden, Jvm.opc_dload_2 );
+  Insert( forbidden, Jvm.opc_dload_3 );
+
+  Insert( forbidden, Jvm.opc_istore_0 );
+  Insert( forbidden, Jvm.opc_istore_1 );
+  Insert( forbidden, Jvm.opc_istore_2 );
+  Insert( forbidden, Jvm.opc_istore_3 );
+  Insert( forbidden, Jvm.opc_astore_0 );
+  Insert( forbidden, Jvm.opc_astore_1 );
+  Insert( forbidden, Jvm.opc_astore_2 );
+  Insert( forbidden, Jvm.opc_astore_3 );
+  Insert( forbidden, Jvm.opc_lstore_0 );
+  Insert( forbidden, Jvm.opc_lstore_1 );
+  Insert( forbidden, Jvm.opc_lstore_2 );
+  Insert( forbidden, Jvm.opc_lstore_3 );
+  Insert( forbidden, Jvm.opc_fstore_0 );
+  Insert( forbidden, Jvm.opc_fstore_1 );
+  Insert( forbidden, Jvm.opc_fstore_2 );
+  Insert( forbidden, Jvm.opc_fstore_3 );
+  Insert( forbidden, Jvm.opc_dstore_0 );
+  Insert( forbidden, Jvm.opc_dstore_1 );
+  Insert( forbidden, Jvm.opc_dstore_2 );
+  Insert( forbidden, Jvm.opc_dstore_3 );
+
+ (* ------------------------------------ *)
+END AsmCodeSets.
+(* ============================================================ *)
+
+

+ 38 - 0
gpcp/AsmDefinitions.cp

@@ -0,0 +1,38 @@
+
+(*
+ *  Define various types and values
+ *  for use by the other Asm* modules.
+ *  This must not depend of any other
+ *  gpcp module.
+ *)
+
+MODULE AsmDefinitions;
+  IMPORT 
+    GPCPcopyright,
+    RTS,
+    JL := java_lang,
+
+    ASM := org_objectweb_asm;
+
+  CONST versionDefault* = "7";
+
+(* ============================================================ *)
+
+  TYPE JlsArr* = POINTER TO ARRAY OF RTS.NativeString;
+       JloArr* = POINTER TO ARRAY OF RTS.NativeObject;
+
+(* ============================================================ *)
+
+  PROCEDURE GetClassVersion*( IN s : ARRAY OF CHAR) : INTEGER;
+  BEGIN
+    IF s = "" THEN RETURN GetClassVersion( versionDefault );
+    ELSIF s = "5" THEN RETURN ASM.Opcodes.V1_5;
+    ELSIF s = "6" THEN RETURN ASM.Opcodes.V1_6;
+    ELSIF s = "7" THEN RETURN ASM.Opcodes.V1_7;
+    ELSIF s = "8" THEN RETURN ASM.Opcodes.V1_8;
+    ELSE THROW( "Bad class version " + s );
+    END;
+  END GetClassVersion;
+
+END AsmDefinitions.
+

+ 1234 - 0
gpcp/AsmFrames.cp

@@ -0,0 +1,1234 @@
+
+
+(* ============================================================ *)
+(*  AsmFrames is the module which provides all the methods      *)
+(*  associated with the MethodFrame and FrameElement types.     *)
+(*  Copyright (c) John Gough 2016-2017.                         *)
+(* ============================================================ *)
+
+(* ============================================================ *
+ *
+ *  About stack frame emission.
+ *  At various points in the code, for Java SE 7+ a stack frame
+ *  marker is emitted to allow the new Prolog-based verifier to
+ *  run efficiently. The stack frames are emitted in a rather
+ *  tricky compressed form which, when expanded, gives the 
+ *  evaluation stack and local variable state at the corresponding 
+ *  code point.
+ *
+ *  Each element in the stack and locals is given a "verification
+ *  type". These are values from a type-lattice.
+ *
+ *  The way that this compiler generates the stack frames is to
+ *  maintain a shadow stack which is updated after the emission
+ *  of each instruction. At control-flow merge points the type
+ *  is the join-type of all the paths merging at that point.
+ *
+ *  The initial state of the shadow stack is determined from the
+ *  type and mode of the formal parameters. The initial state of
+ *  the locals requires that even allocated locals have type
+ *  "TOP" until a definite assignment is made to the local slot.
+ *  This requirement is met by storing the future type of the 
+ *  slot and copying to the locals stack on encountering a store
+ *  to that location.
+ *
+ *  It is a requirement that stack frames cannot be at the
+ *  beginning of method code, nor can they be adjacent without
+ *  at least one intervening instruction. The implementation of
+ *  this requirement is clunky, since GPCP generates code that
+ *  may have multiple target labels that are adjacent (when 
+ *  statements are deeply nested, for example). The clunky 
+ *  algorithm for this is that each label carries with it the 
+ *  verification types of its jump-off locations. As each 
+ *  label-definition is processed the merged state is updated 
+ *  but no frame is emitted. Only when the emission of a
+ *  non-label "instruction" is encountered is the latest merged 
+ *  state emitted in a stack frame.
+ *
+ * ============================================================ *)
+
+MODULE AsmFrames;
+  IMPORT 
+    RTS,
+    Jvm := JVMcodes,
+    Sym := Symbols,
+    Blt := Builtin,
+    CSt := CompState,
+    Id  := IdDesc,
+    Ty  := TypeDesc,
+    Ju  := JavaUtil,
+    Lv  := LitValue,
+
+    JL  := java_lang,
+
+    Hlp := AsmHelpers,
+    Acs := AsmCodeSets,
+    Def := AsmDefinitions,
+    ASM := org_objectweb_asm;
+
+(* ================================================= *)
+(*     Types used for manipulation of stack frames   *)
+(* ================================================= *)
+
+ (* ----------------------------------------------- *)
+ (* Element type of the locals frame vector --      *)
+ (* ----------------------------------------------- *)
+ (* 'state' asserts the state of the local:         *)
+ (*   TOP  - unknown type of value                  *)
+ (*   some java/lang/Integer denoting a basic type  *)
+ (*   some java/lang/String denoting a typename.    *) 
+ (*   NULL - value known to be nil                  *)
+ (* 'dclTp' denotes the CP declared static typename *)
+ (*   for a local of some reference type, after the *)
+ (*   local has had a definite assignment the dclTp *)
+ (*   is copied to the state field.                 *)
+ (* ----------------------------------------------- *)
+  TYPE FrameElement* = 
+    RECORD 
+      state* : RTS.NativeObject;
+      dclTp* : RTS.NativeObject;  (* "state" in waiting *)
+    END;
+
+  TYPE FrameVector* = VECTOR OF FrameElement;
+
+  TYPE FrameSave* = POINTER TO RECORD
+                      lDclArr : Def.JloArr;
+                      loclArr : Def.JloArr;
+                      evalArr : Def.JloArr;
+                    END;
+
+ (* ----------------------------------------------- *)
+ (* Element type of the eval stack vector --        *)
+ (* ----------------------------------------------- *)
+ (* Each item on the stack notes the stack state    *)
+ (* of the eval-stack element at that position.     *)
+ (* ----------------------------------------------- *)
+  TYPE StackVector* = VECTOR OF RTS.NativeObject;
+
+ (* ----------------------------------------------- *)
+ (* MethodFrames simulate locals and eval-stack     *)
+ (* ----------------------------------------------- *)
+ (* localStack holds declared local variables,      *)
+ (* initially with their statically declared types  *)
+ (* memorized in the dclTp field. State fields of   *)
+ (* all live elements of localStack are emitted by  *)
+ (* every mv.visitFrame() call.                     *)
+ (* ----------------------------------------------- *)
+ (* evalStack tracks the current contents of the    *)
+ (* evaluation stack of the JVM at each program     *)
+ (* point. Live elements of the evalStack are       *)
+ (* emitted by every mv.visitFrame() call.          *)
+ (* ----------------------------------------------- *)
+ (* Type-2 elements (LONG and DOUBLE) take up two   *)
+ (* slots in the localStack array, with the second  *)
+ (* being a dummy to preserve the mapping to local  *)
+ (* variable ordinal number. These dummies are      *)
+ (* skipped over in the creation of object arrays   *)
+ (* used in the visitFrame instruction.             *)
+ (* ----------------------------------------------- *)
+  TYPE MethodFrame* = 
+    POINTER TO RECORD
+      procName-   : Lv.CharOpen;
+      descriptor- : Id.Procs;
+      signature-  : RTS.NativeString;
+      localStack* : FrameVector;
+      evalStack*  : StackVector;
+      maxEval-    : INTEGER;
+      maxLocal-   : INTEGER;
+      sigMax-     : INTEGER; (* top of initialized locals *)
+      undefEval   : BOOLEAN;
+    END;
+
+  VAR dummyElement- : FrameElement; (* {TOP,NIL} *)
+
+(* ================================================ *)
+(* ================================================ *)
+(*          Forward Procedure Declarations          *)
+(* ================================================ *)
+(* ================================================ *)
+
+  PROCEDURE^ ( mFrm : MethodFrame )EvLn*() : INTEGER,NEW;
+  PROCEDURE^ ( mFrm : MethodFrame )EvHi*() : INTEGER,NEW;
+  PROCEDURE^ ( mFrm : MethodFrame )LcLn*() : INTEGER,NEW;
+  PROCEDURE^ ( mFrm : MethodFrame )LcHi*() : INTEGER,NEW;
+  PROCEDURE^ ( mFrm : MethodFrame )LcCount*() : INTEGER,NEW;
+  PROCEDURE^ ( mFrm : MethodFrame )EvCount*() : INTEGER,NEW;
+  PROCEDURE^ ( mFrm : MethodFrame )AddLocal*(type : Sym.Type),NEW;
+  PROCEDURE^ ( mFrm : MethodFrame )AddValParam*(type : Sym.Type),NEW;
+  PROCEDURE^ ( mFrm : MethodFrame )AddRefParam*(str : Lv.CharOpen),NEW;
+(*
+ *PROCEDURE^ ( mFrm : MethodFrame )DiagFrame*( ),NEW;
+ *PROCEDURE^ ( mFrm : MethodFrame )DiagEvalStack*(),NEW;
+ *PROCEDURE^ (mFrm : MethodFrame )Diag*(code : INTEGER),NEW;
+ *PROCEDURE^ ( fs : FrameSave )Diag*( ),NEW;
+ *)
+  PROCEDURE^ ( mFrm : MethodFrame )GetLocalArrStr*() : RTS.NativeString,NEW;
+  PROCEDURE^ ( mFrm : MethodFrame )GetDclTpArrStr*() : RTS.NativeString,NEW;
+  PROCEDURE^ ( mFrm : MethodFrame )GetEvalArrStr*() : RTS.NativeString,NEW;
+  PROCEDURE^ ( fs : FrameSave )EvLn*( ) : INTEGER,NEW;
+  PROCEDURE^ ( fs : FrameSave )EvHi*( ) : INTEGER,NEW;
+  PROCEDURE^ ( fs : FrameSave )LcLn*( ) : INTEGER,NEW;
+  PROCEDURE^ ( fs : FrameSave )LcHi*( ) : INTEGER,NEW;
+
+(* ================================================= *)
+(* ================================================= *)
+(*        Static procedures for MethodFrames         *)
+(* ================================================= *)
+(* ================================================= *)
+
+ (* ----------------------------------------------- *)
+ (*   Parse a signature and initialize the Frame    *)
+ (* ----------------------------------------------- *)
+  PROCEDURE ParseSig( frm : MethodFrame; sig : Lv.CharOpen );
+    VAR cIdx : INTEGER;
+        cVal : CHAR;
+        cVec : Lv.CharVector;
+  BEGIN
+    NEW( cVec, 32 );
+    cIdx := 0; cVal := sig[cIdx];
+    LOOP 
+      CASE cVal OF
+      | '(' : (* skip *);
+      | ')' : RETURN;
+
+      | 'I', 'B', 'C', 'S', 'Z' : 
+             (* 
+              *  All 32-bit ordinals get integer frame state 
+              *)
+              frm.AddValParam( Blt.intTp );  (* int      *)
+      | 'J' : frm.AddValParam( Blt.lIntTp ); (* long int *)
+      | 'F' : frm.AddValParam( Blt.sReaTp ); (* float    *)
+      | 'D' : frm.AddValParam( Blt.realTp ); (* double   *)
+
+      | 'L' : (* binary class name *)
+              CUT(cVec, 0);
+              APPEND( cVec, cVal );
+              REPEAT
+                INC( cIdx ); cVal := sig[cIdx]; (* Get Next *)
+                APPEND( cVec, cVal );
+              UNTIL cVal = ';';
+              frm.AddRefParam( Lv.chrVecToCharOpen( cVec ) );
+
+      | '[' : (* binary array name *)
+              CUT(cVec, 0);
+              WHILE cVal = '[' DO
+                APPEND( cVec, cVal );
+                INC( cIdx ); cVal := sig[cIdx]; (* Get Next *)
+              END;
+              APPEND( cVec, cVal ); 
+             (* if this was an 'L' continue until ';' *)
+              IF cVal = 'L' THEN
+                REPEAT
+                  INC( cIdx ); cVal := sig[cIdx]; (* Get Next *)
+                  APPEND( cVec, cVal );
+                UNTIL cVal = ';';
+              END;
+              frm.AddRefParam( Lv.chrVecToCharOpen( cVec ) );
+
+      (* else CASEtrap *)
+      END;
+      INC( cIdx ); cVal := sig[cIdx]; (* Get Next *)
+    END; (* LOOP *)
+  END ParseSig; 
+
+ (* ----------------------------------------------- *)
+ (*             Add Proxies to the frame            *)
+ (* ----------------------------------------------- *)
+  PROCEDURE AddProxies( frm : MethodFrame; prc : Id.Procs );
+    VAR idx  : INTEGER;
+        pars : Id.ParSeq;
+        parX : Id.ParId;
+  BEGIN
+    pars := prc.type(Ty.Procedure).formals;
+    FOR idx := 0 TO pars.tide-1 DO
+      parX := pars.a[idx];
+      IF parX.varOrd > frm.LcHi() THEN
+        frm.AddLocal( parX.type );
+      END;
+    END;
+  END AddProxies;
+ 
+ (* ----------------------------------------------- *)
+ (*             Add locals to the frame             *)
+ (* ----------------------------------------------- *)
+  PROCEDURE AddLocals( frm : MethodFrame; prc : Id.Procs );
+    VAR idx  : INTEGER;
+        locs : Sym.IdSeq;
+        locX : Sym.Idnt;
+  BEGIN
+    locs := prc.locals;
+    FOR idx := 0 TO locs.tide-1 DO
+      locX := locs.a[idx];
+      WITH locX : Id.ParId DO (* ignore *)
+      | locX : Id.LocId DO
+          frm.AddLocal( locX.type );
+      END;
+    END;
+  END AddLocals;
+ 
+ (* ----------------------------------------------- *)
+ (*  Create a new MethodFrame for procedure procId  *)
+ (* ----------------------------------------------- *)
+  PROCEDURE NewMethodFrame*( procId : Id.Procs) : MethodFrame;
+    VAR rslt : MethodFrame;
+        sigL : Lv.CharOpen;
+  BEGIN
+    sigL := procId.type(Ty.Procedure).xName;
+    NEW( rslt );
+    NEW( rslt.localStack , 8 );
+    NEW( rslt.evalStack , 8 );
+    rslt.procName   := procId.prcNm;
+    rslt.descriptor := procId;
+    rslt.signature  := MKSTR( sigL^ );
+    rslt.maxEval    := 0;
+    rslt.maxLocal   := procId.rtsFram;
+    rslt.undefEval  := FALSE;
+   (*
+    *  Allocate slot 0 for the receiver, if any
+    *)
+    IF procId IS Id.MthId THEN
+      rslt.AddRefParam( procId(Id.MthId).bndType.xName );
+    END;
+   (*
+    *  Now load up the frame with the param info.
+    *  All of these are initialized frame elements.
+    *)
+    ParseSig( rslt, sigL );
+    rslt.sigMax := LEN(rslt.localStack);
+   (*
+    *  And now with the local variable info
+    *  All of these are uninitialized frame elements.
+    *)
+    AddProxies( rslt, procId );
+    AddLocals( rslt, procId );
+
+    RETURN rslt;
+  END NewMethodFrame;
+
+ (* ----------------------------------------------- *)
+ (*   Create a MethodFrame for a known procedure    *)
+ (* ----------------------------------------------- *)
+  PROCEDURE SigFrame*( sigL, name, recv : Lv.CharOpen ) : MethodFrame;
+    VAR rslt : MethodFrame;
+  BEGIN
+    NEW( rslt );
+    NEW( rslt.localStack , 8 );
+    NEW( rslt.evalStack , 8 );
+    rslt.maxEval := 0;
+    rslt.maxLocal := 1;
+    rslt.procName := name;
+    IF recv # NIL THEN
+      rslt.AddRefParam( recv );
+    END;
+    ParseSig( rslt, sigL );
+    RETURN rslt;
+  END SigFrame;
+
+ (* ----------------------------------------------- *
+  *  FrameElements get initialized in several contexts:  
+  *   (1) uninitialized locals of any type
+  *        This case should get dclTp <== sigStr or INTEGER etc.,
+  *        and state <== ASM.Opcodes.TOP.
+  *   (2) initialized params of reference type
+  *        This case should get dclTp <== sigStr,
+  *        and state <== sigStr. This should be
+  *        true even in the case of out params.
+  *   (3) locals of basic, value types
+  *        This case should get dclTp <== ASM.Opcodes.INTEGER
+  *        etc. and state <== ASM.Opcodes.TOP
+  * ----------------------------------------------- *)
+
+ (* ----------------------------------------------- *)
+ (*  Create a FrameElement, reflecting the given    *)
+ (*  type. Determine is a dummy second slot needed. *)
+ (* ----------------------------------------------- *)
+  PROCEDURE Uninitialized( type : Sym.Type; 
+                       OUT twoE : BOOLEAN;
+                       OUT elem : FrameElement );
+  BEGIN
+    twoE := FALSE;
+    elem.state := ASM.Opcodes.TOP; 
+    Hlp.EnsureTypName( type );
+    IF (type.kind = Ty.basTp) OR (type.kind = Ty.enuTp) THEN
+      CASE (type(Ty.Base).tpOrd) OF
+      | Ty.boolN .. Ty.intN, Ty.setN, Ty.uBytN :
+          elem.dclTp := ASM.Opcodes.INTEGER;
+      | Ty.sReaN :
+          elem.dclTp := ASM.Opcodes.FLOAT;
+      | Ty.anyRec .. Ty.sStrN :
+          elem.dclTp := ASM.Opcodes.TOP;  (* ???? *)
+      | Ty.lIntN :
+          elem.dclTp := ASM.Opcodes.LONG; twoE := TRUE; 
+      | Ty.realN :
+          elem.dclTp := ASM.Opcodes.DOUBLE; twoE := TRUE;
+      END;
+    ELSE
+      elem.dclTp := MKSTR( type.xName^ );
+    END;
+  END Uninitialized;
+
+ (* ----------------------------------------------- *)
+ (*  Create a single-slot FrameElement with given   *)
+ (*  signature. This is marked as initialized.      *)
+ (* ----------------------------------------------- *)
+  PROCEDURE ParamRefElement( sig  : Lv.CharOpen;
+                         OUT elem : FrameElement);
+  BEGIN
+    elem.dclTp := MKSTR( sig^ );
+    elem.state := elem.dclTp;
+  END ParamRefElement;
+
+ (* ----------------------------------------------- *)
+  PROCEDURE MkFrameSave( loclLen, evalLen : INTEGER ) : FrameSave;
+    VAR rslt : FrameSave;
+  BEGIN
+    NEW( rslt );
+    IF loclLen > 0 THEN 
+      NEW( rslt.loclArr, loclLen );
+      NEW( rslt.lDclArr, loclLen );
+    ELSE
+      rslt.loclArr := NIL;
+      rslt.lDclArr := NIL;
+    END;
+    IF evalLen > 0 THEN 
+      NEW( rslt.evalArr, evalLen );
+    ELSE
+      rslt.evalArr := NIL;
+    END;
+    RETURN rslt;
+  END MkFrameSave;
+
+  PROCEDURE ( old : FrameSave)Shorten( newLen : INTEGER ) : FrameSave,NEW;
+    VAR new : FrameSave;
+        int : INTEGER;
+  BEGIN
+    ASSERT( LEN( old.loclArr ) >= newLen );
+    NEW( new );
+    new.evalArr := old.evalArr;
+    NEW( new.loclArr, newLen );
+    NEW( new.lDclArr, newLen );
+    FOR int := 0 TO newLen - 1 DO
+      new.loclArr[int] := old.loclArr[int];
+      new.lDclArr[int] := old.lDclArr[int];
+    END;
+    RETURN new;
+  END Shorten;
+
+(* ================================================ *)
+(* ================================================ *)
+(*       Typebound methods for MethodFrames         *)
+(* ================================================ *)
+(* ================================================ *)
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)isDummyElem(ix:INTEGER) : BOOLEAN,NEW;
+  BEGIN
+   (*
+    * (dclTp = NIL) ==> 2nd element of type-1 element.
+    * However if state of previous element is TOP
+    * then visitFrame will need to emit TOP, TOP.
+    *)
+    RETURN (mFrm.localStack[ix].dclTp = NIL) &
+           (mFrm.localStack[ix - 1].state # ASM.Opcodes.TOP);
+  END isDummyElem;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)LcHi*() : INTEGER,NEW;
+  BEGIN
+    RETURN LEN( mFrm.localStack ) - 1;
+  END LcHi;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)LcLn*() : INTEGER,NEW;
+  BEGIN
+    RETURN LEN( mFrm.localStack );
+  END LcLn;
+
+ (* --------------------------------------------- *)
+  PROCEDURE ( fs : FrameSave )LcLn( ) : INTEGER,NEW;
+  BEGIN
+    IF fs.loclArr = NIL THEN RETURN 0 END;
+    RETURN LEN( fs.loclArr );
+  END LcLn;
+
+ (* --------------------------------------------- *)
+  PROCEDURE ( fs : FrameSave )LcHi( ) : INTEGER,NEW;
+  BEGIN
+    IF fs.loclArr = NIL THEN RETURN -1 END;
+    RETURN LEN( fs.loclArr ) - 1;
+  END LcHi;
+
+ (* --------------------------------------------- *)
+ (* LcLn gives the *length* of the local array    *)
+ (* LcHi gives the *hi* index of the local array  *)
+ (* LcCount gives the number of logical elements  *)
+ (* However, uninitialized type-2s count as two.  *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)LcCount*() : INTEGER,NEW;
+    VAR count, index : INTEGER;
+  BEGIN
+    count := 0;
+    FOR index := 0 TO mFrm.LcHi() DO 
+      IF ~mFrm.isDummyElem(index) THEN INC(count) END;
+    END; 
+    RETURN count;
+  END LcCount;
+
+ (* --------------------------------------------- *)
+  PROCEDURE ( fs : FrameSave )EvLn( ) : INTEGER,NEW;
+  BEGIN
+    IF fs.evalArr = NIL THEN RETURN 0 END;
+    RETURN LEN( fs.evalArr );
+  END EvLn;
+
+ (* --------------------------------------------- *)
+  PROCEDURE ( fs : FrameSave )EvHi( ) : INTEGER,NEW;
+  BEGIN
+    IF fs.evalArr = NIL THEN RETURN -1 END;
+    RETURN LEN( fs.evalArr ) - 1;
+  END EvHi;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)EvHi*() : INTEGER,NEW;
+  BEGIN
+    RETURN LEN( mFrm.evalStack ) - 1;
+  END EvHi;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)EvLn*() : INTEGER,NEW;
+  BEGIN
+    RETURN LEN( mFrm.evalStack );
+  END EvLn;
+
+ (* --------------------------------------------- *)
+ (* EvLn gives the *length* of the eval array     *)
+ (* EvHi gives the *hi* index of the eval array   *)
+ (* EvCount gives the number of logical elements  *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)EvCount*() : INTEGER,NEW;
+    VAR count, index, evHi : INTEGER;
+        elem : RTS.NativeObject;
+  BEGIN
+    count := 0;
+    index := 0;
+    evHi  := mFrm.EvHi();
+    WHILE index <= evHi DO
+      INC(count);
+      elem := mFrm.evalStack[index];
+      IF (elem = ASM.Opcodes.LONG) OR
+         (elem = ASM.Opcodes.DOUBLE) THEN
+        INC(index);
+      END;
+      INC(index); 
+    END;
+    RETURN count;
+  END EvCount;
+
+ (* --------------------------------------------- *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)setDepth*( i : INTEGER ),NEW;
+    VAR len : INTEGER;
+  BEGIN
+    len := LEN( mFrm.evalStack );
+    IF len > i THEN
+      CUT( mFrm.evalStack, i );
+    ELSE
+      WHILE len < i DO 
+        APPEND( mFrm.evalStack, NIL ); INC(len);
+      END;
+    END;
+  END setDepth;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)InvalidStack*() : BOOLEAN,NEW;
+  BEGIN
+    RETURN mFrm.undefEval;
+  END InvalidStack;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)InvalidateEvalStack*(),NEW;
+  BEGIN
+    mFrm.undefEval := TRUE;
+  END InvalidateEvalStack;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)ValidateEvalStack*(),NEW;
+  BEGIN
+    mFrm.undefEval := FALSE;
+  END ValidateEvalStack;
+
+ (* --------------------------------------------- *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)DeltaEvalDepth*( d : INTEGER ),NEW;
+    VAR new : INTEGER;
+  BEGIN
+    CASE d OF
+      0 : (* skip *)
+    | 1 : APPEND( mFrm.evalStack, NIL );
+    | 2 : APPEND( mFrm.evalStack, NIL ); 
+          APPEND( mFrm.evalStack, NIL );
+    | 3 : APPEND( mFrm.evalStack, NIL );
+          APPEND( mFrm.evalStack, NIL );
+          APPEND( mFrm.evalStack, NIL );
+    ELSE
+      IF d > 0 THEN 
+        CSt.Message( "Delta too big: " + Ju.i2CO(d)^ );
+      ELSIF (mFrm.EvLn()) < -d THEN
+        CSt.Message( "Delta too neg: " + Ju.i2CO(d)^ +
+                     " current count: " + Ju.i2CO(mFrm.EvLn() )^);
+      END;
+
+      ASSERT(d<0);
+      ASSERT((mFrm.EvLn() + d) >= 0);
+      CUT( mFrm.evalStack, mFrm.EvLn() + d );
+    END;
+    IF d > 0 THEN 
+      mFrm.maxEval := MAX( mFrm.maxEval, mFrm.EvLn() );
+    END;
+  END DeltaEvalDepth;
+
+ (* --------------------------------------------- *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)SetTosType*( t : Sym.Type ),NEW;
+    VAR tIx : INTEGER;
+        obj : RTS.NativeObject;
+  BEGIN
+    tIx := mFrm.EvHi();
+    obj := Hlp.TypeToObj( t );
+
+    IF t.isLongType() THEN
+      ASSERT( tIx >= 1 );
+      mFrm.evalStack[tIx - 1] := obj;
+      mFrm.evalStack[tIx] := ASM.Opcodes.TOP;
+    ELSE
+      ASSERT( tIx >= 0 );
+      mFrm.evalStack[tIx] := obj;
+    END;
+  END SetTosType;
+
+ (* --------------------------------------------- *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)SetTosSig*( sig : RTS.NativeString ),NEW;
+    VAR tIx : INTEGER;
+  BEGIN
+    tIx := mFrm.EvHi();
+    ASSERT( tIx >= 0 );
+    mFrm.evalStack[tIx] := Hlp.SigToObj( sig );
+  END SetTosSig;
+
+ (* --------------------------------------------- *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)SetTosState*( bSig : Lv.CharOpen ),NEW;
+  BEGIN
+    mFrm.SetTosSig( MKSTR( bSig^ ) );
+  END SetTosState;
+
+ (* --------------------------------------------- *)
+ (*  Adjust the eval stack depth and/or state.    *)
+ (*  Most instructions can use this, but a few,   *)
+ (*  such as the invoke* and multianewarray need  *)
+ (*  varying extra data, and are treated uniquely *)
+ (*  Also, long values (long, double) excluded.   *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)FixEvalSig*(
+                  code : INTEGER; 
+                  sig  : RTS.NativeString ),NEW;
+  BEGIN
+    ASSERT( ~Acs.badFix( code ) ); (* ==> fixed delta *)
+    IF code = Jvm.opc_goto THEN 
+      mFrm.InvalidateEvalStack(); 
+    ELSE
+      mFrm.DeltaEvalDepth( Jvm.dl[code] );
+      IF sig # NIL THEN 
+        mFrm.SetTosSig( sig );
+      END;
+    END;
+  END FixEvalSig;
+
+  (* 
+   *  Used after various typed *load instructions,
+   *  typed *store instructions, ldc variants, jumps,
+   *  new, newarray, anewarray.
+   *)
+  PROCEDURE (mFrm : MethodFrame)FixEvalStack*(
+                  code : INTEGER; 
+                  type : Sym.Type ),NEW;
+  BEGIN
+    ASSERT( ~Acs.badFix( code ) ); (* ==> fixed delta *)
+    IF code = Jvm.opc_goto THEN 
+      mFrm.InvalidateEvalStack(); 
+    ELSE
+      mFrm.DeltaEvalDepth( Jvm.dl[code] );
+      IF type # NIL THEN 
+        mFrm.SetTosType( type );
+      END;
+    END;
+  END FixEvalStack;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)PutGetFix*(
+                  code : INTEGER; type : Sym.Type ),NEW;
+    VAR jvmSize : INTEGER;
+  BEGIN
+
+    jvmSize := Ju.jvmSize(type);
+    CASE code OF
+    | Jvm.opc_getfield  :                    (* t1 or t2 *) 
+        mFrm.DeltaEvalDepth( jvmSize - 1 );  (*  0 or 1  *)
+        mFrm.SetTosType( type );
+    | Jvm.opc_putfield  :
+        mFrm.DeltaEvalDepth( -jvmSize - 1 ); (* -2 or -3 *)
+    | Jvm.opc_getstatic :
+        mFrm.DeltaEvalDepth( jvmSize );      (*  1 or 2  *)
+        mFrm.SetTosType( type );
+    | Jvm.opc_putstatic :
+        mFrm.DeltaEvalDepth( -jvmSize );     (* -1 or -2 *)
+    END;
+  END PutGetFix;
+
+ (* --------------------------------------------- *)
+ (*    Infer new TOS and mutate evalStack state   *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)MutateEvalStack*( code : INTEGER ),NEW;
+    VAR delta : INTEGER;
+        tosHi : INTEGER;
+        tmpOb : RTS.NativeObject;
+        tmpSt : RTS.NativeString;
+        tempS : RTS.NativeObject;
+  BEGIN
+    delta := Jvm.dl[code];
+    mFrm.DeltaEvalDepth( delta );
+    tosHi := mFrm.EvHi();
+
+    CASE code OF 
+
+    | Jvm.opc_nop,       (* All of these discard the TOS, or    *)
+      Jvm.opc_pop,       (* leave the TOS state equal to that   *) 
+      Jvm.opc_pop2,      (* of (one of) the incoming operand(s) *)
+      Jvm.opc_iastore,
+      Jvm.opc_lastore,
+      Jvm.opc_fastore,
+      Jvm.opc_dastore,
+      Jvm.opc_aastore,
+      Jvm.opc_bastore,
+      Jvm.opc_castore,
+      Jvm.opc_sastore,
+      Jvm.opc_lneg,
+      Jvm.opc_ineg,
+      Jvm.opc_fneg,
+      Jvm.opc_dneg:
+         (* skip *)
+
+    | Jvm.opc_goto,
+      Jvm.opc_ireturn,
+      Jvm.opc_lreturn,
+      Jvm.opc_freturn,
+      Jvm.opc_dreturn,
+      Jvm.opc_areturn,
+      Jvm.opc_return,
+      Jvm.opc_athrow :
+          mFrm.undefEval := TRUE;
+
+    | ASM.Opcodes.ACONST_NULL :
+          mFrm.evalStack[tosHi] := ASM.Opcodes.NULL;
+
+    | ASM.Opcodes.ICONST_M1 ,
+      ASM.Opcodes.ICONST_0 ,
+      ASM.Opcodes.ICONST_1 ,
+      ASM.Opcodes.ICONST_2 ,
+      ASM.Opcodes.ICONST_3 ,
+      ASM.Opcodes.ICONST_4 ,
+      ASM.Opcodes.ICONST_5 ,
+      ASM.Opcodes.IALOAD ,
+      ASM.Opcodes.BALOAD ,
+      ASM.Opcodes.CALOAD ,
+      ASM.Opcodes.SALOAD ,
+      ASM.Opcodes.IADD ,
+
+      ASM.Opcodes.ISUB,
+      ASM.Opcodes.IMUL,
+      ASM.Opcodes.IDIV,
+
+      ASM.Opcodes.IREM ,
+      ASM.Opcodes.ISHL ,
+      ASM.Opcodes.ISHR ,
+      ASM.Opcodes.IUSHR ,
+      ASM.Opcodes.IAND ,
+      ASM.Opcodes.IOR ,
+      ASM.Opcodes.IXOR ,
+      ASM.Opcodes.L2I ,
+      ASM.Opcodes.F2I ,
+      ASM.Opcodes.D2I ,
+      ASM.Opcodes.I2B ,
+      ASM.Opcodes.I2C ,
+      ASM.Opcodes.I2S ,
+      ASM.Opcodes.LCMP, 
+      ASM.Opcodes.FCMPL, 
+      ASM.Opcodes.FCMPG, 
+      ASM.Opcodes.DCMPL, 
+      ASM.Opcodes.DCMPG, 
+      ASM.Opcodes.BIPUSH,
+      ASM.Opcodes.SIPUSH,
+      ASM.Opcodes.ARRAYLENGTH :
+          mFrm.evalStack[tosHi] := ASM.Opcodes.`INTEGER;
+
+    | ASM.Opcodes.LCONST_0 ,
+      ASM.Opcodes.LCONST_1 ,
+      ASM.Opcodes.LALOAD ,
+      ASM.Opcodes.LADD ,
+
+      ASM.Opcodes.LSUB,
+      ASM.Opcodes.LMUL,
+      ASM.Opcodes.LDIV,
+
+      ASM.Opcodes.LREM ,
+      ASM.Opcodes.LSHL ,
+      ASM.Opcodes.LSHR ,
+      ASM.Opcodes.LUSHR ,
+      ASM.Opcodes.LAND ,
+      ASM.Opcodes.LOR ,
+      ASM.Opcodes.LXOR ,
+      ASM.Opcodes.I2L ,
+      ASM.Opcodes.F2L ,
+      ASM.Opcodes.D2L :
+          mFrm.evalStack[tosHi] := ASM.Opcodes.TOP;
+          mFrm.evalStack[tosHi-1] := ASM.Opcodes.LONG;
+
+    | ASM.Opcodes.FCONST_0 ,
+      ASM.Opcodes.FCONST_1 ,
+      ASM.Opcodes.FCONST_2 ,
+      ASM.Opcodes.FALOAD ,
+      ASM.Opcodes.FADD ,
+
+      ASM.Opcodes.FSUB,
+      ASM.Opcodes.FMUL,
+      ASM.Opcodes.FDIV,
+
+      ASM.Opcodes.FREM ,
+      ASM.Opcodes.I2F ,
+      ASM.Opcodes.L2F ,
+      ASM.Opcodes.D2F :
+          mFrm.evalStack[tosHi] := ASM.Opcodes.FLOAT;
+
+    | ASM.Opcodes.DCONST_0 ,
+      ASM.Opcodes.DCONST_1 ,
+      ASM.Opcodes.DALOAD ,
+      ASM.Opcodes.DADD ,
+
+      ASM.Opcodes.DMUL,
+      ASM.Opcodes.DDIV,
+      ASM.Opcodes.DSUB,
+
+      ASM.Opcodes.DREM ,
+      ASM.Opcodes.I2D ,
+      ASM.Opcodes.L2D ,
+      ASM.Opcodes.F2D :
+          mFrm.evalStack[tosHi] := ASM.Opcodes.TOP;
+          mFrm.evalStack[tosHi] := ASM.Opcodes.DOUBLE;
+
+    | ASM.Opcodes.AALOAD : 
+         (* 
+          *  The new TOS location will still hold the
+          *  signature of the array type. Strip one '['
+          *  and assign the signature.
+          *)
+          tmpSt := mFrm.evalStack[tosHi](RTS.NativeString);
+          ASSERT( tmpSt.charAt(0) = '[' );
+          mFrm.evalStack[tosHi] := tmpSt.substring(1);
+
+    | ASM.Opcodes.DUP :
+          mFrm.evalStack[tosHi] := mFrm.evalStack[tosHi-1];
+
+    | ASM.Opcodes.DUP_X1 : 
+          mFrm.evalStack[tosHi] := mFrm.evalStack[tosHi-1];
+          mFrm.evalStack[tosHi-1] := mFrm.evalStack[tosHi-2];
+          mFrm.evalStack[tosHi-2] := mFrm.evalStack[tosHi];
+
+    | ASM.Opcodes.DUP_X2 :
+          mFrm.evalStack[tosHi] := mFrm.evalStack[tosHi-1];
+          mFrm.evalStack[tosHi-1] := mFrm.evalStack[tosHi-2];
+          mFrm.evalStack[tosHi-2] := mFrm.evalStack[tosHi-3];
+          mFrm.evalStack[tosHi-3] := mFrm.evalStack[tosHi];
+
+    | ASM.Opcodes.DUP2 :
+          mFrm.evalStack[tosHi] := mFrm.evalStack[tosHi-2];
+          mFrm.evalStack[tosHi-1] := mFrm.evalStack[tosHi-3];
+
+    | ASM.Opcodes.DUP2_X1 : 
+          mFrm.evalStack[tosHi] := mFrm.evalStack[tosHi-2];
+          mFrm.evalStack[tosHi-1] := mFrm.evalStack[tosHi-3];
+          mFrm.evalStack[tosHi-2] := mFrm.evalStack[tosHi-4];
+          mFrm.evalStack[tosHi-3] := mFrm.evalStack[tosHi];
+          mFrm.evalStack[tosHi-4] := mFrm.evalStack[tosHi-1];
+
+    | ASM.Opcodes.DUP2_X2 : 
+          mFrm.evalStack[tosHi] := mFrm.evalStack[tosHi-2];
+          mFrm.evalStack[tosHi-1] := mFrm.evalStack[tosHi-3];
+          mFrm.evalStack[tosHi-2] := mFrm.evalStack[tosHi-4];
+          mFrm.evalStack[tosHi-3] := mFrm.evalStack[tosHi-5];
+          mFrm.evalStack[tosHi-4] := mFrm.evalStack[tosHi];
+          mFrm.evalStack[tosHi-5] := mFrm.evalStack[tosHi-1];
+
+    | ASM.Opcodes.SWAP :
+          tmpOb := mFrm.evalStack[tosHi];
+          mFrm.evalStack[tosHi] := mFrm.evalStack[tosHi-1];
+          mFrm.evalStack[tosHi-1] := tmpOb;
+   (* --------------------------------- *)
+   (*       ELSE take a CASE TRAP       *)
+   (* --------------------------------- *)
+    END; 
+  END MutateEvalStack;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)AddValParam*( 
+                                type : Sym.Type ),NEW;
+    VAR newFE : FrameElement;
+        need2 : BOOLEAN;
+  BEGIN
+    need2 := FALSE;
+    CASE (type(Ty.Base).tpOrd) OF
+      | Ty.boolN .. Ty.intN, Ty.setN, Ty.uBytN :
+          newFE.dclTp := ASM.Opcodes.INTEGER;
+      | Ty.sReaN :
+          newFE.dclTp := ASM.Opcodes.FLOAT;
+      | Ty.anyRec .. Ty.sStrN :
+          newFE.dclTp := ASM.Opcodes.TOP;  (* ???? *)
+      | Ty.lIntN :
+          newFE.dclTp := ASM.Opcodes.LONG; need2 := TRUE;
+      | Ty.realN :
+          newFE.dclTp := ASM.Opcodes.DOUBLE; need2 := TRUE;
+    END;
+    newFE.state := newFE.dclTp; (* ==> initialized *)
+    APPEND( mFrm.localStack, newFE );
+    IF need2 THEN
+      APPEND( mFrm.localStack, dummyElement );
+    END;
+    mFrm.maxLocal := MAX( mFrm.maxLocal, mFrm.LcLn() );
+  END AddValParam;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)AddLocal*( 
+                                type : Sym.Type ),NEW;
+    VAR newFE : FrameElement;
+        need2 : BOOLEAN;
+        preHi : INTEGER;
+  BEGIN
+    Uninitialized( type, need2, newFE );
+    APPEND( mFrm.localStack, newFE );
+    IF need2 THEN APPEND( mFrm.localStack, dummyElement ) END;
+    mFrm.maxLocal := MAX( mFrm.maxLocal, mFrm.LcLn() );
+  END AddLocal;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)TrackStore*( ord : INTEGER ),NEW;
+  BEGIN
+    IF mFrm.localStack[ord].state = ASM.Opcodes.TOP THEN
+      mFrm.localStack[ord].state := mFrm.localStack[ord].dclTp;
+    END;
+  END TrackStore;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)PopLocal1*(),NEW;
+    VAR preHi : INTEGER;
+  BEGIN
+    CUT( mFrm.localStack, mFrm.LcHi() );
+(*
+ *    Hlp.IMsg( "=================================" );
+ *    Hlp.IMsg( "PopLocal start" );
+ *    mFrm.Diag(0);
+ *    preHi := mFrm.LcHi();
+ *    CUT( mFrm.localStack, mFrm.LcHi() );
+ *    Hlp.IMsg3( "PopLocal", Ju.i2CO(preHi), Ju.i2CO(mFrm.LcHi()) );
+ *    mFrm.Diag(0);
+ *    Hlp.IMsg( "PopLocal end" );
+ *    Hlp.IMsg( "=================================" );
+ *)
+  END PopLocal1;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)PopLocal2*(),NEW;
+    VAR preHi : INTEGER;
+  BEGIN
+    CUT( mFrm.localStack, mFrm.LcHi() - 1 );
+  END PopLocal2;
+
+ (* --------------------------------------------- *)
+ (*     Invalidate locals from sigMax to top      *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)InvalidateLocals*(),NEW;
+    VAR ix : INTEGER;
+  BEGIN
+    FOR ix := mFrm.sigMax TO mFrm.LcHi() DO
+      mFrm.localStack[ix].state := ASM.Opcodes.TOP;
+    END;
+  END InvalidateLocals;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)ReleaseTo*( mark : INTEGER),NEW;
+  BEGIN
+    CUT( mFrm.localStack, mark );
+  END ReleaseTo;
+
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)AddRefParam*( 
+                                str : Lv.CharOpen ),NEW;
+    VAR newFE : FrameElement;
+  BEGIN
+    ParamRefElement( str, newFE );
+    APPEND( mFrm.localStack, newFE );
+    mFrm.maxLocal := MAX( mFrm.maxLocal, mFrm.LcLn() );
+  END AddRefParam;
+
+ (* ================================================ *)
+
+  PROCEDURE ( mFrm : MethodFrame )GetLocalArr*() : Def.JloArr,NEW;
+    VAR indx, count : INTEGER;
+        rslt : POINTER TO ARRAY OF RTS.NativeObject;
+  BEGIN
+    rslt := NIL;
+    IF mFrm.LcLn() > 0 THEN
+      NEW( rslt, mFrm.LcCount() );
+      count := 0;
+      FOR indx := 0 TO mFrm.LcHi() DO
+        IF mFrm.isDummyElem( indx ) THEN (* skip *)
+        ELSE
+          rslt[count] := mFrm.localStack[indx].state;
+          INC(count);
+        END;
+      END;
+    END;
+    RETURN rslt;
+  END GetLocalArr;
+
+ (* --------------------------------------------- *)
+
+  PROCEDURE ( mFrm : MethodFrame )GetDclTpArr*() : Def.JloArr,NEW;
+    VAR indx, count : INTEGER;
+        rslt : POINTER TO ARRAY OF RTS.NativeObject;
+  BEGIN
+    rslt := NIL;
+    IF mFrm.LcLn() > 0 THEN
+      NEW( rslt, mFrm.LcCount() );
+      count := 0;
+      FOR indx := 0 TO mFrm.LcHi() DO
+        IF mFrm.isDummyElem( indx ) THEN (* skip *)
+        ELSE
+          rslt[count] := mFrm.localStack[indx].dclTp;
+          INC(count);
+        END;
+      END;
+    END;
+    RETURN rslt;
+  END GetDclTpArr;
+
+ (* --------------------------------------------- *)
+
+  PROCEDURE ( mFrm : MethodFrame )GetEvalArr*() : Def.JloArr,NEW;
+    VAR index, count : INTEGER;
+        rslt : POINTER TO ARRAY OF RTS.NativeObject;
+        elem : RTS.NativeObject;
+  BEGIN
+    rslt := NIL;
+(*
+ Hlp.Msg("GetEvalArr: count " + Ju.i2CO(mFrm.EvCount())^ + ", hi " + Ju.i2CO(mFrm.EvHi())^ );
+ *)
+    IF mFrm.EvLn() > 0 THEN
+      NEW( rslt, mFrm.EvCount() );
+      index := 0;
+      count := 0;
+      WHILE index <= mFrm.EvHi() DO
+        elem := mFrm.evalStack[index]; 
+(*
+ Hlp.Msg2("  elem " + Ju.i2CO(index)^, Hlp.objToStr(elem) );
+ *)
+        rslt[count] := elem; INC(index); INC(count);
+        IF (elem = ASM.Opcodes.DOUBLE) OR
+           (elem = ASM.Opcodes.LONG) THEN INC(index) ;
+(*
+ Hlp.Msg("  skipping next element " );
+ *)
+        END;
+      END;
+    END;
+    RETURN rslt;
+  END GetEvalArr;
+
+ (* --------------------------------------------- *)
+ (*  Make a shallow copy of the evaluation stack  *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)GetFrameSave*( 
+             save : FrameSave ) : FrameSave,NEW;
+    VAR int,min : INTEGER;
+        eMF, lMF : INTEGER;
+        eFS, lFS : INTEGER;
+        rslt : FrameSave;
+  BEGIN
+   (* ----------- *)
+    IF save = NIL THEN 
+      eMF := mFrm.EvLn();
+      lMF := mFrm.LcLn();
+      rslt := MkFrameSave( lMF, eMF );
+      FOR int := 0 TO eMF - 1 DO
+        rslt.evalArr[int] := mFrm.evalStack[int];
+      END;
+      FOR int := 0 TO lMF - 1 DO
+        rslt.loclArr[int] := mFrm.localStack[int].state;
+        rslt.lDclArr[int] := mFrm.localStack[int].dclTp;
+      END;
+    ELSE
+      eMF := mFrm.EvLn();  (* Eval length in method frame  *)
+      lMF := mFrm.LcLn();  (* Local length in method frame *)
+      eFS := save.EvLn();  (* Eval length in FrameSave     *)
+      lFS := save.LcLn();  (* Local length in FrameSave    *)
+      ASSERT( eFS = eMF );
+      min := MIN( lFS, lMF );
+      IF min < lFS THEN 
+        rslt := save.Shorten( min );
+      ELSE 
+        rslt := save;
+      END;
+      FOR int := 0 TO min-1 DO
+       (*
+        *  The following assertion is not true in general. For
+        *  example, several branches to an exit label may each 
+        *  have a temporary variable at the point of branching 
+        *  that are of different types.
+        *    ASSERT( rslt.lDclArr[int] = mFrm.localStack[int].dclTp );
+        *  At the label's definition point all of the temporaries will
+        *  be out of scope, and the merged list will be truncated.
+        *)
+        IF rslt.loclArr[int] # mFrm.localStack[int].state THEN
+          rslt.loclArr[int] := ASM.Opcodes.TOP;
+        END; 
+      END;
+    END;
+    RETURN rslt;
+  END  GetFrameSave;
+
+ (* --------------------------------------------- *)
+ (*        Copy the stored evaluation stack       *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)OverrideLocalState*( save : FrameSave ),NEW;
+    VAR elem : FrameElement;
+        sHi : INTEGER; (* High index of saved local state *)
+        idx : INTEGER;
+  BEGIN
+   (*
+    *  Frame state is invalid, therefore construct
+    *  new state using only the saved state.
+    *)
+    CUT( mFrm.localStack, 0 );
+    sHi := save.LcHi();
+    FOR idx := 0 TO sHi DO
+      elem.state := save.loclArr[idx];
+      elem.dclTp := save.lDclArr[idx];
+      APPEND( mFrm.localStack, elem );
+    END;
+  END OverrideLocalState;
+
+ (* --------------------------------------------- *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)MergeLocalState*( save : FrameSave ),NEW;
+    VAR elem : FrameElement;
+        lLn : INTEGER; (* length of local state *)
+        sLn : INTEGER;
+        idx : INTEGER;
+  BEGIN
+   (*
+    *  Frame state is valid, therefore construct
+    *  new state merging save and mFrm.localStack.
+    *)
+    sLn := save.LcLn();
+    lLn := MIN( mFrm.LcLn(), sLn );
+    FOR idx := 0 TO lLn - 1 DO
+      ASSERT( save.lDclArr[idx] = mFrm.localStack[idx].dclTp );
+      IF save.loclArr[idx] # mFrm.localStack[idx].state THEN
+        mFrm.localStack[idx].state := ASM.Opcodes.TOP;
+      END;
+      CUT( mFrm.localStack, lLn );
+    END;
+  END MergeLocalState;
+
+ (* --------------------------------------------- *)
+ (* --------------------------------------------- *)
+  PROCEDURE (mFrm : MethodFrame)RestoreFrameState*( save : FrameSave ),NEW;
+    VAR len, int, eL, lL : INTEGER;
+        definedAtEntry : BOOLEAN;
+        ePreState, lPreState : RTS.NativeString;
+  BEGIN
+    IF save = NIL THEN
+      mFrm.setDepth( 0 ); RETURN;
+    END;
+    definedAtEntry := ~mFrm.undefEval;
+    ePreState := NIL; (* Avoid "no initialization warning *)
+    lPreState := NIL; (* Avoid "no initialization warning *)
+    mFrm.undefEval := FALSE;
+   (*
+    *  First, fix the evaluation stack.
+    *)
+    len := save.EvLn();
+    mFrm.setDepth( 0 );
+    FOR int := 0 TO len-1 DO
+      APPEND( mFrm.evalStack, save.evalArr[int] );
+    END;
+   (*
+    *  Next, fix the frame state.
+    *  Note that there are two cases here:
+    *  (1) There is a fall-through into the current label 
+    *      which is the case if mFrm.undefEval is FALSE.
+    *      In this case the saved localStack is copied
+    *      up to the current LcHi, since the jump may 
+    *      have originated from a scope with more locals,
+    *      and the EvLn must match.
+    *  (2) mFrm.undefEval is TRUE: ==> no fall-through.
+    *      In this case the entire saved localStack is 
+    *      copied, as is the evalStack.
+    *)
+    IF definedAtEntry THEN
+      mFrm.MergeLocalState( save );
+    ELSE
+      mFrm.OverrideLocalState( save );
+    END;
+  END RestoreFrameState;
+
+ (* --------------------------------------------- *)
+
+  PROCEDURE ( mFrm : MethodFrame )GetLocalArrStr*() : 
+                                RTS.NativeString,NEW;
+    VAR objArr : Def.JloArr;
+  BEGIN
+    objArr := mFrm.GetLocalArr();
+    RETURN Hlp.ObjArrToStr( objArr );
+  END GetLocalArrStr;
+
+ (* --------------------------------------------- *)
+
+  PROCEDURE ( mFrm : MethodFrame )GetDclTpArrStr*() : 
+                                RTS.NativeString,NEW;
+    VAR objArr : Def.JloArr;
+  BEGIN
+    objArr := mFrm.GetDclTpArr();
+    RETURN Hlp.ObjArrToStr( objArr );
+  END GetDclTpArrStr;
+
+ (* --------------------------------------------- *)
+
+  PROCEDURE ( mFrm : MethodFrame )GetEvalArrStr*() :
+                               RTS.NativeString,NEW;
+    VAR objArr : Def.JloArr;
+  BEGIN
+    IF mFrm.undefEval THEN RETURN Hlp.invalid;
+    ELSE 
+      objArr := mFrm.GetEvalArr();
+      RETURN Hlp.ObjArrToStr( objArr );
+    END;
+  END GetEvalArrStr;
+
+
+(* ================================================ *)
+BEGIN
+  dummyElement.state := ASM.Opcodes.TOP;
+  dummyElement.dclTp := NIL;
+END AsmFrames.
+(* ================================================ *)
+

+ 546 - 0
gpcp/AsmHelpers.cp

@@ -0,0 +1,546 @@
+
+(* ============================================================ *)
+(*  AsmHelpers is the module which provides static helper       *)
+(*  methods for module AsmUtil                                  *)
+(*  Copyright (c) John Gough 2016.                              *)
+(* ============================================================ *)
+
+MODULE AsmHelpers;
+  IMPORT 
+    RTS,
+    Jvm := JVMcodes,
+    Sym := Symbols,
+    Blt := Builtin,
+    CSt := CompState,
+    Id  := IdDesc,
+    Ty  := TypeDesc,
+    Ju  := JavaUtil,
+    Lv  := LitValue,
+
+    JL  := java_lang,
+
+    Def := AsmDefinitions,
+    Acs := AsmCodeSets,
+    ASM := org_objectweb_asm;
+
+(* ================================================ *)
+
+(*
+ *  Helper type for generating ident and
+ *  type names in style required by ASM5
+ *
+ *)
+  TYPE IdntTgPtr = 
+      POINTER TO RECORD
+        name,      (* plain name of ident referent *)
+        owner,     (* _classname_ of owning class  *)
+        signature  (* signature of identifier type *)
+                  : RTS.NativeString;
+      END;
+
+  TYPE TypeTgPtr =
+      POINTER TO RECORD
+        signature, (* signature of type- all cases *)
+        classname  (* class of type- all cases     *)
+            : RTS.NativeString;
+        auxField (* CASE OF type                   *)
+                 (*   Procedure: impl-ret-type     *)
+                 (*   Others: arr-typ (on demand)  *)
+            : Sym.Type;
+      END;
+
+(* ================================================ *)
+
+  VAR noName- : RTS.NativeString;
+      emptyMs- : RTS.NativeString;
+      invalid- : RTS.NativeString;
+
+(* ================================================ *)
+(* ================================================ *)
+(*          Forward Procedure Declarations          *)
+(* ================================================ *)
+(* ================================================ *)
+
+(*  -- currently unused diagnostic helpers
+ *
+ *PROCEDURE^ TyXtnMsg*( ty : Sym.Type );
+ *PROCEDURE^ IdXtnMsg*( id : Sym.Idnt );
+ *PROCEDURE^ IdXtnMsg2*( code : INTEGER; id : Sym.Idnt );
+ * --------------------------------- *)
+
+  PROCEDURE^ EnsurePrcName*( prc : Id.Procs );
+  PROCEDURE^ EnsureBlkName*( blk : Id.BlkId );
+  PROCEDURE^ EnsureRecName*( typ : Ty.Record );
+  PROCEDURE^ EnsureVecName*( vec : Ty.Vector );
+  PROCEDURE^ EnsurePTpName*( pTp : Ty.Procedure );
+  PROCEDURE^ EnsureTypName*( typ : Sym.Type );
+  PROCEDURE^ GetBinaryTypeName*(typ : Sym.Type) : Lv.CharOpen;
+  PROCEDURE^ tyXtn( this : Sym.Type ) : TypeTgPtr;
+  PROCEDURE^ tyCls*( this : Sym.Type ) : RTS.NativeString; 
+  PROCEDURE^ tySig*( this : Sym.Type ) : RTS.NativeString; 
+ 
+(* ================================================ *)
+(*      Notes on the usage of the tgXtn fields      *)
+(* ================================================ *)
+
+  PROCEDURE idXtn( this : Sym.Idnt ) : IdntTgPtr;
+    VAR xtn : IdntTgPtr;
+  BEGIN
+    IF this.tgXtn = NIL THEN 
+      NEW( xtn );
+      this.tgXtn := xtn;
+(* ... *)
+      WITH this : Id.BlkId DO
+          EnsureBlkName( this );
+          xtn.name := MKSTR( this.xName^ );
+          RETURN xtn;
+      | this : Id.PrcId DO
+          EnsurePrcName( this );
+          xtn.owner := MKSTR( this.clsNm^ );
+          xtn.name := MKSTR( this.prcNm^ );
+          xtn.signature := tySig( this.type );
+      | this : Id.MthId DO
+          EnsurePrcName( this );
+          xtn.owner := tyCls( this.bndType );
+          xtn.name := MKSTR( this.prcNm^ );
+          xtn.signature := tySig( this.type );
+      | this : Id.VarId DO (* A static variable *)
+          xtn.name := MKSTR( Sym.getName.ChPtr(this)^ );
+          IF this.recTyp = NIL THEN (* module var *)
+            xtn.owner := idXtn( this.dfScp ).name;
+          ELSE
+            xtn.owner := tyCls( this.recTyp );
+          END;
+          xtn.signature := MKSTR( GetBinaryTypeName( this.type )^ ); 
+
+ASSERT( xtn.name # NIL );
+ASSERT( xtn.owner # NIL );
+ASSERT( xtn.signature # NIL );
+
+      | this : Id.FldId DO
+          xtn.name := MKSTR( this.fldNm^ );
+          xtn.owner := tyCls( this.recTyp );
+          xtn.signature := MKSTR( GetBinaryTypeName( this.type )^ );
+
+ASSERT( this.fldNm # NIL );
+ASSERT( xtn.owner # NIL );
+ASSERT( xtn.signature # NIL );
+
+      | this : Id.LocId DO
+
+          ASSERT( Id.uplevA IN this.locAtt );
+          xtn.name := MKSTR( Sym.getName.ChPtr( this )^ );
+          xtn.owner := tyCls( this.dfScp(Id.Procs).xhrType.boundRecTp() );
+          xtn.signature := MKSTR( GetBinaryTypeName( this.type )^ ); 
+
+ASSERT( xtn.name # NIL );
+ASSERT( xtn.owner # NIL );
+ASSERT( xtn.signature # NIL );
+      END;
+(* ... *)
+      RETURN xtn;
+    ELSE
+      RETURN this.tgXtn(IdntTgPtr);
+    END;
+  END idXtn;
+
+  PROCEDURE idNam*( this : Sym.Idnt ) : RTS.NativeString; 
+  BEGIN
+    RETURN idXtn( this ).name;
+  END idNam;
+
+  PROCEDURE idCls*( this : Sym.Idnt ) : RTS.NativeString; 
+  BEGIN
+    RETURN idXtn( this ).owner;
+  END idCls;
+
+  PROCEDURE idSig*( this : Sym.Idnt ) : RTS.NativeString; 
+  BEGIN
+    RETURN idXtn( this ).signature;
+  END idSig;
+
+ (* --------------------------------------------- *)
+
+  PROCEDURE tyXtn( this : Sym.Type ) : TypeTgPtr;
+    VAR xtn : TypeTgPtr;
+        bnd : TypeTgPtr;
+        sig : Lv.CharOpen;
+  BEGIN
+    IF this.tgXtn = NIL THEN 
+      NEW( xtn );
+      this.tgXtn := xtn;
+      WITH this : Ty.Base DO
+         (* xName is loaded in JavaUtil's mod body *)
+          sig := this.xName;
+          xtn.auxField := Ty.mkArrayOf( this );
+          xtn.signature := MKSTR( sig^ );
+      | this : Ty.Vector DO
+          EnsureVecName( this );
+          xtn.signature := MKSTR( this.xName^ );
+          xtn.classname := tyCls( Ju.getHostRecTp( this ) )
+      | this : Ty.Record DO
+          EnsureRecName( this );
+          xtn.classname := MKSTR( this.xName^ );
+          xtn.signature := MKSTR( this.scopeNm^ );
+      | this : Ty.Array DO
+          sig := GetBinaryTypeName( this ); (* FIXME : Refactor later! *)
+          xtn.signature := MKSTR( sig^ );
+      | this : Ty.Procedure DO
+          EnsurePTpName( this );
+         (* FIXME: do we need classname? *)
+          xtn.signature := MKSTR( this.xName^ );
+      | this : Ty.Pointer DO
+          xtn^ := tyXtn( this.boundTp )^;
+      END;
+      RETURN xtn;
+    ELSE
+      ASSERT( this.tgXtn IS TypeTgPtr );
+      RETURN this.tgXtn(TypeTgPtr);
+    END;
+  END tyXtn;
+
+  (* Returns signature of this type *)
+  PROCEDURE tySig*( this : Sym.Type ) : RTS.NativeString; 
+  BEGIN
+    RETURN tyXtn(this).signature;
+  END tySig;
+
+  (* Returns classname of this type *)
+  PROCEDURE tyCls*( this : Sym.Type ) : RTS.NativeString; 
+  BEGIN
+    RETURN tyXtn(this).classname;
+  END tyCls;
+
+  PROCEDURE tyNam*( this : Sym.Type ) : RTS.NativeString;
+    VAR rslt : RTS.NativeString;
+        tXtn : TypeTgPtr;
+  BEGIN
+    tXtn := tyXtn( this );
+    rslt := tXtn.classname;
+    IF rslt # NIL THEN 
+      RETURN rslt;
+    ELSE
+      RETURN tXtn.signature;
+    END;
+  END tyNam;
+
+  (* Returns type descriptor of an array of this type *)
+  PROCEDURE tyArrTp*( this : Sym.Type ) : Sym.Type;
+    VAR xtn : TypeTgPtr;
+  BEGIN
+    xtn := tyXtn( this ); 
+    IF xtn.auxField = NIL THEN 
+      xtn.auxField := Ty.mkArrayOf( this );
+    END;
+    RETURN xtn.auxField;
+  END tyArrTp;
+
+  (* Returns signature of an array of this type *)
+  PROCEDURE tyArrSig*( this : Sym.Type ) : RTS.NativeString; 
+    VAR xtn : TypeTgPtr;
+  BEGIN
+    RETURN tySig( tyArrTp( this ) );
+  END tyArrSig;
+
+  PROCEDURE tyRetTyp*( this : Sym.Type ) : Sym.Type;
+    VAR xtn : TypeTgPtr;
+   (* ----------------------------- *)
+    PROCEDURE GetImplRetType( this : Ty.Procedure ) : Sym.Type;
+      VAR ix : INTEGER;
+          px : Id.ParId;
+    BEGIN
+      IF this.retType # NIL THEN
+        RETURN this.retType;
+      ELSE
+        FOR ix := 0 TO this.formals.tide-1 DO
+          px := this.formals.a[ix];
+          IF px.boxOrd = Ju.retMarker THEN RETURN px.type END;
+        END;
+        RETURN NIL;
+      END;
+    END GetImplRetType;
+   (* ----------------------------- *)
+  BEGIN
+    WITH this : Ty.Procedure DO
+      xtn := tyXtn( this );
+      IF xtn.auxField = NIL THEN
+        xtn.auxField := GetImplRetType( this );
+      END;
+      RETURN xtn.auxField;
+    (* else take the WITH-trap *)
+    END;
+  END tyRetTyp;
+
+(* ================================================ *)
+(* ================================================ *)
+  PROCEDURE objToStr*( obj : RTS.NativeObject ) : RTS.NativeString;
+    VAR dst : ARRAY 128 OF CHAR;
+  BEGIN
+    IF obj = NIL THEN RETURN noName END;
+
+    WITH obj : RTS.NativeString DO
+      RETURN obj;
+    | obj : JL.Integer DO
+        IF obj = ASM.Opcodes.NULL THEN RETURN MKSTR( "NIL" );
+        ELSIF obj = ASM.Opcodes.TOP THEN RETURN MKSTR( "TOP" );
+        ELSIF obj = ASM.Opcodes.INTEGER THEN RETURN MKSTR( "INT" );
+        ELSIF obj = ASM.Opcodes.LONG THEN RETURN MKSTR( "LNG" );
+        ELSIF obj = ASM.Opcodes.FLOAT THEN RETURN MKSTR( "FLT" );
+        ELSIF obj = ASM.Opcodes.DOUBLE THEN RETURN MKSTR( "DBL" );
+        ELSE RETURN MKSTR( "unknown" );
+        END;
+    ELSE
+      IF obj = NIL THEN dst := "NIL" ELSE RTS.ObjToStr( obj, dst ) END;
+      THROW( "objToStr arg is " + BOX(dst$)^ );
+    END;
+  END objToStr;
+ 
+(* ================================================ *)
+(*       Message Utilities for ASM modules          *)
+(* ================================================ *)
+
+  PROCEDURE Msg*( IN s : ARRAY OF CHAR );
+  BEGIN
+    CSt.Message( "ASM: " + s );
+  END Msg;
+
+ (* --------------------------------------------- *)
+
+  PROCEDURE MsgArr*( IN sep : ARRAY OF CHAR; 
+                          a : Lv.CharOpenArr );
+    VAR str : Lv.CharOpen;
+        idx : INTEGER;
+  BEGIN
+    str := BOX("ASM: " + a[0]^);
+    FOR idx := 1 TO LEN(a) - 1 DO
+      str := BOX( str^ + sep + a[idx]^ );
+    END;
+    CSt.Message( str );
+  END MsgArr;
+
+ (* --------------------------------------------- *)
+
+  PROCEDURE CatStrArr( a : Def.JlsArr ) : RTS.NativeString;
+    VAR str : RTS.NativeString;
+        idx : INTEGER;
+  BEGIN
+    IF a = NIL THEN RETURN emptyMs;
+    ELSE
+      str := a[0];
+      FOR idx := 1 TO LEN(a) - 1 DO
+        str := str + ", " + a[idx];
+      END;
+    END;
+    RETURN str;
+  END CatStrArr;
+
+ (* --------------------------------------------- *)
+
+  PROCEDURE ObjArrToStr*( arr : Def.JloArr ) : RTS.NativeString;
+    VAR strArr : Def.JlsArr;
+        ix : INTEGER;
+  BEGIN
+    IF arr = NIL THEN RETURN emptyMs END;
+    NEW( strArr, LEN( arr ) );
+    FOR ix := 0 TO LEN(strArr) - 1 DO
+      strArr[ix] := objToStr( arr[ix] );
+    END;
+    RETURN CatStrArr( strArr );
+  END ObjArrToStr;
+
+ (* ----------------------------------------------- *)
+ (* ----------------------------------------------- *)
+  PROCEDURE TypeToObj*( type : Sym.Type ) : RTS.NativeObject;
+    VAR rslt : RTS.NativeObject;
+  BEGIN
+    ASSERT( type # NIL );
+    IF (type.kind = Ty.basTp) OR (type.kind = Ty.enuTp) THEN
+      CASE (type(Ty.Base).tpOrd) OF
+      | Ty.boolN .. Ty.intN, Ty.setN, Ty.uBytN :
+          rslt := ASM.Opcodes.INTEGER;
+      | Ty.sReaN :
+          rslt := ASM.Opcodes.FLOAT;
+      | Ty.anyRec .. Ty.sStrN :
+          rslt := ASM.Opcodes.TOP; 
+      | Ty.lIntN :
+          rslt := ASM.Opcodes.LONG;
+      | Ty.realN :
+          rslt := ASM.Opcodes.DOUBLE;
+      END;
+    ELSE
+      EnsureTypName(type);
+      rslt := MKSTR( type.xName^ );
+    END;
+    RETURN rslt;
+  END TypeToObj;
+ (* ----------------------------------------------- *)
+
+ (* ----------------------------------------------- *)
+  PROCEDURE SigToObj*( sig : RTS.NativeString ) : RTS.NativeObject;
+  BEGIN
+    ASSERT( sig # NIL );
+    CASE sig.charAt(0) OF
+      | 'I','B','C','S','Z' : RETURN ASM.Opcodes.INTEGER;
+      | 'J' :                 RETURN ASM.Opcodes.LONG;
+      | 'F' :                 RETURN ASM.Opcodes.FLOAT;
+      | 'D' :                 RETURN ASM.Opcodes.DOUBLE;
+    ELSE
+      RETURN sig;
+    END;
+  END SigToObj;
+
+(* ================================================ *)
+(* ================================================ *)
+(*     Methods to ensure descriptor names exist     *)
+(* ================================================ *)
+(* ================================================ *)
+
+ (* ---------------------------------------------- *)
+ (*  Ensure that this record desc. has valid names *)
+ (* ---------------------------------------------- *)
+  PROCEDURE EnsureRecName*( typ : Ty.Record );
+  BEGIN
+    IF typ.xName = NIL THEN 
+      Ju.MkRecName(typ);
+    END;
+  END EnsureRecName;
+
+ (* ---------------------------------------------- *)
+ (*   Ensure that this proc desc. has valid names  *)
+ (* ---------------------------------------------- *)
+  PROCEDURE EnsurePrcName*( prc : Id.Procs );
+  BEGIN
+    IF prc.scopeNm = NIL THEN Ju.MkProcName( prc ) END;
+  END EnsurePrcName;
+
+ (* ---------------------------------------------- *)
+ (*   Ensure that this field desc. has valid names *)
+ (* ---------------------------------------------- *)
+  PROCEDURE EnsureFldName*( fld : Id.VarId );
+  BEGIN
+    IF fld.varNm = NIL THEN 
+      Ju.MkVarName(fld);
+    END;
+  END EnsureFldName;
+
+ (* ----------------------------------------------- *)
+ (*  Ensure that this block desc. has valid names   *)
+ (* ----------------------------------------------- *)
+  PROCEDURE EnsureBlkName*( blk : Id.BlkId );
+  BEGIN
+    IF blk.xName = NIL THEN Ju.MkBlkName(blk) END;
+  END EnsureBlkName;
+
+ (* ----------------------------------------------- *)
+ (*  Ensure that this vector desc. has valid names  *)
+ (* ----------------------------------------------- *)
+  PROCEDURE EnsureVecName*( vec : Ty.Vector );
+  BEGIN
+    IF vec.xName = NIL THEN Ju.MkVecName(vec) END;
+  END EnsureVecName;
+
+ (* ----------------------------------------------- *)
+ (*  Ensure that this block desc. has valid names   *)
+ (* ----------------------------------------------- *)
+  PROCEDURE EnsurePTpName*( pTp : Ty.Procedure );
+  BEGIN
+    IF pTp.xName = NIL THEN Ju.MkProcTypeName(pTp) END;
+  END EnsurePTpName;
+
+ (* ------------------------------------------------ *)
+ (* Ensure that this type descriptor has valid xName *)
+ (* ------------------------------------------------ *)
+  PROCEDURE EnsureTypName*( typ : Sym.Type );
+  BEGIN
+    IF typ.xName # NIL THEN RETURN END;
+    WITH typ : Ty.Record DO
+        Ju.MkRecName( typ );
+    | typ : Ty.Vector DO
+        Ju.MkVecName( typ );
+    | typ : Ty.Array DO
+        typ.xName := Ju.cat2( Ju.brac, GetBinaryTypeName( typ.elemTp ) );
+    | typ : Ty.Pointer DO
+        EnsureTypName( typ.boundTp );
+        typ.xName := typ.boundTp.xName;
+    | typ : Ty.Procedure DO
+        Ju.MkProcTypeName( typ );
+    ELSE
+      THROW( "Can't make TypName" );
+    END;
+  END EnsureTypName;
+
+ (* ------------------------------------------------- *)
+ (*    Compute the binary type name, and persist it   *)
+ (* ------------------------------------------------- *)
+  PROCEDURE GetBinaryTypeName*(typ : Sym.Type) : Lv.CharOpen;
+  VAR
+    arrayName : Lv.CharOpenSeq;
+    arrayTy : Sym.Type;
+  BEGIN
+    WITH typ : Ty.Base DO
+        RETURN typ.xName;
+    | typ : Ty.Vector DO
+        EnsureVecName( typ );
+        RETURN typ.xName;
+    | typ : Ty.Procedure DO
+        EnsurePTpName( typ );
+        RETURN typ.hostClass.scopeNm;
+    | typ : Ty.Array DO
+        IF typ.xName = NIL THEN
+          Lv.InitCharOpenSeq(arrayName,3);
+          arrayTy := typ;
+          WHILE arrayTy IS Ty.Array DO 
+            Lv.AppendCharOpen(arrayName,Ju.brac); 
+            arrayTy := arrayTy(Ty.Array).elemTp;
+          END;
+          Lv.AppendCharOpen(arrayName, GetBinaryTypeName(arrayTy)); 
+          typ.xName := Lv.arrayCat(arrayName);
+        END;
+        ASSERT(typ.xName # NIL);
+        RETURN typ.xName;
+    | typ : Ty.Record DO
+        EnsureRecName( typ );
+        RETURN typ.scopeNm;
+    | typ : Ty.Enum DO
+        RETURN Blt.intTp.xName;
+    | typ : Ty.Pointer DO
+        RETURN GetBinaryTypeName(typ.boundTp)
+    | typ : Ty.Opaque DO
+        IF typ.xName = NIL THEN 
+          Ju.MkAliasName(typ);
+        END;
+        RETURN typ.scopeNm;
+    END;
+  END GetBinaryTypeName;
+
+(* ================================================ *)
+(*  Factories for the creation of boxed basic types *) 
+(* ================================================ *)
+  PROCEDURE MkInteger*( val : INTEGER ) : JL.Object;
+  BEGIN
+    RETURN JL.Integer.Init( val );
+  END MkInteger;
+
+  PROCEDURE MkLong*( val : LONGINT ) : JL.Object;
+  BEGIN
+    RETURN JL.Long.Init( val );
+  END MkLong;
+
+  PROCEDURE MkFloat*( val : SHORTREAL ) : JL.Object;
+  BEGIN
+    RETURN JL.Float.Init( val );
+  END MkFloat;
+
+  PROCEDURE MkDouble*( val : REAL ) : JL.Object;
+  BEGIN
+    RETURN JL.Double.Init( val );
+  END MkDouble;
+
+(* ================================================ *)
+BEGIN
+  noName := MKSTR( "?" );
+  emptyMs := MKSTR( "empty" );
+  invalid := MKSTR( "invalid" );
+END AsmHelpers.
+(* ================================================ *)
+

+ 1915 - 0
gpcp/AsmUtil.cp

@@ -0,0 +1,1915 @@
+
+(* ============================================================ *)
+(*  AsmUtil is the module which writes java classs file         *)
+(*  structures using the ASM5.* libraries                       *)
+(*  Copyright (c) John Gough 2016.                              *)
+(* ============================================================ *)
+
+MODULE AsmUtil;
+
+  IMPORT 
+        GPCPcopyright,
+        RTS,
+        ASCII,
+        Console,
+        JavaBase,
+        FileNames,
+        GPF := GPFiles,
+        GPB := GPBinFiles,
+        Hsh := NameHash,
+        CSt := CompState,
+        Psr := CPascalP,
+        Jvm := JVMcodes,
+        Sym := Symbols,
+        Blt := Builtin,
+        Id  := IdDesc,
+        Xp  := ExprDesc,
+        Ty  := TypeDesc,
+        Lv  := LitValue,
+        Ju  := JavaUtil,
+        Cu  := ClassUtil,
+
+        JL  := java_lang,
+        Frm := AsmFrames,
+        Hlp := AsmHelpers,
+        Acs := AsmCodeSets,
+        Def := AsmDefinitions,
+        ASM := org_objectweb_asm;
+
+(* ============================================================ *)
+(* ============================================================ *)
+
+  CONST versionDefault = "V1_7";
+
+(* ============================================================ *)
+
+  TYPE AsmLabel*    = POINTER TO RECORD (Ju.Label)
+                     (*  defIx : INTEGER -- inherited field *)
+                     (*  attr*  : SET;                      *)
+                         serNm : Lv.CharOpen;
+                         asmLb : ASM.Label;
+                         evalSave : Frm.FrameSave;
+                     END;
+
+(* ============================================================ *)
+(*                Main Emitter Class Definition                 *)
+(* ============================================================ *)
+
+  TYPE AsmEmitter* = POINTER TO RECORD (Ju.JavaFile)
+                      (*
+                       *  The classfile binary file
+                       *) 
+                       file : GPB.FILE;     
+                      (*
+                       *  The class writer for this emitter
+                       *) 
+                       clsWrtr : ASM.ClassWriter;
+                       labelIx : INTEGER;
+                      (*
+                       *  Source filename of the module file.
+                       *) 
+                       srcFileName : Lv.CharOpen;
+                      (*
+                       *  Binary name of the static class
+                       *  that contains the module static code.
+                       *) 
+                       xName : Lv.CharOpen;
+                       nmStr : RTS.NativeString;
+                      (*
+                       *  The method visitor for the current method
+                       *) 
+                       thisMth : Id.Procs;
+                       procNam : Lv.CharOpen;
+                       thisMv  : ASM.MethodVisitor;
+                      (*
+                       *  Resources for tracking local variable use
+                       *) 
+                       entryLab   : AsmLabel;
+                       exitLab    : AsmLabel;
+                       rescueLab  : AsmLabel;
+                       caseArray  : POINTER TO ARRAY OF ASM.Label;
+                       caseEval   : Frm.FrameSave;
+                       mthFrame   : Frm.MethodFrame;
+                       emitStackFrames : BOOLEAN;
+                       stackFramePending : BOOLEAN;
+                     END;
+
+(* ============================================================ *)
+(*                Various Fixed Native Strings                  *)
+(* ============================================================ *)
+
+  VAR jloStr,     (* "java/lang/Object"    *)
+      jlsStr,     (* "java/lang/String"    *)
+      initStr,    (* "<init>"              *)
+      clinitStr,  (* "<clinit>"            *)
+      copyStr,    (* "__copy__"            *)
+      jleStr,     (* "java/lang/Exception" *)
+      jlmStr,     (* "java/lang/Math"      *)
+      jlcStr,     (* "java/lang/Class"     *)
+      jlchStr,    (* "java/lang/Character" *)
+      jlsyStr,    (* "java/lang/System"    *)
+      rtsStr,     (* "CP/CPJrts/CPJrts"    *)
+      cpMain,     (* "CP/CPmain/CPmain"    *)
+     (* ------------------------------------ *)
+      withTrap,   (* "WithMesg"              *)
+      withTrapSig,(* "(Ljlo;)Ljls"           *)
+      caseTrap,   (* "CaseMesg"              *) 
+      caseTrapSig,(* "(I)Ljava/lang/String;" *)
+     (* ------------------------------------ *)
+      mainSig,    (* "([Ljava/lang/String;)V *)
+      strToVoid,  (* "(Ljava/lang/String;)V  *)
+      noArgVoid : (* "()V"                   *) RTS.NativeString;
+     (* ------------------------------------ *)
+
+  VAR pubAcc,     (* ACC_PUBLIC            *)
+      prvAcc,     (* ACC_PRIVATE;          *)
+      finAcc,     (* ACC_FINAL             *)
+      supAcc,     (* ACC_SUPER             *)
+      staAcc,     (* ACC_STATIC            *)
+      absAcc,     (* ACC_ABSTRACT          *)
+      protec,     (* ACC_PACKAGE           *)
+      pckAcc,     (* ACC_PACKAGE           *)
+
+      pubSta,     (* pub + sta             *)
+      modAcc :    (* pub + fin + sup       *) INTEGER;
+
+      (* Kludge to make NIL typecheck with array formal *)
+      jlsEmptyArr : Def.JlsArr;
+
+  VAR procNames  : ARRAY 24 OF Lv.CharOpen;
+      procSigs   : ARRAY 24 OF Lv.CharOpen;
+      procRetS   : ARRAY 24 OF Lv.CharOpen;
+      getClass   : Lv.CharOpen;
+      IIretI     : Lv.CharOpen;
+      JJretJ     : Lv.CharOpen;
+
+  VAR typeArr    : ARRAY 16 OF INTEGER;
+      typeArrArr : ARRAY 16 OF Ty.Array;
+
+  VAR tagCount : INTEGER;
+
+(* ============================================================ *)
+(*                  Static Variables of Module                  *)
+(* ============================================================ *)
+
+  VAR fileSep : Lv.CharOpen;
+      wrtrFlag : INTEGER;
+      classVersion : INTEGER;
+
+(* ============================================================ *)
+(*    Forward Declarations of Static Procedures and Methods     *)
+(* ============================================================ *)
+
+  PROCEDURE^ MkNewAsmLabel( ) : AsmLabel;
+  PROCEDURE^ InterfaceNameList( rec : Ty.Record ) : Def.JlsArr;
+  PROCEDURE^ clsToVoidDesc(rec : Ty.Record) : Lv.CharOpen;
+
+  PROCEDURE^ (lab : AsmLabel)FixTag(),NEW;
+
+(* ============================================================ *)
+(* ============================================================ *)
+(*                   AsmEmitter Constructor Method              *)
+(* ============================================================ *)
+(* ============================================================ *)
+
+  PROCEDURE SetEmitVer();
+  BEGIN
+    IF CSt.asmVer = "" THEN 
+      CSt.emitNam := BOX("AsmUtil - default (V1_" + Def.versionDefault + ")");
+    ELSE
+      CSt.emitNam := BOX("AsmUtil - V1_" + CSt.asmVer);
+    END;
+  END SetEmitVer;
+
+  PROCEDURE newAsmEmitter*(fileName : ARRAY OF CHAR) : AsmEmitter;
+    VAR result : AsmEmitter;
+        pathName : Lv.CharOpen;
+   (* ------------------------------------------------- *)
+    PROCEDURE Warp(VAR s : ARRAY OF CHAR);
+      VAR i : INTEGER;
+    BEGIN
+      FOR i := 0 TO LEN(s)-1 DO
+        IF s[i] = "/" THEN s[i] := GPF.fileSep END;
+      END;
+    END Warp;
+   (* ------------------------------------------------- *)
+    PROCEDURE GetFullPath(IN fn : ARRAY OF CHAR) : Lv.CharOpen;
+      VAR ps : Lv.CharOpen;
+          ch : CHAR;
+    BEGIN
+      ps := BOX(CSt.binDir$);
+      ch := ps[LEN(ps) - 2]; (* last character *)
+      IF (ch # "/") & (ch # "\") THEN
+        ps := BOX(ps^ + fileSep^ + fn);
+      ELSE
+        ps := BOX(ps^ + fn);
+      END;
+      RETURN ps;
+    END GetFullPath;
+   (* ------------------------------------------------- *)
+  BEGIN
+   (*
+    *  Setting some module globals
+    * --------------- *)
+    wrtrFlag   := 0;
+    SetEmitVer();
+    IF CSt.doVersion THEN
+      CSt.Message("Using " + CSt.emitNam^ + " emitter" );
+    END;
+    classVersion := Def.GetClassVersion(CSt.asmVer);
+   (*
+    *  
+    *)
+    IF CSt.binDir # "" THEN
+      pathName := GetFullPath(fileName);
+    ELSE
+      pathName := BOX(fileName$);
+    END;
+    Warp(pathName);
+    NEW(result);
+    result.file := GPB.createPath(pathName);
+    IF result.file = NIL THEN RETURN NIL 
+    ELSE
+      result.srcFileName := BOX(CSt.srcNam$); 
+      result.emitStackFrames := 
+            (classVersion # ASM.Opcodes.V1_1) &
+            (classVersion > ASM.Opcodes.V1_5);
+    END;
+    RETURN result;
+  END newAsmEmitter;
+
+
+(* ============================================================ *)
+(*         Type-bound methods of AsmEmitter record type         *)
+(* ============================================================ *)
+
+  PROCEDURE (emtr : AsmEmitter)EmitStackFrame(),NEW;
+    VAR loclArr : POINTER TO ARRAY OF RTS.NativeObject;
+        evalArr : POINTER TO ARRAY OF RTS.NativeObject;
+        loclNum : INTEGER;
+        evalNum : INTEGER;
+  BEGIN
+    evalNum := emtr.mthFrame.EvCount();
+    loclNum := emtr.mthFrame.LcCount();
+    evalArr := emtr.mthFrame.GetEvalArr();
+    loclArr := emtr.mthFrame.GetLocalArr();
+    emtr.thisMv.visitFrame( ASM.Opcodes.F_NEW,
+        loclNum, loclArr, evalNum, evalArr );
+    emtr.stackFramePending := FALSE;
+  END EmitStackFrame;
+
+  PROCEDURE (emtr : AsmEmitter)CheckFrame(),NEW;
+  BEGIN
+    IF emtr.stackFramePending THEN emtr.EmitStackFrame() END;
+  END CheckFrame;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)SetProcData( ),NEW;
+  BEGIN
+   (*
+    * Used for local variable table 
+    *)
+    IF CSt.debug THEN
+      emtr.rescueLab := NIL;
+      emtr.entryLab := NIL;
+      emtr.exitLab := NIL;
+     (*
+      * This field is used to suppress emission
+      * of multiple stack frames for the same offset.  
+      *)
+      emtr.stackFramePending := FALSE;
+    END;
+  END SetProcData;
+
+ (* --------------------------------------------------------- *)
+ (* * arrName is the binary name of the array type, e.g. [[D  *)
+ (* * dms is the number of dimensions                         *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)MultiNew*(arrName : Lv.CharOpen;
+                                             dms : INTEGER),NEW;
+  BEGIN
+    emtr.CheckFrame();
+    emtr.thisMv.visitMultiANewArrayInsn( MKSTR(arrName^), dms);
+    emtr.mthFrame.DeltaEvalDepth( 1 - dms );
+    emtr.mthFrame.SetTosState( arrName );
+  END MultiNew;
+
+ (* --------------------------------------------------------- *)
+ (* ------ Push local with index "ord" of a known type ------ *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)LoadLocal*(ord : INTEGER; typ : Sym.Type);
+    VAR code : INTEGER;
+  BEGIN
+   (*
+    *  ASM does not correctly compute stack height
+    *  if the optimized loads ( xLOAD_N for N 1..4)
+    *  are used.  Hence this -
+    *)
+    IF (typ # NIL) & (typ IS Ty.Base) THEN 
+      code := Ju.typeLoad[typ(Ty.Base).tpOrd];
+    ELSE
+      code := ASM.Opcodes.ALOAD; (* all reference types *)
+    END;
+    emtr.CheckFrame();
+    emtr.thisMv.visitVarInsn( code, ord );
+    emtr.mthFrame.FixEvalStack( code, typ );
+  END LoadLocal;
+
+
+ (* --------------------------------------------------------- *)
+ (* --------------------------------------------------------- *)
+ (* -- Store TOS to local with index "ord" of a known type -- *)
+ (* --------------------------------------------------------- *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)StoreLocal*(ord : INTEGER; type : Sym.Type);
+    VAR code : INTEGER;
+  BEGIN
+   (*
+    *  ASM does not correctly compute stack height
+    *  if the optimized loads ( xLOAD_N for N 1..4)
+    *  are used.  Hence this -
+    *)
+    IF (type # NIL) & (type IS Ty.Base) THEN 
+      code := Ju.typeStore[type(Ty.Base).tpOrd];
+    ELSE
+      code := ASM.Opcodes.ASTORE;
+    END;
+    emtr.CheckFrame();
+    emtr.thisMv.visitVarInsn( code, ord );
+    emtr.mthFrame.TrackStore( ord );
+    emtr.mthFrame.FixEvalStack( code, NIL ); (* No TOS type change *)
+  END StoreLocal;
+
+ (* --------------------------------------------------------- *)
+ (*   Push local of reference type to local with index "ord"  *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)AloadLocal*( ord : INTEGER; 
+                                            typ : Sym.Type );
+  BEGIN
+    emtr.CheckFrame();
+    emtr.thisMv.visitVarInsn( ASM.Opcodes.ALOAD, ord );
+    emtr.mthFrame.DeltaEvalDepth( 1 );
+    emtr.mthFrame.SetTosType( typ );
+  END AloadLocal;
+
+ (* --------------------------------------------------------- *)
+ (* --  Allocate new class emitter for static module class -- *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)StartModClass*(mod : Id.BlkId);
+  BEGIN
+    emtr.xName := mod.xName;
+    emtr.nmStr := MKSTR(emtr.xName^);
+    emtr.clsWrtr := ASM.ClassWriter.Init( wrtrFlag );
+    emtr.clsWrtr.visit( 
+        classVersion, modAcc, emtr.nmStr, NIL, jloStr, jlsEmptyArr );
+    emtr.clsWrtr.visitSource( MKSTR(emtr.srcFileName^), NIL );
+  END StartModClass;
+
+
+ (* --------------------------------------------------------- *)
+ (* --------------------------------------------------------- *)
+ (* --  Allocate new class emitter for record module class -- *)
+ (* --------------------------------------------------------- *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)StartRecClass*(rec : Ty.Record);
+    VAR recAtt : INTEGER;
+        index  : INTEGER;
+        clsId  : Sym.Idnt;
+        impRec : Sym.Type;
+        baseNm : RTS.NativeString;
+  BEGIN
+    Hlp.EnsureRecName( rec );
+    emtr.xName := rec.xName;
+    IF rec.baseTp IS Ty.Record THEN 
+      Hlp.EnsureRecName( rec.baseTp(Ty.Record) );
+      baseNm := MKSTR( rec.baseTp.xName^ );
+    ELSE
+      baseNm := jloStr;
+    END;
+    IF rec.recAtt = Ty.noAtt THEN
+      recAtt := supAcc + finAcc;
+    ELSIF rec.recAtt = Ty.isAbs THEN
+      recAtt := supAcc + absAcc;
+    ELSE
+      recAtt := supAcc;
+    END;
+    IF rec.bindTp = NIL THEN
+      clsId := rec.idnt;
+    ELSE
+      clsId := rec.bindTp.idnt;
+    END;
+    IF clsId # NIL THEN
+      IF clsId.vMod = Sym.pubMode THEN INC( recAtt, pubAcc ) END;
+    END;
+   (*
+    *  Get names of interface, if any, into list
+    *)
+    emtr.clsWrtr := ASM.ClassWriter.Init( wrtrFlag );
+    emtr.clsWrtr.visit( 
+        classVersion, recAtt, MKSTR(rec.xName^), NIL, 
+        baseNm, InterfaceNameList(rec) );
+    emtr.clsWrtr.visitSource( MKSTR(emtr.srcFileName^), NIL );
+  END StartRecClass;
+
+ (* --------------------------------------------------------- *)
+ (* ------   Dump the procedure local variable table   ------ *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)DumpLocalTable(),NEW;
+    VAR local : Id.LocId;
+        start : AsmLabel;
+        vName : RTS.NativeString;
+        tName : RTS.NativeString;
+        proc  : Id.Procs;
+        idx   : INTEGER;
+        mv    : ASM.MethodVisitor;
+  BEGIN
+    mv := emtr.thisMv;
+    proc := emtr.thisMth;
+    IF proc # NIL THEN
+      FOR idx := 0 TO proc.locals.tide - 1 DO
+        local := proc.locals.a[idx](Id.LocId);
+        vName := local.namStr;
+        tName := MKSTR( Hlp.GetBinaryTypeName( local.type )^ );
+        IF vName = NIL THEN 
+          IF local(Id.ParId).isRcv THEN
+            vName := MKSTR( "this" );
+          ELSE
+            vName := MKSTR( "__anon" + Ju.i2CO( idx )^ + "__" );
+          END;
+        END;
+        IF local = proc.except THEN 
+          start := emtr.rescueLab;
+        ELSE
+          start := emtr.entryLab;
+        END;
+        mv.visitLocalVariable( vName, tName, NIL,
+            start.asmLb, emtr.exitLab.asmLb, local.varOrd );
+      END;
+    END;
+  END DumpLocalTable;
+  
+
+ (* --------------------------------------------------------- *)
+ (* ------   Allocate method visitor for any method    ------ *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)StartProc*(proc : Id.Procs);
+    VAR attr : INTEGER;
+        method : Id.MthId;
+        mv : ASM.MethodVisitor;
+  BEGIN
+    emtr.thisMth := proc;
+    emtr.procNam := proc.prcNm;
+    IF proc.kind = Id.conMth THEN 
+      attr := 0;
+      method := proc(Id.MthId);
+      IF method.mthAtt * Id.mask = {} THEN attr := finAcc END;
+      IF method.mthAtt * Id.mask = Id.isAbs THEN INC(attr,absAcc) END;
+      IF Id.widen IN method.mthAtt THEN INC(attr,pubAcc) END;
+    ELSE
+      attr := staAcc;
+    END;
+(*
+ *  The following code fails for "implement-only" methods
+ *  since the JVM places the "override method" in a different 
+ *  slot! We must thus live with the insecurity of public mode.
+ *
+ *  IF proc.vMod = Sym.pubMode THEN     (* explicitly public *)
+ *)
+    IF (proc.vMod = Sym.pubMode) OR     (* explicitly public *)
+       (proc.vMod = Sym.rdoMode) THEN   (* "implement only"  *)
+      INC(attr,pubAcc);
+    ELSIF proc.dfScp IS Id.PrcId THEN   (* nested procedure  *)
+      INC(attr,prvAcc);
+    END;
+
+    mv := emtr.clsWrtr.visitMethod( attr, 
+        MKSTR(proc.prcNm^), 
+        MKSTR(proc.type.xName^), 
+        NIL, jlsEmptyArr );
+    emtr.thisMv := mv;
+    emtr.procNam := proc.prcNm;
+
+    emtr.mthFrame := Frm.NewMethodFrame( proc );
+    emtr.SetProcData( );
+
+    mv.visitCode();
+    IF CSt.debug THEN
+      emtr.entryLab := MkNewAsmLabel();
+      mv.visitLabel( emtr.entryLab.asmLb );
+    END;
+  END StartProc;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)EndProc*(); (* NEW,EMPTY *)
+    VAR mv : ASM.MethodVisitor;
+        xL : AsmLabel;
+  BEGIN
+    mv := emtr.thisMv;
+    (* ... *)
+
+    (* ... *)
+    IF CSt.debug THEN
+      xL := MkNewAsmLabel();
+      mv.visitLabel( xL.asmLb );
+      xL.defIx := xL.asmLb.getOffset();
+      emtr.exitLab := xL;
+      emtr.DumpLocalTable();
+    END;
+    mv.visitMaxs( emtr.mthFrame.maxEval, emtr.mthFrame.maxLocal ); 
+    mv.visitEnd(); 
+    emtr.thisMv := NIL;
+    emtr.thisMth := NIL;
+  END EndProc;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)isAbstract*():BOOLEAN;
+    VAR proc : Id.Procs;
+  BEGIN
+    proc := emtr.thisMth;
+    IF proc = NIL THEN
+      THROW( "Can only call isAbstract during a method visit" );
+    END;
+    WITH proc : Id.MthId DO
+      RETURN proc.mthAtt * Id.mask = Id.isAbs;
+    ELSE
+      RETURN FALSE;
+    END;
+  END isAbstract;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)getScope*():Sym.Scope;
+  BEGIN
+    RETURN emtr.thisMth;
+  END getScope;
+
+ (* --------------------------------------------------------- *)
+ (* ------         ------ *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter) EmitField*(field : Id.AbVar);
+    VAR access : INTEGER;
+        fv     : ASM.FieldVisitor;
+  BEGIN
+   (*
+    *  emtr has already allocated a vector of fieldInfo
+    *)
+    CASE field.vMod OF
+    | Sym.prvMode : access := pckAcc;
+    | Sym.pubMode : access := pubAcc;
+    | Sym.rdoMode : access := pubAcc;
+    | Sym.protect : access := protec;
+    END;
+    IF field IS Id.VarId THEN INC( access, staAcc ) END;
+    fv := emtr.clsWrtr.visitField( access, Hlp.idNam(field), Hlp.idSig(field), NIL, NIL );
+    fv.visitEnd();
+  END EmitField;
+
+ (* --------------------------------------------------------- *)
+ (* ------   Translation of NEW( var of type "typ" )   ------ *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)MkNewRecord*(typ : Ty.Record);
+    VAR mv : ASM.MethodVisitor;
+        cn : RTS.NativeString;
+  BEGIN
+    mv := emtr.thisMv;
+    cn := Hlp.tyCls( typ );
+    emtr.CheckFrame();
+    mv.visitTypeInsn( ASM.Opcodes.`NEW, cn );
+    emtr.mthFrame.DeltaEvalDepth( 1 );
+    mv.visitInsn( ASM.Opcodes.DUP );
+    emtr.mthFrame.DeltaEvalDepth( 1 );
+    mv.visitMethodInsn(
+        ASM.Opcodes.INVOKESPECIAL, cn, initStr, noArgVoid, FALSE );
+    emtr.mthFrame.DeltaEvalDepth( -1 );
+    emtr.mthFrame.SetTosType( typ );
+  END MkNewRecord;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)MkNewFixedArray*(topE : Sym.Type;
+                                                len0 : INTEGER);
+    VAR dims : INTEGER;
+        arTp : Ty.Array;
+        elTp : Sym.Type;
+  BEGIN
+    (*
+    //  Fixed-size, possibly multi-dimensional arrays.
+    //  The code relies on the semantic property in CP
+    //  that the element-type of a fixed array type cannot
+    //  be an open array. This simplifies the code somewhat.
+    *)
+    emtr.PushInt(len0);
+    dims := 1;
+    elTp := topE;
+   (*
+    *  Find the number of dimensions ...
+    *)
+    LOOP
+      WITH elTp : Ty.Array DO arTp := elTp ELSE EXIT END;
+      elTp := arTp.elemTp;
+      emtr.PushInt(arTp.length);
+      INC(dims);
+    END;
+    IF dims = 1 THEN
+      emtr.Alloc1d(elTp);
+     (*
+      *  Stack is (top) len0, ref...
+      *)
+      IF elTp.kind = Ty.recTp THEN emtr.Init1dArray(elTp, len0) END;
+    ELSE
+     (*
+      *  Allocate the array headers for all dimensions.
+      *  Stack is (top) lenN, ... len0, ref...
+      *)
+      emtr.MultiNew(Ju.cat2(Ju.brac, Hlp.GetBinaryTypeName(topE)), dims);
+     (*
+      *  Stack is (top) ref...
+      *)
+      IF elTp.kind = Ty.recTp THEN emtr.InitNdArray(topE, elTp) END;
+    END;
+  END MkNewFixedArray;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)MkNewOpenArray*(arrT : Ty.Array;
+                                               dims : INTEGER);
+    VAR elTp : Sym.Type;
+        indx : INTEGER;
+  BEGIN
+   (* 
+    *  Assert: lengths are pushed already...
+    *  and we know from semantic analysis that
+    *  the number of open array dimensions match
+    *  the number of integer LENs in dims.
+    *)
+    elTp := arrT;
+   (*
+    *   Find the number of dimensions ...
+    *)
+    FOR indx := 0 TO dims-1 DO
+      elTp := elTp(Ty.Array).elemTp;
+    END;
+   (*
+    *   Allocate the array headers for all _open_ dimensions.
+    *)
+    IF dims = 1 THEN
+      emtr.Alloc1d(elTp);
+     (*
+      *  Stack is now (top) ref ...
+      *  and we _might_ need to initialize the elements.
+      *)
+      IF (elTp.kind = Ty.recTp) OR 
+         (elTp.kind = Ty.arrTp) THEN 
+        emtr.Init1dArray(elTp, 0);
+      END;
+    ELSE
+      emtr.MultiNew( Hlp.GetBinaryTypeName(arrT), dims );
+     (*
+      *    Stack is now (top) ref ...
+      *    Now we _might_ need to initialize the elements.
+      *)
+      IF (elTp.kind = Ty.recTp) OR 
+         (elTp.kind = Ty.arrTp) THEN 
+        emtr.InitNdArray(arrT.elemTp, elTp);
+      END;
+    END;
+  END MkNewOpenArray;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)MkArrayCopy*(arrT : Ty.Array);
+    VAR dims : INTEGER;
+        elTp : Sym.Type;
+  BEGIN
+   (*
+    *   Assert: we must find the lengths from the runtime 
+    *   descriptors.  Find the number of dimensions.  The 
+    *   array to copy is on the top of stack, which reads -
+    *        (top) aRef, ...
+    *)
+    elTp := arrT.elemTp;
+    IF elTp.kind # Ty.arrTp THEN
+      emtr.Code(Jvm.opc_arraylength); (* (top) len0, aRef,...  *)
+      emtr.Alloc1d(elTp);             (* (top) aRef, ...       *)
+      IF elTp.kind = Ty.recTp THEN emtr.Init1dArray(elTp, 0) END; (*0 ==> open*)
+    ELSE
+      dims := 1;
+      REPEAT
+       (* 
+        *  Invariant: an array reference is on the top of
+        *  of the stack, which reads:
+        *        (top) [arRf, lengths,] arRf ...
+        *)
+        INC(dims);
+        elTp := elTp(Ty.Array).elemTp;
+        emtr.Code(Jvm.opc_dup);         (*           arRf, arRf,... *)
+        emtr.Code(Jvm.opc_arraylength); (*     len0, arRf, arRf,... *)
+        emtr.Code(Jvm.opc_swap);        (*     arRf, len0, arRf,... *)
+        emtr.Code(Jvm.opc_iconst_0);    (*  0, arRf, len0, arRf,... *)
+        emtr.Code(Jvm.opc_aaload);      (*     arRf, len0, arRf,... *)
+       (* 
+        *  Stack reads:        (top) arRf, lenN, [lengths,] arRf ...
+        *)
+      UNTIL  elTp.kind # Ty.arrTp;
+     (*
+      *  Now get the final length...
+      *)
+      emtr.Code(Jvm.opc_arraylength);  
+     (* 
+      *   Stack reads:        (top) lenM, lenN, [lengths,] arRf ...
+      *   Allocate the array headers for all dimensions.
+      *)
+      emtr.MultiNew( Hlp.GetBinaryTypeName(arrT), dims );
+     (*
+      *  Stack is (top) ref...
+      *)
+      IF elTp.kind = Ty.recTp THEN emtr.InitNdArray(arrT.elemTp, elTp) END;
+    END;
+  END MkArrayCopy;
+
+
+(* ============================================================ *)
+(* ============================================================ *)
+(*                 Temporary Local Management                   *)
+(* ============================================================ *)
+(* ============================================================ *)
+
+ (* --------------------------------------------------------- *)
+ (*      newLocal allocates a temp and bumps LocalNum         *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)newLocal*( t : Sym.Type ) : INTEGER;
+    VAR ord, new : INTEGER;
+  BEGIN
+    ord := emtr.mthFrame.LcHi();
+    emtr.mthFrame.AddLocal( t );
+    new := emtr.mthFrame.LcHi();
+    RETURN new;
+  END newLocal;
+
+ (* --------------------------------------------------------- *)
+ (*   newLongLocal allocates a 2-slot temp, bumps LocalNum    *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)newLongLocal*( t : Sym.Type ) : INTEGER;
+    VAR ord,new : INTEGER;
+  BEGIN
+    ord := emtr.mthFrame.LcHi();
+    emtr.mthFrame.AddLocal( t );
+    new := emtr.mthFrame.LcHi();
+    ASSERT( new = ord + 2 );
+    RETURN new;
+  END newLongLocal;
+
+ (* --------------------------------------------------------- *)
+ (*      ReleaseLocal discards the temporary at index "i"     *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)PopLocal*();
+  BEGIN
+    emtr.mthFrame.PopLocal1();
+  END PopLocal;
+
+ (* --------------------------------------------------------- *)
+ (*  ReleaseLongLocal discards the temporary at index i,i+1   *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)PopLongLocal*();
+  BEGIN
+    emtr.mthFrame.PopLocal2();
+  END PopLongLocal;
+
+ (* --------------------------------------------------------- *)
+ (*  Function markTop saves the local variable depth at the   *)
+ (*  point where a call is about to be made. This call may    *)
+ (*  allocate new temporaries during argument evaluation. All *)
+ (*  of these will be dead at the return, and are discarded.  *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)markTop*() : INTEGER;
+    VAR m : INTEGER;
+  BEGIN
+    m := emtr.mthFrame.LcLn();
+    RETURN m;
+  END markTop;
+
+ (* --------------------------------------------------------- *)
+ (*     ReleaseAll discards the temps, restoring localNum     *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)ReleaseAll*(m : INTEGER);
+  BEGIN
+    emtr.mthFrame.ReleaseTo( m );
+  END ReleaseAll;
+
+(* ============================================================ *)
+(* ============================================================ *)
+(*                   Shadow Stack Management                    *)
+(* ============================================================ *)
+(* ============================================================ *)
+
+ (* --------------------------------------------------------- *)
+ (*                Get Evaluation Stack Depth                 *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)getDepth*() : INTEGER;
+  BEGIN
+    RETURN LEN(emtr.mthFrame.evalStack);
+  END getDepth;
+
+ (* --------------------------------------------------------- *)
+ (*                Set Evaluation Stack Depth                 *)
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)setDepth*(i : INTEGER);
+  BEGIN
+    emtr.mthFrame.setDepth( i );
+  END setDepth;
+
+(* ============================================================ *)
+(* ============================================================ *)
+(*                      Label Management                        *)
+(* ============================================================ *)
+(* ============================================================ *)
+
+ (* --------------------------------------------------------- *)
+ (*             Allocate a single JavaUtil.Label              *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)newLabel*() : Ju.Label;
+  BEGIN
+    RETURN MkNewAsmLabel();
+  END newLabel;
+
+  PROCEDURE (emtr : AsmEmitter)newEmptystackLabel*() : Ju.Label;
+    VAR label : AsmLabel; 
+  BEGIN
+    label := MkNewAsmLabel();
+    INCL( label.attr, Ju.forceEmpty );
+    RETURN label;
+  END newEmptystackLabel;
+
+  PROCEDURE (emtr : AsmEmitter)newLoopheaderLabel*() : Ju.Label;
+    VAR label : AsmLabel; 
+  BEGIN
+    label := MkNewAsmLabel();
+    INCL( label.attr, Ju.forceEmit );
+    RETURN label;
+  END newLoopheaderLabel;
+
+ (* --------------------------------------------------------- *)
+ (*            Allocate an array of JavaUtil.Labels           *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)getLabelRange*(VAR labs:ARRAY OF Ju.Label);
+    VAR idx : INTEGER;
+  BEGIN
+    FOR idx := 0 TO LEN(labs) - 1 DO
+      labs[idx] := MkNewAsmLabel();
+    END;
+  END getLabelRange;
+
+ (* --------------------------------------------------------- *)
+ (*                Assign a unique tag to label               *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (lab : AsmLabel)FixTag(),NEW;
+  BEGIN
+    INC(tagCount);
+    lab.serNm := BOX( "label_" + Ju.i2CO(tagCount)^ );
+  END FixTag;
+
+ (* --------------------------------------------------------- *)
+ (*            Check if label has seen a jump edge            *)
+ (* --------------------------------------------------------- *)
+ (* // NOW uses the inherited proc Ju.JumpSeen() 
+  PROCEDURE (lab : AsmLabel)JumpSeen*() : BOOLEAN;
+  BEGIN
+    RETURN jumpSeen IN lab.attr;
+  END JumpSeen;
+  *)
+
+ (* --------------------------------------------------------- *)
+ (*   Check if label not fixed AND not previously jumped to   *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (lab : AsmLabel)FwdTarget() : BOOLEAN,NEW;
+  BEGIN
+    RETURN Ju.unfixed IN lab.attr;
+  END FwdTarget;
+
+ (* --------------------------------------------------------- *)
+  PROCEDURE ( lab : AsmLabel )Str*() : Lv.CharOpen;
+    VAR attr : ARRAY 12 OF CHAR;
+        posn : ARRAY 12 OF CHAR;
+  BEGIN
+    attr := "{.,..,..,.}";
+    IF (Ju.unfixed IN lab.attr)  THEN attr[1] := "?" END;
+    IF (Ju.posFixed IN lab.attr) THEN attr[1] := "P" END;
+    IF (Ju.forceEmpty IN lab.attr) THEN 
+                      attr[3] := "m"; attr[4] := "t" END;
+    IF (Ju.assertEmpty IN lab.attr) THEN 
+                      attr[3] := "M"; attr[4] := "T" END;
+    IF (Ju.jumpSeen IN lab.attr)  THEN   
+                      attr[6] := "j"; attr[7] := "s" END;
+    IF (Ju.forceEmit IN lab.attr) THEN   attr[9] := "!" END;
+    IF lab.defIx > 0 THEN posn := ", @" + Ju.i2CO( lab.defIx )^;
+                     ELSE posn := "" END; 
+    RETURN BOX( lab.serNm^ + ": // " + attr + posn );
+  END Str;
+
+ (* --------------------------------------------------------- *)
+ (*      Emit the no-arg instruction, after legality check    *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)Code*(code : INTEGER);
+  BEGIN
+    ASSERT( ~Acs.badCode( code ) );
+    emtr.CheckFrame();
+    emtr.thisMv.visitInsn( code );
+    emtr.mthFrame.MutateEvalStack( code ); (* Compute TOS change *)
+  END Code;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)CodeI*(code,val : INTEGER);
+  BEGIN
+   (* 
+    * ASM5 allows bipush, sipush and newarray on basic types 
+    *      gpcp only allows bipush and sipush.
+    *) 
+    ASSERT((code = Jvm.opc_bipush) OR
+           (code = Jvm.opc_sipush));
+    emtr.CheckFrame();
+    emtr.thisMv.visitIntInsn( code, val );
+    emtr.mthFrame.MutateEvalStack( code ); 
+  END CodeI;
+
+ (* --------------------------------------------------------- *)
+ (*      Emit LDC for a long-int lit. Arg code is unused      *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)CodeL*(code : INTEGER; num : LONGINT);
+  BEGIN
+    (* code is ignored *)
+    emtr.CheckFrame();
+    emtr.thisMv.visitLdcInsn( Hlp.MkLong( num ) );
+    emtr.mthFrame.FixEvalStack( Jvm.opc_ldc2_w, Blt.lIntTp );
+  END CodeL;
+
+ (* --------------------------------------------------------- *)
+ (*     This is just a version of Code( c ) with a comment    *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)CodeC*(code : INTEGER; 
+                                   IN str  : ARRAY OF CHAR);
+  BEGIN
+    ASSERT( ~Acs.badCode( code ) );
+    emtr.CheckFrame();
+    emtr.thisMv.visitInsn( code );
+    emtr.mthFrame.MutateEvalStack( code ); (* Compute TOS change *)
+  END CodeC;
+
+ (* --------------------------------------------------------- *)
+ (*   Emit LDC for a floating point lit. Arg code is unused   *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)CodeR*(code : INTEGER; 
+                                      num  : REAL; short : BOOLEAN);
+  BEGIN
+    (* code is ignored *)
+    emtr.CheckFrame();
+    IF short THEN
+      emtr.thisMv.visitLdcInsn( Hlp.MkFloat( SHORT(num) ) );
+      emtr.mthFrame.FixEvalStack( Jvm.opc_ldc, Blt.sReaTp );
+    ELSE
+      emtr.thisMv.visitLdcInsn( Hlp.MkDouble( num ) );
+      emtr.mthFrame.FixEvalStack( Jvm.opc_ldc2_w, Blt.realTp );
+    END;
+  END CodeR;
+
+ (* --------------------------------------------------------- *)
+ (*        Emit a jump instruction to the given label         *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)CodeLb*(code : INTEGER; lab : Ju.Label);
+    VAR label : AsmLabel;
+  BEGIN
+    label := lab(AsmLabel);
+    emtr.CheckFrame();
+    emtr.thisMv.visitJumpInsn( code, label.asmLb );
+   (*
+    *  The eval stack effect of the jump must be applied
+    *  before the stack state is copied to label.evalSave
+    *)
+    emtr.mthFrame.FixEvalStack( code, NIL );
+    IF label.FwdTarget() THEN (* ==> this is a forward jump *)
+      label.evalSave := emtr.mthFrame.GetFrameSave( label.evalSave );
+      INCL( label.attr, Ju.jumpSeen );
+    END;
+  END CodeLb;
+
+ (* --------------------------------------------------------- *)
+ (*        Define a Label location and update lab.defIx       *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)DefLab*(lab : Ju.Label);
+    VAR label : AsmLabel;
+        undef : BOOLEAN; (* ==> eval stack is invalid *)
+  BEGIN
+    label := lab(AsmLabel);
+    ASSERT( label.defIx = 0 ); (* Labels are only defined once *)
+   (*
+    *  Only emit a label if a prior jump uses
+    *  this label as a target, or forceEmit is 
+    *  set as is the case for all loop headers.
+    *)
+    IF ~(Ju.jumpSeen IN label.attr) &
+       ~(Ju.forceEmit IN label.attr) THEN 
+      (* CSt.PrintLn("SKIPPING DefLab"); *)
+      RETURN;
+    END;
+
+    emtr.thisMv.visitLabel( label.asmLb );
+    label.defIx := label.asmLb.getOffset(); 
+
+    undef := emtr.mthFrame.InvalidStack();
+    IF Ju.assertEmpty IN label.attr THEN
+      ASSERT( ~undef & (emtr.mthFrame.EvLn() = 0 ) );
+    END;
+
+    IF Ju.jumpSeen IN label.attr THEN
+      emtr.mthFrame.RestoreFrameState( label.evalSave );
+    ELSIF Ju.forceEmpty IN label.attr THEN
+      emtr.mthFrame.RestoreFrameState( NIL );
+    ELSIF undef THEN
+     (*
+      *  State should not be undef, if the label has been
+      *  fallen into, i.e. is not following an unconditional jump.
+      *)
+      THROW( "Undefined stack state at back-edge target label" );
+    END;
+    INCL( label.attr, Ju.posFixed );
+    EXCL( label.attr, Ju.unfixed );
+    emtr.mthFrame.ValidateEvalStack();
+    IF emtr.emitStackFrames THEN
+      emtr.stackFramePending := TRUE;
+    END;
+  END DefLab;
+
+ (* --------------------------------------------------------- *)
+ (*   Define a commented Label location and update lab.defIx  *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)DefLabC*(lab : Ju.Label; 
+                                       IN c : ARRAY OF CHAR);
+  BEGIN
+    emtr.DefLab( lab );
+  END DefLabC;
+
+ (* --------------------------------------------------------- *)
+ (*   Emit an iinc instruction on a local variable of param   *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)CodeInc*(localIx,incVal : INTEGER);
+  BEGIN
+    emtr.CheckFrame();
+    emtr.thisMv.visitIincInsn( localIx, incVal );
+   (* no stack frame change *)
+  END CodeInc;
+
+ (* --------------------------------------------------------- *)
+ (* Emit an instruction that takes a type arg, e.g. checkcast *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)CodeT*(code : INTEGER; ty : Sym.Type);
+    VAR name : RTS.NativeString;
+  BEGIN
+    name := Hlp.tyNam( ty ); (* not signature! *)
+    emtr.CheckFrame();
+    emtr.thisMv.visitTypeInsn( code, name );
+   (* 
+    *  instanceof, checkcast, new, anewarray 
+    *  Stack is bumped for new, otherwise unchanged
+    *)
+    CASE code OF
+    | Jvm.opc_new        : emtr.mthFrame.FixEvalStack( code, ty );
+    | Jvm.opc_anewarray  : emtr.mthFrame.SetTosSig( Hlp.tyArrSig( ty ) );
+    | Jvm.opc_checkcast  : emtr.mthFrame.SetTosType( ty )
+    | Jvm.opc_instanceof : emtr.mthFrame.SetTosType( Blt.intTp );
+    END;
+  END CodeT;
+
+ (* --------------------------------------------------------- *)
+ (*  For ASM, this call just allocates the array of ASM.Label *)
+ (*  which will be filled in by AddSwitchLab calls. The ASM   *)
+ (*  call to emit the tableswitch op is in CodeSwitchEnd.     *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)CodeSwitch*(low,high : INTEGER; 
+                                   defLab : Ju.Label);
+    VAR asmLabs : POINTER TO ARRAY OF ASM.Label;
+        newLen : INTEGER;
+   (* ----------------------------- *)
+    PROCEDURE EvalStackAfterTableswitch(f : Frm.MethodFrame) : Frm.FrameSave;
+      VAR rslt : Frm.FrameSave;
+    BEGIN
+      f.DeltaEvalDepth( -1 );
+      rslt := f.GetFrameSave( NIL );
+      f.FixEvalStack( Jvm.opc_iconst_0, Blt.intTp );
+      RETURN rslt;
+    END EvalStackAfterTableswitch;
+   (* ----------------------------- *)
+  BEGIN
+    newLen := high - low + 1;
+    NEW( asmLabs, newLen );
+    emtr.caseArray := asmLabs;
+    emtr.caseEval := EvalStackAfterTableswitch(emtr.mthFrame);
+  END CodeSwitch;
+
+ (* --------------------------------------------------------- *)
+ (*      The dispatch table is passed to visitTableSwitch     *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)CodeSwitchEnd*( lo, hi : INTEGER;
+                                               defLab : Ju.Label );
+    VAR default : ASM.Label;
+  BEGIN
+    emtr.CheckFrame();
+    WITH defLab : AsmLabel DO
+      default := defLab.asmLb;
+      INCL( defLab.attr, Ju.jumpSeen );
+      defLab.evalSave := emtr.caseEval;
+      emtr.thisMv.visitTableSwitchInsn( lo, hi, default, emtr.caseArray );
+      INCL( defLab.attr, Ju.forceEmpty );
+    END;
+    emtr.mthFrame.InvalidateEvalStack();
+  END CodeSwitchEnd;
+
+ (* --------------------------------------------------------- *)
+ (*     Inserts an ASM.Label in the scratch array in emtr     *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)AddSwitchLab*(lab : Ju.Label; 
+                                             pos : INTEGER);
+  BEGIN
+    WITH lab : AsmLabel DO
+      lab.evalSave := emtr.caseEval;
+      emtr.caseArray[pos] := lab.asmLb;
+      INCL( lab.attr, Ju.forceEmpty );
+      INCL( lab.attr, Ju.jumpSeen );
+    END;
+  END AddSwitchLab;
+
+ (* --------------------------------------------------------- *)
+ (*         Emit a literal string to the constant pool        *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)PushStr*(IN str : Lv.CharOpen);
+  BEGIN
+   (* Push a literal string *)
+    emtr.CheckFrame();
+    emtr.thisMv.visitLdcInsn( MKSTR(str^) );
+    emtr.mthFrame.FixEvalStack( Jvm.opc_ldc, CSt.ntvStr );
+  END PushStr;
+
+ (* --------------------------------------------------------- *)
+ (*                 Load an integer constant                  *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)LoadConst*(num : INTEGER);
+  BEGIN
+(* FIXME for byte case *)
+    emtr.CheckFrame();
+    IF (num >= MIN(SHORTINT)) & (num <= MAX(SHORTINT)) THEN
+      emtr.thisMv.visitIntInsn( Jvm.opc_sipush, num );
+      emtr.mthFrame.FixEvalStack( Jvm.opc_sipush, Blt.sIntTp );
+    ELSE
+      emtr.thisMv.visitLdcInsn( Hlp.MkInteger( num ) );
+      emtr.mthFrame.FixEvalStack( Jvm.opc_ldc, Blt.intTp );
+    END;
+  END LoadConst;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)CallGetClass*();
+  BEGIN
+    THROW( "method CallGetClass not implemented" );
+  END CallGetClass; 
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)CallRTS*(ix,args,ret : INTEGER);
+    VAR classStr : RTS.NativeString;
+  BEGIN
+   (*
+    *  Select the class that supplies the operation
+    *)
+    IF ix = Ju.ToUpper THEN
+       classStr := jlchStr        (* java/lang/Character *)
+    ELSIF ix = Ju.DFloor THEN
+       classStr := jlmStr         (* java/lang/Math      *)
+    ELSIF ix = Ju.SysExit THEN
+       classStr := jlsyStr        (* java/lang/System    *)
+    ELSE
+       classStr := rtsStr         (* CP/CPJrts/CPJrts    *);
+    END;
+
+    emtr.CheckFrame();
+    emtr.thisMv.visitMethodInsn( 
+        ASM.Opcodes.INVOKESTATIC, classStr, 
+        MKSTR(procNames[ix]^), MKSTR(procSigs[ix]^), FALSE );
+    emtr.mthFrame.DeltaEvalDepth( ret - args );
+    IF ret > 0 THEN emtr.mthFrame.SetTosState( procRetS[ix] ) END;
+  END CallRTS; 
+
+ (* --------------------------------------------------------- *)
+ (*         Call a proc with a statically known name          *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)CallIT*(code : INTEGER; 
+                                       proc : Id.Procs; 
+                                       type : Ty.Procedure);
+    VAR interface : BOOLEAN;
+  BEGIN
+    interface := code = Jvm.opc_invokeinterface;
+    emtr.CheckFrame();
+    emtr.thisMv.visitMethodInsn( code, Hlp.idCls( proc ), 
+               Hlp.idNam( proc ), Hlp.idSig( proc ), interface );
+    emtr.mthFrame.DeltaEvalDepth( type.retN - type.argN );
+   (* 
+    *  Return size retN may be non-zero for a pure procedure
+    *  due to the movement of an OUT or VAR parameter to the
+    *  return position. The JVM implementation return-type
+    *  is denoted by the target-specific field tgXtn.aux
+    *)
+    IF type.retN > 0 THEN emtr.mthFrame.SetTosType( Hlp.tyRetTyp( type ) ) END;
+  END CallIT;
+
+
+ (* --------------------------------------------------------- *)
+ (*   Emit head of the constructor for static class features  *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)ClinitHead*();
+    VAR mv : ASM.MethodVisitor;
+  BEGIN
+    mv := emtr.clsWrtr.visitMethod(
+        pubSta, clinitStr, noArgVoid, NIL, jlsEmptyArr );
+    emtr.thisMv := mv;
+    emtr.procNam := BOX("<clinit>");
+
+    emtr.mthFrame := Frm.SigFrame( BOX("()V"), emtr.procNam, NIL );
+    emtr.SetProcData( );
+
+    mv.visitCode();
+  END ClinitHead;
+
+ (* --------------------------------------------------------- *)
+ (*     Emit head of main( array of String ) static method    *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)MainHead*();
+    VAR mv : ASM.MethodVisitor;
+   (* --------------- *)
+    PROCEDURE mkPrcId() : Id.Procs;
+      VAR rslt : Id.PrcId;
+          parN : Id.ParId;
+    BEGIN
+      NEW(rslt);
+      rslt.setPrcKind(Id.conPrc);
+      parN := Id.newParId()(Id.ParId); 
+      parN.parMod := Sym.in;
+      parN.type := CSt.ntvStrArr;
+      Sym.AppendIdnt(rslt.locals, parN);
+      RETURN rslt;
+    END mkPrcId;
+   (* --------------- *)
+
+  BEGIN
+    emtr.thisMth := mkPrcId();
+    mv := emtr.clsWrtr.visitMethod(
+        pubSta, "main", "([Ljava/lang/String;)V", NIL, jlsEmptyArr ); 
+
+    mv.visitCode();
+    emtr.thisMv := mv; 
+    emtr.procNam := BOX("main");
+
+    emtr.mthFrame := Frm.SigFrame( 
+           BOX("([Ljava/lang/String;)V"), emtr.procNam, NIL );
+    emtr.SetProcData( );
+    emtr.entryLab := MkNewAsmLabel();
+   (*
+    *  Save the command line args to the RTS 
+    *)
+    emtr.AloadLocal( 0, CSt.ntvStrArr );
+    mv.visitMethodInsn( 
+        ASM.Opcodes.INVOKESTATIC, cpMain, "PutArgs", mainSig , FALSE );
+    emtr.mthFrame.DeltaEvalDepth( -1 ); (* no SetTos* *)
+  END MainHead;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)VoidTail*();
+    VAR mv : ASM.MethodVisitor;
+  BEGIN
+    mv := emtr.thisMv; 
+    emtr.CheckFrame();
+    mv.visitInsn( ASM.Opcodes.`RETURN );
+   (* no SetTos* *)
+    IF CSt.debug & (emtr.thisMth # NIL) THEN
+      emtr.exitLab := MkNewAsmLabel();
+      mv.visitLabel( emtr.exitLab.asmLb );
+      emtr.exitLab.defIx := emtr.exitLab.asmLb.getOffset();
+      emtr.DumpLocalTable();
+    END;
+    mv.visitMaxs( emtr.mthFrame.maxEval, emtr.mthFrame.maxLocal );  
+    mv.visitEnd();
+    emtr.thisMv := NIL;
+    emtr.thisMth := NIL;
+  END VoidTail;
+
+ (* --------------------------------------------------------- *)
+ (*           Constructor for the module body class           *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)ModNoArgInit*();
+    VAR mv : ASM.MethodVisitor;
+   (* --------------- *)
+    PROCEDURE mkPrcId(e : AsmEmitter) : Id.Procs;
+      VAR rslt : Id.PrcId;
+          parN : Id.ParId;
+          type : Ty.Opaque;
+    BEGIN
+      NEW(rslt);
+      type := Ty.newNamTp();
+      type.xName := e.xName;
+      type.scopeNm := Ju.cat3(Ju.lCap, e.xName, Ju.semi);
+      rslt.setPrcKind(Id.conMth);
+      parN := Id.newParId()(Id.ParId); 
+      parN.isRcv := TRUE;
+      parN.parMod := Sym.in;
+      parN.type := type;
+      Sym.AppendIdnt(rslt.locals, parN);
+      RETURN rslt;
+    END mkPrcId;
+   (* --------------- *)
+  BEGIN
+    emtr.thisMth := mkPrcId(emtr);
+   (* 
+    * Create a new method visitor and save in emitter
+    *)
+    mv := emtr.clsWrtr.visitMethod(
+        ASM.Opcodes.ACC_PUBLIC, "<init>", "()V", NIL, jlsEmptyArr );
+    emtr.thisMv := mv;
+    emtr.procNam := BOX("<init>");
+
+    emtr.mthFrame := Frm.SigFrame( BOX("()V"), emtr.procNam, NIL );
+    emtr.SetProcData( );
+    mv.visitCode();
+    emtr.entryLab := MkNewAsmLabel();
+    mv.visitLabel( emtr.entryLab.asmLb );
+    
+    mv.visitVarInsn( ASM.Opcodes.ALOAD, 0 );
+    emtr.mthFrame.DeltaEvalDepth( 1 );
+    mv.visitMethodInsn( 
+        ASM.Opcodes.INVOKESPECIAL, jloStr, "<init>", "()V", FALSE );
+    emtr.mthFrame.DeltaEvalDepth( -1 );
+    emtr.VoidTail();
+(* FIXME: need to emit LocalVariableTable *)
+  END ModNoArgInit;
+
+ (* --------------------------------------------------------- *)
+ (*             Noarg Constructor for record class            *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)RecMakeInit*(rec : Ty.Record;
+                                            prc : Id.PrcId);
+    VAR mv : ASM.MethodVisitor;
+        sg  : Lv.CharOpen;
+        pTp : Ty.Procedure;
+  BEGIN
+    IF (prc = NIL) &
+       ((Sym.noNew IN rec.xAttr) OR (Sym.xCtor IN rec.xAttr)) THEN
+      RETURN;
+    END;
+   (*
+    *  Get the procedure type, if any.
+    *)
+    IF prc # NIL THEN
+      pTp := prc.type(Ty.Procedure);
+      Ju.MkCallAttr(prc, pTp);
+      sg := pTp.xName;
+    ELSE
+      pTp := NIL;
+      sg := BOX("()V");
+    END;
+   (* 
+    * Create a new method visitor and save in emitter
+    *)
+    mv := emtr.clsWrtr.visitMethod(
+        ASM.Opcodes.ACC_PUBLIC, "<init>", MKSTR(sg^), NIL, jlsEmptyArr );
+    emtr.thisMv := mv;
+    emtr.procNam := BOX("<init>");
+    emtr.mthFrame := Frm.SigFrame( sg, emtr.procNam, NIL );
+    emtr.SetProcData( );
+    mv.visitCode();
+
+    emtr.AloadLocal( 0, rec );
+  END RecMakeInit;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)CallSuperCtor*(rec : Ty.Record;
+                                          pTy : Ty.Procedure);
+    VAR idx : INTEGER;
+        fld : Sym.Idnt;
+        baseStr, sg : RTS.NativeString;
+        mv : ASM.MethodVisitor;
+  BEGIN
+    emtr.CheckFrame();
+    IF pTy # NIL THEN
+      sg := MKSTR(pTy.xName^);
+    ELSE
+      sg := noArgVoid;
+    END;
+   (* 
+    *  Initialize the embedded superclass object
+    *  The receiver object is already pushed on the stack
+    *  QUESTION: what happens if the ctor needs args?
+    *)
+    IF (rec.baseTp # NIL) & (rec.baseTp # Blt.anyRec) THEN
+      baseStr := MKSTR(rec.baseTp(Ty.Record).xName^);
+    ELSE
+      baseStr := jloStr;
+    END;
+    mv := emtr.thisMv;
+    mv.visitMethodInsn(
+        ASM.Opcodes.INVOKESPECIAL, baseStr, initStr, sg, FALSE );
+    emtr.mthFrame.DeltaEvalDepth( -1 );
+   (* 
+    *  Initialize fields as necessary
+    *)
+    FOR idx := 0 TO rec.fields.tide - 1 DO
+      fld := rec.fields.a[idx];
+      IF (fld.type IS Ty.Record) OR 
+         ((fld.type IS Ty.Array) & ~(fld.type IS Ty.Vector)) THEN
+        emtr.AloadLocal( 0, rec ); (* ?? *)
+        emtr.VarInit(fld);
+        emtr.PutGetF( ASM.Opcodes.PUTFIELD, rec, fld(Id.FldId) );
+      END;
+    END;
+  END CallSuperCtor;
+
+ (* --------------------------------------------------------- *)
+ (*  Emit the header for the record (shallow) __copy__ method *)
+ (*  this method makes a *value* copy of the bound record.    *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)CopyProcHead*(rec : Ty.Record);
+    VAR mv : ASM.MethodVisitor;
+        sg : Lv.CharOpen;
+   (* --------------- *)
+    PROCEDURE mkMthId(rec : Ty.Record) : Id.Procs;
+      VAR rslt : Id.MthId;
+          parN : Id.ParId;
+    BEGIN
+      NEW(rslt);
+      rslt.setPrcKind(Id.conMth);
+     (* Receiver (dst) *)
+      parN := Id.newParId()(Id.ParId); 
+      parN.isRcv := TRUE;
+      parN.parMod := Sym.var;
+      parN.type := rec;
+      Sym.AppendIdnt(rslt.locals, parN);
+     (* Source val record *)
+      parN := Id.newParId()(Id.ParId); 
+      parN.parMod := Sym.in;
+      parN.type := rec;
+      Sym.AppendIdnt(rslt.locals, parN);
+      RETURN rslt;
+    END mkMthId;
+   (* --------------- *)
+  BEGIN
+    emtr.thisMth := mkMthId(rec);
+    sg := clsToVoidDesc(rec);
+
+    mv := emtr.clsWrtr.visitMethod( 
+            pubAcc, copyStr, MKSTR(sg^), NIL, jlsEmptyArr );
+    emtr.thisMv := mv;
+    emtr.procNam := BOX(copyStr); (* Coerce JLS to CharOpen *)
+    
+    emtr.mthFrame := Frm.SigFrame( sg, emtr.procNam, rec.xName );
+    emtr.SetProcData( );
+    mv.visitCode();
+    emtr.entryLab := MkNewAsmLabel();
+    mv.visitLabel( emtr.entryLab.asmLb );
+  END CopyProcHead;
+
+ (* --------------------------------------------------------- *)
+ (*       Emit a call to the bound type __copy__ method       *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)ValRecCopy*(typ : Ty.Record);
+  BEGIN
+   (*
+    *  Stack at entry is (top) srcRef, dstRef, ...
+    *)
+    emtr.CheckFrame();
+    emtr.thisMv.visitMethodInsn( ASM.Opcodes.INVOKEVIRTUAL,
+        MKSTR(typ.xName^), copyStr, MKSTR(clsToVoidDesc(typ)^), FALSE );
+    emtr.mthFrame.DeltaEvalDepth( -2 );
+  END ValRecCopy;
+
+ (* --------------------------------------------------------- *)
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)Try*();
+  BEGIN
+    emtr.rescueLab := MkNewAsmLabel();
+    INCL( emtr.rescueLab.attr, Ju.forceEmit );
+    emtr.thisMv.visitTryCatchBlock( 
+        emtr.entryLab.asmLb, 
+        emtr.rescueLab.asmLb, 
+        emtr.rescueLab.asmLb, jleStr );
+  END Try;
+
+ (* --------------------------------------------------------- *)
+ (*    At the catch block label stack depth is exactly one,   *)
+ (*    and variable state exactly as at entry to Try block.   *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)Catch*(prc : Id.Procs);
+    VAR ix : INTEGER;
+  BEGIN
+    emtr.mthFrame.ValidateEvalStack();
+    emtr.mthFrame.setDepth( 1 );
+    emtr.mthFrame.InvalidateLocals();
+    emtr.mthFrame.SetTosType( CSt.ntvExc );
+    emtr.DefLabC( emtr.rescueLab, "Catch Block Entry" );
+   (*
+    *  Remark:  at this label, stack depth is just one!
+    *           After this store the stack is empty.
+    *)
+    emtr.StoreLocal( prc.except.varOrd, NIL ); (* NIL ==> use astore *)
+  END Catch;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)MkNewException*();
+  BEGIN
+    emtr.CheckFrame();
+    emtr.thisMv.visitTypeInsn( Jvm.opc_new, jleStr );
+    emtr.mthFrame.FixEvalStack( Jvm.opc_new, CSt.ntvExc );
+  END MkNewException;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)InitException*();
+  BEGIN
+    emtr.CheckFrame();
+    emtr.thisMv.visitMethodInsn( 
+        ASM.Opcodes.INVOKESPECIAL, jleStr, initStr, strToVoid, FALSE );
+    emtr.mthFrame.DeltaEvalDepth( -2 );
+  END InitException;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)Dump*();
+    VAR rslt : POINTER TO ARRAY OF BYTE;
+        indx : INTEGER;
+  BEGIN
+    emtr.clsWrtr.visitEnd();
+    rslt := emtr.clsWrtr.toByteArray();
+    FOR indx := 0 TO LEN(rslt) - 1 DO
+      GPB.WriteByte( emtr.file, rslt[indx] );
+    END;
+    GPB.CloseFile( emtr.file );
+  END Dump;
+
+ (* --------------------------------------------------------- *
+  * 
+  *  PutField and GetField for class *static* fields 
+  *  JVM static fields occur in two contexts in GPCP --
+  *  * Global variables of module SomeMod are static fields 
+  *    of the class CP/SomeMod/SomeMod.class
+  *  * Static fields of some JVM class defined in some other
+  *    language are accessed using the same instructions
+  *
+  * --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)PutGetS*(code : INTEGER; 
+                                    blk  : Id.BlkId; (* not used anymore *)
+                                    fld  : Id.VarId);
+  BEGIN
+    emtr.CheckFrame();
+    emtr.thisMv.visitFieldInsn( 
+        code, Hlp.idCls(fld), Hlp.idNam(fld), Hlp.idSig(fld) );
+    emtr.mthFrame.PutGetFix( code, fld.type );
+  END PutGetS;
+
+ (* --------------------------------------------------------- *
+  * 
+  *  PutField and GetField for class *instance* fields 
+  *
+  * --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)PutGetF*(code : INTEGER; 
+                                    rec  : Ty.Record; (* not used anymore *)
+                                    fld  : Id.AbVar);
+  BEGIN
+    emtr.CheckFrame();
+    emtr.thisMv.visitFieldInsn( 
+        code, Hlp.idCls(fld), Hlp.idNam(fld), Hlp.idSig(fld) );
+    emtr.mthFrame.PutGetFix( code, fld.type );
+  END PutGetF;
+
+ (* --------------------------------------------------------- *)
+ (*   Allocate a one-dimensional array of given element type  *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)Alloc1d*(elTp : Sym.Type);
+    VAR tName : RTS.NativeString;
+  BEGIN
+    emtr.CheckFrame();
+    WITH elTp : Ty.Base DO
+      IF (elTp.tpOrd < Ty.anyRec) OR (elTp.tpOrd = Ty.uBytN) THEN
+        emtr.thisMv.visitIntInsn(Jvm.opc_newarray, typeArr[elTp.tpOrd]);
+        emtr.mthFrame.FixEvalStack( Jvm.opc_newarray, typeArrArr[elTp.tpOrd] );
+      ELSE
+        emtr.thisMv.visitTypeInsn( Jvm.opc_anewarray, jloStr );
+        emtr.mthFrame.FixEvalStack( Jvm.opc_anewarray, CSt.ntvStrArr );
+      END;
+    ELSE
+      emtr.thisMv.visitTypeInsn( Jvm.opc_anewarray, Hlp.tyNam( elTp ) );
+      emtr.mthFrame.FixEvalSig( Jvm.opc_newarray, Hlp.tyArrSig( elTp ) );
+    END;
+  END Alloc1d;
+
+
+ (* --------------------------------------------------------- *)
+ (*  Initialize a declared variable -                         *)
+ (*  Because the JVM type system does not have value          *)
+ (*  aggregates ALL aggregate type have to be allocated on    *)
+ (*  heap at the point of declaration. This method does this. *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)VarInit*(var : Sym.Idnt);
+    VAR typ : Sym.Type;
+  BEGIN
+   (*
+    *  Precondition: var is of a type that needs initialization
+    *)
+    typ := var.type;
+    WITH typ : Ty.Record DO
+        emtr.MkNewRecord(typ);
+    | typ : Ty.Array DO
+        emtr.MkNewFixedArray(typ.elemTp, typ.length);
+    ELSE
+      emtr.Code(Jvm.opc_aconst_null);
+    END;
+   (* --------------- *)
+  END VarInit;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)Trap*(IN str : ARRAY OF CHAR);
+    VAR mv : ASM.MethodVisitor;
+  BEGIN
+    emtr.CheckFrame();
+    mv := emtr.thisMv;
+    mv.visitTypeInsn( ASM.Opcodes.`NEW, jleStr );
+    mv.visitInsn( ASM.Opcodes.DUP );
+    mv.visitLdcInsn( MKSTR(str) );
+    emtr.mthFrame.DeltaEvalDepth( 3 );
+    mv.visitMethodInsn(
+        ASM.Opcodes.INVOKESPECIAL, jleStr, initStr, strToVoid, FALSE );
+    emtr.mthFrame.DeltaEvalDepth( -2 );
+    mv.visitInsn( ASM.Opcodes.ATHROW );
+    emtr.mthFrame.InvalidateEvalStack();
+   (* no net stack change *)
+  END Trap;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)CaseTrap*(i : INTEGER);
+    VAR mv : ASM.MethodVisitor;
+  BEGIN
+    emtr.CheckFrame();
+    mv := emtr.thisMv;
+    mv.visitTypeInsn( ASM.Opcodes.`NEW, jleStr );
+    mv.visitInsn( ASM.Opcodes.DUP );
+    emtr.LoadLocal( i, Blt.intTp );
+    emtr.mthFrame.DeltaEvalDepth( 3 );
+    mv.visitMethodInsn(
+        ASM.Opcodes.INVOKESTATIC, rtsStr, caseTrap, caseTrapSig, FALSE );
+    mv.visitMethodInsn(
+        ASM.Opcodes.INVOKESPECIAL, jleStr, initStr, strToVoid, FALSE );
+    emtr.mthFrame.DeltaEvalDepth( -2 );
+    mv.visitInsn( ASM.Opcodes.ATHROW );
+    emtr.mthFrame.InvalidateEvalStack();
+   (* no net stack change *)
+  END CaseTrap;
+
+ (* --------------------------------------------------------- *)
+
+  PROCEDURE (emtr : AsmEmitter)WithTrap*(id : Sym.Idnt);
+    VAR mv : ASM.MethodVisitor;
+  BEGIN
+    emtr.CheckFrame();
+    mv := emtr.thisMv;
+    mv.visitTypeInsn( ASM.Opcodes.`NEW, jleStr ); (* +1 *)
+    mv.visitInsn( ASM.Opcodes.DUP );              (* +2 *)
+    emtr.GetVar( id );                            (* +3 *)
+    emtr.mthFrame.DeltaEvalDepth( 3 );
+    mv.visitMethodInsn(
+        ASM.Opcodes.INVOKESTATIC, rtsStr, withTrap, withTrapSig, FALSE );
+    mv.visitMethodInsn(
+        ASM.Opcodes.INVOKESPECIAL, jleStr, initStr, strToVoid, FALSE );
+    emtr.mthFrame.DeltaEvalDepth( -2 );
+    mv.visitInsn( ASM.Opcodes.ATHROW );
+    emtr.mthFrame.InvalidateEvalStack();
+   (* no net stack change *)
+  END WithTrap;
+
+ (* --------------------------------------------------------- *)
+ (*     We presume that there is not need otherwise for       *)
+ (*     a label at this location.  So we generate a dummy.    *)
+ (* --------------------------------------------------------- *)
+  PROCEDURE (emtr : AsmEmitter)Line*(lnNm : INTEGER);
+    VAR dummy : ASM.Label;
+        mv : ASM.MethodVisitor;
+  BEGIN
+    NEW( dummy );
+    mv := emtr.thisMv;
+    mv.visitLabel( dummy );
+    mv.visitLineNumber( lnNm, dummy );
+  END Line;
+
+(* ============================================================ *)
+(* ============================================================ *)
+(*                        Static Methods                        *)
+(* ============================================================ *)
+(* ============================================================ *)
+
+ (* ------------------------------------------------- *)
+ (* ------------------------------------------------- *)
+  PROCEDURE MkNewAsmLabel( ) : AsmLabel;
+    VAR rslt : AsmLabel;
+  BEGIN
+    NEW( rslt );
+    NEW( rslt.asmLb );
+    rslt.defIx := 0;
+    rslt.attr := { Ju.unfixed }; (* Alwasy born unfixed *)
+    rslt.evalSave := NIL;
+    rslt.FixTag();  (* assigns a dummy name to this label *)
+    RETURN rslt;
+  END MkNewAsmLabel;
+
+ (* ------------------------------------------------- *)
+
+  PROCEDURE InterfaceNameList( rec : Ty.Record ) : Def.JlsArr;
+    VAR result  : Def.JlsArr;
+        element : Lv.CharOpen;
+        ix,len  : INTEGER;
+  BEGIN
+    len := rec.interfaces.tide;
+    IF len > 0 THEN
+      NEW(result, len);
+      FOR ix := 0 TO len - 1 DO
+        element := rec.interfaces.a[ix].boundRecTp()(Ty.Record).xName;
+        result[ix] := MKSTR(element^);
+      END;
+    ELSE
+      result := jlsEmptyArr;
+    END;
+    RETURN result;
+  END InterfaceNameList;
+
+ (* ------------------------------------------------- *)
+
+  PROCEDURE clsToVoidDesc(rec : Ty.Record) : Lv.CharOpen;
+  BEGIN
+    Hlp.EnsureRecName( rec );
+    RETURN Ju.cat3(Ju.lPar,rec.scopeNm,Ju.rParV); 
+  END clsToVoidDesc;
+  
+(* ============================================================ *)
+BEGIN  (* Module Body *)
+  tagCount := 0;
+ (* -------------------------------------------- *)
+  jloStr        := MKSTR( "java/lang/Object"    );
+  jlsStr        := MKSTR( "java/lang/String"    );
+  initStr       := MKSTR( "<init>"              );
+  clinitStr     := MKSTR( "<clinit>"            );
+  copyStr       := MKSTR( "__copy__"            );
+  jleStr        := MKSTR( "java/lang/Exception" );
+  jlmStr        := MKSTR( "java/lang/Math"      );
+  jlcStr        := MKSTR( "java/lang/Class"     );
+  jlchStr       := MKSTR( "java/lang/Character" );
+  jlsyStr       := MKSTR( "java/lang/System"    );
+
+  cpMain        := MKSTR( "CP/CPmain/CPmain"    );
+  rtsStr        := MKSTR( "CP/CPJrts/CPJrts"    );
+
+  noArgVoid     := MKSTR( "()V"                    );
+  strToVoid     := MKSTR( "(Ljava/lang/String;)V"  );
+  mainSig       := MKSTR( "([Ljava/lang/String;)V" );
+  
+ (* --------------------------------------------- *)
+  withTrap      := MKSTR( "WithMesg"               ); 
+  withTrapSig   := 
+     MKSTR("(Ljava/lang/Object;)Ljava/lang/String;");
+  caseTrap      := MKSTR( "CaseMesg"               ); 
+  caseTrapSig   := 
+     MKSTR("(I)Ljava/lang/String;");
+ (* --------------------------------------------- *)
+
+  pubAcc        := ASM.Opcodes.ACC_PUBLIC;
+  prvAcc        := ASM.Opcodes.ACC_PRIVATE;
+  finAcc        := ASM.Opcodes.ACC_FINAL;
+  supAcc        := ASM.Opcodes.ACC_SUPER;
+  staAcc        := ASM.Opcodes.ACC_STATIC;
+  absAcc        := ASM.Opcodes.ACC_ABSTRACT;
+  protec        := ASM.Opcodes.ACC_PROTECTED;
+  pckAcc        := 0;
+
+  pubSta        := pubAcc + staAcc;
+  modAcc        := pubAcc + finAcc + supAcc;
+
+  fileSep := Lv.charToCharOpen(GPF.fileSep);
+
+  procNames[Ju.StrCmp]  := Lv.strToCharOpen("strCmp");
+  procNames[Ju.StrToChrOpen] := Lv.strToCharOpen("JavaStrToChrOpen");
+  procNames[Ju.StrToChrs] := Lv.strToCharOpen("JavaStrToFixChr");
+  procNames[Ju.ChrsToStr] := Lv.strToCharOpen("FixChToJavaStr");
+  procNames[Ju.StrCheck] := Lv.strToCharOpen("ChrArrCheck");
+  procNames[Ju.StrLen] := Lv.strToCharOpen("ChrArrLength");
+  procNames[Ju.ToUpper] := Lv.strToCharOpen("toUpperCase");
+  procNames[Ju.DFloor] := Lv.strToCharOpen("floor");
+  procNames[Ju.ModI] := Lv.strToCharOpen("CpModI");
+  procNames[Ju.ModL] := Lv.strToCharOpen("CpModL");
+  procNames[Ju.DivI] := Lv.strToCharOpen("CpDivI");
+  procNames[Ju.DivL] := Lv.strToCharOpen("CpDivL");
+  procNames[Ju.StrCatAA] := Lv.strToCharOpen("ArrArrToString");
+  procNames[Ju.StrCatSA] := Lv.strToCharOpen("StrArrToString");
+  procNames[Ju.StrCatAS] := Lv.strToCharOpen("ArrStrToString");
+  procNames[Ju.StrCatSS] := Lv.strToCharOpen("StrStrToString");
+  procNames[Ju.StrLP1] := Lv.strToCharOpen("ChrArrLplus1");
+  procNames[Ju.StrVal] := Lv.strToCharOpen("ChrArrStrCopy");
+  procNames[Ju.SysExit] := Lv.strToCharOpen("exit");
+  procNames[Ju.LoadTp1] := Lv.strToCharOpen("getClassByOrd");
+  procNames[Ju.LoadTp2] := Lv.strToCharOpen("getClassByName");
+
+  getClass := Lv.strToCharOpen("getClass");
+  IIretI   := Lv.strToCharOpen("(II)I");
+  JJretJ   := Lv.strToCharOpen("(JJ)J");
+
+  procSigs[Ju.StrCmp]   := Lv.strToCharOpen("([C[C)I");
+  procSigs[Ju.StrToChrOpen] := Lv.strToCharOpen("(Ljava/lang/String;)[C");
+  procSigs[Ju.StrToChrs] := Lv.strToCharOpen("([CLjava/lang/String;)V");
+  procSigs[Ju.ChrsToStr] := Lv.strToCharOpen("([C)Ljava/lang/String;");
+  procSigs[Ju.StrCheck] := Lv.strToCharOpen("([C)V");
+  procSigs[Ju.StrLen] := Lv.strToCharOpen("([C)I");
+  procSigs[Ju.ToUpper] := Lv.strToCharOpen("(C)C");
+  procSigs[Ju.DFloor] := Lv.strToCharOpen("(D)D");
+  procSigs[Ju.ModI] := IIretI;
+  procSigs[Ju.ModL] := JJretJ;
+  procSigs[Ju.DivI] := IIretI;
+  procSigs[Ju.DivL] := JJretJ;
+  procSigs[Ju.StrCatAA] := Lv.strToCharOpen("([C[C)Ljava/lang/String;");
+  procSigs[Ju.StrCatSA] := Lv.strToCharOpen(
+                                "(Ljava/lang/String;[C)Ljava/lang/String;");
+  procSigs[Ju.StrCatAS] := Lv.strToCharOpen(
+                                "([CLjava/lang/String;)Ljava/lang/String;");
+  procSigs[Ju.StrCatSS] := Lv.strToCharOpen(
+                   "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+  procSigs[Ju.StrLP1] := procSigs[Ju.StrLen];
+  procSigs[Ju.StrVal] := Lv.strToCharOpen("([C[C)V");
+  procSigs[Ju.SysExit] := Lv.strToCharOpen("(I)V");
+  procSigs[Ju.LoadTp1] := Lv.strToCharOpen("(I)Ljava/lang/Class;");
+  procSigs[Ju.LoadTp2] := Lv.strToCharOpen(
+                               "(Ljava/lang/String;)Ljava/lang/Class;");
+
+  procRetS[Ju.StrVal] := NIL;
+  procRetS[Ju.SysExit] := NIL;
+  procRetS[Ju.StrToChrs] := NIL;
+  procRetS[Ju.StrCheck] := NIL;
+
+  procRetS[Ju.StrCmp] := Lv.strToCharOpen("I");
+  procRetS[Ju.ModI]   := procRetS[Ju.StrCmp];
+  procRetS[Ju.DivI]   := procRetS[Ju.StrCmp];
+  procRetS[Ju.StrLen] := procRetS[Ju.StrCmp];
+  procRetS[Ju.StrLP1] := procRetS[Ju.StrCmp];
+
+  procRetS[Ju.DivL] := Lv.strToCharOpen( "J" );
+  procRetS[Ju.ModL] := procRetS[Ju.DivL];
+
+  procRetS[Ju.LoadTp1] := Lv.strToCharOpen( "Ljava/lang/Class;");
+  procRetS[Ju.LoadTp2] := procRetS[Ju.LoadTp1];
+
+  procRetS[Ju.ChrsToStr] := Lv.strToCharOpen("Ljava/lang/String;");
+  procRetS[Ju.StrCatAA]  := procRetS[Ju.ChrsToStr];
+  procRetS[Ju.StrCatSA]  := procRetS[Ju.ChrsToStr];
+  procRetS[Ju.StrCatAS]  := procRetS[Ju.ChrsToStr];
+  procRetS[Ju.StrCatSS]  := procRetS[Ju.ChrsToStr];
+
+  procRetS[Ju.StrToChrOpen] := Lv.strToCharOpen("[C");
+  procRetS[Ju.ToUpper] := Lv.strToCharOpen("C");
+  procRetS[Ju.DFloor] := Lv.strToCharOpen("D");
+
+ (* Mapping of base types *)
+  typeArr[ Ty.boolN] := ASM.Opcodes.T_BOOLEAN;
+  typeArr[ Ty.sChrN] := ASM.Opcodes.T_SHORT;
+  typeArr[ Ty.charN] := ASM.Opcodes.T_CHAR;
+  typeArr[ Ty.byteN] := ASM.Opcodes.T_BYTE;
+  typeArr[ Ty.uBytN] := ASM.Opcodes.T_BYTE;
+  typeArr[ Ty.sIntN] := ASM.Opcodes.T_SHORT;
+  typeArr[  Ty.intN] := ASM.Opcodes.T_INT;
+  typeArr[ Ty.lIntN] := ASM.Opcodes.T_LONG;
+  typeArr[ Ty.sReaN] := ASM.Opcodes.T_FLOAT;
+  typeArr[ Ty.realN] := ASM.Opcodes.T_DOUBLE;
+  typeArr[  Ty.setN] := ASM.Opcodes.T_INT;
+
+ (* Arrays of base types *)
+  typeArrArr[ Ty.boolN] := Ty.mkArrayOf( Blt.boolTp );
+  typeArrArr[ Ty.charN] := Ty.mkArrayOf( Blt.charTp );
+  typeArrArr[ Ty.sChrN] := typeArrArr[ Ty.charN ];
+  typeArrArr[ Ty.byteN] := Ty.mkArrayOf( Blt.byteTp );
+  typeArrArr[ Ty.uBytN] := typeArrArr[ Ty.byteN ];
+  typeArrArr[ Ty.sIntN] := Ty.mkArrayOf( Blt.sIntTp );
+  typeArrArr[  Ty.intN] := Ty.mkArrayOf( Blt.intTp  );
+  typeArrArr[ Ty.lIntN] := Ty.mkArrayOf( Blt.lIntTp );
+  typeArrArr[ Ty.sReaN] := Ty.mkArrayOf( Blt.sReaTp );
+  typeArrArr[ Ty.realN] := Ty.mkArrayOf( Blt.realTp );
+  typeArrArr[  Ty.setN] := typeArrArr[ Ty.intN ];
+
+END AsmUtil.
+(* ============================================================ *)
+

+ 5 - 6
gpcp/CPascal.cp

@@ -27,7 +27,6 @@ MODULE CPascal;
         Scnr := CPascalS,
         CPascalErrors,
         New := NewSymFileRW,
-        Old := OldSymFileRW,
         NameHash,
         Visitor,
         Builtin,
@@ -152,11 +151,7 @@ MODULE CPascal;
             IF Scnr.errors = 0 THEN
               IF CSt.doSym THEN
                 CondMsg("Emitting symbol file");
-                IF CSt.legacy THEN
-                  Old.EmitSymfile(CSt.thisMod);
-                ELSE
-                  New.EmitSymfile(CSt.thisMod);
-                END;
+                New.EmitSymfile(CSt.thisMod);
                 CSt.symEnd := RTS.GetMillis();
                 IF CSt.doAsm THEN
                   IF CSt.isForeign() THEN
@@ -178,6 +173,8 @@ MODULE CPascal;
         Finalize;
         IF CSt.doStats THEN CSt.Report END;
       END;
+(* ===================================================== *)
+(* Comment out the Rescue clause to get a stack unwind.
     RESCUE (sysX)
       retVal := 2;
       CSt.Message("<< COMPILER PANIC >>");
@@ -194,6 +191,8 @@ MODULE CPascal;
         FixListing;
       END;
       Finalize;
+ *)
+(* ===================================================== *)
     END Compile;
 
 (* ==================================================================== *)

+ 2 - 0
gpcp/CPascalErrors.cp

@@ -47,6 +47,7 @@ MODULE CPascalErrors;
       eTide    : INTEGER;	(* Next index for insertion in buf *)
       prompt*  : BOOLEAN;	(* Emit error message immediately  *)
       nowarn*  : BOOLEAN;	(* Don't store warning messages    *)
+	  no239Err*: BOOLEAN;   (* Don't emit 239 while TRUE       *)
       srcNam   : FileNames.NameString;
       forVisualStudio* : BOOLEAN;
       xmlErrors* : BOOLEAN;
@@ -1001,6 +1002,7 @@ BEGIN
   NEW(eBuffer, 8); eBuffer[0] := NIL; eLimit := 7; eTide := 0;
   prompt := FALSE;
   nowarn := FALSE;
+  no239Err := FALSE;
   forVisualStudio := FALSE;
 END CPascalErrors.
 (* ============================================================ *)

+ 12 - 13
gpcp/CPascalP.cp

@@ -27,7 +27,6 @@ MODULE CPascalP;
         Bi := Builtin,
         StatDesc,
         Visitor,
-        OldSymFileRW,
         NewSymFileRW,
         NameHash;
 
@@ -307,6 +306,7 @@ VAR
     IF (nextT.sym = T.colonequalSym) THEN
       alias := Id.newAlias();
       alias.hash  := NameHash.enterSubStr(token.pos, token.len);
+      IF Cs.verbose THEN alias.SetNameFromHash(alias.hash) END;
       IF Sy.refused(alias, modScope) THEN SemError(4) END;
       Get; (* Read past colonequals symbol *)
      (*
@@ -326,10 +326,9 @@ VAR
       ELSE
         Expect(T.identSym);
         alias.token := token;  (* fake the name for err-msg use *)
-		ident.aliasMod := alias;
-		IF Cs.verbose THEN alias.SetNameFromHash(alias.hash) END;
         idHsh := NameHash.enterSubStr(token.pos, token.len);
       END;
+      ident.aliasMod := alias;
     ELSE
       idHsh := NameHash.enterSubStr(token.pos, token.len);
     END;
@@ -337,7 +336,8 @@ VAR
     ident.dfScp := ident;
     ident.hash  := idHsh;
 
-	IF Cs.verbose THEN ident.SetNameFromHash(idHsh) END;
+(* FIXME *)
+    IF Cs.verbose THEN ident.SetNameFromHash(idHsh) ELSE ident.ClearName() END;
 
     IF ident.hash = Bi.sysBkt THEN
       dummy := Cs.thisMod.symTb.enter(Bi.sysBkt, Cs.sysMod);
@@ -360,7 +360,7 @@ VAR
       *  there are already references to it in the structure.
       *)
       clash.token := ident.token;   (* to help error reports  *)
-	  IF Cs.verbose THEN clash.SetNameFromHash(clash.hash) END;
+      IF Cs.verbose THEN clash.SetNameFromHash(clash.hash) END;
       ident := clash(Id.BlkId);
 	 (*
 	  *  If this is the explicit import of a module that
@@ -406,7 +406,9 @@ VAR
       *  List the file, for importation later  ...
       *)
       Sy.AppendScope(impSeq, ident);
-      IF alias # NIL THEN INCL(ident.xAttr, Sy.anon) END;	        
+      IF alias # NIL THEN 
+	    INCL(ident.xAttr, Sy.anon);
+	  END;	        
       EXCL(ident.xAttr, Sy.weak); (* ==> directly imported *)
       INCL(ident.xAttr, Sy.need); (* ==> needed in symfile *)
 	END;
@@ -463,11 +465,7 @@ VAR
     END;
     
     Cs.import1 := RTS.GetMillis();
-IF Cs.legacy THEN
-    OldSymFileRW.WalkImports(Cs.impSeq, modScope);
-ELSE
     NewSymFileRW.WalkImports(Cs.impSeq, modScope);
-END;
     Cs.import2 := RTS.GetMillis();
   END ImportList;
 
@@ -2604,6 +2602,7 @@ END;
         fDsc := list.a[fIdx](Id.FldId);
         fDsc.type := fTyp;
         fDsc.recTyp := recT;
+        fDsc.fldNm := Sy.getName.ChPtr(fDsc); (* retro fitted *)
         Sy.AppendIdnt(recT.fields, fDsc);
       END;
     END;
@@ -3250,7 +3249,7 @@ END;
       RETURN idnt;
     ELSE
       modS := idnt(Id.BlkId);
-	  IF Sy.anon IN modS.xAttr THEN 
+	  IF (Sy.anon IN modS.xAttr) & ~Cs.Suppress239() THEN 
 	    SemErrorS1(239, Sy.getName.ChPtr(modS.aliasMod));
 	  END;
     END;
@@ -3309,7 +3308,7 @@ END;
       RETURN idnt(Id.TypId);
     ELSIF (idnt.kind = Id.impId) OR (idnt.kind = Id.alias) THEN
       modS := idnt(Id.BlkId);
-	  IF Sy.anon IN modS.xAttr THEN 
+	  IF (Sy.anon IN modS.xAttr) & ~Cs.Suppress239() THEN 
 	    SemErrorS1(239, Sy.getName.ChPtr(modS.aliasMod));
 	  END;
     ELSE
@@ -3367,7 +3366,7 @@ END;
     IF iSyn IS Sy.Scope THEN iSyn(Sy.Scope).ovfChk := Cs.ovfCheck END;
     iSyn.token := nextT;
     iSyn.hash  := NameHash.enterSubStr(nextT.pos, nextT.len);
-    IF Cs.verbose THEN iSyn.SetNameFromHash(iSyn.hash) END;
+    IF Cs.verbose OR Cs.doAsm5 THEN iSyn.SetNameFromHash(iSyn.hash) END;
     iSyn.dfScp := inhScp;
     IF nextT.dlr & ~Cs.special THEN SemErrorT(186, nextT) END;
     Expect(T.identSym);

+ 2 - 2
gpcp/CPascalS.cp

@@ -100,12 +100,12 @@ VAR
 (* ======================== EXPORTS ========================= *)
 PROCEDURE (s : ErrorHandler)Report*(num : INTEGER; 
 				    lin : INTEGER;
-			            col : INTEGER) ,NEW,ABSTRACT;
+                    col : INTEGER) ,NEW,ABSTRACT;
 
 PROCEDURE (s : ErrorHandler)RepSt1*(num : INTEGER; 
 				 IN str : ARRAY OF CHAR;
 				    lin : INTEGER;
-			            col : INTEGER) ,NEW,ABSTRACT;
+                    col : INTEGER) ,NEW,ABSTRACT;
 
 PROCEDURE (s : ErrorHandler)RepSt2*(num : INTEGER; 
 				 IN st1 : ARRAY OF CHAR;

+ 7 - 0
gpcp/ClassMaker.cp

@@ -27,9 +27,16 @@ MODULE ClassMaker;
 
 (* ============================================================ *)
 
+ (* Emitter initialization *)
   PROCEDURE (maker : ClassEmitter)Init*(),NEW,EMPTY;
+
+ (* Define features of the type system base type *)
   PROCEDURE (maker : ClassEmitter)ObjectFeatures*(),NEW,EMPTY;
+
+ (* Emit the code for the Module *)
   PROCEDURE (maker : ClassEmitter)Emit*(),NEW,ABSTRACT;
+
+ (* Call the assembler, if necessary *)
   PROCEDURE (asmbl : Assembler)Assemble*(),NEW,EMPTY;
 
 (* ============================================================ *)

+ 90 - 17
gpcp/ClassUtil.cp

@@ -623,6 +623,10 @@ MODULE ClassUtil;
     fil.exceptAttIx := 0;
     fil.lineNumTabIx := 0;
     fil.jlExceptIx := 0;
+    CSt.emitNam := BOX("ClassUtil");
+    IF CSt.doVersion THEN
+      CSt.Message("Using " + CSt.emitNam^ + " emitter" );
+    END;
     RETURN fil;
   END newClassFile;
 
@@ -683,6 +687,54 @@ MODULE ClassUtil;
 (*                   Java Class File Stuff                      *)
 (* ============================================================ *)
 
+  PROCEDURE (jf : ClassFile)LoadLocal*(ord : INTEGER; typ : D.Type);
+    VAR code : INTEGER;
+  BEGIN
+    IF (typ # NIL) & (typ IS Ty.Base) THEN 
+      code := J.typeLoad[typ(Ty.Base).tpOrd];
+    ELSE
+      code := Jvm.opc_aload; 
+    END;
+    IF ord < 4 THEN
+      CASE code OF
+      | Jvm.opc_iload : code := Jvm.opc_iload_0 + ord;
+      | Jvm.opc_lload : code := Jvm.opc_lload_0 + ord;
+      | Jvm.opc_fload : code := Jvm.opc_fload_0 + ord;
+      | Jvm.opc_dload : code := Jvm.opc_dload_0 + ord;
+      | Jvm.opc_aload : code := Jvm.opc_aload_0 + ord;
+      END;
+      jf.Code(code);
+    ELSE
+      jf.CodeI(code, ord);
+    END;
+  END LoadLocal;
+
+(* ---------------------------------------------------- *)
+
+  PROCEDURE (jf : ClassFile)StoreLocal*(ord : INTEGER; typ : D.Type);
+    VAR code : INTEGER;
+  BEGIN
+    IF (typ # NIL) & (typ IS Ty.Base) THEN 
+      code := J.typeStore[typ(Ty.Base).tpOrd];
+    ELSE
+      code := Jvm.opc_astore;
+    END;
+    IF ord < 4 THEN
+      CASE code OF
+      | Jvm.opc_istore : code := Jvm.opc_istore_0 + ord;
+      | Jvm.opc_lstore : code := Jvm.opc_lstore_0 + ord;
+      | Jvm.opc_fstore : code := Jvm.opc_fstore_0 + ord;
+      | Jvm.opc_dstore : code := Jvm.opc_dstore_0 + ord;
+      | Jvm.opc_astore : code := Jvm.opc_astore_0 + ord;
+      END;
+      jf.Code(code);
+    ELSE
+      jf.CodeI(code, ord);
+    END;
+  END StoreLocal;
+
+(* ---------------------------------------------------- *)
+
   PROCEDURE (cf : ClassFile) InitFields*(numFields : INTEGER);
   BEGIN
     NEW(cf.fields,numFields);
@@ -798,7 +850,7 @@ MODULE ClassUtil;
     m.methId := meth;
     IF meth = NIL THEN
       m.localNum := 0;
-      m.maxLocals := 1;
+      m.maxLocals := 2; (* need 2 for __copy__  'this' + 'arg'*)
     ELSE        (* Id.BlkId *)
       m.localNum := meth.rtsFram;
       m.maxLocals := MAX(meth.rtsFram, 1);
@@ -870,7 +922,7 @@ MODULE ClassUtil;
 
 (* ------------------------------------------------------------ *)
 
-  PROCEDURE (cf : ClassFile)newLocal*() : INTEGER;
+  PROCEDURE (cf : ClassFile)newLocal*( t : D.Type ) : INTEGER;
     VAR ord : INTEGER;
   BEGIN
     ord := cf.meth.localNum;
@@ -883,14 +935,30 @@ MODULE ClassUtil;
 
 (* ------------------------------------------------------------ *)
 
-  PROCEDURE (cf : ClassFile)ReleaseLocal*(i : INTEGER);
+  PROCEDURE (cf : ClassFile)newLongLocal*( t : D.Type ) : INTEGER;
+    VAR ord : INTEGER;
   BEGIN
-   (*
-    *  If you try to release not in LIFO order, the 
-    *  location will not be made free again. This is safe!
-    *)
-    IF i+1 = cf.meth.localNum THEN DEC(cf.meth.localNum) END;
-  END ReleaseLocal;
+    ord := cf.meth.localNum;
+    INC(cf.meth.localNum, 2);
+    IF cf.meth.localNum > cf.meth.maxLocals THEN 
+      cf.meth.maxLocals := cf.meth.localNum;
+    END;
+    RETURN ord;
+  END newLongLocal;
+
+(* ------------------------------------------------------------ *)
+
+  PROCEDURE (cf : ClassFile)PopLocal*();
+  BEGIN
+    DEC(cf.meth.localNum);
+  END PopLocal;
+
+(* ------------------------------------------------------------ *)
+
+  PROCEDURE (cf : ClassFile)PopLongLocal*();
+  BEGIN
+    DEC(cf.meth.localNum, 2);
+  END PopLongLocal;
 
 (* ------------------------------------------------------------ *)
 
@@ -1056,7 +1124,8 @@ MODULE ClassUtil;
     *)
     FOR idx := 0 TO rec.fields.tide-1 DO
       fld := rec.fields.a[idx];
-      IF (fld.type IS Ty.Record) OR (fld.type IS Ty.Array) THEN
+      IF (fld.type IS Ty.Record) OR 
+         ((fld.type IS Ty.Array) & ~(fld.type IS Ty.Vector)) THEN
 	cf.Code(Jvm.opc_aload_0);
 	cf.VarInit(fld);
         cf.PutGetF(Jvm.opc_putfield, rec, fld(Id.FldId));
@@ -1101,7 +1170,7 @@ MODULE ClassUtil;
 
 (* ============================================================ *)
 
-  PROCEDURE GetTypeName*(typ : D.Type) : L.CharOpen;
+  PROCEDURE GetTypeName(typ : D.Type) : L.CharOpen;
   VAR
     arrayName : L.CharOpenSeq;
     arrayTy : D.Type;
@@ -1188,14 +1257,15 @@ MODULE ClassUtil;
  
   PROCEDURE (cf : ClassFile)DefLab*(lab : J.Label);
   BEGIN
-    ASSERT(lab.defIx = 0);
-    lab.defIx := cf.meth.codes.codeLen;
+    IF lab.defIx = 0 THEN lab.defIx := cf.meth.codes.codeLen END;
   END DefLab;
 
   PROCEDURE (cf : ClassFile)DefLabC*(lab : J.Label; IN c : ARRAY OF CHAR);
   BEGIN
-    ASSERT(lab.defIx = 0);
-    lab.defIx := cf.meth.codes.codeLen;
+    IF lab.defIx = 0 THEN lab.defIx := cf.meth.codes.codeLen END;
+(*
+CSt.PrintLn( "DefLabC: " + c );
+ *)
   END DefLabC;
 
 (* -------------------------------------------- *)
@@ -1221,6 +1291,7 @@ MODULE ClassUtil;
     op.op := code;
     op.lab := lab;
     INC(cf.meth.codes.codeLen,3);
+    INCL(lab.attr, J.jumpSeen);
     cf.meth.codes.AddInstruction(op);
     cf.meth.FixStack(code);
   END CodeLb;
@@ -1368,8 +1439,10 @@ MODULE ClassUtil;
   END CodeInc;
 
 (* -------------------------------------------- *)
-
-  PROCEDURE (cf : ClassFile)CodeSwitch*(low,high : INTEGER; defLab : J.Label);
+(*          defLab is the default label         *)
+(* -------------------------------------------- *)
+  PROCEDURE (cf : ClassFile)CodeSwitch*(
+                   low,high : INTEGER; defLab : J.Label);
   VAR
     sw : OpSwitch;
     len : INTEGER;

+ 112 - 61
gpcp/CompState.cp

@@ -20,6 +20,7 @@ MODULE CompState;
         IdDesc,
         Console, 
         CPascalS,
+        LitValue,
         NameHash,
         FileNames,
         ClassMaker,
@@ -44,6 +45,7 @@ MODULE CompState;
     ntvEvt* : Symbols.Type;     (* native MulticastDelegate     *)
     rtsXHR* : Symbols.Type;     (* native XHR type descriptor   *)
     ntvVal* : Symbols.Type;     (* native ValueType type        *)
+    ntvStrArr* : Symbols.Type; 
 
     objId*  : Symbols.Idnt;
     strId*  : Symbols.Idnt;
@@ -69,12 +71,15 @@ MODULE CompState;
     lstNam-   : FileNames.NameString;    (* name of the listing file    *)
 
     target-   : ARRAY 6 OF CHAR;
+    asmVer-   : ARRAY 6 OF CHAR; 
     emitter-  : ClassMaker.ClassEmitter;
+    emitNam*  : POINTER TO ARRAY OF CHAR;
 
     cpSymX-,                             (* User supplied CPSYM name    *)
     binDir-,                             (* PE-file directory .NET only *)
     symDir-   : FileNames.NameString;    (* Symbol file directory       *)
-
+    
+    
     strict-,
     special-,
     warning-,
@@ -89,15 +94,17 @@ MODULE CompState;
     doVersion-,
     doneVersion,
     doSym-,
-    doAsm-,
+    doAsm5-,      (* Default for jvm, as of gpcp v1.4.02  *)
+    doDWC-,       (* Legacy class file emitter in v1.3.19 *)
     doJsmn-,
     forceIlasm,
     forcePerwapi,
     doIlasm-,
+    doAsm-,
     doCode-,
     quiet-,
     system-    : BOOLEAN;
-    legacy*    : BOOLEAN;
+
     netRel-,
     listLevel-,
     hashSize-  : INTEGER;
@@ -125,10 +132,25 @@ MODULE CompState;
   VAR
     expectedNet : BOOLEAN;         (* A .NET specific option was parsed  *)
     expectedJvm : BOOLEAN;         (* A JVM specific option was parsed   *)
-    expectedLlvm : BOOLEAN;        (* An LLVM specific option was parsed *)
+
+  VAR
+    indent : INTEGER;
 
 (* ==================================================================== *)
 (*                             Utilities                                *)
+(* ==================================================================== *)
+
+    PROCEDURE IncIndent*(); BEGIN INC(indent) END IncIndent;
+    PROCEDURE DecIndent*(); BEGIN DEC(indent) END DecIndent;
+    PROCEDURE ZeroIndent*(); BEGIN indent := 0   END ZeroIndent;
+
+    PROCEDURE IndentMsg*( IN s : ARRAY OF CHAR );
+      VAR i : INTEGER;
+    BEGIN
+      FOR i := 0 TO indent DO Console.WriteString( "  " ) END;
+      Console.WriteString( s ); Console.WriteLn;
+    END IndentMsg;
+
 (* ==================================================================== *)
 
     PROCEDURE SetSysLib*(lib : IdDesc.BlkId);
@@ -146,14 +168,21 @@ MODULE CompState;
       emitter.ObjectFeatures();
     END ImportObjectFeatures;
 
+	PROCEDURE Suppress239*() : BOOLEAN; 
+	BEGIN 
+	  RETURN CPascalErrors.no239Err;
+	END Suppress239;
+
     PROCEDURE SetQuiet*(); 
     BEGIN
       CPascalErrors.nowarn := TRUE;
+	  CPascalErrors.no239Err := TRUE;
     END SetQuiet;
     
     PROCEDURE RestoreQuiet*();
     BEGIN
       CPascalErrors.nowarn := ~warning;
+	  CPascalErrors.no239Err := FALSE;
     END RestoreQuiet;
 
     PROCEDURE targetIsNET*() : BOOLEAN;
@@ -166,11 +195,6 @@ MODULE CompState;
       RETURN target = "jvm";
     END targetIsJVM;
 
-    PROCEDURE targetIsLLVM*() : BOOLEAN;
-    BEGIN
-      RETURN target = "llvm";
-    END targetIsLLVM;
-
     PROCEDURE Message*(IN mss : ARRAY OF CHAR);
     BEGIN
       Console.WriteString(prefix);
@@ -220,6 +244,7 @@ MODULE CompState;
       PrintLn("gardens point component pascal: " + GPCPcopyright.verStr);
       Message("Usage from the command line ...");
       IF RTS.defaultTarget = "net" THEN
+
 PrintLn("       $ gpcp [cp-options] file {file}");
 PrintLn("# CP Options ...");
 PrintLn("       /bindir=XXX  ==> Place binary files in directory XXX");
@@ -244,7 +269,7 @@ PrintLn("       /quiet       ==> Compile silently if possible");
 PrintLn("       /strict      ==> Disallow non-standard constructs");
 PrintLn("       /special     ==> Compile dummy symbol file");
 PrintLn("       /symdir=XXX  ==> Place symbol files in directory XXX");
-PrintLn("       /target=XXX  ==> Emit (jvm|net|llvm) assembly");
+PrintLn("       /target=XXX  ==> Emit (jvm|net) assembly");
 PrintLn("       /unsafe      ==> Allow unsafe code generation");
 PrintLn("       /vX.X        ==> (v1.0 | v1.1 | v2.0) CLR target version");
 PrintLn("       /verbose     ==> Emit verbose diagnostics");
@@ -253,24 +278,25 @@ PrintLn("       /vserror     ==> Print error messages in Visual Studio format");
 PrintLn("       /warn-       ==> Don't emit warnings");
 PrintLn("       /nowarn      ==> Don't emit warnings");
 PrintLn("       /whidbey     ==> Target code for Whidbey Beta release");
-PrintLn("       /xmlerror    ==> Print error messages in XML format");
+PrintLn("       /xmlerror    ==> Emit error messages in XML format");
 PrintLn(' Unix-style options: "-option" are recognized also');
-      ELSE
-        IF RTS.defaultTarget = "jvm" THEN
+
+      ELSIF RTS.defaultTarget = "jvm" THEN
+
 PrintLn("       $ cprun gpcp [cp-options] file {file}, OR");
 PrintLn("       $ java [java-options] CP.gpcp.gpcp [cp-options] file {file}");
-        ELSIF RTS.defaultTarget = "llvm" THEN
-          PrintLn("       $ gpcp [cp-options] file {file}");
-        END;
 PrintLn("# CP Options ...");
-PrintLn("       -clsdir=XXX  ==> Set class tree root in directory XXX");
+PrintLn("       -asm7        ==> Default: Generate class files with V1_7 format");
+PrintLn("       -asmN        ==> Classfiles use V1_N format, N = (5 .. 8)");
+PrintLn("       -clsdir:XXX  ==> Set class tree root in directory XXX");
 PrintLn("       -copyright   ==> Display copyright notice");
-PrintLn("       -cpsym=XXX   ==> Use environ. variable XXX instead of CPSYM");
+PrintLn("       -cpsym:XXX   ==> Use environ. variable XXX instead of CPSYM");
 PrintLn("       -dostats     ==> Give a statistical summary");
 PrintLn("       -extras      ==> Enable experimental compiler features");
 PrintLn("       -help        ==> Write out this usage message");
-PrintLn("       -hsize=NNN   ==> Set hashtable size >= NNN (0 .. 65000)");
+PrintLn("       -hsize:NNN   ==> Set hashtable size >= NNN (0 .. 65000)");
 PrintLn("       -jasmin      ==> Ceate asm files and run Jasmin");
+PrintLn("       -legacy      ==> Use the pre-v1.4 jvm class writer");
 PrintLn("       -list        ==> (default) Create *.lst file if errors");
 PrintLn("       -list+       ==> Unconditionally create *.lst file");
 PrintLn("       -list-       ==> Don't create error *.lst file");
@@ -280,17 +306,20 @@ PrintLn("       -nosym       ==> Don't create *.sym (or asm or object) files");
 PrintLn("       -quiet       ==> Compile silently if possible");
 PrintLn("       -special     ==> Compile dummy symbol file");
 PrintLn("       -strict      ==> Disallow non-standard constructs");
-PrintLn("       -symdir=XXX  ==> Place symbol files in directory XXX");
-PrintLn("       -target=XXX  ==> Emit (jvm|net|llvm) assembly");
+PrintLn("       -symdir:XXX  ==> Place symbol files in directory XXX");
+PrintLn("       -target:XXX  ==> Emit (jvm|net) assembly");
 PrintLn("       -verbose     ==> Emit verbose diagnostics");
 PrintLn("       -version     ==> Write out version number");
 PrintLn("       -warn-       ==> Don't emit warnings");
 PrintLn("       -nowarn      ==> Don't emit warnings");
-PrintLn("       -xmlerror    ==> Print error messages in XML format");
+PrintLn("       -xmlerror    ==> Emit error messages in XML format");
+
         IF RTS.defaultTarget = "jvm" THEN
+
 PrintLn("# Java Options ...");
 PrintLn("       -D<name>=<value>  pass <value> to JRE as system property <name>");
 PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JRE");
+
         END;
       END;
       Message("This program comes with NO WARRANTY");
@@ -304,7 +333,7 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
     PROCEDURE ParseOption*(IN opt : ARRAY OF CHAR);
 	  CONST MaxTargetLength = 4;
       VAR copy : ARRAY 16 OF CHAR;
-	      trgt : ARRAY MaxTargetLength + 1 OF CHAR;
+          trgt : ARRAY MaxTargetLength + 1 OF CHAR;
           indx : INTEGER;
      (* ----------------------------------------- *)
       PROCEDURE Unknown(IN str : ARRAY OF CHAR);
@@ -350,22 +379,23 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
         END;
       END GetSuffix;
      (* ----------------------------------------- *)
-	  PROCEDURE RaiseSuffix(preLen : INTEGER;
-	                        outLen : INTEGER;
-	                        IN opt : ARRAY OF CHAR;
-							OUT dir : ARRAY OF CHAR);
+      PROCEDURE RaiseSuffix(preLen : INTEGER;
+                            outLen : INTEGER;
+                            IN opt : ARRAY OF CHAR;
+                           OUT dir : ARRAY OF CHAR);
         VAR idx : INTEGER;
             chr : CHAR;
       BEGIN
         idx := 0;
-		REPEAT
+        REPEAT
           chr := opt[idx + preLen];
-		  dir[idx] := CAP(chr);
-		  INC(idx);
-		UNTIL (chr = 0X) OR (idx >= outLen) OR ((idx + preLen) > LEN(opt));
-		dir[idx] := 0X;
+          dir[idx] := CAP(chr);
+          INC(idx);
+        UNTIL (chr = 0X) OR (idx >= outLen) OR ((idx + preLen) > LEN(opt));
+        dir[idx] := 0X;
       END RaiseSuffix;
-
+     (* ----------------------------------------- *)
+     (*  Note: str is mutable, pat is immutable   *)
      (* ----------------------------------------- *)
       PROCEDURE StartsWith(str : ARRAY OF CHAR; IN pat : ARRAY OF CHAR) : BOOLEAN;
       BEGIN
@@ -381,8 +411,23 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
       copy[15] := 0X;
 
       CASE copy[0] OF
+      | "a" : 
+          IF StartsWith(copy, "asm") THEN
+            GetSuffix(LEN("-asm"), opt, asmVer);
+            IF (LEN(asmVer$) # 1) OR
+               ( asmVer[0] < '5') OR (asmVer[0] > '8') THEN 
+              Unknown(opt);
+            ELSE
+              doCode     := TRUE;
+              doAsm5     := TRUE;
+              expectedJvm := TRUE;
+            END;
+          ELSE 
+            Unknown(opt);
+          END;
       | "b" : 
-          IF StartsWith(copy, "bindir=") THEN
+          IF StartsWith(copy, "bindir=") OR 
+             StartsWith(copy, "bindir:") THEN
             GetSuffix(LEN("/bindir="), opt, binDir);
             expectedNet := TRUE;
             IF ~quiet THEN 
@@ -394,17 +439,21 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
       | "c" : 
           IF copy = "copyright" THEN 
             GPCPcopyright.Write;
-          ELSIF StartsWith(copy, "clsdir=") THEN
+          ELSIF StartsWith(copy, "clsdir=") OR
+                StartsWith(copy, "clsdir:") THEN
             GetSuffix(LEN("/clsdir="), opt, binDir);
             expectedJvm := TRUE;
             IF ~quiet THEN 
               Message("output class tree rooted at <" + binDir +">");
             END;
-          ELSIF StartsWith(copy, "cpsym=") THEN
+          ELSIF StartsWith(copy, "cpsym=") OR
+                StartsWith(copy, "cpsym:") THEN
             GetSuffix(LEN("/cpsym="), opt, cpSymX);
+          (*
             IF ~quiet THEN 
               Message("using %" + cpSymX +"% as symbol file path");
             END;
+           *)
           ELSE
             Unknown(opt);
           END;
@@ -450,7 +499,10 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
           ELSIF copy = "list" THEN
             listLevel  := CPascalS.listErrOnly;
           ELSIF copy = "legacy" THEN
-            legacy := TRUE;
+            doDWC      := TRUE;
+            doCode     := TRUE;
+            doAsm5     := FALSE;
+            expectedJvm := TRUE;
           ELSE 
             Unknown(opt);
           END;
@@ -497,7 +549,8 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
             strict     := FALSE;
           ELSIF copy = "strict" THEN
             strict     := TRUE;
-          ELSIF StartsWith(copy, "symdir=") THEN
+          ELSIF StartsWith(copy, "symdir=") OR
+                StartsWith(copy, "symdir:") THEN
             GetSuffix(LEN("/symdir="), opt, symDir);
             IF ~quiet THEN 
               Message("sym directory set to <" + symDir +">");
@@ -506,7 +559,8 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
             Unknown(opt);
           END;
       | "t" :
-          IF StartsWith(copy, "target=") THEN
+          IF StartsWith(copy, "target=") OR
+             StartsWith(copy, "target:") THEN
             RaiseSuffix(LEN("/target="), MaxTargetLength, opt, trgt);
             IF trgt = "JVM" THEN
               IF RTS.defaultTarget = "jvm" THEN
@@ -518,8 +572,6 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
                 Message("NET is default target for this build");
               END;
               target := "net";
-            ELSIF trgt = "LLVM" THEN
-              target := "llvm";
             ELSE
               Message('Unknown target, using "target=' +
                                                     RTS.defaultTarget + '"');
@@ -593,28 +645,22 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
           ("WARNING - a JVM-specific option was specified for .NET target");
           expectedJvm := FALSE;
         END;
-        IF expectedLlvm THEN Message
-          ("WARNING - an LLVM-specific option was specified for .NET target");
-          expectedLlvm := FALSE;
-        END;
       ELSIF target = "jvm" THEN
         IF expectedNet THEN Message
           ("WARNING - a .NET-specific option was specified for JVM target");
           expectedNet := FALSE;
         END;
-        IF expectedLlvm THEN Message
-          ("WARNING - an LLVM-specific option was specified for JVM target");
-          expectedLlvm := FALSE;
-        END;
-      ELSIF target = "llvm" THEN
-        IF expectedJvm THEN Message
-          ("WARNING - a JVM-specific option was specified for LLVM target");
-          expectedJvm := FALSE;
-        END;
-        IF expectedNet THEN Message
-          ("WARNING - a .NET-specific option was specified for LLVM target");
-          expectedNet := FALSE;
-        END;
+      END;
+     (*
+      *  If gpcp is running on the CLR, then (currently) 
+      *  the asm5 emitter is not supported.
+      *)
+      IF (RTS.defaultTarget = "net") & doAsm5  THEN
+        Message
+          ("WARNING - gpcp-CLR does not support ASM5, using -legacy emitter"); 
+        doDWC      := TRUE;
+        doCode     := TRUE;
+        doAsm5     := FALSE;
       END;
      (* 
       *  If debug is set, for this version, ILASM is used unless /perwapi is explicit
@@ -644,8 +690,12 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
       FileNames.AppendExt(basNam, "lst", lstNam);
 
       CreateThisMod;
+
       xhrId := IdDesc.newFldId();
       xhrId.hash := NameHash.enterStr("prev");
+      xhrId.fldNm := BOX( "prev" );
+      emitNam    := BOX("????");
+
       srcBkt     := NameHash.enterStr("src");
       corBkt     := NameHash.enterStr("mscorlib_System");
 
@@ -659,7 +709,8 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
     VAR str1 : ARRAY 8 OF CHAR;
         str2 : ARRAY 8 OF CHAR;
   BEGIN
-    Message(target + GPCPcopyright.verStr); 
+    Message("GPCP-" + target + GPCPcopyright.verStr); 
+    Message("Using " + emitNam^ + " emitter" );
     GPText.IntToStr(CPascalS.line, str1);
     Message(str1 + " source lines");
     GPText.IntToStr(impMax, str1);
@@ -681,7 +732,6 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
 
   PROCEDURE InitOptions*;
   BEGIN
-    legacy      := FALSE;
     warning     := TRUE;
     verbose     := FALSE;
     doHelp      := FALSE; doneHelp    := FALSE;
@@ -699,6 +749,8 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
     forcePerwapi := FALSE;
     doCode      := TRUE;
     doAsm       := TRUE;
+    doAsm5      := (RTS.defaultTarget = "jvm");
+    doDWC       := FALSE;
     special     := FALSE;
     strict      := FALSE;
     quiet       := FALSE;
@@ -707,7 +759,6 @@ PrintLn("       -DCPSYM=$CPSYM    pass value of CPSYM environment variable to JR
     hashSize    := 5000;        (* gets default hash size *)
     expectedNet := FALSE;
     expectedJvm := FALSE;
-    expectedLlvm := FALSE;
     cpSymX      := "CPSYM";
   END InitOptions;
 

+ 1 - 1
gpcp/ExprDesc.cp

@@ -2187,7 +2187,7 @@ MODULE ExprDesc;
                                    lIn : V.VarSet) : V.VarSet;
   (* Assert: expression has been fully attributed.   *)
   BEGIN
-      (* Really: recurse over set elements *)
+   (* Really: recurse over set elements *)
     RETURN lIn;
   END checkLive;
 

+ 5 - 1
gpcp/GPCPcopyright.cp

@@ -49,7 +49,11 @@ MODULE GPCPcopyright;
      (* VERSION    = "1.3.15 of 04 October 2012"; *)
      (* VERSION    = "1.3.16 of 01 January 2013"; *)
      (* VERSION    = "1.3.17 of 01 June 2013"; *)
-        VERSION    = "1.3.18 of 26 August 2013"; 
+     (* VERSION    = "1.3.18 of 26 August 2013"; *)
+     (* VERSION    = "1.4.00 of 17 August 2016"; *)
+     (* VERSION    = "1.4.01 of 21 October 2016"; *)
+     (* VERSION    = "1.4.02 of 14 November 2016"; *)
+        VERSION    = "1.4.03 of 13 June 2017"; 
 	verStr*    = " version " + VERSION;
 
   CONST	prefix     = "#gpcp: ";

+ 35 - 32
gpcp/GPCPcopyright.rtf

@@ -1,5 +1,5 @@
 {\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang3081\deflangfe3081\themelang3081\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;}
-{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
 {\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}
 {\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
 {\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
@@ -7,31 +7,34 @@
 {\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
 {\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f49\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f50\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;}
 {\f52\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f53\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f54\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f55\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);}
-{\f56\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f57\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
-{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
-{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
-{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
-{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
-{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}
-{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}
-{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
-{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
-{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
-{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
-{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
-{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
-{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
-{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
-{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}
-{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
-{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
-{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
-{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
-{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;
-\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \fs22 }{\*\defpap 
-\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 
-\ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\s1\ql \li0\ri0\sb240\sa60\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 
-\ab\af1\afs32\alang1025 \ltrch\fcs0 \b\f1\fs32\lang1033\langfe1033\kerning32\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink15 \sqformat heading 1;}{\*\cs10 \additive \ssemihidden Default Paragraph Font;}{\*
+{\f56\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f57\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}
+{\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f387\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}
+{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
+{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
+{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}
+{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}
+{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
+{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
+{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
+{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
+{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}
+{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}
+{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}
+{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
+{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
+{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;
+\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;
+\red192\green192\blue192;}{\*\defchp \fs22 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{
+\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{
+\s1\ql \li0\ri0\sb240\sa60\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af1\afs32\alang1025 \ltrch\fcs0 \b\f1\fs32\lang1033\langfe1033\kerning32\cgrid\langnp1033\langfenp1033 
+\sbasedon0 \snext0 \slink15 \sqformat heading 1;}{\*\cs10 \additive \ssemihidden Default Paragraph Font;}{\*
 \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1
 \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang3081\langfe3081\cgrid\langnp3081\langfenp3081 \snext11 \ssemihidden \sunhideused \sqformat Normal Table;}{\*\cs15 \additive 
 \rtlch\fcs1 \ab\af31503\afs32 \ltrch\fcs0 \b\fs32\lang1033\langfe1033\kerning32\loch\f31502\hich\af31502\dbch\af31501\langnp1033\langfenp1033 \sbasedon10 \slink1 \slocked \spriority9 Heading 1 Char;}}{\*\listtable{\list\listtemplateid-1508889896
@@ -45,9 +48,9 @@
 \rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li5040\jclisttab\tx5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67698713\'02\'07.;}{\levelnumbers
 \'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li5760\jclisttab\tx5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67698715
 \'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li6480\jclisttab\tx6480\lin6480 }{\listname ;}\listid1123961876}}{\*\listoverridetable{\listoverride\listid1123961876\listoverridecount0\ls1}}{\*\rsidtbl \rsid30932
-\rsid608180\rsid941286\rsid9770042}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\title Gardens Point Component Pascal Copyright}{\author gough}{\operator john}
-{\creatim\yr2001\mo12\dy17\hr21\min36}{\revtim\yr2012\mo7\dy31\hr11\min40}{\version5}{\edmins17}{\nofpages1}{\nofwords234}{\nofchars1303}{\*\company Faculty of Information Technology}{\nofcharsws1534}{\vern32773}}{\*\xmlnstbl {\xmlns1 http://schemas.micro
-soft.com/office/word/2003/wordml}{\xmlns2 urn:schemas-microsoft-com:office:smarttags}}\paperw12240\paperh15840\margl1800\margr1800\margt1440\margb1440\gutter0\ltrsect 
+\rsid608180\rsid941286\rsid8743837\rsid9770042}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\title Gardens Point Component Pascal Copyright}{\author gough}
+{\operator john}{\creatim\yr2001\mo12\dy17\hr21\min36}{\revtim\yr2017\mo6\dy12\hr11\min15}{\version6}{\edmins19}{\nofpages1}{\nofwords234}{\nofchars1303}{\*\company Faculty of Information Technology}{\nofcharsws1534}{\vern32775}}{\*\xmlnstbl {\xmlns1 http
+://schemas.microsoft.com/office/word/2003/wordml}{\xmlns2 urn:schemas-microsoft-com:office:smarttags}}\paperw12240\paperh15840\margl1800\margr1800\margt1440\margb1440\gutter0\ltrsect 
 \widowctrl\ftnbj\aenddoc\trackmoves1\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\noxlattoyen
 \expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1800\dgvorigin1440\dghshow1\dgvshow1
 \jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\rsidroot9770042 \fet0{\*\wgrffmtfilter 013f}\ilfomacatclnup0{\*\template 
@@ -58,7 +61,7 @@ C:\\Documents and Settings\\gough\\Application Data\\Microsoft\\Templates\\Norma
 \b\f1\fs32\lang1033\langfe1033\kerning32\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid9770042 Gardens Point Component Pascal Copyright
 \par }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid9770042 
 
-\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid941286 Copyright \'a9 1998 \endash  2012}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid9770042  Queensland University of Technology (QUT). All rights reserved.
+\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid8743837 Copyright \'a9 1998 \endash  2017}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid9770042  Queensland University of Technology (QUT). All rights reserved.
 \par 
 \par Redistribution and use in source and binary forms, with or without modification are permitted provided that the following conditions are met:
 \par 
@@ -180,8 +183,8 @@ fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f0000000000000000000000000061
-bc69bd6ecd01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f000000000000000000000000605c
+805119e3d201feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
 0000000000000000000000000000000000000000000000000105000000000000}}

+ 1 - 1
gpcp/Hello.cp

@@ -1,7 +1,7 @@
 MODULE Hello;
   IMPORT CPmain, Console;
 
-  CONST greet = "Hello Beta2 world";
+  CONST greet = "Hello AsmEmitter world";
 
 BEGIN
   Console.WriteString(greet); 

+ 1 - 0
gpcp/JVMcodes.cp

@@ -730,5 +730,6 @@ BEGIN
 	dl[opc_goto_w]		:= 0;
 	dl[opc_jsr_w]		:= 1;
 	dl[opc_breakpoint] 	:= 0;
+
 END JVMcodes.
 (* ============================================================ *)

Datei-Diff unterdrückt, da er zu groß ist
+ 309 - 262
gpcp/JavaMaker.cp


+ 37 - 0
gpcp/JavaTarget.cp

@@ -0,0 +1,37 @@
+(* ============================================================ *)
+(*  Target is the module which selects the target ClassMaker.	*)
+(*  Copyright (c) John Gough 1999, 2017.			*)
+(* ============================================================ *)
+
+MODULE JavaTarget; (* JavaTargetForJVM.cp *)
+
+  IMPORT 
+        RTS,
+	GPCPcopyright,
+	CompState,
+        AsmUtil,
+        JavaUtil,
+        ClassUtil;
+
+(* ============================================================ *)
+
+  PROCEDURE NewJavaEmitter*(IN fileName : ARRAY OF CHAR) : JavaUtil.JavaFile;
+  BEGIN
+    IF CompState.doAsm5 THEN 
+      IF CompState.verbose THEN CompState.Message("Using ASM emitter") END;
+      RETURN AsmUtil.newAsmEmitter(fileName);
+    ELSIF CompState.doDWC THEN 
+      IF CompState.verbose THEN CompState.Message("Using DWC emitter") END;
+      RETURN ClassUtil.newClassFile(fileName);
+    ELSE 
+      THROW( "no jvm emitter chosen" );
+    END; 
+  END NewJavaEmitter;
+
+(* ============================================================ *)
+BEGIN
+  IF RTS.defaultTarget # "jvm" THEN
+    CompState.Abort("Wrong JavaTarget implementation: Use JavaTargetForCLR.cp");
+  END;
+END JavaTarget.
+(* ============================================================ *)

+ 32 - 0
gpcp/JavaTargetForCLR.cp

@@ -0,0 +1,32 @@
+(* ============================================================ *)
+(*  Target is the module which selects the target ClassMaker.	*)
+(*  Copyright (c) John Gough 1999, 2017.			*)
+(* ============================================================ *)
+
+MODULE JavaTarget; (* JavaTargetForCLR.cp *)
+
+  IMPORT 
+        RTS,
+	GPCPcopyright,
+	CompState,
+        JavaUtil,
+        ClassUtil;
+
+(* ============================================================ *)
+
+  PROCEDURE NewJavaEmitter*(IN fileName : ARRAY OF CHAR) : JavaUtil.JavaFile;
+  BEGIN
+    IF CompState.doDWC THEN 
+      RETURN ClassUtil.newClassFile(fileName);
+    ELSE 
+      THROW( "no jvm emitter chosen" );
+    END; 
+  END NewJavaEmitter;
+
+(* ============================================================ *)
+BEGIN
+  IF RTS.defaultTarget = "jvm" THEN
+    CompState.Abort("Wrong JavaTarget implementation: Use JavaTargetForJVM.cp");
+  END;
+END JavaTarget.
+(* ============================================================ *)

+ 35 - 0
gpcp/JavaTargetForJVM.cp

@@ -0,0 +1,35 @@
+(* ============================================================ *)
+(*  Target is the module which selects the target ClassMaker.	*)
+(*  Copyright (c) John Gough 1999, 2017.			*)
+(* ============================================================ *)
+
+MODULE JavaTarget; (* JavaTargetForJVM.cp *)
+
+  IMPORT 
+        RTS,
+	GPCPcopyright,
+	CompState,
+        AsmUtil,
+        JavaUtil,
+        ClassUtil;
+
+(* ============================================================ *)
+
+  PROCEDURE NewJavaEmitter*(IN fileName : ARRAY OF CHAR) : JavaUtil.JavaFile;
+  BEGIN
+    IF CompState.doAsm5 THEN 
+      RETURN AsmUtil.newAsmEmitter(fileName);
+    ELSIF CompState.doDWC THEN 
+      RETURN ClassUtil.newClassFile(fileName);
+    ELSE 
+      THROW( "no jvm emitter chosen" );
+    END; 
+  END NewJavaEmitter;
+
+(* ============================================================ *)
+BEGIN
+  IF RTS.defaultTarget # "jvm" THEN
+    CompState.Abort("Wrong JavaTarget implementation: Use JavaTargetForCLR.cp");
+  END;
+END JavaTarget.
+(* ============================================================ *)

Datei-Diff unterdrückt, da er zu groß ist
+ 360 - 184
gpcp/JavaUtil.cp


+ 110 - 48
gpcp/JsmnUtil.cp

@@ -14,9 +14,9 @@ MODULE JsmnUtil;
         FileNames,
 	GPTextFiles,
 	CompState,
-        J := JavaUtil,
-	D := Symbols,
-	G := Builtin,
+        J  := JavaUtil,
+	Sy := Symbols,
+	G  := Builtin,
 	Id := IdDesc,
 	Ty := TypeDesc,
 	Jvm := JVMcodes;
@@ -36,14 +36,8 @@ MODULE JsmnUtil;
 	objectInit* = "java/lang/Object/<init>()V";
 	mainStr*    = "main([Ljava/lang/String;)V";
 	jlExcept*   = "java/lang/Exception";
-(*
- *	jlError*    = "java/lang/Error";
- *)
 	jlError*    = jlExcept;
 	mkExcept*   = "java/lang/Exception/<init>(Ljava/lang/String;)V";
-(*
- *	mkError*    = "java/lang/Error/<init>(Ljava/lang/String;)V";
- *)
 	mkError*    = mkExcept;
 	putArgStr*  = "CP/CPmain/CPmain/PutArgs([Ljava/lang/String;)V";
 
@@ -51,7 +45,7 @@ MODULE JsmnUtil;
 (* ============================================================ *)
 
   TYPE ProcInfo*  = POINTER TO RECORD
-		      prId- : D.Scope;  (* mth., prc. or mod.	*)
+		      prId- : Sy.Scope;  (* mth., prc. or mod.	*)
 		      lMax  : INTEGER;	(* max locals for proc  *)
 		      lNum  : INTEGER;	(* current locals proc  *)
 		      dMax  : INTEGER;	(* max depth for proc.  *)
@@ -90,6 +84,7 @@ MODULE JsmnUtil;
     NEW(f);
     f.file := GPTextFiles.createFile(fileName);
     IF f.file = NIL THEN RETURN NIL; END;
+    CompState.emitNam := BOX("Jasmin");
     RETURN f;
   END newJsmnFile;
 
@@ -113,7 +108,7 @@ MODULE JsmnUtil;
 (*			ProcInfo Methods			*)
 (* ============================================================ *)
 
-  PROCEDURE newProcInfo*(proc : D.Scope) : ProcInfo;
+  PROCEDURE newProcInfo*(proc : Sy.Scope) : ProcInfo;
     VAR p : ProcInfo;
   BEGIN
     NEW(p);
@@ -140,7 +135,7 @@ MODULE JsmnUtil;
     procName : FileNames.NameString;
   BEGIN
     os.proc := newProcInfo(proc);
-    os.Comment("PROCEDURE " + D.getName.ChPtr(proc)^);
+    os.Comment("PROCEDURE " + Sy.getName.ChPtr(proc)^);
    (*
     *  Compute the method attributes
     *)
@@ -160,10 +155,10 @@ MODULE JsmnUtil;
  *  since the JVM places the "override method" in a different 
  *  slot! We must thus live with the insecurity of public mode.
  *
- *  IF proc.vMod = D.pubMode THEN	(* explicitly public *)
+ *  IF proc.vMod = Sy.pubMode THEN	(* explicitly public *)
  *)
-    IF (proc.vMod = D.pubMode) OR	(* explicitly public *)
-       (proc.vMod = D.rdoMode) THEN     (* "implement only"  *)
+    IF (proc.vMod = Sy.pubMode) OR	(* explicitly public *)
+       (proc.vMod = Sy.rdoMode) THEN     (* "implement only"  *)
       attr := attr + Jvm.att_public;
     ELSIF proc.dfScp IS Id.PrcId THEN	(* nested procedure  *)
       attr := attr + Jvm.att_private;
@@ -179,6 +174,8 @@ MODULE JsmnUtil;
   PROCEDURE^ (os : JsmnFile)Stack(),NEW;
   PROCEDURE^ (os : JsmnFile)Blank(),NEW;
 
+(* ------------------------------------------------------------ *)
+
   PROCEDURE (os : JsmnFile)EndProc*();
   BEGIN
     IF (os.proc.attr * Jvm.att_abstract # {}) THEN
@@ -198,14 +195,14 @@ MODULE JsmnUtil;
 
 (* ------------------------------------------------------------ *)
 
-  PROCEDURE (os : JsmnFile)getScope*() : D.Scope;
+  PROCEDURE (os : JsmnFile)getScope*() : Sy.Scope;
   BEGIN
     RETURN os.proc.prId; 
   END getScope;
 
 (* ------------------------------------------------------------ *)
 
-  PROCEDURE (os : JsmnFile)newLocal*() : INTEGER;
+  PROCEDURE (os : JsmnFile)newLocal*( t : Sy.Type ) : INTEGER;
     VAR ord : INTEGER;
         info : ProcInfo;
   BEGIN
@@ -218,14 +215,78 @@ MODULE JsmnUtil;
 
 (* ------------------------------------------------------------ *)
 
-  PROCEDURE (os : JsmnFile)ReleaseLocal*(i : INTEGER);
+  PROCEDURE (os : JsmnFile)newLongLocal*( t : Sy.Type ) : INTEGER;
+    VAR ord : INTEGER;
+        info : ProcInfo;
   BEGIN
-   (*
-    *  If you try to release not in LIFO order, the 
-    *  location will not be made free again. This is safe!
-    *)
-    IF i+1 = os.proc.lNum THEN DEC(os.proc.lNum) END;
-  END ReleaseLocal;
+    info := os.proc; 
+    ord := info.lNum;
+    INC(info.lNum, 2);
+    IF info.lNum > info.lMax THEN info.lMax := info.lNum END;
+    RETURN ord;
+  END newLongLocal;
+
+(* ------------------------------------------------------------ *)
+
+  PROCEDURE (jf : JsmnFile)LoadLocal*(ord : INTEGER; typ : Sy.Type);
+    VAR code : INTEGER;
+  BEGIN
+    IF (typ # NIL) & (typ IS Ty.Base) THEN 
+      code := J.typeLoad[typ(Ty.Base).tpOrd];
+    ELSE
+      code := Jvm.opc_aload; 
+    END;
+    IF ord < 4 THEN
+      CASE code OF
+      | Jvm.opc_iload : code := Jvm.opc_iload_0 + ord;
+      | Jvm.opc_lload : code := Jvm.opc_lload_0 + ord;
+      | Jvm.opc_fload : code := Jvm.opc_fload_0 + ord;
+      | Jvm.opc_dload : code := Jvm.opc_dload_0 + ord;
+      | Jvm.opc_aload : code := Jvm.opc_aload_0 + ord;
+      END;
+      jf.Code(code);
+    ELSE
+      jf.CodeI(code, ord);
+    END;
+  END LoadLocal;
+
+(* ---------------------------------------------------- *)
+
+  PROCEDURE (jf : JsmnFile)StoreLocal*(ord : INTEGER; typ : Sy.Type);
+    VAR code : INTEGER;
+  BEGIN
+    IF (typ # NIL) & (typ IS Ty.Base) THEN 
+      code := J.typeStore[typ(Ty.Base).tpOrd];
+    ELSE
+      code := Jvm.opc_astore;
+    END;
+    IF ord < 4 THEN
+      CASE code OF
+      | Jvm.opc_istore : code := Jvm.opc_istore_0 + ord;
+      | Jvm.opc_lstore : code := Jvm.opc_lstore_0 + ord;
+      | Jvm.opc_fstore : code := Jvm.opc_fstore_0 + ord;
+      | Jvm.opc_dstore : code := Jvm.opc_dstore_0 + ord;
+      | Jvm.opc_astore : code := Jvm.opc_astore_0 + ord;
+      END;
+      jf.Code(code);
+    ELSE
+      jf.CodeI(code, ord);
+    END;
+  END StoreLocal;
+
+(* ------------------------------------------------------------ *)
+
+  PROCEDURE (os : JsmnFile)PopLocal*();
+  BEGIN
+    DEC(os.proc.lNum);
+  END PopLocal;
+
+(* ------------------------------------------------------------ *)
+
+  PROCEDURE (os : JsmnFile)PopLongLocal*();
+  BEGIN
+    DEC(os.proc.lNum, 2);
+  END PopLongLocal;
 
 (* ------------------------------------------------------------ *)
 
@@ -321,11 +382,11 @@ MODULE JsmnUtil;
   BEGIN
     os.Blank();
     IF prc = NIL THEN
-      IF D.noNew IN rec.xAttr THEN 
+      IF Sy.noNew IN rec.xAttr THEN 
         os.Comment("There is no no-arg constructor for this class");
         os.Blank();
         RETURN;					(* PREMATURE RETURN HERE *)
-      ELSIF D.xCtor IN rec.xAttr THEN 
+      ELSIF Sy.xCtor IN rec.xAttr THEN 
         os.Comment("There is an explicit no-arg constructor for this class");
         os.Blank();
         RETURN;					(* PREMATURE RETURN HERE *)
@@ -360,7 +421,7 @@ MODULE JsmnUtil;
   PROCEDURE (os : JsmnFile)CallSuperCtor*(rec : Ty.Record;
                                           pTy : Ty.Procedure);
     VAR	idx : INTEGER;
-	fld : D.Idnt;
+	fld : Sy.Idnt;
 	pNm : INTEGER;
 	string2 : LitValue.CharOpen;
   BEGIN
@@ -535,14 +596,14 @@ MODULE JsmnUtil;
 
 (* ============================================================ *)
 
-  PROCEDURE (os : JsmnFile)Idnt(idD : D.Idnt),NEW;
+  PROCEDURE (os : JsmnFile)Idnt(idD : Sy.Idnt),NEW;
   BEGIN
-    GPText.WriteString(os.file, D.getName.ChPtr(idD));
+    GPText.WriteString(os.file, Sy.getName.ChPtr(idD));
   END Idnt;
 
 (* ============================================================ *)
 
-  PROCEDURE (os : JsmnFile)Type(typ : D.Type),NEW;
+  PROCEDURE (os : JsmnFile)Type(typ : Sy.Type),NEW;
   BEGIN
     WITH typ : Ty.Base DO
 	GPText.WriteString(os.file, typ.xName);
@@ -570,7 +631,7 @@ MODULE JsmnUtil;
 
 (* ============================================================ *)
 
-  PROCEDURE (os : JsmnFile)TypeTag(typ : D.Type),NEW;
+  PROCEDURE (os : JsmnFile)TypeTag(typ : Sy.Type),NEW;
   BEGIN
     WITH typ : Ty.Base DO
 	GPText.WriteString(os.file, typ.xName);
@@ -726,7 +787,7 @@ MODULE JsmnUtil;
 
 (* -------------------------------------------- *)
 
-  PROCEDURE (os : JsmnFile)CodeT*(code : INTEGER; type : D.Type);
+  PROCEDURE (os : JsmnFile)CodeT*(code : INTEGER; type : Sy.Type);
   BEGIN
     os.Prefix(code);
     GPTextFiles.WriteChar(os.file, ASCII.HT);
@@ -800,7 +861,8 @@ MODULE JsmnUtil;
 
 (* -------------------------------------------- *)
 
-  PROCEDURE (os : JsmnFile)CodeSwitch*(loIx,hiIx : INTEGER; dfLb : J.Label);
+  PROCEDURE (os : JsmnFile)CodeSwitch*(
+             loIx,hiIx : INTEGER; defLab : J.Label);
   BEGIN
     os.CodeII(Jvm.opc_tableswitch,loIx,hiIx);
   END CodeSwitch;
@@ -878,7 +940,7 @@ MODULE JsmnUtil;
 
 (* ============================================================ *)
 
-  PROCEDURE (os : JsmnFile)MultiNew*(elT : D.Type;
+  PROCEDURE (os : JsmnFile)MultiNew*(elT : Sy.Type;
 				     dms : INTEGER),NEW;
    (* dsc is the array descriptor, dms the number of dimensions *)
     VAR i : INTEGER;
@@ -948,7 +1010,7 @@ MODULE JsmnUtil;
 
 (* ============================================================ *)
 
-  PROCEDURE (os : JsmnFile)Alloc1d*(elTp : D.Type);
+  PROCEDURE (os : JsmnFile)Alloc1d*(elTp : Sy.Type);
   BEGIN
     WITH elTp : Ty.Base DO
       IF (elTp.tpOrd < Ty.anyRec) THEN
@@ -980,10 +1042,10 @@ MODULE JsmnUtil;
 
 (* ============================================================ *)
 
-  PROCEDURE (os : JsmnFile)MkNewFixedArray*(topE : D.Type; len0 : INTEGER);
+  PROCEDURE (os : JsmnFile)MkNewFixedArray*(topE : Sy.Type; len0 : INTEGER);
     VAR dims : INTEGER;
 	arTp : Ty.Array;
-	elTp : D.Type;
+	elTp : Sy.Type;
   BEGIN
     (*
     //  Fixed-size, possibly multi-dimensional arrays.
@@ -1025,7 +1087,7 @@ MODULE JsmnUtil;
 (* ============================================================ *)
 
   PROCEDURE (os : JsmnFile)MkNewOpenArray*(arrT : Ty.Array; dims : INTEGER);
-    VAR elTp : D.Type;
+    VAR elTp : Sy.Type;
 	indx : INTEGER;
   BEGIN
    (* 
@@ -1072,7 +1134,7 @@ MODULE JsmnUtil;
 
   PROCEDURE (os : JsmnFile)MkArrayCopy*(arrT : Ty.Array);
     VAR dims : INTEGER;
-        elTp : D.Type;
+        elTp : Sy.Type;
   BEGIN
    (*
     *	Assert: we must find the lengths from the runtime 
@@ -1122,8 +1184,8 @@ MODULE JsmnUtil;
 
 (* ============================================================ *)
 
-  PROCEDURE (os : JsmnFile)VarInit*(var : D.Idnt);
-    VAR typ : D.Type;
+  PROCEDURE (os : JsmnFile)VarInit*(var : Sy.Idnt);
+    VAR typ : Sy.Type;
   BEGIN
    (*
     *  Precondition: var is of a type that needs initialization
@@ -1194,7 +1256,7 @@ MODULE JsmnUtil;
 
 (* ============================================================ *)
 
-  PROCEDURE (os : JsmnFile)WithTrap*(id : D.Idnt);
+  PROCEDURE (os : JsmnFile)WithTrap*(id : Sy.Idnt);
   BEGIN
     os.CodeS(Jvm.opc_new, jlError);
     os.Code(Jvm.opc_dup);
@@ -1221,10 +1283,10 @@ MODULE JsmnUtil;
  
   PROCEDURE (os : JsmnFile)StartRecClass*(rec : Ty.Record);
   VAR
-    baseT  : D.Type;
+    baseT  : Sy.Type;
     attSet : SET;
-    clsId  : D.Idnt;
-    impRec : D.Type;
+    clsId  : Sy.Idnt;
+    impRec : Sy.Type;
     index  : INTEGER;
   BEGIN
     os.Blank();
@@ -1250,9 +1312,9 @@ MODULE JsmnUtil;
     *   Account for the identifier visibility.
     *)
     IF clsId # NIL THEN
-      IF clsId.vMod = D.pubMode THEN
+      IF clsId.vMod = Sy.pubMode THEN
 	attSet := attSet + Jvm.att_public;
-      ELSIF clsId.vMod = D.prvMode THEN
+      ELSIF clsId.vMod = Sy.prvMode THEN
 	attSet := attSet + Jvm.att_private;
       END;
     END;
@@ -1303,7 +1365,7 @@ MODULE JsmnUtil;
   BEGIN
     IF id IS Id.FldId THEN att := Jvm.att_empty; 
     ELSE att := Jvm.att_static; END;
-    IF id.vMod # D.prvMode THEN (* any export ==> public in JVM *)
+    IF id.vMod # Sy.prvMode THEN (* any export ==> public in JVM *)
       att := att + Jvm.att_public;
     END;
     os.CatStr(Jvm.dirStr[Jvm.dot_field]);

+ 29 - 1
gpcp/LitValue.cp

@@ -19,14 +19,16 @@ MODULE LitValue;
 
   TYPE
     CharOpen*    = POINTER TO ARRAY OF CHAR;
+    CharOpenArr*  = POINTER TO ARRAY OF CharOpen;
     CharOpenSeq* = RECORD
 		     high  : INTEGER;
 		     tide- : INTEGER;
-		     a-    : POINTER TO ARRAY OF CharOpen;
+		     a-    : CharOpenArr;
 		   END;
 
     CharVector*  = VECTOR OF CHAR;
 
+
 (* ============================================================ *)
 
   TYPE
@@ -337,6 +339,16 @@ MODULE LitValue;
     RETURN strToCharOpen(arr);
   END intToCharOpen;   
 
+(* -------------------------------------------- *)
+
+  PROCEDURE charToCharOpen*(c : CHAR) : CharOpen;
+    VAR arr : CharOpen;
+  BEGIN
+    NEW( arr, 2 );
+    arr[0] := c;
+    RETURN arr;
+  END charToCharOpen;   
+
 (* -------------------------------------------- *)
 
   PROCEDURE ToStr*(in : CharOpen; OUT out : ARRAY OF CHAR);
@@ -531,6 +543,22 @@ MODULE LitValue;
     RETURN 0;
   END strCmp;
 
+(* -------------------------------------------- *)
+ 
+  PROCEDURE SvConcat3*( a,b,c : CharOpen; sp : CHAR ) : CharOpen;
+    VAR nmArray : CharOpenSeq;
+        spacer : CharOpen;
+  BEGIN
+    spacer := charToCharOpen( sp );
+    InitCharOpenSeq(nmArray, 5); 
+    AppendCharOpen(nmArray, a);
+    AppendCharOpen(nmArray, spacer);
+    AppendCharOpen(nmArray, b);
+    AppendCharOpen(nmArray, spacer);
+    AppendCharOpen(nmArray, c);
+    RETURN arrayCat(nmArray);
+  END SvConcat3;
+
 (* -------------------------------------------- *)
 
   PROCEDURE DiagCharOpen*(ptr : CharOpen);

+ 2 - 2
gpcp/MsilAsmForeign.cp

@@ -14,8 +14,8 @@ FOREIGN MODULE MsilAsm;
   PROCEDURE Init*();
 
   PROCEDURE Assemble*(IN file : ARRAY OF CHAR; 
-		     IN optn : ARRAY OF CHAR; (* "/debug" or "" *)
-			    main : BOOLEAN); 	  (* /exe or /dll   *)
+                      IN optn : ARRAY OF CHAR; (* "/debug" or "" *)
+                         main : BOOLEAN); 	  (* /exe or /dll   *)
 
   PROCEDURE DoAsm*(IN file : ARRAY OF CHAR; 
 		   IN optn : ARRAY OF CHAR;	(* "/debug" or "" *)

+ 1 - 0
gpcp/MsilMaker.cp

@@ -144,6 +144,7 @@ MODULE MsilMaker;
     Bi.MkDummyClass("String", blk, Ty.noAtt, str);
     Bi.SetPtrBase(str, obj);
     CSt.ntvStr := str.type;
+    CSt.ntvStrArr := Ty.mkArrayOf(str.type);
     Bi.MkDummyClass("Exception", blk, Ty.extns, exc);
     Bi.SetPtrBase(exc, obj);
     CSt.ntvExc := exc.type;

+ 5 - 4
gpcp/NewSymFileRW.cp

@@ -470,7 +470,7 @@ MODULE NewSymFileRW;
      (*
       *   Emit Optional Parameter name 
       *)
-      IF ~CSt.legacy & (parI.hash # 0) THEN
+      IF (parI.hash # 0) THEN
         f.WriteStringForName(Nh.charOpenOfHash(parI.hash));
       END;
     END;
@@ -575,7 +575,7 @@ MODULE NewSymFileRW;
     f.Write(id.rcvFrm.parMod);
     f.EmitTypeOrd(id.rcvFrm.type);
     IF id.prcNm # NIL THEN f.WriteStringForName(id.prcNm) END; 
-    IF ~CSt.legacy & (id.rcvFrm.hash # 0) THEN f.WriteNameForId(id.rcvFrm) END;
+    IF (id.rcvFrm.hash # 0) THEN f.WriteNameForId(id.rcvFrm) END;
     f.FormalType(id.type(Ty.Procedure));
   END EmitMethodId;
 
@@ -1516,8 +1516,9 @@ MODULE NewSymFileRW;
     WHILE f.sSym = namSy DO
       fldD := Id.newFldId();
       fldD.SetMode(f.iAtt);
-      fldD.hash := Nh.enterStr(f.strAtt);
-      fldD.type := f.typeOf(readOrd(f.file));
+      fldD.hash  := Nh.enterStr(f.strAtt);
+      fldD.fldNm := BOX(f.strAtt^);
+      fldD.type  := f.typeOf(readOrd(f.file));
       fldD.recTyp := rslt;
       f.GetSym();
       IF rslt.symTb.enter(fldD.hash, fldD) THEN 

+ 0 - 2045
gpcp/OldSymFileRW.cp

@@ -1,2045 +0,0 @@
-(* ==================================================================== *)
-(*									*)
-(*  SymFileRW:  Symbol-file reading and writing for GPCP.		*)
-(*	Copyright (c) John Gough 1999, 2000.				*)
-(*									*)
-(* ==================================================================== *)
-
-MODULE OldSymFileRW;
-
-  IMPORT 
-        GPCPcopyright,
-        RTS,
-        Error,
-        Console,
-        GF := GPFiles,
-        BF := GPBinFiles,
-        Id := IdDesc,
-        D  := Symbols,
-        LitValue,
-        Visitor,
-        ExprDesc,
-        Ty := TypeDesc,
-        B  := Builtin,
-        S  := CPascalS,
-        G  := CompState,
-        Nh := NameHash,
-        FileNames;
-
-(* ========================================================================= *
-// Collected syntax ---
-// 
-// SymFile    = Header [String (falSy | truSy | <other attribute>)]
-//              [ VersionName ]
-//		{Import | Constant | Variable | Type | Procedure} 
-//		TypeList Key.
-//	-- optional String is external name.
-//	-- falSy ==> Java class
-//	-- truSy ==> Java interface
-//	-- others ...
-// Header     = magic modSy Name.
-// VersionName= numSy longint numSy longint numSy longint.
-//      --            mj# mn#       bld rv#    8xbyte extract
-// Import     = impSy Name [String] Key.
-//	-- optional string is explicit external name of class
-// Constant   = conSy Name Literal.
-// Variable   = varSy Name TypeOrd.
-// Type       = typSy Name TypeOrd.
-// Procedure  = prcSy Name [String] FormalType.
-//	-- optional string is explicit external name of procedure
-// Method     = mthSy Name byte byte TypeOrd [String] [Name] FormalType.
-//	-- optional string is explicit external name of method
-// FormalType = [retSy TypeOrd] frmSy {parSy byte TypeOrd [String]} endFm.
-//	-- optional phrase is return type for proper procedures
-// TypeOrd    = ordinal.
-// TypeHeader = tDefS Ord [fromS Ord Name].
-//	-- optional phrase occurs if:
-//	-- type not from this module, i.e. indirect export
-// TypeList   = start { Array | Record | Pointer | ProcType | 
-//                Enum | Vector | NamedType } close.
-// Array      = TypeHeader arrSy TypeOrd (Byte | Number | <empty>) endAr.
-//	-- nullable phrase is array length for fixed length arrays
-// Vector     = TypeHeader vecSy TypeOrd endAr.
-// Pointer    = TypeHeader ptrSy TypeOrd.
-// Event      = TypeHeader evtSy FormalType.
-// ProcType   = TypeHeader pTpSy FormalType.
-// Record     = TypeHeader recSy recAtt [truSy | falSy] 
-//		[basSy TypeOrd] [iFcSy {basSy TypeOrd}]
-//		{Name TypeOrd} {Method} {Statics} endRc.
-//	-- truSy ==> is an extension of external interface
-//	-- falSy ==> is an extension of external class
-// 	-- basSy option defines base type, if not ANY / j.l.Object
-// Statics    = ( Constant | Variable | Procedure ).
-// Enum       = TypeHeader eTpSy { Constant } endRc.
-// NamedType  = TypeHeader.
-// Name	      = namSy byte UTFstring.
-// Literal    = Number | String | Set | Char | Real | falSy | truSy.
-// Byte       = bytSy byte.
-// String     = strSy UTFstring.
-// Number     = numSy longint.
-// Real       = fltSy ieee-double.
-// Set        = setSy integer.
-// Key        = keySy integer..
-// Char       = chrSy unicode character.
-//
-// Notes on the syntax:
-// All record types must have a Name field, even though this is often
-// redundant.  The issue is that every record type (including those that
-// are anonymous in CP) corresponds to a IR class, and the definer 
-// and the user of the class _must_ agree on the IR name of the class.
-// The same reasoning applies to procedure types, which must have equal
-// interface names in all modules.
-// ======================================================================== *)
-
-  CONST
-        modSy = ORD('H'); namSy = ORD('$'); bytSy = ORD('\');
-        numSy = ORD('#'); chrSy = ORD('c'); strSy = ORD('s');
-        fltSy = ORD('r'); falSy = ORD('0'); truSy = ORD('1');
-        impSy = ORD('I'); setSy = ORD('S'); keySy = ORD('K');
-        conSy = ORD('C'); typSy = ORD('T'); tDefS = ORD('t');
-        prcSy = ORD('P'); retSy = ORD('R'); mthSy = ORD('M');
-        varSy = ORD('V'); parSy = ORD('p'); start = ORD('&');
-        close = ORD('!'); recSy = ORD('{'); endRc = ORD('}');
-        frmSy = ORD('('); fromS = ORD('@'); endFm = ORD(')');
-        arrSy = ORD('['); endAr = ORD(']'); pTpSy = ORD('%');
-        ptrSy = ORD('^'); basSy = ORD('+'); eTpSy = ORD('e');
-        iFcSy = ORD('~'); evtSy = ORD('v'); vecSy = ORD('*');
-
-  CONST
-        magic   = 0DEADD0D0H;
-        syMag   = 0D0D0DEADH;
-        dumped* = -1;
-
-(* ============================================================ *)
-
-  TYPE
-        SymFile = POINTER TO RECORD 
-        	    file : BF.FILE;
-        	    cSum : INTEGER;
-        	    modS : Id.BlkId;
-        	    iNxt : INTEGER;
-        	    oNxt : INTEGER;
-        	    work : D.TypeSeq;
-        	  END;
-
-  TYPE
-        SymFileReader* = POINTER TO RECORD
-        	    file  : BF.FILE;
-        	    modS  : Id.BlkId;
-        	    impS  : Id.BlkId;
-        	    sSym  : INTEGER;
-        	    cAtt  : CHAR;
-        	    iAtt  : INTEGER;
-        	    lAtt  : LONGINT;
-        	    rAtt  : REAL;
-        	    sAtt  : FileNames.NameString;
-                    oArray : D.IdSeq;
-        	    sArray : D.ScpSeq;		(* These two sequences	*)
-  		    tArray : D.TypeSeq;		(* must be private as   *)
-        	  END;				(* file parses overlap. *)
-
-(* ============================================================ *)
-
-  TYPE	TypeLinker*  = POINTER TO RECORD (D.SymForAll) sym : SymFileReader END;
-  TYPE	SymFileSFA*  = POINTER TO RECORD (D.SymForAll) sym : SymFile END;
-
-(* ============================================================ *)
-
-  VAR   lastKey : INTEGER;	(* private state for CPMake *)
-        fSepArr : ARRAY 2 OF CHAR;
-
-(* ============================================================ *)
-(* ========	     Import Stack Implementation	======= *)
-(* ============================================================ *)
-
-   VAR	stack	: ARRAY 32 OF Id.BlkId;
-        topIx	: INTEGER;
-
-   PROCEDURE InitStack;
-   BEGIN
-     topIx := 0; G.impMax := 0;
-   END InitStack;
-
-   PROCEDURE PushStack(b : Id.BlkId);
-   BEGIN
-     stack[topIx] := b; 
-     INC(topIx);
-     IF topIx > G.impMax THEN G.impMax := topIx END; 
-   END PushStack;
-
-   PROCEDURE PopStack;
-   BEGIN
-     DEC(topIx);
-   END PopStack;
-
-(* ============================================================ *)
-
-  PROCEDURE GetLastKeyVal*() : INTEGER;
-  BEGIN
-    RETURN lastKey;
-  END GetLastKeyVal;
-
-(* ============================================================ *)
-(* ========	Various writing utility procedures	======= *)
-(* ============================================================ *)
-
-  PROCEDURE newSymFile(mod : Id.BlkId) : SymFile;
-    VAR new : SymFile;
-  BEGIN
-    NEW(new);
-   (*
-    *  Initialization: cSum starts at zero. Since impOrd of
-    *  the module is zero, impOrd of the imports starts at 1.
-    *)
-    new.cSum := 0;
-    new.iNxt := 1;
-    new.oNxt := D.tOffset;
-    new.modS := mod;
-    D.InitTypeSeq(new.work, 32);
-    RETURN new;
-  END newSymFile;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)Write(chr : INTEGER),NEW;
-    VAR tmp : INTEGER;
-  BEGIN [UNCHECKED_ARITHMETIC]
-   (* need to turn off overflow checking here *)
-    tmp := f.cSum * 2 + chr;
-    IF f.cSum < 0 THEN INC(tmp) END;
-    f.cSum := tmp;
-    BF.WriteByte(f.file, chr);
-  END Write;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)WriteStrUTF(IN nam : ARRAY OF CHAR),NEW;
-    VAR buf : ARRAY 256 OF INTEGER;
-        num : INTEGER;
-        idx : INTEGER;
-        chr : INTEGER;
-  BEGIN
-    num := 0;
-    idx := 0;
-    chr := ORD(nam[idx]);
-    WHILE chr # 0H DO
-      IF    chr <= 7FH THEN 		(* [0xxxxxxx] *)
-        buf[num] := chr; INC(num);
-      ELSIF chr <= 7FFH THEN 		(* [110xxxxx,10xxxxxx] *)
-        buf[num+1] := 080H + chr MOD 64; chr := chr DIV 64;
-        buf[num  ] := 0C0H + chr; INC(num, 2);
-      ELSE 				(* [1110xxxx,10xxxxxx,10xxxxxxx] *)
-        buf[num+2] := 080H + chr MOD 64; chr := chr DIV 64;
-        buf[num+1] := 080H + chr MOD 64; chr := chr DIV 64;
-        buf[num  ] := 0E0H + chr; INC(num, 3);
-      END;
-      INC(idx); chr := ORD(nam[idx]);
-    END;
-    f.Write(num DIV 256);
-    f.Write(num MOD 256);
-    FOR idx := 0 TO num-1 DO f.Write(buf[idx]) END;
-  END WriteStrUTF;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)WriteOpenUTF(chOp : LitValue.CharOpen),NEW;
-    VAR buf : ARRAY 256 OF INTEGER;
-        num : INTEGER;
-        idx : INTEGER;
-        chr : INTEGER;
-  BEGIN
-    num := 0;
-    idx := 0;
-    chr := ORD(chOp[0]);
-    WHILE chr # 0H DO
-      IF    chr <= 7FH THEN 		(* [0xxxxxxx] *)
-        buf[num] := chr; INC(num);
-      ELSIF chr <= 7FFH THEN 		(* [110xxxxx,10xxxxxx] *)
-        buf[num+1] := 080H + chr MOD 64; chr := chr DIV 64;
-        buf[num  ] := 0C0H + chr; INC(num, 2);
-      ELSE 				(* [1110xxxx,10xxxxxx,10xxxxxxx] *)
-        buf[num+2] := 080H + chr MOD 64; chr := chr DIV 64;
-        buf[num+1] := 080H + chr MOD 64; chr := chr DIV 64;
-        buf[num  ] := 0E0H + chr; INC(num, 3);
-      END;
-      INC(idx);
-      chr := ORD(chOp[idx]);
-    END;
-    f.Write(num DIV 256);
-    f.Write(num MOD 256);
-    FOR idx := 0 TO num-1 DO f.Write(buf[idx]) END;
-  END WriteOpenUTF;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)WriteString(IN nam : ARRAY OF CHAR),NEW;
-  BEGIN
-    f.Write(strSy); 
-    f.WriteStrUTF(nam);
-  END WriteString;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)WriteName(idD : D.Idnt),NEW;
-  BEGIN
-    f.Write(namSy); 
-    f.Write(idD.vMod); 
-    f.WriteOpenUTF(Nh.charOpenOfHash(idD.hash));
-  END WriteName;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)WriteChar(chr : CHAR),NEW;
-    CONST mask = {0 .. 7};
-    VAR   a,b,int : INTEGER;
-  BEGIN
-    f.Write(chrSy);
-    int := ORD(chr);
-    b := ORD(BITS(int) * mask); int := ASH(int, -8);
-    a := ORD(BITS(int) * mask); 
-    f.Write(a); 
-    f.Write(b); 
-  END WriteChar;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)Write4B(int : INTEGER),NEW;
-    CONST mask = {0 .. 7};
-    VAR   a,b,c,d : INTEGER;
-  BEGIN
-    d := ORD(BITS(int) * mask); int := ASH(int, -8);
-    c := ORD(BITS(int) * mask); int := ASH(int, -8);
-    b := ORD(BITS(int) * mask); int := ASH(int, -8);
-    a := ORD(BITS(int) * mask); 
-    f.Write(a); 
-    f.Write(b); 
-    f.Write(c); 
-    f.Write(d); 
-  END Write4B;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)Write8B(val : LONGINT),NEW;
-  BEGIN
-    f.Write4B(RTS.hiInt(val));
-    f.Write4B(RTS.loInt(val));
-  END Write8B;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)WriteNum(val : LONGINT),NEW;
-  BEGIN
-    f.Write(numSy);
-    f.Write8B(val);
-  END WriteNum;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)WriteReal(flt : REAL),NEW;
-    VAR rslt : LONGINT;
-  BEGIN
-    f.Write(fltSy);
-    rslt := RTS.realToLongBits(flt);
-    f.Write8B(rslt);
-  END WriteReal;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)WriteOrd(ord : INTEGER),NEW;
-  BEGIN
-    IF ord <= 7FH THEN 
-      f.Write(ord);
-    ELSIF ord <= 7FFFH THEN
-      f.Write(128 + ord MOD 128);	(* LS7-bits first *)
-      f.Write(ord DIV 128);		(* MS8-bits next  *)
-    ELSE
-      ASSERT(FALSE);
-    END;
-  END WriteOrd;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitTypeOrd(t : D.Type),NEW;
-  (*
-   *  This proceedure facilitates the naming rules
-   *  for records and (runtime) classes: -
-   *
-   *  (1)  Classes derived from named record types have
-   *       names synthesized from the record typename.
-   *  (2)  If a named pointer is bound to an anon record
-   *       the class takes its name from the pointer name.
-   *  (3)  If both the pointer and the record types have
-   *       names, the class is named from the record.
-   *)
-    VAR recT : Ty.Record;
-   (* ------------------------------------ *)
-    PROCEDURE AddToWorklist(syF :SymFile; tyD : D.Type);
-    BEGIN
-      tyD.dump := syF.oNxt; INC(syF.oNxt);
-      D.AppendType(syF.work, tyD);
-      IF tyD.idnt = NIL THEN 
-        tyD.idnt := Id.newSfAnonId(tyD.dump);
-        tyD.idnt.type := tyD;
-      END;
-    END AddToWorklist;
-   (* ------------------------------------ *)
-  BEGIN
-    IF t.dump = 0 THEN (* type is not dumped yet *)
-      WITH t : Ty.Record DO
-       (*
-        *   We wish to ensure that anonymous records are
-        *   never emitted before their binding pointer
-        *   types.  This ensures that we do not need to
-        *   merge types when reading the files.
-        *)
-        IF (t.bindTp # NIL) & 
-           (t.bindTp.dump = 0) THEN 
-          AddToWorklist(f, t.bindTp);		(* First the pointer...  *)
-        END;
-        AddToWorklist(f, t);			(* Then this record type *)
-      | t : Ty.Pointer DO
-       (*
-        *  If a pointer to record is being emitted, and 
-        *  the pointer is NOT anonymous, then the class
-        *  is known by the name of the record.  Thus the
-        *  record name must be emitted, at least opaquely.
-        *  Furthermore, we must indicate the binding
-        *  relationship between the pointer and record.
-        *  (It is possible that DCode need record size.)
-        *)
-        AddToWorklist(f, t);			(* First this pointer... *)
-        IF (t.boundTp # NIL) & 
-           (t.boundTp.dump = 0) &
-           (t.boundTp IS Ty.Record) THEN
-          recT := t.boundTp(Ty.Record);
-          IF recT.bindTp = NIL THEN
-            t.force := D.forced;
-            AddToWorklist(f, t.boundTp);	(* Then the record type  *)
-          END;
-        END;
-      ELSE (* All others *)
-        AddToWorklist(f, t);			(* Just add the type.    *)
-      END;
-    END;
-    f.WriteOrd(t.dump);
-  END EmitTypeOrd;
-
-(* ============================================================ *)
-(* ========	    Various writing procedures		======= *)
-(* ============================================================ *)
-
-  PROCEDURE (f : SymFile)FormalType(t : Ty.Procedure),NEW;
-  (*
-  ** FormalType = [retSy TypeOrd] frmSy {parSy Byte TypeOrd [String]} endFm.
-  *)
-    VAR indx : INTEGER;
-        parI : Id.ParId;
-  BEGIN
-    IF t.retType # NIL THEN
-      f.Write(retSy);
-      f.EmitTypeOrd(t.retType);
-     (*
-      *   The structure of this type must be
-      *   emitted, unless it is an imported type.
-      *)
-      t.retType.ConditionalMark();
-    END;
-    f.Write(frmSy);
-    FOR indx := 0 TO t.formals.tide-1 DO
-      parI := t.formals.a[indx];
-      f.Write(parSy);
-      f.Write(parI.parMod);
-      f.EmitTypeOrd(parI.type);
-     (*
-      *   Emit Optional Parameter name 
-      *)
-      IF ~G.legacy & (parI.hash # 0) THEN
-        f.WriteString(Nh.charOpenOfHash(parI.hash));
-      END;
-     (*
-      *   The structure of this type must be
-      *   emitted, unless it is an imported type.
-      *)
-      parI.type.ConditionalMark();
-    END;
-    f.Write(endFm);
-  END FormalType;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitConstId(id : Id.ConId),NEW;
-    VAR conX : ExprDesc.LeafX;
-        cVal : LitValue.Value;
-        sVal : INTEGER;
-  (*
-  ** Constant = conSy Name Literal.
-  ** Literal  = Number | String | Set | Char | Real | falSy | truSy.
-  *)
-  BEGIN
-    conX := id.conExp(ExprDesc.LeafX);
-    cVal := conX.value;
-    f.Write(conSy);
-    f.WriteName(id);
-    CASE conX.kind OF
-    | ExprDesc.tBool  : f.Write(truSy);
-    | ExprDesc.fBool  : f.Write(falSy);
-    | ExprDesc.numLt  : f.WriteNum(cVal.long());
-    | ExprDesc.charLt : f.WriteChar(cVal.char());
-    | ExprDesc.realLt : f.WriteReal(cVal.real());
-    | ExprDesc.strLt  : f.WriteString(cVal.chOpen());
-    | ExprDesc.setLt  : 
-        f.Write(setSy); 
-        IF cVal # NIL THEN sVal := cVal.int() ELSE sVal := 0 END;
-        f.Write4B(sVal);
-    END;
-  END EmitConstId;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitTypeId(id : Id.TypId),NEW;
-  (*
-  **  Type = TypeSy Name TypeOrd.
-  *)
-  BEGIN
-    f.Write(typSy);
-    f.WriteName(id);
-    f.EmitTypeOrd(id.type);
-   (*
-    *   The structure of this type must be
-    *   emitted, even if it is an imported type.
-    *)
-    id.type.UnconditionalMark();
-  END EmitTypeId;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitVariableId(id : Id.VarId),NEW;
-  (*
-  ** Variable = varSy Name TypeOrd.
-  *)
-  BEGIN
-    f.Write(varSy);
-    f.WriteName(id);
-    f.EmitTypeOrd(id.type);
-   (*
-    *   The structure of this type must be
-    *   emitted, unless it is an imported type.
-    *)
-    id.type.ConditionalMark();
-  END EmitVariableId;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitImportId(id : Id.BlkId),NEW;
-  (*
-  ** Import = impSy Name.
-  *)
-  BEGIN
-    IF D.need IN id.xAttr THEN
-      f.Write(impSy);
-      f.WriteName(id);
-      IF id.scopeNm # NIL THEN f.WriteString(id.scopeNm) END;
-      f.Write(keySy);
-      f.Write4B(id.modKey);
-      id.impOrd := f.iNxt; INC(f.iNxt);
-    END;
-  END EmitImportId;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitProcedureId(id : Id.PrcId),NEW;
-  (*
-  ** Procedure = prcSy Name FormalType.
-  *)
-  BEGIN
-    f.Write(prcSy);
-    f.WriteName(id);
-    IF id.prcNm # NIL THEN f.WriteString(id.prcNm) END;
-    IF id.kind = Id.ctorP THEN f.Write(truSy) END;
-    f.FormalType(id.type(Ty.Procedure));
-  END EmitProcedureId;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitMethodId(id : Id.MthId),NEW;
-  (*
-  ** Method = mthSy Name Byte Byte TypeOrd [strSy ] FormalType.
-  *)
-  BEGIN
-    IF id.kind = Id.fwdMth THEN id := id.resolve(Id.MthId) END;
-    f.Write(mthSy);
-    f.WriteName(id);
-    f.Write(ORD(id.mthAtt));
-    f.Write(id.rcvFrm.parMod);
-    f.EmitTypeOrd(id.rcvFrm.type);
-    IF id.prcNm # NIL THEN f.WriteString(id.prcNm) END;
-    IF ~G.legacy & (id.rcvFrm.hash # 0) THEN f.WriteName(id.rcvFrm) END;
-    f.FormalType(id.type(Ty.Procedure));
-  END EmitMethodId;
-
-(* ======================================= *)
-
-  PROCEDURE moduleOrd(tpId : D.Idnt) : INTEGER;
-    VAR impM : Id.BlkId;
-  BEGIN
-    IF  (tpId = NIL) OR 
-        (tpId.dfScp = NIL) OR 
-        (tpId.dfScp.kind = Id.modId) THEN
-      RETURN 0;
-    ELSE
-      impM := tpId.dfScp(Id.BlkId);
-      IF impM.impOrd = 0 THEN RETURN -1 ELSE RETURN impM.impOrd END;
-    END;
-  END moduleOrd;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitTypeHeader(t : D.Type),NEW;
-  (*
-  **  TypeHeader = typSy Ord [fromS Ord Name].
-  *)
-    VAR mod : INTEGER;
-        idt : D.Idnt;
-   (* =================================== *)
-    PROCEDURE warp(id : D.Idnt) : D.Idnt;
-    BEGIN
-      IF    id.type = G.ntvObj THEN RETURN G.objId;
-      ELSIF id.type = G.ntvStr THEN RETURN G.strId;
-      ELSIF id.type = G.ntvExc THEN RETURN G.excId;
-      ELSIF id.type = G.ntvTyp THEN RETURN G.clsId;
-      ELSE  RETURN NIL;
-      END;
-    END warp;
-   (* =================================== *)
-  BEGIN
-    WITH t : Ty.Record DO
-      IF t.bindTp = NIL THEN 
-        idt := t.idnt;
-      ELSIF t.bindTp.dump = 0 THEN
-        ASSERT(FALSE);
-        idt := NIL;
-      ELSE
-        idt := t.bindTp.idnt;
-      END;
-    ELSE
-      idt := t.idnt;
-    END;
-    mod := moduleOrd(t.idnt);
-    f.Write(tDefS);
-    f.WriteOrd(t.dump);
-   (*
-    *  Convert native types back to RTS.nativeXXX, if necessary.
-    *  That is ... if the native module is not explicitly imported.
-    *)
-    IF mod = -1 THEN idt := warp(idt); mod := moduleOrd(idt) END;
-    IF mod # 0 THEN
-      f.Write(fromS);
-      f.WriteOrd(mod);
-      f.WriteName(idt);
-    END;
-  END EmitTypeHeader;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitArrOrVecType(t : Ty.Array),NEW;
-  BEGIN
-    f.EmitTypeHeader(t);
-    IF t.force # D.noEmit THEN	(* Don't emit structure unless forced *)
-      IF t.kind = Ty.vecTp THEN f.Write(vecSy) ELSE f.Write(arrSy) END;
-      f.EmitTypeOrd(t.elemTp);
-      IF t.length > 127 THEN
-        f.Write(numSy);
-        f.Write8B(t.length);
-      ELSIF t.length > 0 THEN
-        f.Write(bytSy);
-        f.Write(t.length);
-      END;
-      f.Write(endAr);
-    END;
-  END EmitArrOrVecType;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitRecordType(t : Ty.Record),NEW;
-    VAR index  : INTEGER;
-        field  : D.Idnt;
-        method : D.Idnt;
-  (*
-  **  Record = TypeHeader recSy recAtt [truSy | falSy | <others>] 
-  **		[basSy TypeOrd] [iFcSy {basSy TypeOrd}]
-  **		{Name TypeOrd} {Method} {Statics} endRc.
-  *)
-  BEGIN
-    f.EmitTypeHeader(t);
-    IF t.force # D.noEmit THEN	(* Don't emit structure unless forced *)
-      f.Write(recSy);
-      index := t.recAtt; 
-      IF D.noNew IN t.xAttr THEN INC(index, Ty.noNew) END;
-      IF D.clsTp IN t.xAttr THEN INC(index, Ty.clsRc) END;
-      f.Write(index);
-   (* ########## *)
-      IF t.recAtt = Ty.iFace THEN
-  	f.Write(truSy);
-      ELSIF G.special OR (D.isFn IN t.xAttr) THEN  
-        f.Write(falSy);
-      END;
-   (* ########## *)
-      IF t.baseTp # NIL THEN			(* this is the parent type *)
-        f.Write(basSy);
-        f.EmitTypeOrd(t.baseTp);
-      END;
-   (* ########## *)
-      IF t.interfaces.tide > 0 THEN
-        f.Write(iFcSy);
-        FOR index := 0 TO t.interfaces.tide-1 DO	(* any interfaces  *)
-          f.Write(basSy);
-          f.EmitTypeOrd(t.interfaces.a[index]);
-        END;
-      END;
-   (* ########## *)
-      FOR index := 0 TO t.fields.tide-1 DO
-        field := t.fields.a[index];
-        IF field.vMod # D.prvMode THEN
-          f.WriteName(field);
-          f.EmitTypeOrd(field.type);
-        END;
-      END;
-      IF t.force = D.forced THEN  (* Don't emit methods unless forced *)
-        FOR index := 0 TO t.methods.tide-1 DO
-          method := t.methods.a[index];
-          IF method.vMod # D.prvMode THEN
-            f.EmitMethodId(method(Id.MthId));
-          END;
-        END;
-(*
- *      IF G.special THEN  (* we might need to emit static stuff *)
- *
- *  From 1.2.0 this provides for contructors that do not
- *  extend imported foreign record types.
- *)
-          FOR index := 0 TO t.statics.tide-1 DO
-            field := t.statics.a[index];
-            IF field.vMod # D.prvMode THEN
-              CASE field.kind OF
-              | Id.conId  : f.EmitConstId(field(Id.ConId));
-              | Id.varId  : f.EmitVariableId(field(Id.VarId));
-              | Id.ctorP,
-                Id.conPrc : f.EmitProcedureId(field(Id.PrcId));
-              END;
-            END;
-          END;
-        END;
-(*
- *    END;
- *)
-      f.Write(endRc);
-    END;
-    D.AppendType(f.modS.expRecs, t);
-  END EmitRecordType;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitEnumType(t : Ty.Enum),NEW;
-    VAR index  : INTEGER;
-        const  : D.Idnt;
-  (*
-  **  Enum = TypeHeader eTpSy { constant } endRc.
-  *)
-  BEGIN
-    f.EmitTypeHeader(t);
-    f.Write(eTpSy);
-    FOR index := 0 TO t.statics.tide-1 DO
-      const := t.statics.a[index];
-      IF const.vMod # D.prvMode THEN f.EmitConstId(const(Id.ConId)) END;
-    END;
-    f.Write(endRc);
-    (* D.AppendType(f.modS.expRecs, t); *)
-  END EmitEnumType;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitOpaqueType(t : Ty.Opaque),NEW;
-  BEGIN
-    f.EmitTypeHeader(t);
-  END EmitOpaqueType;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitPointerType(t : Ty.Pointer),NEW;
-  BEGIN
-    f.EmitTypeHeader(t);
-    IF (t.force # D.noEmit) OR 			(* Only emit structure if *)
-       (t.boundTp.force # D.noEmit) THEN	(* ptr or boundTp forced. *)
-      f.Write(ptrSy);
-      f.EmitTypeOrd(t.boundTp);
-    END;
-  END EmitPointerType;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitProcedureType(t : Ty.Procedure),NEW;
-  BEGIN
-    f.EmitTypeHeader(t);
-    IF t.isEventType() THEN f.Write(evtSy) ELSE f.Write(pTpSy) END;
-    f.FormalType(t);
-    D.AppendType(f.modS.expRecs, t);
-  END EmitProcedureType;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFile)EmitTypeList(),NEW;
-    VAR indx : INTEGER;
-        type : D.Type;
-  BEGIN
-   (*
-    *   We cannot use a FOR loop here, as the tide changes
-    *   during evaluation, as a result of reaching new types.
-    *)
-    indx := 0;
-    WHILE indx < f.work.tide DO
-      type := f.work.a[indx];
-
-      WITH type : Ty.Array     DO f.EmitArrOrVecType(type);
-      |    type : Ty.Record    DO f.EmitRecordType(type);
-      |    type : Ty.Opaque    DO f.EmitOpaqueType(type);
-      |    type : Ty.Pointer   DO f.EmitPointerType(type);
-      |    type : Ty.Procedure DO f.EmitProcedureType(type);
-      |    type : Ty.Enum      DO f.EmitEnumType(type);
-      END;
-      INC(indx);
-    END;
-  END EmitTypeList;
-
-(* ======================================= *)
-
-  PROCEDURE EmitSymfile*(m : Id.BlkId);
-
-    VAR symVisit : SymFileSFA;
-        symfile  : SymFile;
-        marker   : INTEGER;
-(*
- *      fileName : FileNames.NameString;
- *)
-        fNamePtr : LitValue.CharOpen;
-  (* ----------------------------------- *)
-    PROCEDURE mkPathName(m : D.Idnt) : LitValue.CharOpen;
-      VAR str : LitValue.CharOpen;
-    BEGIN
-      str := BOX(G.symDir);
-      IF str[LEN(str) - 2] = GF.fileSep THEN
-        str := BOX(str^ + D.getName.ChPtr(m)^ + ".cps");
-      ELSE
-        str := BOX(str^ + fSepArr + D.getName.ChPtr(m)^ + ".cps");
-      END;
-      RETURN str;
-    END mkPathName;
-  (* ----------------------------------- *)
-  (*
-  ** SymFile = Header [String (falSy | truSy | <others>)]
-  **            [ VersionName]
-  **		{Import | Constant | Variable
-  **                 | Type | Procedure | Method} TypeList.
-  ** Header = magic modSy Name.
-  ** VersionName= numSy longint numSy longint numSy longint.
-  **      --            mj# mn#       bld rv#        8xbyte extract
-  *)
-  BEGIN
-   (*
-    *  Create the SymFile structure, and open the output file.
-    *)
-    symfile := newSymFile(m);
-   (* Start of alternative gpcp1.2 code *)
-    IF G.symDir # "" THEN
-      fNamePtr := mkPathName(m);
-      symfile.file := BF.createPath(fNamePtr);
-    ELSE
-      fNamePtr := BOX(D.getName.ChPtr(m)^ + ".cps");
-      symfile.file := BF.createFile(fNamePtr);
-    END;
-    IF symfile.file = NIL THEN
-      S.SemError.Report(177, 0, 0);
-      Error.WriteString("Cannot create file <" + fNamePtr^ + ">"); 
-      Error.WriteLn;
-      RETURN;
-    ELSE
-     (*
-      *  Emit the symbol file header
-      *)
-      IF G.verbose THEN G.Message("Created " + fNamePtr^) END;
-     (* End of alternative gpcp1.2 code *)
-      IF D.rtsMd IN m.xAttr THEN
-        marker := RTS.loInt(syMag);	(* ==> a system module *)
-      ELSE
-        marker := RTS.loInt(magic);	(* ==> a normal module *)
-      END;
-      symfile.Write4B(RTS.loInt(marker));
-      symfile.Write(modSy);
-      symfile.WriteName(m);
-      IF m.scopeNm # NIL THEN (* explicit name *)
-        symfile.WriteString(m.scopeNm);
-        symfile.Write(falSy);
-      END;
-     (*
-      *  Emit the optional TypeName, if required.
-      *
-      *  VersionName= numSy longint numSy longint numSy longint.
-      *       --            mj# mn#       bld rv#        8xbyte extract
-      *)
-      IF m.verNm # NIL THEN
-        symfile.WriteNum(m.verNm[0] * 100000000L + m.verNm[1]);
-        symfile.WriteNum(m.verNm[2] * 100000000L + m.verNm[3]);
-        symfile.WriteNum(m.verNm[4] * 100000000L + m.verNm[5]);
-      END;
-     (*
-      *  Create the symbol table visitor, an extension of 
-      *  Symbols.SymForAll type.  Emit symbols from the scope.
-      *)
-      NEW(symVisit);
-      symVisit.sym := symfile;
-      symfile.modS.symTb.Apply(symVisit); 
-     (*
-      *  Now emit the types on the worklist.
-      *)
-      symfile.Write(start);
-      symfile.EmitTypeList();
-      symfile.Write(close);
-     (*
-      *  Now emit the accumulated checksum key symbol.
-      *)
-      symfile.Write(keySy);
-      lastKey := symfile.cSum;
-      IF G.special THEN symfile.Write4B(0) ELSE symfile.Write4B(lastKey) END;
-      BF.CloseFile(symfile.file);
-    END;
-  END EmitSymfile;
-
-(* ============================================================ *)
-(* ========	Various reading utility procedures	======= *)
-(* ============================================================ *)
-
-  PROCEDURE read(f : BF.FILE) : INTEGER;
-  BEGIN
-    RETURN BF.readByte(f);
-  END read;
-
-(* ======================================= *)
-
-  PROCEDURE ReadUTF(f : BF.FILE; OUT nam : ARRAY OF CHAR);
-    CONST
-        bad = "Bad UTF-8 string";
-    VAR num : INTEGER;
-        bNm : INTEGER;
-        idx : INTEGER;
-        chr : INTEGER;
-  BEGIN
-    num := 0;
-    bNm := read(f) * 256 + read(f);
-    FOR idx := 0 TO bNm-1 DO
-      chr := read(f);
-      IF chr <= 07FH THEN		(* [0xxxxxxx] *)
-        nam[num] := CHR(chr); INC(num);
-      ELSIF chr DIV 32 = 06H THEN	(* [110xxxxx,10xxxxxx] *)
-        bNm := chr MOD 32 * 64;
-        chr := read(f);
-        IF chr DIV 64 = 02H THEN
-          nam[num] := CHR(bNm + chr MOD 64); INC(num);
-        ELSE
-          RTS.Throw(bad);
-        END;
-      ELSIF chr DIV 16 = 0EH THEN	(* [1110xxxx,10xxxxxx,10xxxxxxx] *)
-        bNm := chr MOD 16 * 64;
-        chr := read(f);
-        IF chr DIV 64 = 02H THEN
-          bNm := (bNm + chr MOD 64) * 64; 
-          chr := read(f);
-          IF chr DIV 64 = 02H THEN
-            nam[num] := CHR(bNm + chr MOD 64); INC(num);
-          ELSE 
-            RTS.Throw(bad);
-          END;
-        ELSE
-          RTS.Throw(bad);
-        END;
-      ELSE
-        RTS.Throw(bad);
-      END;
-    END;
-    nam[num] := 0X;
-  END ReadUTF;
-
-(* ======================================= *)
-
-  PROCEDURE readChar(f : BF.FILE) : CHAR;
-  BEGIN
-    RETURN CHR(read(f) * 256 + read(f));
-  END readChar;
-
-(* ======================================= *)
-
-  PROCEDURE readInt(f : BF.FILE) : INTEGER;
-  BEGIN [UNCHECKED_ARITHMETIC]
-    (* overflow checking off here *)
-    RETURN ((read(f) * 256 + read(f)) * 256 + read(f)) * 256 + read(f);
-  END readInt;
-
-(* ======================================= *)
-
-  PROCEDURE readLong(f : BF.FILE) : LONGINT;
-    VAR result : LONGINT;
-        index  : INTEGER;
-  BEGIN [UNCHECKED_ARITHMETIC]
-    (* overflow checking off here *)
-    result := read(f);
-    FOR index := 1 TO 7 DO
-      result := result * 256 + read(f);
-    END;
-    RETURN result;
-  END readLong;
-
-(* ======================================= *)
-
-  PROCEDURE readReal(f : BF.FILE) : REAL;
-    VAR result : LONGINT;
-  BEGIN
-    result := readLong(f);
-    RETURN RTS.longBitsToReal(result);
-  END readReal;
-
-(* ======================================= *)
-
-  PROCEDURE readOrd(f : BF.FILE) : INTEGER;
-    VAR chr : INTEGER;
-  BEGIN
-    chr := read(f);
-    IF chr <= 07FH THEN RETURN chr;
-    ELSE
-      DEC(chr, 128);
-      RETURN chr + read(f) * 128;
-    END;
-  END readOrd;
-
-(* ============================================================ *)
-(* ========		Symbol File Reader		======= *)
-(* ============================================================ *)
-
-  PROCEDURE newSymFileReader*(mod : Id.BlkId) : SymFileReader;
-    VAR new : SymFileReader;
-  BEGIN
-    NEW(new);
-    new.modS := mod;
-    D.InitIdSeq(new.oArray, 4);
-    D.InitTypeSeq(new.tArray, 8);
-    D.InitScpSeq(new.sArray, 8);
-    RETURN new;
-  END newSymFileReader;
-
-(* ======================================= *)
-  PROCEDURE^ (f : SymFileReader)SymFile(IN nm : ARRAY OF CHAR),NEW;
-  PROCEDURE^ WalkThisImport(imp, mod : Id.BlkId);
-(* ======================================= *)
-
-  PROCEDURE Abandon(f : SymFileReader);
-  BEGIN
-    RTS.Throw("Bad symbol file format" + 
-              Nh.charOpenOfHash(f.impS.hash)^); 
-  END Abandon;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFileReader)GetSym(),NEW;
-    VAR file : BF.FILE;
-  BEGIN
-    file := f.file;
-    f.sSym := read(file);
-    CASE f.sSym OF
-    | namSy : 
-        f.iAtt := read(file); ReadUTF(file, f.sAtt);
-    | strSy : 
-        ReadUTF(file, f.sAtt);
-    | retSy, fromS, tDefS, basSy :
-        f.iAtt := readOrd(file);
-    | bytSy :
-        f.iAtt := read(file);
-    | keySy, setSy :
-        f.iAtt := readInt(file);
-    | numSy :
-        f.lAtt := readLong(file);
-    | fltSy :
-        f.rAtt := readReal(file);
-    | chrSy :
-        f.cAtt := readChar(file);
-    ELSE (* nothing to do *)
-    END;
-  END GetSym;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFileReader)ReadPast(sym : INTEGER),NEW;
-  BEGIN
-    IF f.sSym # sym THEN Abandon(f) END;
-    f.GetSym();
-  END ReadPast;
-
-(* ======================================= *)
-
-  PROCEDURE (f : SymFileReader)Parse*(scope : Id.BlkId;
-                                      filNm : FileNames.NameString),NEW;
-    VAR fileName : FileNames.NameString;
-        marker   : INTEGER;
-        token    : S.Token;
-  BEGIN
-    token := scope.token;
-
-    f.impS := scope;
-    D.AppendScope(f.sArray, scope);
-    fileName := filNm + ".cps";
-    f.file := BF.findOnPath("CPSYM", fileName);
-   (* #### *)
-    IF f.file = NIL THEN
-      fileName := "__" + fileName;
-      f.file := BF.findOnPath("CPSYM", fileName);
-      IF f.file # NIL THEN
-        S.SemError.RepSt2(309, filNm, fileName, token.lin, token.col);
-        filNm := "__" + filNm;
-        scope.clsNm := LitValue.strToCharOpen(filNm);
-      END;
-    END;
-   (* #### *)
-    IF f.file = NIL THEN
-      S.SemError.Report(129, token.lin, token.col); RETURN;
-    ELSE
-      IF G.verbose THEN G.Message("Opened " + fileName) END;
-      marker := readInt(f.file);
-      IF marker = RTS.loInt(magic) THEN
-        (* normal case, nothing to do *)
-      ELSIF marker = RTS.loInt(syMag) THEN
-        INCL(scope.xAttr, D.rtsMd);
-      ELSE
-        S.SemError.Report(130, token.lin, token.col); RETURN;
-      END;
-      f.GetSym();
-      f.SymFile(filNm);
-      IF G.verbose THEN 
-        G.Message("Ended " + fileName + ", Key: " 
-        		+ LitValue.intToCharOpen(f.impS.modKey)^);
-      END;
-      BF.CloseFile(f.file);
-    END;
-  END Parse;
-
-(* ============================================ *)
-
-  PROCEDURE testInsert(id : D.Idnt; sc : D.Scope) : D.Idnt;
-    VAR ident : D.Idnt;
-
-    PROCEDURE Report(i,s : D.Idnt);
-      VAR iS, sS : FileNames.NameString;
-    BEGIN
-      D.getName.Of(i, iS);
-      D.getName.Of(s, sS);
-      S.SemError.RepSt2(172, iS, sS, S.line, S.col);
-    END Report;
-
-  BEGIN
-    IF sc.symTb.enter(id.hash, id) THEN
-      ident := id;
-    ELSE
-      ident := sc.symTb.lookup(id.hash);	(* Warp the return Idnt	*)
-      IF ident.kind # id.kind THEN Report(id, sc); ident := id END;
-    END;
-    RETURN ident;
-  END testInsert;
-
-(* ============================================ *)
-
-  PROCEDURE Insert(id : D.Idnt; VAR tb : D.SymbolTable);
-    VAR ident : D.Idnt;
-
-    PROCEDURE Report(i : D.Idnt);
-      VAR iS : FileNames.NameString;
-    BEGIN
-      D.getName.Of(i, iS);
-      S.SemError.RepSt1(172, iS, 1, 1);
-    END Report;
-
-  BEGIN
-    IF ~tb.enter(id.hash, id) THEN
-      ident := tb.lookup(id.hash);		(* and test isForeign? *)
-      IF ident.kind # id.kind THEN Report(id) END;
-    END;
-  END Insert;
-
-(* ============================================ *)
- 
-  PROCEDURE InsertInRec(id : D.Idnt; rec : Ty.Record; sfr : SymFileReader);
-  (* insert, taking into account possible overloaded methods. *)
-  VAR
-    ok : BOOLEAN;
-    oId : Id.OvlId;
-
-    PROCEDURE Report(i : D.Idnt; IN s : ARRAY OF CHAR);
-      VAR iS, sS : FileNames.NameString;
-    BEGIN
-      D.getName.Of(i, iS);
-(*
- *    D.getName.Of(s, sS);
- *    S.SemError.RepSt2(172, iS, sS, S.line, S.col);
- *)
-      S.SemError.RepSt2(172, iS, s, S.line, S.col);
-    END Report;
-
-  BEGIN
-    Ty.InsertInRec(id,rec,TRUE,oId,ok);
-    IF oId # NIL THEN D.AppendIdnt(sfr.oArray,oId); END;
-(*
-    IF ~ok THEN Report(id,rec.idnt); END;
- *)
-    IF ~ok THEN Report(id, rec.name()) END;
-  END InsertInRec;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)getLiteral() : D.Expr,NEW;
-    VAR expr : D.Expr;
-  BEGIN
-    CASE f.sSym OF
-    | truSy : expr := ExprDesc.mkTrueX();
-    | falSy : expr := ExprDesc.mkFalseX();
-    | numSy : expr := ExprDesc.mkNumLt(f.lAtt);
-    | chrSy : expr := ExprDesc.mkCharLt(f.cAtt);
-    | fltSy : expr := ExprDesc.mkRealLt(f.rAtt);
-    | setSy : expr := ExprDesc.mkSetLt(BITS(f.iAtt));
-    | strSy : expr := ExprDesc.mkStrLt(f.sAtt);		(* implicit f.sAtt^ *)
-    END;
-    f.GetSym();						(* read past value  *)
-    RETURN expr;
-  END getLiteral;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)typeOf(ord : INTEGER) : D.Type,NEW;
-    VAR newT : D.Type;
-        indx : INTEGER;
-  BEGIN
-    IF ord < D.tOffset THEN				(* builtin type	*)	
-      RETURN B.baseTypeArray[ord];
-    ELSIF ord - D.tOffset < f.tArray.tide THEN
-      RETURN f.tArray.a[ord - D.tOffset];
-    ELSE 
-      indx := f.tArray.tide + D.tOffset;
-      REPEAT
-        newT := Ty.newTmpTp();
-        newT.dump := indx; INC(indx);
-        D.AppendType(f.tArray, newT);
-      UNTIL indx > ord;
-      RETURN newT;
-    END;
-  END typeOf;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)getTypeFromOrd() : D.Type,NEW;
-    VAR ord : INTEGER;
-  BEGIN
-    ord := readOrd(f.file);
-    f.GetSym();
-    RETURN f.typeOf(ord);
-  END getTypeFromOrd;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)getFormalType(rslt : Ty.Procedure;
-        				     indx : INTEGER) : D.Type,NEW;
-  (*
-  ** FormalType = [retSy TypeOrd] frmSy {parSy Byte TypeOrd [String]} endFm.
-  //	-- optional phrase is return type for proper procedures
-  *)
-    VAR parD : Id.ParId;
-        byte : INTEGER;
-  BEGIN
-    IF f.sSym = retSy THEN 
-      rslt.retType := f.typeOf(f.iAtt);
-      f.GetSym();
-    END;
-    f.ReadPast(frmSy);
-    WHILE f.sSym = parSy DO
-      byte := read(f.file);
-      parD := Id.newParId();
-      parD.parMod := byte;
-      parD.varOrd := indx; 
-      parD.type := f.getTypeFromOrd();
-     (* Skip over optional parameter name string *)
-      IF f.sSym = strSy THEN (* parD.hash := Nh.enterStr(f.sAtt); *)
-        f.GetSym;
-      END;
-      Id.AppendParam(rslt.formals, parD);
-      INC(indx);
-    END;
-    f.ReadPast(endFm);
-    RETURN rslt;
-  END getFormalType;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)pointerType(old : D.Type) : D.Type,NEW;
-  (* Assert: the current symbol ptrSy 		*)
-  (* Pointer   = TypeHeader ptrSy TypeOrd.	*)
-    VAR rslt : Ty.Pointer;
-        indx : INTEGER;
-        junk : D.Type;
-        isEvt: BOOLEAN;
-  BEGIN
-    isEvt := (f.sSym = evtSy);
-    indx := readOrd(f.file);
-    WITH old : Ty.Pointer DO
-      rslt := old;
-     (*
-      *  Check if there is space in the tArray for this
-      *  element, otherwise expand using typeOf().
-      *)
-      IF indx - D.tOffset >= f.tArray.tide THEN
-        junk := f.typeOf(indx);
-      END;
-      f.tArray.a[indx - D.tOffset] := rslt.boundTp;
-    ELSE
-      rslt := Ty.newPtrTp();
-      rslt.boundTp := f.typeOf(indx);
-      IF isEvt THEN rslt.SetKind(Ty.evtTp) END;
-    END;
-    f.GetSym();
-    RETURN rslt;
-  END pointerType;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)procedureType() : D.Type,NEW;
-  (* Assert: the current symbol is pTpSy.	*)
-  (* ProcType  = TypeHeader pTpSy FormalType.	*)
-  BEGIN
-    f.GetSym();		(* read past pTpSy *)
-    RETURN f.getFormalType(Ty.newPrcTp(), 0);
-  END procedureType;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)eventType() : D.Type,NEW;
-  (* Assert: the current symbol is evtSy.	*)
-  (* EventType = TypeHeader evtSy FormalType.	*)
-  BEGIN
-    f.GetSym();		(* read past evtSy *)
-    RETURN f.getFormalType(Ty.newEvtTp(), 0);
-  END eventType;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)arrayType() : Ty.Array,NEW;
-  (* Assert: at entry the current symbol is arrSy.		     *)
-  (* Array      = TypeHeader arrSy TypeOrd (Byte | Number | ) endAr. *)
-  (*	-- nullable phrase is array length for fixed length arrays   *)
-    VAR rslt : Ty.Array;
-        eTyp : D.Type;
-  BEGIN
-    rslt := Ty.newArrTp();
-    rslt.elemTp := f.typeOf(readOrd(f.file));
-    f.GetSym();
-    IF f.sSym = bytSy THEN
-      rslt.length := f.iAtt;
-      f.GetSym();
-    ELSIF f.sSym = numSy THEN
-      rslt.length := SHORT(f.lAtt);
-      f.GetSym();
-    (* ELSE length := 0 *)
-    END;
-    f.ReadPast(endAr);
-    RETURN rslt;
-  END arrayType;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)vectorType() : Ty.Vector,NEW;
-  (* Assert: at entry the current symbol is vecSy.                   *)
-  (* Vector     = TypeHeader vecSy TypeOrd endAr.                    *)
-    VAR rslt : Ty.Vector;
-        eTyp : D.Type;
-  BEGIN
-    rslt := Ty.newVecTp();
-    rslt.elemTp := f.typeOf(readOrd(f.file));
-    f.GetSym();
-    f.ReadPast(endAr);
-    RETURN rslt;
-  END vectorType;
-
-(* ============================================ *)
-  PROCEDURE^ (f : SymFileReader)procedure() : Id.PrcId,NEW;
-  PROCEDURE^ (f : SymFileReader)method()    : Id.MthId,NEW;
-  PROCEDURE^ (f : SymFileReader)constant()  : Id.ConId,NEW;
-  PROCEDURE^ (f : SymFileReader)variable()  : Id.VarId,NEW;
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)recordType(old  : D.Type) : D.Type,NEW;
-  (* Assert: at entry the current symbol is recSy.			*)
-  (* Record     = TypeHeader recSy recAtt [truSy | falSy | <others>] 	*)
-  (*	[basSy TypeOrd] [iFcSy {basSy TypeOrd}]				*)
-  (*	{Name TypeOrd} {Method} {Statics} endRc.			*)
-    CONST 
-        vlTp = Ty.valRc;
-    VAR rslt : Ty.Record;
-        fldD : Id.FldId;
-        varD : Id.VarId;
-        mthD : Id.MthId;
-        conD : Id.ConId;
-        prcD : Id.PrcId;
-        typD : Id.TypId;
-        oldS : INTEGER;
-        attr : INTEGER;
-        mskd : INTEGER;
-  BEGIN
-    WITH old : Ty.Record DO rslt := old ELSE rslt := Ty.newRecTp() END;
-    attr := read(f.file);
-    mskd := attr MOD 8;
-   (*
-    *  The recAtt field has two other bits piggy-backed onto it.
-    *  The noNew Field of xAttr is just added on in the writing 
-    *  and is stripped off here.  The valRc field is used to lock
-    *  in foreign value classes, even though they have basTp # NIL.
-    *)
-(*
- *  IF mskd # Ty.noAtt THEN INCL(rslt.xAttr, D.clsTp) END;
- *  IF attr >= noNw THEN DEC(attr, noNw); INCL(rslt.xAttr, D.noNew) END;
- *)
-    IF attr >= Ty.clsRc THEN DEC(attr,Ty.clsRc); INCL(rslt.xAttr,D.clsTp) END;
-    IF attr >= Ty.noNew THEN DEC(attr,Ty.noNew); INCL(rslt.xAttr,D.noNew) END;
-
-    rslt.recAtt := attr;
-    f.GetSym();				(* Get past recSy rAtt	*)
-    IF f.sSym = falSy THEN
-      INCL(rslt.xAttr, D.isFn);
-      f.GetSym();
-    ELSIF f.sSym = truSy THEN
-      INCL(rslt.xAttr, D.isFn);
-      INCL(rslt.xAttr, D.fnInf);
-      INCL(rslt.xAttr, D.noCpy);
-      f.GetSym();
-    END;
-    IF f.impS.scopeNm # NIL THEN rslt.extrnNm := f.impS.scopeNm END;
-
-    IF f.sSym = basSy THEN
-      rslt.baseTp := f.typeOf(f.iAtt);
-      IF f.iAtt # Ty.anyRec THEN INCL(rslt.xAttr, D.clsTp) END;
-      f.GetSym();
-    END;
-    IF f.sSym = iFcSy THEN
-      f.GetSym();
-      WHILE f.sSym = basSy DO
-        typD := Id.newSfAnonId(f.iAtt);
-        typD.type := f.typeOf(f.iAtt);
-        D.AppendType(rslt.interfaces, typD.type);
-        f.GetSym();
-      END;
-    END;
-    WHILE f.sSym = namSy DO
-      fldD := Id.newFldId();
-      fldD.SetMode(f.iAtt);
-      fldD.hash := Nh.enterStr(f.sAtt);
-      fldD.type := f.typeOf(readOrd(f.file));
-      fldD.recTyp := rslt;
-      f.GetSym();
-      IF rslt.symTb.enter(fldD.hash, fldD) THEN 
-        D.AppendIdnt(rslt.fields, fldD);
-      END;
-    END;
-
-    WHILE (f.sSym = mthSy) OR
-          (f.sSym = prcSy) OR
-          (f.sSym = varSy) OR
-          (f.sSym = conSy) DO
-      oldS := f.sSym; f.GetSym();
-      IF oldS = mthSy THEN
-        mthD := f.method();
-        mthD.bndType := rslt;
-        mthD.type(Ty.Procedure).receiver := rslt;
-        InsertInRec(mthD,rslt,f);
-        D.AppendIdnt(rslt.methods, mthD);
-      ELSIF oldS = prcSy THEN
-        prcD := f.procedure();
-        prcD.bndType := rslt;
-        InsertInRec(prcD,rslt,f);
-        D.AppendIdnt(rslt.statics, prcD);
-      ELSIF oldS = varSy THEN
-        varD := f.variable();
-        varD.recTyp := rslt;
-        InsertInRec(varD,rslt,f);
-        D.AppendIdnt(rslt.statics, varD);
-      ELSIF oldS = conSy THEN
-        conD := f.constant();
-        conD.recTyp := rslt;
-        InsertInRec(conD,rslt,f);
-      ELSE
-        Abandon(f);
-      END;
-    END;
-(* #### *)
-    IF attr >= Ty.valRc THEN 
-      DEC(attr, Ty.valRc); 
-      EXCL(rslt.xAttr, D.clsTp);
-      EXCL(rslt.xAttr, D.noCpy);
-    END;
-(* #### *)
-    f.ReadPast(endRc); 
-    RETURN rslt;
-  END recordType;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)enumType() : D.Type,NEW;
-  (* Assert: at entry the current symbol is eTpSy.			*)
-  (* Enum  = TypeHeader eTpSy { Constant} endRc.			*)
-    VAR rslt : Ty.Enum;
-        cnst : D.Idnt;
-  BEGIN
-    rslt := Ty.newEnuTp();
-    f.GetSym();				(* Get past recSy 	*)
-    WHILE f.sSym = conSy DO
-      f.GetSym();
-      cnst := f.constant();
-      Insert(cnst, rslt.symTb);
-      D.AppendIdnt(rslt.statics, cnst);
-    END;
-    f.ReadPast(endRc); 
-    RETURN rslt;
-  END enumType;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)Type(),NEW;
-  (* Type       = typSy Name TypeOrd.		*)
-    VAR newI : Id.TypId;
-        oldI : D.Idnt;
-        type : D.Type;
-  BEGIN
-   (* 
-    * Post: every previously unknown typId id
-    *	has the property:  id.type.idnt = id.
-    *   If oldI # newT, then the new typId has
-    *   newT.type.idnt = oldI.
-    *)
-    newI := Id.newTypId(NIL);
-    newI.SetMode(f.iAtt);
-    newI.hash := Nh.enterStr(f.sAtt);
-    newI.type := f.getTypeFromOrd(); 
-    newI.dfScp := f.impS;
-    oldI := testInsert(newI, f.impS);
-
-    IF oldI # newI THEN 
-      f.tArray.a[newI.type.dump - D.tOffset] := oldI.type;
-    END;
-
-    IF newI.type.idnt = NIL THEN newI.type.idnt := oldI END;
-  END Type;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)Import(),NEW;
-  (* Import     = impSy Name [String] Key.	*)
-  (*	-- optional string is external name	*)
-  (* first symbol should be namSy here.		*)
-    VAR impD : Id.BlkId;
-        oldS : Id.BlkId;
-        oldD : D.Idnt;
-  BEGIN
-    impD := Id.newImpId();
-    impD.dfScp := impD;			(* ImpId define their own scope *)
-
-    INCL(impD.xAttr, D.weak);
-    impD.SetMode(f.iAtt);
-    impD.hash := Nh.enterStr(f.sAtt);
-    f.ReadPast(namSy); 
-    IF impD.hash = f.modS.hash THEN	(* Importing own imp indirectly	*)
-        				(* Shouldn't this be an error?  *)
-      D.AppendScope(f.sArray, f.modS);
-      IF f.sSym = strSy THEN 
-        (* probably don't need to do anything here ... *)
-        f.GetSym();
-      END;
-    ELSE				(* Importing some other module.	*)
-      oldD := testInsert(impD, f.modS);
-      IF f.sSym = strSy THEN 
-        impD.scopeNm := LitValue.strToCharOpen(f.sAtt);
-        f.GetSym();
-      END;
-      IF (oldD # impD) & (oldD.kind = Id.impId) THEN
-        oldS := oldD(Id.BlkId);
-        D.AppendScope(f.sArray, oldS);
-        IF (oldS.modKey # 0) & (f.iAtt # oldS.modKey) THEN
-          S.SemError.RepSt1(133,		(* Detected bad KeyVal	*)
-        	Nh.charOpenOfHash(impD.hash)^, 
-        	S.line, S.col);
-        END;
-(* should not be necessary anymore *)
-        IF ~(D.weak IN oldS.xAttr) &
-           ~(D.fixd IN oldS.xAttr) THEN
-         (*
-          *   This recursively reads the symbol files for 
-          *   any imports of this file which are on the
-          *   list to be imported later anyhow.
-          *)
-          WalkThisImport(oldS, f.modS);
-        END;
-      ELSE
-        D.AppendScope(f.sArray, impD);
-      END;
-      impD.modKey := f.iAtt;
-    END;
-    f.ReadPast(keySy);
-  END Import;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)constant() : Id.ConId,NEW;
-  (* Constant   = conSy Name Literal.		*)
-  (* Assert: f.sSym = namSy.			*)
-    VAR newC : Id.ConId;
-        anyI : D.Idnt;
-  BEGIN
-    newC := Id.newConId();
-    newC.SetMode(f.iAtt);
-    newC.hash := Nh.enterStr(f.sAtt);
-    newC.dfScp := f.impS;
-    f.ReadPast(namSy);
-    newC.conExp := f.getLiteral();
-    newC.type := newC.conExp.type;
-    RETURN newC;
-  END constant;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)variable() : Id.VarId,NEW;
-  (* Variable   = varSy Name TypeOrd.		*)
-    VAR newV : Id.VarId;
-        anyI : D.Idnt;
-  BEGIN
-    newV := Id.newVarId();
-    newV.SetMode(f.iAtt);
-    newV.hash := Nh.enterStr(f.sAtt);
-    newV.type := f.getTypeFromOrd();
-    newV.dfScp := f.impS;
-    RETURN newV;
-  END variable;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)procedure() : Id.PrcId,NEW;
-  (* Procedure  = prcSy Name[String]FormalType. *)
-  (* This is a static proc, mths come with Recs *)
-    VAR newP : Id.PrcId;
-        anyI : D.Idnt;
-  BEGIN
-    newP := Id.newPrcId();
-    newP.setPrcKind(Id.conPrc);
-    newP.SetMode(f.iAtt);
-    newP.hash := Nh.enterStr(f.sAtt);
-    newP.dfScp := f.impS;
-    f.ReadPast(namSy);
-    IF f.sSym = strSy THEN 
-      newP.prcNm := LitValue.strToCharOpen(f.sAtt);
-     (* and leave scopeNm = NIL *)
-      f.GetSym();
-    END;
-    IF f.sSym = truSy THEN	(* ### this is a constructor ### *)
-      f.GetSym();
-      newP.setPrcKind(Id.ctorP);
-    END;			(* ### this is a constructor ### *)
-    newP.type := f.getFormalType(Ty.newPrcTp(), 0);
-    (* IF this is a java module, do some semantic checks *)
-    (* ... *)
-    RETURN newP;
-  END procedure;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)method() : Id.MthId,NEW;
-  (* Method     = mthSy Name byte byte TypeOrd [String][Name] FormalType. *)
-    VAR newM : Id.MthId;
-        rcvD : Id.ParId;
-        rFrm : INTEGER;
-        mAtt : SET;
-  BEGIN
-    newM := Id.newMthId();
-    newM.SetMode(f.iAtt);
-    newM.setPrcKind(Id.conMth);
-    newM.hash := Nh.enterStr(f.sAtt);
-    newM.dfScp := f.impS;
-    rcvD := Id.newParId();
-    rcvD.varOrd := 0;
-   (* byte1 is the method attributes  *)
-    mAtt := BITS(read(f.file));
-   (* byte2 is param form of receiver *)
-    rFrm := read(f.file);
-   (* next 1 or 2 bytes are rcv-type  *)
-    rcvD.type := f.typeOf(readOrd(f.file));
-    f.GetSym();
-    rcvD.parMod := rFrm;
-    IF f.sSym = strSy THEN 
-      newM.prcNm := LitValue.strToCharOpen(f.sAtt);
-     (* and leave scopeNm = NIL *)
-      f.GetSym();
-    END;
-   (* Skip over optional receiver name string *)
-    IF f.sSym = namSy THEN (* rcvD.hash := Nh.enterString(f.sAtt); *)
-      f.GetSym();
-    END;
-   (* End skip over optional receiver name *)
-    newM.type := f.getFormalType(Ty.newPrcTp(), 1);
-    newM.mthAtt := mAtt;
-    newM.rcvFrm := rcvD;
-   (* IF this is a java module, do some semantic checks *)
-    RETURN newM;
-  END method;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)TypeList(),NEW;
-  (* TypeList   = start { Array | Record | Pointer      *)
-  (*		  | ProcType | Vector} close.           *)
-  (* TypeHeader = tDefS Ord [fromS Ord Name].           *)
-    VAR modOrd : INTEGER;
-        typOrd : INTEGER;
-        typIdx : INTEGER;
-        tpDesc : D.Type;
-        tpTemp : D.Type;
-        tpIdnt : Id.TypId;
-        prevId : D.Idnt;
-        prevTp : D.Type;
-        impScp : D.Scope;
-        linkIx : INTEGER;
-        bndTyp : D.Type;
-        typeFA : TypeLinker;
-  BEGIN
-    WHILE f.sSym = tDefS DO
-      linkIx := 0;
-      tpIdnt := NIL;
-     (* Do type header *)
-      typOrd := f.iAtt;
-      typIdx := typOrd - D.tOffset;
-      tpTemp := f.tArray.a[typIdx];
-      impScp := NIL;
-      f.ReadPast(tDefS);
-     (*
-      *  The [fromS modOrd typNam] appears if the type is imported.
-      *  There are two cases:
-      *     this is the first time that "mod.typNam" has been 
-      *     seen during this compilation 
-      *                   ==> insert a new typId descriptor in mod.symTb
-      *     this name is already in the mod.symTb table
-      *                   ==> fetch the previous descriptor
-      *)
-      IF f.sSym = fromS THEN
-        modOrd := f.iAtt;
-        impScp := f.sArray.a[modOrd];
-        f.GetSym();
-        tpIdnt := Id.newTypId(NIL);
-        tpIdnt.SetMode(f.iAtt);
-        tpIdnt.hash := Nh.enterStr(f.sAtt);
-        tpIdnt.dfScp := impScp;
-        tpIdnt := testInsert(tpIdnt, impScp)(Id.TypId);
-        f.ReadPast(namSy);
-      END;
-
-     (* Get type info. *)
-      CASE f.sSym OF
-      | arrSy : tpDesc := f.arrayType();
-      | vecSy : tpDesc := f.vectorType();
-      | recSy : tpDesc := f.recordType(tpTemp);
-      | pTpSy : tpDesc := f.procedureType();
-      | evtSy : tpDesc := f.eventType();
-      | eTpSy : tpDesc := f.enumType();
-      | ptrSy : tpDesc := f.pointerType(tpTemp);
-                IF tpDesc # NIL THEN 
-                  bndTyp := tpDesc(Ty.Pointer).boundTp;
-                  IF (bndTyp # NIL) & 
-                     (bndTyp.kind = Ty.tmpTp) THEN
-                    linkIx := bndTyp.dump - D.tOffset;
-                  END;
-                END;
-      ELSE 
-        tpDesc := Ty.newNamTp();
-      END;
-      IF tpIdnt # NIL THEN
-       (*
-        *  A name has been declared for this type, tpIdnt is
-        *  the (possibly previously known) id descriptor, and
-        *  tpDesc is the newly parsed descriptor of the type.
-        *) 
-        IF  tpIdnt.type = NIL THEN 
-         (*
-          *  Case #1: no previous type.
-          *  This is the first time the compiler has seen this type
-          *)
-          tpIdnt.type := tpDesc;
-          tpDesc.idnt := tpIdnt;
-        ELSIF tpDesc IS Ty.Opaque THEN
-         (* 
-          *  Case #2: previous type exists, new type is opaque.
-          *  Throw away the newly parsed opaque type desc, and
-          *  use the previously known type *even* if it is opaque!
-          *)
-          tpDesc := tpIdnt.type;
-        ELSIF tpIdnt.type IS Ty.Opaque THEN
-         (*
-          *  Case #3: previous type is opaque, new type is non-opaque.
-          *  This type had been seen opaquely, but now has a 
-          *  non-opaque definition
-          *)
-          tpIdnt.type(Ty.Opaque).resolved := tpDesc;
-          tpIdnt.type := tpDesc;
-          tpDesc.idnt := tpIdnt;
-        ELSE
-         (*
-          *  Case #4: previous type is non-opaque, new type is non-opaque.
-          *  This type already has a non-opaque descriptor.
-          *  We shall keep the original copy.
-          *)
-          tpDesc := tpIdnt.type;
-        END;
-       (*
-        *  Normally, imported types cannot be anonymous.
-        *  However, there is one special case here. Anon
-        *  records can be record base types, but are always 
-        *  preceeded by the binding pointer type. A typical
-        *  format of output from SymDec might be ---
-        *
-        *       T18 = SomeMod.BasePtr
-        *             POINTER TO T19;
-        *       T19 = EXTENSIBLE RECORD  (T11) ... END;
-        *
-        *  in this case T19 is an anon record from SomeMod,
-        *  not the current module.
-        *
-        *  Thus we pre-override the future record declaration
-        *  by the bound type of the pointer.  This ensures
-        *  uniqueness of the record descriptor, even if it is
-        *  imported indirectly multiple times.
-        *)
-        WITH tpDesc : Ty.Pointer DO
-          IF linkIx # 0 THEN f.tArray.a[linkIx] := tpDesc.boundTp END;
-        ELSE (* skip *)
-        END;
-        f.tArray.a[typIdx] := tpDesc;
-      ELSE  
-       (* 
-        *  tpIdnt is NIL ==> type is from this import,
-        *  except for the special case above.  In the usual
-        *  case we replace the tmpTp by tpDesc. In the special
-        *  case the tmpTp has been already been overridden by 
-        *  the previously imported bound type.
-        *)
-        prevTp := f.tArray.a[typIdx];
-        prevId := prevTp.idnt;
-        IF (prevId # NIL) &
-           (prevId.type.kind = Ty.namTp) THEN
-          prevId.type(Ty.Opaque).resolved := tpDesc;
-          prevId.type := tpDesc;
-        END;
-        tpDesc.idnt := prevId;
-        f.tArray.a[typIdx] := tpDesc;
-      END;
-    END; (* while *)
-   (*
-    *  First we fix up all symbolic references in the
-    *  the type array.  Postcondition is : no element
-    *  of the type array directly or indirectly refers
-    *  to a temporary type.
-    *)
-    FOR linkIx := 0 TO f.tArray.tide - 1 DO
-      f.tArray.a[linkIx].TypeFix(f.tArray);
-    END;
-   (*
-    *  We now fix up all references in the symbol table
-    *  that still refer to temporary symbol-file types.
-    *)
-    NEW(typeFA);
-    typeFA.sym := f;
-    f.impS.symTb.Apply(typeFA); 
-    f.ReadPast(close);
-   (*
-    *  Now check that all overloaded ids are necessary
-    *)
-    FOR linkIx := 0 TO f.oArray.tide - 1 DO
-      f.oArray.a[linkIx].OverloadFix();
-      f.oArray.a[linkIx] := NIL;
-    END;
-  END TypeList;
-
-(* ============================================ *)
-
-  PROCEDURE (f : SymFileReader)SymFile(IN nm : ARRAY OF CHAR),NEW;
-   (*
-   // SymFile    = Header [String (falSy | truSy | <others>)]
-   //		{Import | Constant | Variable | Type | Procedure} 
-   //		TypeList Key.
-   // Header     = magic modSy Name.
-   //
-   //  magic has already been recognized.
-   *)
-    VAR oldS : INTEGER;
-  BEGIN
-    f.ReadPast(modSy);
-    IF f.sSym = namSy THEN (* do something with f.sAtt *)
-      IF nm # f.sAtt THEN
-        Error.WriteString("Wrong name in symbol file. Expected <");
-        Error.WriteString(nm + ">, found <");
-        Error.WriteString(f.sAtt + ">"); 
-        Error.WriteLn;
-        HALT(1);
-      END;
-      f.GetSym();
-    ELSE RTS.Throw("Bad symfile header");
-    END;
-    IF f.sSym = strSy THEN (* optional name *)
-      f.impS.scopeNm := LitValue.strToCharOpen(f.sAtt);
-      f.GetSym();
-      IF f.sSym = falSy THEN 
-        INCL(f.impS.xAttr, D.isFn);
-        f.GetSym();
-      ELSIF f.sSym = truSy THEN
-        INCL(f.impS.xAttr, D.isFn);
-        INCL(f.impS.xAttr, D.fnInf);
-        f.GetSym();
-      ELSE RTS.Throw("Bad explicit name");
-      END; 
-    END; 
-    IF f.sSym = numSy THEN (* optional strong name info.    *)
-      NEW(f.impS.verNm);   (* POINTER TO ARRAY 6 OF INTEGER *)
-      f.impS.verNm[0] := RTS.hiInt(f.lAtt);
-      f.impS.verNm[1] := RTS.loInt(f.lAtt);
-      f.GetSym();
-      f.impS.verNm[2] := RTS.hiInt(f.lAtt);
-      f.impS.verNm[3] := RTS.loInt(f.lAtt);
-      f.GetSym();
-      f.impS.verNm[4] := RTS.hiInt(f.lAtt);
-      f.impS.verNm[5] := RTS.loInt(f.lAtt);
-      f.GetSym();
-      IF G.verbose THEN
-        Console.WriteString("version:"); 
-        Console.WriteInt(f.impS.verNm[0],1); Console.Write(".");
-        Console.WriteInt(f.impS.verNm[1],1); Console.Write(".");
-        Console.WriteInt(f.impS.verNm[2],1); Console.Write(".");
-        Console.WriteInt(f.impS.verNm[3],1); 
-        Console.WriteHex(f.impS.verNm[4],9);
-        Console.WriteHex(f.impS.verNm[5],9); Console.WriteLn;
-      END;
-    END;
-    LOOP
-      oldS := f.sSym;
-      f.GetSym();
-      CASE oldS OF
-      | start : EXIT;
-      | typSy : f.Type();
-      | impSy : f.Import();
-      | conSy : Insert(f.constant(),  f.impS.symTb);
-      | varSy : Insert(f.variable(),  f.impS.symTb);
-      | prcSy : Insert(f.procedure(), f.impS.symTb);
-      ELSE RTS.Throw("Bad object");
-      END;
-    END;
-   (* Now read the typelist *)
-    f.TypeList();
-    IF f.sSym = keySy THEN
-      IF f.impS.modKey = 0 THEN 
-        f.impS.modKey := f.iAtt;
-      ELSIF f.impS.modKey # f.iAtt THEN
-        S.SemError.Report(173, S.line, S.col);	(* Detected bad KeyVal	*)
-      END;
-    ELSE RTS.Throw("Missing keySy");
-    END; 
-  END SymFile;
-
-(* ============================================================ *)
-(* ========	     SymFileSFA visitor method		======= *)
-(* ============================================================ *)
-
-  PROCEDURE (t : SymFileSFA)Op*(id : D.Idnt);
-  BEGIN
-    IF (id.kind = Id.impId) OR (id.vMod # D.prvMode) THEN
-      CASE id.kind OF
-      | Id.typId  : t.sym.EmitTypeId(id(Id.TypId));
-      | Id.conId  : t.sym.EmitConstId(id(Id.ConId));
-      | Id.impId  : t.sym.EmitImportId(id(Id.BlkId));
-      | Id.varId  : t.sym.EmitVariableId(id(Id.VarId));
-(* new *)
-      | Id.conPrc : t.sym.EmitProcedureId(id(Id.PrcId));
-(*
- * old ... we used to emit the constructor as a static method.
- *         Now it appears as a static in the bound record decl.
- *
- *    | Id.ctorP,
- *      Id.conPrc : t.sym.EmitProcedureId(id(Id.PrcId));
- *)
-      ELSE (* skip *)
-      END;
-    END;
-  END Op;
-
-(* ============================================================ *)
-(* ========	     TypeLinker visitor method		======= *)
-(* ============================================================ *)
-
-  PROCEDURE (t : TypeLinker)Op*(id : D.Idnt);
-  BEGIN
-    IF id.type = NIL THEN RETURN
-    ELSIF id.type.kind = Ty.tmpTp THEN
-      id.type := Ty.update(t.sym.tArray, id.type);
-    ELSE
-      id.type.TypeFix(t.sym.tArray);
-    END;
-    IF  (id IS Id.TypId) & 
-        (id.type.idnt = NIL) THEN id.type.idnt := id END;
-  END Op;
-
-(* ============================================================ *)
-(* ========	    Symbol file parser method		======= *)
-(* ============================================================ *)
-
-  PROCEDURE WalkThisImport(imp, mod : Id.BlkId);
-    VAR syFil : SymFileReader;
-        filNm : FileNames.NameString;
-  BEGIN
-    PushStack(imp);
-    INCL(imp.xAttr, D.fixd);
-    S.GetString(imp.token.pos, imp.token.len, filNm);
-    syFil := newSymFileReader(mod);
-    syFil.Parse(imp, filNm);
-    PopStack;
-  END WalkThisImport;
- 
-(* ============================================ *)
-
-  PROCEDURE WalkImports*(IN imps : D.ScpSeq; modI : Id.BlkId);
-    VAR indx : INTEGER;
-        scpI : D.Scope;
-        blkI : Id.BlkId;
-  BEGIN
-   (*
-    *  The list of scopes has been constructed by
-    *  the parser, while reading the import list.
-    *  In the case of already known scopes the list
-    *  references the original descriptor.
-    *)
-    InitStack;
-    FOR indx := 0 TO imps.tide-1 DO
-      scpI := imps.a[indx];
-      blkI := scpI(Id.BlkId);
-      IF blkI.kind = Id.alias THEN
-        blkI.symTb  := blkI.dfScp.symTb;
-      ELSIF ~(D.fixd IN blkI.xAttr) THEN 
-        WalkThisImport(blkI,modI);
-      END;
-    END;
-  END WalkImports;
-
-(* ============================================================ *)
-BEGIN
-  lastKey := 0;
-  fSepArr[0] := GF.fileSep;
-END OldSymFileRW.
-(* ============================================================ *)

Datei-Diff unterdrückt, da er zu groß ist
+ 11 - 938
gpcp/PeUtil.cp


+ 1 - 1
gpcp/StatDesc.cp

@@ -525,7 +525,7 @@ MODULE StatDesc;
        (*
         * Third check: does the expression need type coercion.
         *)
-        IF (rTp # lTp) & (rTp IS T.Base) THEN
+        IF (s.rhsX.kind # E.nilLt) & (rTp # lTp) & (rTp IS T.Base) THEN
           s.rhsX := E.coerceUp(s.rhsX, lTp);
           rTp := lTp;
         END;

+ 5 - 0
gpcp/Symbols.cp

@@ -237,6 +237,11 @@ MODULE Symbols;
     t.namStr := MKSTR(NameHash.charOpenOfHash(hash)^);
   END SetNameFromHash;
 
+  PROCEDURE (t : Idnt)ClearName*(),NEW;
+  BEGIN
+    t.namStr := NIL;
+  END ClearName;
+
 (* ============================================================ *)
 (*  This diagnostic method is placed here to use when GPCP-CLR  *)
 (*  itself is being debugged. If ToString is present then       *)

+ 1 - 12
gpcp/Target.cp

@@ -3,7 +3,7 @@
 (*  Copyright (c) John Gough 1999, 2000.			*)
 (* ============================================================ *)
 
-MODULE Target;
+MODULE Target; 
 
   IMPORT 
 	GPCPcopyright,
@@ -11,9 +11,6 @@ MODULE Target;
 	CompState,
 	ClassMaker,
 	JavaMaker,
-(*
- *	LlvmMaker,
- *)
 	MsilMaker,
 	IdDesc;
 
@@ -36,14 +33,6 @@ MODULE Target;
       maker := MsilMaker.newMsilEmitter(mod);
       assmb := MsilMaker.newMsilAsm();
       Symbols.SetTargetIsNET(TRUE);
-(*
- *   (* LLVM backend coming in 2013? *)
- *  ELSIF str = "llvm" THEN 
- *    maker := LlvmMaker.newBitCodeEmitter(mod);
- *    assmb := LlvmMaker.newBitCodeAssembler();
- *    Symbols.SetTargetIsNET(FALSE);
- *  ELSIF ...
- *)
     ELSE
       CompState.Message("Unknown emitter name <" + str + ">");
     END;

+ 5 - 5
gpcp/TypeDesc.cp

@@ -1444,19 +1444,19 @@ MODULE TypeDesc;
         *  - else this is an overload, and must be marked.
         *)
         WITH existingId : Id.FldId DO
-            ok := rec.symTb.enter(id.hash, id);
+            ok := rec.symTb.enter(id.hash, id); (* *)
         | existingId : Id.Procs DO
             IF existingId.type.sigsMatch(id.type) THEN
-              ok := rec.symTb.enter(id.hash, id);
+              ok := rec.symTb.enter(id.hash, id); (* *)
             ELSE
               oId := newOvlIdent(id,rec);
-              ok := rec.symTb.enter(oId.hash,oId);
+              ok := rec.symTb.enter(oId.hash,oId); (* *)
             END;
         | existingId : Id.OvlId DO
             oId := existingId;
-            AddToOvlIdent(id,existingId,doKindCheck,ok);
+            AddToOvlIdent(id,existingId,doKindCheck,ok); (* *)
         ELSE (* must be a field *)
-            ok := rec.symTb.enter(id.hash, id);
+            ok := rec.symTb.enter(id.hash, id); (* *)
         END;
       END;
     ELSIF ~rec.symTb.enter(id.hash, id) THEN

+ 208 - 0
gpcp/build.xml

@@ -0,0 +1,208 @@
+
+<!-- ============================================================  -->
+<!-- This is an ANT build file to build the JVM executables for    -->
+<!-- CPMake, gpcp and Browse from the sources in this directory.   -->
+<!-- Typical invocation is                                         -->
+<!--     $ ant rebuildall                                          -->
+<!-- ============================================================  -->
+<!-- Build gpcp with -asm8 flag, including packaging in a jar file -->
+<!-- ============================================================  -->
+
+<project>
+    <target name="help"> 
+        <echo>Run ant -projecthelp</echo>
+    </target>
+
+    <target name="clean" description="Remove most generated files">
+	    <delete dir="staging/gpcp"/>
+	    <delete dir="staging/cpmake"/>
+	    <delete dir="staging/browse"/>
+	    <delete dir="staging/CP"/>
+	    <delete dir="deploy"/>
+    </target>
+    
+    <target name="cleancp" description="Remove classfile tree ./CP">
+	    <delete dir="CP"/>
+    </target>
+    
+    <!-- Set some property values -->
+    <target name="init">
+        <property name="JRoot" location="./../../"/>
+	<echo>$${JRoot} set to ${JRoot}</echo>
+	<property name="CPSYM" value=".;${JRoot}/symfiles;${JRoot}/symfiles/JvmSystem"/>
+	<echo>$${CPSYM} set to ${CPSYM}</echo>
+    </target>
+
+    <!-- Build gpcp into staging/gpcp directory -->
+    <target name="-buildgpcp" depends="init" description="Compile gpcp compiler sources"> 
+	    <!-- Ensure that we have the JVM-specific source variants -->
+	    <copy file="JavaTargetForJVM.cp" tofile="JavaTarget.cp" overwrite="true"/>
+	    <copy file="PeUtilForJVM.cp" tofile="PeUtil.cp" overwrite="true"/>
+	    <!-- Compile all the source files of gpcp in dependency order -->
+	    <java jar="${JRoot}/jars/cpmake.jar" failonerror="true" fork="true" dir=".">
+                <jvmarg value="-DCPSYM=${CPSYM}"/>
+                <arg value="-all"/>
+                <arg value="-nowarn"/>
+                <arg value="-asm8"/>
+		<arg value="-clsdir:staging/gpcp"/>
+                <arg value="gpcp"/>
+	    </java>
+	    <javac srcdir="${JRoot}/sources/gpcp/libs/java" failonerror="true" destdir="staging/gpcp" includeantruntime="false" debug="true"/>
+    </target>
+
+    <!-- Build CPMake into staging/cpmake directory -->
+    <target name="-buildcpmake" depends="init" description="Compile CPMake sources not part of gpcp">            
+	    <java jar="${JRoot}/jars/gpcp.jar" failonerror="true" fork="true" dir=".">
+                <jvmarg value="-DCPSYM=${CPSYM}"/>
+                <arg value="-nowarn"/>
+                <arg value="-asm8"/>
+		<arg value="-clsdir:staging/cpmake"/>
+		<arg value="ModuleHandler.cp"/>
+		<arg value="SymbolFile.cp"/>
+                <arg value="CPMake.cp"/>
+	    </java>
+    </target>
+
+    <!-- Build Browse into staging/browse directory -->
+    <target name="-buildbrowse" depends="init" description="Compile Browse sources not part of gpcp">            
+	    <java jar="${JRoot}/jars/gpcp.jar" failonerror="true" fork="true" dir=".">
+                <jvmarg value="-DCPSYM=${CPSYM}"/>
+                <arg value="-nowarn"/>
+                <arg value="-asm8"/>
+		<arg value="-clsdir:staging/browse"/>
+                <arg value="Browse.cp"/>
+	    </java>
+    </target>
+
+    <!-- Create the gpcp.jar archive, referencing asm.jar and cprts.jar -->
+    <target name="jargpcp" depends="-buildgpcp" description="Create gpcp.jar into ./deploy">
+	    <mkdir dir="deploy"/>
+	    <jar destfile="deploy/gpcp.jar" basedir="staging/gpcp">
+		    <manifest>
+			    <attribute name="Main-Class" value="CP.gpcp.gpcp"/>
+			    <attribute name="Class-Path" value="cprts.jar asm-5.1.jar"/>
+		    </manifest>
+	    </jar>
+    </target>
+
+    <!-- Create the cpmake.jar archive, referencing gpcp.jar etc. -->
+    <target name="jarcpmake" depends="-buildcpmake" description="Create cpmake.jar into ./deploy">
+	    <mkdir dir="deploy"/>
+	    <jar destfile="deploy/cpmake.jar" basedir="staging/cpmake">
+		    <manifest>
+			    <attribute name="Main-Class" value="CP.CPMake.CPMake"/>
+			    <attribute name="Class-Path" value="gpcp.jar cprts.jar asm-5.1.jar"/>
+		    </manifest>
+	    </jar>
+    </target>
+
+    <!-- Create the browse.jar archive, referencing gpcp.jar etc. -->
+    <target name="jarbrowse" depends="-buildbrowse" description="Create Browse.jar into ./deploy">
+	    <mkdir dir="deploy"/>
+	    <jar destfile="deploy/browse.jar" basedir="staging/browse">
+		    <manifest>
+			    <attribute name="Main-Class" value="CP.Browse.Browse"/>
+			    <attribute name="Class-Path" value="gpcp.jar cprts.jar"/>
+		    </manifest>
+	    </jar>
+    </target>
+
+    <!-- Build runtime system libraries into ${JRoot}/sources/libs/java/dest -->
+    <target name="-buildrts" depends="init" description="Compile runtime system sources">
+	    <delete dir="${JRoot}/sources/libs/java/dest"/>
+	    <mkdir dir="${JRoot}/sources/libs/java/dest"/>
+	    <!-- Compile all the runtime system java classes -->
+	    <javac srcdir="${JRoot}/sources/libs/java" failonerror="true" destdir="${JRoot}/sources/libs/java/dest" includeantruntime="false" debug="true"/>
+    </target>
+
+    <!-- Build component pascal libraries into ../libs/cpascal              -->
+    <!-- Symbol Files go to ../libs/cpascal/symfiles                      -->
+    <!-- Browse HTML Files go to ../libs/cpascal/symfiles/HtmlBrowseFiles -->
+    <!-- Class Files go to ../libs/cpascal/CP/*                           -->
+    <target name="buildcplibs" depends="init" description="Compile gpcp library sources">
+	    <delete dir="${JRoot}/sources/libs/cpascal/CP"/>
+	    <delete dir="${JRoot}/sources/libs/cpascal/symfiles"/>
+	    <mkdir dir="${JRoot}/sources/libs/cpascal/symfiles"/>
+	    <mkdir dir="${JRoot}/sources/libs/cpascal/HtmlBrowseFiles"/>
+	    <!-- Compile all the CP system (foreign implementation) files -->
+	    <java jar="${JRoot}/jars/gpcp.jar" fork="true" dir="${JRoot}/sources/libs/cpascal">
+                <jvmarg value="-DCPSYM=${CPSYM}"/>
+                <arg value="-special"/>
+		<arg value="-symdir:symfiles"/>
+		<arg value="ASCII.cp"/>
+		<arg value="Console.cp"/>
+		<arg value="CPmain.cp"/>
+		<arg value="Error.cp"/>
+		<arg value="GPFiles.cp"/>
+		<arg value="GPBinFiles.cp"/>
+		<arg value="GPTextFiles.cp"/>
+                <arg value="ProgArgs.cp"/>
+                <arg value="RTS.cp"/>
+                <arg value="StdIn.cp"/>
+	    </java>
+	    <!-- Compile all the CP (non-foreign implementation) files -->
+	    <java jar="${JRoot}/jars/gpcp.jar" fork="true" dir="${JRoot}/sources/libs/cpascal">
+                <jvmarg value="-DCPSYM=${CPSYM}"/>
+		<arg value="-symdir:symfiles"/>
+		<arg value="RealStr.cp"/>
+		<arg value="StringLib.cp"/>
+	    </java>
+	    <!-- Create html browse files for all libraries -->
+	    <java jar="${JRoot}/jars/browse.jar" fork="true" dir="${JRoot}/sources/libs/cpascal/symfiles">
+		<jvmarg value="-DCPSYM=${CPSYM}"/>
+		<arg value="-dst:HtmlBrowseFiles"/>
+		<arg value="-html"/>
+		<arg value="-sort"/>
+		<arg value="ASCII.cps"/>
+		<arg value="ASCII.cps"/>
+		<arg value="Console.cps"/>
+		<arg value="CPmain.cps"/>
+		<arg value="Error.cps"/>
+		<arg value="GPFiles.cps"/>
+		<arg value="GPBinFiles.cps"/>
+		<arg value="GPTextFiles.cps"/>
+		<arg value="ProgArgs.cps"/>
+		<arg value="RTS.cps"/>
+		<arg value="StdIn.cps"/>
+		<arg value="RealStr.cps"/>
+		<arg value="StringLib.cps"/>
+	    </java>
+    </target>
+
+    <!-- Create the cprts.jar cp runtime system archive -->
+    <target name="jarRTS" depends="-buildrts" description="Create cprts.jar archive into ./deploy">
+	    <mkdir dir="deploy"/>
+	    <!-- Create the jar archive for these RTS classes -->
+	    <jar destfile="deploy/cprts.jar" basedir="../libs/java/dest"/>
+    </target>
+
+    <!-- Copy the ASM library and copyright notice to ./deploy -->
+    <target name="-copyAsmJar" depends="init" description="Copy asm.jar from JRoot/jars to ./deploy">
+	    <mkdir dir="deploy"/>
+	    <!-- Copy the ASM library class files -->
+	    <copy file="${JRoot}/jars/asm-5.1.jar" todir="deploy"/>
+	    <copy file="${JRoot}/jars/asm-5.1.pom" todir="deploy"/>
+    </target>
+
+    <target name="rebuildgpcp" depends="clean, jargpcp"/>
+    <target name="rebuildall" depends="clean, -copyAsmJar, jarRTS, jargpcp, jarcpmake, jarbrowse" description="Rebuild all jar files into ./deploy"/>
+
+    <!-- Copy the class files to a class tree hierarchy. Used so that -->
+    <!-- the compiler may be run from the classpath rather than jars. -->
+    <target name="makeclasstree" depends="-buildgpcp, -buildcpmake, -buildbrowse, -buildrts, cleancp" description="Rebuild all tools into classfile tree ./CP">
+	    <mkdir dir="CP"/>
+	    <copy todir="CP">
+		    <fileset dir="staging/gpcp/CP"/>
+	    </copy>
+	    <copy todir="CP">
+		    <fileset dir="staging/cpmake/CP"/>
+	    </copy>
+	    <copy todir="CP">
+		    <fileset dir="staging/browse/CP"/>
+	    </copy>
+	    <copy todir="CP">
+		    <fileset dir="../libs/java/dest/CP"/>
+	    </copy>
+    </target>
+</project>
+

+ 1 - 1
gpcp/gpcp.cp

@@ -1,7 +1,7 @@
 (* ==================================================================== *)
 (*									*)
 (*  Driver Module for the Gardens Point Component Pascal Compiler.	*)
-(*	Copyright (c) John Gough 1999, 2000.				*)
+(*	Copyright (c) John Gough 1999, 2016.				*)
 (*	This module was extensively modified from the driver		*)
 (*	automatically produced by the M2 version of COCO/R, using	*)
 (*	the CPascal.atg grammar used for the JVM version of GPCP.	*)

+ 49 - 0
j2cps/build.xml

@@ -0,0 +1,49 @@
+<!-- ============================================================= -->
+<!-- This is an ANT build file to build j2cps from the sources in  -->
+<!-- this directory. Typical invocation is                         -->
+<!--     $ ant { clean | compile | deploy}                         -->
+<!-- ============================================================= -->
+<project>
+    <target name="help">
+	<echo>Run "ant -projecthelp"</echo>
+    </target>
+
+    <target name="clean">
+	 <delete includeemptydirs="true">
+		 <fileset dir="build/j2cps"/>
+	 </delete>
+	 <delete includeemptydirs="true">
+		 <fileset dir="build/j2cpsfiles"/>
+	 </delete>
+	 <delete includeemptydirs="true">
+	     <fileset dir="deploy"/>
+	 </delete>
+    </target>
+    
+    <!-- Set some property values -->
+    <target name="init">
+        <property name="JRoot" value="./../../"/>
+        <property name="CPSYM" value=".;${JRoot}/symfiles;${JRoot}/symfiles/JvmSystem"/>
+    </target>
+
+    <!-- Build j2cps into build directory -->
+    <target name="compile" depends="init" description="Compile J2CPS into a class tree rooted here">            
+	    <mkdir dir="build"/>
+	    <javac srcdir="."
+		   destdir="build"
+		   debug="on"
+		   includeantruntime="false"
+            />
+    </target>
+
+    <!-- Build j2cps into a jar file in deploy directory -->
+    <target name="jarj2cps" depends="compile" description="Package J2CPS into ./deploy/j2cps.jar">            
+	    <mkdir dir="deploy"/>
+	    <jar destfile="deploy/j2cps.jar" basedir="build">
+		    <manifest>
+			    <attribute name="Main-Class" value="j2cps/j2cps"/>
+		    </manifest>
+	    </jar>
+    </target>
+</project>
+

+ 6 - 11
libs/csharp/RTS.cs

@@ -781,7 +781,7 @@ public class ProgArgs
 
         public static void GetEnvVar(char[] name, char[] valu) {
             System.String nam = CP_rts.mkStr(name);
-            System.String val = System.Environment.GetEnvironmentVariable(nam);
+            System.String val = System.Environment.GetEnvironmentVariable(nam, System.EnvironmentVariableTarget.User);
             CP_rts.StrToChF(valu, val);
         }
 
@@ -891,16 +891,11 @@ public class CP_rts
 	// Known in ILASM as [RTS]CP_rts::chrArrLength
 	public static int chrArrLength(char[] src)
 	{
-	    int  ix = 0;
-	    char ch;
-	    do {
-		ch = src[ix];
-		ix++;
-	    } while (ch != '\0');
-// System.Console.Write(ix-1);
-// System.Console.Write(' ');
-// System.Console.WriteLine(src);
-	    return ix-1;
+        int len = src.Length;
+        for (int ix = 0; ix < len; ix++)
+            if (src[ix] == '\0')
+                return ix;
+        return len;
 	}
 
 /* -------------------------------------------------------------------- */

+ 5 - 0
libs/java/CPJrts.java

@@ -113,6 +113,8 @@ public class CPJrts
 
 	public static char[] JavaStrToChrOpen(String input)
 	{
+            if (input == null) 
+                return null;
 	    int    len = input.length();
 	    char[] str = new char[len+1];
 	    input.getChars(0, len, str, 0);
@@ -133,7 +135,10 @@ public class CPJrts
 
 	public static String FixChToJavaStr(char[] arr)
 	{
+            if (arr == null) return null;
+	    //
             // This truncation makes semantics same as .NET version
+	    //
             int len = ChrArrLength(arr);
 	    return new String(arr, 0, len);
 	}

+ 5 - 1
libs/java/GPBinFiles.java

@@ -9,6 +9,7 @@ package CP.GPBinFiles;
 import java.io.*;
 import CP.CPJ.CPJ;
 import CP.GPFiles.GPFiles.*;
+import CP.ProgArgs.ProgArgs.*;
 
 public class GPBinFiles {
 
@@ -40,6 +41,10 @@ public class GPBinFiles {
 
     String nextDir;
     String thisPath = System.getProperty(pName);
+    if (thisPath == null)
+	    thisPath = System.getenv(pName);
+    if (thisPath == null)
+	    return null;
     GPBinFiles_FILE cpf = new GPBinFiles_FILE();
     boolean found = false; 
     boolean pathFinished = false;
@@ -122,7 +127,6 @@ public class GPBinFiles {
     //    cpf.length = cpf.rf.length();
     return cpf;
   } 
-
   public static boolean EOF(GPBinFiles_FILE cpf) throws IOException {
     return cpf.rf.getFilePointer() >= cpf.length;
   }

+ 2 - 0
libs/java/MakeAll.bat

@@ -24,3 +24,5 @@ javac -d . VecR32.java
 javac -d . VecR64.java
 javac -d . VecBase.java
 javac -d . VecRef.java
+pause
+

+ 35 - 0
libs/java/MakeRTSjar.bat

@@ -0,0 +1,35 @@
+
+REM @echo off
+REM this compiles all of the standard java-sourced libraries for GPCP
+REM and collects then together in a JAR file. New for gpcp-JVM v1.4.*
+mkdir dest
+javac -d dest Console.java
+javac -d dest CPJ.java
+javac -d dest CPJrts.java
+javac -d dest XHR.java
+javac -d dest CPmain.java
+javac -d dest Error.java
+javac -d dest GPFiles_FILE.java
+javac -d dest GPFiles.java
+javac -d dest GPBinFiles_FILE.java
+javac -d dest GPBinFiles.java
+javac -d dest GPTextFiles_FILE.java
+javac -d dest GPTextFiles.java
+javac -d dest ProcType.java
+javac -d dest ProgArgs.java
+javac -d dest RTS.java
+javac -d dest StdIn.java
+javac -d dest VecBase.java
+javac -d dest VecChr.java
+javac -d dest VecI32.java
+javac -d dest VecI64.java
+javac -d dest VecR32.java
+javac -d dest VecR64.java
+javac -d dest VecBase.java
+javac -d dest VecRef.java
+cd dest
+jar cvf cprts.jar .
+copy cprts.jar ..
+cd ..
+pause
+

+ 5 - 0
libs/java/ProgArgs.java

@@ -42,7 +42,12 @@ public class ProgArgs
         public static void GetEnvVar(char[] ss, char[] ds) 
         {
             String path = CP.CPJ.CPJ.MkStr(ss);
+	    //
+	    //  getenv was deprecated between jave 1.1 and SE 5 (!)
+	    //
             String valu = System.getProperty(path);
+	    if (valu == null) // Try getenv instead
+		    valu = System.getenv(path);
             int i;
             for (i = 0; 
                  i < valu.length() && i < ds.length;

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.