mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-05 19:30:27 +02:00
* generate a declaration with an dynamic array and one with an open array
parameter in case of array parameters (and in case of constructors, make the open array as "const"; heuristic, not guaranteed 100% safe!) + support for generating include files rather than full units (e.g., for the system unit types), -i option * don't generate imports for anonymous inner types ($1 etc) * mark routines with 'package' visibility as 'public', because some packages are split over multiple units (system unit and jdk import unit) -> allows using these routines in illegal ways, which will result in run time errors + support to also select individual classes with the -x/-a parameters + add "virtual" modifier to methods where appropriate (so the compiler won't force it automatically anymore) git-svn-id: branches/jvmbackend@18439 -
This commit is contained in:
parent
fc2d239f95
commit
6dd7d9db41
@ -71,6 +71,7 @@ public class JavapEnvironment {
|
||||
boolean extDirflag;
|
||||
boolean nothingToDo = true;
|
||||
boolean showallAttr = false;
|
||||
boolean generateInclude = false;
|
||||
String classpath = null;
|
||||
String outputName = "java";
|
||||
ArrayList<String> excludePrefixes;
|
||||
|
@ -282,11 +282,6 @@ public class JavapPrinter {
|
||||
prevVis=newVis;
|
||||
}
|
||||
printMethodSignature(method);
|
||||
// all interface methods are marked as "abstract", and cannot be final
|
||||
if (!cls.isInterface())
|
||||
out.print(method.getModifiers());
|
||||
printExceptions(method);
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
prefix=prefix.substring(2);
|
||||
@ -296,33 +291,60 @@ public class JavapPrinter {
|
||||
* Print method signature.
|
||||
*/
|
||||
public void printMethodSignature(PascalMethodData method){
|
||||
out.print(prefix);
|
||||
StringBuilder sigStart = new StringBuilder();
|
||||
StringBuilder sigEnd;
|
||||
sigStart.append(prefix);
|
||||
String pascalName = method.getName();
|
||||
if(pascalName.equals("<init>")){
|
||||
out.print("constructor create");
|
||||
out.print(method.getParameters());
|
||||
sigStart.append("constructor create");
|
||||
sigEnd = new StringBuilder();
|
||||
// to fix compilation in Delphi mode
|
||||
sigEnd.append("; overload;");
|
||||
String dynArrParas = method.getParameters(false,true);
|
||||
String openArrParas = method.getParameters(true,true);
|
||||
out.print(sigStart+dynArrParas+sigEnd);
|
||||
printExceptions(method);
|
||||
out.println();
|
||||
if (!dynArrParas.equals(openArrParas)) {
|
||||
out.print(sigStart+openArrParas+sigEnd);
|
||||
printExceptions(method);
|
||||
out.println();
|
||||
}
|
||||
}else if(pascalName.equals("<clinit>")){
|
||||
out.print("class constructor classcreate");
|
||||
sigStart.append("class constructor classcreate");
|
||||
}else{
|
||||
String rettype = method.getReturnType();
|
||||
if (method.isStatic())
|
||||
out.print("class ");
|
||||
sigStart.append("class ");
|
||||
if (rettype.equals(""))
|
||||
out.print("procedure ");
|
||||
sigStart.append("procedure ");
|
||||
else
|
||||
out.print("function ");
|
||||
out.print(pascalName);
|
||||
out.print(method.getParameters());
|
||||
sigStart.append("function ");
|
||||
sigStart.append(pascalName);
|
||||
sigEnd = new StringBuilder();
|
||||
if (!rettype.equals(""))
|
||||
out.print(": "+rettype);
|
||||
sigEnd.append(": "+rettype);
|
||||
if (method.isStatic())
|
||||
out.print("; static");
|
||||
sigEnd.append("; static");
|
||||
String externalName = method.getExternalName();
|
||||
if (externalName != null)
|
||||
out.print("; external name '"+externalName+"'");
|
||||
sigEnd.append("; external name '"+externalName+"'");
|
||||
// to fix compilation in Delphi mode
|
||||
sigEnd.append("; overload;");
|
||||
// all interface methods are marked as "abstract", and cannot be final
|
||||
if (!cls.isInterface())
|
||||
sigEnd.append(method.getModifiers());
|
||||
String dynArrParas = method.getParameters(false,false);
|
||||
String openArrParas = method.getParameters(true,false);
|
||||
out.print(sigStart+dynArrParas+sigEnd);
|
||||
printExceptions(method);
|
||||
out.println();
|
||||
if (!dynArrParas.equals(openArrParas)) {
|
||||
out.print(sigStart+openArrParas+sigEnd);
|
||||
printExceptions(method);
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
// to fix compilation in Delphi mode
|
||||
out.print("; overload;");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -760,7 +782,12 @@ public class JavapPrinter {
|
||||
String[] accflags = innerClasses[i].getAccess();
|
||||
PascalInnerClassData inner = (PascalInnerClassData)innerClasses[i];
|
||||
String innerClassName = cls.StringValue(inner.inner_class_info_index);
|
||||
if (innerClassName.startsWith(curClassName+"$")){
|
||||
// * inner class names that do not begin with this class' name are
|
||||
// unrelated to this class (they're nested somewhere else)
|
||||
// * inner class names that start with 0-9 are anonymous
|
||||
if (innerClassName.startsWith(curClassName+"$") &&
|
||||
!((innerClassName.charAt(curClassName.length()+1) >= '0') &&
|
||||
(innerClassName.charAt(curClassName.length()+1) <= '9'))) {
|
||||
boolean accessOk = checkAccess(accflags);
|
||||
boolean isStaticInner = inner.isStatic();
|
||||
innerPrinter = new JavapPrinter(env.getFileInputStream(javaclassname(innerClassName)), out, env, prefix+" ", cls,
|
||||
@ -800,7 +827,10 @@ public class JavapPrinter {
|
||||
case VIS_PRIVATE:
|
||||
return "strict private";
|
||||
case VIS_PACKAGE:
|
||||
return "private";
|
||||
// should be "private", but then won't work for classes of the
|
||||
// same package declared in different units, which happens
|
||||
// at least for the classes in the system unit...
|
||||
return "public";
|
||||
case VIS_PROTECTED:
|
||||
return "protected";
|
||||
case VIS_PUBLIC:
|
||||
|
@ -32,6 +32,7 @@ package fpc.tools.javapp;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.jgrapht.alg.CycleDetector;
|
||||
import org.jgrapht.graph.*;
|
||||
@ -98,6 +99,7 @@ public class Main{
|
||||
out.println(" -classpath <pathlist> Specify where to find user class files");
|
||||
out.println(" -help Print this usage message");
|
||||
out.println(" -J<flag> Pass <flag> directly to the runtime system");
|
||||
out.println(" -i Generate include files instead of complete unit");
|
||||
out.println(" -l Print line number and local variable tables");
|
||||
out.println(" -o <output_base_name> Base name of output unit (default: java");
|
||||
out.println(" -public Print only public classes and members");
|
||||
@ -134,6 +136,8 @@ public class Main{
|
||||
env.showVerbose = true;
|
||||
} else if (arg.equals("-v")) {
|
||||
env.showVerbose = true;
|
||||
} else if (arg.equals("-i")) {
|
||||
env.generateInclude = true;
|
||||
} else if (arg.equals("-h")) {
|
||||
error("-h is no longer available - use the 'javah' program");
|
||||
return false;
|
||||
@ -249,7 +253,11 @@ public class Main{
|
||||
PascalUnit thisUnit;
|
||||
String includeName, mainUnitName;
|
||||
|
||||
mainUnitName = env.outputName+".pas";
|
||||
if (env.generateInclude) {
|
||||
mainUnitName = env.outputName+"h.inc";
|
||||
} else {
|
||||
mainUnitName = env.outputName+".pas";
|
||||
}
|
||||
includeName = env.outputName+".inc";
|
||||
|
||||
includeFile = createFile(includeName);
|
||||
@ -272,45 +280,49 @@ public class Main{
|
||||
|
||||
try {
|
||||
String currentExcludePkg;
|
||||
String currentPkgPrefix;
|
||||
String currentPrefix;
|
||||
if (skipPkgsStepper.hasNext())
|
||||
currentExcludePkg = skipPkgsStepper.next();
|
||||
else
|
||||
currentExcludePkg = ".......";
|
||||
if (argStepper.hasNext())
|
||||
currentPkgPrefix = argStepper.next().replace('.', '/');
|
||||
else
|
||||
currentPkgPrefix = ".......";
|
||||
System.out.println("Indexing classes under "+currentPkgPrefix+"...");
|
||||
if (argStepper.hasNext()) {
|
||||
currentPrefix = argStepper.next();
|
||||
if (!currentPrefix.equals(".")) {
|
||||
currentPrefix = currentPrefix.replace('.', '/');
|
||||
} else {
|
||||
currentPrefix = "./";
|
||||
}
|
||||
} else
|
||||
currentPrefix = ".......";
|
||||
System.out.println("Indexing classes under "+currentPrefix+"...");
|
||||
do {
|
||||
String currentClass = classStepper.next();
|
||||
// if the current class name is > the current package name, skip packages
|
||||
// until we have a package to which the current class belongs, or the
|
||||
// next in line
|
||||
while (argStepper.hasNext() &&
|
||||
!currentClass.startsWith(currentPkgPrefix) &&
|
||||
(currentClass.compareTo(currentPkgPrefix) > 0)) {
|
||||
!PascalUnit.classOrPackageInPrefix(currentClass,currentPrefix) &&
|
||||
(currentClass.compareTo(currentPrefix) > 0)) {
|
||||
String currentArg = argStepper.next();
|
||||
// convention: '.' as package name = no package name, otherwise actual package name
|
||||
if (!currentArg.equals(".")) {
|
||||
currentArg = currentArg.replace('.', '/');
|
||||
currentPkgPrefix = currentArg;
|
||||
currentPrefix = currentArg;
|
||||
} else {
|
||||
currentArg = "./";
|
||||
currentPkgPrefix = currentArg;
|
||||
currentPrefix = currentArg;
|
||||
}
|
||||
System.out.println("Indexing classes under "+currentPkgPrefix+"...");
|
||||
currentPkgPrefix = currentArg;
|
||||
System.out.println("Indexing classes under "+currentPrefix+"...");
|
||||
currentPrefix = currentArg;
|
||||
}
|
||||
boolean doPrintClass = false;
|
||||
// should check whether the class is explicitly excluded from being printed
|
||||
if (currentClass.startsWith(currentPkgPrefix)) {
|
||||
if (PascalUnit.classOrPackageInPrefix(currentClass,currentPrefix)) {
|
||||
while (skipPkgsStepper.hasNext() &&
|
||||
!currentClass.startsWith(currentExcludePkg) &&
|
||||
!PascalUnit.classOrPackageInPrefix(currentClass,currentExcludePkg) &&
|
||||
(currentClass.compareTo(currentExcludePkg) > 0)) {
|
||||
currentExcludePkg = skipPkgsStepper.next();
|
||||
}
|
||||
if (!currentClass.startsWith(currentExcludePkg)) {
|
||||
if (!PascalUnit.classOrPackageInPrefix(currentClass,currentExcludePkg)) {
|
||||
doPrintClass = true;
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public class PascalFieldData extends FieldData {
|
||||
* Returns Pascal type signature of a field.
|
||||
*/
|
||||
public String getType(){
|
||||
return new PascalTypeSignature(getInternalSig(),cls).getFieldType();
|
||||
return new PascalTypeSignature(getInternalSig(),cls,false,false).getFieldType();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,8 +26,9 @@ public class PascalMethodData extends MethodData {
|
||||
* Return modifiers of the method that matter to Pascal import.
|
||||
*/
|
||||
public String getModifiers(){
|
||||
if ((access & ACC_FINAL) !=0) return " final;";
|
||||
if ((access & ACC_ABSTRACT) !=0) return " abstract;";
|
||||
if ((access & ACC_FINAL) !=0) return " virtual; final;";
|
||||
if ((access & ACC_ABSTRACT) !=0) return " virtual; abstract;";
|
||||
if (!isStatic()) return " virtual;";
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -36,7 +37,7 @@ public class PascalMethodData extends MethodData {
|
||||
*/
|
||||
public String getReturnType(){
|
||||
|
||||
String rttype = (new PascalTypeSignature(getInternalSig(), cls)).getReturnType();
|
||||
String rttype = (new PascalTypeSignature(getInternalSig(), cls, false, false)).getReturnType();
|
||||
return rttype;
|
||||
}
|
||||
|
||||
@ -55,8 +56,8 @@ public class PascalMethodData extends MethodData {
|
||||
/**
|
||||
* Return java type parameter signature.
|
||||
*/
|
||||
public String getParameters(){
|
||||
String ptype = (new PascalTypeSignature(getInternalSig(),cls)).getParameters();
|
||||
public String getParameters(boolean useOpenArrays, boolean useConstOpenArrays){
|
||||
String ptype = (new PascalTypeSignature(getInternalSig(),cls,useOpenArrays,useConstOpenArrays)).getParameters();
|
||||
|
||||
return ptype;
|
||||
}
|
||||
|
@ -3,8 +3,17 @@ package fpc.tools.javapp;
|
||||
import java.util.Vector;
|
||||
|
||||
public class PascalTypeSignature extends TypeSignature {
|
||||
|
||||
// use open arrays rather than dynamic arrays for array parameters
|
||||
private boolean useOpenArrays;
|
||||
// when creating open array parameters, declare them as "const" rather than var
|
||||
// (done for constructors, under the assumption that these won't change the
|
||||
// incoming data)
|
||||
private boolean useConstOpenArrays;
|
||||
|
||||
public PascalTypeSignature(String JVMSignature, ClassData cls) {
|
||||
public PascalTypeSignature(String JVMSignature, ClassData cls, boolean useOpenArrays, boolean useConstOpenArrays) {
|
||||
this.useOpenArrays = useOpenArrays;
|
||||
this.useConstOpenArrays = useConstOpenArrays;
|
||||
init(JVMSignature);
|
||||
}
|
||||
|
||||
@ -74,7 +83,11 @@ public class PascalTypeSignature extends TypeSignature {
|
||||
}else {
|
||||
componentType = getBaseType(arrayType);
|
||||
}
|
||||
return outerClass+"Arr"+dimCount+componentType;
|
||||
if (!useOpenArrays ||
|
||||
(dimCount>1))
|
||||
return outerClass+"Arr"+dimCount+componentType;
|
||||
else
|
||||
return "array of "+outerClass+componentType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -84,17 +97,28 @@ public class PascalTypeSignature extends TypeSignature {
|
||||
/* number of arguments of a method.*/
|
||||
argumentlength = parameters.size();
|
||||
/* Pascal type signature.*/
|
||||
String parametersignature = "(";
|
||||
StringBuilder parametersignature = new StringBuilder("(");
|
||||
int i;
|
||||
|
||||
for(i = 0; i < argumentlength; i++){
|
||||
parametersignature += "para"+(i+1)+": "+(String)parameters.elementAt(i);
|
||||
String paraType = (String)parameters.elementAt(i);
|
||||
// contents of open arrays could be changed -> var parameters
|
||||
if (paraType.contains("array of")) {
|
||||
if (!useConstOpenArrays)
|
||||
parametersignature.append("var ");
|
||||
else
|
||||
parametersignature.append("const ");
|
||||
}
|
||||
parametersignature.append("para");
|
||||
parametersignature.append(i+1);
|
||||
parametersignature.append(": ");
|
||||
parametersignature.append(paraType);
|
||||
if(i != parameters.size()-1){
|
||||
parametersignature += "; ";
|
||||
parametersignature.append("; ");
|
||||
}
|
||||
}
|
||||
parametersignature += ")";
|
||||
return parametersignature;
|
||||
parametersignature.append(")");
|
||||
return parametersignature.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -170,6 +170,25 @@ public class PascalUnit {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param currentName name to check
|
||||
* @param currentPrefix if prefix ends in '.' or '/', assumed to be package, otherwise class
|
||||
* @return whether currentName is a class inside currentPrefix
|
||||
*/
|
||||
public static boolean classOrPackageInPrefix(String currentName, String currentPrefix) {
|
||||
boolean res = currentName.startsWith(currentPrefix);
|
||||
char lastPrefixChar = currentPrefix.charAt(currentPrefix.length()-1);
|
||||
if ((lastPrefixChar != '.') &&
|
||||
(lastPrefixChar != '/')) {
|
||||
res &=
|
||||
(currentName.length() == currentPrefix.length()) ||
|
||||
((currentName.length() > currentPrefix.length()) &&
|
||||
(currentName.charAt(currentPrefix.length()) == '$'));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
public void registerUsedClass(String className) {
|
||||
className = className.replace('.','/');
|
||||
@ -181,7 +200,7 @@ public class PascalUnit {
|
||||
isSkel = false;
|
||||
// first check for skeleton classes/packages
|
||||
for (int i = 0; i < skelPrefixes.length; i++) {
|
||||
if (className.startsWith(skelPrefixes[i])) {
|
||||
if (classOrPackageInPrefix(className,skelPrefixes[i])) {
|
||||
isSkel = true;
|
||||
break;
|
||||
}
|
||||
@ -194,11 +213,11 @@ public class PascalUnit {
|
||||
// check whether we should fully print it; if not,
|
||||
// declare as anonymous external
|
||||
for (int i = 0; i < pkgPrefixes.length; i++) {
|
||||
if (className.startsWith(pkgPrefixes[i])) {
|
||||
if (classOrPackageInPrefix(className,pkgPrefixes[i])) {
|
||||
boolean excluded = false;
|
||||
// then excluded
|
||||
for (int j = 0; j < excludePrefixes.length; j++) {
|
||||
if (className.startsWith(excludePrefixes[j])) {
|
||||
if (classOrPackageInPrefix(className,excludePrefixes[j])) {
|
||||
excluded = true;
|
||||
break;
|
||||
}
|
||||
@ -378,16 +397,18 @@ public class PascalUnit {
|
||||
Enumeration<String> strIterator;
|
||||
Enumeration<SkelItem> skelIterator;
|
||||
|
||||
unitFile.print("{ Imports for Java packages: "+RealPkgName(pkgPrefixes[0]));
|
||||
unitFile.print("{ Imports for Java packages/classes: "+RealPkgName(pkgPrefixes[0]));
|
||||
for (int i = 1; i < pkgPrefixes.length; i++) {
|
||||
unitFile.print(", "+RealPkgName(pkgPrefixes[i]));
|
||||
}
|
||||
unitFile.println(" }");
|
||||
unitFile.println("unit "+env.outputName+";");
|
||||
unitFile.println("{$mode delphi}");
|
||||
unitFile.println();
|
||||
unitFile.println("interface");
|
||||
unitFile.println();
|
||||
if (!env.generateInclude) {
|
||||
unitFile.println("unit "+env.outputName+";");
|
||||
unitFile.println("{$mode delphi}");
|
||||
unitFile.println();
|
||||
unitFile.println("interface");
|
||||
unitFile.println();
|
||||
}
|
||||
unitFile.println("type");
|
||||
// forward declaration for all classes/interfaces in this package
|
||||
strIterator = Collections.enumeration(registeredInternalClasses);
|
||||
@ -402,11 +423,13 @@ public class PascalUnit {
|
||||
skelIterator = Collections.enumeration(registeredSkelObjs);
|
||||
printSkelObjs(skelIterator);
|
||||
unitFile.println();
|
||||
unitFile.println("{$include "+includeName+"}");
|
||||
unitFile.println();
|
||||
unitFile.println("implementation");
|
||||
unitFile.println();
|
||||
unitFile.println("end.");
|
||||
if (!env.generateInclude) {
|
||||
unitFile.println("{$include "+includeName+"}");
|
||||
unitFile.println();
|
||||
unitFile.println("implementation");
|
||||
unitFile.println();
|
||||
unitFile.println("end.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user