diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/net/java/games/gluegen/CMethodBindingEmitter.java | 173 | ||||
-rw-r--r-- | src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java | 32 | ||||
-rw-r--r-- | src/net/java/games/gluegen/pcpp/PCPP.java | 55 |
3 files changed, 160 insertions, 100 deletions
diff --git a/src/net/java/games/gluegen/CMethodBindingEmitter.java b/src/net/java/games/gluegen/CMethodBindingEmitter.java index 27df36cea..e72c0ab77 100644 --- a/src/net/java/games/gluegen/CMethodBindingEmitter.java +++ b/src/net/java/games/gluegen/CMethodBindingEmitter.java @@ -349,10 +349,12 @@ public class CMethodBindingEmitter extends FunctionEmitter writer.println(" {"); emitBodyVariableDeclarations(writer); emitBodyUserVariableDeclarations(writer); - emitBodyVariablePreCallSetup(writer); + emitBodyVariablePreCallSetup(writer, false); + emitBodyVariablePreCallSetup(writer, true); emitBodyCallCFunction(writer); emitBodyUserVariableAssignments(writer); - emitBodyVariablePostCallCleanup(writer); + emitBodyVariablePostCallCleanup(writer, true); + emitBodyVariablePostCallCleanup(writer, false); emitBodyReturnResult(writer); writer.println("}"); writer.println(); @@ -365,7 +367,8 @@ public class CMethodBindingEmitter extends FunctionEmitter emitPointerDeclaration(writer, binding.getContainingType(), binding.getContainingCType(), - CMethodBindingEmitter.cThisArgumentName()); + CMethodBindingEmitter.cThisArgumentName(), + null); } boolean emittedDataCopyTemps = false; @@ -382,13 +385,14 @@ public class CMethodBindingEmitter extends FunctionEmitter emitPointerDeclaration(writer, binding.getJavaArgumentType(i), binding.getCArgumentType(i), - convName); + convName, + binding.getArgumentName(i)); if (needsDataCopy && !emittedDataCopyTemps) { // emit loop counter and array length variables used during data // copy writer.println(" jobject _tmpObj;"); writer.println(" int _copyIndex;"); - writer.println(" jsize _arrayLen"+convName+";"); + writer.println(" jsize _tmpArrayLen;"); emittedDataCopyTemps = true; } } else if (type.isString()) { @@ -461,7 +465,8 @@ public class CMethodBindingEmitter extends FunctionEmitter * emitBodyVariableDeclarations(), PRIOR TO calling the actual C * function. */ - protected void emitBodyVariablePreCallSetup(PrintWriter writer) + protected void emitBodyVariablePreCallSetup(PrintWriter writer, + boolean emittingPrimitiveArrayCritical) { // Convert all Buffers to pointers first so we don't have to // call ReleasePrimitiveArrayCritical for any arrays if any @@ -496,6 +501,13 @@ public class CMethodBindingEmitter extends FunctionEmitter } if (javaArgType.isArray()) { + boolean needsDataCopy = javaArgTypeNeedsDataCopy(javaArgType); + Class subArrayElementJavaType = javaArgType.getJavaClass().getComponentType(); + + if ((!needsDataCopy && !emittingPrimitiveArrayCritical) || + (needsDataCopy && emittingPrimitiveArrayCritical)) { + continue; + } if (EMIT_NULL_CHECKS) { writer.print(" if ("); @@ -503,34 +515,31 @@ public class CMethodBindingEmitter extends FunctionEmitter writer.println(" != NULL) {"); } - writer.print(" "); - String convName = pointerConversionArgumentName(i); - writer.print(convName); - writer.print(" = ("); Type cArgType = binding.getCArgumentType(i); String cArgTypeName = cArgType.getName(); - if (javaArgType.isArray() && - javaArgType.getJavaClass().getComponentType() == java.lang.String.class) { - // java-side type is String[] - cArgTypeName = "jstring *"; - } - writer.print(cArgTypeName); - writer.print(") (*env)->GetPrimitiveArrayCritical(env, "); - writer.print(binding.getArgumentName(i)); - writer.println(", NULL);"); - - // Handle the case where the array elements are of a type that needs a - // data copy operation to convert from the java memory model to the C - // memory model (e.g., int[][], String[], etc) - // - // FIXME: should factor out this whole block of code into a separate - // method for clarity and maintenance purposes - Class subArrayElementJavaType = javaArgType.getJavaClass().getComponentType(); - boolean needsDataCopy = - subArrayElementJavaType.isArray() || - subArrayElementJavaType == java.lang.String.class; - if (needsDataCopy) - { + + String convName = pointerConversionArgumentName(i); + + if (!needsDataCopy) { + writer.print(" "); + writer.print(convName); + writer.print(" = ("); + if (javaArgType.isArray() && + javaArgType.getJavaClass().getComponentType() == java.lang.String.class) { + // java-side type is String[] + cArgTypeName = "jstring *"; + } + writer.print(cArgTypeName); + writer.print(") (*env)->GetPrimitiveArrayCritical(env, "); + writer.print(binding.getArgumentName(i)); + writer.println(", NULL);"); + } else { + // Handle the case where the array elements are of a type that needs a + // data copy operation to convert from the java memory model to the C + // memory model (e.g., int[][], String[], etc) + // + // FIXME: should factor out this whole block of code into a separate + // method for clarity and maintenance purposes if (cArgType.toString().indexOf("const") == -1) { // FIXME: if the arg type is non-const, the sematics might be that // the function modifies the argument -- we don't yet support @@ -546,11 +555,11 @@ public class CMethodBindingEmitter extends FunctionEmitter } writer.println(); - writer.println(" /* Copy contents of " + convName + + writer.println(" /* Copy contents of " + binding.getArgumentName(i) + " into " + convName + "_copy */"); // get length of array being copied - String arrayLenName = "_arrayLen"+convName; + String arrayLenName = "_tmpArrayLen"; writer.print(" "); writer.print(arrayLenName); writer.print(" = (*env)->GetArrayLength(env, "); @@ -628,6 +637,10 @@ public class CMethodBindingEmitter extends FunctionEmitter } } else if (javaArgType.isString()) { + if (emittingPrimitiveArrayCritical) { + continue; + } + if (EMIT_NULL_CHECKS) { writer.print(" if ("); writer.print(binding.getArgumentName(i)); @@ -645,7 +658,6 @@ public class CMethodBindingEmitter extends FunctionEmitter // FIXME throw new RuntimeException("Outgoing arrays of StructAccessors not yet implemented"); - } } } @@ -655,7 +667,8 @@ public class CMethodBindingEmitter extends FunctionEmitter * Code to clean up any variables that were declared in * emitBodyVariableDeclarations(), AFTER calling the actual C function. */ - protected void emitBodyVariablePostCallCleanup(PrintWriter writer) + protected void emitBodyVariablePostCallCleanup(PrintWriter writer, + boolean emittingPrimitiveArrayCritical) { // Release primitive arrays and temporary UTF8 strings if necessary for (int i = 0; i < binding.getNumArguments(); i++) { @@ -664,27 +677,36 @@ public class CMethodBindingEmitter extends FunctionEmitter continue; } if (javaArgType.isArray()) { - String convName = pointerConversionArgumentName(i); + boolean needsDataCopy = javaArgTypeNeedsDataCopy(javaArgType); + Class subArrayElementJavaType = javaArgType.getJavaClass().getComponentType(); + + if ((!needsDataCopy && !emittingPrimitiveArrayCritical) || + (needsDataCopy && emittingPrimitiveArrayCritical)) { + continue; + } - // Release array if (EMIT_NULL_CHECKS) { writer.print(" if ("); writer.print(binding.getArgumentName(i)); writer.println(" != NULL) {"); } - // clean up the case where the array elements are of a type that needed - // a data copy operation to convert from the java memory model to the - // C memory model (e.g., int[][], String[], etc) - // - // FIXME: should factor out this whole block of code into a separate - // method for clarity and maintenance purposes - Class subArrayElementJavaType = javaArgType.getJavaClass().getComponentType(); - boolean needsDataCopy = - subArrayElementJavaType.isArray() || - subArrayElementJavaType == java.lang.String.class; - if (needsDataCopy) - { + String convName = pointerConversionArgumentName(i); + + if (!needsDataCopy) { + // Release array + writer.print(" (*env)->ReleasePrimitiveArrayCritical(env, "); + writer.print(binding.getArgumentName(i)); + writer.print(", "); + writer.print(convName); + writer.println(", JNI_ABORT);"); + } else { + // clean up the case where the array elements are of a type that needed + // a data copy operation to convert from the java memory model to the + // C memory model (e.g., int[][], String[], etc) + // + // FIXME: should factor out this whole block of code into a separate + // method for clarity and maintenance purposes Type cArgType = binding.getCArgumentType(i); String cArgTypeName = cArgType.getName(); @@ -699,7 +721,7 @@ public class CMethodBindingEmitter extends FunctionEmitter } writer.println(" /* Clean up " + convName + "_copy */"); - String arrayLenName = "_arrayLen" + convName; + String arrayLenName = "_tmpArrayLen"; // free each element PointerType cArgPtrType = cArgType.asPointer(); @@ -748,17 +770,16 @@ public class CMethodBindingEmitter extends FunctionEmitter writer.println(); } // end of cleaning up copied data - writer.print(" (*env)->ReleasePrimitiveArrayCritical(env, "); - writer.print(binding.getArgumentName(i)); - writer.print(", "); - writer.print(convName); - writer.println(", JNI_ABORT);"); if (EMIT_NULL_CHECKS) { writer.println(" }"); } } else if (javaArgType.isString()) { + if (emittingPrimitiveArrayCritical) { + continue; + } + if (EMIT_NULL_CHECKS) { writer.print(" if ("); writer.print(binding.getArgumentName(i)); @@ -828,6 +849,9 @@ public class CMethodBindingEmitter extends FunctionEmitter } if (javaArgType.isArray() || javaArgType.isNIOBuffer()) { writer.print(pointerConversionArgumentName(i)); + if (javaArgTypeNeedsDataCopy(javaArgType)) { + writer.print("_copy"); + } } else { if (javaArgType.isString()) { writer.print("_UTF8"); } writer.print(binding.getArgumentName(i)); @@ -1036,7 +1060,7 @@ public class CMethodBindingEmitter extends FunctionEmitter writer.print(" if ("); writer.print(varName); writer.println(" == NULL) {"); - writer.println(" (*env)->ThrowNew(env, (*env)->FindClass(env, \"java/lang/OutOfMemoryException\"),"); + writer.println(" (*env)->ThrowNew(env, (*env)->FindClass(env, \"java/lang/OutOfMemoryError\"),"); writer.print(" \"" + errorMessage); writer.print(" in native dispatcher for \\\""); writer.print(binding.getName()); @@ -1097,7 +1121,8 @@ public class CMethodBindingEmitter extends FunctionEmitter private boolean emitPointerDeclaration(PrintWriter writer, JavaType javaType, Type cType, - String cVariableName) { + String cVariableName, + String javaArgumentName) { String ptrTypeString = null; boolean needsDataCopy = false; @@ -1110,6 +1135,7 @@ public class CMethodBindingEmitter extends FunctionEmitter ptrTypeString = cType.getName(); } else if (javaType.isArray()) { + needsDataCopy = javaArgTypeNeedsDataCopy(javaType); // It's an array; get the type of the elements in the array Class elementType = javaType.getJavaClass().getComponentType(); if (elementType.isPrimitive()) @@ -1119,12 +1145,9 @@ public class CMethodBindingEmitter extends FunctionEmitter else if (elementType == java.lang.String.class) { ptrTypeString = "jstring *"; - needsDataCopy = true; } else if (elementType.isArray()) { - needsDataCopy = true; - Class subElementType = elementType.getComponentType(); if (subElementType.isPrimitive()) { @@ -1155,14 +1178,16 @@ public class CMethodBindingEmitter extends FunctionEmitter ptrTypeString = cType.getName(); } - // declare the pointer variable - writer.print(" "); - writer.print(ptrTypeString); - writer.print(" "); - writer.print(cVariableName); - writer.println(" = NULL;"); - - if (needsDataCopy) + if (!needsDataCopy) + { + // declare the pointer variable + writer.print(" "); + writer.print(ptrTypeString); + writer.print(" "); + writer.print(cVariableName); + writer.println(" = NULL;"); + } + else { // Declare a variable to hold a copy of the argument data in which the // incoming data has been properly laid out in memory to match the C @@ -1178,7 +1203,7 @@ public class CMethodBindingEmitter extends FunctionEmitter writer.print(" "); writer.print(cVariableName); writer.print("_copy = NULL; /* copy of data in "); - writer.print(cVariableName); + writer.print(javaArgumentName); writer.println(", laid out according to C memory model */"); } @@ -1239,5 +1264,13 @@ public class CMethodBindingEmitter extends FunctionEmitter } } + protected boolean javaArgTypeNeedsDataCopy(JavaType javaArgType) { + if (javaArgType.isArray()) { + Class subArrayElementJavaType = javaArgType.getJavaClass().getComponentType(); + return (subArrayElementJavaType.isArray() || + subArrayElementJavaType == java.lang.String.class); + } + return false; + } } diff --git a/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java b/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java index 2a1559e52..bb80190d3 100644 --- a/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java +++ b/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java @@ -113,24 +113,27 @@ public class CGLPAWrapperEmitter extends CMethodBindingEmitter super.emitBodyVariableDeclarations(writer); } - protected void emitBodyVariablePreCallSetup(PrintWriter writer) + protected void emitBodyVariablePreCallSetup(PrintWriter writer, + boolean emittingPrimitiveArrayCritical) { - super.emitBodyVariablePreCallSetup(writer); + super.emitBodyVariablePreCallSetup(writer, emittingPrimitiveArrayCritical); - // set the function pointer to the value of the passed-in glProcAddress - FunctionSymbol cSym = getBinding().getCSymbol(); - String funcPointerTypedefName = - GLEmitter.getGLFunctionPointerTypedefName(cSym); + if (!emittingPrimitiveArrayCritical) { + // set the function pointer to the value of the passed-in glProcAddress + FunctionSymbol cSym = getBinding().getCSymbol(); + String funcPointerTypedefName = + GLEmitter.getGLFunctionPointerTypedefName(cSym); - String ptrVarName = "ptr_" + cSym.getName(); + String ptrVarName = "ptr_" + cSym.getName(); - writer.print(" "); - writer.print(ptrVarName); - writer.print(" = ("); - writer.print(funcPointerTypedefName); - writer.println(") (intptr_t) glProcAddress;"); + writer.print(" "); + writer.print(ptrVarName); + writer.print(" = ("); + writer.print(funcPointerTypedefName); + writer.println(") (intptr_t) glProcAddress;"); - writer.println(" assert(" + ptrVarName + " != NULL);"); + writer.println(" assert(" + ptrVarName + " != NULL);"); + } } // FIXME: refactor this and the superclass version so we don't have to copy @@ -192,6 +195,9 @@ public class CGLPAWrapperEmitter extends CMethodBindingEmitter } if (javaType.isArray() || javaType.isNIOBuffer()) { writer.print(pointerConversionArgumentName(i)); + if (javaArgTypeNeedsDataCopy(javaType)) { + writer.print("_copy"); + } } else { if (javaType.isString()) { writer.print("_UTF8"); } writer.print(binding.getArgumentName(i)); diff --git a/src/net/java/games/gluegen/pcpp/PCPP.java b/src/net/java/games/gluegen/pcpp/PCPP.java index 4bddc976f..585d0d9fa 100644 --- a/src/net/java/games/gluegen/pcpp/PCPP.java +++ b/src/net/java/games/gluegen/pcpp/PCPP.java @@ -143,7 +143,8 @@ public class PCPP { to constants. Macros and multi-line defines (which typically contain either macro definitions or expressions) are currently not handled. */ - private Map/*<String, String>*/ defineMap = new HashMap(); + private Map/*<String, String>*/ defineMap = new HashMap(); + private Set/*<String>*/ nonConstantDefines = new HashSet(); /** List containing the #include paths as Strings */ private List/*<String>*/ includePaths; @@ -364,9 +365,9 @@ public class PCPP { } else { // System.err.println("UNDEFINED: '" + name + "' (line " + lineNumber() + " file " + filename() + ")"); } + nonConstantDefines.remove(name); } else System.err.println("FAILED TO UNDEFINE: '" + name + "' (line " + lineNumber() + " file " + filename() + ")"); - } private void handleDefine() throws IOException { @@ -414,7 +415,7 @@ public class PCPP { } else { // Value is a symbolic constant like "#define FOO BAR". // Try to look up the symbol's value - String newValue = (String) defineMap.get(value); + String newValue = resolveDefine(value, true); if (newValue != null) { // Set the value to the value of the symbol. // @@ -427,30 +428,32 @@ public class PCPP { { // Still perform textual replacement defineMap.put(name, value); + nonConstantDefines.add(name); emitDefine = false; } } } else { - // can't handle definitions that aren't constants or empty + // Non-constant define; try to do reasonable textual substitution anyway + // (FIXME: should identify some of these, like (-1), as constants) emitDefine = false; - StringBuffer buf = new StringBuffer("#define "); - buf.append(name); - for (int i = 0; i < sz; ++i) { - buf.append(" "); - buf.append(values.get(i)); + StringBuffer val = new StringBuffer(); + for (int i = 0; i < sz; i++) { + if (i != 0) { + val.append(" "); + } + val.append(resolveDefine((String) values.get(i), false)); } - System.err.println("WARNING: Ignoring \"" + buf.toString() + - "\" at \"" + filename() + "\" line " + lineNumber() + - ": Unable to handle definition to non-constant"); if (defineMap.get(name) != null) { - // This is probably something the user should investigate. + // This is probably something the user should investigate. throw new RuntimeException("Cannot redefine symbol \"" + name + " from \"" + defineMap.get(name) + "\" to non-constant " + - " definition \"" + buf.toString() + "\""); + " definition \"" + val.toString() + "\""); } - } + defineMap.put(name, val.toString()); + nonConstantDefines.add(name); + } if (emitDefine) { @@ -500,6 +503,24 @@ public class PCPP { return true; } + private String resolveDefine(String word, boolean returnNullIfNotFound) { + String lastWord = (String) defineMap.get(word); + if (lastWord == null) { + if (returnNullIfNotFound) { + return null; + } + return word; + } + String nextWord = null; + do { + nextWord = (String) defineMap.get(lastWord); + if (nextWord != null) { + lastWord = nextWord; + } + } while (nextWord != null); + return lastWord; + } + //////////////////////////////////////////////// // Handling of #if/#ifdef/ifndef/endif directives // //////////////////////////////////////////////// @@ -628,8 +649,8 @@ public class PCPP { // See if the statement is "true"; i.e., a non-zero expression if (symbolValue != null) { - // The statement is true if the symbol is defined. - return true; + // The statement is true if the symbol is defined and is a constant expression + return (!nonConstantDefines.contains(word)); } else { // The statement is true if the symbol evaluates to a non-zero value // |