Skip to content

Commit

Permalink
Add option to put labels on separate lines
Browse files Browse the repository at this point in the history
We currently have two options for assembly code output, selected by
a checkbox in the application settings: always put labels on the same
lines as the instruction or data operand, or split the labels onto
their own line if they were wider than the label text field.

This change adds a third option, which puts labels on their own line
whenever possible.  Assemblers don't generally allow this for variable
assignment pseudo-ops like "foo = $1000", but it's accepted for most
other situations.  This is a cosmetic change to the output, and will
not affect the generated code.

The old true/false app setting will be disregarded.  "Split if too
long" will be used by default.

Added test 20280-label-placement to exercise the "split whenever
allowed" behavior.

The "export" function has a similar option that has not been updated
(for no particular reason other than laziness).

Also, simplified the app settings GetEnum / SetEnum calls, which
can infer the enumerated type from the arguments.  This should not
impact behavior.
  • Loading branch information
fadden committed Apr 21, 2024
1 parent e425237 commit 4322a0c
Show file tree
Hide file tree
Showing 28 changed files with 506 additions and 101 deletions.
8 changes: 4 additions & 4 deletions CommonUtil/Misc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ public static void DumpNamespacesInAssembly(Type type) {
/// </summary>
/// <remarks>
/// Usage:
/// AppDomain.CurrentDomain.UnhandledException +=
/// new UnhandledExceptionEventHandler(CommonUtil.Misc.CrashReporter);
/// <code>AppDomain.CurrentDomain.UnhandledException +=
/// new UnhandledExceptionEventHandler(CommonUtil.Misc.CrashReporter);</code>
///
/// Thanks: https://stackoverflow.com/a/21308327/294248
/// Thanks: <see href="https://stackoverflow.com/a/21308327/294248"/>.
/// </remarks>
public static void CrashReporter(object sender, UnhandledExceptionEventArgs e) {
const string CRASH_PATH = @"CrashLog.txt";
Expand Down Expand Up @@ -80,7 +80,7 @@ public static void CrashReporter(object sender, UnhandledExceptionEventArgs e) {
/// faster than setting array elements individually.
/// </summary>
/// <remarks>
/// From https://stackoverflow.com/a/18659408/294248
/// From <see href="https://stackoverflow.com/a/18659408/294248"/>.
///
/// Invokes Array.Copy() on overlapping elements. Other approaches involve using
/// Buffer.BlockCopy or unsafe code. Apparently .NET Core has an Array.Fill(), but
Expand Down
31 changes: 18 additions & 13 deletions SourceGen/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public class AppSettings {
// Source generation settings.
public const string SRCGEN_DEFAULT_ASM = "srcgen-default-asm";
public const string SRCGEN_ADD_IDENT_COMMENT = "srcgen-add-ident-comment";
public const string SRCGEN_LONG_LABEL_NEW_LINE = "srcgen-long-label-new-line";
public const string SRCGEN_LABEL_NEW_LINE = "srcgen-label-new-line";
public const string SRCGEN_SHOW_CYCLE_COUNTS = "srcgen-show-cycle-counts";

// Label file generation settings.
Expand Down Expand Up @@ -291,21 +291,20 @@ public void SetBool(string name, bool value) {
/// <summary>
/// Retrieves an enumerated value setting.
/// </summary>
/// <typeparam name="T">Enumerated type.</typeparam>
/// <param name="name">Setting name.</param>
/// <param name="enumType">Enum type that the value is part of.</param>
/// <param name="defaultValue">Setting default value.</param>
/// <returns>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.</returns>
public int GetEnum(string name, Type enumType, int defaultValue) {
/// name exists, or the stored value is not a member of the enumeration.</returns>
public T GetEnum<T>(string name, T defaultValue) {
if (!mSettings.TryGetValue(name, out string valueStr)) {
return defaultValue;
}
try {
object o = Enum.Parse(enumType, valueStr);
return (int)o;
object o = Enum.Parse(typeof(T), valueStr);
return (T)o;
} catch (ArgumentException ae) {
Debug.WriteLine("Failed to parse " + valueStr + " (enum " + enumType + "): " +
Debug.WriteLine("Failed to parse '" + valueStr + "' (enum " + typeof(T) + "): " +
ae.Message);
return defaultValue;
}
Expand All @@ -314,14 +313,20 @@ public int GetEnum(string name, Type enumType, int defaultValue) {
/// <summary>
/// Sets an enumerated setting.
/// </summary>
/// <remarks>
/// The value is output to the settings file as a string, rather than an integer, allowing
/// the correct handling even if the enumerated values are renumbered.
/// </remarks>
/// <typeparam name="T">Enumerated type.</typeparam>
/// <param name="name">Setting name.</param>
/// <param name="enumType">Enum type.</param>
/// <param name="value">Setting value (integer enum index).</param>
public void SetEnum(string name, Type enumType, int value) {
string newVal = Enum.GetName(enumType, value);
public void SetEnum<T>(string name, T value) {
if (value == null) {
throw new NotImplementedException("Can't handle a null-valued enum type");
}
string newVal = Enum.GetName(typeof(T), value);
if (newVal == null) {
// Shouldn't be possible if an enum value of the correct type is passed in.
Debug.WriteLine("Unable to get enum name type=" + enumType + " value=" + value);
Debug.WriteLine("Unable to get enum name type=" + typeof(T) + " value=" + value);
return;
}
if (!mSettings.TryGetValue(name, out string oldValue) || oldValue != newVal) {
Expand Down
11 changes: 7 additions & 4 deletions SourceGen/AsmGen/AsmAcme.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ public class GenAcme : IGenerator {
private string mWorkDirectory;

/// <summary>
/// If set, long labels get their own line.
/// Influences whether labels are put on their own line.
/// </summary>
private bool mLongLabelNewLine;
private GenCommon.LabelPlacement mLabelNewLine;

/// <summary>
/// Output column widths.
Expand Down Expand Up @@ -198,7 +198,8 @@ public void Configure(DisasmProject project, string workDirectory, string fileNa
mFileNameBase = fileNameBase;
Settings = settings;

mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
GenCommon.LabelPlacement.SplitIfTooLong);

AssemblerConfig config = AssemblerConfig.GetConfig(settings,
AssemblerInfo.Id.Acme);
Expand Down Expand Up @@ -667,7 +668,9 @@ public void OutputLine(string label, string opcode, string operand, string comme
!string.Equals(opcode, sDataOpNames.EquDirective,
StringComparison.InvariantCultureIgnoreCase)) {

if (mLongLabelNewLine && label.Length >= mColumnWidths[0]) {
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
label.Length >= mColumnWidths[0])) {
mOutStream.WriteLine(label);
label = string.Empty;
}
Expand Down
11 changes: 7 additions & 4 deletions SourceGen/AsmGen/AsmCc65.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ public class GenCc65 : IGenerator {
private string mWorkDirectory;

/// <summary>
/// If set, long labels get their own line.
/// Influences whether labels are put on their own line.
/// </summary>
private bool mLongLabelNewLine;
private GenCommon.LabelPlacement mLabelNewLine;

/// <summary>
/// Output column widths.
Expand Down Expand Up @@ -188,7 +188,8 @@ public void Configure(DisasmProject project, string workDirectory, string fileNa
mFileNameBase = fileNameBase;
Settings = settings;

mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
GenCommon.LabelPlacement.SplitIfTooLong);

AssemblerConfig config = AssemblerConfig.GetConfig(settings,
AssemblerInfo.Id.Cc65);
Expand Down Expand Up @@ -659,7 +660,9 @@ public void OutputLine(string label, string opcode, string operand, string comme
StringComparison.InvariantCultureIgnoreCase)) {
label += ':';

if (mLongLabelNewLine && label.Length >= mColumnWidths[0]) {
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
label.Length >= mColumnWidths[0])) {
mOutStream.WriteLine(label);
label = string.Empty;
}
Expand Down
18 changes: 11 additions & 7 deletions SourceGen/AsmGen/AsmMerlin32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ public class GenMerlin32 : IGenerator {
private string mWorkDirectory;

/// <summary>
/// If set, long labels get their own line.
/// Influences whether labels are put on their own line.
/// </summary>
private bool mLongLabelNewLine;
private GenCommon.LabelPlacement mLabelNewLine;

/// <summary>
/// Output column widths.
Expand Down Expand Up @@ -174,7 +174,8 @@ public void Configure(DisasmProject project, string workDirectory, string fileNa
mFileNameBase = fileNameBase;
Settings = settings;

mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
GenCommon.LabelPlacement.SplitIfTooLong);

AssemblerConfig config = AssemblerConfig.GetConfig(settings,
AssemblerInfo.Id.Merlin32);
Expand Down Expand Up @@ -606,11 +607,14 @@ public void OutputLine(string fullLine) {
// IGenerator
public void OutputLine(string label, string opcode, string operand, string comment) {
// Split long label, but not on EQU directives (confuses the assembler).
if (mLongLabelNewLine && label.Length >= mColumnWidths[0] &&
!string.Equals(opcode, sDataOpNames.EquDirective,
if (!string.IsNullOrEmpty(label) && !string.Equals(opcode, sDataOpNames.EquDirective,
StringComparison.InvariantCultureIgnoreCase)) {
mOutStream.WriteLine(label);
label = string.Empty;
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
label.Length >= mColumnWidths[0])) {
mOutStream.WriteLine(label);
label = string.Empty;
}
}

mLineBuilder.Clear();
Expand Down
11 changes: 7 additions & 4 deletions SourceGen/AsmGen/AsmTass64.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ public int StartOffset {
private string mWorkDirectory;

/// <summary>
/// If set, long labels get their own line.
/// Influences whether labels are put on their own line.
/// </summary>
private bool mLongLabelNewLine;
private GenCommon.LabelPlacement mLabelNewLine;

/// <summary>
/// Output column widths.
Expand Down Expand Up @@ -201,7 +201,8 @@ public void Configure(DisasmProject project, string workDirectory, string fileNa
mFileNameBase = fileNameBase;
Settings = settings;

mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
mLabelNewLine = Settings.GetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
GenCommon.LabelPlacement.SplitIfTooLong);

AssemblerConfig config = AssemblerConfig.GetConfig(settings,
AssemblerInfo.Id.Tass64);
Expand Down Expand Up @@ -777,7 +778,9 @@ public void OutputLine(string label, string opcode, string operand, string comme
!string.Equals(opcode, sDataOpNames.VarDirective,
StringComparison.InvariantCultureIgnoreCase)) {

if (mLongLabelNewLine && label.Length >= mColumnWidths[0]) {
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
label.Length >= mColumnWidths[0])) {
mOutStream.WriteLine(label);
label = string.Empty;
}
Expand Down
12 changes: 10 additions & 2 deletions SourceGen/AsmGen/GenCommon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,19 @@
using CommonUtil;

namespace SourceGen.AsmGen {
/// <summary>
/// Code common to all assembly source generators.
/// </summary>
public class GenCommon {
public enum LabelPlacement {
Unknown = 0,
PreferSameLine,
SplitIfTooLong,
PreferSeparateLine,
}

/// <summary>
/// Generates assembly source.
///
/// This code is common to all generators.
/// </summary>
/// <param name="gen">Reference to generator object (presumably the caller).</param>
/// <param name="sw">Text output sink.</param>
Expand Down
6 changes: 2 additions & 4 deletions SourceGen/Exporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -550,10 +550,8 @@ private bool OutputToHtml(BackgroundWorker worker, string pathName, bool overwri
// but we're only doing this on the template file, which should be small.
tmplStr = tmplStr.Replace("$ProjectName$", mProject.DataFileName);
tmplStr = tmplStr.Replace("$AppVersion$", App.ProgramVersion.ToString());
string expModeStr = ((Formatter.FormatConfig.ExpressionMode)
AppSettings.Global.GetEnum(AppSettings.FMT_EXPRESSION_MODE,
typeof(Formatter.FormatConfig.ExpressionMode),
(int)Formatter.FormatConfig.ExpressionMode.Unknown)).ToString();
string expModeStr = AppSettings.Global.GetEnum(AppSettings.FMT_EXPRESSION_MODE,
Formatter.FormatConfig.ExpressionMode.Unknown).ToString();
tmplStr = tmplStr.Replace("$ExpressionStyle$", expModeStr);
string dateStr = DateTime.Now.ToString("yyyy/MM/dd");
string timeStr = DateTime.Now.ToString("HH:mm:ss zzz");
Expand Down
9 changes: 4 additions & 5 deletions SourceGen/MainController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,8 @@ private void LoadAppSettings() {
settings.SetString(AppSettings.FMT_OPERAND_PREFIX_LONG, "f:");

settings.SetBool(AppSettings.SRCGEN_ADD_IDENT_COMMENT, true);
settings.SetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, true);
settings.SetEnum(AppSettings.SRCGEN_LABEL_NEW_LINE,
AsmGen.GenCommon.LabelPlacement.SplitIfTooLong);

#if DEBUG
settings.SetBool(AppSettings.DEBUG_MENU_ENABLED, true);
Expand Down Expand Up @@ -1462,10 +1463,8 @@ public void CopyToClipboard() {
return;
}

ClipLineFormat format = (ClipLineFormat)AppSettings.Global.GetEnum(
AppSettings.CLIP_LINE_FORMAT,
typeof(ClipLineFormat),
(int)ClipLineFormat.AssemblerSource);
ClipLineFormat format = AppSettings.Global.GetEnum(AppSettings.CLIP_LINE_FORMAT,
ClipLineFormat.AssemblerSource);

int[] rightWidths = new int[] { 16, 6, 16, 80 };

Expand Down
Binary file added SourceGen/SGTestData/20280-label-placement
Binary file not shown.
Loading

0 comments on commit 4322a0c

Please sign in to comment.