35 import java.foreign.Library;
36 import java.nio.file.Files;
37 import java.nio.file.Path;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Collections;
41 import java.util.HashMap;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Properties;
45 import java.util.Set;
46 import java.util.TreeSet;
47 import java.util.function.Function;
48 import java.util.function.Predicate;
49 import java.util.jar.JarOutputStream;
50 import java.util.logging.Logger;
51 import java.util.regex.Pattern;
52 import java.util.stream.Collectors;
53 import java.util.zip.ZipEntry;
54 import com.sun.tools.jextract.parser.Parser;
55 import com.sun.tools.jextract.tree.Tree;
56 import com.sun.tools.jextract.tree.HeaderTree;
57
58 import static java.nio.file.StandardOpenOption.CREATE;
59 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
60 import static java.nio.file.StandardOpenOption.WRITE;
61
62 /**
63 * The setup for the tool execution
64 */
65 public final class Context {
66 // package name to TypeDictionary
67 private final Map<String, TypeDictionary> tdMap;
68 // The folder path mapping to package name
69 private final Map<Path, String> pkgMap;
70 // The header file parsed
71 private final Map<Path, HeaderFile> headerMap;
72 // The args for parsing C
73 private final List<String> clangArgs;
74 // The set of source header files
75 private final Set<Path> sources;
76 // The list of library names
324 logger.config(() -> "First encounter of header file " + hf.path + ", assigned to package " + hf.pkgName);
325 // Only generate code for header files sepcified or in the same package
326 // System headers are excluded, they need to be explicitly specified in jextract cmdline
327 if (sources.contains(p) ||
328 (!loc.isInSystemHeader()) && (header.pkgName.equals(main.pkgName))) {
329 logger.config("Code gen for header " + p + " enabled in package " + header.pkgName);
330 header.useCodeFactory(fn.apply(header));
331 }
332 headerMap.put(p, header);
333 }
334 }
335 }
336
337 header.processTree(tree, main, isBuiltIn);
338 }
339
340 public void parse() {
341 parse(header -> new AsmCodeFactory(this, header));
342 }
343
344 private boolean filterCursor(Cursor c) {
345 if (c.isDeclaration()) {
346 Type type = c.type();
347 if (type.kind() == TypeKind.FunctionProto ||
348 type.kind() == TypeKind.FunctionNoProto) {
349 String name = c.spelling();
350
351 if (isSymbolExcluded(name)) {
352 return false;
353 }
354
355 if (!isSymbolFound(name)) {
356 err.println(Main.format("warn.symbol.not.found", name));
357 }
358 }
359 }
360 return true;
361 }
362
363 public void parse(Function<HeaderFile, AsmCodeFactory> fn) {
364 initSymChecker();
365 initSymFilter();
366
367 List<HeaderTree> headers = parser.parse(sources, clangArgs, this::filterCursor);
368 processHeaders(headers, fn);
369 }
370
371 private void processHeaders(List<HeaderTree> headers, Function<HeaderFile, AsmCodeFactory> fn) {
372 headers.forEach(header -> {
373 HeaderFile hf = headerMap.computeIfAbsent(header.path(), p -> getHeaderFile(p, null));
374 hf.useLibraries(libraryNames, libraryPaths);
375 hf.useCodeFactory(fn.apply(hf));
376 logger.info(() -> "Processing header file " + header.path());
377
378 header.declarations().stream()
379 .peek(decl -> logger.finest(
380 () -> "Cursor: " + decl.name() + "@" + decl.USR() + "?" + decl.isDeclaration()))
381 .forEach(decl -> processTree(decl, hf, fn));
382 });
383 }
384
385 private Map<String, List<AsmCodeFactory>> getPkgCfMap() {
386 final Map<String, List<AsmCodeFactory>> mapPkgCf = new HashMap<>();
387 // Build the pkg to CodeFactory map
388 headerMap.values().forEach(header -> {
389 AsmCodeFactory cf = header.getCodeFactory();
390 String pkg = header.pkgName;
391 logger.config(() -> "File " + header + " is in package: " + pkg);
392 if (cf == null) {
|
35 import java.foreign.Library;
36 import java.nio.file.Files;
37 import java.nio.file.Path;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Collections;
41 import java.util.HashMap;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Properties;
45 import java.util.Set;
46 import java.util.TreeSet;
47 import java.util.function.Function;
48 import java.util.function.Predicate;
49 import java.util.jar.JarOutputStream;
50 import java.util.logging.Logger;
51 import java.util.regex.Pattern;
52 import java.util.stream.Collectors;
53 import java.util.zip.ZipEntry;
54 import com.sun.tools.jextract.parser.Parser;
55 import com.sun.tools.jextract.tree.FunctionTree;
56 import com.sun.tools.jextract.tree.HeaderTree;
57 import com.sun.tools.jextract.tree.Tree;
58
59 import static java.nio.file.StandardOpenOption.CREATE;
60 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
61 import static java.nio.file.StandardOpenOption.WRITE;
62
63 /**
64 * The setup for the tool execution
65 */
66 public final class Context {
67 // package name to TypeDictionary
68 private final Map<String, TypeDictionary> tdMap;
69 // The folder path mapping to package name
70 private final Map<Path, String> pkgMap;
71 // The header file parsed
72 private final Map<Path, HeaderFile> headerMap;
73 // The args for parsing C
74 private final List<String> clangArgs;
75 // The set of source header files
76 private final Set<Path> sources;
77 // The list of library names
325 logger.config(() -> "First encounter of header file " + hf.path + ", assigned to package " + hf.pkgName);
326 // Only generate code for header files sepcified or in the same package
327 // System headers are excluded, they need to be explicitly specified in jextract cmdline
328 if (sources.contains(p) ||
329 (!loc.isInSystemHeader()) && (header.pkgName.equals(main.pkgName))) {
330 logger.config("Code gen for header " + p + " enabled in package " + header.pkgName);
331 header.useCodeFactory(fn.apply(header));
332 }
333 headerMap.put(p, header);
334 }
335 }
336 }
337
338 header.processTree(tree, main, isBuiltIn);
339 }
340
341 public void parse() {
342 parse(header -> new AsmCodeFactory(this, header));
343 }
344
345 private boolean symbolFilter(Tree tree) {
346 String name = tree.name();
347 if (isSymbolExcluded(name)) {
348 return false;
349 }
350
351 // check for function symbols in libraries & warn missing symbols
352 if (tree instanceof FunctionTree && !isSymbolFound(name)) {
353 err.println(Main.format("warn.symbol.not.found", name));
354 }
355
356 return true;
357 }
358
359 public void parse(Function<HeaderFile, AsmCodeFactory> fn) {
360 initSymChecker();
361 initSymFilter();
362
363 List<HeaderTree> headers = parser.parse(sources, clangArgs);
364 processHeaders(headers, fn);
365 }
366
367 private void processHeaders(List<HeaderTree> headers, Function<HeaderFile, AsmCodeFactory> fn) {
368 headers.stream().
369 map((new TreeFilter(this::symbolFilter))::transform).
370 map((new TypedefHandler())::transform).
371 map((new EmptyNameHandler())::transform).
372 forEach(header -> {
373 HeaderFile hf = headerMap.computeIfAbsent(header.path(), p -> getHeaderFile(p, null));
374 hf.useLibraries(libraryNames, libraryPaths);
375 hf.useCodeFactory(fn.apply(hf));
376 logger.info(() -> "Processing header file " + header.path());
377
378 header.declarations().stream()
379 .peek(decl -> logger.finest(
380 () -> "Cursor: " + decl.name() + "@" + decl.USR() + "?" + decl.isDeclaration()))
381 .forEach(decl -> processTree(decl, hf, fn));
382 });
383 }
384
385 private Map<String, List<AsmCodeFactory>> getPkgCfMap() {
386 final Map<String, List<AsmCodeFactory>> mapPkgCf = new HashMap<>();
387 // Build the pkg to CodeFactory map
388 headerMap.values().forEach(header -> {
389 AsmCodeFactory cf = header.getCodeFactory();
390 String pkg = header.pkgName;
391 logger.config(() -> "File " + header + " is in package: " + pkg);
392 if (cf == null) {
|