From 09eba228dd2a32816b577dadb4de37a897ac17f4 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Tue, 12 Oct 2021 11:16:50 -0700 Subject: [PATCH] Add "remove formatting" action This action removes operand formatting from all code and data in the selected range. In most cases this is equivalent to simply editing the various items and clicking the "default" format radio button, but the feature can be used to remove data formats that end up inside multi-byte instructions. Instructions with such formats cause warnings and were tricky to fix. Labels embedded in multi-byte items are also tricky to remove, so this clears those as well. It does not remove visible labels. This is done in a single pass, which means that labels that would become visible after the formatting is cleared will still be removed. Also, fix inclusion of address range end lines when restoring the selection. Their peculiar nature -- being associated with the offset of the last byte of multi-byte items -- was interfering with the selection save code. This does not add them to the selection when an address region deletion is undone, since technically they weren't part of the selection. Also, moved Edit Note higher in the Actions menu. --- CommonUtil/AddressMap.cs | 3 ++ SourceGen/LineListGen.cs | 15 +++++--- SourceGen/MainController.cs | 48 ++++++++++++++++++++++++++ SourceGen/WpfGui/MainWindow.xaml | 6 +++- SourceGen/WpfGui/MainWindow.xaml.cs | 9 ++++- docs/sgmanual/mainwin.html | 53 +++++++++++++++++++++-------- 6 files changed, 113 insertions(+), 21 deletions(-) diff --git a/CommonUtil/AddressMap.cs b/CommonUtil/AddressMap.cs index b083584..0e1b4e8 100644 --- a/CommonUtil/AddressMap.cs +++ b/CommonUtil/AddressMap.cs @@ -1099,6 +1099,9 @@ namespace CommonUtil { /// We use inclusive Offset values for both start and end. If we don't do this, the /// offset for end records will be outside the file bounds. It also gets a bit painful /// when the display list tries to update [M,N] if the end is actually held at N+1. + /// The fundamental problem is that the "end region" directive is a separate physical + /// entity in the line list, not an abstract start+length value, which must be placed + /// inside the address region. /// public class AddressChange { // True if this is a region start, false if a region end. diff --git a/SourceGen/LineListGen.cs b/SourceGen/LineListGen.cs index eaf6e7c..8c765f5 100644 --- a/SourceGen/LineListGen.cs +++ b/SourceGen/LineListGen.cs @@ -307,7 +307,15 @@ namespace SourceGen { if (lineType == Line.Type.Code || lineType == Line.Type.Data) { lineType = Line.Type.CodeOrData; } - if (line.FileOffset != curOffset) { + if (line.FileOffset == curOffset || lineType == Line.Type.ArEndDirective) { + // Another item at same offset. We special-case the arend directive + // because it's contained within the previous item, so we want it to be + // set on the existing [offset,offset+span) range tag. + tag.mSpan = Math.Max(tag.mSpan, line.OffsetSpan); + tag.mTypes |= lineType; + Debug.Assert(line.FileOffset >= tag.mOffset && + line.FileOffset < tag.mOffset + tag.mSpan); + } else { // advanced to new offset, flush previous if (tag != null) { savedSel.mSelectionTags.Add(tag); @@ -315,10 +323,6 @@ namespace SourceGen { curOffset = line.FileOffset; tag = new Tag(line.FileOffset, line.OffsetSpan, lineType); - } else { - // another item at same offset - tag.mSpan = Math.Max(tag.mSpan, line.OffsetSpan); - tag.mTypes |= lineType; } } if (curOffset == -1) { @@ -344,6 +348,7 @@ namespace SourceGen { /// that correspond to items in the SavedSelection tag list. /// /// Display list, with list of Lines. + /// Index of line to place at top of list control. /// Set of selected lines. public DisplayListSelection Restore(LineListGen dl, out int topIndex) { List lineList = dl.mLineList; diff --git a/SourceGen/MainController.cs b/SourceGen/MainController.cs index 1643392..9509548 100644 --- a/SourceGen/MainController.cs +++ b/SourceGen/MainController.cs @@ -2788,6 +2788,48 @@ namespace SourceGen { } } + public bool CanRemoveFormatting() { + // Want at least one line of code or data. No need to check for existing formatting. + EntityCounts counts = SelectionAnalysis.mEntityCounts; + return (counts.mDataLines > 0 || counts.mCodeLines > 0); + } + + public void RemoveFormatting() { + RangeSet sel = OffsetSetFromSelected(); + ChangeSet cs = new ChangeSet(16); + foreach (int offset in sel) { + if (offset < 0) { + // header comment + continue; + } + + // Formatted? + if (mProject.OperandFormats.TryGetValue(offset, out FormatDescriptor oldFd)) { + Debug.WriteLine("Remove format from +" + offset.ToString("x6")); + UndoableChange uc = UndoableChange.CreateOperandFormatChange(offset, + oldFd, null); + cs.Add(uc); + } + + // As an added bonus, check for mid-line labels. The tricky part with this is + // that the determination of visibility is made before the effects of removing + // the formatting are known. In general we try very hard to avoid embedding + // labels, so this is unlikely to be a problem. + Anattrib attr = mProject.GetAnattrib(offset); + if (attr.Symbol != null && !attr.IsStart) { + Debug.WriteLine("Remove label from +" + offset.ToString("x6")); + UndoableChange uc = UndoableChange.CreateLabelChange(offset, attr.Symbol, null); + cs.Add(uc); + } + } + + if (cs.Count != 0) { + ApplyUndoableChanges(cs); + } else { + Debug.WriteLine("No formatting or embedded labels found"); + } + } + public void ReloadExternalFiles() { string messages = mProject.LoadExternalFiles(); if (messages.Length != 0) { @@ -3525,6 +3567,11 @@ namespace SourceGen { RangeSet rs = new RangeSet(); foreach (int index in mMainWin.CodeDisplayList.SelectedIndices) { + if (CodeLineList[index].LineType == LineListGen.Line.Type.ArEndDirective) { + // We don't care about these, and they have the offset of the *last* byte + // of multi-byte instructions, which is a little confusing. + continue; + } int offset = CodeLineList[index].FileOffset; // Mark every byte of an instruction or multi-byte data item -- @@ -3536,6 +3583,7 @@ namespace SourceGen { // header area len = 1; } + Anattrib attr = mProject.GetAnattrib(offset); Debug.Assert(len > 0); for (int i = offset; i < offset + len; i++) { rs.Add(i); diff --git a/SourceGen/WpfGui/MainWindow.xaml b/SourceGen/WpfGui/MainWindow.xaml index a0c77c2..6791931 100644 --- a/SourceGen/WpfGui/MainWindow.xaml +++ b/SourceGen/WpfGui/MainWindow.xaml @@ -177,6 +177,7 @@ limitations under the License. + Ctrl+A @@ -315,6 +316,8 @@ limitations under the License. CanExecute="IsProjectOpen" Executed="ReloadExternalFilesCmd_Executed"/> + + - @@ -446,6 +449,7 @@ limitations under the License. + diff --git a/SourceGen/WpfGui/MainWindow.xaml.cs b/SourceGen/WpfGui/MainWindow.xaml.cs index afbb059..6013a47 100644 --- a/SourceGen/WpfGui/MainWindow.xaml.cs +++ b/SourceGen/WpfGui/MainWindow.xaml.cs @@ -1145,6 +1145,10 @@ namespace SourceGen.WpfGui { (counts.mCodeStartTags != 0 || counts.mCodeStopTags != 0 || counts.mInlineDataTags != 0); } + private void CanRemoveFormatting(object sender, CanExecuteRoutedEventArgs e) { + e.CanExecute = IsProjectOpen() && mMainCtrl.CanRemoveFormatting(); + } + private void CanJumpToOperand(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = IsProjectOpen() && mMainCtrl.CanJumpToOperand(); } @@ -1371,10 +1375,13 @@ namespace SourceGen.WpfGui { } private void RemoveAnalyzerTagsCmd_Executed(object sender, ExecutedRoutedEventArgs e) { - Debug.WriteLine("remove atags"); mMainCtrl.MarkAsType(CodeAnalysis.AnalyzerTag.None, false); } + private void RemoveFormattingCmd_Executed(object sender, ExecutedRoutedEventArgs e) { + mMainCtrl.RemoveFormatting(); + } + private void SaveCmd_Executed(object sender, ExecutedRoutedEventArgs e) { mMainCtrl.SaveProject(); } diff --git a/docs/sgmanual/mainwin.html b/docs/sgmanual/mainwin.html index b0a51f2..2b534dd 100644 --- a/docs/sgmanual/mainwin.html +++ b/docs/sgmanual/mainwin.html @@ -162,23 +162,14 @@ or character string, effectively selects the entire item.

