package de.fuberlin.projectF.CodeGenerator;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import de.fuberlin.projectF.CodeGenerator.model.Token;
//Dies ist die Hauptklasse des Projekts und kümmert sich um globale angelegenheiten wie
//die übergebenen Parameter. Sie stellt auch das Interface zur Anbindung an das Hauptprojekt dar.
public class CodeGenerator {
//Variante f�r File-Input
public static String generateCode(File llvmFile, String asmType, boolean debug,
boolean guiFlag) {
Debuginfo debuginfo = new Debuginfo(debug);
try {
Lexer lex = new FileLexer(llvmFile, debuginfo);
return generateCode2(debuginfo, asmType, guiFlag, lex);
} catch (FileNotFoundException e) {
System.err.println("Could't find input file " + llvmFile);
e.printStackTrace();
}
return "";
}
//Variante f�r String-Input
public static String generateCode(String llvmCode, String asmType, boolean debug,
boolean guiFlag) {
Debuginfo debuginfo = new Debuginfo(debug);
Lexer lex = new StringLexer(llvmCode, debuginfo);
return generateCode2(debuginfo, asmType, guiFlag, lex);
}
//extrahiert weil wir jetzt 2 verschiedene Lexer haben
private static String generateCode2(Debuginfo debuginfo, String asmType, boolean guiFlag,
Lexer lex) {
// Variablenverwaltung und Übersetzter erstellen
Translator trans = new Translator(asmType);
// Token durchgehen und übersetzten bis EOF
GUI gui = null;
int linecount = 0;
ArrayList<Token> tokenStream;
// Token einlesen
debuginfo.println("---> Start LLVM Code Parser --->\n");
tokenStream = lex.getTokenStream();
if(tokenStream == null) {
System.out.println("Error");
}
lex.close();
debuginfo.println("\n<--- LLVM Code Parser finished <---");
// Token informationen ausgeben
debuginfo.println("---> Print out detailed token information --->\n");
if (debuginfo.getDebugflag()) {
for (Token t : tokenStream) {
System.out.println("Token #" + linecount++);
t.print();
}
}
debuginfo.println("\n<--- Print out Token information end <---");
// Token Tabelle in der gui füllen
if (guiFlag) {
gui = new GUI();
gui.updateTokenStreamTable(tokenStream);
}
// Token übersetzen
try {
debuginfo.println("---> Start of translation --->\n");
trans.translate(tokenStream);
} catch (Exception e) {
e.printStackTrace();
if (guiFlag) {
gui.updateCodeArea(trans.getCode());
gui.appendCodeArea("\nError:\n");
for (StackTraceElement errStack : e.getStackTrace())
gui.appendCodeArea("at " + errStack.getMethodName() + "("
+ errStack.getFileName() + ":"
+ errStack.getLineNumber() + ")");
}
}
debuginfo.println("\n<--- Translation finished <---");
// Ausgabe des erzeugten Code's
debuginfo.println("---> Print out generated assembler code --->\n");
if (debuginfo.getDebugflag()) {
trans.print();
}
debuginfo.println("\n<--- End of generated code<---");
// Ausgabe des erzeugten Code's in die GUI
if (guiFlag)
gui.updateCodeArea(trans.getCode());
// Rückgabe des erzeugten Code's
return trans.getCode();
}
public static void main(String[] args) {
boolean debug = false;
boolean gui = false;
boolean exec = false;
String asmType = "gnu";
ArrayList<String> inputFile = new ArrayList<String>();
//Inhalt der inputFiles als String
String outputFile = null;
String configFile = "mc_config.cfg";
// Argumente parsen
for (int i = 0; i < args.length; i++) {
if (args[i].compareTo("-o") == 0 || args[i].compareTo("--output") == 0) {
if ((i + 1) <= args.length)
outputFile = args[++i];
else {
System.err.println("Option -o needs a second parameter");
return;
}
} else if (args[i].compareTo("-C") == 0 || args[i].compareTo("--config") == 0) {
if ((i + 1) <= args.length)
configFile = args[++i];
else {
System.err.println("Option -C needs a second parameter");
return;
}
} else if (args[i].compareTo("-asmType") == 0) {
if ((i + 1) <= args.length){
i++;
if(args[i].compareTo("intel") == 0)
asmType = "intel";
else if(args[i].compareTo("gnu") == 0)
asmType = "gnu";
else {
System.err.println("The assembler type " + args[i] + " is not supported");
return;
}
} else {
System.err.println("Option -asmType needs a second parameter");
return;
}
} else if (args[i].compareTo("-e") == 0 || args[i].compareTo("--exec") == 0) {
exec = true;
} else if (args[i].compareTo("-intel") == 0) {
asmType = "intel";
} else if (args[i].compareTo("-gnu") == 0) {
asmType = "gnu";
} else if (args[i].compareTo("-v") == 0 || args[i].compareTo("--verbose") == 0) {
debug = true;
} else if (args[i].compareTo("-g") == 0 || args[i].compareTo("--gui") == 0) {
gui = true;
} else
inputFile.add(args[i]);
}
// Argumente Fehlerbehandlung
if (inputFile.size() == 0) {
System.err.println("No inputfile spezified!");
return;
}
for (String filename : inputFile) {
File file = new File(filename);
String output = generateCode(file, asmType, debug, gui);
if (outputFile != null) {
writeFile(exec, outputFile, output);
}
}
//Wenn -e gesetzt dann erstelle die auszuführende Datei anhand der Befehle
//aus der mit -C angegebenen Config datei
if (exec == true) {
exec(outputFile, configFile);
}
}
//Schreiben des erzeugten Assemblercodes in die Ausgabedatei
public static void writeFile(boolean exec, String outputFile, String output) {
try{
FileOutputStream schreibeStrom;
//Falls -e gesetzt schreibe den Code in eine .asm Datei
if(exec == true)
schreibeStrom = new FileOutputStream(outputFile + ".asm");
//Falls -e nicht gesetzt schreibeCode direkt in die Ausgabedatei
else
schreibeStrom = new FileOutputStream(outputFile);
for (int i=0; i < output.length(); i++){
schreibeStrom.write((byte)output.charAt(i));
}
schreibeStrom.close();
}catch(IOException e) {
System.err.println("Couldn't write output file");
e.printStackTrace();
}
}
//Diese Funktion liesst die einzelnen Zeilen der Config Datei,
//ersetzt in den gelesenen Zeilen die Platzhalter <input> und <output>
//und führt dies dann als Befehle auf der Commandozeile aus
public static void exec(String outputFile, String configFile) {
//Testen on Windows oder Linux
if(System.getProperty("os.name").toLowerCase().indexOf("windows") >= 0 ||
System.getProperty("os.name").toLowerCase().indexOf("linux") >= 0) {
String line;
FileInputStream fstream;
DataInputStream in;
BufferedReader br;
try {
//Lesen der Config Datei Zeilen
fstream = new FileInputStream(configFile);
in = new DataInputStream(fstream);
br = new BufferedReader(new InputStreamReader(in));
while ((line = br.readLine()) != null) {
line = line.trim();
if (line.length() == 0 || line.charAt(0) == '#') {
continue;
}
//ersetzen der Platzhalter
line = line.replace("<input>", outputFile + ".asm");
line = line.replace("<output>", outputFile);
//ausführen der gelesenen Zeile
Runtime.getRuntime().exec(line).waitFor();
}
fstream.close();
//Fehlerbehandlung
} catch (FileNotFoundException e) {
System.err.println("Could't find config file");
e.printStackTrace();
} catch(IOException e) {
System.err.println("Failed to read from config file");
e.printStackTrace();
} catch (InterruptedException e) {
System.err.println("Failed to execute command");
e.printStackTrace();
}
} else {
System.err.println("unknown oparating system detected");
}
}
}