diff --git a/SourceGen/AppForms/EditAppSettings.Designer.cs b/SourceGen/AppForms/EditAppSettings.Designer.cs
index 251af8a..d325672 100644
--- a/SourceGen/AppForms/EditAppSettings.Designer.cs
+++ b/SourceGen/AppForms/EditAppSettings.Designer.cs
@@ -91,6 +91,8 @@ namespace SourceGen.AppForms {
this.showAsmIdentCheckBox = new System.Windows.Forms.CheckBox();
this.disableLabelLocalizationCheckBox = new System.Windows.Forms.CheckBox();
this.displayFormatTabPage = new System.Windows.Forms.TabPage();
+ this.expressionStyleComboBox = new System.Windows.Forms.ComboBox();
+ this.expressionStyleLabel = new System.Windows.Forms.Label();
this.fmtExplanationLabel = new System.Windows.Forms.Label();
this.quickDisplayFormatGroup = new System.Windows.Forms.GroupBox();
this.displayFmtQuickComboBox = new System.Windows.Forms.ComboBox();
@@ -157,8 +159,6 @@ namespace SourceGen.AppForms {
this.defineData1Label = new System.Windows.Forms.Label();
this.equDirectiveTextBox = new System.Windows.Forms.TextBox();
this.equDirectiveLabel = new System.Windows.Forms.Label();
- this.expressionStyleLabel = new System.Windows.Forms.Label();
- this.expressionStyleComboBox = new System.Windows.Forms.ComboBox();
this.settingsTabControl.SuspendLayout();
this.codeViewTabPage.SuspendLayout();
this.codeViewMiscGroupBox.SuspendLayout();
@@ -752,6 +752,24 @@ namespace SourceGen.AppForms {
this.displayFormatTabPage.Text = "Display Format";
this.displayFormatTabPage.UseVisualStyleBackColor = true;
//
+ // expressionStyleComboBox
+ //
+ this.expressionStyleComboBox.FormattingEnabled = true;
+ this.expressionStyleComboBox.Location = new System.Drawing.Point(98, 153);
+ this.expressionStyleComboBox.Name = "expressionStyleComboBox";
+ this.expressionStyleComboBox.Size = new System.Drawing.Size(121, 21);
+ this.expressionStyleComboBox.TabIndex = 5;
+ this.expressionStyleComboBox.SelectedIndexChanged += new System.EventHandler(this.expressionStyleComboBox_SelectedIndexChanged);
+ //
+ // expressionStyleLabel
+ //
+ this.expressionStyleLabel.AutoSize = true;
+ this.expressionStyleLabel.Location = new System.Drawing.Point(7, 156);
+ this.expressionStyleLabel.Name = "expressionStyleLabel";
+ this.expressionStyleLabel.Size = new System.Drawing.Size(85, 13);
+ this.expressionStyleLabel.TabIndex = 4;
+ this.expressionStyleLabel.Text = "Expression style:";
+ //
// fmtExplanationLabel
//
this.fmtExplanationLabel.AutoSize = true;
@@ -1468,24 +1486,6 @@ namespace SourceGen.AppForms {
this.equDirectiveLabel.Text = "Equate:";
this.equDirectiveLabel.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
- // expressionStyleLabel
- //
- this.expressionStyleLabel.AutoSize = true;
- this.expressionStyleLabel.Location = new System.Drawing.Point(7, 156);
- this.expressionStyleLabel.Name = "expressionStyleLabel";
- this.expressionStyleLabel.Size = new System.Drawing.Size(85, 13);
- this.expressionStyleLabel.TabIndex = 4;
- this.expressionStyleLabel.Text = "Expression style:";
- //
- // expressionStyleComboBox
- //
- this.expressionStyleComboBox.FormattingEnabled = true;
- this.expressionStyleComboBox.Location = new System.Drawing.Point(98, 153);
- this.expressionStyleComboBox.Name = "expressionStyleComboBox";
- this.expressionStyleComboBox.Size = new System.Drawing.Size(121, 21);
- this.expressionStyleComboBox.TabIndex = 5;
- this.expressionStyleComboBox.SelectedIndexChanged += new System.EventHandler(this.expressionStyleComboBox_SelectedIndexChanged);
- //
// EditAppSettings
//
this.AcceptButton = this.okButton;
diff --git a/SourceGen/AppForms/EditAppSettings.cs b/SourceGen/AppForms/EditAppSettings.cs
index ec4b891..d777523 100644
--- a/SourceGen/AppForms/EditAppSettings.cs
+++ b/SourceGen/AppForms/EditAppSettings.cs
@@ -37,6 +37,15 @@ namespace SourceGen.AppForms {
PseudoOp = 3
}
+ ///
+ /// Clipboard format enumeration. Numbers must match order of items in combo box.
+ ///
+ public enum ClipLineFormat {
+ Unknown = -1,
+ AssemblerSource = 0,
+ Disassembly = 1
+ }
+
///
/// ProjectView reference. When the user hits Apply, the object's ApplyAppSettings
/// method will be invoked.
@@ -140,7 +149,7 @@ namespace SourceGen.AppForms {
showCol5, showCol6, showCol7, showCol8 };
Debug.Assert(NUM_COLUMNS == 9);
- // Extract formats from column-width button labels.
+ // Extract format strings from column-width button labels.
for (int i = 0; i < NUM_COLUMNS; i++) {
mColButtons[i].Click += ColumnVisibilityButtonClick;
mColumnFormats[i] = mColButtons[i].Text;
@@ -230,7 +239,8 @@ namespace SourceGen.AppForms {
upperSCheckBox.Checked = mSettings.GetBool(AppSettings.FMT_UPPER_OPERAND_S, false);
upperXYCheckBox.Checked = mSettings.GetBool(AppSettings.FMT_UPPER_OPERAND_XY, false);
- int clipIndex = mSettings.GetInt(AppSettings.CLIP_LINE_FORMAT, 0);
+ int clipIndex = mSettings.GetEnum(AppSettings.CLIP_LINE_FORMAT,
+ typeof(ClipLineFormat), 0);
if (clipIndex >= 0 && clipIndex < clipboardFormatComboBox.Items.Count) {
clipboardFormatComboBox.SelectedIndex = clipIndex;
}
@@ -422,7 +432,8 @@ namespace SourceGen.AppForms {
}
private void clipboardFormatComboBox_SelectedIndexChanged(object sender, EventArgs e) {
- mSettings.SetInt(AppSettings.CLIP_LINE_FORMAT, clipboardFormatComboBox.SelectedIndex);
+ mSettings.SetEnum(AppSettings.CLIP_LINE_FORMAT, typeof(ClipLineFormat),
+ clipboardFormatComboBox.SelectedIndex);
SetDirty(true);
}
diff --git a/SourceGen/AppForms/EditProjectProperties.Designer.cs b/SourceGen/AppForms/EditProjectProperties.Designer.cs
index 37d9481..ce5b848 100644
--- a/SourceGen/AppForms/EditProjectProperties.Designer.cs
+++ b/SourceGen/AppForms/EditProjectProperties.Designer.cs
@@ -45,6 +45,9 @@ namespace SourceGen.AppForms {
"This is a test to gauge column widths"}, -1);
this.tabControl1 = new System.Windows.Forms.TabControl();
this.generalTab = new System.Windows.Forms.TabPage();
+ this.miscGroupBox = new System.Windows.Forms.GroupBox();
+ this.autoLabelStyleComboBox = new System.Windows.Forms.ComboBox();
+ this.autoLabelStyleLabel = new System.Windows.Forms.Label();
this.analysisGroupBox = new System.Windows.Forms.GroupBox();
this.seekAltTargetCheckBox = new System.Windows.Forms.CheckBox();
this.minStringCharsComboBox = new System.Windows.Forms.ComboBox();
@@ -86,6 +89,7 @@ namespace SourceGen.AppForms {
this.applyButton = new System.Windows.Forms.Button();
this.tabControl1.SuspendLayout();
this.generalTab.SuspendLayout();
+ this.miscGroupBox.SuspendLayout();
this.analysisGroupBox.SuspendLayout();
this.entryFlagsGroupBox.SuspendLayout();
this.cpuGroupBox.SuspendLayout();
@@ -112,6 +116,7 @@ namespace SourceGen.AppForms {
//
// generalTab
//
+ this.generalTab.Controls.Add(this.miscGroupBox);
this.generalTab.Controls.Add(this.analysisGroupBox);
this.generalTab.Controls.Add(this.entryFlagsGroupBox);
this.generalTab.Controls.Add(this.cpuGroupBox);
@@ -123,6 +128,40 @@ namespace SourceGen.AppForms {
this.generalTab.Text = "General";
this.generalTab.UseVisualStyleBackColor = true;
//
+ // miscGroupBox
+ //
+ this.miscGroupBox.Controls.Add(this.autoLabelStyleComboBox);
+ this.miscGroupBox.Controls.Add(this.autoLabelStyleLabel);
+ this.miscGroupBox.Location = new System.Drawing.Point(7, 177);
+ this.miscGroupBox.Name = "miscGroupBox";
+ this.miscGroupBox.Size = new System.Drawing.Size(422, 100);
+ this.miscGroupBox.TabIndex = 3;
+ this.miscGroupBox.TabStop = false;
+ this.miscGroupBox.Text = "Miscellaneous";
+ //
+ // autoLabelStyleComboBox
+ //
+ this.autoLabelStyleComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.autoLabelStyleComboBox.FormattingEnabled = true;
+ this.autoLabelStyleComboBox.Items.AddRange(new object[] {
+ "Simple (\"L1234\")",
+ "Annotated (\"W_1234\")",
+ "Fully Annotated (\"DWR_1234\")"});
+ this.autoLabelStyleComboBox.Location = new System.Drawing.Point(98, 19);
+ this.autoLabelStyleComboBox.Name = "autoLabelStyleComboBox";
+ this.autoLabelStyleComboBox.Size = new System.Drawing.Size(318, 21);
+ this.autoLabelStyleComboBox.TabIndex = 1;
+ this.autoLabelStyleComboBox.SelectedIndexChanged += new System.EventHandler(this.autoLabelStyleComboBox_SelectedIndexChanged);
+ //
+ // autoLabelStyleLabel
+ //
+ this.autoLabelStyleLabel.AutoSize = true;
+ this.autoLabelStyleLabel.Location = new System.Drawing.Point(6, 22);
+ this.autoLabelStyleLabel.Name = "autoLabelStyleLabel";
+ this.autoLabelStyleLabel.Size = new System.Drawing.Size(81, 13);
+ this.autoLabelStyleLabel.TabIndex = 0;
+ this.autoLabelStyleLabel.Text = "Auto-label style:";
+ //
// analysisGroupBox
//
this.analysisGroupBox.Controls.Add(this.seekAltTargetCheckBox);
@@ -568,6 +607,8 @@ namespace SourceGen.AppForms {
this.Load += new System.EventHandler(this.EditProperties_Load);
this.tabControl1.ResumeLayout(false);
this.generalTab.ResumeLayout(false);
+ this.miscGroupBox.ResumeLayout(false);
+ this.miscGroupBox.PerformLayout();
this.analysisGroupBox.ResumeLayout(false);
this.analysisGroupBox.PerformLayout();
this.entryFlagsGroupBox.ResumeLayout(false);
@@ -628,5 +669,8 @@ namespace SourceGen.AppForms {
private System.Windows.Forms.Label configuredScriptsLabel;
private System.Windows.Forms.Button importSymbolsButton;
private System.Windows.Forms.CheckBox seekAltTargetCheckBox;
+ private System.Windows.Forms.GroupBox miscGroupBox;
+ private System.Windows.Forms.ComboBox autoLabelStyleComboBox;
+ private System.Windows.Forms.Label autoLabelStyleLabel;
}
}
\ No newline at end of file
diff --git a/SourceGen/AppForms/EditProjectProperties.cs b/SourceGen/AppForms/EditProjectProperties.cs
index 0c16c79..0d355cf 100644
--- a/SourceGen/AppForms/EditProjectProperties.cs
+++ b/SourceGen/AppForms/EditProjectProperties.cs
@@ -112,6 +112,13 @@ namespace SourceGen.AppForms {
}
minStringCharsComboBox.SelectedIndex = selIndex;
+ selIndex = (int) mWorkProps.AutoLabelStyle;
+ if (selIndex < 0 || selIndex >= autoLabelStyleComboBox.Items.Count) {
+ Debug.Assert(false, "bad AutoLabelStyle " + mWorkProps.AutoLabelStyle);
+ selIndex = 0;
+ }
+ autoLabelStyleComboBox.SelectedIndex = selIndex;
+
LoadProjectSymbols();
LoadPlatformSymbolFiles();
LoadExtensionScriptNames();
@@ -245,6 +252,7 @@ namespace SourceGen.AppForms {
}
private void minStringCharsComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+ // ComboBox must be the value 0, then N+2 in each subsequent entry (3, 4, 5, ...).
int index = minStringCharsComboBox.SelectedIndex;
int newVal;
if (index == 0) {
@@ -260,6 +268,15 @@ namespace SourceGen.AppForms {
}
}
+ private void autoLabelStyleComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+ AutoLabel.Style newStyle = (AutoLabel.Style)autoLabelStyleComboBox.SelectedIndex;
+ if (newStyle != mWorkProps.AutoLabelStyle) {
+ mWorkProps.AutoLabelStyle = newStyle;
+ mDirty = true;
+ UpdateControls();
+ }
+ }
+
#endregion General
diff --git a/SourceGen/AppForms/FormatSplitAddress.cs b/SourceGen/AppForms/FormatSplitAddress.cs
index dc8feeb..b2a15f7 100644
--- a/SourceGen/AppForms/FormatSplitAddress.cs
+++ b/SourceGen/AppForms/FormatSplitAddress.cs
@@ -385,7 +385,7 @@ namespace SourceGen.AppForms {
// won't generate identical labels for different addresses, and we do
// want to generate a single label if more than one table entry refers
// to the same target.
- Symbol tmpSym = SymbolTable.GenerateUniqueForAddress(addr,
+ Symbol tmpSym = AutoLabel.GenerateUniqueForAddress(addr,
mProject.SymbolTable, "T");
// tmpSym was returned as an auto-label, make it a user label instead
tmpSym = new Symbol(tmpSym.Label, tmpSym.Value, Symbol.Source.User,
diff --git a/SourceGen/AppForms/ProjectView.cs b/SourceGen/AppForms/ProjectView.cs
index 3ddb606..dc04f04 100644
--- a/SourceGen/AppForms/ProjectView.cs
+++ b/SourceGen/AppForms/ProjectView.cs
@@ -1731,11 +1731,13 @@ namespace SourceGen.AppForms {
// Edit > Copy (Ctrl+C)
private void copyToolStripMenuItem_Click(object sender, EventArgs e) {
- const int AssemblerSource = 0;
- const int Disassembly = 1;
const bool addCsv = true;
- int format = AppSettings.Global.GetInt(AppSettings.CLIP_LINE_FORMAT, AssemblerSource);
+ EditAppSettings.ClipLineFormat format =
+ (EditAppSettings.ClipLineFormat) AppSettings.Global.GetEnum(
+ AppSettings.CLIP_LINE_FORMAT,
+ typeof(EditAppSettings.ClipLineFormat),
+ (int) EditAppSettings.ClipLineFormat.AssemblerSource);
StringBuilder fullText = new StringBuilder(codeListView.SelectedIndices.Count * 50);
StringBuilder csv = new StringBuilder(codeListView.SelectedIndices.Count * 40);
StringBuilder sb = new StringBuilder(100);
@@ -1743,7 +1745,7 @@ namespace SourceGen.AppForms {
int addrAdj = mProject.CpuDef.HasAddr16 ? 6 : 9;
int disAdj = 0;
int bytesWidth = 0;
- if (format == Disassembly) {
+ if (format == EditAppSettings.ClipLineFormat.Disassembly) {
// A limit of 8 gets us 4 bytes from dense display ("20edfd60") and 3 if spaces
// are included ("20 ed fd") with no excess. We want to increase it to 11 so
// we can always show 4 bytes.
@@ -1766,7 +1768,7 @@ namespace SourceGen.AppForms {
case DisplayList.Line.Type.EquDirective:
case DisplayList.Line.Type.RegWidthDirective:
case DisplayList.Line.Type.OrgDirective:
- if (format == Disassembly) {
+ if (format == EditAppSettings.ClipLineFormat.Disassembly) {
if (!string.IsNullOrEmpty(parts.Addr)) {
sb.Append(parts.Addr);
sb.Append(": ");
@@ -1791,7 +1793,7 @@ namespace SourceGen.AppForms {
sb.Append("\r\n");
break;
case DisplayList.Line.Type.LongComment:
- if (format == Disassembly) {
+ if (format == EditAppSettings.ClipLineFormat.Disassembly) {
TextUtil.AppendPaddedString(sb, string.Empty, disAdj);
}
sb.Append(parts.Comment);
diff --git a/SourceGen/AppSettings.cs b/SourceGen/AppSettings.cs
index 38f6c0e..7d46b78 100644
--- a/SourceGen/AppSettings.cs
+++ b/SourceGen/AppSettings.cs
@@ -243,6 +243,40 @@ namespace SourceGen {
Dirty = true;
}
+ ///
+ /// Retrieves an enumerated value setting.
+ ///
+ /// Setting name.
+ /// Enum type that the value is part of.
+ /// Setting default value.
+ /// The value found, or the default value if no setting with the specified
+ /// name exists, or the stored value is not a member of the specified enumerated
+ /// type.
+ public int GetEnum(string name, Type enumType, int defaultValue) {
+ if (!mSettings.TryGetValue(name, out string valueStr)) {
+ return defaultValue;
+ }
+ try {
+ object o = Enum.Parse(enumType, valueStr);
+ return (int)o;
+ } catch (ArgumentException ae) {
+ Debug.WriteLine("Failed to parse " + valueStr + " (enum " + enumType + "): " +
+ ae.Message);
+ return defaultValue;
+ }
+ }
+
+ ///
+ /// Sets an enumerated setting.
+ ///
+ /// Setting name.
+ /// Enum type.
+ /// Setting value (integer enum index).
+ public void SetEnum(string name, Type enumType, int value) {
+ mSettings[name] = Enum.GetName(enumType, value);
+ Dirty = true;
+ }
+
///
/// Retrieves a string setting. The default value will be returned if the key
/// is not found, or if the value is null.
diff --git a/SourceGen/AsmGen/AssemblerVersion.cs b/SourceGen/AsmGen/AssemblerVersion.cs
index f52a1ae..3102ffa 100644
--- a/SourceGen/AsmGen/AssemblerVersion.cs
+++ b/SourceGen/AsmGen/AssemblerVersion.cs
@@ -20,7 +20,7 @@ using System.Diagnostics;
namespace SourceGen.AsmGen {
public class AssemblerVersion {
///
- /// Version string reported by the assembler.
+ /// Version string reported by the assembler. Retained mostly for debugging.
///
public string VersionStr { get; private set; }
@@ -49,7 +49,7 @@ namespace SourceGen.AsmGen {
}
public override string ToString() {
- return "[" + VersionStr + "/" + Version + "]";
+ return "['" + VersionStr + "'/" + Version + "]";
}
}
diff --git a/SourceGen/AutoLabel.cs b/SourceGen/AutoLabel.cs
new file mode 100644
index 0000000..b3053b6
--- /dev/null
+++ b/SourceGen/AutoLabel.cs
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2019 faddenSoft
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+
+namespace SourceGen {
+ ///
+ /// Functions for generation of "auto" labels.
+ ///
+ public static class AutoLabel {
+ ///
+ /// Auto-label style enumeration. Values were chosen to map directly to a combo box.
+ ///
+ public enum Style {
+ Unknown = -1,
+ Simple = 0,
+ Annotated = 1,
+ FullyAnnotated = 2
+ }
+
+ ///
+ /// Generates a unique address symbol. Does not add the symbol to the table.
+ ///
+ /// This does not follow any Formatter rules -- labels are always entirely upper-case.
+ ///
+ /// Address that label will be applied to.
+ /// Symbol table, for uniqueness check.
+ /// Prefix to use; must start with a letter.
+ /// Newly-created, unique symbol.
+ public static Symbol GenerateUniqueForAddress(int addr, SymbolTable symbols,
+ string prefix) {
+ // $1234 == L1234, $05/1234 == L51234.
+ string label = prefix + addr.ToString("X4"); // always upper-case
+ if (symbols.TryGetValue(label, out Symbol unused)) {
+ const int MAX_RENAME = 999;
+ string baseLabel = label;
+ StringBuilder sb = new StringBuilder(baseLabel.Length + 8);
+ int index = -1;
+
+ do {
+ // This is expected to be unlikely and infrequent, so a simple linear
+ // probe for uniqueness is fine. Labels are based on the address, not
+ // the offset, so even without user-created labels there's still an
+ // opportunity for duplication.
+ index++;
+ sb.Clear();
+ sb.Append(baseLabel);
+ sb.Append('_');
+ sb.Append(index);
+ label = sb.ToString();
+ } while (index <= MAX_RENAME && symbols.TryGetValue(label, out unused));
+ if (index > MAX_RENAME) {
+ // I give up
+ throw new Exception("Too many identical symbols: " + label);
+ }
+ }
+ Symbol sym = new Symbol(label, addr, Symbol.Source.Auto,
+ Symbol.Type.LocalOrGlobalAddr);
+ return sym;
+ }
+
+ ///
+ /// Source reference type.
+ ///
+ /// The enum is in priority order, i.e. the lowest-valued item "wins" in situations
+ /// where only one value is used.
+ ///
+ [Flags]
+ private enum RefTypes {
+ None = 0,
+ SubCall = 1 << 0,
+ Branch = 1 << 1,
+ DataRef = 1 << 2,
+ Write = 1 << 3,
+ Read = 1 << 4,
+ }
+ private static readonly char[] TAGS = { 'S', 'B', 'D', 'W', 'R' };
+
+ ///
+ /// Generates an auto-label with a prefix string based on the XrefSet.
+ ///
+ /// Address that label will be applied to.
+ /// Symbol table, for uniqueness check.
+ /// Cross-references for this location.
+ /// Newly-created, unique symbol.
+ public static Symbol GenerateAnnotatedLabel(int addr, SymbolTable symbols,
+ XrefSet xset, Style style) {
+ Debug.Assert(xset != null);
+ Debug.Assert(style != Style.Simple);
+
+ RefTypes rtypes = RefTypes.None;
+ foreach (XrefSet.Xref xr in xset) {
+ switch (xr.Type) {
+ case XrefSet.XrefType.SubCallOp:
+ rtypes |= RefTypes.SubCall;
+ break;
+ case XrefSet.XrefType.BranchOp:
+ rtypes |= RefTypes.Branch;
+ break;
+ case XrefSet.XrefType.RefFromData:
+ rtypes |= RefTypes.DataRef;
+ break;
+ case XrefSet.XrefType.MemAccessOp:
+ switch (xr.AccType) {
+ case Asm65.OpDef.MemoryEffect.Read:
+ rtypes |= RefTypes.Read;
+ break;
+ case Asm65.OpDef.MemoryEffect.Write:
+ rtypes |= RefTypes.Write;
+ break;
+ case Asm65.OpDef.MemoryEffect.ReadModifyWrite:
+ rtypes |= RefTypes.Read;
+ rtypes |= RefTypes.Write;
+ break;
+ case Asm65.OpDef.MemoryEffect.None:
+ case Asm65.OpDef.MemoryEffect.Unknown:
+ break;
+ default:
+ Debug.Assert(false);
+ break;
+ }
+ break;
+ default:
+ Debug.Assert(false);
+ break;
+ }
+ }
+
+ if (rtypes == RefTypes.None) {
+ // unexpected
+ Debug.Assert(false);
+ return GenerateUniqueForAddress(addr, symbols, "X_");
+ }
+
+ StringBuilder sb = new StringBuilder(8);
+ for (int i = 0; i < TAGS.Length; i++) {
+ if (((int) rtypes & (1 << i)) != 0) {
+ sb.Append(TAGS[i]);
+
+ if (style == Style.Annotated) {
+ break;
+ }
+ }
+ }
+ sb.Append('_');
+ return GenerateUniqueForAddress(addr, symbols, sb.ToString());
+ }
+ }
+}
diff --git a/SourceGen/DataAnalysis.cs b/SourceGen/DataAnalysis.cs
index 6148151..5714ba6 100644
--- a/SourceGen/DataAnalysis.cs
+++ b/SourceGen/DataAnalysis.cs
@@ -311,7 +311,7 @@ namespace SourceGen {
// incorporates the address. It's possible through various means to end
// up with a user or platform label that matches an auto label, so we
// need to do some renaming in that case. Shouldn't happen often.
- Symbol sym = SymbolTable.GenerateUniqueForAddress(mAnattribs[targetOffset].Address,
+ Symbol sym = AutoLabel.GenerateUniqueForAddress(mAnattribs[targetOffset].Address,
mProject.SymbolTable, "L");
mAnattribs[targetOffset].Symbol = sym;
// This will throw if the symbol already exists. That is the desired
diff --git a/SourceGen/DisasmProject.cs b/SourceGen/DisasmProject.cs
index 338531f..69c9038 100644
--- a/SourceGen/DisasmProject.cs
+++ b/SourceGen/DisasmProject.cs
@@ -477,6 +477,13 @@ namespace SourceGen {
GenerateXrefs();
reanalysisTimer.EndTask("GenerateXrefs");
+ // replace simple auto-labels ("L1234") with annotated versions ("WR_1234")
+ if (ProjectProps.AutoLabelStyle != AutoLabel.Style.Simple) {
+ reanalysisTimer.StartTask("AnnotateAutoLabels");
+ AnnotateAutoLabels();
+ reanalysisTimer.EndTask("AnnotateAutoLabels");
+ }
+
reanalysisTimer.StartTask("GenerateActiveDefSymbolList");
// Generate the list of project/platform symbols that are being used. This forms
// the list of EQUates at the top of the file.
@@ -676,7 +683,7 @@ namespace SourceGen {
/// Call this after the code and data analysis passes have completed. This doesn't
/// interact with labels, so the ordering there doesn't matter.
///
- public void GeneratePlatformSymbolRefs() {
+ private void GeneratePlatformSymbolRefs() {
bool checkNearby = ProjectProps.AnalysisParams.SeekNearbyTargets;
for (int offset = 0; offset < mAnattribs.Length; ) {
@@ -738,7 +745,7 @@ namespace SourceGen {
///
/// Call this after the code and data analysis passes have completed.
///
- public void GenerateXrefs() {
+ private void GenerateXrefs() {
// Xref generation. There are two general categories of references:
// (1) Numeric reference. Comes from instructions (e.g. "LDA $1000" or "BRA $1000")
// and Numeric/Address data items.
@@ -901,6 +908,39 @@ namespace SourceGen {
return xset; // will be null if not found
}
+ ///
+ /// Replaces generic auto-labels with fancier versions generated from xrefs.
+ ///
+ private void AnnotateAutoLabels() {
+ AutoLabel.Style style = ProjectProps.AutoLabelStyle;
+ Debug.Assert(style != AutoLabel.Style.Simple);
+
+ for (int offset = 0; offset < mAnattribs.Length; offset++) {
+ Anattrib attr = mAnattribs[offset];
+ if (attr.Symbol != null && attr.Symbol.SymbolSource == Symbol.Source.Auto) {
+ XrefSet xset = GetXrefSet(offset);
+ if (xset == null) {
+ // Nothing useful to do here. This is unexpected, since auto-labels
+ // should only exist because something referenced the offset.
+ continue;
+ }
+ Symbol newSym =
+ AutoLabel.GenerateAnnotatedLabel(attr.Address, SymbolTable, xset, style);
+ if (!newSym.Equals(attr.Symbol)) {
+ //Debug.WriteLine("Replace " + attr.Symbol.Label + " with " +newSym.Label);
+
+ // Replace the symbol in Anattribs, update the symbol table, then
+ // call Refactor to update everything that referenced it.
+ Symbol oldSym = mAnattribs[offset].Symbol;
+ mAnattribs[offset].Symbol = newSym;
+ SymbolTable.Remove(oldSym);
+ SymbolTable.Add(newSym);
+ RefactorLabel(offset, oldSym.Label);
+ }
+ }
+ }
+ }
+
///
/// Generates the list of project/platform symbols that are being used. Any
/// DefSymbol with a non-empty Xrefs is included. Previous contents are cleared.
diff --git a/SourceGen/ProjectFile.cs b/SourceGen/ProjectFile.cs
index 9a77fa4..1968b87 100644
--- a/SourceGen/ProjectFile.cs
+++ b/SourceGen/ProjectFile.cs
@@ -185,6 +185,7 @@ namespace SourceGen {
public string CpuName { get; set; }
public bool IncludeUndocumentedInstr { get; set; }
public int EntryFlags { get; set; }
+ public string AutoLabelStyle { get; set; }
public SerAnalysisParameters AnalysisParams { get; set; }
public List PlatformSymbolFileIdentifiers { get; set; }
public List ExtensionScriptFileIdentifiers { get; set; }
@@ -195,6 +196,7 @@ namespace SourceGen {
CpuName = Asm65.CpuDef.GetCpuNameFromType(props.CpuType);
IncludeUndocumentedInstr = props.IncludeUndocumentedInstr;
EntryFlags = props.EntryFlags.AsInt;
+ AutoLabelStyle = props.AutoLabelStyle.ToString();
AnalysisParams = new SerAnalysisParameters(props.AnalysisParams);
// External file identifiers require no conversion.
@@ -461,6 +463,12 @@ namespace SourceGen {
proj.ProjectProps.CpuType = Asm65.CpuDef.GetCpuTypeFromName(spf.ProjectProps.CpuName);
proj.ProjectProps.IncludeUndocumentedInstr = spf.ProjectProps.IncludeUndocumentedInstr;
proj.ProjectProps.EntryFlags = Asm65.StatusFlags.FromInt(spf.ProjectProps.EntryFlags);
+ if (Enum.TryParse(spf.ProjectProps.AutoLabelStyle,
+ out AutoLabel.Style als)) {
+ proj.ProjectProps.AutoLabelStyle = als;
+ } else {
+ // unknown value, leave as default
+ }
proj.ProjectProps.AnalysisParams = new ProjectProperties.AnalysisParameters();
proj.ProjectProps.AnalysisParams.AnalyzeUncategorizedData =
spf.ProjectProps.AnalysisParams.AnalyzeUncategorizedData;
diff --git a/SourceGen/ProjectProperties.cs b/SourceGen/ProjectProperties.cs
index bfc276a..eaf6251 100644
--- a/SourceGen/ProjectProperties.cs
+++ b/SourceGen/ProjectProperties.cs
@@ -26,6 +26,12 @@ namespace SourceGen {
/// All fields are explicitly handled by the ProjectFile serializer.
///
public class ProjectProperties {
+ //
+ // NOTE:
+ // If you add or modify a member, make sure to update the copy constructor and
+ // add serialization code to ProjectFile.
+ //
+
///
/// Some parameters we feed to the analyzers.
///
@@ -61,6 +67,11 @@ namespace SourceGen {
///
public Asm65.StatusFlags EntryFlags { get; set; }
+ ///
+ /// Naming style for auto-generated labels.
+ ///
+ public AutoLabel.Style AutoLabelStyle { get; set; }
+
///
/// Configurable parameters for the analyzers.
///
@@ -101,6 +112,7 @@ namespace SourceGen {
CpuType = src.CpuType;
IncludeUndocumentedInstr = src.IncludeUndocumentedInstr;
EntryFlags = src.EntryFlags;
+ AutoLabelStyle = src.AutoLabelStyle;
AnalysisParams = new AnalysisParameters(src.AnalysisParams);
diff --git a/SourceGen/RuntimeData/Help/mainwin.html b/SourceGen/RuntimeData/Help/mainwin.html
index c5dd301..7006bed 100644
--- a/SourceGen/RuntimeData/Help/mainwin.html
+++ b/SourceGen/RuntimeData/Help/mainwin.html
@@ -227,9 +227,12 @@ data operand, and provides an indication of the nature of the reference:
data - address referenced by data (e.g. .DD2 addr)
In addition, the source will be identified as a symbolic ("Sym") or
-numeric ("Num") reference. Symbolic references may be offset from the
-actual operand value; if this is the case, the adjustment will be shown
-as well.
+numeric ("Num") reference. Most will be symbolic, because SourceGen
+generates symbols automatically. However, references to addresses that
+are offset from a symbol will also create a numeric reference entry.
+For example, "LDA addr+1" will create a symbolic reference at <addr>
+(shown in the table with an adjustment of "+1") and a numeric reference
+at <addr+1>.
Double-clicking on a reference moves the code list selection to that
reference, and adds the previous selection to the navigation stack.
diff --git a/SourceGen/SourceGen.csproj b/SourceGen/SourceGen.csproj
index 14090d1..79a0444 100644
--- a/SourceGen/SourceGen.csproj
+++ b/SourceGen/SourceGen.csproj
@@ -131,6 +131,7 @@
+
diff --git a/SourceGen/SymbolTable.cs b/SourceGen/SymbolTable.cs
index 1d4926f..a162fc9 100644
--- a/SourceGen/SymbolTable.cs
+++ b/SourceGen/SymbolTable.cs
@@ -211,42 +211,5 @@ namespace SourceGen {
mSymbolsByValue.Remove(sym);
ChangeSerial++;
}
-
- ///
- /// Generates a unique address symbol. Does not add the symbol to the list.
- ///
- /// Address that label will be applied to.
- /// Symbol table.
- /// Prefix to use; must start with a letter.
- /// Newly-created, unique symbol.
- public static Symbol GenerateUniqueForAddress(int addr, SymbolTable symbols,
- string prefix) {
- // $1234 == L1234, $05/1234 == L51234.
- string label = prefix + addr.ToString("X4"); // always upper-case
- if (symbols.TryGetValue(label, out Symbol unused)) {
- const int MAX_RENAME = 999;
- string baseLabel = label;
- StringBuilder sb = new StringBuilder(baseLabel.Length + 8);
- int index = -1;
-
- do {
- // This is expected to be unlikely and infrequent, so a simple linear
- // probe for uniqueness is fine.
- index++;
- sb.Clear();
- sb.Append(baseLabel);
- sb.Append('_');
- sb.Append(index);
- label = sb.ToString();
- } while (index <= MAX_RENAME && symbols.TryGetValue(label, out unused));
- if (index > MAX_RENAME) {
- // I give up
- throw new Exception("Too many identical symbols");
- }
- }
- Symbol sym = new Symbol(label, addr, Symbol.Source.Auto,
- Symbol.Type.LocalOrGlobalAddr);
- return sym;
- }
}
}
diff --git a/SourceGen/XrefSet.cs b/SourceGen/XrefSet.cs
index 3fa602e..c138767 100644
--- a/SourceGen/XrefSet.cs
+++ b/SourceGen/XrefSet.cs
@@ -28,9 +28,6 @@ namespace SourceGen {
public class XrefSet : IEnumerable {
///
/// Reference type. This is mostly useful for display to the user.
- ///
- /// The enum is in priority order, i.e. the lowest-valued
- /// item "wins" in situations where only one value is used.
///
public enum XrefType {
Unknown = 0,