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

Tue, 28 Dec 2010 15:54:52 -0800

author
ohair
date
Tue, 28 Dec 2010 15:54:52 -0800
changeset 798
4868a36f6fd8
parent 712
a1d31ab7b525
child 1054
111bbf1ad913
permissions
-rw-r--r--

6962318: Update copyright year
Reviewed-by: xdono

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

mercurial