1 /*
   2  * Copyright (c) 2019, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package com.sun.tools.jextract;
  24 
  25 import java.util.ArrayList;
  26 import java.util.List;
  27 import java.util.Set;
  28 import com.sun.tools.jextract.tree.FunctionTree;
  29 import com.sun.tools.jextract.tree.VarTree;
  30 
  31 /**
  32  * A helper class to generate static forwarder header class in source form.
  33  * After aggregating various constituents of a .java source, build method
  34  * is called to get overall generated source string.
  35  */
  36 final class JavaSourceBuilderExt extends JavaSourceBuilder {
  37     JavaSourceBuilderExt(int align) {
  38         super(align);
  39     }
  40 
  41     JavaSourceBuilderExt() {
  42         super();
  43     }
  44 
  45     protected void addImportSection() {
  46         sb.append("import java.foreign.*;\n");
  47         sb.append("import java.foreign.memory.*;\n");
  48         sb.append("import java.lang.invoke.*;\n\n");
  49     }
  50 
  51     protected void classBegin(String name, boolean isStatic) {
  52         classBegin(name, isStatic, null);
  53     }
  54 
  55     protected void classBegin(String name, boolean isStatic, String superType) {
  56         check();
  57         indent();
  58         sb.append("public ");
  59         if (isStatic) {
  60             sb.append("static ");
  61         }
  62         sb.append("class ");
  63         sb.append(name);
  64         if (superType != null) {
  65             sb.append(" extends ");
  66             sb.append(superType);
  67         }
  68         sb.append(" {\n\n");
  69     }
  70 
  71     protected void classEnd() {
  72         interfaceEnd();
  73     }
  74 
  75     // implement LibraryScope scope(LibraryInterfaceObject) method
  76     protected void emitScopeAccessor(String libraryField) {
  77         check();
  78         incrAlign();
  79         indent();
  80         sb.append("public static Scope scope() {\n");
  81         incrAlign();
  82         indent();
  83         sb.append("return Libraries.libraryScope(");
  84         sb.append(libraryField);
  85         sb.append(");\n");
  86         decrAlign();
  87         indent();
  88         sb.append("}\n\n");
  89         decrAlign();
  90     }
  91 
  92     // add private static field for the underlying header interface (bound) object
  93     protected void addLibraryField(String className, String libraryField) {
  94         check();
  95         incrAlign();
  96         indent();
  97         sb.append("private static final ");
  98         sb.append(className);
  99         sb.append(' ');
 100         sb.append(libraryField);
 101         sb.append(" = Libraries.bind(MethodHandles.lookup(), ");
 102         sb.append(className);
 103         sb.append(".class);\n\n");
 104         decrAlign();
 105     }
 106 
 107     // add a static final field for enum constant or a C macro
 108     protected void addField(String name, JType type, Object value, String libraryField) {
 109         check();
 110         incrAlign();
 111         indent();
 112         sb.append("public static final ");
 113         sb.append(type.getSourceSignature(false));
 114         sb.append(' ');
 115         sb.append(name);
 116         sb.append(" = ");
 117         if (value != null) {
 118             boolean isChar = value instanceof Character;
 119             if (isChar) {
 120                 sb.append('\'');
 121             }
 122             sb.append(value);
 123             if (isChar) {
 124                 sb.append('\'');
 125             }
 126             if (value instanceof Long) {
 127                 sb.append('L');
 128             } else if (value instanceof Double) {
 129                 sb.append('D');
 130             }
 131         } else {
 132             sb.append(libraryField);
 133             sb.append('.');
 134             sb.append(name);
 135             sb.append("()");
 136         }
 137         sb.append(";\n\n");
 138         decrAlign();
 139     }
 140 
 141     // emit static forwarder methods for a variable getter, setter and pointer getter
 142     protected void emitStaticForwarder(VarTree varTree, JType type, String libraryField) {
 143         check();
 144         incrAlign();
 145 
 146         String fieldName = varTree.name();
 147 
 148         // getter
 149         indent();
 150         sb.append("public static ");
 151         sb.append(type.getSourceSignature(false));
 152         sb.append(' ');
 153         sb.append(fieldName);
 154         sb.append("$get() {\n");
 155         incrAlign();
 156         indent();
 157         sb.append("return ");
 158         sb.append(libraryField);
 159         sb.append('.');
 160         sb.append(fieldName);
 161         sb.append("$get();\n");
 162         decrAlign();
 163         indent();
 164         sb.append("}\n\n");
 165 
 166         // setter
 167         indent();
 168         sb.append("public static void ");
 169         sb.append(fieldName);
 170         sb.append("$set(");
 171         sb.append(type.getSourceSignature(true));
 172         sb.append(" value) {\n");
 173         incrAlign();
 174         indent();
 175         sb.append(libraryField);
 176         sb.append('.');
 177         sb.append(fieldName);
 178         sb.append("$set(value);\n");
 179         decrAlign();
 180         indent();
 181         sb.append("}\n\n");
 182 
 183         // ptr getter
 184         JType ptrType = JType.GenericType.ofPointer(type);
 185         indent();
 186         sb.append("public static ");
 187         sb.append(ptrType.getSourceSignature(false));
 188         sb.append(' ');
 189         sb.append(fieldName);
 190         sb.append("$ptr() {\n");
 191         incrAlign();
 192         indent();
 193         sb.append("return ");
 194         sb.append(libraryField);
 195         sb.append('.');
 196         sb.append(fieldName);
 197         sb.append("$ptr();\n");
 198         decrAlign();
 199         indent();
 200         sb.append("}\n\n");
 201 
 202         decrAlign();
 203     }
 204 
 205     // emit static forwarder method of a function
 206     protected void emitStaticForwarder(FunctionTree funcTree, JType.Function fn, String libraryField) {
 207         check();
 208 
 209         final int numArgs = fn.isVarArgs? fn.args.length + 1 : fn.args.length;
 210         final String[] argTypes = new String[numArgs];
 211         final String[] argNames = new String[numArgs];
 212         fillArgTypes(fn, argTypes);
 213         fillArgNames(fn, funcTree, argNames);
 214 
 215         incrAlign();
 216         indent();
 217         sb.append("public static ");
 218         sb.append(fn.returnType.getSourceSignature(false));
 219         sb.append(' ');
 220         sb.append(funcTree.name());
 221         sb.append('(');
 222         for (int i = 0; i < numArgs; i++) {
 223             sb.append(argTypes[i]);
 224             sb.append(' ');
 225             sb.append(argNames[i]);
 226             if (i != numArgs - 1) {
 227                 sb.append(", ");
 228             }
 229         }
 230         sb.append(") {\n");
 231         incrAlign();
 232         indent();
 233         if (fn.returnType != JType.Void) {
 234             sb.append("return ");
 235         }
 236         sb.append(libraryField);
 237         sb.append('.');
 238         sb.append(funcTree.name());
 239         sb.append('(');
 240         for (int j = 0; j < numArgs; j++) {
 241             sb.append(argNames[j]);
 242             if (j != numArgs - 1) {
 243                 sb.append(", ");
 244             }
 245         }
 246         sb.append(");\n");
 247         decrAlign();
 248         indent();
 249         sb.append("}\n\n");
 250         decrAlign();
 251     }
 252 }