the Actions menu item in the menu bar. The set of options that are enabled will depend on what you have selected in the main window.

    -
  • Set Address. Sets the - target address at that offset. When multiple lines are selected, - the target addresses at the start and end of the range is set. - Enabled when the first line selected is code, data, or an address - override, and the full selected range does not overlap with another - address override.
  • -
  • Override Status Flags. Changes - the status flags at that offset. Enabled when a single instruction - line is selected.
  • -
  • Edit Label. Sets the label - at that offset. Enabled when a single instruction or data line is - selected.
  • Edit Operand. Opens the Edit Instruction Operand or Edit Data Operand window, depending on what's selected. Enabled when a single instruction line is selected, or when one or more data lines are selected.
  • +
  • Edit Label. Sets the label + at that offset. Enabled when a single instruction or data line is + selected.
  • Edit Comment. Sets the comment at that offset. Enabled when a single instruction or data line is selected.
  • @@ -188,6 +179,15 @@ enabled will depend on what you have selected in the main window.

  • Edit Note. Sets the note at that offset. Enabled when a single instruction or data line, or an existing note, is selected.
  • +
  • Define Address Region. + Sets the assembly address at the selected offset. Can be used + to set a start point with a floating end, or specify a region + with a fixed end point (useful for code that get relocated). + Enabled when the first line selected is code, data, or an address + start directive.
  • +
  • Override Status Flags. Changes + the status flags at that offset. Enabled when a single instruction + line is selected.
  • Edit Project Symbol. Sets the name, value, and comment of the project symbol. Enabled when a single equate directive, generated from a project symbol, is @@ -199,14 +199,16 @@ enabled will depend on what you have selected in the main window.

    variable table.
  • Create/Edit Visualization Set. Create a new visualization set or edit an existing set.
  • - +
