duke@1: /* ohair@554: * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: duke@1: package com.sun.tools.javah; duke@1: duke@1: import java.io.OutputStream; duke@1: import java.io.PrintWriter; jjg@416: import java.util.ArrayList; jjg@416: import java.util.HashSet; jjg@416: import java.util.List; duke@1: jjg@416: import java.util.Set; jjg@416: import javax.lang.model.element.Element; jjg@416: import javax.lang.model.element.ExecutableElement; jjg@416: import javax.lang.model.element.Modifier; jjg@416: import javax.lang.model.element.Name; jjg@416: import javax.lang.model.element.TypeElement; jjg@416: import javax.lang.model.element.VariableElement; jjg@416: import javax.lang.model.type.ArrayType; jjg@416: import javax.lang.model.type.PrimitiveType; jjg@416: import javax.lang.model.type.TypeKind; jjg@416: import javax.lang.model.type.TypeMirror; jjg@416: import javax.lang.model.type.TypeVisitor; jjg@416: import javax.lang.model.util.ElementFilter; darcy@575: import javax.lang.model.util.SimpleTypeVisitor7; jjg@416: jjg@416: /* jjg@416: *

This is NOT part of any API supported by Sun Microsystems. jjg@416: * If you write code that depends on this, you do so at your own jjg@416: * risk. This code and its internal interfaces are subject to change jjg@416: * or deletion without notice.

jjg@416: * jjg@416: * @author Sucheta Dambalkar(Revised) jjg@416: */ duke@1: public class LLNI extends Gen { duke@1: duke@1: protected final char innerDelim = '$'; /* For inner classes */ jjg@416: protected Set doneHandleTypes; jjg@416: List fields; jjg@416: List methods; duke@1: private boolean doubleAlign; duke@1: private int padFieldNum = 0; duke@1: jjg@416: LLNI(boolean doubleAlign, Util util) { jjg@416: super(util); duke@1: this.doubleAlign = doubleAlign; duke@1: } duke@1: duke@1: protected String getIncludes() { duke@1: return ""; duke@1: } duke@1: jjg@416: protected void write(OutputStream o, TypeElement clazz) throws Util.Exit { jjg@416: String cname = mangleClassName(clazz.getQualifiedName().toString()); duke@1: PrintWriter pw = wrapWriter(o); jjg@416: fields = ElementFilter.fieldsIn(clazz.getEnclosedElements()); jjg@416: methods = ElementFilter.methodsIn(clazz.getEnclosedElements()); duke@1: generateDeclsForClass(pw, clazz, cname); jjg@416: // FIXME check if errors occurred on the PrintWriter and throw exception if so duke@1: } duke@1: duke@1: protected void generateDeclsForClass(PrintWriter pw, jjg@416: TypeElement clazz, String cname) throws Util.Exit { jjg@416: doneHandleTypes = new HashSet(); duke@1: /* The following handle types are predefined in "typedefs.h". Suppress duke@1: inclusion in the output by generating them "into the blue" here. */ duke@1: genHandleType(null, "java.lang.Class"); duke@1: genHandleType(null, "java.lang.ClassLoader"); duke@1: genHandleType(null, "java.lang.Object"); duke@1: genHandleType(null, "java.lang.String"); duke@1: genHandleType(null, "java.lang.Thread"); duke@1: genHandleType(null, "java.lang.ThreadGroup"); duke@1: genHandleType(null, "java.lang.Throwable"); duke@1: jjg@416: pw.println("/* LLNI Header for class " + clazz.getQualifiedName() + " */" + lineSep); duke@1: pw.println("#ifndef _Included_" + cname); duke@1: pw.println("#define _Included_" + cname); duke@1: pw.println("#include \"typedefs.h\""); duke@1: pw.println("#include \"llni.h\""); duke@1: pw.println("#include \"jni.h\"" + lineSep); duke@1: duke@1: forwardDecls(pw, clazz); duke@1: structSectionForClass(pw, clazz, cname); duke@1: methodSectionForClass(pw, clazz, cname); duke@1: pw.println("#endif"); duke@1: } duke@1: duke@1: protected void genHandleType(PrintWriter pw, String clazzname) { duke@1: String cname = mangleClassName(clazzname); jjg@416: if (!doneHandleTypes.contains(cname)) { jjg@416: doneHandleTypes.add(cname); duke@1: if (pw != null) { duke@1: pw.println("#ifndef DEFINED_" + cname); duke@1: pw.println(" #define DEFINED_" + cname); duke@1: pw.println(" GEN_HANDLE_TYPES(" + cname + ");"); duke@1: pw.println("#endif" + lineSep); duke@1: } duke@1: } duke@1: } duke@1: duke@1: protected String mangleClassName(String s) { duke@1: return s.replace('.', '_') jjg@416: .replace('/', '_') duke@1: .replace(innerDelim, '_'); duke@1: } duke@1: jjg@416: protected void forwardDecls(PrintWriter pw, TypeElement clazz) { jjg@416: TypeElement object = elems.getTypeElement("java.lang.Object"); jjg@416: if (clazz.equals(object)) jjg@416: return; duke@1: jjg@416: genHandleType(pw, clazz.getQualifiedName().toString()); jjg@416: TypeElement superClass = (TypeElement) (types.asElement(clazz.getSuperclass())); duke@1: jjg@416: if (superClass != null) { jjg@416: String superClassName = superClass.getQualifiedName().toString(); duke@1: forwardDecls(pw, superClass); duke@1: } duke@1: jjg@416: for (VariableElement field: fields) { duke@1: jjg@416: if (!field.getModifiers().contains(Modifier.STATIC)) { jjg@416: TypeMirror t = types.erasure(field.asType()); jjg@416: TypeSignature newTypeSig = new TypeSignature(elems); jjg@416: String tname = newTypeSig.qualifiedTypeName(t); duke@1: String sig = newTypeSig.getTypeSignature(tname); duke@1: duke@1: if (sig.charAt(0) != '[') duke@1: forwardDeclsFromSig(pw, sig); duke@1: } duke@1: } duke@1: jjg@416: for (ExecutableElement method: methods) { duke@1: jjg@416: if (method.getModifiers().contains(Modifier.NATIVE)) { jjg@416: TypeMirror retType = types.erasure(method.getReturnType()); jjg@416: String typesig = signature(method); jjg@416: TypeSignature newTypeSig = new TypeSignature(elems); duke@1: String sig = newTypeSig.getTypeSignature(typesig, retType); duke@1: duke@1: if (sig.charAt(0) != '[') duke@1: forwardDeclsFromSig(pw, sig); duke@1: duke@1: } duke@1: } duke@1: } duke@1: duke@1: protected void forwardDeclsFromSig(PrintWriter pw, String sig) { duke@1: int len = sig.length(); duke@1: int i = sig.charAt(0) == '(' ? 1 : 0; duke@1: duke@1: /* Skip the initial "(". */ duke@1: while (i < len) { duke@1: if (sig.charAt(i) == 'L') { duke@1: int j = i + 1; duke@1: while (sig.charAt(j) != ';') j++; duke@1: genHandleType(pw, sig.substring(i + 1, j)); duke@1: i = j + 1; duke@1: } else { duke@1: i++; duke@1: } duke@1: } duke@1: } duke@1: duke@1: protected void structSectionForClass(PrintWriter pw, jjg@416: TypeElement jclazz, String cname) { duke@1: jjg@416: String jname = jclazz.getQualifiedName().toString(); duke@1: duke@1: if (cname.equals("java_lang_Object")) { duke@1: pw.println("/* struct java_lang_Object is defined in typedefs.h. */"); duke@1: pw.println(); duke@1: return; duke@1: } duke@1: pw.println("#if !defined(__i386)"); duke@1: pw.println("#pragma pack(4)"); duke@1: pw.println("#endif"); duke@1: pw.println(); duke@1: pw.println("struct " + cname + " {"); duke@1: pw.println(" ObjHeader h;"); duke@1: pw.print(fieldDefs(jclazz, cname)); duke@1: duke@1: if (jname.equals("java.lang.Class")) duke@1: pw.println(" Class *LLNI_mask(cClass);" + duke@1: " /* Fake field; don't access (see oobj.h) */"); duke@1: pw.println("};" + lineSep + lineSep + "#pragma pack()"); duke@1: pw.println(); duke@1: return; duke@1: } duke@1: duke@1: private static class FieldDefsRes { duke@1: public String className; /* Name of the current class. */ duke@1: public FieldDefsRes parent; duke@1: public String s; duke@1: public int byteSize; duke@1: public boolean bottomMost; duke@1: public boolean printedOne = false; duke@1: jjg@416: FieldDefsRes(TypeElement clazz, FieldDefsRes parent, boolean bottomMost) { jjg@416: this.className = clazz.getQualifiedName().toString(); duke@1: this.parent = parent; duke@1: this.bottomMost = bottomMost; duke@1: int byteSize = 0; duke@1: if (parent == null) this.s = ""; duke@1: else this.s = parent.s; duke@1: } duke@1: } duke@1: duke@1: /* Returns "true" iff added a field. */ jjg@416: private boolean doField(FieldDefsRes res, VariableElement field, jjg@416: String cname, boolean padWord) { duke@1: duke@1: String fieldDef = addStructMember(field, cname, padWord); duke@1: if (fieldDef != null) { duke@1: if (!res.printedOne) { /* add separator */ duke@1: if (res.bottomMost) { duke@1: if (res.s.length() != 0) duke@1: res.s = res.s + " /* local members: */" + lineSep; duke@1: } else { duke@1: res.s = res.s + " /* inherited members from " + duke@1: res.className + ": */" + lineSep; duke@1: } duke@1: res.printedOne = true; duke@1: } duke@1: res.s = res.s + fieldDef; duke@1: return true; duke@1: } duke@1: duke@1: // Otherwise. duke@1: return false; duke@1: } duke@1: jjg@416: private int doTwoWordFields(FieldDefsRes res, TypeElement clazz, jjg@416: int offset, String cname, boolean padWord) { duke@1: boolean first = true; jjg@416: List fields = ElementFilter.fieldsIn(clazz.getEnclosedElements()); duke@1: jjg@416: for (VariableElement field: fields) { jjg@416: TypeKind tk = field.asType().getKind(); jjg@416: boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE); duke@1: if (twoWords && doField(res, field, cname, first && padWord)) { duke@1: offset += 8; first = false; duke@1: } duke@1: } duke@1: return offset; duke@1: } duke@1: jjg@416: String fieldDefs(TypeElement clazz, String cname) { duke@1: FieldDefsRes res = fieldDefs(clazz, cname, true); duke@1: return res.s; duke@1: } duke@1: jjg@416: FieldDefsRes fieldDefs(TypeElement clazz, String cname, jjg@416: boolean bottomMost){ duke@1: FieldDefsRes res; duke@1: int offset; duke@1: boolean didTwoWordFields = false; jjg@416: jjg@416: TypeElement superclazz = (TypeElement) types.asElement(clazz.getSuperclass()); duke@1: duke@1: if (superclazz != null) { jjg@416: String supername = superclazz.getQualifiedName().toString(); duke@1: res = new FieldDefsRes(clazz, duke@1: fieldDefs(superclazz, cname, false), duke@1: bottomMost); duke@1: offset = res.parent.byteSize; duke@1: } else { duke@1: res = new FieldDefsRes(clazz, null, bottomMost); duke@1: offset = 0; duke@1: } duke@1: jjg@416: List fields = ElementFilter.fieldsIn(clazz.getEnclosedElements()); duke@1: jjg@416: for (VariableElement field: fields) { duke@1: duke@1: if (doubleAlign && !didTwoWordFields && (offset % 8) == 0) { duke@1: offset = doTwoWordFields(res, clazz, offset, cname, false); duke@1: didTwoWordFields = true; duke@1: } duke@1: jjg@416: TypeKind tk = field.asType().getKind(); jjg@416: boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE); duke@1: duke@1: if (!doubleAlign || !twoWords) { duke@1: if (doField(res, field, cname, false)) offset += 4; duke@1: } duke@1: duke@1: } duke@1: duke@1: if (doubleAlign && !didTwoWordFields) { duke@1: if ((offset % 8) != 0) offset += 4; duke@1: offset = doTwoWordFields(res, clazz, offset, cname, true); duke@1: } duke@1: duke@1: res.byteSize = offset; duke@1: return res; duke@1: } duke@1: duke@1: /* OVERRIDE: This method handles instance fields */ jjg@416: protected String addStructMember(VariableElement member, String cname, jjg@416: boolean padWord) { duke@1: String res = null; duke@1: jjg@416: if (member.getModifiers().contains(Modifier.STATIC)) { duke@1: res = addStaticStructMember(member, cname); duke@1: // if (res == null) /* JNI didn't handle it, print comment. */ duke@1: // res = " /* Inaccessible static: " + member + " */" + lineSep; duke@1: } else { jjg@416: TypeMirror mt = types.erasure(member.asType()); duke@1: if (padWord) res = " java_int padWord" + padFieldNum++ + ";" + lineSep; jjg@416: res = " " + llniType(mt, false, false) + " " + llniFieldName(member); jjg@416: if (isLongOrDouble(mt)) res = res + "[2]"; duke@1: res = res + ";" + lineSep; duke@1: } duke@1: return res; duke@1: } duke@1: duke@1: static private final boolean isWindows = duke@1: System.getProperty("os.name").startsWith("Windows"); duke@1: duke@1: /* duke@1: * This method only handles static final fields. duke@1: */ jjg@416: protected String addStaticStructMember(VariableElement field, String cname) { duke@1: String res = null; duke@1: Object exp = null; duke@1: jjg@416: if (!field.getModifiers().contains(Modifier.STATIC)) duke@1: return res; jjg@416: if (!field.getModifiers().contains(Modifier.FINAL)) duke@1: return res; duke@1: jjg@416: exp = field.getConstantValue(); duke@1: duke@1: if (exp != null) { duke@1: /* Constant. */ duke@1: jjg@416: String cn = cname + "_" + field.getSimpleName(); duke@1: String suffix = null; duke@1: long val = 0; duke@1: /* Can only handle int, long, float, and double fields. */ jjg@416: if (exp instanceof Byte jjg@416: || exp instanceof Short jjg@416: || exp instanceof Integer) { duke@1: suffix = "L"; jjg@416: val = ((Number)exp).intValue(); duke@1: } jjg@416: else if (exp instanceof Long) { duke@1: // Visual C++ supports the i64 suffix, not LL duke@1: suffix = isWindows ? "i64" : "LL"; duke@1: val = ((Long)exp).longValue(); duke@1: } jjg@416: else if (exp instanceof Float) suffix = "f"; jjg@416: else if (exp instanceof Double) suffix = ""; jjg@416: else if (exp instanceof Character) { jjg@416: suffix = "L"; jjg@416: Character ch = (Character) exp; jjg@416: val = ((int) ch) & 0xffff; jjg@416: } duke@1: if (suffix != null) { duke@1: // Some compilers will generate a spurious warning duke@1: // for the integer constants for Integer.MIN_VALUE duke@1: // and Long.MIN_VALUE so we handle them specially. duke@1: if ((suffix.equals("L") && (val == Integer.MIN_VALUE)) || duke@1: (suffix.equals("LL") && (val == Long.MIN_VALUE))) { duke@1: res = " #undef " + cn + lineSep duke@1: + " #define " + cn duke@1: + " (" + (val + 1) + suffix + "-1)" + lineSep; jjg@416: } else if (suffix.equals("L") || suffix.endsWith("LL")) { jjg@416: res = " #undef " + cn + lineSep jjg@416: + " #define " + cn + " " + val + suffix + lineSep; duke@1: } else { duke@1: res = " #undef " + cn + lineSep jjg@416: + " #define " + cn + " " + exp + suffix + lineSep; duke@1: } duke@1: } duke@1: } duke@1: return res; duke@1: } duke@1: duke@1: protected void methodSectionForClass(PrintWriter pw, jjg@416: TypeElement clazz, String cname) jjg@416: throws Util.Exit { duke@1: String methods = methodDecls(clazz, cname); duke@1: duke@1: if (methods.length() != 0) { duke@1: pw.println("/* Native method declarations: */" + lineSep); duke@1: pw.println("#ifdef __cplusplus"); duke@1: pw.println("extern \"C\" {"); duke@1: pw.println("#endif" + lineSep); duke@1: pw.println(methods); duke@1: pw.println("#ifdef __cplusplus"); duke@1: pw.println("}"); duke@1: pw.println("#endif"); duke@1: } duke@1: } duke@1: jjg@416: protected String methodDecls(TypeElement clazz, String cname) throws Util.Exit { duke@1: duke@1: String res = ""; jjg@416: for (ExecutableElement method: methods) { jjg@416: if (method.getModifiers().contains(Modifier.NATIVE)) duke@1: res = res + methodDecl(method, clazz, cname); duke@1: } duke@1: return res; duke@1: } duke@1: jjg@416: protected String methodDecl(ExecutableElement method, jjg@416: TypeElement clazz, String cname) jjg@416: throws Util.Exit { duke@1: String res = null; duke@1: jjg@416: TypeMirror retType = types.erasure(method.getReturnType()); jjg@416: String typesig = signature(method); jjg@416: TypeSignature newTypeSig = new TypeSignature(elems); duke@1: String sig = newTypeSig.getTypeSignature(typesig, retType); duke@1: boolean longName = needLongName(method, clazz); duke@1: duke@1: if (sig.charAt(0) != '(') jjg@416: util.error("invalid.method.signature", sig); duke@1: duke@1: duke@1: res = "JNIEXPORT " + jniType(retType) + " JNICALL" + lineSep + jniMethodName(method, cname, longName) duke@1: + "(JNIEnv *, " + cRcvrDecl(method, cname); jjg@416: List params = method.getParameters(); jjg@416: List argTypes = new ArrayList(); jjg@416: for (VariableElement p: params){ jjg@416: argTypes.add(types.erasure(p.asType())); duke@1: } duke@1: duke@1: /* It would have been nice to include the argument names in the duke@1: declaration, but there seems to be a bug in the "BinaryField" duke@1: class, causing the getArguments() method to return "null" for duke@1: most (non-constructor) methods. */ jjg@416: for (TypeMirror argType: argTypes) jjg@416: res = res + ", " + jniType(argType); duke@1: res = res + ");" + lineSep; duke@1: return res; duke@1: } duke@1: jjg@416: protected final boolean needLongName(ExecutableElement method, jjg@416: TypeElement clazz) { jjg@416: Name methodName = method.getSimpleName(); jjg@416: for (ExecutableElement memberMethod: methods) { duke@1: if ((memberMethod != method) && jjg@416: memberMethod.getModifiers().contains(Modifier.NATIVE) && jjg@416: (methodName.equals(memberMethod.getSimpleName()))) duke@1: return true; duke@1: } duke@1: return false; duke@1: } duke@1: jjg@416: protected final String jniMethodName(ExecutableElement method, String cname, duke@1: boolean longName) { jjg@416: String res = "Java_" + cname + "_" + method.getSimpleName(); duke@1: duke@1: if (longName) { jjg@416: TypeMirror mType = types.erasure(method.getReturnType()); jjg@416: List params = method.getParameters(); jjg@416: List argTypes = new ArrayList(); jjg@416: for (VariableElement param: params) { jjg@416: argTypes.add(types.erasure(param.asType())); duke@1: } duke@1: duke@1: res = res + "__"; jjg@416: for (TypeMirror t: argTypes) { jjg@416: String tname = t.toString(); jjg@416: TypeSignature newTypeSig = new TypeSignature(elems); duke@1: String sig = newTypeSig.getTypeSignature(tname); duke@1: res = res + nameToIdentifier(sig); duke@1: } duke@1: } duke@1: return res; duke@1: } duke@1: jjg@416: // copied from JNI.java jjg@416: protected final String jniType(TypeMirror t) throws Util.Exit { jjg@416: TypeElement throwable = elems.getTypeElement("java.lang.Throwable"); jjg@416: TypeElement jClass = elems.getTypeElement("java.lang.Class"); jjg@416: TypeElement jString = elems.getTypeElement("java.lang.String"); jjg@416: Element tclassDoc = types.asElement(t); jjg@416: jjg@416: switch (t.getKind()) { jjg@416: case ARRAY: { jjg@416: TypeMirror ct = ((ArrayType) t).getComponentType(); jjg@416: switch (ct.getKind()) { jjg@416: case BOOLEAN: return "jbooleanArray"; jjg@416: case BYTE: return "jbyteArray"; jjg@416: case CHAR: return "jcharArray"; jjg@416: case SHORT: return "jshortArray"; jjg@416: case INT: return "jintArray"; jjg@416: case LONG: return "jlongArray"; jjg@416: case FLOAT: return "jfloatArray"; jjg@416: case DOUBLE: return "jdoubleArray"; jjg@416: case ARRAY: jjg@416: case DECLARED: return "jobjectArray"; jjg@416: default: throw new Error(ct.toString()); jjg@416: } jjg@416: } jjg@416: jjg@416: case VOID: return "void"; jjg@416: case BOOLEAN: return "jboolean"; jjg@416: case BYTE: return "jbyte"; jjg@416: case CHAR: return "jchar"; jjg@416: case SHORT: return "jshort"; jjg@416: case INT: return "jint"; jjg@416: case LONG: return "jlong"; jjg@416: case FLOAT: return "jfloat"; jjg@416: case DOUBLE: return "jdouble"; jjg@416: jjg@416: case DECLARED: { jjg@416: if (tclassDoc.equals(jString)) duke@1: return "jstring"; jjg@416: else if (types.isAssignable(t, throwable.asType())) jjg@416: return "jthrowable"; jjg@416: else if (types.isAssignable(t, jClass.asType())) duke@1: return "jclass"; duke@1: else duke@1: return "jobject"; duke@1: } duke@1: } jjg@416: jjg@416: util.bug("jni.unknown.type"); duke@1: return null; /* dead code. */ duke@1: } duke@1: jjg@416: protected String llniType(TypeMirror t, boolean handleize, boolean longDoubleOK) { duke@1: String res = null; jjg@416: jjg@416: switch (t.getKind()) { jjg@416: case ARRAY: { jjg@416: TypeMirror ct = ((ArrayType) t).getComponentType(); jjg@416: switch (ct.getKind()) { jjg@416: case BOOLEAN: res = "IArrayOfBoolean"; break; jjg@416: case BYTE: res = "IArrayOfByte"; break; jjg@416: case CHAR: res = "IArrayOfChar"; break; jjg@416: case SHORT: res = "IArrayOfShort"; break; jjg@416: case INT: res = "IArrayOfInt"; break; jjg@416: case LONG: res = "IArrayOfLong"; break; jjg@416: case FLOAT: res = "IArrayOfFloat"; break; jjg@416: case DOUBLE: res = "IArrayOfDouble"; break; jjg@416: case ARRAY: jjg@416: case DECLARED: res = "IArrayOfRef"; break; jjg@416: default: throw new Error(ct.getKind() + " " + ct); jjg@416: } duke@1: if (!handleize) res = "DEREFERENCED_" + res; jjg@416: break; duke@1: } jjg@416: jjg@416: case VOID: jjg@416: res = "void"; jjg@416: break; jjg@416: jjg@416: case BOOLEAN: jjg@416: case BYTE: jjg@416: case CHAR: jjg@416: case SHORT: jjg@416: case INT: jjg@416: res = "java_int" ; jjg@416: break; jjg@416: jjg@416: case LONG: jjg@416: res = longDoubleOK ? "java_long" : "val32 /* java_long */"; jjg@416: break; jjg@416: jjg@416: case FLOAT: jjg@416: res = "java_float"; jjg@416: break; jjg@416: jjg@416: case DOUBLE: jjg@416: res = longDoubleOK ? "java_double" : "val32 /* java_double */"; jjg@416: break; jjg@416: jjg@416: case DECLARED: jjg@416: TypeElement e = (TypeElement) types.asElement(t); jjg@416: res = "I" + mangleClassName(e.getQualifiedName().toString()); jjg@416: if (!handleize) res = "DEREFERENCED_" + res; jjg@416: break; jjg@416: jjg@416: default: jjg@416: throw new Error(t.getKind() + " " + t); // FIXME duke@1: } jjg@416: duke@1: return res; duke@1: } duke@1: jjg@416: protected final String cRcvrDecl(Element field, String cname) { jjg@416: return (field.getModifiers().contains(Modifier.STATIC) ? "jclass" : "jobject"); duke@1: } duke@1: duke@1: protected String maskName(String s) { duke@1: return "LLNI_mask(" + s + ")"; duke@1: } duke@1: jjg@416: protected String llniFieldName(VariableElement field) { jjg@416: return maskName(field.getSimpleName().toString()); duke@1: } duke@1: jjg@416: protected final boolean isLongOrDouble(TypeMirror t) { darcy@575: TypeVisitor v = new SimpleTypeVisitor7() { jjg@416: public Boolean defaultAction(TypeMirror t, Void p){ jjg@416: return false; jjg@416: } jjg@416: public Boolean visitArray(ArrayType t, Void p) { jjg@416: return visit(t.getComponentType(), p); jjg@416: } jjg@416: public Boolean visitPrimitive(PrimitiveType t, Void p) { jjg@416: TypeKind tk = t.getKind(); jjg@416: return (tk == TypeKind.LONG || tk == TypeKind.DOUBLE); jjg@416: } jjg@416: }; jjg@416: return v.visit(t, null); duke@1: } duke@1: duke@1: /* Do unicode to ansi C identifier conversion. duke@1: %%% This may not be right, but should be called more often. */ duke@1: protected final String nameToIdentifier(String name) { duke@1: int len = name.length(); duke@1: StringBuffer buf = new StringBuffer(len); duke@1: for (int i = 0; i < len; i++) { duke@1: char c = name.charAt(i); duke@1: if (isASCIILetterOrDigit(c)) duke@1: buf.append(c); duke@1: else if (c == '/') duke@1: buf.append('_'); duke@1: else if (c == '.') duke@1: buf.append('_'); duke@1: else if (c == '_') duke@1: buf.append("_1"); duke@1: else if (c == ';') duke@1: buf.append("_2"); duke@1: else if (c == '[') duke@1: buf.append("_3"); duke@1: else duke@1: buf.append("_0" + ((int)c)); duke@1: } duke@1: return new String(buf); duke@1: } duke@1: duke@1: protected final boolean isASCIILetterOrDigit(char c) { duke@1: if (((c >= 'A') && (c <= 'Z')) || duke@1: ((c >= 'a') && (c <= 'z')) || duke@1: ((c >= '0') && (c <= '9'))) duke@1: return true; duke@1: else duke@1: return false; duke@1: } duke@1: } jjg@416: