public void WordWrap(string outputAinFilename) { var options = new CodeDisplayOptions(); var projectWriter = new AssemblerProjectWriter(ainFile, options); projectWriter.BeforeWritingInstruction += new EventHandler <InstructionInfoEventArgs>(projectWriter_BeforeWritingInstruction); string tempFile = Path.GetTempFileName(); try { var saveProjectInBackground = new ExplorerForm.SaveProjectInBackground(); saveProjectInBackground.SaveAsProject(projectWriter, tempFile, true); var buildProjectInBackground = new ExplorerForm.BuildProjectInBackground(); buildProjectInBackground.Run(tempFile, outputAinFilename, true); //projectWriter.SaveAsProject(tempFile, true); //var projectReader = new AssemblerProjectReader(); //projectReader.LoadProject(tempFile); //var outputAinFile = projectReader.MakeAinFile(); //outputAinFile.WriteAndEncryptAinFile(outputAinFilename); } finally { File.Delete(tempFile); } }
//private List<object> GetFunctionsToOutput(List<TokenExpression> tokens) //{ // List<object> FunctionsToOutput = new List<object>(); // bool hasOutputZero = false; // foreach (var function in ainFile.Functions) // { // if (function.Name == "NULL") // { // } // else if (function.Name.EndsWith("@2")) // { // if (!hasOutputZero) // { // FunctionsToOutput.Add(ainFile.GetFunction("0")); // hasOutputZero = true; // } // FunctionsToOutput.Add(function); // } // else if (function.Name == "0") // { // } // else // { // FunctionsToOutput.Add(function); // } // } // FunctionsToOutput.Add(ainFile.GetFunction("NULL")); // return FunctionsToOutput; //} public void Test() { //List<TokenExpression> tokens = new List<TokenExpression>(); ////string expression = "a - -obj.method()()[4] - -3;"; ////string expression = "- -a - -obj.method()()[4] - -3;"; ////string expression = "- -a - -obj.method()(-9*-8 + 5)[4 == 4 + 5 == 4] - -3;"; ////string expression = "- -a - -obj.method()(-9*-8 + 5)[4 == 4 + 5 == 4] - -3;"; //IncludeString(expression, tokens); //this.reader = new TokenReader(tokens); //var exp = ReadExpression(); string projectFilename = @"<insert filename here>"; Compile(projectFilename); string outputJamFileName = Path.Combine(Path.GetDirectoryName(projectFilename), "output\\main.jam"); //string outputJamFileName = Path.Combine(Path.GetDirectoryName(projectFilename), "..\\DISASSEMBLED2\\main.jam"); //string filename = @"<insert filename here>"; //List<TokenExpression> tokens = new List<TokenExpression>(); //IncludeFile(filename, tokens); //string libraryPath = @"<insert filename here>"; //LoadHllFiles(libraryPath); ainFile.LoadAlternativeNames(); ainFile.LoadMetadata(); AssemblerProjectWriter writer = new AssemblerProjectWriter(ainFile); writer.Options.ShowGlobalPrefix = false; writer.SaveAsProject(outputJamFileName, false); //todo: fix _date_ macro, needs spaces instead of leading zeroes }
public override string ToString() { if (QuoteCharacter != 0) { return(AssemblerProjectWriter.EscapeString(Value, QuoteCharacter, true)); } return(Value); }
public void CompileCodeInPlace(string[] fileNames) { StringBuilder sb = new StringBuilder(); foreach (var fileName in fileNames) { sb.AppendLine("#include " + AssemblerProjectWriter.EscapeAndQuoteString(Path.GetFullPath(fileName))); } CompileCodeInPlace(sb.ToString()); }
private static void CreateProject(string inputAinFilename, string outputProjectFilename) { var ainFile = new AinFile(inputAinFilename); ainFile.LoadAlternativeNames(); //var alternativeNames = new AlternativeNames(inputAinFilename); var writer = new AssemblerProjectWriter(ainFile); //writer.AlternativeNames = alternativeNames; writer.SaveAsProject(outputProjectFilename, false); }
public void SaveTextToMultipleFiles(string outputFileName, Encoding encoding) { this.IncludeMessages = true; this.IncludeStrings = false; string baseDirectoryName = Path.GetDirectoryName(outputFileName); string textDirectory = Path.Combine(baseDirectoryName, "text"); string rootFileName = Path.Combine(textDirectory, "root.txt"); Directory.CreateDirectory(textDirectory); using (var rootFileStream = new FileStream(rootFileName, FileMode.Create, FileAccess.Write)) { var rootTextWriter = new StreamWriter(rootFileStream, encoding); var enumerator = new FunctionEnumerator(ainFile); var results = enumerator.GetFilesAndFunctions(); foreach (var result1 in results) { string jafFileName = result1.name; foreach (var functionNode in result1.children) { var function = ainFile.GetFunction(functionNode.name); var text = GetTextFromFunction(function); if (text.Count > 2) { string functionName = AssemblerProjectWriter.SanitizeVariableName(function.Name); if (functionName.StartsWith("\"")) { } else { string includeFileName = Path.Combine(jafFileName, functionName + ".txt"); string fileName = Path.Combine(textDirectory, includeFileName); string outputDirectory = Path.GetDirectoryName(fileName); Directory.CreateDirectory(outputDirectory); File.WriteAllLines(fileName, text.ToArray(), encoding); rootTextWriter.WriteLine("#include \"" + includeFileName + "\""); } } } } rootTextWriter.Flush(); rootFileStream.Flush(); rootTextWriter.Close(); rootFileStream.Close(); } using (var textWriter2 = new StreamWriter(outputFileName, false, encoding)) { textWriter2.WriteLine("#include \"text/root.txt\""); textWriter2.Flush(); textWriter2.Close(); } }
public void CompileCode(string codeText, out byte[] codeBytes, out string disassembledCode, bool topLevel, Dictionary <string, string> codePatches) { int oldStructCount = ainFile.Structs.Count; int oldFunctionCount = ainFile.Functions.Count; int oldSwitchCount = ainFile.Switches.Count; int oldFunctypeCount = ainFile.FunctionTypes.Count; int oldDelegateCount = ainFile.Delegates.Count; int oldGlobalCount = ainFile.Globals.Count; int oldLibraryCount = ainFile.Libraries.Count; codeBytes = null; disassembledCode = null; var lastDefaultAinFile = Expression.defaultAinFile; try { if (!topLevel) { string dummyFunctionName = "DUMMY" + dummyFunctionNumber.ToString("0000"); codeText = "void " + dummyFunctionName + "()" + Environment.NewLine + "{" + Environment.NewLine + codeText + Environment.NewLine + "}" + Environment.NewLine; dummyFunctionNumber++; } List <TokenExpression> tokens = new List <TokenExpression>(); IncludeString(codeText, tokens); ainFile.Version = this.AinVersion; ainFile.TargetVMVersion = this.TargetVMVersion; ainFile.IsAi2File = this.IsAi2File; ainFile.UsesMsg1 = this.UsesMsg1; ainFile.KeyCode = this.KeyCode; ainFile.GameVersion = this.gameVersion; ainFile.UseSimplifiedCode = this.UseSimplifiedCode; if (ainFile.Version >= 6) { this.Messages.DoNotCombine = true; } var firstPass = new FirstPass(); if (this.Error != null) { firstPass.Error += this.Error; } var result = firstPass.CompileFirstPass(tokens); if (firstPass.Errors.Count > 0) { this.Errors.AddRange(firstPass.Errors); return; } bool createAdditionalFunctions = topLevel; var symbolsCreated = CreateSymbols(result, createAdditionalFunctions); var functionsToOutput = symbolsCreated.OfType <Function>().ToArray(); var structsCreated = symbolsCreated.OfType <Struct>().ToArray(); var librariesToOutput = symbolsCreated.OfType <HllLibrary>().ToArray(); if (ainFile.Libraries.Count > oldLibraryCount + librariesToOutput.Length) { //fix missing libraries librariesToOutput = librariesToOutput.Concat(ainFile.Libraries.Skip(oldLibraryCount)).ToArray(); } GetInitialValues(result); if (!CompileSecondPass()) { return; } GenerateExpressions(); var codeGenerator = new CodeGenerator(ainFile); foreach (var function in functionsToOutput) { var expression = this.FunctionDefinitions.GetOrNull(function); function.Crc = 0; function.Address = codeGenerator.Address + 6; codeGenerator.GenerateCodeForFunction(expression); } var writer = new AssemblerProjectWriter(ainFile); codeBytes = codeGenerator.Code.ToArray(); StringWriter sw = new StringWriter(); List <Function> functionsToOutput2 = new List <Function>(); foreach (var function in functionsToOutput) { bool handled = false; if (codePatches != null) { if (function.Index < oldFunctionCount) { disassembledCode = writer.GetDisassembledCode(function, codeBytes); codePatches[function.Name] = disassembledCode; //writer.GetDisassembledCode(codeBytes, new Function[] { function }, ainFile.Structs.Count, ainFile.Delegates.Count, ainFile.FunctionTypes.Count, ainFile.Globals.Count); handled = true; } } if (!handled) { functionsToOutput2.Add(function); } } writer.GetDisassembledCode(sw, codeBytes, functionsToOutput, functionsToOutput2.ToArray(), structsCreated, librariesToOutput, oldDelegateCount, oldFunctypeCount, oldGlobalCount); disassembledCode = sw.ToString(); ainFile.MAIN = Functions.Contains("main") ? (Functions.Get("main").Index) : -1; ainFile.MSGF = Functions.Contains("message") ? (Functions.Get("message").Index) : -1; ainFile.OJMP = Functions.Contains("onjump") ? (Functions.Get("onjump").Index) : -1; RemoveFunctypes(ainFile); FixStructs(ainFile); ainFile.ComputeFunctionHashes(); SortGlobalInitialValues(ainFile); SortSwitchCases(ainFile); if (!topLevel && Errors.Count > 0) { disassembledCode = null; codeBytes = null; } } finally { Expression.defaultAinFile = lastDefaultAinFile; if (!topLevel) { this.FunctionDeclarationTokens.Clear(); this.FunctionDefinitionTokens.Clear(); this.FunctionDefinitions.Clear(); } } }
static void ToStringReal(TokenExpression ex, MyIndentedTextWriter tw) { if (ex == null) { return; } switch (ex.TokenType) { default: if (!String.IsNullOrEmpty(ex.Token.Value) && ex.Token.Value != "...") { tw.Write(ex.Token.Value); } if (ex.Subexpressions.Count > 0) { tw.Write(" "); ToStringReal(ex.Subexpressions, tw); } break; case TokenType.Array: case TokenType.AddressOf: case TokenType.At: case TokenType.Complement: case TokenType.Increment: case TokenType.Decrement: if (!String.IsNullOrEmpty(ex.Token.Value) && ex.Token.Value != "...") { tw.Write(ex.Token.Value); } if (ex.Subexpressions.Count > 0) { ToStringReal(ex.Subexpressions, tw); } break; case TokenType.Block: if (!tw.TabsPending) { tw.WriteLine(); } tw.WriteLine("{"); tw.Indent++; ToStringReal(ex.Subexpressions, tw); tw.Indent--; if (!tw.TabsPending) { tw.WriteLine(); } tw.WriteLine("}"); break; case TokenType.Statement: ToStringReal(ex.Subexpressions, tw); tw.WriteLine(";"); break; case TokenType.StringLiteral: tw.Write(AssemblerProjectWriter.EscapeAndQuoteString(ex.Token.Value)); break; case TokenType.CharLiteral: case TokenType.Message: tw.Write(AssemblerProjectWriter.EscapeAndQuoteMessage(ex.Token.Value)); break; case TokenType.ArrayIndex: tw.Write("["); ToStringReal(ex.Subexpressions, tw); tw.Write("]"); break; case TokenType.Assert: tw.Write("assert ("); for (int i = 0; i < ex.Subexpressions.Count; i++) { if (i != 0) { tw.Write(", "); } ToStringReal(ex.Subexpressions[i], tw); } tw.Write(")"); break; case TokenType.For: tw.Write("for ("); for (int i = 0; i < 3; i++) { if (i != 0) { tw.Write("; "); } var subex = ex.Subexpressions.GetOrNull(i); ToStringReal(subex, tw); } tw.WriteLine(")"); ToStringReal(ex.Subexpressions.GetOrNull(3), tw); break; case TokenType.While: tw.Write("while ("); ToStringReal(ex.Subexpressions.GetOrNull(0), tw); tw.WriteLine(")"); ToStringReal(ex.Subexpressions.GetOrNull(1), tw); break; case TokenType.If: tw.Write("if ("); ToStringReal(ex.Subexpressions.GetOrNull(0), tw); tw.WriteLine(")"); ToStringReal(ex.Subexpressions.GetOrNull(1), tw); { var subex = ex.Subexpressions.GetOrNull(2); if (subex != null) { ToStringReal(subex, tw); } } break; case TokenType.Switch: tw.Write("switch ("); ToStringReal(ex.Subexpressions.GetOrNull(0), tw); tw.WriteLine(")"); ToStringReal(ex.Subexpressions.Skip(1), tw); break; case TokenType.FunctionCall: ToStringReal(ex.Subexpressions.GetOrNull(0), tw); tw.Write("("); ToStringReal(ex.Subexpressions.Skip(1), tw); tw.Write(")"); break; case TokenType.PostDecrement: case TokenType.PostIncrement: ToStringReal(ex.Subexpressions, tw); tw.Write(ex.Token.Value); break; //infix binary operators case TokenType.And: case TokenType.AndAssign: case TokenType.Assign: case TokenType.Colon: case TokenType.Comma: case TokenType.Divide: case TokenType.DivideAssign: case TokenType.Dot: case TokenType.EqualTo: case TokenType.LeftShift: case TokenType.LeftShiftAssign: case TokenType.LessThan: case TokenType.LessThanOrEqualTo: case TokenType.LogicalAnd: case TokenType.LogicalOr: case TokenType.Minus: case TokenType.MinusAssign: case TokenType.Modulo: case TokenType.ModuloAssign: case TokenType.Multiply: case TokenType.MultiplyAssign: case TokenType.NotEqualTo: case TokenType.Or: case TokenType.OrAssign: case TokenType.Plus: case TokenType.PlusAssign: case TokenType.QuestionMark: case TokenType.ReferenceAssign: case TokenType.ReferenceEqualTo: case TokenType.ReferenceNotEqualTo: case TokenType.ReferenceSwap: case TokenType.RightShift: case TokenType.RightShiftAssign: case TokenType.Xor: case TokenType.XorAssign: //output left side ToStringReal(ex.Subexpressions.GetOrNull(0), tw); if (ex.TokenType != TokenType.Comma && ex.TokenType != TokenType.Dot) { tw.Write(" "); } if (String.IsNullOrEmpty(ex.Token.Value) || ex.Token.Value == "...") { if (keywordTableInverse.ContainsKey(ex.TokenType)) { tw.Write(keywordTableInverse[ex.TokenType]); } } else { tw.Write(ex.Token.Value); } if (ex.TokenType != TokenType.Dot) { tw.Write(" "); } ToStringReal(ex.Subexpressions.Skip(1), tw); break; } //foreach (var ex in exBase.GetAllSubexpressionsRecursive()) //{ // switch (ex.TokenType) // { // case TokenType.And: // case TokenType. // default: // sb.Append(ex.Token.Value); // break; // } //} //return sb.ToString(); }
private void HandleMessage(InstructionInfoEventArgs e, string messageText) { int indentSize = GetIndentSize(messageText); int realSplitPosition = FindCharacterIndexOfRightMargin(messageText, maxCharactersPerLine); if (realSplitPosition < messageText.Length || e.Handled == true) { e.Handled = true; while (realSplitPosition < messageText.Length) { int position = FindSplitPoint(messageText, realSplitPosition); if (position <= indentSize) { //for really long lines - split them at the wrap position instead of an infinite loop position = realSplitPosition; } string line = messageText.Substring(0, position); e.WriteLine(" " + AssemblerProjectWriter.EscapeAndQuoteMessage(line) + " "); GenerateNextLine(e); e.WriteLine(""); messageText = messageText.Substring(position); //eat spaces position = 0; while (position < messageText.Length && messageText[position] == ' ') { position++; } if (position > 0) { messageText = messageText.Substring(position); } //add indent if enabled if (MaintainIndentation) { if (indentSize > 0) { messageText = "".PadLeft(indentSize, ' ') + messageText; } } //find next split realSplitPosition = FindCharacterIndexOfRightMargin(messageText, maxCharactersPerLine); } //remaining text is set to something if this is a "next message" call, so output any leftover text at that time. //Otherwise, if we have the leftover text feature disabled, output it now. if (!this.RemoveLineBreaksIfWordWrapping || this.remainingText != "") { e.WriteText(" " + AssemblerProjectWriter.EscapeAndQuoteMessage(messageText) + " "); this.remainingText = ""; } else { this.remainingText = messageText; } } }
void writer_BeforeWritingInstruction(object sender, InstructionInfoEventArgs e) { var instructionInfo = e.InstructionInfo; var instruction = instructionInfo.instruction; int word1 = instructionInfo.word1; if (InsideFunction) { if (!hasOutputFunction) { if (this.CodePatches.ContainsKey(currentFunctionName)) { var codePatch = this.CodePatches[currentFunctionName]; e.WriteLine(codePatch); } hasOutputFunction = true; } if (instruction == Instruction.FUNC || instruction == Instruction.ENDFUNC || instruction == Instruction.EOF) { //will emit the ENDFUNC or next FUNC instruction InsideFunction = false; e.StopEmittingCode = false; } else { e.Handled = true; e.StopEmittingCode = true; return; } } if (instruction == Instruction.FUNC) { int functionNumber = instructionInfo.word1; var function = ainFile.GetFunction(functionNumber); if (function != null) { stringNumber = 0; messageNumber = 0; currentFunctionName = function.Name; stringDictionary = stringEntries.GetOrNull(currentFunctionName); messageDictionary = messageEntries.GetOrNull(currentFunctionName); if (this.CodePatches.ContainsKey(currentFunctionName)) { //var codePatch = this.CodePatches[currentFunctionName]; //e.WriteLine(codePatch); e.Handled = false; e.StopEmittingCode = false; //will emit the FUNC instruction, but then not the rest this.InsideFunction = true; this.hasOutputFunction = false; } } } else /*if (stringDictionary != null || messageDictionary != null)*/ { if (instruction == Instruction.MSG) { string originalMessage = originalAinFile.GetMessage(word1); string newMessage = null; if (messageDictionary != null) { newMessage = messageDictionary.GetOrNull(messageNumber); } if (newMessage != null && newMessage != originalMessage) { e.Text = newMessage; } if (this.WordWrap) { if (this.wordWrapper.HasRemainingText == false && e.Text == originalMessage) { //don't wrap text because we match the original and don't have remaining text } else { wordWrapper.projectWriter_BeforeWritingInstruction(sender, e); } } if (e.Dirty && !e.Handled) { //recheck this! newMessage = e.Text; e.WriteLine("\tMSG " + AssemblerProjectWriter.EscapeAndQuoteMessage(newMessage)); e.Handled = true; } messageNumber++; } //string instructions are handled by writer_BeforeWritingString else if (instruction == Instruction.CALLFUNC) { //for text wrapping (to do later) if (this.WordWrap) { wordWrapper.projectWriter_BeforeWritingInstruction(sender, e); } } } }
private void ExportAndMerge() { string newDisassembledCode = null; if ((this.CodePatches2 != null && this.CodePatches2.Length > 0) || numberedStrings.Count > 0) { this.ainFile = ainFile.Clone(); } if (this.CodePatches2 != null && this.CodePatches2.Length > 0) { //this.ainFile = ainFile.Clone(); var compiler = new Compiler.Compiler(ainFile); byte[] codeBytes; compiler.CompileCode(this.CodePatches2.ToString(), out codeBytes, out newDisassembledCode, true, this.CodePatches); if (newDisassembledCode == null || compiler.Errors.Count > 0) { var errorsListForm = new ErrorsListForm(); errorsListForm.SetErrorList(compiler.Errors); errorsListForm.Show(); return; } //foreach (var func in functionsToOutput) //{ // this.CodePatches[func.Name] = ""; //} } currentFunctionName = ""; stringDictionary = null; messageDictionary = null; stringNumber = 0; messageNumber = 0; //var ainFile = this.ainFile; if (numberedStrings.Count > 0) { //this.ainFile = ainFile.Clone(); var stringExportImport = new StringExportImport(ainFile); int firstMessage = stringExportImport.GetFirstMessageIdNumber(); int lastMessage = firstMessage + ainFile.Messages.Count; int firstString = stringExportImport.GetFirstStringIdNumber(); int lastString = firstString + ainFile.Strings.Count; foreach (var pair in numberedStrings) { int number = pair.Key; string message = pair.Value; if (number >= firstMessage && number < lastMessage) { ainFile.Messages[number - firstMessage] = message; } else if (number >= firstString && number < lastString) { ainFile.Strings[number - firstString] = message; } } } using (TemporaryFile tempFile = new TemporaryFile("jam", true)) { var saver = new ExplorerForm.SaveProjectInBackground(); var options = new CodeDisplayOptions(); options.AnnotateWithDecompiledCode = false; options.MergeDuplicateStrings = true; options.MergeDuplicateMessages = true; var writer = new AssemblerProjectWriter(ainFile, options); writer.BeforeWritingInstruction += new EventHandler <InstructionInfoEventArgs>(writer_BeforeWritingInstruction); writer.BeforeWritingString += new EventHandler <InstructionInfoEventArgs>(writer_BeforeWritingString); saver.SaveAsProject(writer, tempFile.FileName, true); if (newDisassembledCode != null) { using (var fs = new FileStream(tempFile.FileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) { using (var sw = new StreamWriter(fs, Extensions.TextEncoding)) { sw.WriteLine(); sw.WriteLine(newDisassembledCode); sw.Flush(); fs.Flush(); sw.Close(); fs.Close(); } } } //WaitForFileLock(tempFile.FileName, 2000); //tempFile.FileName var builder = new ExplorerForm.BuildProjectInBackground(); builder.ForceUniqueMessages = true; builder.Run(tempFile.FileName, this.outputFileName, true); } }
private void ReadReplacementFile(TextReaderWrapper tr, string textFileName) { textFileName = Path.GetFullPath(textFileName); if (IncludedFiles.Contains(textFileName.ToUpperInvariant())) { return; } IncludedFiles.Set(textFileName.ToUpperInvariant()); string line; while (true) { line = tr.ReadLine(); if (line == null) { break; } //remove initial whitespace line = line.TrimStart(); //check for "#include" if (line.StartsWith("#include ")) { string filenameToInclude = line.Substring("#include ".Length); //check for quotes? if (filenameToInclude.StartsWith("\"") && filenameToInclude.EndsWith("\"")) { filenameToInclude = filenameToInclude.Substring(1, filenameToInclude.Length - 2); } string basePath = tr.DirectoryName; filenameToInclude = Path.Combine(basePath, filenameToInclude); if (!File.Exists(filenameToInclude)) { throw new FileNotFoundException("Cannot find file: " + filenameToInclude, filenameToInclude); } if (File.Exists(filenameToInclude) && !IncludedFiles.Contains(filenameToInclude.ToUpperInvariant())) { IncludedFiles.Add(filenameToInclude.ToUpperInvariant()); var encoding = EncodingDetector.DetectEncoding(filenameToInclude); tr.IncludeTextReader(new StreamReader(filenameToInclude, encoding)); } continue; } //remove commented text int indexOfComment = line.IndexOf('#'); if (indexOfComment >= 0) { line = line.Substring(0, indexOfComment); } //reading one of these lines: //CODE //function x functionName (or func, f) //string x text (or str, s) //message x text (or msg, m) //id x text (or i) //x text (same as id x text) string lineTrim = line.Trim(); if (lineTrim.Equals("CODE", StringComparison.OrdinalIgnoreCase) || lineTrim.Equals("CODE2", StringComparison.OrdinalIgnoreCase)) { bool isCode2 = lineTrim.Equals("CODE2", StringComparison.OrdinalIgnoreCase); StringBuilder codeText = new StringBuilder(); while (true) { line = tr.ReadLine(); lineTrim = line.Trim(); if (lineTrim.StartsWith("#include")) { string filenameToInclude = lineTrim.Substring("#include ".Length); //check for quotes? if (filenameToInclude.StartsWith("\"") && filenameToInclude.EndsWith("\"")) { filenameToInclude = filenameToInclude.Substring(1, filenameToInclude.Length - 2); } string basePath = tr.DirectoryName; if (!Path.IsPathRooted(filenameToInclude)) { filenameToInclude = Path.Combine(basePath, filenameToInclude); } filenameToInclude = Path.GetFullPath(filenameToInclude); if (!File.Exists(filenameToInclude)) { throw new FileNotFoundException("Cannot find file: " + filenameToInclude, filenameToInclude); } if (File.Exists(filenameToInclude) && !IncludedFiles.Contains(filenameToInclude.ToUpperInvariant())) { IncludedFiles.Add(filenameToInclude.ToUpperInvariant()); if (isCode2) { //replace with #include <fullpath>, let the compiler handle the actual include codeText.AppendLine("#include " + AssemblerProjectWriter.EscapeAndQuoteString(filenameToInclude)); } else { var encoding = EncodingDetector.DetectEncoding(filenameToInclude); tr.IncludeTextReader(new StreamReader(filenameToInclude, encoding)); } } continue; } if (lineTrim.ToUpperInvariant() == "ENDCODE") { if (isCode2) { CodePatches2.AppendLine(codeText.ToString()); } else { CodePatches.Set(currentFunctionName, codeText.ToString()); } break; } else { codeText.AppendLine(line); } } continue; } //find first space int spaceIndex = line.IndexOf(' '); if (spaceIndex == -1) { continue; } string tagName = line.Substring(0, spaceIndex); line = line.Substring(spaceIndex + 1); int number; //if it starts with a number, it's a legacy text replacement if (IntUtil.TryParse(tagName, out number) == true) { tagName = "id"; } else { bool isFunction = false; string tagNameLower = tagName.ToLowerInvariant(); if (tagNameLower == "f" || tagNameLower == "func" || tagNameLower == "function") { isFunction = true; } line = line.TrimStart(); spaceIndex = line.IndexOf(' '); if (spaceIndex == -1) { if (isFunction) { number = -1; } else { continue; } } else { string numberString = line.Substring(0, spaceIndex); line = line.Substring(spaceIndex + 1); if (IntUtil.TryParse(numberString, out number) == false) { if (isFunction) { line = numberString + " " + line; number = -1; } else { continue; } } } } line = StringExportImport.UnescapeText(line); switch (tagName.ToLowerInvariant()) { case "f": case "func": case "function": string nextFunctionName = line.Trim(); var function = ainFile.GetFunction(number); if (function == null) { function = ainFile.GetFunction(nextFunctionName); if (function == null) { continue; } } currentFunctionName = function.Name; stringDictionary = stringEntries.GetOrAddNew(currentFunctionName); messageDictionary = messageEntries.GetOrAddNew(currentFunctionName); break; case "string": case "str": case "s": stringDictionary.Set(number, line); break; case "msg": case "message": case "m": messageDictionary.Set(number, line); break; case "i": case "id": numberedStrings.Set(number, line); break; } } }
private List <string> GetTextFromFunction(Function function) { int numberOfNonCommentedLines = 0; int numberOfStrings = 0; int numberOfMessages = 0; //Expression expression = null; //int expressionLastAddress = function.Address; useStringsToMatch = StringsToMatch != null && StringsToMatch.Count > 0; //List<string> strings = new List<string>(); //List<string> messages = new List<string>(); List <string> functionLines = new List <string>(); string functionLineString = "FUNCTION " + /*function.Index.ToString() + " " + */ AssemblerProjectWriter.SanitizeVariableName(function.Name); functionLines.Add(functionLineString); functionLines.Add("#x strings, x messages"); //this line gets changed later (it's index 1) int address = function.Address; string lastName = null; while (address < ainFile.Code.Length) { var instructionInfo = ainFile.Peek(address); if (instructionInfo.instruction == Instruction.ENDFUNC || instructionInfo.instruction == Instruction.FUNC) { break; } if (this.AnnotateEnumerationType != null && instructionInfo.instruction == Instruction.CALLFUNC) { var func = ainFile.GetFunction(instructionInfo.word1); if (VariablesUsingEnumerationType.Contains(func)) { var parameters = GetParametersThatUsesEnumerationType(func); if (parameters.FirstOrDefault() != null) { foreach (var parameter in parameters) { int i = parameter.Index; int addr = instructionInfo.CurrentAddress - (func.ParameterCount) * 6 + i * 6; var ins2 = ainFile.Peek(addr); if (ins2.instruction == Instruction.PUSH) { string enumerationValue = this.AnnotateEnumerationType.GetOrDefault(ins2.word1, ""); if (!String.IsNullOrEmpty(enumerationValue)) { functionLines.Add(""); functionLines.Add("#" + enumerationValue); } } else if (ins2.instruction == Instruction.S_PUSH) { string str = ainFile.GetString(ins2.word1); if (!String.IsNullOrEmpty(str)) { if (this.replacementStringsForAnnotations != null && this.replacementStringsForAnnotations.ContainsKey(str)) { string nextStr = this.replacementStringsForAnnotations[str]; if (!nextStr.StartsWith("*")) { str = nextStr; } else { str = lastName; } } else { } if (lastName != str) { lastName = str; functionLines.Add(""); functionLines.Add("#" + str); } } } } } } } if (instructionInfo.instruction == Instruction.MSG) { //if (this.AnnotateEnumerationType != null) //{ // if (expression == null) // { // expression = ainFile.DecompiledCodeCache.GetDecompiledCode(function); // } // CatchUpToAddress(ref expression, functionLines, address); //} int messageNumber = instructionInfo.word1; string message = ainFile.GetMessage(messageNumber); if (message != null) { if (useStringsToMatch == false || StringsToMatch.Contains(message)) { string messageLine = "m " + numberOfMessages.ToString("000") + " " + StringExportImport.EscapeText(message); functionLines.Add(messageLine); } numberOfMessages++; numberOfNonCommentedLines++; } } else if (instructionInfo.instruction == Instruction.STRSWITCH) { int switchBlockNumber = instructionInfo.word1; var switchBlock = ainFile.Switches.GetOrNull(switchBlockNumber); if (switchBlock != null) { foreach (var switchCase in switchBlock.SwitchCases) { int stringNumber = switchCase.Value; string str = ainFile.GetString(stringNumber); if (str != null) { AddString(ref numberOfNonCommentedLines, ref numberOfStrings, functionLines, stringNumber, str); } } } } else { int indexOfStringArgument = instructionInfo.instruction.IndexOfStringArgument(); if (indexOfStringArgument != -1) { int stringNumber = instructionInfo.words[indexOfStringArgument]; string str = ainFile.GetString(stringNumber); if (str != null) { AddString(ref numberOfNonCommentedLines, ref numberOfStrings, functionLines, stringNumber, str); } } } address = instructionInfo.nextAddress; } functionLines[1] = "#" + numberOfStrings.ToString() + " strings, " + numberOfMessages.ToString() + " messages"; if (numberOfNonCommentedLines == 0) { functionLines.Clear(); } return(functionLines); }