< prev index next >

src/jdk.jextract/share/classes/com/sun/tools/jextract/Context.java

Print this page




  66 /**
  67  * The setup for the tool execution
  68  */
  69 public final class Context {
  70     // package name to TypeDictionary
  71     private final Map<String, TypeDictionary> tdMap;
  72     // The folder path mapping to package name
  73     private final Map<Path, String> pkgMap;
  74     // The header file parsed
  75     private final Map<Path, HeaderFile> headerMap;
  76     // The args for parsing C
  77     private final List<String> clangArgs;
  78     // The set of source header files
  79     private final Set<Path>  sources;
  80     // The list of library names
  81     private final List<String> libraryNames;
  82     // The list of library paths
  83     private final List<String> libraryPaths;
  84     // The list of library paths for link checks
  85     private final List<String> linkCheckPaths;


  86     // Symbol patterns to be excluded
  87     private final List<Pattern> excludeSymbols;
  88     // generate static forwarder class or not?
  89     private boolean genStaticForwarder;
  90 
  91     final PrintWriter out;
  92     final PrintWriter err;
  93 
  94     private Predicate<String> symChecker;
  95     private Predicate<String> symFilter;

  96 
  97     private final Parser parser;
  98 
  99     private final static String defaultPkg = "jextract.dump";
 100     final Logger logger = Logger.getLogger(getClass().getPackage().getName());
 101 
 102     public Context(PrintWriter out, PrintWriter err) {
 103         this.tdMap = new HashMap<>();
 104         this.pkgMap = new HashMap<>();
 105         this.headerMap = new HashMap<>();
 106         this.clangArgs = new ArrayList<>();
 107         this.sources = new TreeSet<>();
 108         this.libraryNames = new ArrayList<>();
 109         this.libraryPaths = new ArrayList<>();
 110         this.linkCheckPaths = new ArrayList<>();

 111         this.excludeSymbols = new ArrayList<>();
 112         this.parser = new Parser(out, err, Main.INCLUDE_MACROS);
 113         this.out = out;
 114         this.err = err;
 115     }
 116 
 117     public Context() {
 118         this(new PrintWriter(System.out, true), new PrintWriter(System.err, true));
 119     }
 120 
 121     TypeDictionary typeDictionaryFor(String pkg) {
 122         return tdMap.computeIfAbsent(pkg, p->new TypeDictionary(this, p));
 123     }
 124 
 125     void addClangArg(String arg) {
 126         clangArgs.add(arg);
 127     }
 128 
 129     public void addSource(Path path) {
 130         sources.add(path);
 131     }
 132 
 133     void addLibraryName(String name) {
 134         libraryNames.add(name);
 135     }
 136 
 137     void addLibraryPath(String path) {
 138         libraryPaths.add(path);
 139     }
 140 
 141     void addLinkCheckPath(String path) {
 142         linkCheckPaths.add(path);
 143     }
 144 




 145     void addExcludeSymbols(String pattern) {
 146         excludeSymbols.add(Pattern.compile(pattern));
 147     }
 148 
 149     void setGenStaticForwarder(boolean flag) {
 150         this.genStaticForwarder = flag;
 151     }
 152 
 153     // return the absolute path of the library of given name by searching
 154     // in the given array of paths.
 155     private static Optional<Path> findLibraryPath(Path[] paths, String libName) {
 156          return Arrays.stream(paths).
 157               map(p -> p.resolve(System.mapLibraryName(libName))).
 158               filter(Files::isRegularFile).map(Path::toAbsolutePath).findFirst();
 159     }
 160 
 161     /*
 162      * Load the specified shared libraries from the specified paths.
 163      *
 164      * @param lookup Lookup object of the caller.


 201                                 }
 202                                 return true;
 203                             } catch (NoSuchMethodException nsme) {
 204                                 return false;
 205                             }
 206                         }).findFirst().isPresent());
 207                 };
 208             } catch (UnsatisfiedLinkError ex) {
 209                 err.println(Main.format("warn.lib.not.found"));
 210                 symChecker = null;
 211             }
 212         } else {
 213             symChecker = null;
 214         }
 215     }
 216 
 217     private boolean isSymbolFound(String name) {
 218         return symChecker == null? true : symChecker.test(name);
 219     }
 220 
 221     private void initSymFilter() {










 222         if (!excludeSymbols.isEmpty()) {
 223             Pattern[] pats = excludeSymbols.toArray(new Pattern[0]);
 224             symFilter = name -> {
 225                 return Arrays.stream(pats).filter(pat -> pat.matcher(name).matches()).
 226                     findFirst().isPresent();
 227             };
 228         } else {
 229             symFilter = null;
 230         }
 231     }
 232 




 233     private boolean isSymbolExcluded(String name) {
 234         return symFilter == null? false : symFilter.test(name);
 235     }
 236 
 237     /**
 238      * Setup a package name for a given folder.
 239      *
 240      * @param folder The path to the folder, use null to set catch-all.
 241      * @param pkg    The package name
 242      * @return True if the folder is setup successfully. False is a package
 243      * has been assigned for the folder.
 244      */
 245     public boolean usePackageForFolder(Path folder, String pkg) {
 246         if (folder != null) {
 247             folder = folder.toAbsolutePath();
 248             if (!Files.isDirectory(folder)) {
 249                 folder = folder.getParent();
 250             }
 251         }
 252         String existing = pkgMap.putIfAbsent(folder, pkg);
 253         final String finalFolder = (null == folder) ? "all folders not configured" : folder.toString();
 254         if (null == existing) {


 373                     if (sources.contains(p) ||
 374                         (header.pkgName.equals(main.pkgName))) {
 375                         logger.config("Code gen for header " + p + " enabled in package " + header.pkgName);
 376                         header.useCodeFactory(fn.apply(header));
 377                     }
 378                     headerMap.put(p, header);
 379                 }
 380             }
 381         }
 382 
 383         header.processTree(tree, main, isBuiltIn);
 384     }
 385 
 386     public void parse() {
 387         parse(header -> genStaticForwarder?
 388             new AsmCodeFactoryExt(this, header) : new AsmCodeFactory(this, header));
 389     }
 390 
 391     private boolean symbolFilter(Tree tree) {
 392          String name = tree.name();
 393          if (isSymbolExcluded(name)) {
 394              return false;
 395          }
 396 
 397          // check for function symbols in libraries & warn missing symbols
 398          if (tree instanceof FunctionTree && !isSymbolFound(name)) {
 399              err.println(Main.format("warn.symbol.not.found", name));
 400              //auto-exclude symbols not found
 401              return false;
 402          }
 403 
 404          return true;
 405     }
 406 
 407     public void parse(Function<HeaderFile, AsmCodeFactory> fn) {
 408         initSymChecker();
 409         initSymFilter();
 410 
 411         List<HeaderTree> headers = parser.parse(sources, clangArgs);
 412         processHeaders(headers, fn);
 413     }
 414 
 415     private void processHeaders(List<HeaderTree> headers, Function<HeaderFile, AsmCodeFactory> fn) {
 416         headers.stream().
 417                 map(new TreeFilter(this::symbolFilter)).
 418                 map(new TypedefHandler()).
 419                 map(new EmptyNameHandler()).
 420                 forEach(header -> {
 421             HeaderFile hf = headerMap.computeIfAbsent(header.path(), p -> getHeaderFile(p, null));
 422             hf.useCodeFactory(fn.apply(hf));
 423             logger.info(() -> "Processing header file " + header.path());
 424 
 425             header.declarations().stream()
 426                     .peek(decl -> logger.finest(
 427                         () -> "Cursor: " + decl.name() + "@" + decl.USR() + "?" + decl.isDeclaration()))
 428                     .forEach(decl -> processTree(decl, hf, fn));
 429         });




  66 /**
  67  * The setup for the tool execution
  68  */
  69 public final class Context {
  70     // package name to TypeDictionary
  71     private final Map<String, TypeDictionary> tdMap;
  72     // The folder path mapping to package name
  73     private final Map<Path, String> pkgMap;
  74     // The header file parsed
  75     private final Map<Path, HeaderFile> headerMap;
  76     // The args for parsing C
  77     private final List<String> clangArgs;
  78     // The set of source header files
  79     private final Set<Path>  sources;
  80     // The list of library names
  81     private final List<String> libraryNames;
  82     // The list of library paths
  83     private final List<String> libraryPaths;
  84     // The list of library paths for link checks
  85     private final List<String> linkCheckPaths;
  86     // Symbol patterns to be included
  87     private final List<Pattern> includeSymbols;
  88     // Symbol patterns to be excluded
  89     private final List<Pattern> excludeSymbols;
  90     // generate static forwarder class or not?
  91     private boolean genStaticForwarder;
  92 
  93     final PrintWriter out;
  94     final PrintWriter err;
  95 
  96     private Predicate<String> symChecker;
  97     private Predicate<String> includeSymFilter;
  98     private Predicate<String> excludeSymFilter;
  99 
 100     private final Parser parser;
 101 
 102     private final static String defaultPkg = "jextract.dump";
 103     final Logger logger = Logger.getLogger(getClass().getPackage().getName());
 104 
 105     public Context(PrintWriter out, PrintWriter err) {
 106         this.tdMap = new HashMap<>();
 107         this.pkgMap = new HashMap<>();
 108         this.headerMap = new HashMap<>();
 109         this.clangArgs = new ArrayList<>();
 110         this.sources = new TreeSet<>();
 111         this.libraryNames = new ArrayList<>();
 112         this.libraryPaths = new ArrayList<>();
 113         this.linkCheckPaths = new ArrayList<>();
 114         this.includeSymbols = new ArrayList<>();
 115         this.excludeSymbols = new ArrayList<>();
 116         this.parser = new Parser(out, err, Main.INCLUDE_MACROS);
 117         this.out = out;
 118         this.err = err;
 119     }
 120 
 121     public Context() {
 122         this(new PrintWriter(System.out, true), new PrintWriter(System.err, true));
 123     }
 124 
 125     TypeDictionary typeDictionaryFor(String pkg) {
 126         return tdMap.computeIfAbsent(pkg, p->new TypeDictionary(this, p));
 127     }
 128 
 129     void addClangArg(String arg) {
 130         clangArgs.add(arg);
 131     }
 132 
 133     public void addSource(Path path) {
 134         sources.add(path);
 135     }
 136 
 137     void addLibraryName(String name) {
 138         libraryNames.add(name);
 139     }
 140 
 141     void addLibraryPath(String path) {
 142         libraryPaths.add(path);
 143     }
 144 
 145     void addLinkCheckPath(String path) {
 146         linkCheckPaths.add(path);
 147     }
 148 
 149     void addIncludeSymbols(String pattern) {
 150         includeSymbols.add(Pattern.compile(pattern));
 151     }
 152 
 153     void addExcludeSymbols(String pattern) {
 154         excludeSymbols.add(Pattern.compile(pattern));
 155     }
 156 
 157     void setGenStaticForwarder(boolean flag) {
 158         this.genStaticForwarder = flag;
 159     }
 160 
 161     // return the absolute path of the library of given name by searching
 162     // in the given array of paths.
 163     private static Optional<Path> findLibraryPath(Path[] paths, String libName) {
 164          return Arrays.stream(paths).
 165               map(p -> p.resolve(System.mapLibraryName(libName))).
 166               filter(Files::isRegularFile).map(Path::toAbsolutePath).findFirst();
 167     }
 168 
 169     /*
 170      * Load the specified shared libraries from the specified paths.
 171      *
 172      * @param lookup Lookup object of the caller.


 209                                 }
 210                                 return true;
 211                             } catch (NoSuchMethodException nsme) {
 212                                 return false;
 213                             }
 214                         }).findFirst().isPresent());
 215                 };
 216             } catch (UnsatisfiedLinkError ex) {
 217                 err.println(Main.format("warn.lib.not.found"));
 218                 symChecker = null;
 219             }
 220         } else {
 221             symChecker = null;
 222         }
 223     }
 224 
 225     private boolean isSymbolFound(String name) {
 226         return symChecker == null? true : symChecker.test(name);
 227     }
 228 
 229     private void initSymFilters() {
 230         if (!includeSymbols.isEmpty()) {
 231             Pattern[] pats = includeSymbols.toArray(new Pattern[0]);
 232             includeSymFilter = name -> {
 233                 return Arrays.stream(pats).filter(pat -> pat.matcher(name).matches()).
 234                     findFirst().isPresent();
 235             };
 236         } else {
 237             includeSymFilter = null;
 238         }
 239 
 240         if (!excludeSymbols.isEmpty()) {
 241             Pattern[] pats = excludeSymbols.toArray(new Pattern[0]);
 242             excludeSymFilter = name -> {
 243                 return Arrays.stream(pats).filter(pat -> pat.matcher(name).matches()).
 244                     findFirst().isPresent();
 245             };
 246         } else {
 247             excludeSymFilter = null;
 248         }
 249     }
 250 
 251     private boolean isSymbolIncluded(String name) {
 252         return includeSymFilter == null? true : includeSymFilter.test(name);
 253     }
 254 
 255     private boolean isSymbolExcluded(String name) {
 256         return excludeSymFilter == null? false : excludeSymFilter.test(name);
 257     }
 258 
 259     /**
 260      * Setup a package name for a given folder.
 261      *
 262      * @param folder The path to the folder, use null to set catch-all.
 263      * @param pkg    The package name
 264      * @return True if the folder is setup successfully. False is a package
 265      * has been assigned for the folder.
 266      */
 267     public boolean usePackageForFolder(Path folder, String pkg) {
 268         if (folder != null) {
 269             folder = folder.toAbsolutePath();
 270             if (!Files.isDirectory(folder)) {
 271                 folder = folder.getParent();
 272             }
 273         }
 274         String existing = pkgMap.putIfAbsent(folder, pkg);
 275         final String finalFolder = (null == folder) ? "all folders not configured" : folder.toString();
 276         if (null == existing) {


 395                     if (sources.contains(p) ||
 396                         (header.pkgName.equals(main.pkgName))) {
 397                         logger.config("Code gen for header " + p + " enabled in package " + header.pkgName);
 398                         header.useCodeFactory(fn.apply(header));
 399                     }
 400                     headerMap.put(p, header);
 401                 }
 402             }
 403         }
 404 
 405         header.processTree(tree, main, isBuiltIn);
 406     }
 407 
 408     public void parse() {
 409         parse(header -> genStaticForwarder?
 410             new AsmCodeFactoryExt(this, header) : new AsmCodeFactory(this, header));
 411     }
 412 
 413     private boolean symbolFilter(Tree tree) {
 414          String name = tree.name();
 415          if (!isSymbolIncluded(name) || isSymbolExcluded(name)) {
 416              return false;
 417          }
 418 
 419          // check for function symbols in libraries & warn missing symbols
 420          if (tree instanceof FunctionTree && !isSymbolFound(name)) {
 421              err.println(Main.format("warn.symbol.not.found", name));
 422              //auto-exclude symbols not found
 423              return false;
 424          }
 425 
 426          return true;
 427     }
 428 
 429     public void parse(Function<HeaderFile, AsmCodeFactory> fn) {
 430         initSymChecker();
 431         initSymFilters();
 432 
 433         List<HeaderTree> headers = parser.parse(sources, clangArgs);
 434         processHeaders(headers, fn);
 435     }
 436 
 437     private void processHeaders(List<HeaderTree> headers, Function<HeaderFile, AsmCodeFactory> fn) {
 438         headers.stream().
 439                 map(new TreeFilter(this::symbolFilter)).
 440                 map(new TypedefHandler()).
 441                 map(new EmptyNameHandler()).
 442                 forEach(header -> {
 443             HeaderFile hf = headerMap.computeIfAbsent(header.path(), p -> getHeaderFile(p, null));
 444             hf.useCodeFactory(fn.apply(hf));
 445             logger.info(() -> "Processing header file " + header.path());
 446 
 447             header.declarations().stream()
 448                     .peek(decl -> logger.finest(
 449                         () -> "Cursor: " + decl.name() + "@" + decl.USR() + "?" + decl.isDeclaration()))
 450                     .forEach(decl -> processTree(decl, hf, fn));
 451         });


< prev index next >