001: /* (C) Copyright IBM Corp 2005-2007. */
002: package xtc.lang.jeannie;
003:
004: import java.io.BufferedWriter;
005: import java.io.File;
006: import java.io.FileWriter;
007: import java.io.IOException;
008: import java.io.PrintWriter;
009: import java.io.Reader;
010: import java.io.Writer;
011:
012: import xtc.lang.CPrinter;
013: import xtc.lang.JavaEntities;
014: import xtc.lang.JavaPrinter;
015: import xtc.parser.ParseException;
016: import xtc.parser.Result;
017: import xtc.parser.SemanticValue;
018: import xtc.tree.LineupPrinter;
019: import xtc.tree.Node;
020: import xtc.tree.Printer;
021: import xtc.tree.Visitor;
022: import xtc.util.Runtime;
023: import xtc.util.SymbolTable;
024: import xtc.util.Tool;
025:
026: /**
027: * A compiler from Jeannie to separate Java and C files that use JNI.
028: *
029: * @author Martin Hirzel
030: */
031: public final class Jeannie extends Tool {
032: public static String getStem(final String fileName) {
033: final int lastSlash = fileName.lastIndexOf(File.separatorChar);
034: final int extensionStart = fileName.indexOf('.', lastSlash);
035: return -1 == extensionStart ? fileName : fileName.substring(0,
036: extensionStart);
037: }
038:
039: public static void main(String[] args) {
040: new Jeannie().run(args);
041: }
042:
043: public final String getCopy() {
044: return "(C) 2005-2007 IBM, Robert Grimm, and NYU";
045: }
046:
047: public final String getName() {
048: return "Jeannie compiler";
049: }
050:
051: public final void init() {
052: super .init();
053: runtime
054: .bool("printAST", "printAST", false,
055: "Print the AST in generic form.")
056: .bool("printSource", "printSource", false,
057: "Print the AST in Jeannie source form.")
058: .bool("analyze", "optionAnalyze", false,
059: "Analyze the program's AST.")
060: .bool("printSymbolTable", "printSymbolTable", false,
061: "Print the program's symbol table.")
062: .bool("translate", "translate", false,
063: "Generate separate C and Java code.")
064: .bool("markAST", "optionMarkAST", true,
065: "Mark AST nodes with types.")
066: .bool("strict", "optionStrict", true,
067: "Enforce strict C99 compliance.")
068: .bool("pedantic", "optionPedantic", false,
069: "Enforce strict C99 compliance.")
070: .bool("pretty", "pretty", false,
071: "Optimize output for human-readability.")
072: .word(
073: "jniCall",
074: "jniCall",
075: false,
076: "Calling conventions qualifier to C JNI functions."
077: + " The default is the empty string \"\"."
078: + " On cygwin, use -jniCall \"__attribute__((__stdcall__))\".")
079: .bool(
080: "showFilePaths",
081: "showFilePaths",
082: false,
083: "Should line markers in the generated Java source code show "
084: + " file paths (true), or just relative file names (false)?");
085: runtime.setValue("optionMarkAST", true);
086: runtime.setValue("optionStrict", true);
087: runtime.setValue("optionPedantic", true);
088: }
089:
090: public final Node parse(final Reader in, final File file)
091: throws IOException, ParseException {
092: final Reader inUnescaped = new JavaEntities.UnicodeUnescaper(in);
093: final JeannieParser parser = new JeannieParser(inUnescaped,
094: file.toString(), (int) file.length());
095: final Result parseResult = parser.pFile(0);
096: if (!parseResult.hasValue())
097: parser.signal(parseResult.parseError());
098: final Node messy = (Node) ((SemanticValue) parseResult).value;
099: final Node result = (Node) new AstSimplifier(null)
100: .dispatch(messy);
101: result.setProperty("originalFileName", file.getCanonicalPath());
102: return result;
103: }
104:
105: public final void prepare() {
106: super .prepare();
107: if (runtime.test("printSymbolTable")
108: || runtime.test("translate"))
109: if (!runtime.test("optionAnalyze"))
110: runtime
111: .error("need analyze option to obtain symbol table");
112: }
113:
114: public final void process(final Node node) {
115: if (runtime.test("optionAnalyze")) {
116: // Make sure the classpath is set.
117: if (!runtime.hasValue(Runtime.INPUT_DIRECTORY))
118: runtime.setValue(Runtime.INPUT_DIRECTORY, new File(
119: System.getProperty("user.dir")));
120:
121: // Perform type checking.
122: final SymbolTable tab = new SymbolTable();
123: final Analyzer ana = new Analyzer(runtime, tab, null);
124: ana.dispatch(node);
125: if (0 < runtime.errorCount())
126: System.exit(-1);
127:
128: // Print the symbol table.
129: if (runtime.test("printSymbolTable")) {
130: final Visitor visitor = runtime.console().visitor();
131: try {
132: tab.root().dump(runtime.console());
133: } finally {
134: runtime.console().register(visitor);
135: }
136: runtime.console().flush();
137: }
138:
139: // Generate code.
140: if (runtime.test("translate")) {
141: final String outStem = getStem((String) node
142: .getProperty("originalFileName"));
143: final boolean sfp = runtime.test("showFilePaths");
144: final CodeGenerator cg = new CodeGenerator(runtime, tab);
145: final CodeGenerator.Out cgOut = (CodeGenerator.Out) cg
146: .dispatch(node);
147: try {
148: final Writer writer = new BufferedWriter(
149: new FileWriter(outStem + ".i"));
150: final Printer printer = runtime.test("pretty") ? new Printer(
151: writer)
152: : new LineupPrinter(writer, sfp);
153: new CPrinter(printer).dispatch(cgOut._cNode);
154: printer.flush();
155: writer.close();
156: } catch (final IOException e) {
157: throw new Error(e);
158: }
159: try {
160: final Writer writer = new BufferedWriter(
161: new FileWriter(outStem + ".java"));
162: final Printer printer = runtime.test("pretty") ? new Printer(
163: writer)
164: : new LineupPrinter(writer, sfp);
165: new JavaPrinter(printer).dispatch(cgOut._javaNode);
166: printer.flush();
167: writer.close();
168: } catch (final IOException e) {
169: throw new Error(e);
170: }
171: if (!runtime.test("pretty"))
172: try {
173: final PrintWriter writer = new PrintWriter(
174: new FileWriter(outStem + ".jni.symbols"));
175: Utilities.printTopLevelDeclarations(writer,
176: cgOut._javaNode);
177: writer.println();
178: Utilities.printLocalVariableMap(writer, node,
179: tab, cg._cSubstitutions,
180: cg._javaSubstitutions);
181: writer.close();
182: } catch (final IOException e) {
183: throw new Error(e);
184: }
185: }
186: }
187: if (runtime.test("printAST")) {
188: runtime.console().format(node).pln().flush();
189: }
190: if (runtime.test("printSource")) {
191: new JeanniePrinter(runtime.console(), null).dispatch(node);
192: runtime.console().flush();
193: }
194: }
195: }
|