public static InstructionSet Load(string definition) { string[] lines = definition.Replace("\r", "").Split('\n'); var table = new InstructionSet(); for (int i = 0; i < lines.Length; i++) { string line = lines[i].Trim(); if (line.StartsWith("#") || string.IsNullOrEmpty(line)) continue; line = line.RemoveExcessWhitespace(); if (line.StartsWith("OPERAND ")) { string[] parts = line.Split(' '); var operand = new Operand(parts[2], parts[3]); if (!table.OperandGroups.ContainsKey(parts[1])) table.OperandGroups.Add(parts[1], new OperandGroup(parts[1])); table.OperandGroups[parts[1]].Operands.Add(operand); } else if (line.StartsWith("INS ")) { string[] parts = line.Split(' '); string match = parts[1]; string value = line.Substring(line.IndexOf(' ') + 1); value = value.Substring(value.IndexOf(' ') + 1); table.Instructions.Add(new Instruction(match.ToLower(), value.Replace(" ", ""))); } else if (line.StartsWith("WORDSIZE ")) table.WordSize = int.Parse(line.Substring(9)); else { throw new FormatException("In the instruction set, \"" + line + "\" is not valid."); } } return table; }
public Assembler(InstructionSet instructionSet) { InstructionSet = instructionSet; ExpressionEngine = new ExpressionEngine(); SuspendedLines = 0; LineNumbers = new Stack<int>(); FileNames = new Stack<string>(); IncludePaths = new List<string>(); Macros = new List<Macro>(); }
public Assembler(InstructionSet instructionSet, AssemblySettings settings) { InstructionSet = instructionSet; Settings = settings; ExpressionEngine = new ExpressionEngine(settings); SuspendedLines = 0; LineNumbers = new Stack<int>(); FileNames = new Stack<string>(); IncludePaths = new List<string>(); Macros = new List<Macro>(); IfStack = new Stack<bool>(); WorkingIfStack = new Stack<bool>(); Listing = true; }
public static InstructionSet Load(string definition) { string[] lines = definition.Replace("\r", "").Split('\n'); var table = new InstructionSet(); for (int i = 0; i < lines.Length; i++) { string line = lines[i].Trim(); if (line.StartsWith("#") || string.IsNullOrEmpty(line)) { continue; } line = line.RemoveExcessWhitespace(); if (line.StartsWith("OPERAND ")) { string[] parts = line.Split(' '); var operand = new Operand(parts[2], parts[3]); if (!table.OperandGroups.ContainsKey(parts[1])) { table.OperandGroups.Add(parts[1], new OperandGroup(parts[1])); } table.OperandGroups[parts[1]].Operands.Add(operand); } else if (line.StartsWith("INS ")) { string[] parts = line.Split(' '); string match = parts[1]; string value = line.Substring(line.IndexOf(' ') + 1); value = value.Substring(value.IndexOf(' ') + 1); table.Instructions.Add(new Instruction(match.ToLower(), value.Replace(" ", ""))); } else if (line.StartsWith("WORDSIZE ")) { table.WordSize = int.Parse(line.Substring(9)); } else { throw new FormatException("In the instruction set, \"" + line + "\" is not valid."); } } return(table); }
public static int Main(string[] args) { InstructionSets = new Dictionary <string, InstructionSet>(); InstructionSets.Add("z80", LoadInternalSet("sass.Tables.z80.table")); string instructionSet = "z80"; // Default string inputFile = null, outputFile = null; var settings = new AssemblySettings(); List <string> defines = new List <string>(); for (int i = 0; i < args.Length; i++) { string arg = args[i]; if (arg.StartsWith("-") && arg != "-") { try { switch (arg) { case "-d": case "--define": defines.AddRange(args[++i].Split(',')); break; case "--debug-mode": Thread.Sleep(10000); break; case "--encoding": try { settings.Encoding = Encoding.GetEncoding(args[++i]); } catch { Console.Error.WriteLine("The specified encoding was not recognized. Use sass --list-encodings to see available encodings."); return(1); } break; case "-h": case "-?": case "/?": case "/help": case "-help": case "--help": DisplayHelp(); return(0); case "--inc": case "--include": settings.IncludePath = args[++i].Split(';'); break; case "--input": case "--input-file": inputFile = args[++i]; break; case "--instr": case "--instruction-set": instructionSet = args[++i]; break; case "-l": case "--listing": settings.ListingOutput = args[++i]; break; case "--list-encodings": Console.WriteLine("The default encoding is UTF-8. The following are available: "); foreach (var encoding in Encoding.GetEncodings()) { Console.WriteLine("{0} [{1}]", encoding.DisplayName, encoding.Name); } Console.WriteLine("Use the identifier (in [brackets]) with --encoding)."); return(0); case "--nest-macros": settings.AllowNestedMacros = true; break; case "--output": case "--output-file": outputFile = args[++i]; break; case "-s": case "--symbols": settings.SymbolOutput = args[++i]; break; case "-v": case "--verbose": settings.Verbose = true; break; } } catch (ArgumentOutOfRangeException) { Console.Error.WriteLine("Error: Invalid usage. Use sass.exe --help for usage information."); return(1); } } else { if (inputFile == null) { inputFile = args[i]; } else if (outputFile == null) { outputFile = args[i]; } else { Console.Error.WriteLine("Error: Invalid usage. Use sass.exe --help for usage information."); return(1); } } } if (inputFile == null) { Console.Error.WriteLine("No input file specified. Use sass.exe --help for usage information."); return(1); } if (outputFile == null) { outputFile = Path.GetFileNameWithoutExtension(inputFile) + ".bin"; } InstructionSet selectedInstructionSet; if (!InstructionSets.ContainsKey(instructionSet)) { if (File.Exists(instructionSet)) { selectedInstructionSet = InstructionSet.Load(File.ReadAllText(instructionSet)); } else { Console.Error.WriteLine("Specified instruction set was not found."); return(1); } } else { selectedInstructionSet = InstructionSets[instructionSet]; } var assembler = new Assembler(selectedInstructionSet, settings); foreach (var define in defines) { assembler.ExpressionEngine.Symbols.Add(define.ToLower(), new Symbol(1)); } string file; if (inputFile == "-") { file = Console.In.ReadToEnd(); } else { file = File.ReadAllText(inputFile); } var watch = new Stopwatch(); watch.Start(); var output = assembler.Assemble(file, inputFile); watch.Stop(); if (outputFile == "-") { Console.OpenStandardOutput().Write(output.Data, 0, output.Data.Length); } else { File.WriteAllBytes(outputFile, output.Data); } var errors = from l in output.Listing where l.Warning != AssemblyWarning.None || l.Error != AssemblyError.None orderby l.RootLineNumber select l; if (!settings.Verbose) { foreach (var listing in errors) { if (listing.Error != AssemblyError.None) { Console.Error.WriteLine(listing.FileName + ":" + listing.LineNumber + " Error: " + listing.Error); } if (listing.Warning != AssemblyWarning.None) { Console.Error.WriteLine(listing.FileName + ":" + listing.LineNumber + " Warning: " + listing.Warning); } } } if (settings.Verbose || settings.ListingOutput != null) { var listing = GenerateListing(output); if (settings.Verbose) { Console.Write(listing); } if (settings.ListingOutput != null) { File.WriteAllText(settings.ListingOutput, listing); } } if (settings.SymbolOutput != null) { WriteSymbols(settings.SymbolOutput, assembler); } Console.Error.WriteLine("Assembly done: {0} ms", watch.ElapsedMilliseconds); if (Debugger.IsAttached) { Console.Error.WriteLine("Press any key to continue..."); Console.ReadKey(true); } return(errors.Count(e => e.Error != AssemblyError.None)); }