1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-11-30 01:50:10 +00:00

Progress toward new assembler configuration

Use configured column widths when generating output.

The regression test always uses the assembler-preferred default
widths.
This commit is contained in:
Andy McFadden 2018-10-20 21:24:28 -07:00
parent 4f9af30455
commit 9aabd988a8
4 changed files with 70 additions and 33 deletions

View File

@ -58,6 +58,11 @@ namespace SourceGen.AsmGen {
/// </summary> /// </summary>
private bool mLongLabelNewLine; private bool mLongLabelNewLine;
/// <summary>
/// Output column widths.
/// </summary>
private int[] mColumnWidths;
/// <summary> /// <summary>
/// Base filename. Typically the project file name without the ".dis65" extension. /// Base filename. Typically the project file name without the ".dis65" extension.
/// </summary> /// </summary>
@ -145,6 +150,10 @@ namespace SourceGen.AsmGen {
Settings = settings; Settings = settings;
mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false); mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
AssemblerConfig config = AssemblerConfig.GetConfig(settings,
AssemblerInfo.Id.Cc65);
mColumnWidths = (int[])config.ColumnWidths.Clone();
} }
// IGenerator // IGenerator
@ -460,16 +469,17 @@ namespace SourceGen.AsmGen {
StringComparison.InvariantCultureIgnoreCase)) { StringComparison.InvariantCultureIgnoreCase)) {
label += ':'; label += ':';
if (mLongLabelNewLine && label.Length >= 9) { if (mLongLabelNewLine && label.Length >= mColumnWidths[0]) {
mOutStream.WriteLine(label); mOutStream.WriteLine(label);
label = string.Empty; label = string.Empty;
} }
} }
mLineBuilder.Clear(); mLineBuilder.Clear();
TextUtil.AppendPaddedString(mLineBuilder, label, 9); TextUtil.AppendPaddedString(mLineBuilder, label, mColumnWidths[0]);
TextUtil.AppendPaddedString(mLineBuilder, opcode, 9 + 8); TextUtil.AppendPaddedString(mLineBuilder, opcode, mColumnWidths[0] + mColumnWidths[1]);
TextUtil.AppendPaddedString(mLineBuilder, operand, 9 + 8 + 11); TextUtil.AppendPaddedString(mLineBuilder, operand,
mColumnWidths[0] + mColumnWidths[1] + mColumnWidths[2]);
if (string.IsNullOrEmpty(comment)) { if (string.IsNullOrEmpty(comment)) {
// Trim trailing spaces off of opcode or operand. If they want trailing // Trim trailing spaces off of opcode or operand. If they want trailing
// spaces at the end of a comment, that's fine. // spaces at the end of a comment, that's fine.
@ -657,9 +667,12 @@ namespace SourceGen.AsmGen {
/// Cross-assembler execution interface. /// Cross-assembler execution interface.
/// </summary> /// </summary>
public class AsmCc65 : IAssembler { public class AsmCc65 : IAssembler {
private List<string> PathNames { get; set; } // Paths from generator.
private List<string> mPathNames;
// Directory to make current before executing assembler.
private string mWorkDirectory;
private string WorkDirectory { get; set; }
// IAssembler // IAssembler
public void GetExeIdentifiers(out string humanName, out string exeName) { public void GetExeIdentifiers(out string humanName, out string exeName) {
@ -712,21 +725,21 @@ namespace SourceGen.AsmGen {
// IAssembler // IAssembler
public void Configure(List<string> pathNames, string workDirectory) { public void Configure(List<string> pathNames, string workDirectory) {
// Clone pathNames, in case the caller decides to modify the original. // Clone pathNames, in case the caller decides to modify the original.
PathNames = new List<string>(pathNames.Count); mPathNames = new List<string>(pathNames.Count);
foreach (string str in pathNames) { foreach (string str in pathNames) {
PathNames.Add(str); mPathNames.Add(str);
} }
WorkDirectory = workDirectory; mWorkDirectory = workDirectory;
} }
// IAssembler // IAssembler
public AssemblerResults RunAssembler(BackgroundWorker worker) { public AssemblerResults RunAssembler(BackgroundWorker worker) {
// Reduce input file to a partial path if possible. This is really just to make // Reduce input file to a partial path if possible. This is really just to make
// what we display to the user a little easier to read. // what we display to the user a little easier to read.
string pathName = PathNames[0]; string pathName = mPathNames[0];
if (pathName.StartsWith(WorkDirectory)) { if (pathName.StartsWith(mWorkDirectory)) {
pathName = pathName.Remove(0, WorkDirectory.Length + 1); pathName = pathName.Remove(0, mWorkDirectory.Length + 1);
} else { } else {
// Unexpected, but shouldn't be a problem. // Unexpected, but shouldn't be a problem.
Debug.WriteLine("NOTE: source file is not in work directory"); Debug.WriteLine("NOTE: source file is not in work directory");
@ -742,14 +755,14 @@ namespace SourceGen.AsmGen {
// Wrap pathname in quotes in case it has spaces. // Wrap pathname in quotes in case it has spaces.
// (Do we need to shell-escape quotes in the pathName?) // (Do we need to shell-escape quotes in the pathName?)
ShellCommand cmd = new ShellCommand(config.ExecutablePath, ShellCommand cmd = new ShellCommand(config.ExecutablePath,
"--target none \"" + pathName + "\"", WorkDirectory, null); "--target none \"" + pathName + "\"", mWorkDirectory, null);
cmd.Execute(); cmd.Execute();
// Can't really do anything with a "cancel" request. // Can't really do anything with a "cancel" request.
// Output filename is the input filename without the ".S". Since the filename // Output filename is the input filename without the ".S". Since the filename
// was generated by us we can be confident in the format. // was generated by us we can be confident in the format.
string outputFile = PathNames[0].Substring(0, PathNames[0].Length - 2); string outputFile = mPathNames[0].Substring(0, mPathNames[0].Length - 2);
return new AssemblerResults(cmd.FullCommandLine, cmd.ExitCode, cmd.Stdout, return new AssemblerResults(cmd.FullCommandLine, cmd.ExitCode, cmd.Stdout,
cmd.Stderr, outputFile); cmd.Stderr, outputFile);

View File

@ -59,6 +59,11 @@ namespace SourceGen.AsmGen {
/// </summary> /// </summary>
private bool mLongLabelNewLine; private bool mLongLabelNewLine;
/// <summary>
/// Output column widths.
/// </summary>
private int[] mColumnWidths;
/// <summary> /// <summary>
/// Base filename. Typically the project file name without the ".dis65" extension. /// Base filename. Typically the project file name without the ".dis65" extension.
/// </summary> /// </summary>
@ -134,6 +139,10 @@ namespace SourceGen.AsmGen {
Settings = settings; Settings = settings;
mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false); mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);
AssemblerConfig config = AssemblerConfig.GetConfig(settings,
AssemblerInfo.Id.Merlin32);
mColumnWidths = (int[])config.ColumnWidths.Clone();
} }
// IGenerator; executes on background thread // IGenerator; executes on background thread
@ -343,7 +352,7 @@ namespace SourceGen.AsmGen {
// IGenerator // IGenerator
public void OutputLine(string label, string opcode, string operand, string comment) { public void OutputLine(string label, string opcode, string operand, string comment) {
// Split long label, but not on EQU directives (confuses the assembler). // Split long label, but not on EQU directives (confuses the assembler).
if (mLongLabelNewLine && label.Length >= 9 && if (mLongLabelNewLine && label.Length >= mColumnWidths[0] &&
!String.Equals(opcode, sDataOpNames.EquDirective, !String.Equals(opcode, sDataOpNames.EquDirective,
StringComparison.InvariantCultureIgnoreCase)) { StringComparison.InvariantCultureIgnoreCase)) {
mOutStream.WriteLine(label); mOutStream.WriteLine(label);
@ -351,9 +360,10 @@ namespace SourceGen.AsmGen {
} }
mLineBuilder.Clear(); mLineBuilder.Clear();
TextUtil.AppendPaddedString(mLineBuilder, label, 9); TextUtil.AppendPaddedString(mLineBuilder, label, mColumnWidths[0]);
TextUtil.AppendPaddedString(mLineBuilder, opcode, 9 + 6); TextUtil.AppendPaddedString(mLineBuilder, opcode, mColumnWidths[0] + mColumnWidths[1]);
TextUtil.AppendPaddedString(mLineBuilder, operand, 9 + 6 + 11); TextUtil.AppendPaddedString(mLineBuilder, operand,
mColumnWidths[0] + mColumnWidths[1] + mColumnWidths[2]);
if (string.IsNullOrEmpty(comment)) { if (string.IsNullOrEmpty(comment)) {
// Trim trailing spaces off of opcode or operand. If they want trailing // Trim trailing spaces off of opcode or operand. If they want trailing
// spaces at the end of a comment, that's fine. // spaces at the end of a comment, that's fine.
@ -604,9 +614,11 @@ namespace SourceGen.AsmGen {
/// Cross-assembler execution interface. /// Cross-assembler execution interface.
/// </summary> /// </summary>
public class AsmMerlin32 : IAssembler { public class AsmMerlin32 : IAssembler {
private List<string> PathNames { get; set; } // Paths from generator.
private List<string> mPathNames;
private string WorkDirectory { get; set; } // Directory to make current before executing assembler.
private string mWorkDirectory;
// IAssembler // IAssembler
@ -659,21 +671,21 @@ namespace SourceGen.AsmGen {
// IAssembler // IAssembler
public void Configure(List<string> pathNames, string workDirectory) { public void Configure(List<string> pathNames, string workDirectory) {
// Clone pathNames, in case the caller decides to modify the original. // Clone pathNames, in case the caller decides to modify the original.
PathNames = new List<string>(pathNames.Count); mPathNames = new List<string>(pathNames.Count);
foreach (string str in pathNames) { foreach (string str in pathNames) {
PathNames.Add(str); mPathNames.Add(str);
} }
WorkDirectory = workDirectory; mWorkDirectory = workDirectory;
} }
// IAssembler // IAssembler
public AssemblerResults RunAssembler(BackgroundWorker worker) { public AssemblerResults RunAssembler(BackgroundWorker worker) {
// Reduce input file to a partial path if possible. This is really just to make // Reduce input file to a partial path if possible. This is really just to make
// what we display to the user a little easier to read. // what we display to the user a little easier to read.
string pathName = PathNames[0]; string pathName = mPathNames[0];
if (pathName.StartsWith(WorkDirectory)) { if (pathName.StartsWith(mWorkDirectory)) {
pathName = pathName.Remove(0, WorkDirectory.Length + 1); pathName = pathName.Remove(0, mWorkDirectory.Length + 1);
} else { } else {
// Unexpected, but shouldn't be a problem. // Unexpected, but shouldn't be a problem.
Debug.WriteLine("NOTE: source file is not in work directory"); Debug.WriteLine("NOTE: source file is not in work directory");
@ -689,14 +701,14 @@ namespace SourceGen.AsmGen {
// Wrap pathname in quotes in case it has spaces. // Wrap pathname in quotes in case it has spaces.
// (Do we need to shell-escape quotes in the pathName?) // (Do we need to shell-escape quotes in the pathName?)
ShellCommand cmd = new ShellCommand(config.ExecutablePath, ". \"" + pathName + "\"", ShellCommand cmd = new ShellCommand(config.ExecutablePath, ". \"" + pathName + "\"",
WorkDirectory, null); mWorkDirectory, null);
cmd.Execute(); cmd.Execute();
// Can't really do anything with a "cancel" request. // Can't really do anything with a "cancel" request.
// Output filename is the input filename without the ".S". Since the filename // Output filename is the input filename without the ".S". Since the filename
// was generated by us we can be confident in the format. // was generated by us we can be confident in the format.
string outputFile = PathNames[0].Substring(0, PathNames[0].Length - 2); string outputFile = mPathNames[0].Substring(0, mPathNames[0].Length - 2);
return new AssemblerResults(cmd.FullCommandLine, cmd.ExitCode, cmd.Stdout, return new AssemblerResults(cmd.FullCommandLine, cmd.ExitCode, cmd.Stdout,
cmd.Stderr, outputFile); cmd.Stderr, outputFile);

View File

@ -37,7 +37,8 @@ namespace SourceGen.AsmGen {
AssemblerConfig GetDefaultConfig(); AssemblerConfig GetDefaultConfig();
/// <summary> /// <summary>
/// Queries the assembler for its version. /// Queries the assembler for its version. Assembler executable paths are queried from
/// the global settings object.
/// </summary> /// </summary>
/// <returns>Assembler version info, or null if query failed.</returns> /// <returns>Assembler version info, or null if query failed.</returns>
AssemblerVersion QueryVersion(); AssemblerVersion QueryVersion();

View File

@ -387,10 +387,21 @@ namespace SourceGen.Tests {
// it for the localization test. // it for the localization test.
settings.SetBool(AppSettings.SRCGEN_DISABLE_LABEL_LOCALIZATION, true); settings.SetBool(AppSettings.SRCGEN_DISABLE_LABEL_LOCALIZATION, true);
// We will also want to define (or remove to get default behavior) any IEnumerator<AssemblerInfo> iter = AssemblerInfo.GetInfoEnumerator();
// assembler-specific stuff that affects generated output, like column widths. while (iter.MoveNext()) {
// We need to retain the assembler-specific configuration for things like AssemblerInfo.Id asmId = iter.Current.AssemblerId;
// where the assembler shell command lives. AssemblerConfig curConfig =
AssemblerConfig.GetConfig(settings, asmId);
AssemblerConfig defConfig =
AssemblerInfo.GetAssembler(asmId).GetDefaultConfig();
// Merge the two together. We want the default assembler config for most
// things, but the executable path from the current config.
defConfig.ExecutablePath = curConfig.ExecutablePath;
// Write it into the test settings.
AssemblerConfig.SetConfig(settings, asmId, defConfig);
}
return settings; return settings;
} }