ParseSystemLibrary.java
package dev.civl.mc.run.common;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import dev.civl.abc.ast.IF.AST;
import dev.civl.abc.ast.node.IF.ASTNode;
import dev.civl.abc.ast.node.IF.ASTNode.NodeKind;
import dev.civl.abc.main.ABCExecutor;
import dev.civl.abc.main.DynamicTask;
import dev.civl.abc.main.UnitTask;
import dev.civl.abc.token.IF.SourceFile;
import dev.civl.mc.config.IF.CIVLConstants;
public class ParseSystemLibrary implements DynamicTask {
private ABCExecutor executor;
private Map<String, String> macros;
/**
* the index of the AST that has been last visited, initially -1
*/
private int lastSeenAST = -1;
/**
* true iff the unit task for system library implementation civl-omp.cvl has
* been added.
*
*/
private boolean civlOmpAdded = false;
/**
* true iff the OpenMP header omp.h is present. Initialized as false.
*/
private boolean hasOmpHeader = false;
public ParseSystemLibrary(ABCExecutor executor,
Map<String, String> macros) {
this.executor = executor;
this.macros = macros;
}
private Set<String> getExistingFiles() {
int num = executor.getNumCompleteUnitTasks();
Set<String> fileNames = new HashSet<>();
for (int i = 0; i < num; i++) {
AST ast = executor.getAST(i);
Collection<SourceFile> files = ast.getSourceFiles();
for (SourceFile file : files) {
String filename = file.getName();
fileNames.add(filename);
}
}
return fileNames;
}
@Override
public UnitTask[] generateTasks() {
int num = executor.getNumCompleteUnitTasks();
List<UnitTask> result = new ArrayList<>();
Set<String> existingFiles = getExistingFiles();
Set<String> processedFiles = new HashSet<>();
for (int i = this.lastSeenAST + 1; i < num; i++) {
AST ast = executor.getAST(i);
Collection<SourceFile> files = ast.getSourceFiles();
for (SourceFile file : files) {
String filename = file.getName();
if (!processedFiles.add(filename))
continue;
File systemFile = getSystemImplementation(file.getFile());
if (filename.equals(CIVLConstants.OMP))
this.hasOmpHeader = true;
if (systemFile != null) {
String systemFilename = systemFile.getName();
if (!existingFiles.contains(systemFilename)
&& processedFiles.add(systemFilename)) {
result.add(newUnitTask(systemFile));
}
}
}
if (!hasOmpHeader && !this.civlOmpAdded) {
if (this.hasOmpPragma(ast.getRootNode())) {
result.add(newUnitTask(
new File(CIVLConstants.CIVL_LIB_SRC_PATH,
CIVLConstants.CIVL_OMP_SRC)));
this.civlOmpAdded = true;
}
}
}
this.lastSeenAST = num - 1;
UnitTask[] tasks = new UnitTask[result.size()];
return result.toArray(tasks);
}
private UnitTask newUnitTask(File systemFile) {
UnitTask newTask = new UnitTask(new File[]{systemFile});
newTask.setMacros(macros);
return newTask;
}
private boolean hasOmpPragma(ASTNode node) {
if (node.nodeKind() == NodeKind.OMP_NODE)
return true;
for (ASTNode child : node.children()) {
if (child != null) {
if (hasOmpPragma(child))
return true;
}
}
return false;
}
/**
* Finds out the file name of the system implementation of a header file,
* which stands for a certain system library, such as civlc.cvh, mpi.h,
* omp.h, stdio.h, etc.
*
* @param file
* @return The file name of the system implementation of the given header
* file, or null if there is no implementation of the header file.
*/
private File getSystemImplementation(File file) {
// Check that the path is one of the system include
// paths. Because a user could create their own "pthread.h"
// (for example), in which case we don't want to link in the
// system implementation.
if (!file.getPath().startsWith(CIVLConstants.ROOT_RESOURCE_PATH_STR))
return null;
// for debugging...
// System.out.println("Including system file: "+file.getPath());
String name = file.getName();
if (CIVLConstants.getCivlLibHeaders().contains(name)) {
String srcName = name.substring(0, name.length() - 1) + "l";
if (CIVLConstants.getCivlLibSrcs().contains(srcName))
return new File(CIVLConstants.CIVL_LIB_SRC_PATH, srcName);
} else if (CIVLConstants.getCStdLibHeaders().contains(name)) {
String srcName = name.substring(0, name.length() - 1) + "cvl";
if (CIVLConstants.getCStdLibSrcs().contains(srcName))
return new File(CIVLConstants.CIVL_LIB_SRC_PATH, srcName);
}
return null;
}
}