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 extends VariableElement> 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 extends VariableElement> 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: