blob: e79170a28a8b1c1872e01a91a995c15e6d86df04 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001import java.io.PrintStream;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002import java.util.ArrayList;
3import java.util.HashSet;
4import java.util.Iterator;
5import java.util.List;
6
Jack Palevichffac1ef2009-04-14 19:00:09 -07007public class JniCodeEmitter {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08008
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08009 static final boolean mUseCPlusPlus = true;
Jack Palevichffac1ef2009-04-14 19:00:09 -070010 protected boolean mUseContextPointer = true;
Jack Palevich427f5852009-04-15 19:13:17 -070011 protected boolean mUseStaticMethods = false;
Jack Palevichffac1ef2009-04-14 19:00:09 -070012 protected String mClassPathName;
13 protected ParameterChecker mChecker;
14 protected List<String> nativeRegistrations = new ArrayList<String>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080015 boolean needsExit;
Jack Palevichffac1ef2009-04-14 19:00:09 -070016 protected static String indent = " ";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017 HashSet<String> mFunctionsEmitted = new HashSet<String>();
18
Jack Palevichffac1ef2009-04-14 19:00:09 -070019 public static String getJniName(JType jType) {
20 String jniName = "";
21 if (jType.isClass()) {
22 return "L" + jType.getBaseType() + ";";
23 } else if (jType.isArray()) {
24 jniName = "[";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080025 }
Jack Palevichffac1ef2009-04-14 19:00:09 -070026
27 String baseType = jType.getBaseType();
28 if (baseType.equals("int")) {
29 jniName += "I";
30 } else if (baseType.equals("float")) {
31 jniName += "F";
32 } else if (baseType.equals("boolean")) {
33 jniName += "Z";
34 } else if (baseType.equals("short")) {
35 jniName += "S";
36 } else if (baseType.equals("long")) {
37 jniName += "L";
38 } else if (baseType.equals("byte")) {
39 jniName += "B";
Jack Palevich50d0b142009-11-19 16:34:55 +080040 } else if (baseType.equals("String")) {
41 jniName += "Ljava/lang/String;";
42 } else if (baseType.equals("void")) {
43 // nothing.
44 } else {
45 throw new RuntimeException("Uknown primitive basetype " + baseType);
Jack Palevichffac1ef2009-04-14 19:00:09 -070046 }
47 return jniName;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080048 }
49
Jack Palevichffac1ef2009-04-14 19:00:09 -070050
51 public void emitCode(CFunc cfunc, String original,
52 PrintStream javaInterfaceStream,
53 PrintStream javaImplStream,
54 PrintStream cStream) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080055 JFunc jfunc;
56 String signature;
57 boolean duplicate;
Jack Palevich6cbca502009-04-13 16:22:25 -070058
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080059 if (cfunc.hasTypedPointerArg()) {
60 jfunc = JFunc.convert(cfunc, true);
61
62 // Don't emit duplicate functions
63 // These may appear because they are defined in multiple
64 // Java interfaces (e.g., GL11/GL11ExtensionPack)
65 signature = jfunc.toString();
66 duplicate = false;
67 if (mFunctionsEmitted.contains(signature)) {
68 duplicate = true;
69 } else {
70 mFunctionsEmitted.add(signature);
71 }
72
73 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070074 emitNativeDeclaration(jfunc, javaImplStream);
75 emitJavaCode(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080076 }
Jack Palevich427f5852009-04-15 19:13:17 -070077 if (javaInterfaceStream != null) {
78 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
79 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080080 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070081 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080082 }
83 }
84
85 jfunc = JFunc.convert(cfunc, false);
86
87 signature = jfunc.toString();
88 duplicate = false;
89 if (mFunctionsEmitted.contains(signature)) {
90 duplicate = true;
91 } else {
92 mFunctionsEmitted.add(signature);
93 }
94
95 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -070096 emitNativeDeclaration(jfunc, javaImplStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080097 }
Jack Palevich427f5852009-04-15 19:13:17 -070098 if (javaInterfaceStream != null) {
99 emitJavaInterfaceCode(jfunc, javaInterfaceStream);
100 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800101 if (!duplicate) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700102 emitJavaCode(jfunc, javaImplStream);
103 emitJniCode(jfunc, cStream);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800104 }
105 }
106
107 public void emitNativeDeclaration(JFunc jfunc, PrintStream out) {
108 out.println(" // C function " + jfunc.getCFunc().getOriginal());
109 out.println();
110
111 emitFunction(jfunc, out, true, false);
112 }
113
114 public void emitJavaInterfaceCode(JFunc jfunc, PrintStream out) {
115 emitFunction(jfunc, out, false, true);
116 }
117
118 public void emitJavaCode(JFunc jfunc, PrintStream out) {
119 emitFunction(jfunc, out, false, false);
120 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700121
Jack Palevich66089a32009-12-08 15:43:51 +0800122 boolean isPointerFunc(JFunc jfunc) {
123 String name = jfunc.getName();
124 return (name.endsWith("Pointer") || name.endsWith("PointerOES"))
125 && jfunc.getCFunc().hasPointerArg();
126 }
127
Jack Palevichffac1ef2009-04-14 19:00:09 -0700128 void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800129 boolean isVoid = jfunc.getType().isVoid();
Jack Palevich66089a32009-12-08 15:43:51 +0800130 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800131
132 if (!isVoid) {
133 out.println(iii +
134 jfunc.getType() + " _returnValue;");
135 }
136 out.println(iii +
137 (isVoid ? "" : "_returnValue = ") +
138 jfunc.getName() +
139 (isPointerFunc ? "Bounds" : "" ) +
140 "(");
Jack Palevich6cbca502009-04-13 16:22:25 -0700141
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800142 int numArgs = jfunc.getNumArgs();
143 for (int i = 0; i < numArgs; i++) {
144 String argName = jfunc.getArgName(i);
145 JType argType = jfunc.getArgType(i);
146
147 if (grabArray && argType.isTypedBuffer()) {
148 String typeName = argType.getBaseType();
149 typeName = typeName.substring(9, typeName.length() - 6);
150 out.println(iii + indent + "get" + typeName + "Array(" + argName + "),");
Jack Palevich6cbca502009-04-13 16:22:25 -0700151 out.print(iii + indent + "getOffset(" + argName + ")");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800152 } else {
153 out.print(iii + indent + argName);
154 }
155 if (i == numArgs - 1) {
156 if (isPointerFunc) {
157 out.println(",");
158 out.println(iii + indent + argName + ".remaining()");
159 } else {
160 out.println();
161 }
162 } else {
163 out.println(",");
164 }
165 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700166
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800167 out.println(iii + ");");
168 }
169
Jack Palevichffac1ef2009-04-14 19:00:09 -0700170 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
171 String iii) {
172 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
173 "offset", "_remaining", iii);
174 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800175
Jack Palevichffac1ef2009-04-14 19:00:09 -0700176 void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
177 String offset, String remaining, String iii) {
178 out.println(iii + " default:");
179 out.println(iii + " _needed = 0;");
180 out.println(iii + " break;");
181 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800182
Jack Palevichffac1ef2009-04-14 19:00:09 -0700183 out.println(iii + "if (" + remaining + " < _needed) {");
184 if (emitExceptionCheck) {
185 out.println(iii + indent + "_exception = 1;");
186 }
187 out.println(iii + indent +
188 (mUseCPlusPlus ? "_env" : "(*_env)") +
189 "->ThrowNew(" +
190 (mUseCPlusPlus ? "" : "_env, ") +
191 "IAEClass, " +
192 "\"" +
193 (isBuffer ?
194 "remaining()" : "length - " + offset) +
195 " < needed\");");
196 out.println(iii + indent + "goto exit;");
197 needsExit = true;
198 out.println(iii + "}");
199 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800200
201 boolean isNullAllowed(CFunc cfunc) {
202 String[] checks = mChecker.getChecks(cfunc.getName());
203 int index = 1;
204 if (checks != null) {
205 while (index < checks.length) {
206 if (checks[index].equals("return")) {
207 index += 2;
208 } else if (checks[index].startsWith("check")) {
209 index += 3;
210 } else if (checks[index].equals("ifcheck")) {
211 index += 5;
212 } else if (checks[index].equals("unsupported")) {
213 index += 1;
214 } else if (checks[index].equals("nullAllowed")) {
215 return true;
216 } else {
217 System.out.println("Error: unknown keyword \"" +
218 checks[index] + "\"");
219 System.exit(0);
220 }
221 }
222 }
223 return false;
224 }
225
226 String getErrorReturnValue(CFunc cfunc) {
227 CType returnType = cfunc.getType();
228 boolean isVoid = returnType.isVoid();
229 if (isVoid) {
230 return null;
231 }
232
233 String[] checks = mChecker.getChecks(cfunc.getName());
234
235 int index = 1;
236 if (checks != null) {
237 while (index < checks.length) {
238 if (checks[index].equals("return")) {
239 return checks[index + 1];
240 } else if (checks[index].startsWith("check")) {
241 index += 3;
242 } else if (checks[index].equals("ifcheck")) {
243 index += 5;
244 } else if (checks[index].equals("unsupported")) {
245 index += 1;
246 } else if (checks[index].equals("nullAllowed")) {
247 index += 1;
248 } else {
249 System.out.println("Error: unknown keyword \"" +
250 checks[index] + "\"");
251 System.exit(0);
252 }
253 }
254 }
255
256 return null;
257 }
258
259 boolean isUnsupportedFunc(CFunc cfunc) {
260 String[] checks = mChecker.getChecks(cfunc.getName());
261 int index = 1;
262 if (checks != null) {
263 while (index < checks.length) {
264 if (checks[index].equals("unsupported")) {
265 return true;
266 } else if (checks[index].equals("return")) {
267 index += 2;
268 } else if (checks[index].startsWith("check")) {
269 index += 3;
270 } else if (checks[index].equals("ifcheck")) {
271 index += 5;
272 } else if (checks[index].equals("nullAllowed")) {
273 index += 1;
274 } else {
275 System.out.println("Error: unknown keyword \"" +
276 checks[index] + "\"");
277 System.exit(0);
278 }
279 }
280 }
281 return false;
282 }
283
284 void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
Jack Palevichffac1ef2009-04-14 19:00:09 -0700285 boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800286
Jack Palevichffac1ef2009-04-14 19:00:09 -0700287 String[] checks = mChecker.getChecks(cfunc.getName());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800288
Jack Palevichffac1ef2009-04-14 19:00:09 -0700289 boolean lastWasIfcheck = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800290
Jack Palevichffac1ef2009-04-14 19:00:09 -0700291 int index = 1;
292 if (checks != null) {
293 while (index < checks.length) {
294 if (checks[index].startsWith("check")) {
295 if (lastWasIfcheck) {
296 printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
297 offset, remaining, iii);
298 }
299 lastWasIfcheck = false;
300 if (cname != null && !cname.equals(checks[index + 1])) {
301 index += 3;
302 continue;
303 }
304 out.println(iii + "if (" + remaining + " < " +
305 checks[index + 2] +
306 ") {");
307 if (emitExceptionCheck) {
308 out.println(iii + indent + "_exception = 1;");
309 }
310 String exceptionClassName = "IAEClass";
311 // If the "check" keyword was of the form
312 // "check_<class name>", use the class name in the
313 // exception to be thrown
314 int underscore = checks[index].indexOf('_');
315 if (underscore >= 0) {
316 exceptionClassName = checks[index].substring(underscore + 1) + "Class";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800317 }
Jack Palevichffac1ef2009-04-14 19:00:09 -0700318 out.println(iii + indent +
319 (mUseCPlusPlus ? "_env" : "(*_env)") +
320 "->ThrowNew(" +
321 (mUseCPlusPlus ? "" : "_env, ") +
322 exceptionClassName + ", " +
323 "\"" +
324 (isBuffer ?
325 "remaining()" : "length - " + offset) +
326 " < " + checks[index + 2] +
327 "\");");
328
329 out.println(iii + indent + "goto exit;");
330 needsExit = true;
331 out.println(iii + "}");
332
333 index += 3;
334 } else if (checks[index].equals("ifcheck")) {
335 String[] matches = checks[index + 4].split(",");
336
337 if (!lastWasIfcheck) {
338 out.println(iii + "int _needed;");
339 out.println(iii +
340 "switch (" +
341 checks[index + 3] +
342 ") {");
343 }
344
345 for (int i = 0; i < matches.length; i++) {
346 out.println("#if defined(" + matches[i] + ")");
347 out.println(iii +
348 " case " +
349 matches[i] +
350 ":");
351 out.println("#endif // defined(" + matches[i] + ")");
352 }
353 out.println(iii +
354 " _needed = " +
355 checks[index + 2] +
356 ";");
357 out.println(iii +
358 " break;");
359
360 lastWasIfcheck = true;
361 index += 5;
362 } else if (checks[index].equals("return")) {
363 // ignore
364 index += 2;
365 } else if (checks[index].equals("unsupported")) {
366 // ignore
367 index += 1;
368 } else if (checks[index].equals("nullAllowed")) {
369 // ignore
370 index += 1;
371 } else {
372 System.out.println("Error: unknown keyword \"" +
373 checks[index] + "\"");
374 System.exit(0);
375 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800376 }
Jack Palevichffac1ef2009-04-14 19:00:09 -0700377 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800378
Jack Palevichffac1ef2009-04-14 19:00:09 -0700379 if (lastWasIfcheck) {
380 printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800381 }
382 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800383
Jack Palevichffac1ef2009-04-14 19:00:09 -0700384 boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800385 if (nonPrimitiveArgs.size() > 0) {
386 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
387 int idx = nonPrimitiveArgs.get(i).intValue();
388 int cIndex = jfunc.getArgCIndex(idx);
389 if (jfunc.getArgType(idx).isArray()) {
390 if (!cfunc.getArgType(cIndex).isConst()) {
391 return true;
392 }
393 } else if (jfunc.getArgType(idx).isBuffer()) {
394 if (!cfunc.getArgType(cIndex).isConst()) {
395 return true;
396 }
397 }
398 }
399 }
400
401 return false;
402 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700403
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800404 /**
405 * Emit a function in several variants:
406 *
407 * if nativeDecl: public native <returntype> func(args);
408 *
409 * if !nativeDecl:
410 * if interfaceDecl: public <returntype> func(args);
411 * if !interfaceDecl: public <returntype> func(args) { body }
412 */
Jack Palevichffac1ef2009-04-14 19:00:09 -0700413 void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
Jack Palevich66089a32009-12-08 15:43:51 +0800414 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800415
416 if (!nativeDecl && !interfaceDecl && !isPointerFunc) {
417 // If it's not a pointer function, we've already emitted it
418 // with nativeDecl == true
419 return;
420 }
421
Jack Palevich427f5852009-04-15 19:13:17 -0700422 String maybeStatic = mUseStaticMethods ? "static " : "";
423
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800424 if (isPointerFunc) {
425 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700426 (nativeDecl ? "private " + maybeStatic +"native " :
427 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800428 jfunc.getType() + " " +
429 jfunc.getName() +
430 (nativeDecl ? "Bounds" : "") +
431 "(");
432 } else {
433 out.println(indent +
Jack Palevich427f5852009-04-15 19:13:17 -0700434 (nativeDecl ? "public " + maybeStatic +"native " :
435 (interfaceDecl ? "" : "public ") + maybeStatic) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800436 jfunc.getType() + " " +
437 jfunc.getName() +
438 "(");
439 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700440
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800441 int numArgs = jfunc.getNumArgs();
442 for (int i = 0; i < numArgs; i++) {
443 String argName = jfunc.getArgName(i);
444 JType argType = jfunc.getArgType(i);
Jack Palevich6cbca502009-04-13 16:22:25 -0700445
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800446 out.print(indent + indent + argType + " " + argName);
447 if (i == numArgs - 1) {
448 if (isPointerFunc && nativeDecl) {
449 out.println(",");
450 out.println(indent + indent + "int remaining");
451 } else {
452 out.println();
453 }
454 } else {
455 out.println(",");
456 }
457 }
458
459 if (nativeDecl || interfaceDecl) {
460 out.println(indent + ");");
461 } else {
462 out.println(indent + ") {");
463
464 String iii = indent + indent;
465
Jack Palevich46d25a32009-05-07 18:28:29 -0700466 // emitBoundsChecks(jfunc, out, iii);
467 emitFunctionCall(jfunc, out, iii, false);
468
469 // Set the pointer after we call the native code, so that if
470 // the native code throws an exception we don't modify the
471 // pointer. We assume that the native code is written so that
472 // if an exception is thrown, then the underlying glXXXPointer
473 // function will not have been called.
474
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800475 String fname = jfunc.getName();
476 if (isPointerFunc) {
477 // TODO - deal with VBO variants
478 if (fname.equals("glColorPointer")) {
479 out.println(iii + "if ((size == 4) &&");
480 out.println(iii + " ((type == GL_FLOAT) ||");
481 out.println(iii + " (type == GL_UNSIGNED_BYTE) ||");
482 out.println(iii + " (type == GL_FIXED)) &&");
483 out.println(iii + " (stride >= 0)) {");
484 out.println(iii + indent + "_colorPointer = pointer;");
485 out.println(iii + "}");
486 } else if (fname.equals("glNormalPointer")) {
487 out.println(iii + "if (((type == GL_FLOAT) ||");
488 out.println(iii + " (type == GL_BYTE) ||");
489 out.println(iii + " (type == GL_SHORT) ||");
490 out.println(iii + " (type == GL_FIXED)) &&");
491 out.println(iii + " (stride >= 0)) {");
492 out.println(iii + indent + "_normalPointer = pointer;");
493 out.println(iii + "}");
494 } else if (fname.equals("glTexCoordPointer")) {
495 out.println(iii + "if (((size == 2) ||");
496 out.println(iii + " (size == 3) ||");
497 out.println(iii + " (size == 4)) &&");
498 out.println(iii + " ((type == GL_FLOAT) ||");
499 out.println(iii + " (type == GL_BYTE) ||");
500 out.println(iii + " (type == GL_SHORT) ||");
501 out.println(iii + " (type == GL_FIXED)) &&");
502 out.println(iii + " (stride >= 0)) {");
503 out.println(iii + indent + "_texCoordPointer = pointer;");
504 out.println(iii + "}");
505 } else if (fname.equals("glVertexPointer")) {
506 out.println(iii + "if (((size == 2) ||");
507 out.println(iii + " (size == 3) ||");
508 out.println(iii + " (size == 4)) &&");
509 out.println(iii + " ((type == GL_FLOAT) ||");
510 out.println(iii + " (type == GL_BYTE) ||");
511 out.println(iii + " (type == GL_SHORT) ||");
512 out.println(iii + " (type == GL_FIXED)) &&");
513 out.println(iii + " (stride >= 0)) {");
514 out.println(iii + indent + "_vertexPointer = pointer;");
515 out.println(iii + "}");
Jack Palevich66089a32009-12-08 15:43:51 +0800516 } else if (fname.equals("glPointSizePointerOES")) {
517 out.println(iii + "if (((type == GL_FLOAT) ||");
518 out.println(iii + " (type == GL_FIXED)) &&");
519 out.println(iii + " (stride >= 0)) {");
520 out.println(iii + indent + "_pointSizePointerOES = pointer;");
521 out.println(iii + "}");
522 } else if (fname.equals("glMatrixIndexPointerOES")) {
523 out.println(iii + "if (((size == 2) ||");
524 out.println(iii + " (size == 3) ||");
525 out.println(iii + " (size == 4)) &&");
526 out.println(iii + " ((type == GL_FLOAT) ||");
527 out.println(iii + " (type == GL_BYTE) ||");
528 out.println(iii + " (type == GL_SHORT) ||");
529 out.println(iii + " (type == GL_FIXED)) &&");
530 out.println(iii + " (stride >= 0)) {");
531 out.println(iii + indent + "_matrixIndexPointerOES = pointer;");
532 out.println(iii + "}");
533 } else if (fname.equals("glWeightPointer")) {
534 out.println(iii + "if (((size == 2) ||");
535 out.println(iii + " (size == 3) ||");
536 out.println(iii + " (size == 4)) &&");
537 out.println(iii + " ((type == GL_FLOAT) ||");
538 out.println(iii + " (type == GL_BYTE) ||");
539 out.println(iii + " (type == GL_SHORT) ||");
540 out.println(iii + " (type == GL_FIXED)) &&");
541 out.println(iii + " (stride >= 0)) {");
542 out.println(iii + indent + "_weightPointerOES = pointer;");
543 out.println(iii + "}");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800544 }
545 }
546
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800547 boolean isVoid = jfunc.getType().isVoid();
548
549 if (!isVoid) {
550 out.println(indent + indent + "return _returnValue;");
551 }
552 out.println(indent + "}");
553 }
554 out.println();
555 }
556
Jack Palevichffac1ef2009-04-14 19:00:09 -0700557 public void addNativeRegistration(String s) {
558 nativeRegistrations.add(s);
559 }
560
Jack Palevich427f5852009-04-15 19:13:17 -0700561 public void emitNativeRegistration(String registrationFunctionName,
562 PrintStream cStream) {
Jack Palevichffac1ef2009-04-14 19:00:09 -0700563 cStream.println("static const char *classPathName = \"" +
564 mClassPathName +
565 "\";");
566 cStream.println();
567
568 cStream.println("static JNINativeMethod methods[] = {");
569
570 cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
571
572 Iterator<String> i = nativeRegistrations.iterator();
573 while (i.hasNext()) {
574 cStream.println(i.next());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800575 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700576
Jack Palevichffac1ef2009-04-14 19:00:09 -0700577 cStream.println("};");
578 cStream.println();
579
580
Jack Palevich427f5852009-04-15 19:13:17 -0700581 cStream.println("int " + registrationFunctionName + "(JNIEnv *_env)");
Jack Palevichffac1ef2009-04-14 19:00:09 -0700582 cStream.println("{");
583 cStream.println(indent +
584 "int err;");
585
586 cStream.println(indent +
587 "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
588
589 cStream.println(indent + "return err;");
590 cStream.println("}");
591 }
592
593 public JniCodeEmitter() {
594 super();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800595 }
596
597 String getJniType(JType jType) {
598 if (jType.isVoid()) {
599 return "void";
600 }
601
602 String baseType = jType.getBaseType();
603 if (jType.isPrimitive()) {
604 if (baseType.equals("String")) {
605 return "jstring";
606 } else {
607 return "j" + baseType;
608 }
609 } else if (jType.isArray()) {
610 return "j" + baseType + "Array";
611 } else {
612 return "jobject";
613 }
614 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700615
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800616 String getJniMangledName(String name) {
617 name = name.replaceAll("_", "_1");
618 name = name.replaceAll(";", "_2");
619 name = name.replaceAll("\\[", "_3");
620 return name;
621 }
622
623 public void emitJniCode(JFunc jfunc, PrintStream out) {
624 CFunc cfunc = jfunc.getCFunc();
Jack Palevich6cbca502009-04-13 16:22:25 -0700625
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800626 // Emit comment identifying original C function
627 //
628 // Example:
629 //
630 // /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
631 //
632 out.println("/* " + cfunc.getOriginal() + " */");
633
634 // Emit JNI signature (name)
635 //
636 // Example:
637 //
638 // void
639 // android_glClipPlanef__I_3FI
640 //
641
642 String outName = "android_" + jfunc.getName();
Jack Palevich66089a32009-12-08 15:43:51 +0800643 boolean isPointerFunc = isPointerFunc(jfunc);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800644 boolean isVBOPointerFunc = (outName.endsWith("Pointer") ||
Jack Palevich66089a32009-12-08 15:43:51 +0800645 outName.endsWith("PointerOES") ||
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800646 outName.endsWith("DrawElements")) &&
647 !jfunc.getCFunc().hasPointerArg();
648 if (isPointerFunc) {
649 outName += "Bounds";
650 }
651
652 out.print("static ");
653 out.println(getJniType(jfunc.getType()));
654 out.print(outName);
655
656 String rsignature = getJniName(jfunc.getType());
657
658 String signature = "";
659 int numArgs = jfunc.getNumArgs();
660 for (int i = 0; i < numArgs; i++) {
661 JType argType = jfunc.getArgType(i);
662 signature += getJniName(argType);
663 }
664 if (isPointerFunc) {
665 signature += "I";
666 }
667
668 // Append signature to function name
Jack Palevich50d0b142009-11-19 16:34:55 +0800669 String sig = getJniMangledName(signature).replace('.', '_').replace('/', '_');
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800670 out.print("__" + sig);
671 outName += "__" + sig;
Jack Palevich6cbca502009-04-13 16:22:25 -0700672
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800673 signature = signature.replace('.', '/');
674 rsignature = rsignature.replace('.', '/');
Jack Palevich6cbca502009-04-13 16:22:25 -0700675
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800676 out.println();
677 if (rsignature.length() == 0) {
678 rsignature = "V";
679 }
680
681 String s = "{\"" +
682 jfunc.getName() +
683 (isPointerFunc ? "Bounds" : "") +
684 "\", \"(" + signature +")" +
685 rsignature +
686 "\", (void *) " +
687 outName +
688 " },";
689 nativeRegistrations.add(s);
690
691 List<Integer> nonPrimitiveArgs = new ArrayList<Integer>();
Jack Palevich50d0b142009-11-19 16:34:55 +0800692 List<Integer> stringArgs = new ArrayList<Integer>();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800693 int numBufferArgs = 0;
694 List<String> bufferArgNames = new ArrayList<String>();
695
696 // Emit JNI signature (arguments)
697 //
698 // Example:
699 //
700 // (JNIEnv *_env, jobject this, jint plane, jfloatArray equation_ref, jint offset) {
701 //
702 out.print(" (JNIEnv *_env, jobject _this");
703 for (int i = 0; i < numArgs; i++) {
704 out.print(", ");
705 JType argType = jfunc.getArgType(i);
706 String suffix;
707 if (!argType.isPrimitive()) {
708 if (argType.isArray()) {
709 suffix = "_ref";
710 } else {
711 suffix = "_buf";
712 }
713 nonPrimitiveArgs.add(new Integer(i));
714 if (jfunc.getArgType(i).isBuffer()) {
715 int cIndex = jfunc.getArgCIndex(i);
716 String cname = cfunc.getArgName(cIndex);
717 bufferArgNames.add(cname);
718 numBufferArgs++;
719 }
720 } else {
721 suffix = "";
722 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800723 if (argType.isString()) {
724 stringArgs.add(new Integer(i));
725 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800726
727 out.print(getJniType(argType) + " " + jfunc.getArgName(i) + suffix);
728 }
729 if (isPointerFunc) {
730 out.print(", jint remaining");
731 }
732 out.println(") {");
Jack Palevich6cbca502009-04-13 16:22:25 -0700733
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800734 int numArrays = 0;
735 int numBuffers = 0;
Jack Palevich50d0b142009-11-19 16:34:55 +0800736 int numStrings = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800737 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
738 int idx = nonPrimitiveArgs.get(i).intValue();
Jack Palevich50d0b142009-11-19 16:34:55 +0800739 JType argType = jfunc.getArgType(idx);
740 if (argType.isArray()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800741 ++numArrays;
742 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800743 if (argType.isBuffer()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800744 ++numBuffers;
745 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800746 if (argType.isString()) {
747 ++numStrings;
748 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800749 }
750
751 // Emit method body
752
753 // Emit local variable declarations for _exception and _returnValue
754 //
755 // Example:
756 //
757 // android::gl::ogles_context_t *ctx;
Jack Palevich6cbca502009-04-13 16:22:25 -0700758 //
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800759 // jint _exception;
760 // GLenum _returnValue;
761 //
762 CType returnType = cfunc.getType();
763 boolean isVoid = returnType.isVoid();
764
765 boolean isUnsupported = isUnsupportedFunc(cfunc);
766 if (isUnsupported) {
767 out.println(indent +
768 "_env->ThrowNew(UOEClass,");
769 out.println(indent +
770 " \"" + cfunc.getName() + "\");");
771 if (!isVoid) {
772 String retval = getErrorReturnValue(cfunc);
773 out.println(indent + "return " + retval + ";");
774 }
775 out.println("}");
776 out.println();
777 return;
778 }
779
780 if (mUseContextPointer) {
781 out.println(indent +
782 "android::gl::ogles_context_t *ctx = getContext(_env, _this);");
783 }
784
Jack Palevich50d0b142009-11-19 16:34:55 +0800785 boolean initializeReturnValue = stringArgs.size() > 0;
786
787 boolean emitExceptionCheck = (numArrays > 0 || numBuffers > 0 || numStrings > 0) &&
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800788 hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs);
789 // mChecker.getChecks(cfunc.getName()) != null
790
791 // Emit an _exeption variable if there will be error checks
792 if (emitExceptionCheck) {
793 out.println(indent + "jint _exception = 0;");
794 }
795
796 // Emit a single _array or multiple _XXXArray variables
797 if (numBufferArgs == 1) {
798 out.println(indent + "jarray _array = (jarray) 0;");
799 } else {
800 for (int i = 0; i < numBufferArgs; i++) {
801 out.println(indent + "jarray _" + bufferArgNames.get(i) +
802 "Array = (jarray) 0;");
803 }
804 }
805 if (!isVoid) {
806 String retval = getErrorReturnValue(cfunc);
807 if (retval != null) {
808 out.println(indent + returnType.getDeclaration() +
809 " _returnValue = " + retval + ";");
Jack Palevich50d0b142009-11-19 16:34:55 +0800810 } else if (initializeReturnValue) {
811 out.println(indent + returnType.getDeclaration() +
812 " _returnValue = 0;");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800813 } else {
814 out.println(indent + returnType.getDeclaration() +
815 " _returnValue;");
816 }
817 }
818
819 // Emit local variable declarations for pointer arguments
820 //
821 // Example:
822 //
823 // GLfixed *eqn_base;
824 // GLfixed *eqn;
825 //
826 String offset = "offset";
827 String remaining = "_remaining";
828 if (nonPrimitiveArgs.size() > 0) {
829 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
830 int idx = nonPrimitiveArgs.get(i).intValue();
831 int cIndex = jfunc.getArgCIndex(idx);
832 String cname = cfunc.getArgName(cIndex);
833
834 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
835 String decl = type.getDeclaration();
836 if (jfunc.getArgType(idx).isArray()) {
837 out.println(indent +
838 decl +
839 (decl.endsWith("*") ? "" : " ") +
840 jfunc.getArgName(idx) +
841 "_base = (" + decl + ") 0;");
842 }
Jack Palevich50d0b142009-11-19 16:34:55 +0800843 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800844 "_" + cname + "Remaining";
845 out.println(indent +
846 "jint " + remaining + ";");
847 out.println(indent +
848 decl +
849 (decl.endsWith("*") ? "" : " ") +
Jack Palevich6cbca502009-04-13 16:22:25 -0700850 jfunc.getArgName(idx) +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800851 " = (" + decl + ") 0;");
852 }
853
854 out.println();
855 }
856
Jack Palevich50d0b142009-11-19 16:34:55 +0800857 // Emit local variable declaration for strings
858 if (stringArgs.size() > 0) {
859 for (int i = 0; i < stringArgs.size(); i++) {
860 int idx = stringArgs.get(i).intValue();
861 int cIndex = jfunc.getArgCIndex(idx);
862 String cname = cfunc.getArgName(cIndex);
863
864 out.println(indent + "const char* _native" + cname + " = 0;");
865 }
866
867 out.println();
868 }
869
870 // Null pointer checks and GetStringUTFChars
871 if (stringArgs.size() > 0) {
872 for (int i = 0; i < stringArgs.size(); i++) {
873 int idx = stringArgs.get(i).intValue();
874 int cIndex = jfunc.getArgCIndex(idx);
875 String cname = cfunc.getArgName(cIndex);
876
877 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
878 String decl = type.getDeclaration();
879 out.println(indent + "if (!" + cname + ") {");
880 out.println(indent + " _env->ThrowNew(IAEClass, \"" + cname + " == null\");");
881 out.println(indent + " goto exit;");
882 needsExit = true;
883 out.println(indent + "}");
884
885 out.println(indent + "_native" + cname + " = _env->GetStringUTFChars(" + cname + ", 0);");
886 }
887
888 out.println();
889 }
890
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800891 // Emit 'GetPrimitiveArrayCritical' for arrays
892 // Emit 'GetPointer' calls for Buffer pointers
893 int bufArgIdx = 0;
894 if (nonPrimitiveArgs.size() > 0) {
895 for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
896 int idx = nonPrimitiveArgs.get(i).intValue();
897 int cIndex = jfunc.getArgCIndex(idx);
Jack Palevich6cbca502009-04-13 16:22:25 -0700898
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800899 String cname = cfunc.getArgName(cIndex);
900 offset = numArrays <= 1 ? "offset" :
901 cname + "Offset";
Jack Palevich50d0b142009-11-19 16:34:55 +0800902 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800903 "_" + cname + "Remaining";
904
905 if (jfunc.getArgType(idx).isArray()) {
906 out.println(indent +
Jack Palevich6cbca502009-04-13 16:22:25 -0700907 "if (!" +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800908 cname +
909 "_ref) {");
910 if (emitExceptionCheck) {
911 out.println(indent + indent + "_exception = 1;");
912 }
913 out.println(indent + " " +
914 (mUseCPlusPlus ? "_env" : "(*_env)") +
915 "->ThrowNew(" +
916 (mUseCPlusPlus ? "" : "_env, ") +
917 "IAEClass, " +
918 "\"" + cname +
919 " == null\");");
920 out.println(indent + " goto exit;");
921 needsExit = true;
922 out.println(indent + "}");
923
924 out.println(indent + "if (" + offset + " < 0) {");
925 if (emitExceptionCheck) {
926 out.println(indent + indent + "_exception = 1;");
927 }
928 out.println(indent + " " +
929 (mUseCPlusPlus ? "_env" : "(*_env)") +
930 "->ThrowNew(" +
931 (mUseCPlusPlus ? "" : "_env, ") +
932 "IAEClass, " +
933 "\"" + offset + " < 0\");");
934 out.println(indent + " goto exit;");
935 needsExit = true;
936 out.println(indent + "}");
937
938 out.println(indent + remaining + " = " +
Jack Palevich6cbca502009-04-13 16:22:25 -0700939 (mUseCPlusPlus ? "_env" : "(*_env)") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800940 "->GetArrayLength(" +
941 (mUseCPlusPlus ? "" : "_env, ") +
942 cname + "_ref) - " + offset + ";");
943
944 emitNativeBoundsChecks(cfunc, cname, out, false,
945 emitExceptionCheck,
946 offset, remaining, " ");
947
948 out.println(indent +
949 cname +
950 "_base = (" +
951 cfunc.getArgType(cIndex).getDeclaration() +
952 ")");
953 out.println(indent + " " +
954 (mUseCPlusPlus ? "_env" : "(*_env)") +
955 "->GetPrimitiveArrayCritical(" +
Jack Palevich6cbca502009-04-13 16:22:25 -0700956 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800957 jfunc.getArgName(idx) +
958 "_ref, (jboolean *)0);");
959 out.println(indent +
960 cname + " = " + cname + "_base + " + offset +
961 ";");
962 out.println();
963 } else {
964 String array = numBufferArgs <= 1 ? "_array" :
965 "_" + bufferArgNames.get(bufArgIdx++) + "Array";
966
Jack Palevich46d25a32009-05-07 18:28:29 -0700967 boolean nullAllowed = isNullAllowed(cfunc) || isPointerFunc;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800968 if (nullAllowed) {
969 out.println(indent + "if (" + cname + "_buf) {");
970 out.print(indent);
971 }
Jack Palevich6cbca502009-04-13 16:22:25 -0700972
Jack Palevich46d25a32009-05-07 18:28:29 -0700973 if (isPointerFunc) {
974 out.println(indent +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800975 cname +
976 " = (" +
977 cfunc.getArgType(cIndex).getDeclaration() +
Jack Palevich6eedc8d2009-05-15 18:13:34 -0700978 ") getDirectBufferPointer(_env, " +
Jack Palevich46d25a32009-05-07 18:28:29 -0700979 cname + "_buf);");
980 String iii = " ";
Jack Palevich5afdc872009-10-21 11:02:44 -0700981 out.println(iii + indent + "if ( ! " + cname + " ) {");
Jack Palevich46d25a32009-05-07 18:28:29 -0700982 out.println(iii + iii + indent + "return;");
983 out.println(iii + indent + "}");
984 } else {
985 out.println(indent +
986 cname +
987 " = (" +
988 cfunc.getArgType(cIndex).getDeclaration() +
989 ")getPointer(_env, " +
990 cname +
991 "_buf, &" + array + ", &" + remaining +
992 ");");
993 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800994
Jack Palevich5afdc872009-10-21 11:02:44 -0700995 emitNativeBoundsChecks(cfunc, cname, out, true,
996 emitExceptionCheck,
997 offset, remaining, nullAllowed ? " " : " ");
998
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800999 if (nullAllowed) {
1000 out.println(indent + "}");
1001 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001002 }
1003 }
1004 }
1005
1006 if (!isVoid) {
1007 out.print(indent + "_returnValue = ");
1008 } else {
1009 out.print(indent);
1010 }
1011 String name = cfunc.getName();
1012
1013 if (mUseContextPointer) {
1014 name = name.substring(2, name.length()); // Strip off 'gl' prefix
1015 name = name.substring(0, 1).toLowerCase() +
1016 name.substring(1, name.length());
1017 out.print("ctx->procs.");
1018 }
Jack Palevich6cbca502009-04-13 16:22:25 -07001019
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001020 out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
1021
Jack Palevich6cbca502009-04-13 16:22:25 -07001022 numArgs = cfunc.getNumArgs();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001023 if (numArgs == 0) {
1024 if (mUseContextPointer) {
1025 out.println("ctx);");
1026 } else {
1027 out.println(");");
1028 }
1029 } else {
1030 if (mUseContextPointer) {
1031 out.println("ctx,");
1032 } else {
1033 out.println();
1034 }
1035 for (int i = 0; i < numArgs; i++) {
1036 String typecast;
1037 if (i == numArgs - 1 && isVBOPointerFunc) {
1038 typecast = "const GLvoid *";
1039 } else {
1040 typecast = cfunc.getArgType(i).getDeclaration();
1041 }
1042 out.print(indent + indent +
1043 "(" +
1044 typecast +
Jack Palevich50d0b142009-11-19 16:34:55 +08001045 ")");
1046 if (cfunc.getArgType(i).isConstCharPointer()) {
1047 out.print("_native");
1048 }
1049 out.print(cfunc.getArgName(i));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001050
1051 if (i == numArgs - 1) {
1052 if (isPointerFunc) {
1053 out.println(",");
1054 out.println(indent + indent + "(GLsizei)remaining");
1055 } else {
1056 out.println();
1057 }
1058 } else {
1059 out.println(",");
1060 }
1061 }
1062 out.println(indent + ");");
1063 }
1064
1065 if (needsExit) {
1066 out.println();
1067 out.println("exit:");
1068 needsExit = false;
1069 }
1070
1071 bufArgIdx = 0;
1072 if (nonPrimitiveArgs.size() > 0) {
1073 for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
1074 int idx = nonPrimitiveArgs.get(i).intValue();
1075
1076 int cIndex = jfunc.getArgCIndex(idx);
1077 if (jfunc.getArgType(idx).isArray()) {
Jack Palevich6cbca502009-04-13 16:22:25 -07001078
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001079 // If the argument is 'const', GL will not write to it.
1080 // In this case, we can use the 'JNI_ABORT' flag to avoid
1081 // the need to write back to the Java array
1082 out.println(indent +
1083 "if (" + jfunc.getArgName(idx) + "_base) {");
1084 out.println(indent + indent +
1085 (mUseCPlusPlus ? "_env" : "(*_env)") +
1086 "->ReleasePrimitiveArrayCritical(" +
Jack Palevich6cbca502009-04-13 16:22:25 -07001087 (mUseCPlusPlus ? "" : "_env, ") +
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001088 jfunc.getArgName(idx) + "_ref, " +
1089 cfunc.getArgName(cIndex) +
1090 "_base,");
1091 out.println(indent + indent + indent +
1092 (cfunc.getArgType(cIndex).isConst() ?
1093 "JNI_ABORT" :
1094 "_exception ? JNI_ABORT: 0") +
1095 ");");
1096 out.println(indent + "}");
1097 } else if (jfunc.getArgType(idx).isBuffer()) {
Jack Palevich46d25a32009-05-07 18:28:29 -07001098 if (! isPointerFunc) {
1099 String array = numBufferArgs <= 1 ? "_array" :
1100 "_" + bufferArgNames.get(bufArgIdx++) + "Array";
1101 out.println(indent + "if (" + array + ") {");
1102 out.println(indent + indent +
1103 "releasePointer(_env, " + array + ", " +
1104 cfunc.getArgName(cIndex) +
1105 ", " +
1106 (cfunc.getArgType(cIndex).isConst() ?
1107 "JNI_FALSE" : "_exception ? JNI_FALSE :" +
1108 " JNI_TRUE") +
1109 ");");
1110 out.println(indent + "}");
1111 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001112 }
1113 }
1114 }
1115
Jack Palevich50d0b142009-11-19 16:34:55 +08001116 // Emit local variable declaration for strings
1117 if (stringArgs.size() > 0) {
1118 for (int i = 0; i < stringArgs.size(); i++) {
1119 int idx = stringArgs.get(i).intValue();
1120 int cIndex = jfunc.getArgCIndex(idx);
1121 String cname = cfunc.getArgName(cIndex);
1122
1123 out.println(indent + "if (_native" + cname + ") {");
1124 out.println(indent + " _env->ReleaseStringUTFChars(" + cname + ", _native" + cname + ");");
1125 out.println(indent + "}");
1126 }
1127
1128 out.println();
1129 }
1130
1131
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001132 if (!isVoid) {
1133 out.println(indent + "return _returnValue;");
1134 }
1135
1136 out.println("}");
1137 out.println();
1138 }
1139
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001140}