src/share/classes/com/sun/tools/javah/LLNI.java

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26
aoqi@0 27 package com.sun.tools.javah;
aoqi@0 28
aoqi@0 29 import java.io.OutputStream;
aoqi@0 30 import java.io.PrintWriter;
aoqi@0 31 import java.util.ArrayList;
aoqi@0 32 import java.util.HashSet;
aoqi@0 33 import java.util.List;
aoqi@0 34
aoqi@0 35 import java.util.Set;
aoqi@0 36 import javax.lang.model.element.Element;
aoqi@0 37 import javax.lang.model.element.ExecutableElement;
aoqi@0 38 import javax.lang.model.element.Modifier;
aoqi@0 39 import javax.lang.model.element.Name;
aoqi@0 40 import javax.lang.model.element.TypeElement;
aoqi@0 41 import javax.lang.model.element.VariableElement;
aoqi@0 42 import javax.lang.model.type.ArrayType;
aoqi@0 43 import javax.lang.model.type.PrimitiveType;
aoqi@0 44 import javax.lang.model.type.TypeKind;
aoqi@0 45 import javax.lang.model.type.TypeMirror;
aoqi@0 46 import javax.lang.model.type.TypeVisitor;
aoqi@0 47 import javax.lang.model.util.ElementFilter;
aoqi@0 48 import javax.lang.model.util.SimpleTypeVisitor8;
aoqi@0 49
aoqi@0 50 /*
aoqi@0 51 * <p><b>This is NOT part of any supported API.
aoqi@0 52 * If you write code that depends on this, you do so at your own
aoqi@0 53 * risk. This code and its internal interfaces are subject to change
aoqi@0 54 * or deletion without notice.</b></p>
aoqi@0 55 *
aoqi@0 56 * @author Sucheta Dambalkar(Revised)
aoqi@0 57 */
aoqi@0 58 public class LLNI extends Gen {
aoqi@0 59
aoqi@0 60 protected final char innerDelim = '$'; /* For inner classes */
aoqi@0 61 protected Set<String> doneHandleTypes;
aoqi@0 62 List<VariableElement> fields;
aoqi@0 63 List<ExecutableElement> methods;
aoqi@0 64 private boolean doubleAlign;
aoqi@0 65 private int padFieldNum = 0;
aoqi@0 66
aoqi@0 67 LLNI(boolean doubleAlign, Util util) {
aoqi@0 68 super(util);
aoqi@0 69 this.doubleAlign = doubleAlign;
aoqi@0 70 }
aoqi@0 71
aoqi@0 72 protected String getIncludes() {
aoqi@0 73 return "";
aoqi@0 74 }
aoqi@0 75
aoqi@0 76 protected void write(OutputStream o, TypeElement clazz) throws Util.Exit {
aoqi@0 77 try {
aoqi@0 78 String cname = mangleClassName(clazz.getQualifiedName().toString());
aoqi@0 79 PrintWriter pw = wrapWriter(o);
aoqi@0 80 fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
aoqi@0 81 methods = ElementFilter.methodsIn(clazz.getEnclosedElements());
aoqi@0 82 generateDeclsForClass(pw, clazz, cname);
aoqi@0 83 // FIXME check if errors occurred on the PrintWriter and throw exception if so
aoqi@0 84 } catch (TypeSignature.SignatureException e) {
aoqi@0 85 util.error("llni.sigerror", e.getMessage());
aoqi@0 86 }
aoqi@0 87 }
aoqi@0 88
aoqi@0 89 protected void generateDeclsForClass(PrintWriter pw,
aoqi@0 90 TypeElement clazz, String cname)
aoqi@0 91 throws TypeSignature.SignatureException, Util.Exit {
aoqi@0 92 doneHandleTypes = new HashSet<String>();
aoqi@0 93 /* The following handle types are predefined in "typedefs.h". Suppress
aoqi@0 94 inclusion in the output by generating them "into the blue" here. */
aoqi@0 95 genHandleType(null, "java.lang.Class");
aoqi@0 96 genHandleType(null, "java.lang.ClassLoader");
aoqi@0 97 genHandleType(null, "java.lang.Object");
aoqi@0 98 genHandleType(null, "java.lang.String");
aoqi@0 99 genHandleType(null, "java.lang.Thread");
aoqi@0 100 genHandleType(null, "java.lang.ThreadGroup");
aoqi@0 101 genHandleType(null, "java.lang.Throwable");
aoqi@0 102
aoqi@0 103 pw.println("/* LLNI Header for class " + clazz.getQualifiedName() + " */" + lineSep);
aoqi@0 104 pw.println("#ifndef _Included_" + cname);
aoqi@0 105 pw.println("#define _Included_" + cname);
aoqi@0 106 pw.println("#include \"typedefs.h\"");
aoqi@0 107 pw.println("#include \"llni.h\"");
aoqi@0 108 pw.println("#include \"jni.h\"" + lineSep);
aoqi@0 109
aoqi@0 110 forwardDecls(pw, clazz);
aoqi@0 111 structSectionForClass(pw, clazz, cname);
aoqi@0 112 methodSectionForClass(pw, clazz, cname);
aoqi@0 113 pw.println("#endif");
aoqi@0 114 }
aoqi@0 115
aoqi@0 116 protected void genHandleType(PrintWriter pw, String clazzname) {
aoqi@0 117 String cname = mangleClassName(clazzname);
aoqi@0 118 if (!doneHandleTypes.contains(cname)) {
aoqi@0 119 doneHandleTypes.add(cname);
aoqi@0 120 if (pw != null) {
aoqi@0 121 pw.println("#ifndef DEFINED_" + cname);
aoqi@0 122 pw.println(" #define DEFINED_" + cname);
aoqi@0 123 pw.println(" GEN_HANDLE_TYPES(" + cname + ");");
aoqi@0 124 pw.println("#endif" + lineSep);
aoqi@0 125 }
aoqi@0 126 }
aoqi@0 127 }
aoqi@0 128
aoqi@0 129 protected String mangleClassName(String s) {
aoqi@0 130 return s.replace('.', '_')
aoqi@0 131 .replace('/', '_')
aoqi@0 132 .replace(innerDelim, '_');
aoqi@0 133 }
aoqi@0 134
aoqi@0 135 protected void forwardDecls(PrintWriter pw, TypeElement clazz)
aoqi@0 136 throws TypeSignature.SignatureException {
aoqi@0 137 TypeElement object = elems.getTypeElement("java.lang.Object");
aoqi@0 138 if (clazz.equals(object))
aoqi@0 139 return;
aoqi@0 140
aoqi@0 141 genHandleType(pw, clazz.getQualifiedName().toString());
aoqi@0 142 TypeElement superClass = (TypeElement) (types.asElement(clazz.getSuperclass()));
aoqi@0 143
aoqi@0 144 if (superClass != null) {
aoqi@0 145 String superClassName = superClass.getQualifiedName().toString();
aoqi@0 146 forwardDecls(pw, superClass);
aoqi@0 147 }
aoqi@0 148
aoqi@0 149 for (VariableElement field: fields) {
aoqi@0 150
aoqi@0 151 if (!field.getModifiers().contains(Modifier.STATIC)) {
aoqi@0 152 TypeMirror t = types.erasure(field.asType());
aoqi@0 153 TypeSignature newTypeSig = new TypeSignature(elems);
aoqi@0 154 String tname = newTypeSig.qualifiedTypeName(t);
aoqi@0 155 String sig = newTypeSig.getTypeSignature(tname);
aoqi@0 156
aoqi@0 157 if (sig.charAt(0) != '[')
aoqi@0 158 forwardDeclsFromSig(pw, sig);
aoqi@0 159 }
aoqi@0 160 }
aoqi@0 161
aoqi@0 162 for (ExecutableElement method: methods) {
aoqi@0 163
aoqi@0 164 if (method.getModifiers().contains(Modifier.NATIVE)) {
aoqi@0 165 TypeMirror retType = types.erasure(method.getReturnType());
aoqi@0 166 String typesig = signature(method);
aoqi@0 167 TypeSignature newTypeSig = new TypeSignature(elems);
aoqi@0 168 String sig = newTypeSig.getTypeSignature(typesig, retType);
aoqi@0 169
aoqi@0 170 if (sig.charAt(0) != '[')
aoqi@0 171 forwardDeclsFromSig(pw, sig);
aoqi@0 172
aoqi@0 173 }
aoqi@0 174 }
aoqi@0 175 }
aoqi@0 176
aoqi@0 177 protected void forwardDeclsFromSig(PrintWriter pw, String sig) {
aoqi@0 178 int len = sig.length();
aoqi@0 179 int i = sig.charAt(0) == '(' ? 1 : 0;
aoqi@0 180
aoqi@0 181 /* Skip the initial "(". */
aoqi@0 182 while (i < len) {
aoqi@0 183 if (sig.charAt(i) == 'L') {
aoqi@0 184 int j = i + 1;
aoqi@0 185 while (sig.charAt(j) != ';') j++;
aoqi@0 186 genHandleType(pw, sig.substring(i + 1, j));
aoqi@0 187 i = j + 1;
aoqi@0 188 } else {
aoqi@0 189 i++;
aoqi@0 190 }
aoqi@0 191 }
aoqi@0 192 }
aoqi@0 193
aoqi@0 194 protected void structSectionForClass(PrintWriter pw,
aoqi@0 195 TypeElement jclazz, String cname) {
aoqi@0 196
aoqi@0 197 String jname = jclazz.getQualifiedName().toString();
aoqi@0 198
aoqi@0 199 if (cname.equals("java_lang_Object")) {
aoqi@0 200 pw.println("/* struct java_lang_Object is defined in typedefs.h. */");
aoqi@0 201 pw.println();
aoqi@0 202 return;
aoqi@0 203 }
aoqi@0 204 pw.println("#if !defined(__i386)");
aoqi@0 205 pw.println("#pragma pack(4)");
aoqi@0 206 pw.println("#endif");
aoqi@0 207 pw.println();
aoqi@0 208 pw.println("struct " + cname + " {");
aoqi@0 209 pw.println(" ObjHeader h;");
aoqi@0 210 pw.print(fieldDefs(jclazz, cname));
aoqi@0 211
aoqi@0 212 if (jname.equals("java.lang.Class"))
aoqi@0 213 pw.println(" Class *LLNI_mask(cClass);" +
aoqi@0 214 " /* Fake field; don't access (see oobj.h) */");
aoqi@0 215 pw.println("};" + lineSep + lineSep + "#pragma pack()");
aoqi@0 216 pw.println();
aoqi@0 217 return;
aoqi@0 218 }
aoqi@0 219
aoqi@0 220 private static class FieldDefsRes {
aoqi@0 221 public String className; /* Name of the current class. */
aoqi@0 222 public FieldDefsRes parent;
aoqi@0 223 public String s;
aoqi@0 224 public int byteSize;
aoqi@0 225 public boolean bottomMost;
aoqi@0 226 public boolean printedOne = false;
aoqi@0 227
aoqi@0 228 FieldDefsRes(TypeElement clazz, FieldDefsRes parent, boolean bottomMost) {
aoqi@0 229 this.className = clazz.getQualifiedName().toString();
aoqi@0 230 this.parent = parent;
aoqi@0 231 this.bottomMost = bottomMost;
aoqi@0 232 int byteSize = 0;
aoqi@0 233 if (parent == null) this.s = "";
aoqi@0 234 else this.s = parent.s;
aoqi@0 235 }
aoqi@0 236 }
aoqi@0 237
aoqi@0 238 /* Returns "true" iff added a field. */
aoqi@0 239 private boolean doField(FieldDefsRes res, VariableElement field,
aoqi@0 240 String cname, boolean padWord) {
aoqi@0 241
aoqi@0 242 String fieldDef = addStructMember(field, cname, padWord);
aoqi@0 243 if (fieldDef != null) {
aoqi@0 244 if (!res.printedOne) { /* add separator */
aoqi@0 245 if (res.bottomMost) {
aoqi@0 246 if (res.s.length() != 0)
aoqi@0 247 res.s = res.s + " /* local members: */" + lineSep;
aoqi@0 248 } else {
aoqi@0 249 res.s = res.s + " /* inherited members from " +
aoqi@0 250 res.className + ": */" + lineSep;
aoqi@0 251 }
aoqi@0 252 res.printedOne = true;
aoqi@0 253 }
aoqi@0 254 res.s = res.s + fieldDef;
aoqi@0 255 return true;
aoqi@0 256 }
aoqi@0 257
aoqi@0 258 // Otherwise.
aoqi@0 259 return false;
aoqi@0 260 }
aoqi@0 261
aoqi@0 262 private int doTwoWordFields(FieldDefsRes res, TypeElement clazz,
aoqi@0 263 int offset, String cname, boolean padWord) {
aoqi@0 264 boolean first = true;
aoqi@0 265 List<VariableElement> fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
aoqi@0 266
aoqi@0 267 for (VariableElement field: fields) {
aoqi@0 268 TypeKind tk = field.asType().getKind();
aoqi@0 269 boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE);
aoqi@0 270 if (twoWords && doField(res, field, cname, first && padWord)) {
aoqi@0 271 offset += 8; first = false;
aoqi@0 272 }
aoqi@0 273 }
aoqi@0 274 return offset;
aoqi@0 275 }
aoqi@0 276
aoqi@0 277 String fieldDefs(TypeElement clazz, String cname) {
aoqi@0 278 FieldDefsRes res = fieldDefs(clazz, cname, true);
aoqi@0 279 return res.s;
aoqi@0 280 }
aoqi@0 281
aoqi@0 282 FieldDefsRes fieldDefs(TypeElement clazz, String cname,
aoqi@0 283 boolean bottomMost){
aoqi@0 284 FieldDefsRes res;
aoqi@0 285 int offset;
aoqi@0 286 boolean didTwoWordFields = false;
aoqi@0 287
aoqi@0 288 TypeElement superclazz = (TypeElement) types.asElement(clazz.getSuperclass());
aoqi@0 289
aoqi@0 290 if (superclazz != null) {
aoqi@0 291 String supername = superclazz.getQualifiedName().toString();
aoqi@0 292 res = new FieldDefsRes(clazz,
aoqi@0 293 fieldDefs(superclazz, cname, false),
aoqi@0 294 bottomMost);
aoqi@0 295 offset = res.parent.byteSize;
aoqi@0 296 } else {
aoqi@0 297 res = new FieldDefsRes(clazz, null, bottomMost);
aoqi@0 298 offset = 0;
aoqi@0 299 }
aoqi@0 300
aoqi@0 301 List<VariableElement> fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
aoqi@0 302
aoqi@0 303 for (VariableElement field: fields) {
aoqi@0 304
aoqi@0 305 if (doubleAlign && !didTwoWordFields && (offset % 8) == 0) {
aoqi@0 306 offset = doTwoWordFields(res, clazz, offset, cname, false);
aoqi@0 307 didTwoWordFields = true;
aoqi@0 308 }
aoqi@0 309
aoqi@0 310 TypeKind tk = field.asType().getKind();
aoqi@0 311 boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE);
aoqi@0 312
aoqi@0 313 if (!doubleAlign || !twoWords) {
aoqi@0 314 if (doField(res, field, cname, false)) offset += 4;
aoqi@0 315 }
aoqi@0 316
aoqi@0 317 }
aoqi@0 318
aoqi@0 319 if (doubleAlign && !didTwoWordFields) {
aoqi@0 320 if ((offset % 8) != 0) offset += 4;
aoqi@0 321 offset = doTwoWordFields(res, clazz, offset, cname, true);
aoqi@0 322 }
aoqi@0 323
aoqi@0 324 res.byteSize = offset;
aoqi@0 325 return res;
aoqi@0 326 }
aoqi@0 327
aoqi@0 328 /* OVERRIDE: This method handles instance fields */
aoqi@0 329 protected String addStructMember(VariableElement member, String cname,
aoqi@0 330 boolean padWord) {
aoqi@0 331 String res = null;
aoqi@0 332
aoqi@0 333 if (member.getModifiers().contains(Modifier.STATIC)) {
aoqi@0 334 res = addStaticStructMember(member, cname);
aoqi@0 335 // if (res == null) /* JNI didn't handle it, print comment. */
aoqi@0 336 // res = " /* Inaccessible static: " + member + " */" + lineSep;
aoqi@0 337 } else {
aoqi@0 338 TypeMirror mt = types.erasure(member.asType());
aoqi@0 339 if (padWord) res = " java_int padWord" + padFieldNum++ + ";" + lineSep;
aoqi@0 340 res = " " + llniType(mt, false, false) + " " + llniFieldName(member);
aoqi@0 341 if (isLongOrDouble(mt)) res = res + "[2]";
aoqi@0 342 res = res + ";" + lineSep;
aoqi@0 343 }
aoqi@0 344 return res;
aoqi@0 345 }
aoqi@0 346
aoqi@0 347 static private final boolean isWindows =
aoqi@0 348 System.getProperty("os.name").startsWith("Windows");
aoqi@0 349
aoqi@0 350 /*
aoqi@0 351 * This method only handles static final fields.
aoqi@0 352 */
aoqi@0 353 protected String addStaticStructMember(VariableElement field, String cname) {
aoqi@0 354 String res = null;
aoqi@0 355 Object exp = null;
aoqi@0 356
aoqi@0 357 if (!field.getModifiers().contains(Modifier.STATIC))
aoqi@0 358 return res;
aoqi@0 359 if (!field.getModifiers().contains(Modifier.FINAL))
aoqi@0 360 return res;
aoqi@0 361
aoqi@0 362 exp = field.getConstantValue();
aoqi@0 363
aoqi@0 364 if (exp != null) {
aoqi@0 365 /* Constant. */
aoqi@0 366
aoqi@0 367 String cn = cname + "_" + field.getSimpleName();
aoqi@0 368 String suffix = null;
aoqi@0 369 long val = 0;
aoqi@0 370 /* Can only handle int, long, float, and double fields. */
aoqi@0 371 if (exp instanceof Byte
aoqi@0 372 || exp instanceof Short
aoqi@0 373 || exp instanceof Integer) {
aoqi@0 374 suffix = "L";
aoqi@0 375 val = ((Number)exp).intValue();
aoqi@0 376 }
aoqi@0 377 else if (exp instanceof Long) {
aoqi@0 378 // Visual C++ supports the i64 suffix, not LL
aoqi@0 379 suffix = isWindows ? "i64" : "LL";
aoqi@0 380 val = ((Long)exp).longValue();
aoqi@0 381 }
aoqi@0 382 else if (exp instanceof Float) suffix = "f";
aoqi@0 383 else if (exp instanceof Double) suffix = "";
aoqi@0 384 else if (exp instanceof Character) {
aoqi@0 385 suffix = "L";
aoqi@0 386 Character ch = (Character) exp;
aoqi@0 387 val = ((int) ch) & 0xffff;
aoqi@0 388 }
aoqi@0 389 if (suffix != null) {
aoqi@0 390 // Some compilers will generate a spurious warning
aoqi@0 391 // for the integer constants for Integer.MIN_VALUE
aoqi@0 392 // and Long.MIN_VALUE so we handle them specially.
aoqi@0 393 if ((suffix.equals("L") && (val == Integer.MIN_VALUE)) ||
aoqi@0 394 (suffix.equals("LL") && (val == Long.MIN_VALUE))) {
aoqi@0 395 res = " #undef " + cn + lineSep
aoqi@0 396 + " #define " + cn
aoqi@0 397 + " (" + (val + 1) + suffix + "-1)" + lineSep;
aoqi@0 398 } else if (suffix.equals("L") || suffix.endsWith("LL")) {
aoqi@0 399 res = " #undef " + cn + lineSep
aoqi@0 400 + " #define " + cn + " " + val + suffix + lineSep;
aoqi@0 401 } else {
aoqi@0 402 res = " #undef " + cn + lineSep
aoqi@0 403 + " #define " + cn + " " + exp + suffix + lineSep;
aoqi@0 404 }
aoqi@0 405 }
aoqi@0 406 }
aoqi@0 407 return res;
aoqi@0 408 }
aoqi@0 409
aoqi@0 410 protected void methodSectionForClass(PrintWriter pw,
aoqi@0 411 TypeElement clazz, String cname)
aoqi@0 412 throws TypeSignature.SignatureException, Util.Exit {
aoqi@0 413 String methods = methodDecls(clazz, cname);
aoqi@0 414
aoqi@0 415 if (methods.length() != 0) {
aoqi@0 416 pw.println("/* Native method declarations: */" + lineSep);
aoqi@0 417 pw.println("#ifdef __cplusplus");
aoqi@0 418 pw.println("extern \"C\" {");
aoqi@0 419 pw.println("#endif" + lineSep);
aoqi@0 420 pw.println(methods);
aoqi@0 421 pw.println("#ifdef __cplusplus");
aoqi@0 422 pw.println("}");
aoqi@0 423 pw.println("#endif");
aoqi@0 424 }
aoqi@0 425 }
aoqi@0 426
aoqi@0 427 protected String methodDecls(TypeElement clazz, String cname)
aoqi@0 428 throws TypeSignature.SignatureException, Util.Exit {
aoqi@0 429
aoqi@0 430 String res = "";
aoqi@0 431 for (ExecutableElement method: methods) {
aoqi@0 432 if (method.getModifiers().contains(Modifier.NATIVE))
aoqi@0 433 res = res + methodDecl(method, clazz, cname);
aoqi@0 434 }
aoqi@0 435 return res;
aoqi@0 436 }
aoqi@0 437
aoqi@0 438 protected String methodDecl(ExecutableElement method,
aoqi@0 439 TypeElement clazz, String cname)
aoqi@0 440 throws TypeSignature.SignatureException, Util.Exit {
aoqi@0 441 String res = null;
aoqi@0 442
aoqi@0 443 TypeMirror retType = types.erasure(method.getReturnType());
aoqi@0 444 String typesig = signature(method);
aoqi@0 445 TypeSignature newTypeSig = new TypeSignature(elems);
aoqi@0 446 String sig = newTypeSig.getTypeSignature(typesig, retType);
aoqi@0 447 boolean longName = needLongName(method, clazz);
aoqi@0 448
aoqi@0 449 if (sig.charAt(0) != '(')
aoqi@0 450 util.error("invalid.method.signature", sig);
aoqi@0 451
aoqi@0 452
aoqi@0 453 res = "JNIEXPORT " + jniType(retType) + " JNICALL" + lineSep + jniMethodName(method, cname, longName)
aoqi@0 454 + "(JNIEnv *, " + cRcvrDecl(method, cname);
aoqi@0 455 List<? extends VariableElement> params = method.getParameters();
aoqi@0 456 List<TypeMirror> argTypes = new ArrayList<TypeMirror>();
aoqi@0 457 for (VariableElement p: params){
aoqi@0 458 argTypes.add(types.erasure(p.asType()));
aoqi@0 459 }
aoqi@0 460
aoqi@0 461 /* It would have been nice to include the argument names in the
aoqi@0 462 declaration, but there seems to be a bug in the "BinaryField"
aoqi@0 463 class, causing the getArguments() method to return "null" for
aoqi@0 464 most (non-constructor) methods. */
aoqi@0 465 for (TypeMirror argType: argTypes)
aoqi@0 466 res = res + ", " + jniType(argType);
aoqi@0 467 res = res + ");" + lineSep;
aoqi@0 468 return res;
aoqi@0 469 }
aoqi@0 470
aoqi@0 471 protected final boolean needLongName(ExecutableElement method,
aoqi@0 472 TypeElement clazz) {
aoqi@0 473 Name methodName = method.getSimpleName();
aoqi@0 474 for (ExecutableElement memberMethod: methods) {
aoqi@0 475 if ((memberMethod != method) &&
aoqi@0 476 memberMethod.getModifiers().contains(Modifier.NATIVE) &&
aoqi@0 477 (methodName.equals(memberMethod.getSimpleName())))
aoqi@0 478 return true;
aoqi@0 479 }
aoqi@0 480 return false;
aoqi@0 481 }
aoqi@0 482
aoqi@0 483 protected final String jniMethodName(ExecutableElement method, String cname,
aoqi@0 484 boolean longName)
aoqi@0 485 throws TypeSignature.SignatureException {
aoqi@0 486 String res = "Java_" + cname + "_" + method.getSimpleName();
aoqi@0 487
aoqi@0 488 if (longName) {
aoqi@0 489 TypeMirror mType = types.erasure(method.getReturnType());
aoqi@0 490 List<? extends VariableElement> params = method.getParameters();
aoqi@0 491 List<TypeMirror> argTypes = new ArrayList<TypeMirror>();
aoqi@0 492 for (VariableElement param: params) {
aoqi@0 493 argTypes.add(types.erasure(param.asType()));
aoqi@0 494 }
aoqi@0 495
aoqi@0 496 res = res + "__";
aoqi@0 497 for (TypeMirror t: argTypes) {
aoqi@0 498 String tname = t.toString();
aoqi@0 499 TypeSignature newTypeSig = new TypeSignature(elems);
aoqi@0 500 String sig = newTypeSig.getTypeSignature(tname);
aoqi@0 501 res = res + nameToIdentifier(sig);
aoqi@0 502 }
aoqi@0 503 }
aoqi@0 504 return res;
aoqi@0 505 }
aoqi@0 506
aoqi@0 507 // copied from JNI.java
aoqi@0 508 protected final String jniType(TypeMirror t) throws Util.Exit {
aoqi@0 509 TypeElement throwable = elems.getTypeElement("java.lang.Throwable");
aoqi@0 510 TypeElement jClass = elems.getTypeElement("java.lang.Class");
aoqi@0 511 TypeElement jString = elems.getTypeElement("java.lang.String");
aoqi@0 512 Element tclassDoc = types.asElement(t);
aoqi@0 513
aoqi@0 514 switch (t.getKind()) {
aoqi@0 515 case ARRAY: {
aoqi@0 516 TypeMirror ct = ((ArrayType) t).getComponentType();
aoqi@0 517 switch (ct.getKind()) {
aoqi@0 518 case BOOLEAN: return "jbooleanArray";
aoqi@0 519 case BYTE: return "jbyteArray";
aoqi@0 520 case CHAR: return "jcharArray";
aoqi@0 521 case SHORT: return "jshortArray";
aoqi@0 522 case INT: return "jintArray";
aoqi@0 523 case LONG: return "jlongArray";
aoqi@0 524 case FLOAT: return "jfloatArray";
aoqi@0 525 case DOUBLE: return "jdoubleArray";
aoqi@0 526 case ARRAY:
aoqi@0 527 case DECLARED: return "jobjectArray";
aoqi@0 528 default: throw new Error(ct.toString());
aoqi@0 529 }
aoqi@0 530 }
aoqi@0 531
aoqi@0 532 case VOID: return "void";
aoqi@0 533 case BOOLEAN: return "jboolean";
aoqi@0 534 case BYTE: return "jbyte";
aoqi@0 535 case CHAR: return "jchar";
aoqi@0 536 case SHORT: return "jshort";
aoqi@0 537 case INT: return "jint";
aoqi@0 538 case LONG: return "jlong";
aoqi@0 539 case FLOAT: return "jfloat";
aoqi@0 540 case DOUBLE: return "jdouble";
aoqi@0 541
aoqi@0 542 case DECLARED: {
aoqi@0 543 if (tclassDoc.equals(jString))
aoqi@0 544 return "jstring";
aoqi@0 545 else if (types.isAssignable(t, throwable.asType()))
aoqi@0 546 return "jthrowable";
aoqi@0 547 else if (types.isAssignable(t, jClass.asType()))
aoqi@0 548 return "jclass";
aoqi@0 549 else
aoqi@0 550 return "jobject";
aoqi@0 551 }
aoqi@0 552 }
aoqi@0 553
aoqi@0 554 util.bug("jni.unknown.type");
aoqi@0 555 return null; /* dead code. */
aoqi@0 556 }
aoqi@0 557
aoqi@0 558 protected String llniType(TypeMirror t, boolean handleize, boolean longDoubleOK) {
aoqi@0 559 String res = null;
aoqi@0 560
aoqi@0 561 switch (t.getKind()) {
aoqi@0 562 case ARRAY: {
aoqi@0 563 TypeMirror ct = ((ArrayType) t).getComponentType();
aoqi@0 564 switch (ct.getKind()) {
aoqi@0 565 case BOOLEAN: res = "IArrayOfBoolean"; break;
aoqi@0 566 case BYTE: res = "IArrayOfByte"; break;
aoqi@0 567 case CHAR: res = "IArrayOfChar"; break;
aoqi@0 568 case SHORT: res = "IArrayOfShort"; break;
aoqi@0 569 case INT: res = "IArrayOfInt"; break;
aoqi@0 570 case LONG: res = "IArrayOfLong"; break;
aoqi@0 571 case FLOAT: res = "IArrayOfFloat"; break;
aoqi@0 572 case DOUBLE: res = "IArrayOfDouble"; break;
aoqi@0 573 case ARRAY:
aoqi@0 574 case DECLARED: res = "IArrayOfRef"; break;
aoqi@0 575 default: throw new Error(ct.getKind() + " " + ct);
aoqi@0 576 }
aoqi@0 577 if (!handleize) res = "DEREFERENCED_" + res;
aoqi@0 578 break;
aoqi@0 579 }
aoqi@0 580
aoqi@0 581 case VOID:
aoqi@0 582 res = "void";
aoqi@0 583 break;
aoqi@0 584
aoqi@0 585 case BOOLEAN:
aoqi@0 586 case BYTE:
aoqi@0 587 case CHAR:
aoqi@0 588 case SHORT:
aoqi@0 589 case INT:
aoqi@0 590 res = "java_int" ;
aoqi@0 591 break;
aoqi@0 592
aoqi@0 593 case LONG:
aoqi@0 594 res = longDoubleOK ? "java_long" : "val32 /* java_long */";
aoqi@0 595 break;
aoqi@0 596
aoqi@0 597 case FLOAT:
aoqi@0 598 res = "java_float";
aoqi@0 599 break;
aoqi@0 600
aoqi@0 601 case DOUBLE:
aoqi@0 602 res = longDoubleOK ? "java_double" : "val32 /* java_double */";
aoqi@0 603 break;
aoqi@0 604
aoqi@0 605 case DECLARED:
aoqi@0 606 TypeElement e = (TypeElement) types.asElement(t);
aoqi@0 607 res = "I" + mangleClassName(e.getQualifiedName().toString());
aoqi@0 608 if (!handleize) res = "DEREFERENCED_" + res;
aoqi@0 609 break;
aoqi@0 610
aoqi@0 611 default:
aoqi@0 612 throw new Error(t.getKind() + " " + t); // FIXME
aoqi@0 613 }
aoqi@0 614
aoqi@0 615 return res;
aoqi@0 616 }
aoqi@0 617
aoqi@0 618 protected final String cRcvrDecl(Element field, String cname) {
aoqi@0 619 return (field.getModifiers().contains(Modifier.STATIC) ? "jclass" : "jobject");
aoqi@0 620 }
aoqi@0 621
aoqi@0 622 protected String maskName(String s) {
aoqi@0 623 return "LLNI_mask(" + s + ")";
aoqi@0 624 }
aoqi@0 625
aoqi@0 626 protected String llniFieldName(VariableElement field) {
aoqi@0 627 return maskName(field.getSimpleName().toString());
aoqi@0 628 }
aoqi@0 629
aoqi@0 630 protected final boolean isLongOrDouble(TypeMirror t) {
aoqi@0 631 TypeVisitor<Boolean,Void> v = new SimpleTypeVisitor8<Boolean,Void>() {
aoqi@0 632 public Boolean defaultAction(TypeMirror t, Void p){
aoqi@0 633 return false;
aoqi@0 634 }
aoqi@0 635 public Boolean visitArray(ArrayType t, Void p) {
aoqi@0 636 return visit(t.getComponentType(), p);
aoqi@0 637 }
aoqi@0 638 public Boolean visitPrimitive(PrimitiveType t, Void p) {
aoqi@0 639 TypeKind tk = t.getKind();
aoqi@0 640 return (tk == TypeKind.LONG || tk == TypeKind.DOUBLE);
aoqi@0 641 }
aoqi@0 642 };
aoqi@0 643 return v.visit(t, null);
aoqi@0 644 }
aoqi@0 645
aoqi@0 646 /* Do unicode to ansi C identifier conversion.
aoqi@0 647 %%% This may not be right, but should be called more often. */
aoqi@0 648 protected final String nameToIdentifier(String name) {
aoqi@0 649 int len = name.length();
aoqi@0 650 StringBuilder buf = new StringBuilder(len);
aoqi@0 651 for (int i = 0; i < len; i++) {
aoqi@0 652 char c = name.charAt(i);
aoqi@0 653 if (isASCIILetterOrDigit(c))
aoqi@0 654 buf.append(c);
aoqi@0 655 else if (c == '/')
aoqi@0 656 buf.append('_');
aoqi@0 657 else if (c == '.')
aoqi@0 658 buf.append('_');
aoqi@0 659 else if (c == '_')
aoqi@0 660 buf.append("_1");
aoqi@0 661 else if (c == ';')
aoqi@0 662 buf.append("_2");
aoqi@0 663 else if (c == '[')
aoqi@0 664 buf.append("_3");
aoqi@0 665 else
aoqi@0 666 buf.append("_0" + ((int)c));
aoqi@0 667 }
aoqi@0 668 return new String(buf);
aoqi@0 669 }
aoqi@0 670
aoqi@0 671 protected final boolean isASCIILetterOrDigit(char c) {
aoqi@0 672 if (((c >= 'A') && (c <= 'Z')) ||
aoqi@0 673 ((c >= 'a') && (c <= 'z')) ||
aoqi@0 674 ((c >= '0') && (c <= '9')))
aoqi@0 675 return true;
aoqi@0 676 else
aoqi@0 677 return false;
aoqi@0 678 }
aoqi@0 679 }
aoqi@0 680

mercurial