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

Wed, 02 Jun 2010 19:08:47 -0700

author
darcy
date
Wed, 02 Jun 2010 19:08:47 -0700
changeset 575
9a7c998bf2fc
parent 554
9d9f26857129
child 581
f2fdd52e4e87
permissions
-rw-r--r--

6933147: Provided new utility visitors supporting SourceVersion.RELEASE_7
Reviewed-by: jjg

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

mercurial