LibraryLoader.java

package edu.udel.cis.vsl.tass.front.minimp.lib;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import edu.udel.cis.vsl.tass.config.RunConfiguration;
import edu.udel.cis.vsl.tass.config.VerifyConfiguration;
import edu.udel.cis.vsl.tass.front.minimp.ast.declaration.ASTDeclarationIF;
import edu.udel.cis.vsl.tass.front.minimp.ast.declaration.ASTFunctionDeclaration;
import edu.udel.cis.vsl.tass.front.minimp.ast.declaration.ASTVariableDeclaration;
import edu.udel.cis.vsl.tass.front.minimp.ast.misc.AST;
import edu.udel.cis.vsl.tass.front.minimp.parser.TreeParser;
import edu.udel.cis.vsl.tass.model.IF.SyntaxException;
import edu.udel.cis.vsl.tass.util.Sourceable;

public class LibraryLoader {
	Map<String, LibraryIF> cache = new HashMap<String, LibraryIF>();

	/**
	 * Get the library with the give name. The source should be the source
	 * object for the "#include ..." line in the source file. It is used to
	 * report error if the library is not found.
	 * 
	 * NOTE: the "name" of the library is something like "stdlib.h" but the
	 * library file that is loaded will be "libstdlib.c" in the directory
	 * defined by "tass.library.path", which is currently the directory
	 * .../tass/lib.
	 */
	public LibraryIF loadLibrary(Sourceable source, String name)
			throws SyntaxException {
		LibraryIF library = cache.get(name);
		if (library != null)
			return library;
		library = load(source, name);
		cache.put(name, library);
		return library;
	}

	private LibraryIF load(Sourceable source, String name)
			throws SyntaxException {
		LibraryIF library = new Library(name);
		RunConfiguration configuration = new VerifyConfiguration();
		TreeParser parser = null;
		int index = name.lastIndexOf('.');
		if (index == -1)
			name = name + ".c";
		else
			name = name.substring(0, index + 1) + "c";

		String fileName = System.getProperty("tass.library.path") + "/lib"
				+ name;
		try {
			parser = new TreeParser(fileName, configuration, null);
		} catch (IOException e) {
			throw new SyntaxException(source, "Failed to load library: "
					+ fileName);
		}
		AST parsedLibrary = parser.processAST();

		// TODO: the library loaded might include other libraries...

		Collection<String> subLibs = parsedLibrary.getLibraryNames();
		List<ASTFunctionDeclaration> functionList = parsedLibrary
				.getFunctionList();

		List<ASTVariableDeclaration> inputs = new LinkedList<ASTVariableDeclaration>();
		for (ASTDeclarationIF d : parsedLibrary.getGlobalVariableList()) {
			if (!(d instanceof ASTVariableDeclaration)) {
				throw new SyntaxException(source, "Global variable "
						+ d.getName().toString() + " should be a variable.");
			} else {
				inputs.add((ASTVariableDeclaration) d);
			}
		}
		((Library) library).addInputs(inputs);
		((Library) library).addFunctions(functionList);
		((Library) library).addTypes(parsedLibrary.getTypeNameMap());
		((Library) library).addConstants(parsedLibrary.getConstantMap());
		((Library) library).addLibrariesUsed(subLibs);
		return library;
	}
}