Kaynağa Gözat

+ generate external names for methods imported under a different name
* switched to mode delphi to avoid problems with nested types in child
classes having the same name as nested types in the parent
* generate skeleton classes for all internal classes that have "package"
visibility so you can inherit from them (full definitions are not
possible because that causes circular dependencies)
-> the entire official JDK 1.5 interface, except for java.awt.Dialog
(circular dependency with java.awt.Window) can now be generated using
-a java.awt.Dialog -a sun. -a com.sun. -a apple. -protected java. javax. org.
(on Mac OS X; the "-a apple." probably has to be changed into something
else on other platforms)

git-svn-id: branches/jvmbackend@18409 -

Jonas Maebe 14 yıl önce
ebeveyn
işleme
2a64e411ce

+ 59 - 14
utils/javapp/src/fpc/tools/javapp/ClassIdentifierInfo.java

@@ -35,14 +35,26 @@ public class ClassIdentifierInfo {
 		}
 	}
 
-	private String checkSafeIdentifierName(String id) {
-		for (int i = 0; i < superClasses.length; i++) {
-			id = getSafeIdentifierNameForClass(superClasses[i],id);
+	private static String getMapIdentifer(String id) {
+		String testName;
+		if (id.equals("<init>"))
+			testName = "CREATE";
+		else if (id.equals("<clinit"))
+			testName = "CLASSCONSTRUCTOR";
+		else
+			testName = id.toUpperCase();
+		return testName;
+	}
+	
+	private String checkSafeIdentifierName(String id, String testName, boolean checkSupers) {
+		if (checkSupers) {
+			for (int i = 0; i < superClasses.length; i++) {
+				id = getSafeIdentifierNameForClassInternal(superClasses[i],id,testName,checkSupers);
+			}
 		}
 		id = PascalKeywords.escapeIfPascalKeyword(id);
-		String testName = id.toUpperCase();
 		String orgName;
-		if (id.indexOf('$') != -1) {
+		if (id.contains("$")) {
 			System.out.println("  Warning, cannot represent identifier '"+id+"', hiding");
 			id = id.replace("$","__");
 		}
@@ -55,16 +67,19 @@ public class ClassIdentifierInfo {
 	}
 
 	private String addIdentifier(String id) {
-		String testName = id.toUpperCase();
-		for (int i = 0; i < superClasses.length; i++) {
-			id = getSafeIdentifierNameForClass(superClasses[i],id);
-		}
-		id = checkSafeIdentifierName(id);
+		String testName = getMapIdentifer(id);
+		id = checkSafeIdentifierName(id,testName,true);
 		identifiers.put(testName, id);
 		return id;
 	}
-	
-	
+		
+	private String addMethodIdentifier(String id) {
+		String testName = getMapIdentifer(id);
+		id = checkSafeIdentifierName(id,testName,false);
+		identifiers.put(testName, id);
+		return id;
+	}
+
 	public static String AddIdentifierNameForClass(String className, String identifier) {
 		ClassIdentifierInfo classIdInfo = identifierStore.get(className);
 		if (classIdInfo == null) {
@@ -73,12 +88,42 @@ public class ClassIdentifierInfo {
 		return classIdInfo.addIdentifier(identifier);
 	}
 	
-	public static String getSafeIdentifierNameForClass(String className, String identifier) {
+	public static String AddMethodIdentifierNameForClass(String className, String identifier) {
+		/** all constructors are called <init> and will be renamed to create
+		 *  -> any method called create will have to be renamed. This happens automatically
+		 *  for classes (since the constructor will be added first), but not for interfaces
+		 *  (they don't have a constructor) -> force it here 
+		 */
+		if (identifier.equals("create"))
+			identifier = "create_";
 		ClassIdentifierInfo classIdInfo = identifierStore.get(className);
 		if (classIdInfo == null) {
 			throw new IllegalStateException("Class info for "+className+" not registered");
 		}
-		return classIdInfo.checkSafeIdentifierName(identifier);
+		return classIdInfo.addMethodIdentifier(identifier);
 	}
+
 	
+	private static String getSafeIdentifierNameForClassInternal(String className, String identifier, String testName, boolean checkSupers) {
+		ClassIdentifierInfo classIdInfo = identifierStore.get(className);
+		if (classIdInfo == null) {
+			throw new IllegalStateException("Class info for "+className+" not registered");
+		}
+		return classIdInfo.checkSafeIdentifierName(identifier,testName,checkSupers);
+	}
+	
+	public static String getSafeIdentifierNameForClass(String className, String identifier) {
+		return getSafeIdentifierNameForClassInternal(className,identifier,getMapIdentifer(identifier),false);
+	}
+	
+	public static String getSafeMethodIdentifierNameForClass(String className, String identifier) {
+		/** all constructors are called <init> and will be renamed to create
+		 *  -> any method called create will have to be renamed. This happens automatically
+		 *  for classes (since the constructor will be added first), but not for interfaces
+		 *  (they don't have a constructor) -> force it here 
+		 */
+		if (identifier.equals("create"))
+			identifier = "create_";
+	return getSafeIdentifierNameForClassInternal(className,identifier,getMapIdentifer(identifier),true);
+	}
 }

+ 100 - 86
utils/javapp/src/fpc/tools/javapp/JavapPrinter.java

@@ -51,15 +51,17 @@ public class JavapPrinter {
     PrintWriter out;
     String prefix;
     boolean doCollectDependencies;
+    boolean printOnlySkel;
     
     private ArrayList<JavapPrinter> innerClassPrinters;
 
-    public JavapPrinter(InputStream cname, PrintWriter out, JavapEnvironment env, String prefix, PascalClassData outerClass, boolean doCollectDependencies){
+    public JavapPrinter(InputStream cname, PrintWriter out, JavapEnvironment env, String prefix, PascalClassData outerClass, boolean doCollectDependencies, boolean printOnlySkel){
         this.out = out;
         this.cls = new PascalClassData(cname,outerClass,env,doCollectDependencies);
         this.env = env;
         this.prefix = prefix;
         this.doCollectDependencies = doCollectDependencies;
+        this.printOnlySkel = printOnlySkel;
         innerClassPrinters = new ArrayList<JavapPrinter>();
         collectInnerClasses();
     }
@@ -69,11 +71,10 @@ public class JavapPrinter {
      */
     public void print(){
     	printclassHeader();
-    	// avoid some circular dependencies 
-    	if ((cls.access & ACC_PUBLIC) != 0) {
+    	if (!printOnlySkel) {
     		printfields();
+    		printMethods();
     	}
-   		printMethods();
         printend();
     }
 
@@ -101,66 +102,67 @@ public class JavapPrinter {
     	}
     	// the actual class/interface
     	out.print(prefix);
-        if(cls.isInterface())   {
-            // The only useful access modifier of an interface is
-            // public; interfaces are always marked as abstract and
-            // cannot be final.
-        	out.print(shortname + " = interface ");
-        }
-        else if(cls.isClass()) {
-            out.print(shortname+" = class ");
-            String []accflags = cls.getModifiers();
-            printAccess(accflags);
-        }
+    	if(cls.isInterface())   {
+    		// The only useful access modifier of an interface is
+    		// public; interfaces are always marked as abstract and
+    		// cannot be final.
+    		out.print(shortname + " = interface ");
+    	}
+    	else if(cls.isClass()) {
+    		out.print(shortname+" = class ");
+    		String []accflags = cls.getModifiers();
+    		printAccess(accflags);
+    	}
 
-        out.print("external ");
-        String pkgname = cls.getClassPackageName();
-        if (pkgname != null)
-        	out.print("'"+pkgname+"' ");
-        out.print("name '"+cls.getExternalClassName()+"' ");
-        
-        // FPC doesn't like it when you say that an interface's superclass is
-        // java.lang.Object, since that's a class (although at the JVM level
-        // it's true)
-        boolean printedOpeningBracket = false;
-    	String superClass = cls.getSuperClassName();
-        if((superClass != null) &&
-        		(cls.isClass() ||
-        				!PascalClassData.getShortPascalClassName(superClass).equals("JLObject"))){
-        	printedOpeningBracket = true;
-        	String fullPascalSuperClass = PascalClassData.getFullPascalClassName(superClass);
-        	String reducedPascalSuperClass = fullPascalSuperClass;
-        	if (!PascalClassData.currentUnit.isExternalInnerClass(superClass) &&
-        			((PascalClassData)cls).outerClass != null) {
-        		reducedPascalSuperClass = fullPascalSuperClass.replace(((PascalClassData)cls).outerClass.getShortPascalClassName()+".","");
-        	}
-        	if (reducedPascalSuperClass.equals(fullPascalSuperClass)) {
-        		out.print("(" + PascalClassData.getShortPascalClassName(superClass));
-        	} else {
-        		out.print("(" + reducedPascalSuperClass);
-        	}
-        	
-        }
+    	out.print("external ");
+    	String pkgname = cls.getClassPackageName();
+    	if (pkgname != null)
+    		out.print("'"+pkgname+"' ");
+    	out.print("name '"+cls.getExternalClassName()+"' ");
+
+    	if (!printOnlySkel) {
+    		// FPC doesn't like it when you say that an interface's superclass is
+    		// java.lang.Object, since that's a class (although at the JVM level
+    		// it's true)
+    		boolean printedOpeningBracket = false;
+    		String superClass = cls.getSuperClassName();
+    		if((superClass != null) &&
+    				(cls.isClass() ||
+    						!PascalClassData.getShortPascalClassName(superClass).equals("JLObject"))){
+    			printedOpeningBracket = true;
+    			String fullPascalSuperClass = PascalClassData.getFullPascalClassName(superClass);
+    			String reducedPascalSuperClass = fullPascalSuperClass;
+    			if (!PascalClassData.currentUnit.isExternalInnerClass(superClass) &&
+    					((PascalClassData)cls).outerClass != null) {
+    				reducedPascalSuperClass = fullPascalSuperClass.replace(((PascalClassData)cls).outerClass.getShortPascalClassName()+".","");
+    			}
+    			if (reducedPascalSuperClass.equals(fullPascalSuperClass)) {
+    				out.print("(" + PascalClassData.getShortPascalClassName(superClass));
+    			} else {
+    				out.print("(" + reducedPascalSuperClass);
+    			}
 
-        String []interfacelist =  cls.getPascalSuperInterfaces();
-        if(interfacelist.length > 0){
-        	// assume all classes that implement interfaces inherit from
-        	// a class (correct, since java.lang.Object does not implement
-        	// any interfaces
-        	if (!printedOpeningBracket) {
-        		out.print("(");
-        		printedOpeningBracket=true;
-        		out.print(interfacelist[0]);
-        	}
-        	else
-                out.print(", "+interfacelist[0]);
-            for(int j = 1; j < interfacelist.length; j++){
-                out.print(", "+interfacelist[j]);
-            }
-        }
-        if (printedOpeningBracket)
-        	out.print(")");
+    		}
 
+    		String []interfacelist =  cls.getPascalSuperInterfaces();
+    		if(interfacelist.length > 0){
+    			// assume all classes that implement interfaces inherit from
+    			// a class (correct, since java.lang.Object does not implement
+    			// any interfaces
+    			if (!printedOpeningBracket) {
+    				out.print("(");
+    				printedOpeningBracket=true;
+    				out.print(interfacelist[0]);
+    			}
+    			else
+    				out.print(", "+interfacelist[0]);
+    			for(int j = 1; j < interfacelist.length; j++){
+    				out.print(", "+interfacelist[j]);
+    			}
+    		}
+    		if (printedOpeningBracket)
+    			out.print(")");
+        }
         /* inner classes */
         printClassAttributes();
     }
@@ -295,12 +297,12 @@ public class JavapPrinter {
      */
     public void printMethodSignature(PascalMethodData method){
     	out.print(prefix);
-    	String methodName = method.getName(); 
-        if(methodName.equals("<init>")){
+    	String pascalName = method.getName();
+        if(pascalName.equals("<init>")){
             out.print("constructor create");
             out.print(method.getParameters());
-        }else if(methodName.equals("<clinit>")){
-            out.print("class constructor create");
+        }else if(pascalName.equals("<clinit>")){
+            out.print("class constructor classcreate");
         }else{
         	String rettype = method.getReturnType();
         	if (method.isStatic())
@@ -309,12 +311,15 @@ public class JavapPrinter {
         		out.print("procedure ");
         	else
         		out.print("function ");
-            out.print(method.getName());
+            out.print(pascalName);
             out.print(method.getParameters());
             if (!rettype.equals(""))
             	out.print(": "+rettype);
         	if (method.isStatic())
         		out.print("; static");
+        	String externalName = method.getExternalName();
+        	if (externalName != null)
+        		out.print("; external name '"+externalName+"'");
         }
         // to fix compilation in Delphi mode
         out.print("; overload;");
@@ -759,18 +764,8 @@ public class JavapPrinter {
             			boolean accessOk = checkAccess(accflags);
             			boolean isStaticInner = inner.isStatic();
             			innerPrinter = new JavapPrinter(env.getFileInputStream(javaclassname(innerClassName)), out, env, prefix+"    ", cls,
-            					doCollectDependencies && accessOk && isStaticInner);
-            			if(accessOk){
-            				// no support yet for non-static inner classes
-            				if (!isStaticInner) {
-            					// register as external class
-            					PascalClassData.currentUnit.registerInnerClassAsExternalClass(innerClassName);
-            					continue;
-            				}
-            				innerClassPrinters.add(innerPrinter);
-            			}
-            			else
-            				PascalClassData.currentUnit.registerInnerClassAsExternalClass(innerClassName);
+            					doCollectDependencies && accessOk && isStaticInner, printOnlySkel || !accessOk || !isStaticInner);
+            			innerClassPrinters.add(innerPrinter);
             		}
             	}
             }
@@ -780,11 +775,17 @@ public class JavapPrinter {
     /**
      * Print InnerClass attribute information.
      */
-	private final int VIS_PROTECTED = 0;
-	private final int VIS_PUBLIC = 1;
+	private final int VIS_PRIVATE = 0;
+	private final int VIS_PACKAGE = 1;
+	private final int VIS_PROTECTED = 2;
+	private final int VIS_PUBLIC = 3;
 
 	private boolean checkInnerVisibility(int access, int visOk) {
 		switch (visOk) {
+		case VIS_PRIVATE:
+			return ((access & ACC_PRIVATE) != 0);
+		case VIS_PACKAGE:
+			return ((access & (ACC_PUBLIC|ACC_PROTECTED|ACC_PRIVATE)) == 0);
 		case VIS_PROTECTED:
 			return ((access & ACC_PROTECTED) != 0);
 		case VIS_PUBLIC:
@@ -793,14 +794,29 @@ public class JavapPrinter {
 			return false;
 		}
 	}
+	
+	private String visibilitySectionName(int vis) {
+		switch (vis) {
+		case VIS_PRIVATE:
+			return "strict private";
+		case VIS_PACKAGE:
+			return "private";
+		case VIS_PROTECTED:
+			return "protected";
+		case VIS_PUBLIC:
+			return "public";
+		default:
+			return "";
+		}
+	}
     
     public void printInnerClasses(){//throws ioexception
     	
-		if (innerClassPrinters.size() > 1)
+    	if (innerClassPrinters.size() > 1)
     		orderInnerClasses();
 
 		if (innerClassPrinters.size() > 0) {
-    		for (int protpub = 0; protpub < 2; protpub++) {
+    		for (int protpub = VIS_PACKAGE; protpub <= VIS_PUBLIC; protpub++) {
     			// no vibility sections in interfaces
     			boolean first = true;
     			for (int i = 0; i < innerClassPrinters.size(); i++) {
@@ -811,10 +827,7 @@ public class JavapPrinter {
     					if (first) {
     						if (!cls.isInterface()) {
     							out.print(prefix);
-    							if (protpub==VIS_PROTECTED)
-    								out.println("strict protected");
-    							else
-    								out.println("public");
+    							out.println(visibilitySectionName(protpub));
     						}
     			    		out.println(innerPrinter.prefix.substring(2)+"type");
     						first = false;
@@ -1026,6 +1039,7 @@ public class JavapPrinter {
 
     public void printend(){
         out.println(prefix+"end;");
+        out.println();
 /*        
         if (cls.isInnerClass()) {
         	String shortName = PascalClassData.getShortClassName(cls.getClassName());

+ 11 - 7
utils/javapp/src/fpc/tools/javapp/Main.java

@@ -103,7 +103,7 @@ public class Main{
 		out.println("   -public                   Print only public classes and members");
 		out.println("   -protected                Print protected/public classes and members");
 		out.println("   -private                  Show all classes and members");
-		out.println("   -x <class_or_pkgename>    Do not print a certain classes or package (suffix package names with '.'");
+		out.println("   -x <class_or_pkgename>    Treat this class/package as defined in another unit (suffix package names with '.'");
 		out.println("   -s                        Print internal type signatures");
 		out.println("   -bootclasspath <pathlist> Override location of class files loaded");
 		out.println("                             by the bootstrap class loader");
@@ -236,9 +236,13 @@ public class Main{
 
 		// collect all class names in the environment (format: /package/name/classname)
 		SortedSet<String> classes = env.getClassesList();
-		// same for arguments
+		// sort package lists that should/should not be printed
+		// to optimize checking; combine exclude and skeleton prefixes in one list
 		Collections.sort(pkgList);
-		Collections.sort(env.excludePrefixes);
+		ArrayList<String> dontPrintPrefixes = new ArrayList<String>(env.excludePrefixes.size()+env.skelPrefixes.size());
+		dontPrintPrefixes.addAll(env.excludePrefixes);
+		dontPrintPrefixes.addAll(env.skelPrefixes);
+		Collections.sort(dontPrintPrefixes);
 		// create the unit
 		PrintWriter includeFile;
 		PrintWriter mainUnitFile;
@@ -262,7 +266,7 @@ public class Main{
 		// first read all requested classes and build dependency graph
 		Iterator<String> classStepper = classes.iterator();
 		Iterator<String> argStepper = pkgList.iterator();
-		Iterator<String> skipPkgsStepper = env.excludePrefixes.iterator();
+		Iterator<String> skipPkgsStepper = dontPrintPrefixes.iterator();
 		HashSet<String> classesToPrintList = new HashSet<String>();
 		SimpleDirectedGraph<String,DefaultEdge> classDependencies = new SimpleDirectedGraph<String, DefaultEdge>(DefaultEdge.class);
 
@@ -315,7 +319,7 @@ public class Main{
 				// but only collect dependency information if we actually
 				// have to print the class
 				InputStream classin = env.getFileInputStream(currentClass);
-				JavapPrinter printer = new JavapPrinter(classin, includeFile, env, "  ",null,doPrintClass);
+				JavapPrinter printer = new JavapPrinter(classin, includeFile, env, "  ",null,doPrintClass,true);
 				if (doPrintClass) {
 					if (!classDependencies.containsVertex(currentClass))
 						classDependencies.addVertex(currentClass);
@@ -354,7 +358,7 @@ public class Main{
 					continue;
 				try {
 					InputStream classin = env.getFileInputStream(currentClass);
-					JavapPrinter printer = new JavapPrinter(classin, includeFile, env, "  ",null, true);
+					JavapPrinter printer = new JavapPrinter(classin, includeFile, env, "  ",null, true,false);
 					printer.print();
 
 					//					JavapClassPrinter.PrintClass(env,includeFile,currentClass,"  ");
@@ -378,7 +382,7 @@ public class Main{
 
 					try {
 						InputStream classin = env.getFileInputStream(currentClass);
-						JavapPrinter printer = new JavapPrinter(classin, includeFile, env, "  ",null,true);
+						JavapPrinter printer = new JavapPrinter(classin, includeFile, env, "  ",null,true,false);
 						printer.print();
 
 						//					JavapClassPrinter.PrintClass(env,includeFile,currentClass,"  ");

+ 1 - 1
utils/javapp/src/fpc/tools/javapp/MethodData.java

@@ -216,7 +216,7 @@ public class MethodData {
         int attr_len=in.readInt(); // attr_length in prog
         int num_exceptions = in.readUnsignedShort();
         exc_index_table=new int[num_exceptions];
-        int[] exc_index_table=new int[num_exceptions];
+//        int[] exc_index_table=new int[num_exceptions];
         for (int l = 0; l < num_exceptions; l++) {
             int exc=in.readShort();
             exc_index_table[l]=exc;

+ 16 - 3
utils/javapp/src/fpc/tools/javapp/PascalClassData.java

@@ -40,6 +40,8 @@ public class PascalClassData extends ClassData {
 			HashSet<String> myDeps = getDependencies();
 			String mySuperClass = getSuperClassName();
 			boolean foundMatch = false;
+			String [] interfaces = getSuperInterfaces();
+			boolean intfMatches[] = new boolean[interfaces.length];
 			PascalClassData outerMostClass = this;
 			while (outerMostClass.outerClass != null) {
 				/**
@@ -57,12 +59,23 @@ public class PascalClassData extends ClassData {
 				 *  end;
 				 *    -> Retry must depend on Result
 				 */
+				String outerClassName = outerMostClass.outerClass.getClassName();
 				if (!foundMatch &&
-						mySuperClass.startsWith(outerMostClass.outerClass.getClassName()) &&
-						!mySuperClass.equals(outerMostClass.outerClass.getClassName())) {
+						mySuperClass.startsWith(outerClassName) &&
+						!mySuperClass.equals(outerClassName)) {
 					foundMatch = true;
 					outerMostClass.addNestedDepdency(mySuperClass);
 				}
+				for (int i = 0; i < interfaces.length; i++) {
+					if (!intfMatches[i]) {
+						String intf = interfaces[i];
+						if (intf.startsWith(outerClassName) &&
+								!intf.equals(outerClassName)) {
+							intfMatches[i] = true;
+							outerMostClass.addNestedDepdency(intf);
+						}
+					}
+				}
 				outerMostClass = outerMostClass.outerClass;
 			}
 			myDeps.remove(outerMostClass.getMasterClassName());
@@ -369,7 +382,7 @@ public class PascalClassData extends ClassData {
     	return new PascalInnerClassData(this);
     }
     
-        public HashSet<String> getDependencies() {
+    public HashSet<String> getDependencies() {
     	HashSet<String> res = new HashSet<String>();
     	// inheritance dependencies (superclass and implemented interfaces)
     	String superClass = getSuperClassName();

+ 1 - 1
utils/javapp/src/fpc/tools/javapp/PascalKeywords.java

@@ -10,7 +10,7 @@ public class PascalKeywords {
 	}
 	
 	static public String escapeIfPascalKeyword(String str) {
-		if (isPascalKeyword(str))
+		if (isPascalKeyword(str.toUpperCase()))
 			return "&"+str;
 		return str;
 	}

+ 22 - 9
utils/javapp/src/fpc/tools/javapp/PascalMethodData.java

@@ -61,18 +61,31 @@ public class PascalMethodData extends MethodData {
         return ptype;
     }
     
-
+    /**
+     * 
+     * @return if the method requires a separate "external" name due to identifier
+     * disambiguation, it is returned. Otherwise returns null.
+     */
+    public String getExternalName() {
+		String realName = super.getName();
+		// handled separately
+		if (realName.equals("<init>") ||
+				realName.equals("<clinit>"))
+			return null;
+		String pascalName = getName();
+		if (pascalName.charAt(0) == '&')
+			pascalName = pascalName.substring(1);
+		if (!pascalName.equals(realName)) {
+			return realName;
+		} else {
+			return null;
+		}
+    }
+    
     public String getName(){
     	if (cachedName == null) {
     		String realName = super.getName();
-    		cachedName = ClassIdentifierInfo.AddIdentifierNameForClass(cls.getClassName(),realName);
-    		// this will require compiler support for remapping field names
-    		// (we also need it for Objective-C and C++ anyway)
-    		if ((cachedName.charAt(0) != '&') &&
-    				!cachedName.equals(realName)) {
-    			System.out.println("  Duplicate identifier conflict in "+cls.getClassName()+" for method '"+realName+"', disabled");
-    		}
-    				
+    		cachedName = ClassIdentifierInfo.AddMethodIdentifierNameForClass(cls.getClassName(),realName);
     	}
     	return cachedName;
     }

+ 4 - 1
utils/javapp/src/fpc/tools/javapp/PascalUnit.java

@@ -293,6 +293,7 @@ public class PascalUnit {
 			unitFile.println("  "+getShortPascalName(curClass)+" = "+kind+";");
 	    	// create formal array types for array parameters
 			printArrayTypes("  ",getShortPascalName(curClass));
+	        unitFile.println();
 		}
 	}
 	
@@ -308,6 +309,7 @@ public class PascalUnit {
 			unitFile.println("  "+shortPascalName+" = "+kind+" external '"+pkgExternalName+"' name '"+shortExternalName+"';");
 	    	// create formal array types for array parameters
 			printArrayTypes("  ",shortPascalName);
+	        unitFile.println();
 		}
 	}
 	
@@ -349,6 +351,7 @@ public class PascalUnit {
 				shortPascalName = PascalClassData.getShortClassName(curClass);
 			} else {
 				shortPascalName = PascalClassData.getShortPascalClassName(curClass);
+		        unitFile.println();
 			}
 			unitFile.println(prefix+shortPascalName+" = "+curSkelItem.kind+" external '"+pkgExternalName+"' name '"+shortExternalName+"'");
 			// make sure we only match inner classes, not classes that start with the word in the current package
@@ -381,7 +384,7 @@ public class PascalUnit {
 		}
 		unitFile.println(" }");
 		unitFile.println("unit "+env.outputName+";");
-		unitFile.println("{$mode objfpc}");
+		unitFile.println("{$mode delphi}");
 		unitFile.println();
 		unitFile.println("interface");
 		unitFile.println();