/******************************************************************************* * Copyright (c) 2004, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.tools.internal; import java.lang.reflect.*; import java.util.*; public class NativesGenerator extends JNIGenerator { boolean enterExitMacro; public NativesGenerator() { enterExitMacro = true; } @Override public void generateCopyright() { outputln(fixDelimiter(getMetaData().getCopyright())); } @Override public void generateIncludes() { String outputName = getOutputName(); outputln("#include \"swt.h\""); output("#include \""); output(outputName); outputln("_structs.h\""); output("#include \""); output(outputName); outputln("_stats.h\""); outputln(); } public void generate(JNIClass clazz, String methodName) { JNIMethod[] methods = clazz.getDeclaredMethods(); int count = 0; for (int i = 0; i < methods.length; i++) { if (methods[i].getName().startsWith(methodName)) count++; } JNIMethod[] result = new JNIMethod[count]; count = 0; for (int i = 0; i < methods.length; i++) { if (methods[i].getName().startsWith(methodName)) result[count++] = methods[i]; } generate(result); } @Override public void generate(JNIClass clazz) { JNIMethod[] methods = clazz.getDeclaredMethods(); int i = 0; for (; i < methods.length; i++) { JNIMethod method = methods[i]; if ((method.getModifiers() & Modifier.NATIVE) != 0) break; } if (i == methods.length) return; sort(methods); generateNativeMacro(clazz); generateExcludes(methods); generate(methods); } public void generate(JNIMethod[] methods) { sort(methods); for (int i = 0; i < methods.length; i++) { JNIMethod method = methods[i]; if ((method.getModifiers() & Modifier.NATIVE) == 0) continue; generate(method); if (progress != null) progress.step(); } } boolean isStruct(String flagsStr) { String[] flags = split(flagsStr, " "); for (int i = 0; i < flags.length; i++) { if (flags[i].equals(Flags.FLAG_STRUCT)) return true; } return false; } boolean isFloatingPoint(String type) { return type.equals("float") || type.equals("double"); } void generateCallback(JNIMethod method, String function, JNIParameter[] params, JNIType returnType) { output("static jintLong "); output(function); outputln(";"); output("static "); String[] types = split((String)method.getParam("callback_types"), ";"); String[] flags = split((String)method.getParam("callback_flags"), ";"); output(types[0]); output(" "); output("proc_"); output(function); output("("); boolean first = true; for (int i = 1; i < types.length; i++) { if (!first) output(", "); output(types[i]); output(" "); output("arg"); output(String.valueOf(i - 1)); first = false; } outputln(") {"); output("\t"); if (isStruct(flags[0]) || isFloatingPoint(types[0])) { output(types[0]); output("* lprc = "); } else if (!types[0].equals("void")) { output("return "); } output("(("); output(types[0]); if (isStruct(flags[0]) || isFloatingPoint(types[0])) output("*"); output(" (*)("); first = true; for (int i = 1; i < types.length; i++) { if (!first) output(", "); first = false; output(types[i]); if (isStruct(flags[i]) || isFloatingPoint(types[i])) output("*"); } output("))"); output(function); output(")("); first = true; for (int i = 1; i < types.length; i++) { if (!first) output(", "); first = false; if (isStruct(flags[i]) || isFloatingPoint(types[i])) output("&"); output("arg"); output(String.valueOf(i -1)); } outputln(");"); if (isStruct(flags[0]) || isFloatingPoint(types[0])) { output("\t"); output(types[0]); outputln(" rc;"); outputln("\tif (lprc) {"); outputln("\t\trc = *lprc;"); outputln("\t\tfree(lprc);"); outputln("\t} else {"); output("\t\tmemset(&rc, 0, sizeof("); output(types[0]); outputln("));"); outputln("\t}"); outputln("\treturn rc;"); } outputln("}"); output("static jintLong "); output(method.getName()); outputln("(jintLong func) {"); output("\t"); output(function); outputln(" = func;"); output("\treturn (jintLong)proc_"); output(function); outputln(";"); outputln("}"); } public void generate(JNIMethod method) { if (method.getFlag(FLAG_NO_GEN)) return; JNIType returnType = method.getReturnType(), returnType64 = method.getReturnType64(); if (!(returnType.isType("void") || returnType.isPrimitive() || isSystemClass(returnType) || returnType.isType("java.lang.String"))) { output("Warning: bad return type. :"); outputln(method.toString()); return; } JNIParameter[] params = method.getParameters(); String function = getFunctionName(method), function64 = getFunctionName(method, method.getParameterTypes64()); generateSourceStart(function, function64); boolean sameFunction = function.equals(function64); if (!sameFunction) { output("#ifndef "); output(JNI64); outputln(); } boolean isCPP = getCPP(); if (isCPP) { output("extern \"C\" "); generateFunctionPrototype(method, function, params, returnType, returnType64, true); outputln(";"); } if (function.startsWith("CALLBACK_")) { generateCallback(method, function, params, returnType); } generateFunctionPrototype(method, function, params, returnType, returnType64, !sameFunction); if (!function.equals(function64)) { outputln(); outputln("#else"); if (isCPP) { output("extern \"C\" "); generateFunctionPrototype(method, function64, params, returnType, returnType64, true); outputln(";"); } generateFunctionPrototype(method, function64, params, returnType, returnType64, !sameFunction); outputln(); outputln("#endif"); } generateFunctionBody(method, function, function64, params, returnType, returnType64); generateSourceEnd(function); outputln(); } public void setEnterExitMacro(boolean enterExitMacro) { this.enterExitMacro = enterExitMacro; } void generateExcludes(JNIMethod[] methods) { HashSet<String> excludes = new HashSet<String>(); for (int i = 0; i < methods.length; i++) { JNIMethod method = methods[i]; if ((method.getModifiers() & Modifier.NATIVE) == 0) continue; String exclude = method.getExclude(); if (exclude.length() != 0) { excludes.add(exclude); } } for (String exclude: excludes) { outputln(exclude); for (int i = 0; i < methods.length; i++) { JNIMethod method = methods[i]; if ((method.getModifiers() & Modifier.NATIVE) == 0) continue; String methodExclude = method.getExclude(); if (exclude.equals(methodExclude)) { output("#define NO_"); outputln(getFunctionName(method)); } } outputln("#endif"); outputln(); } } void generateNativeMacro(JNIClass clazz) { output("#ifndef "); output(clazz.getSimpleName()); outputln("_NATIVE"); output("#define "); output(clazz.getSimpleName()); output("_NATIVE(func) Java_"); output(toC(clazz.getName())); outputln("_##func"); outputln("#endif"); outputln(); } boolean generateGetParameter(JNIMethod method, JNIParameter param, boolean critical, int indent) { JNIType paramType = param.getType(), paramType64 = param.getType64(); if (paramType.isPrimitive() || isSystemClass(paramType)) return false; String iStr = String.valueOf(param.getParameter()); for (int j = 0; j < indent; j++) output("\t"); output("if (arg"); output(iStr); output(") if ((lparg"); output(iStr); output(" = "); boolean isCPP = getCPP(); if (paramType.isArray()) { JNIType componentType = paramType.getComponentType(); if (componentType.isPrimitive()) { if (critical) { if (isCPP) { output("("); output(componentType.getTypeSignature2(!paramType.equals(paramType64))); output("*)"); output("env->GetPrimitiveArrayCritical(arg"); } else { output("(*env)->GetPrimitiveArrayCritical(env, arg"); } output(iStr); output(", NULL)"); } else { if (isCPP) { output("env->Get"); } else { output("(*env)->Get"); } output(componentType.getTypeSignature1(!paramType.equals(paramType64))); if (isCPP) { output("ArrayElements(arg"); } else { output("ArrayElements(env, arg"); } output(iStr); output(", NULL)"); } } else { throw new Error("not done"); } } else if (paramType.isType("java.lang.String")) { if (param.getFlag(FLAG_UNICODE)) { if (isCPP) { output("env->GetStringChars(arg"); } else { output("(*env)->GetStringChars(env, arg"); } output(iStr); output(", NULL)"); } else { if (isCPP) { output("env->GetStringUTFChars(arg"); } else { output("(*env)->GetStringUTFChars(env, arg"); } output(iStr); output(", NULL)"); } } else { if (param.getFlag(FLAG_NO_IN)) { output("&_arg"); output(iStr); } else { output("get"); output(paramType.getSimpleName()); output("Fields(env, arg"); output(iStr); output(", &_arg"); output(iStr); output(")"); } } outputln(") == NULL) goto fail;"); return true; } void generateSetParameter(JNIParameter param, boolean critical) { JNIType paramType = param.getType(), paramType64 = param.getType64(); if (paramType.isPrimitive() || isSystemClass(paramType)) return; String iStr = String.valueOf(param.getParameter()); boolean isCPP = getCPP(); if (paramType.isArray()) { output("\tif (arg"); output(iStr); output(" && lparg"); output(iStr); output(") "); JNIType componentType = paramType.getComponentType(); if (componentType.isPrimitive()) { if (critical) { if (isCPP) { output("env->ReleasePrimitiveArrayCritical(arg"); } else { output("(*env)->ReleasePrimitiveArrayCritical(env, arg"); } output(iStr); } else { if (isCPP) { output("env->Release"); } else { output("(*env)->Release"); } output(componentType.getTypeSignature1(!paramType.equals(paramType64))); if (isCPP) { output("ArrayElements(arg"); } else { output("ArrayElements(env, arg"); } output(iStr); } output(", lparg"); output(iStr); output(", "); if (param.getFlag(FLAG_NO_OUT)) { output("JNI_ABORT"); } else { output("0"); } output(");"); } else { throw new Error("not done"); } outputln(); } else if (paramType.isType("java.lang.String")) { output("\tif (arg"); output(iStr); output(" && lparg"); output(iStr); output(") "); if (param.getFlag(FLAG_UNICODE)) { if (isCPP) { output("env->ReleaseStringChars(arg"); } else { output("(*env)->ReleaseStringChars(env, arg"); } } else { if (isCPP) { output("env->ReleaseStringUTFChars(arg"); } else { output("(*env)->ReleaseStringUTFChars(env, arg"); } } output(iStr); output(", lparg"); output(iStr); outputln(");"); } else { if (!param.getFlag(FLAG_NO_OUT)) { output("\tif (arg"); output(iStr); output(" && lparg"); output(iStr); output(") "); output("set"); output(paramType.getSimpleName()); output("Fields(env, arg"); output(iStr); output(", lparg"); output(iStr); outputln(");"); } } } void generateEnterExitMacro(JNIMethod method, String function, String function64, boolean enter) { if (!enterExitMacro) return; boolean tryCatch = method.getFlag(FLAG_TRYCATCH); if (!function.equals(function64)) { output("#ifndef "); output(JNI64); outputln(); } output("\t"); output(method.getDeclaringClass().getSimpleName()); output("_NATIVE_"); output(enter ? "ENTER" : "EXIT"); if (tryCatch) output(enter ? "_TRY" : "_CATCH"); output("(env, that, "); output(function); outputln("_FUNC);"); if (!function.equals(function64)) { outputln("#else"); output("\t"); output(method.getDeclaringClass().getSimpleName()); output("_NATIVE_"); output(enter ? "ENTER" : "EXIT"); if (tryCatch) output(enter ? "_TRY" : "_CATCH"); output("(env, that, "); output(function64); outputln("_FUNC);"); outputln("#endif"); } } boolean generateLocalVars(JNIMethod method, JNIParameter[] params, JNIType returnType, JNIType returnType64) { boolean needsReturn = enterExitMacro; for (int i = 0; i < params.length; i++) { JNIParameter param = params[i]; JNIType paramType = param.getType(), paramType64 = param.getType64(); if (paramType.isPrimitive() || isSystemClass(paramType)) continue; output("\t"); if (paramType.isArray()) { JNIType componentType = paramType.getComponentType(); if (componentType.isPrimitive()) { output(componentType.getTypeSignature2(!paramType.equals(paramType64))); output(" *lparg" + i); output("=NULL;"); } else { throw new Error("not done"); } } else if (paramType.isType("java.lang.String")) { if (param.getFlag(FLAG_UNICODE)) { output("const jchar *lparg" + i); } else { output("const char *lparg" + i); } output("= NULL;"); } else { if (param.getTypeClass().getFlag(Flags.FLAG_STRUCT)) { output("struct "); } output(paramType.getSimpleName()); output(" _arg" + i); if (param.getFlag(FLAG_INIT)) output("={0}"); output(", *lparg" + i); output("=NULL;"); } outputln(); needsReturn = true; } if (needsReturn) { if (!returnType.isType("void")) { output("\t"); output(returnType.getTypeSignature2(!returnType.equals(returnType64))); outputln(" rc = 0;"); } } return needsReturn; } boolean generateGetters(JNIMethod method, JNIParameter[] params) { boolean genFailTag = false; int criticalCount = 0; for (int i = 0; i < params.length; i++) { JNIParameter param = params[i]; if (!isCritical(param)) { genFailTag |= generateGetParameter(method, param, false, 1); } else { criticalCount++; } } if (criticalCount != 0) { outputln("#ifdef JNI_VERSION_1_2"); outputln("\tif (IS_JNI_1_2) {"); for (int i = 0; i < params.length; i++) { JNIParameter param = params[i]; if (isCritical(param)) { genFailTag |= generateGetParameter(method, param, true, 2); } } outputln("\t} else"); outputln("#endif"); outputln("\t{"); for (int i = 0; i < params.length; i++) { JNIParameter param = params[i]; if (isCritical(param)) { genFailTag |= generateGetParameter(method, param, false, 2); } } outputln("\t}"); } return genFailTag; } void generateSetters(JNIMethod method, JNIParameter[] params) { int criticalCount = 0; for (int i = params.length - 1; i >= 0; i--) { JNIParameter param = params[i]; if (isCritical(param)) { criticalCount++; } } if (criticalCount != 0) { outputln("#ifdef JNI_VERSION_1_2"); outputln("\tif (IS_JNI_1_2) {"); for (int i = params.length - 1; i >= 0; i--) { JNIParameter param = params[i]; if (isCritical(param)) { output("\t"); generateSetParameter(param, true); } } outputln("\t} else"); outputln("#endif"); outputln("\t{"); for (int i = params.length - 1; i >= 0; i--) { JNIParameter param = params[i]; if (isCritical(param)) { output("\t"); generateSetParameter(param, false); } } outputln("\t}"); } for (int i = params.length - 1; i >= 0; i--) { JNIParameter param = params[i]; if (!isCritical(param)) { generateSetParameter(param, false); } } } void generateDynamicFunctionCall(JNIMethod method, JNIParameter[] params, JNIType returnType, JNIType returnType64, boolean needsReturn) { outputln("/*"); generateFunctionCall(method, params, returnType, returnType64, needsReturn); outputln("*/"); outputln("\t{"); String name = method.getName(); if (name.startsWith("_")) name = name.substring(1); output("\t\t"); output(method.getDeclaringClass().getSimpleName()); output("_LOAD_FUNCTION(fp, "); output(name); outputln(")"); outputln("\t\tif (fp) {"); output("\t\t"); generateFunctionCallLeftSide(method, returnType, returnType64, needsReturn); output("(("); output(returnType.getTypeSignature2(!returnType.equals(returnType64))); output(" (CALLING_CONVENTION*)("); for (int i = 0; i < params.length; i++) { if (i != 0) output(", "); JNIParameter param = params[i]; String cast = param.getCast(); boolean isStruct = param.getFlag(FLAG_STRUCT); if (cast.length() > 2) { cast = cast.substring(1, cast.length() - 1); if (isStruct) { int index = cast.lastIndexOf('*'); if (index != -1) cast = cast.substring(0, index).trim(); } output(cast); } else { JNIType paramType = param.getType(), paramType64 = param.getType64(); output(paramType.getTypeSignature4(!paramType.equals(paramType64), isStruct)); } } output("))"); output("fp"); output(")"); generateFunctionCallRightSide(method, params, 0); output(";"); outputln(); outputln("\t\t}"); outputln("\t}"); } void generateFunctionCallLeftSide(JNIMethod method, JNIType returnType, JNIType returnType64, boolean needsReturn) { output("\t"); if (!returnType.isType("void")) { if (needsReturn) { output("rc = "); } else { output("return "); } output("("); output(returnType.getTypeSignature2(!returnType.equals(returnType64))); output(")"); } if (method.getFlag(FLAG_ADDRESS)) { output("&"); } if (method.getFlag(FLAG_JNI)) { boolean isCPP = getCPP(); output(isCPP ? "env->" : "(*env)->"); } } void generateFunctionCallRightSide(JNIMethod method, JNIParameter[] params, int paramStart) { if (!method.getFlag(FLAG_CONST)) { output("("); if (method.getFlag(FLAG_JNI)) { boolean isCPP = getCPP(); if (!isCPP) output("env, "); } for (int i = paramStart; i < params.length; i++) { JNIParameter param = params[i]; if (i != paramStart) output(", "); if (param.getFlag(FLAG_STRUCT)) output("*"); output(param.getCast()); if (param.getFlag(FLAG_OBJECT)) output("TO_OBJECT("); if (i == params.length - 1 && param.getFlag(FLAG_SENTINEL)) { output("NULL"); } else { JNIType paramType = param.getType(); if (!paramType.isPrimitive() && !isSystemClass(paramType)) output("lp"); output("arg" + i); } if (param.getFlag(FLAG_OBJECT)) output(")"); } output(")"); } } void generateFunctionCall(JNIMethod method, JNIParameter[] params, JNIType returnType, JNIType returnType64, boolean needsReturn) { String name = method.getName(); String copy = (String)method.getParam("copy"); boolean isCPP = getCPP(); boolean makeCopy = copy.length() != 0 && isCPP && !returnType.isType("void"); if (makeCopy) { output("\t"); output(copy); output(" temp = "); } else { generateFunctionCallLeftSide(method, returnType, returnType64, needsReturn); } int paramStart = 0; if (name.startsWith("_")) name = name.substring(1); boolean objc_struct = false; if (name.equals("objc_msgSend_stret") || name.equals("objc_msgSendSuper_stret")) objc_struct = true; if (objc_struct) { outputln("if (STRUCT_SIZE_LIMIT == 0) {"); output("\t\t"); } if (name.equalsIgnoreCase("call") || name.startsWith("callFunc")) { output("("); String cast = params[0].getCast(); if (cast.length() != 0 && !cast.equals("()")) { output(cast); } else { output("("); output(returnType.getTypeSignature2(!returnType.equals(returnType64))); output(" ("); output((String)method.getParam("convention")); output("*)())"); } output("arg0)"); paramStart = 1; } else if (name.startsWith("VtblCall") || name.startsWith("_VtblCall")) { output("(("); output(returnType.getTypeSignature2(!returnType.equals(returnType64))); output(" (STDMETHODCALLTYPE *)("); for (int i = 1; i < params.length; i++) { if (i != 1) output(", "); JNIParameter param = params[i]; JNIType paramType = param.getType(), paramType64 = param.getType64(); output(paramType.getTypeSignature4(!paramType.equals(paramType64), param.getFlag(FLAG_STRUCT))); } output("))(*("); JNIType paramType = params[1].getType(), paramType64 = params[1].getType64(); output(paramType.getTypeSignature4(!paramType.equals(paramType64), false)); output(" **)arg1)[arg0])"); paramStart = 1; } else if (method.getFlag(FLAG_CPP) || method.getFlag(FLAG_SETTER) || method.getFlag(FLAG_GETTER) || method.getFlag(FLAG_ADDER)) { if (method.getFlag(FLAG_OBJECT)) { output("TO_HANDLE("); } output("("); JNIParameter param = params[0]; if (param.getFlag(FLAG_STRUCT)) output("*"); String cast = param.getCast(); if (cast.length() != 0 && !cast.equals("()")) { output(cast); } if (param.getFlag(FLAG_OBJECT)) { output("TO_OBJECT("); } output("arg0"); if (param.getFlag(FLAG_OBJECT)) { output(")"); } output(")->"); String accessor = method.getAccessor(); if (accessor.length() != 0) { output(accessor); } else { int index = -1; if ((index = name.indexOf('_')) != -1) { output(name.substring(index + 1, name.length())); } else { output(name); } } paramStart = 1; } else if (method.getFlag(FLAG_GCNEW)) { output("TO_HANDLE(gcnew "); String accessor = method.getAccessor(); if (accessor.length() != 0) { output(accessor); } else { int index = -1; if ((index = name.indexOf('_')) != -1) { output(name.substring(index + 1)); } else { output(name); } } } else if (method.getFlag(FLAG_NEW)) { if (method.getFlag(FLAG_OBJECT)) { output("TO_HANDLE("); } output("new "); String accessor = method.getAccessor(); if (accessor.length() != 0) { output(accessor); } else { int index = -1; if ((index = name.indexOf('_')) != -1) { output(name.substring(0, index)); } else { output(name); } } } else if (method.getFlag(FLAG_DELETE)) { output("delete "); JNIParameter param = params[0]; String cast = param.getCast(); if (cast.length() != 0 && !cast.equals("()")) { output(cast); } else { output("("); output(name.substring(0, name.indexOf("_"))); output(" *)"); } outputln("arg0;"); return; } else { if (method.getFlag(FLAG_OBJECT)) { output("TO_HANDLE("); } if (method.getFlag(Flags.FLAG_CAST)) { output("(("); String returnCast = returnType.getTypeSignature2(!returnType.equals(returnType64)); if (name.equals("objc_msgSend_bool") && returnCast.equals("jboolean")) { returnCast = "BOOL"; } output(returnCast); output(" (*)("); for (int i = 0; i < params.length; i++) { if (i != 0) output(", "); JNIParameter param = params[i]; String cast = param.getCast(); if (cast != null && cast.length() != 0) { if (cast.startsWith("(")) cast = cast.substring(1); if (cast.endsWith(")")) cast = cast.substring(0, cast.length() - 1); output(cast); } else { JNIType paramType = param.getType(), paramType64 = param.getType64(); if (!(paramType.isPrimitive() || paramType.isArray())) { if (param.getTypeClass().getFlag(FLAG_STRUCT)) { output("struct "); } } output(paramType.getTypeSignature4(!paramType.equals(paramType64), param.getFlag(FLAG_STRUCT))); } } output("))"); } String accessor = method.getAccessor(); if (accessor.length() != 0) { output(accessor); } else { output(name); } if (method.getFlag(Flags.FLAG_CAST)) { output(")"); } } if ((method.getFlag(FLAG_SETTER) && params.length == 3) || (method.getFlag(FLAG_GETTER) && params.length == 2)) { output("[arg1]"); paramStart++; } if (method.getFlag(FLAG_SETTER)) output(" = "); if (method.getFlag(FLAG_ADDER)) output(" += "); if (!method.getFlag(FLAG_GETTER)) { generateFunctionCallRightSide(method, params, paramStart); } if (method.getFlag(FLAG_GCNEW) || method.getFlag(FLAG_OBJECT)) { output(")"); } output(";"); outputln(); if (makeCopy) { outputln("\t{"); output("\t\t"); output(copy); output("* copy = new "); output(copy); outputln("();"); outputln("\t\t*copy = temp;"); output("\t\trc = "); output("("); output(returnType.getTypeSignature2(!returnType.equals(returnType64))); output(")"); outputln("copy;"); outputln("\t}"); } if (objc_struct) { outputln("\t} else if (sizeof(_arg0) > STRUCT_SIZE_LIMIT) {"); generate_objc_msgSend_stret (method, params, name); generateFunctionCallRightSide(method, params, 1); outputln(";"); outputln("\t} else {"); generate_objc_msgSend_stret (method, params, name.substring(0, name.length() - "_stret".length())); generateFunctionCallRightSide(method, params, 1); outputln(";"); outputln("\t}"); } } void generate_objc_msgSend_stret (JNIMethod method, JNIParameter[] params, String func) { output("\t\t*lparg0 = (*("); JNIType paramType = params[0].getType(), paramType64 = params[0].getType64(); output(paramType.getTypeSignature4(!paramType.equals(paramType64), true)); output(" (*)("); for (int i = 1; i < params.length; i++) { if (i != 1) output(", "); JNIParameter param = params[i]; String cast = param.getCast(); if (cast != null && cast.length() != 0) { if (cast.startsWith("(")) cast = cast.substring(1); if (cast.endsWith(")")) cast = cast.substring(0, cast.length() - 1); output(cast); } else { paramType = param.getType(); paramType64 = param.getType64(); if (!(paramType.isPrimitive() || paramType.isArray())) { if (param.getTypeClass().getFlag(FLAG_STRUCT)) { output("struct "); } } output(paramType.getTypeSignature4(!paramType.equals(paramType64), param.getFlag(FLAG_STRUCT))); } } output("))"); output(func); output(")"); } void generateReturn(JNIMethod method, JNIType returnType, boolean needsReturn) { if (needsReturn && !returnType.isType("void")) { outputln("\treturn rc;"); } } void generateMemmove(JNIMethod method, String function, String function64, JNIParameter[] params) { generateEnterExitMacro(method, function, function64, true); output("\t"); boolean get = params[0].getType().isPrimitive(); String className = params[get ? 1 : 0].getType().getSimpleName(); output(get ? "if (arg1) get" : "if (arg0) set"); output(className); output(get ? "Fields(env, arg1, (" : "Fields(env, arg0, ("); output(className); output(get ? " *)arg0)" : " *)arg1)"); outputln(";"); generateEnterExitMacro(method, function, function64, false); } void generateFunctionBody(JNIMethod method, String function, String function64, JNIParameter[] params, JNIType returnType, JNIType returnType64) { outputln("{"); /* Custom GTK memmoves. */ String name = method.getName(); if (name.startsWith("_")) name = name.substring(1); boolean isMemove = (name.equals("memmove") || name.equals("MoveMemory")) && params.length == 2 && returnType.isType("void"); if (isMemove) { generateMemmove(method, function, function64, params); } else { boolean needsReturn = generateLocalVars(method, params, returnType, returnType64); generateEnterExitMacro(method, function, function64, true); boolean genFailTag = generateGetters(method, params); if (method.getFlag(FLAG_DYNAMIC)) { generateDynamicFunctionCall(method, params, returnType, returnType64, needsReturn); } else { generateFunctionCall(method, params, returnType, returnType64, needsReturn); } if (genFailTag) outputln("fail:"); generateSetters(method, params); generateEnterExitMacro(method, function, function64, false); generateReturn(method, returnType, needsReturn); } outputln("}"); } void generateFunctionPrototype(JNIMethod method, String function, JNIParameter[] params, JNIType returnType, JNIType returnType64, boolean singleLine) { output("JNIEXPORT "); output(returnType.getTypeSignature2(!returnType.equals(returnType64))); output(" JNICALL "); output(method.getDeclaringClass().getSimpleName()); output("_NATIVE("); output(function); if (singleLine) { output(")"); output("(JNIEnv *env, "); } else { outputln(")"); output("\t(JNIEnv *env, "); } if ((method.getModifiers() & Modifier.STATIC) != 0) { output("jclass"); } else { output("jobject"); } output(" that"); for (int i = 0; i < params.length; i++) { output(", "); JNIType paramType = params[i].getType(), paramType64 = params[i].getType64(); output(paramType.getTypeSignature2(!paramType.equals(paramType64))); output(" arg" + i); } output(")"); if (!singleLine) outputln(); } void generateSourceStart(String function, String function64) { if (function.equals(function64)) { output("#ifndef NO_"); outputln(function); } else { output("#if (!defined(NO_"); output(function); output(") && !defined("); output(JNI64); output(")) || (!defined(NO_"); output(function64); output(") && defined("); output(JNI64); outputln("))"); } } void generateSourceEnd(String function) { outputln("#endif"); } boolean isCritical(JNIParameter param) { JNIType paramType = param.getType(); return paramType.isArray() && paramType.getComponentType().isPrimitive() && param.getFlag(FLAG_CRITICAL); } boolean isSystemClass(JNIType type) { return type.isType("java.lang.Object") || type.isType("java.lang.Class") ; } }