// IGenerator public void OutputOrgDirective(int offset, int address) { // 64tass separates the "compile offset", which determines where the output fits // into the generated binary, and "program counter", which determines the code // the assembler generates. Since we need to explicitly specify every byte in // the output file, the compile offset isn't very useful. We want to set it once // before the first line of code, then leave it alone. // // Any subsequent ORG changes are made to the program counter, and take the form // of a pair of ops (.logical <addr> to open, .here to end). Omitting the .here // causes an error. if (offset == 0) { // Set the "compile offset" to the initial address. OutputLine("*", "=", SourceFormatter.FormatHexValue(Project.AddrMap.Get(0), 4), string.Empty); } else { if (mNeedHereOp) { OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(HERE_PSEUDO_OP), string.Empty, string.Empty); } OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(sDataOpNames.OrgDirective), SourceFormatter.FormatHexValue(address, 4), string.Empty); mNeedHereOp = true; } }
// IGenerator public void OutputOrgDirective(int offset, int address) { // If there's only one address range, just set the "real" PC. If there's more // than one we can run out of space if the source file has a chunk in high memory // followed by a chunk in low memory, because the "real" PC determines when the // 64KB bank is overrun. if (offset == 0) { // first one if (Project.AddrMap.Count == 1) { OutputLine("*", "=", SourceFormatter.FormatHexValue(address, 4), string.Empty); return; } else { // set the real PC to address zero to ensure we get a full 64KB OutputLine("*", "=", SourceFormatter.FormatHexValue(0, 4), string.Empty); } } if (mInPseudoPcBlock) { // close previous block OutputLine(string.Empty, CLOSE_PSEUDOPC, string.Empty, string.Empty); } OutputLine(string.Empty, sDataOpNames.OrgDirective, SourceFormatter.FormatHexValue(address, 4) + " {", string.Empty); mInPseudoPcBlock = true; }
// IGenerator public void OutputOrgDirective(int offset, int address) { // Linear search for offset. List should be small, so this should be quick. int index = 0; foreach (AddressMap.AddressMapEntry ame in Project.AddrMap) { if (ame.Offset == offset) { break; } index++; } mLineBuilder.Clear(); TextUtil.AppendPaddedString(mLineBuilder, ";", 0); // using +1 to make it look like the comment ';' shifted it over TextUtil.AppendPaddedString(mLineBuilder, SourceFormatter.FormatPseudoOp(".segment"), mColumnWidths[0] + 1); TextUtil.AppendPaddedString(mLineBuilder, string.Format("\"SEG{0:D3}\"", index), mColumnWidths[0] + mColumnWidths[1] + 1); OutputLine(mLineBuilder.ToString()); OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(sDataOpNames.OrgDirective), SourceFormatter.FormatHexValue(address, 4), string.Empty); }
/// <summary> /// Outputs formatted data in an unformatted way, because the code generator couldn't /// figure out how to do something better. /// </summary> private void OutputNoJoy(int offset, int length, string labelStr, string commentStr) { byte[] data = Project.FileData; Debug.Assert(length > 0); Debug.Assert(offset >= 0 && offset < data.Length); bool singleValue = true; byte val = data[offset]; for (int i = 1; i < length; i++) { if (data[offset + i] != val) { singleValue = false; break; } } if (singleValue && length > 1) { string opcodeStr = SourceFormatter.FormatPseudoOp(sDataOpNames.Fill); string operandStr = length + "," + SourceFormatter.FormatHexValue(val, 2); OutputLine(labelStr, opcodeStr, operandStr, commentStr); } else { OutputDenseHex(offset, length, labelStr, commentStr); } }
private static string InjectSourceCodeAtLevel(int level, string sourceCode) { SourceFormatter formatter = new SourceFormatter(); formatter.AppendCodeBlock(level, sourceCode); return(formatter.ReturnSource()); }
public static string GenerateContractEventHandlerMethod(CsField sourceField, CsEvent targetEvent, NamespaceManager manager = null) { if (sourceField == null) { return(null); } if (!sourceField.IsLoaded) { return(null); } if (targetEvent == null) { return(null); } if (!targetEvent.IsLoaded) { return(null); } SourceFormatter formatter = new SourceFormatter(); formatter.AppendCodeLine(0, "/// <summary>"); formatter.AppendCodeLine(0, $"/// Handles the raised event {targetEvent.Name}"); formatter.AppendCodeLine(0, "/// </summary>"); formatter.AppendCodeLine(0, $"protected void {GenerateContractEventHandlerMethodName(sourceField,targetEvent)}{targetEvent.EventHandlerDelegate.Parameters.CSharpFormatParametersSignature(manager,false)}"); formatter.AppendCodeLine(0, "{"); formatter.AppendCodeLine(0); formatter.AppendCodeLine(1, "//TODO: Add Event handler logic"); formatter.AppendCodeLine(0); formatter.AppendCodeLine(0, "}"); formatter.AppendCodeLine(0); return(formatter.ReturnSource()); }
// IGenerator public void OutputAsmConfig() { CpuDef cpuDef = Project.CpuDef; string cpuStr; if (cpuDef.Type == CpuDef.CpuType.Cpu65816) { cpuStr = "65816"; } else if (cpuDef.Type == CpuDef.CpuType.Cpu65C02) { cpuStr = "65c02"; } else if (cpuDef.Type == CpuDef.CpuType.CpuW65C02) { cpuStr = "w65c02"; } else if (cpuDef.Type == CpuDef.CpuType.Cpu6502 && cpuDef.HasUndocumented) { cpuStr = "6510"; } else { cpuStr = "6502"; } OutputLine(string.Empty, SourceFormatter.FormatPseudoOp("!cpu"), cpuStr, string.Empty); }
/// <summary> /// Updates the directives in the page file to use razor syntax. /// </summary> /// <param name="fileName">The file being processed.</param> /// <param name="sourceData">The source data to be updated.</param> /// <returns>The updated content.</returns> private async Task <String> SetRazorPageDirectives(string fileName, Dictionary <string, string> sourceData) { //String result = String.Empty; SourceFormatter result = new SourceFormatter(); try { var pageData = sourceData["HeaderData"]; Regex regex = new Regex(@"(?<=\bMasterPageFile="")[^""]*"); Match match = regex.Match(pageData); string layout = match.Value; layout = layout.Replace(".", ""); //remove the old-style Site.Master layout to read SiteMaster result.AppendCode($"@page \"/{fileName}\" "); if (layout.Length > 0) { //Making sure the ~ gets removed from directives result.AppendCodeLine(0, $"@layout { layout.Replace("~/", "")}"); } //result += $"@inherits {fileName}Base\r\n\r\n {sourceData["alteredSource"]}"; result.AppendCodeLine(0); result.AppendCodeLine(0); result.AppendCodeLine(0, $"{sourceData["alteredSource"]}"); } catch (Exception unhandledError) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"The following unhandled error occured while setting the razor page directives in the file {fileName}. '{unhandledError.Message}'"); } return(result.ReturnSource()); }
public static string GeneratePartialClass(CsClass source, NamespaceManager manager = null) { if (source == null) { return(null); } if (!source.IsLoaded) { return(null); } SourceFormatter formatter = new SourceFormatter(); StringBuilder classBuilder = new StringBuilder($"{source.Security.CSharpFormatKeyword()} partial {Keywords.Class} {source.Name}"); if (source.IsGeneric) { classBuilder.Append(source.GenericParameters.CSharpFormatGenericParametersSignature(manager)); } formatter.AppendCodeLine(0); formatter.AppendCodeLine(0, $"namespace {source.Namespace}"); formatter.AppendCodeLine(0, "{"); formatter.AppendCodeLine(0); formatter.AppendCodeLine(1, classBuilder.ToString()); formatter.AppendCodeLine(1, "{"); formatter.AppendCodeLine(1); formatter.AppendCodeLine(1, "}"); formatter.AppendCodeLine(0); formatter.AppendCodeLine(0, "}"); return(formatter.ReturnSource()); }
public void TestBasicTransformation() { SourceCode source = new SourceCode("abc123"); SourceTransformation transformation = new SourceTransformation(new SourceContext(0, 3), n => "a"); string transformed = SourceFormatter.Format(source, transformation); Assert.AreEqual(transformed, "aaa123"); }
public void TestNestedTransformation() { SourceCode source = new SourceCode("1111111"); SourceTransformation transformation1 = new SourceTransformation(new SourceContext(2, 3), n => "2"); SourceTransformation transformation2 = new SourceTransformation(new SourceContext(3, 1), n => "3"); string transformed = SourceFormatter.Format(source, transformation1, transformation2); Assert.AreEqual(transformed, "1123211"); }
public void TestUnrollingWithHigherIndexThanZero() { SourceCode source = new SourceCode("abc123"); SourceTransformation transformation1 = new SourceTransformation(new SourceContext(2, 3), n => "2"); SourceTransformation transformation2 = new SourceTransformation(new SourceContext(3, 1), n => "3"); var unrolled = SourceFormatter.UnrollNested(new[] { transformation1, transformation2 }).ToArray(); Assert.IsNotNull(unrolled); Assert.AreEqual(unrolled.Length, 3); Assert.AreEqual(unrolled[0].Context, new SourceContext(2, 1)); Assert.AreEqual(unrolled[1].Context, new SourceContext(3, 1)); Assert.AreEqual(unrolled[2].Context, new SourceContext(4, 1)); }
// IGenerator public void OutputLocalVariableTable(int offset, List <DefSymbol> newDefs, LocalVariableTable allDefs) { foreach (DefSymbol defSym in newDefs) { string valueStr = PseudoOp.FormatNumericOperand(SourceFormatter, Project.SymbolTable, null, defSym.DataDescriptor, defSym.Value, 1, PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix); OutputLine(SourceFormatter.FormatVariableLabel(defSym.Label), SourceFormatter.FormatPseudoOp(sDataOpNames.VarDirective), valueStr, SourceFormatter.FormatEolComment(defSym.Comment)); } }
public void TestUnrolling() { SourceCode source = new SourceCode("abc123"); SourceTransformation transformation = new SourceTransformation(new SourceContext(0, 4), n => "a"); SourceTransformation transformationNested = new SourceTransformation(new SourceContext(1, 1), n => "b"); var unrolled = SourceFormatter.UnrollNested(new[] { transformation, transformationNested }).ToArray(); Assert.IsNotNull(unrolled); Assert.AreEqual(unrolled.Length, 4); Assert.AreEqual(unrolled[0].Context, new SourceContext(0, 1)); Assert.AreEqual(unrolled[1].Context, new SourceContext(1, 1)); Assert.AreEqual(unrolled[2].Context, new SourceContext(2, 1)); Assert.AreEqual(unrolled[3].Context, new SourceContext(3, 1)); }
// IGenerator public void OutputLocalVariableTable(int offset, List <DefSymbol> newDefs, LocalVariableTable allDefs) { foreach (DefSymbol defSym in newDefs) { // Use an operand length of 1 so values are shown as concisely as possible. string valueStr = PseudoOp.FormatNumericOperand(SourceFormatter, Project.SymbolTable, null, defSym.DataDescriptor, defSym.Value, 1, PseudoOp.FormatNumericOpFlags.None); OutputLine(SourceFormatter.FormatVariableLabel(defSym.Label), SourceFormatter.FormatPseudoOp(sDataOpNames.VarDirective), valueStr, SourceFormatter.FormatEolComment(defSym.Comment)); } }
// IGenerator public void OutputRegWidthDirective(int offset, int prevM, int prevX, int newM, int newX) { // prevM/prevX may be ambiguous for offset 0, but otherwise everything // should be either 0 or 1. Debug.Assert(newM == 0 || newM == 1); Debug.Assert(newX == 0 || newX == 1); if (offset == 0 && newM == 1 && newX == 1) { // Assembler defaults to short regs, so we can skip this. return; } OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(REG_WIDTH_DIRECTIVE), "%" + newM + newX, string.Empty); }
// IGenerator public void FlushArDirectives() { // Output pending directives. There will always be something to do here unless // we were in "relative" mode. Debug.Assert(mNextAddress >= 0 || mIsInRelative); if (mNextAddress >= 0) { OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective), SourceFormatter.FormatHexValue(mNextAddress, 4), string.Empty); } mNextAddress = -1; mIsInRelative = false; }
// IGenerator public void OutputRegWidthDirective(int offset, int prevM, int prevX, int newM, int newX) { if (prevM != newM) { string mop = (newM == 0) ? ".al" : ".as"; OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(mop), string.Empty, string.Empty); } if (prevX != newX) { string xop = (newX == 0) ? ".xl" : ".xs"; OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(xop), string.Empty, string.Empty); } }
// IGenerator public void OutputLocalVariableTable(int offset, List <DefSymbol> newDefs, LocalVariableTable allDefs) { OutputLine(string.Empty, "!zone", "Z" + offset.ToString("x6"), string.Empty); for (int i = 0; i < allDefs.Count; i++) { DefSymbol defSym = allDefs[i]; string valueStr = PseudoOp.FormatNumericOperand(SourceFormatter, Project.SymbolTable, null, defSym.DataDescriptor, defSym.Value, 1, PseudoOp.FormatNumericOpFlags.None); OutputEquDirective(SourceFormatter.FormatVariableLabel(defSym.Label), valueStr, defSym.Comment); } }
public static string GenerateRaiseContractEvent(CsEvent targetEvent, NamespaceManager manager = null) { if (targetEvent == null) { return(null); } if (!targetEvent.IsLoaded) { return(null); } SourceFormatter formatter = new SourceFormatter(); string eventParameters = targetEvent.RaiseMethod.Parameters.CSharpFormatParametersSignature(manager); int parameterCount = 0; StringBuilder parameterBuilder = new StringBuilder(); foreach (var raiseMethodParameter in targetEvent.RaiseMethod.Parameters) { parameterCount++; if (parameterCount > 1) { parameterBuilder.Append($", {raiseMethodParameter.Name}"); continue; } parameterBuilder.Append(raiseMethodParameter.Name); } formatter.AppendCodeLine(0, "/// <summary>"); formatter.AppendCodeLine(0, $"/// Raises the event {targetEvent.Name}"); formatter.AppendCodeLine(0, "/// </summary>"); formatter.AppendCodeLine(0, $"protected void On{targetEvent.Name}{targetEvent.RaiseMethod.Parameters.CSharpFormatParametersSignature(manager,false)}"); formatter.AppendCodeLine(0, "{"); formatter.AppendCodeLine(0); formatter.AppendCodeLine(1, $"var raiseHandler = _{targetEvent.Name.ConvertToCamelCase()};"); formatter.AppendCodeLine(1, $"raiseHandler?.Invoke({parameterBuilder});"); formatter.AppendCodeLine(0); formatter.AppendCodeLine(0, "}"); formatter.AppendCodeLine(0); return(formatter.ReturnSource()); }
// IGenerator public void OutputAsmConfig() { CpuDef cpuDef = Project.CpuDef; string cpuStr; if (cpuDef.Type == CpuDef.CpuType.Cpu65816) { cpuStr = "65816"; } else if (cpuDef.Type == CpuDef.CpuType.Cpu65C02) { cpuStr = "65c02"; } else if (cpuDef.Type == CpuDef.CpuType.CpuW65C02) { cpuStr = "w65c02"; } else if (cpuDef.Type == CpuDef.CpuType.Cpu6502 && cpuDef.HasUndocumented) { cpuStr = "6502i"; } else { cpuStr = "6502"; } OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(".cpu"), '\"' + cpuStr + '\"', string.Empty); // C64 PETSCII and C64 screen codes are built in. Define ASCII if we also // need that. mCurrentEncoding = CharEncoding.Encoding.C64Petscii; CheckAsciiFormats(out bool hasAscii, out bool hasHighAscii); if (hasHighAscii) { OutputLine(string.Empty, ".enc", '"' + HIGH_ASCII_ENC_NAME + '"', string.Empty); OutputLine(string.Empty, ".cdef", "$20,$7e,$a0", string.Empty); mCurrentEncoding = CharEncoding.Encoding.HighAscii; } if (hasAscii) { OutputLine(string.Empty, ".enc", '"' + ASCII_ENC_NAME + '"', string.Empty); OutputLine(string.Empty, ".cdef", "$20,$7e,$20", string.Empty); mCurrentEncoding = CharEncoding.Encoding.Ascii; } }
/// <summary> /// Generates a method that releases to a target interface contract for the target field. /// </summary> /// <param name="sourceField">The field for which events to subscribe to.</param> /// <param name="contract">The contract to subscribe to.</param> /// <returns>Full source code for the subscribe method.</returns> public static string GenerateContractReleaseMethod(CsField sourceField, CsInterface contract) { if (sourceField == null) { return(null); } if (!sourceField.IsLoaded) { return(null); } if (contract == null) { return(null); } if (!contract.IsLoaded) { return(null); } SourceFormatter formatter = new SourceFormatter(); formatter.AppendCodeLine(0, "/// <summary>"); formatter.AppendCodeLine(0, $"/// Releases the events from the interface contract of {contract.Namespace}.{contract.Name} for the field {sourceField.Name}"); formatter.AppendCodeLine(0, "/// </summary>"); formatter.AppendCodeLine(0, $"private void {GenerateContractReleaseMethodName(sourceField)}()"); formatter.AppendCodeLine(0, "{"); formatter.AppendCodeLine(0); formatter.AppendCodeLine(1, $"if({sourceField.Name} == null) return;"); formatter.AppendCodeLine(0); foreach (var contractEvent in contract.Events) { if (!contractEvent.IsLoaded) { continue; } formatter.AppendCodeLine(1, $"{sourceField.Name}.{contractEvent.Name} -= {sourceField.Name.ConvertToProperCase(new []{'_'})}_{contractEvent.Name}_EventHandler;"); } formatter.AppendCodeLine(0); formatter.AppendCodeLine(0, "}"); formatter.AppendCodeLine(0); return(formatter.ReturnSource()); }
// IGenerator public void OutputLocalVariableTable(int offset, List <DefSymbol> newDefs, LocalVariableTable allDefs) { // We can do better here, but it requires knowing whether anything in "newDefs" // overwrote a previous entry. If everything is new, we don't need to start // a new zone, and can just output newDefs. (We don't need to start a new zone // on a "clear previous".) OutputLine(string.Empty, "!zone", "Z" + offset.ToString("x6"), string.Empty); for (int i = 0; i < allDefs.Count; i++) { DefSymbol defSym = allDefs[i]; string valueStr = PseudoOp.FormatNumericOperand(SourceFormatter, Project.SymbolTable, null, defSym.DataDescriptor, defSym.Value, 1, PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix); OutputEquDirective(SourceFormatter.FormatVariableLabel(defSym.Label), valueStr, defSym.Comment); } }
// IGenerator public void GenerateShortSequence(int offset, int length, out string opcode, out string operand) { Debug.Assert(length >= 1 && length <= 4); // Use a comma-separated list of individual hex bytes. opcode = sDataOpNames.DefineData1; StringBuilder sb = new StringBuilder(length * 4); for (int i = 0; i < length; i++) { if (i != 0) { sb.Append(','); } sb.Append(SourceFormatter.FormatHexValue(Project.FileData[offset + i], 2)); } operand = sb.ToString(); }
// IGenerator public void OutputOrgDirective(int offset, int address) { // For the first one, set the "real" PC. For all subsequent directives, set the // "pseudo" PC. if (offset == 0) { OutputLine("*", "=", SourceFormatter.FormatHexValue(address, 4), string.Empty); } else { if (mInPseudoPcBlock) { // close previous block OutputLine(string.Empty, CLOSE_PSEUDOPC, string.Empty, string.Empty); } OutputLine(string.Empty, sDataOpNames.OrgDirective, SourceFormatter.FormatHexValue(address, 4) + " {", string.Empty); mInPseudoPcBlock = true; } }
/// <summary> /// Extension method that will add a using statement to target source code. If the using statement already exists it will simply return the existing source. /// </summary> /// <param name="source">The source code to update.</param> /// <param name="nameSpace">The namespace to be added to the using statement.</param> /// <param name="alias">Optional parameter to set if you want an alias assigned to the namespace.</param> /// <returns>The updated source code or the original source code if no changes were necessary.</returns> public static async Task <CsSource> AddUsingStatementAsync(this CsSource source, string nameSpace, string alias = null) { // ReSharper disable once ExpressionIsAlwaysNull if (source == null) { return(source); } if (string.IsNullOrEmpty(nameSpace)) { return(source); } if (source.HasUsingStatement(nameSpace, alias)) { return(source); } SourceFormatter usingFormatter = new SourceFormatter(); usingFormatter.AppendCodeLine(0, alias == null ? $"using {nameSpace};" : $"using {alias} = {nameSpace};"); string usingStatement = usingFormatter.ReturnSource(); CsSource result = null; if (source.NamespaceReferences.Any()) { var lastUsingStatement = source.NamespaceReferences.Last(); result = await lastUsingStatement.AddAfterAsync(usingStatement); } else { result = await source.AddToBeginningAsync(usingStatement); } return(result); }
// IGenerator public void OutputEquDirective(string name, string valueStr, string comment) { OutputLine(name, SourceFormatter.FormatPseudoOp(sDataOpNames.EquDirective), valueStr, SourceFormatter.FormatEolComment(comment)); }
// IGenerator public void OutputDataOp(int offset) { Formatter formatter = SourceFormatter; byte[] data = Project.FileData; Anattrib attr = Project.GetAnattrib(offset); string labelStr = string.Empty; if (attr.Symbol != null) { labelStr = mLocalizer.ConvLabel(attr.Symbol.Label); } string commentStr = SourceFormatter.FormatEolComment(Project.Comments[offset]); string opcodeStr, operandStr; FormatDescriptor dfd = attr.DataDescriptor; Debug.Assert(dfd != null); int length = dfd.Length; Debug.Assert(length > 0); bool multiLine = false; switch (dfd.FormatType) { case FormatDescriptor.Type.Default: if (length != 1) { Debug.Assert(false); length = 1; } opcodeStr = sDataOpNames.DefineData1; int operand = RawData.GetWord(data, offset, length, false); operandStr = formatter.FormatHexValue(operand, length * 2); break; case FormatDescriptor.Type.NumericLE: opcodeStr = sDataOpNames.GetDefineData(length); operand = RawData.GetWord(data, offset, length, false); UpdateCharacterEncoding(dfd); operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable, mLocalizer.LabelMap, dfd, operand, length, PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix); break; case FormatDescriptor.Type.NumericBE: opcodeStr = sDataOpNames.GetDefineBigData(length); if ((string.IsNullOrEmpty(opcodeStr))) { // Nothing defined, output as comma-separated single-byte values. GenerateShortSequence(offset, length, out opcodeStr, out operandStr); } else { UpdateCharacterEncoding(dfd); operand = RawData.GetWord(data, offset, length, true); operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable, mLocalizer.LabelMap, dfd, operand, length, PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix); } break; case FormatDescriptor.Type.Fill: opcodeStr = sDataOpNames.Fill; operandStr = length + "," + formatter.FormatHexValue(data[offset], 2); break; case FormatDescriptor.Type.Dense: multiLine = true; opcodeStr = operandStr = null; OutputDenseHex(offset, length, labelStr, commentStr); break; case FormatDescriptor.Type.Junk: int fillVal = Helper.CheckRangeHoldsSingleValue(data, offset, length); if (fillVal >= 0 && GenCommon.CheckJunkAlign(offset, dfd, Project.AddrMap)) { // .align <expression>[, <fill>] opcodeStr = sDataOpNames.Align; int alignVal = 1 << FormatDescriptor.AlignmentToPower(dfd.FormatSubType); operandStr = alignVal.ToString() + "," + formatter.FormatHexValue(fillVal, 2); } else if (fillVal >= 0) { // treat same as Fill opcodeStr = sDataOpNames.Fill; operandStr = length + "," + formatter.FormatHexValue(fillVal, 2); } else { // treat same as Dense multiLine = true; opcodeStr = operandStr = null; OutputDenseHex(offset, length, labelStr, commentStr); } break; case FormatDescriptor.Type.StringGeneric: case FormatDescriptor.Type.StringReverse: case FormatDescriptor.Type.StringNullTerm: case FormatDescriptor.Type.StringL8: case FormatDescriptor.Type.StringL16: case FormatDescriptor.Type.StringDci: multiLine = true; opcodeStr = operandStr = null; OutputString(offset, labelStr, commentStr); break; default: opcodeStr = "???"; operandStr = "***"; break; } if (!multiLine) { opcodeStr = formatter.FormatPseudoOp(opcodeStr); OutputLine(labelStr, opcodeStr, operandStr, commentStr); } }
private async Task <CsSource> UpdateSubscriptionAsync(CsField subscriptionField, CsClass sourceClass, VsCSharpSource source) { SourceFormatter formatter = new SourceFormatter(); string injectSourceCode = null; var contract = subscriptionField.DataType.GetInterfaceModel(); if (contract == null) { return(null); } CsSource sourceCode = source.SourceCode; try { CsClass currentClass = sourceClass; var events = contract.Events; var subscribePath = ContractHelper.GetSubscribeFilePath(currentClass); if (!subscribePath.hasFile) { var manager = sourceCode.LoadNamespaceManager(sourceClass.Namespace); var parent = await source.GetParentAsync(); if (parent == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } VsDocument generatedDocument = null; string partialClassSource = CSharpSourceGenerationCommon.GeneratePartialClass(currentClass, manager); if (parent.ModelType == VisualStudioModelType.ProjectFolder) { var parentFolder = parent as VsProjectFolder; if (parentFolder == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } generatedDocument = await parentFolder.AddDocumentAsync(Path.GetFileName(subscribePath.filePath), partialClassSource); } else { var parentProject = parent as VsProject; if (parentProject == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } generatedDocument = await parentProject.AddDocumentAsync(subscribePath.filePath, partialClassSource); } sourceCode = await generatedDocument.GetCSharpSourceModelAsync(); sourceCode = await sourceCode.AddMissingNamespaces(contract.Events, currentClass.Namespace); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } } else { var parent = await source.GetParentAsync(); VsCSharpSource sourceDocument = null; if (parent.ModelType == VisualStudioModelType.ProjectFolder) { var parentFolder = parent as VsProjectFolder; if (parentFolder == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } var children = await parentFolder.GetChildrenAsync(false, true); sourceDocument = children.Where(c => c.ModelType == VisualStudioModelType.CSharpSource) .Cast <VsCSharpSource>() .FirstOrDefault(s => s.SourceCode.SourceDocument == subscribePath.filePath); } else { var parentProject = parent as VsProject; if (parentProject == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } var children = await parentProject.GetChildrenAsync(false, true); sourceDocument = children.Where(c => c.ModelType == VisualStudioModelType.CSharpSource) .Cast <VsCSharpSource>() .FirstOrDefault(s => s.SourceCode.SourceDocument == subscribePath.filePath);; } if (sourceDocument == null) { throw new CodeFactoryException("Could load the contract document."); } sourceCode = sourceDocument.SourceCode; sourceCode = await sourceCode.AddMissingNamespaces(contract.Events, currentClass.Namespace); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } } var namespaceManager = sourceCode.LoadNamespaceManager(currentClass.Namespace); foreach (var contractEvent in contract.Events) { var eventHandlerName = CSharpSourceGenerationWPF.GenerateContractEventHandlerMethodName(subscriptionField, contractEvent); if (eventHandlerName == null) { throw new CodeFactoryException($"Could not create the source code for a contract event handler."); } if (currentClass.Methods.Any(m => m.Name == eventHandlerName)) { continue; } var eventHandlerSource = CSharpSourceGenerationWPF.GenerateContractEventHandlerMethod(subscriptionField, contractEvent, namespaceManager); if (eventHandlerSource == null) { throw new CodeFactoryException($"Could not create the source code for the event handler {eventHandlerName}"); } sourceCode = await currentClass.AddToEndAsync(subscribePath.filePath, InjectSourceCodeAtLevel(2, eventHandlerSource)); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } } var subscriptionName = CSharpSourceGenerationWPF.GenerateContractSubscriptionMethodName(subscriptionField); var subscriptionMethod = currentClass.Methods.FirstOrDefault(m => m.Name == subscriptionName); if (subscriptionMethod != null) { sourceCode = await subscriptionMethod.DeleteAsync(); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } } var subscriptionSource = CSharpSourceGenerationWPF.GenerateContractSubscriptionMethod(subscriptionField, contract); if (subscriptionSource == null) { throw new CodeFactoryException("Cannot generate the subscription contract source code."); } sourceCode = await currentClass.AddToEndAsync(subscribePath.filePath, InjectSourceCodeAtLevel(2, subscriptionSource)); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } var releaseName = CSharpSourceGenerationWPF.GenerateContractReleaseMethodName(subscriptionField); var releaseMethod = currentClass.Methods.FirstOrDefault(m => m.Name == releaseName); if (releaseMethod != null) { sourceCode = await releaseMethod.DeleteAsync(); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } } var releaseSource = CSharpSourceGenerationWPF.GenerateContractReleaseMethod(subscriptionField, contract); if (releaseSource == null) { throw new CodeFactoryException("Cannot generate the release contract source code."); } sourceCode = await currentClass.AddToEndAsync(subscribePath.filePath, InjectSourceCodeAtLevel(2, releaseSource)); } catch (CodeFactoryException) { throw; } catch (Exception unhandledException) { throw new CodeFactoryException("The following unhandledException occured", unhandledException); } return(sourceCode); }
// IGenerator public void OutputArDirective(CommonUtil.AddressMap.AddressChange change) { // This is similar in operation to the AsmTass64 implementation. See comments there. Debug.Assert(mPcDepth >= 0); int nextAddress = change.Address; if (nextAddress == Address.NON_ADDR) { // Start non-addressable regions at zero to ensure they don't overflow bank. nextAddress = 0; } if (change.IsStart) { if (change.Region.HasValidPreLabel) { string labelStr = mLocalizer.ConvLabel(change.Region.PreLabel); OutputLine(labelStr, string.Empty, string.Empty, string.Empty); } if (mPcDepth == 0 && mFirstIsOpen) { mPcDepth++; // Set the "real" PC for the first address change. If we're in "loadable" // mode, just set "*=". If we're in "streaming" mode, we set "*=" to zero // and then use a pseudo-PC. if (mOutputMode == OutputMode.Loadable) { OutputLine("*", "=", SourceFormatter.FormatHexValue(nextAddress, 4), string.Empty); return; } else { // set the real PC to address zero to ensure we get a full 64KB OutputLine("*", "=", SourceFormatter.FormatHexValue(0, 4), string.Empty); } } AddressMap.AddressRegion region = change.Region; string addrStr; if (region.HasValidIsRelative) { int diff = nextAddress - region.PreLabelAddress; string pfxStr; if (diff >= 0) { pfxStr = "*+"; } else { pfxStr = "*-"; diff = -diff; } addrStr = pfxStr + SourceFormatter.FormatHexValue(diff, 4); } else { addrStr = SourceFormatter.FormatHexValue(nextAddress, 4); } OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective), addrStr + " {", string.Empty); mPcDepth++; } else { mPcDepth--; if (mPcDepth > 0 || !mFirstIsOpen) { // close previous block OutputLine(string.Empty, SourceFormatter.FormatPseudoOp(sDataOpNames.ArEndDirective), string.Empty, string.Empty); //";" + SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective)); } else { // mark initial "*=" region as closed, but don't output anything mFirstIsOpen = false; } } }