summaryrefslogtreecommitdiffstats
path: root/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java')
-rw-r--r--src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java220
1 files changed, 220 insertions, 0 deletions
diff --git a/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java b/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java
new file mode 100644
index 000000000..2357e7c38
--- /dev/null
+++ b/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package net.java.games.gluegen;
+
+import java.io.*;
+import java.util.*;
+import java.text.MessageFormat;
+
+import net.java.games.gluegen.cgram.types.*;
+
+/** Emits the Java-side component of the Java<->C JNI binding. */
+public class JavaMethodBindingImplEmitter extends JavaMethodBindingEmitter
+{
+ private boolean isUnimplemented;
+
+ public JavaMethodBindingImplEmitter(MethodBinding binding, PrintWriter output, String runtimeExceptionType)
+ {
+ this(binding, output, runtimeExceptionType, false);
+ }
+
+ public JavaMethodBindingImplEmitter(MethodBinding binding,
+ PrintWriter output,
+ String runtimeExceptionType,
+ boolean isUnimplemented)
+ {
+ super(binding, output, runtimeExceptionType);
+ setCommentEmitter(defaultJavaCommentEmitter);
+ this.isUnimplemented = isUnimplemented;
+ }
+
+ protected void emitBody(PrintWriter writer)
+ {
+ MethodBinding binding = getBinding();
+ if (needsBody()) {
+ writer.println();
+ writer.println(" {");
+ if (isUnimplemented) {
+ writer.println(" throw new " + getRuntimeExceptionType() + "(\"Unimplemented\");");
+ } else {
+ emitPreCallSetup(binding, writer);
+ emitReturnVariableSetup(binding, writer);
+ emitCall(binding, writer);
+ }
+ writer.println(" }");
+ } else {
+ writer.println(";");
+ }
+ }
+
+ protected boolean needsBody() {
+ return isUnimplemented || getBinding().needsBody() || getBinding().hasContainingType();
+ }
+
+ protected void emitPreCallSetup(MethodBinding binding, PrintWriter writer) {
+ emitArrayLengthChecks(binding, writer);
+ }
+
+ protected void emitArrayLengthChecks(MethodBinding binding, PrintWriter writer) {
+ // Check lengths of any incoming arrays if necessary
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ Type type = binding.getCArgumentType(i);
+ if (type.isArray()) {
+ ArrayType arrayType = type.asArray();
+ writer.println(" if (" + binding.getArgumentName(i) + ".length < " + arrayType.getLength() + ")");
+ writer.println(" throw new " + getRuntimeExceptionType() + "(\"Length of array \\\"" + binding.getArgumentName(i) +
+ "\\\" was less than the required " + arrayType.getLength() + "\");");
+ }
+ }
+ }
+
+ protected void emitReturnVariableSetup(MethodBinding binding, PrintWriter writer) {
+ writer.print(" ");
+ JavaType returnType = binding.getJavaReturnType();
+ if (!returnType.isVoid()) {
+ if (returnType.isCompoundTypeWrapper() ||
+ returnType.isNIOByteBuffer()) {
+ writer.println("ByteBuffer _res;");
+ writer.print(" _res = ");
+ } else {
+ writer.print("return ");
+ }
+ }
+ }
+
+ protected void emitCall(MethodBinding binding, PrintWriter writer) {
+ writer.print(getImplMethodName());
+ writer.print("(");
+ emitCallArguments(binding, writer);
+ writer.print(")");
+ emitCallResultReturn(binding, writer);
+ }
+
+ protected int emitCallArguments(MethodBinding binding, PrintWriter writer) {
+ boolean needComma = false;
+ int numArgsEmitted = 0;
+ if (binding.hasContainingType()) {
+ // Emit this pointer
+ assert(binding.getContainingType().isCompoundTypeWrapper());
+ writer.print("getBuffer()");
+ needComma = true;
+ ++numArgsEmitted;
+ }
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ JavaType type = binding.getJavaArgumentType(i);
+ if (type.isJNIEnv() || binding.isArgumentThisPointer(i)) {
+ // Don't need to expose these at the Java level
+ continue;
+ }
+
+ if (type.isVoid()) {
+ // Make sure this is the only param to the method; if it isn't,
+ // there's something wrong with our parsing of the headers.
+ assert(binding.getNumArguments() == 1);
+ continue;
+ }
+
+ if (needComma) {
+ writer.print(", ");
+ }
+
+ if (type.isCompoundTypeWrapper()) {
+ writer.print("((");
+ }
+ writer.print(binding.getArgumentName(i));
+ if (type.isCompoundTypeWrapper()) {
+ writer.print(" == null) ? null : ");
+ writer.print(binding.getArgumentName(i));
+ writer.print(".getBuffer())");
+ }
+ needComma = true;
+ ++numArgsEmitted;
+ }
+ return numArgsEmitted;
+ }
+
+ protected void emitCallResultReturn(MethodBinding binding, PrintWriter writer) {
+ JavaType returnType = binding.getJavaReturnType();
+ if (returnType.isCompoundTypeWrapper()) {
+ writer.println(";");
+ String fmt = getReturnedArrayLengthExpression();
+ writer.println(" if (_res == null) return null;");
+ if (fmt == null) {
+ writer.print(" return new " + returnType.getName() + "(_res.order(ByteOrder.nativeOrder()))");
+ } else {
+ writer.println(" _res.order(ByteOrder.nativeOrder());");
+ String[] argumentNames = new String[binding.getNumArguments()];
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ argumentNames[i] = binding.getArgumentName(i);
+ }
+ String expr = new MessageFormat(fmt).format(argumentNames);
+ PointerType cReturnTypePointer = binding.getCReturnType().asPointer();
+ CompoundType cReturnType = null;
+ if (cReturnTypePointer != null) {
+ cReturnType = cReturnTypePointer.getTargetType().asCompound();
+ }
+ if (cReturnType == null) {
+ throw new RuntimeException("ReturnedArrayLength directive currently only supported for pointers to compound types " +
+ "(error occurred while generating Java glue code for " + binding.getName() + ")");
+ }
+ writer.println(" " + getReturnTypeString(false) + " _retarray = new " + getReturnTypeString(true) + "[" + expr + "];");
+ writer.println(" for (int _count = 0; _count < " + expr + "; _count++) {");
+ // Create temporary ByteBuffer slice
+ // FIXME: probably need Type.getAlignedSize() for arrays of
+ // compound types (rounding up to machine-dependent alignment)
+ writer.println(" _res.position(_count * " + cReturnType.getSize() + ");");
+ writer.println(" _res.limit ((1 + _count) * " + cReturnType.getSize() + ");");
+ writer.println(" ByteBuffer _tmp = _res.slice();");
+ writer.println(" _tmp.order(ByteOrder.nativeOrder());");
+ writer.println(" _res.position(0);");
+ writer.println(" _res.limit(_res.capacity());");
+ writer.println(" _retarray[_count] = new " + returnType.getName() + "(_tmp);");
+ writer.println(" }");
+ writer.print (" return _retarray");
+ }
+ } else if (returnType.isNIOBuffer()) {
+ writer.println(";");
+ writer.println(" if (_res == null) return null;");
+ writer.print(" return _res.order(ByteOrder.nativeOrder())");
+ }
+ writer.println(";");
+ }
+}
+