public void ImportPexts(ArrayList pextsList) { Utilities.Utilities.VerbouseOut("PREPROCESSOR", "Reading pext list"); foreach (pextData pextName in pextsList) { pexts = pexts.Concat(CodeIO.LoadPext(pextName.pextName, pextName.mountPoint)).GroupBy(i => i.Key).ToDictionary(group => group.Key, group => group.First().Value); } }
public Preprocessor(ArrayList importsList) { Utilities.Utilities.VerbouseOut("PREPROCESSOR", "Reading macroses list"); foreach (string macrosName in importsList) { imports = imports.Concat(CodeIO.LoadMacros(macrosName)).GroupBy(i => i.Key).ToDictionary(group => group.Key, group => group.First().Value); } }
public Assembly(string programName) { this.programName = programName; string[] lines = CodeIO.LoadFile(programName); //Clearing Code //Removing comments and trimming Utilities.Utilities.VerbouseOut("-=-=Clearing code from comments=-=-"); lines = ClearCode(lines); Utilities.Utilities.VerbouseOut("-=-=Parsing lines=-=-"); parsed = SplitCode(lines); //Get hat Utilities.Utilities.VerbouseOut("-=-=Parsing libraries imports=-=-"); ArrayList imports = GetImports(parsed); //Catching imports Utilities.Utilities.VerbouseOut("Importing"); importManager = new Preprocessor(imports); //Calling preprocessor Utilities.Utilities.VerbouseOut("PREPROCESSOR", "Inserting macroses..."); for (int i = 0; i < importManager.CountMacroses(); i++) { parsed = InsertAllMacro(parsed); } Utilities.Utilities.VerbouseOut("PREPROCESSOR", "Updated code: "); if (Program.verboseMode) { for (int j = 0; j < parsed.Length; j++) { Console.Write(j + ":\t"); for (int k = 0; k < parsed[j].Length; k++) { Console.Write(parsed[j][k] + " "); } Console.WriteLine(); } } Utilities.Utilities.VerbouseOut("PREPROCESSOR", "Finding definitions..."); parsed = importManager.CatchDefines(parsed); var safer = new List <string[]>(); for (int i = 0; i < parsed.Length; i++) { if (parsed[i] != null) { safer.Add(parsed[i]); } } parsed = safer.ToArray(); Utilities.Utilities.VerbouseOut("-=-=Parsing pExts=-=-"); ArrayList pexts = GetPexts(parsed); importManager.ImportPexts(pexts); Utilities.Utilities.VerbouseOut("Removing preprocessor code from source..."); parsed = ClearHatAfterImport(parsed); //Catching labels Utilities.Utilities.VerbouseOut("Parsing labels..."); CodeLine[] code = LabelCatcher(parsed); //Converting code to object form Utilities.Utilities.VerbouseOut("PREPROCESSOR", "Cleared code: "); if (Program.verboseMode) { for (int j = 0; j < parsed.Length; j++) { Console.Write(j + ":\t"); for (int k = 0; k < parsed[j].Length; k++) { Console.Write(parsed[j][k] + " "); } Console.WriteLine(); } } Utilities.Utilities.VerbouseOut("Converting code to object form"); for (int i = 0; i < code.Length; i++) { string opcode = code[i].code[0].ToLower(); string label = code[i].label; if (opcode == "add") { program.Add(new Add(code[i].code[1], code[i].code[2])); } else if (opcode == "in") { if (code[i].code.Length == 2) { program.Add(new In(code[i].code[1])); } else if (code[i].code.Length > 2) { program.Add(new In(code[i].code[1], code[i].code[2])); } } else if (opcode == "jmp") { program.Add(new Jmp(code[i].code[1])); } else if (opcode == "jnc") { program.Add(new Jnc(code[i].code[1])); } else if (opcode == "ld") { program.Add(new Ld(code[i].code[1])); } else if (opcode == "mov") { if (code[i].code.Length == 3) { program.Add(new Mov(code[i].code[1], code[i].code[2])); } else if (code[i].code.Length > 3) { program.Add(new Mov(code[i].code[1], code[i].code[2], code[i].code[3])); } } else if (opcode == "out") { if (code[i].code.Length == 2) { program.Add(new Out(code[i].code[1])); } else if (code[i].code.Length > 2) { program.Add(new Out(code[i].code[1], code[i].code[2])); } } else if (opcode == "st") { program.Add(new St(code[i].code[1])); } else if (opcode == "swi") { program.Add(new Swi(code[i].code[1])); } else if (opcode == "swm") { program.Add(new Swm(code[i].code[1])); } else { program.InsertSubTree(program.Count, importManager.LookUpPext(opcode, code[i].code)); } if (label != null) { program.AddLabel(label); } } Utilities.Utilities.VerbouseOut("Linking labels..."); for (int i = 0; i <= program.Count; i++) { if (program[i].opcode is Jmp || program[i].opcode is Jnc) { if (program[i].opcode.Arg1 == null) { ((PCChanger)program[i].opcode).Link = program[program[i].opcode.FastAdd.toInt() + 1]; Utilities.Utilities.VerbouseOut("LABEL_LINKER", "Linked: " + program[i].opcode.Name + " " + program[i].opcode.FastAdd.ToString() + " to " + ((PCChanger)program[i].opcode).Link.ToString()); } else { ((PCChanger)program[i].opcode).Link = program.GetLabel(program[i].opcode.Arg1); Utilities.Utilities.VerbouseOut("LABEL_LINKER", "Linked: " + program[i].opcode.Name + " " + program[i].opcode.Arg1.ToString() + " to " + ((PCChanger)program[i].opcode).Link.ToString()); } } } if (Program.verboseMode) { Console.WriteLine("---Final code---"); int length = program.Count; for (int i = 1; i <= length; i++) { Console.Write(i + ":\t"); IOpcode line = program.Get(i).opcode; Console.Write(line.Name + "\t"); if (line.Arg1 != null) { Console.Write(line.Arg1 + "\t"); } if (line is Mov) { if (line.Arg2 != null) { Console.Write(line.Arg2 + "\t"); } } if (line.FastAdd != null) { Console.Write(line.FastAdd.GetValue()); } Console.WriteLine(); } } }
public string[][] CatchDefines(string[][] text) { for (int i = 0; i < text.Length; i++) { if (text[i] != null) { if (text[i][0] == "#define") { AddDefinition(text[i][1], text[i][2]); Utilities.Utilities.VerbouseOut("\tDefined: " + text[i][1] + " = " + text[i][2], ConsoleColor.Green); } else if (text[i][0] == "#ifdef") { string testval = text[i][1]; int cacheIter = i; if (definitions.ContainsKey(testval)) { text[i] = null; i++; while (text[i][0] != "#endif" && text[i][0] != "#else") { i++; } if (text[i][0] == "#else") { text[i] = null; i++; while (text[i][0] != "#endif") { text[i] = null; i++; } } } else { text[i] = null; i++; while (text[i][0] != "#endif" && text[i][0] != "#else") { text[i] = null; i++; } if (text[i][0] == "#else") { text[i] = null; i++; while (text[i][0] != "#endif") { i++; } } } i = cacheIter; } else if (text[i][0] == "#ifndef") { string testval = text[i][1]; int cacheIter = i; if (!definitions.ContainsKey(testval)) { text[i] = null; i++; while (text[i][0] != "#endif" && text[i][0] != "#else") { i++; } if (text[i][0] == "#else") { text[i] = null; i++; while (text[i][0] != "#endif") { text[i] = null; i++; } } } else { text[i] = null; i++; while (text[i][0] != "#endif" && text[i][0] != "#else") { text[i] = null; i++; } if (text[i][0] == "#else") { text[i] = null; i++; while (text[i][0] != "#endif") { i++; } } } i = cacheIter; } else if (text[i][0] == "#line") { int stringNum = int.Parse(text[i][1]); string filename = text[i][2].Substring(1, text[i][2].Length - 2); text[i] = Assembly.SplitCode(CodeIO.LoadFile(filename))[stringNum]; } else if (text[i][0] == "#error") { Utilities.Utilities.Error("COMPILATION_WORKFLOW", text[i][1]); Environment.Exit(1); } else if (text[i][0] == "#message") { Utilities.Utilities.Message(text[i][1]); } else if (text[i][0] == "#pragma") { switch (text[i][1]) { case "8_BIT": AddDefinition(text[i][1], "TRUE"); Program.eightBit = true; break; case "NO_OPT": AddDefinition(text[i][1], "TRUE"); Program.optimize = false; break; case "4_BIT": AddDefinition(text[i][1], "TRUE"); Program.eightBit = false; break; case "USE_TRACE": AddDefinition(text[i][1], "TRUE"); Program.useTracer = true; break; case "NO_TRACE": AddDefinition(text[i][1], "TRUE"); Program.useTracer = false; break; case "CONFIG": if (!Program.configExists) { Utilities.Utilities.Error("PREPROCESSOR", "Configuration file was not specified."); } AddDefinition("HAS_CONFIG", "TRUE"); for (int j = 0; j < Program.config.Length; j++) { AddDefinition("config." + Program.config[j][0], Program.config[j][1]); } break; case "UNDEF_ALL": definitions.Clear(); break; case "DEF_SYS": if (Program.eightBit) { AddDefinition("8_BIT", "TRUE"); } else { AddDefinition("4_BIT", "TRUE"); } if (Program.makeBinary) { AddDefinition("BINARY", "TRUE"); } else { AddDefinition("TEXT", "TRUE"); } if (Program.optimize) { AddDefinition("OPTIMIZE", "TRUE"); } else { AddDefinition("NO_OPT", "TRUE"); } if (Program.useTracer) { AddDefinition("USE_TRACE", "TRUE"); } else { AddDefinition("NO_TRACE", "TRUE"); } break; } } else if (text[i][0] == "#sumdef") { string val = text[i][1]; string addval = text[i][2]; int oldVal = FastAdd.IsFastAdd(val) ? int.Parse(val) : new FastAdd(definitions[val]).toInt(); int toAdd = FastAdd.IsFastAdd(addval) ? int.Parse(addval) : new FastAdd(definitions[addval]).toInt(); definitions[val] = (oldVal + toAdd).ToString(); Utilities.Utilities.VerbouseOut("\tRedefined: " + text[i][1] + ": " + (oldVal + toAdd).ToString(), ConsoleColor.Yellow); } else if (text[i][0] == "#resdef") { string val = text[i][1]; string resval = text[i][2]; int oldVal = FastAdd.IsFastAdd(val) ? int.Parse(val) : new FastAdd(definitions[val]).toInt(); int toSub = FastAdd.IsFastAdd(resval) ? int.Parse(resval) : new FastAdd(definitions[resval]).toInt(); definitions[val] = (oldVal - toSub).ToString(); Utilities.Utilities.VerbouseOut("\tRedefined: " + text[i][1] + ": " + (oldVal - toSub).ToString(), ConsoleColor.Yellow); } else if (text[i][0] == "#undef") { RemoveDefinition(text[i][1]); Utilities.Utilities.VerbouseOut("\tUndefined: " + text[i][1], ConsoleColor.Red); } else if (text[i][0] == "#map") { if (text[i].Length > 3) { MapDefine(text[i][2], text[i][1], int.Parse(text[i][3])); } else { MapDefine(text[i][2], text[i][1], Program.eightBit ? 256 : 16); } } else if (text[i][0] == "#fordef") { List <string[]> dictLocal = new List <string[]>(); int j = i + 1; int pastePos = i; string iterator = text[i][1]; int initialValue = FastAdd.IsFastAdd(text[i][2]) ? int.Parse(text[i][2]) : new FastAdd(definitions[text[i][2]]).toInt(); int endingVale = FastAdd.IsFastAdd(text[i][3]) ? int.Parse(text[i][3]) : int.Parse(definitions[text[i][3]]); int step = int.Parse(text[i][4]); text[i] = null; while (text[j][0] != "#endfor") { dictLocal.Add(text[j]); text[j] = null; j++; } text[j] = null; for (int l = initialValue; l < endingVale; l += step) { for (int k = 0; k < dictLocal.Count; k++) { text = InsertCopySplitLine(text, dictLocal[k], pastePos, iterator, l.ToString()); Assembly.InsertSplitLine(dictLocal[k], pastePos, iterator, l.ToString()); pastePos++; } } i--; } else { for (int j = 0; j < text[i].Length; j++) { var toPaste = GetDefinition(text[i][j]); if (toPaste != null) { text[i][j] = toPaste; Assembly.ReplaceLexem(i, j, toPaste); } } } } } if (Program.verboseMode) { if (definitions.Keys.Count > 0) { Utilities.Utilities.Warning("PREPROCESSOR", "WARNING: NOT ALL DEFINITIONS WERE UNDEFINED"); foreach (string s in definitions.Keys) { Console.WriteLine("\t{0}\t:\t{1}", s, definitions[s]); } Utilities.Utilities.Warning("PREPROCESSOR", "Undefined variables may cause assembly errors"); } } return(text); }
static void Main(string[] args) { CommandLineApplication commandLine = new CommandLineApplication(throwOnUnexpectedArg: false) { Name = "TD4", Description = "(c) 2019 JL Computer Inc. TD4++ CPU Developer Kit.\nOptimizing assembler" }; string outputFile; string links; bool optimize; var argument = commandLine.Argument("filename", "Source .s file", false); CommandOption output = commandLine.Option("-o | --Output <output>", "Ouput file name", CommandOptionType.SingleValue); CommandOption target = commandLine.Option("-t | --Target <target>", "Output target. \n\t\t\'td4e\' produces binary output for TD4+ processor. Classic TD4 programs should be assembled using this option. TD4+ is set by default. \n\t\t\'td4e8\' produces code for TD4++ which have 8bit Im. \n\t\t\'asm\' produces assembler code. \n\t\t\'asm8\' produces 8bit assembler code", CommandOptionType.SingleValue); CommandOption libraries = commandLine.Option("-l | --Link <location>", "Libraries location (if not default)", CommandOptionType.SingleValue); CommandOption verbose = commandLine.Option("-v | --Verbose", "Verbose mode", CommandOptionType.NoValue); CommandOption useTracerKey = commandLine.Option("-T | --Tracer", "Use code tracer", CommandOptionType.NoValue); CommandOption optimization = commandLine.Option("-O | --Optimize", "Optimize assembly (experimental)", CommandOptionType.NoValue); CommandOption configFile = commandLine.Option("-c | --Configuration <file.conf>", "Machine configuration file", CommandOptionType.SingleValue); commandLine.HelpOption("-? | -h | --Help"); commandLine.OnExecute(() => { if (output.HasValue()) { outputFile = output.Value(); if (outputFile == null) { outputFile = "a.out"; } Program.outputFile = outputFile; verboseMode = verbose.HasValue(); useTracer = useTracerKey.HasValue(); if (target.HasValue()) { if (target.Value() == "td4e") { makeBinary = true; eightBit = false; } else if (target.Value() == "td4e8") { makeBinary = true; eightBit = true; } else if (target.Value() == "asm") { makeBinary = false; eightBit = false; } else if (target.Value() == "asm8") { makeBinary = false; eightBit = true; } else { Console.WriteLine("Unknown target: \"{0}\". Aborting.", target.Value()); Environment.Exit(1); } } if (configFile.HasValue()) { configExists = true; config = CodeIO.LoadConfig(configFile.Value()); } optimize = optimization.HasValue(); links = libraries.Value(); if (links == null) { links = Directory.GetCurrentDirectory(); } if (verboseMode) { Console.WriteLine("TD4++ Assembler v3.0"); Console.WriteLine("-=-=Session info=-=-"); Console.WriteLine("Source file: " + argument.Value); Console.WriteLine("Output file: " + outputFile); Console.WriteLine("Libraries location: " + links); Console.WriteLine("Use optimizer: " + optimize.ToString()); Console.WriteLine("Use tracer: " + useTracer.ToString()); Console.WriteLine("Target: {0}", target.Value()); Console.WriteLine("---Verbose mode---"); } Assembly assembly = new Assembly(argument.Value); Utilities.Utilities.VerbouseOut("Parsing finished"); if (optimize) { Optimizer.Optimizer opt = new Optimizer.Optimizer(assembly); Utilities.Utilities.VerbouseOut("Optimiztion finished"); } //Output Utilities.Utilities.VerbouseOut("-=-=Writing=-=-"); if (makeBinary) { CodeIO.WriteAssembly(assembly.Linker()); } else { CodeIO.WriteSource(assembly.Linker()); } Utilities.Utilities.VerbouseOut("DONE"); } else { commandLine.ShowHint(); } return(0); }); commandLine.Execute(args); }