+
  • Analyzer Tags (Tag Address As Code Start Point, Tag Address As Code Stop Point, Tag Bytes As Inline Data, Remove Analyzer Tags). Enabled when one or more code and data lines are selected. Remove Analyzer Tags is only enabled when at least one line has tags. The keyboard shortcuts are two-key combinations.
  • - +
+
  • Format Address Table. Formats a series of bytes as parts of a table of addresses.
  • Toggle Single-Byte Format. Toggles @@ -214,6 +216,9 @@ enabled will depend on what you have selected in the main window.

    when one or more data lines are selected.
  • Format As Word. Formats two bytes as a 16-bit little-endian word.
  • +
  • Remove Formatting. Reverts + instruction and data operand formats to the default. Clears + embedded labels.
  • Delete Note / Long Comment. Deletes the selected note or long comment. Enabled when a single note or long comment is selected.
  • Show Hex Dump. Opens the hex dump @@ -359,11 +364,20 @@ include:

    • Hidden label: a label placed on code or data is now stuck in the middle of a multi-byte instruction or data item.
    • +
    • Hidden local variable table: a local variable table has been + placed in the middle of a multi-byte item.
    • +
    • Hidden visualization: a visualization set has been + placed in the middle of a multi-byte item.
    • Unresolved weak ref: a reference to a non-existent symbol was found.
    • +
    • Non-addressable label reference: a code or data operand has a + reference to a label defined in a non-addressable section of the + file. (The generated code will likely fail to assemble.)
    • Invalid offset or length: the offset or length in a format object had an invalid value.
    • Invalid descriptor: the format descriptor is inappropriate, e.g. formatting an instruction as a string.
    • +
    • Bank overrun: the generated code would run past address $ffff. + The handling of this in generated code is assembler-dependent.

    The "context" column will provide additional detail about the problem, and the "resolution" column will indicate how it's being handled. In most @@ -576,6 +590,17 @@ multi-byte data item, is the start of a new region (see what splits a region), or is the last byte in the file.

    +

    Remove Formatting

    + +

    Removes instruction and data operand formatting from the selected lines. +This removes the visible formatting as well as any formatting instructions +that got embedded inside multi-byte data items. (You will be notified of +such things in the message list.)

    + +

    This will also remove any labels that are embedded in multi-byte items, +without removing visible labels.

    + +

    Toggle Data Scan

    This menu item is in the Edit menu, and acts as a shortcut to opening