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.nio.file.Path; 26 import java.util.Collections; 27 import java.util.List; 28 import java.util.concurrent.atomic.AtomicInteger; 29 import java.util.logging.Logger; 30 import jdk.internal.clang.Cursor; 31 import jdk.internal.clang.CursorKind; 32 import jdk.internal.clang.Type; 33 import jdk.internal.clang.TypeKind; 34 35 /** 36 * This class represent a native code header file 37 */ 38 public final class HeaderFile { 39 private final Context ctx; 40 final Path path; 41 final String pkgName; 42 final String clsName; 43 private final TypeDictionary dict; 44 // The top header file cause this file to be parsed 45 private HeaderFile main; 46 private AsmCodeFactory cf; 47 List<String> libraries; // immutable 48 List<String> libraryPaths; // immutable 49 50 private final AtomicInteger serialNo; 51 52 private final Logger logger = Logger.getLogger(getClass().getPackage().getName()); 53 54 HeaderFile(Context ctx, Path path, String pkgName, String clsName, HeaderFile main) { 55 this.ctx = ctx; 56 this.path = path; 57 this.pkgName = pkgName; 58 this.clsName = clsName; 59 dict = ctx.typeDictionaryFor(pkgName); 60 serialNo = new AtomicInteger(); 61 this.main = main == null ? this : main; 62 } 63 64 void useLibraries(List<String> libraries, List<String> libraryPaths) { 65 this.libraries = Collections.unmodifiableList(libraries); 66 this.libraryPaths = Collections.unmodifiableList(libraryPaths); 67 } 68 69 AsmCodeFactory getCodeFactory() { 70 return cf; 71 } 72 73 /** 74 * Call this function to enable code generation for this HeaderFile. 75 * This function should only be called once to turn on code generation and before process any cursor. 76 * @param cf The CodeFactory used to generate code 77 */ 78 void useCodeFactory(AsmCodeFactory cf) { 79 if (null != this.cf) { 80 logger.config(() -> "CodeFactory had been initialized for " + path); 81 // Diagnosis code 82 if (Main.DEBUG) { 83 new Throwable().printStackTrace(ctx.err); 84 } 85 } else { 86 this.cf = cf; 87 } 88 } 89 90 @Override 91 public String toString() { 92 return "HeaderFile(path=" + path + ")"; 93 } 94 95 private int serialNo() { 96 return serialNo.incrementAndGet(); 97 } 98 99 void processCursor(Cursor c, HeaderFile main, boolean isBuiltIn) { 100 if (c.isDeclaration()) { 101 logger.finest(() -> "Looking at cursor " + c.spelling() + " of kind " + c.kind()); 102 if (c.kind() == CursorKind.UnexposedDecl || 103 c.kind() == CursorKind.Namespace) { 104 c.children() 105 .filter(c1 -> c1.isDeclaration()) 106 .peek(c1 -> logger.finest( 211 t, defC.isInvalid() ? dcl : defC); 212 if (gen_code) { 213 cf.addType(jt, defC); 214 } 215 return jt; 216 } 217 218 // Use of dict.lookup() and lookup() is tricky, if a type should have being 219 // declared earlier, use dict.lookup(); otherwise use lookup() for potentially 220 // local declaration of a type. 221 JType define(Type t) { 222 JType jt; 223 JType2 jt2; 224 logger.fine("Define " + t.kind() + ":" + t.spelling() + " for TD " + pkgName); 225 switch (t.kind()) { 226 case Unexposed: 227 case Elaborated: 228 jt = define(t.canonicalType()); 229 break; 230 case ConstantArray: 231 jt = JType.ofArray(globalLookup(t.getElementType())); 232 break; 233 case IncompleteArray: 234 jt = JType.ofArray(globalLookup(t.getElementType())); 235 break; 236 case FunctionProto: 237 case FunctionNoProto: 238 JType[] args = new JType[t.numberOfArgs()]; 239 for (int i = 0; i < args.length; i++) { 240 // argument could be function pointer declared locally 241 args[i] = globalLookup(t.argType(i)); 242 } 243 jt = new JType.Function(Utils.getFunction(t), t.isVariadic(), globalLookup(t.resultType()), args); 244 break; 245 case Enum: 246 String name = Utils.toInternalName(pkgName, clsName, 247 Utils.toClassName(Utils.getIdentifier(t))); 248 jt = TypeAlias.of(name, JType.Int); 249 break; 250 case Invalid: 251 throw new IllegalArgumentException("Invalid type"); 252 case Record: | 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.nio.file.Path; 26 import java.util.ArrayList; 27 import java.util.Collections; 28 import java.util.List; 29 import java.util.Objects; 30 import java.util.concurrent.atomic.AtomicInteger; 31 import java.util.logging.Logger; 32 import java.util.stream.Stream; 33 import jdk.internal.clang.Cursor; 34 import jdk.internal.clang.CursorKind; 35 import jdk.internal.clang.Type; 36 import jdk.internal.clang.TypeKind; 37 38 /** 39 * This class represent a native code header file 40 */ 41 public final class HeaderFile { 42 private final Context ctx; 43 final Path path; 44 final String pkgName; 45 final String clsName; 46 private final TypeDictionary dict; 47 // The top header file cause this file to be parsed 48 private HeaderFile main; 49 // files included that are from the same directory 50 private final List<HeaderFile> includedFiles; 51 private AsmCodeFactory cf; 52 List<String> libraries; // immutable 53 List<String> libraryPaths; // immutable 54 55 private final AtomicInteger serialNo; 56 57 private final Logger logger = Logger.getLogger(getClass().getPackage().getName()); 58 59 HeaderFile(Context ctx, Path path, String pkgName, String clsName, HeaderFile main) { 60 this.ctx = ctx; 61 this.path = path; 62 this.pkgName = pkgName; 63 this.clsName = clsName; 64 this.dict = ctx.typeDictionaryFor(pkgName); 65 this.serialNo = new AtomicInteger(); 66 this.main = main == null ? this : main; 67 this.includedFiles = new ArrayList<>(); 68 } 69 70 Stream<HeaderFile> getIncludedFiles() { 71 return includedFiles.stream(); 72 } 73 74 void useLibraries(List<String> libraries, List<String> libraryPaths) { 75 this.libraries = Collections.unmodifiableList(libraries); 76 this.libraryPaths = Collections.unmodifiableList(libraryPaths); 77 } 78 79 AsmCodeFactory getCodeFactory() { 80 return cf; 81 } 82 83 /** 84 * Call this function to enable code generation for this HeaderFile. 85 * This function should only be called once to turn on code generation and before process any cursor. 86 * @param cf The CodeFactory used to generate code 87 */ 88 void useCodeFactory(AsmCodeFactory cf) { 89 if (null != this.cf) { 90 logger.config(() -> "CodeFactory had been initialized for " + path); 91 // Diagnosis code 92 if (Main.DEBUG) { 93 new Throwable().printStackTrace(ctx.err); 94 } 95 } else { 96 this.cf = cf; 97 // The 'main' header interface inherits from included header interfaces 98 // only if the included file is assigned to the same package and is from 99 // the same directory. 100 if (this != main && Objects.equals(pkgName, main.pkgName) && 101 Objects.equals(path.getParent(), main.path.getParent())) { 102 main.includedFiles.add(this); 103 } 104 } 105 } 106 107 @Override 108 public String toString() { 109 return "HeaderFile(path=" + path + ")"; 110 } 111 112 private int serialNo() { 113 return serialNo.incrementAndGet(); 114 } 115 116 void processCursor(Cursor c, HeaderFile main, boolean isBuiltIn) { 117 if (c.isDeclaration()) { 118 logger.finest(() -> "Looking at cursor " + c.spelling() + " of kind " + c.kind()); 119 if (c.kind() == CursorKind.UnexposedDecl || 120 c.kind() == CursorKind.Namespace) { 121 c.children() 122 .filter(c1 -> c1.isDeclaration()) 123 .peek(c1 -> logger.finest( 228 t, defC.isInvalid() ? dcl : defC); 229 if (gen_code) { 230 cf.addType(jt, defC); 231 } 232 return jt; 233 } 234 235 // Use of dict.lookup() and lookup() is tricky, if a type should have being 236 // declared earlier, use dict.lookup(); otherwise use lookup() for potentially 237 // local declaration of a type. 238 JType define(Type t) { 239 JType jt; 240 JType2 jt2; 241 logger.fine("Define " + t.kind() + ":" + t.spelling() + " for TD " + pkgName); 242 switch (t.kind()) { 243 case Unexposed: 244 case Elaborated: 245 jt = define(t.canonicalType()); 246 break; 247 case ConstantArray: 248 case IncompleteArray: 249 jt = JType.ofArray(globalLookup(t.getElementType())); 250 break; 251 case FunctionProto: 252 case FunctionNoProto: 253 JType[] args = new JType[t.numberOfArgs()]; 254 for (int i = 0; i < args.length; i++) { 255 // argument could be function pointer declared locally 256 args[i] = globalLookup(t.argType(i)); 257 } 258 jt = new JType.Function(Utils.getFunction(t), t.isVariadic(), globalLookup(t.resultType()), args); 259 break; 260 case Enum: 261 String name = Utils.toInternalName(pkgName, clsName, 262 Utils.toClassName(Utils.getIdentifier(t))); 263 jt = TypeAlias.of(name, JType.Int); 264 break; 265 case Invalid: 266 throw new IllegalArgumentException("Invalid type"); 267 case Record: |