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