diff --git a/Asm65/Formatter.cs b/Asm65/Formatter.cs index 8a0239f..7f3f863 100644 --- a/Asm65/Formatter.cs +++ b/Asm65/Formatter.cs @@ -23,24 +23,26 @@ using AddressMode = Asm65.OpDef.AddressMode; namespace Asm65 { /// <summary> /// Functions used for formatting bits of 65xx code into human-readable form. + /// </summary> + /// <remarks> + /// <para>There are a variety of ways to format a given thing, based on personal preference + /// (e.g. whether opcodes are upper- or lower-case) and assembler syntax requirements.</para> /// - /// There are a variety of ways to format a given thing, based on personal preference - /// (e.g. whether opcodes are upper- or lower-case) and assembler syntax requirements. - /// - /// The functions in this class serve two purposes: (1) produce consistent output + /// <para>The functions in this class serve two purposes: (1) produce consistent output /// throughout the program; (2) cache format strings and other components to reduce /// string manipulation overhead. Note the caching is per-Formatter, so it's best to - /// create just one and share it around. + /// create just one and share it around.</para> /// - /// The configuration of a Formatter may not be altered once created. This is important + /// <para>The configuration of a Formatter may not be altered once created. This is important /// in situations where we compute output size in one pass and generate it in another, /// because it guarantees that a given Formatter object will produce the same number of - /// lines of output. + /// lines of output.</para> /// - /// NOTE: if the CpuDef changes, the cached values in the Formatter will become invalid + /// <para>NOTE: if the CpuDef changes, the cached values in the Formatter will become invalid /// (e.g. mOpcodeStrings). Discard the Formatter and create a new one. (This could be - /// fixed by keying off of the OpDef instead of OpDef.Opcode, but that's less convenient.) - /// </summary> + /// fixed by keying off of the OpDef instead of OpDef.Opcode, but that's less + /// convenient.)</para> + /// </remarks> public class Formatter { // Default wrap point for long operands. This potentially affects both on-screen // display and source code generation. @@ -50,49 +52,82 @@ namespace Asm65 { /// Various format configuration options. Fill one of these out and pass it to /// the Formatter constructor. /// </summary> - public struct FormatConfig { - // alpha case for some case-insensitive items - public bool mUpperHexDigits; // display hex values in upper case? - public bool mUpperOpcodes; // display opcodes in upper case? - public bool mUpperPseudoOpcodes; // display pseudo-opcodes in upper case? - public bool mUpperOperandA; // display acc operand in upper case? - public bool mUpperOperandS; // display stack operand in upper case? - public bool mUpperOperandXY; // display index register operand in upper case? + public class FormatConfig { + // + // Cosmetic changes. + // - public bool mAddSpaceLongComment; // insert space after delimiter for long comments? + /// <summary>Display hex values in upper case?</summary> + public bool UpperHexDigits { get; set; } = false; + /// <summary>Display opcodes in upper case?</summary> + public bool UpperOpcodes { get; set; } = false; + /// <summary>Display pseudo-opcodes in upper case?</summary> + public bool UpperPseudoOpcodes { get; set; } = false; + /// <summary>Display acc operand in upper case?</summary> + public bool UpperOperandA { get; set; } = false; + /// <summary>Display stack operand in upper case?</summary> + public bool UpperOperandS { get; set; } = false; + /// <summary>Display index register operand in upper case?</summary> + public bool UpperOperandXY { get; set; } = false; - // functional changes to assembly output - public bool mSuppressHexNotation; // omit '$' before hex digits - public bool mSuppressImpliedAcc; // emit just "LSR" rather than "LSR A"? - public bool mBankSelectBackQuote; // use '`' rather than '^' for bank selector? + /// <summary>Insert space after delimiter for long comments?</summary> + public bool AddSpaceLongComment { get; set; } = false; - public string mForceDirectOperandPrefix; // these may be null or empty - public string mForceAbsOpcodeSuffix; - public string mForceAbsOperandPrefix; - public string mForceDirectOpcodeSuffix; - public string mForceLongOpcodeSuffix; - public string mForceLongOperandPrefix; + // + // Functional changes to assembly output. + // - public string mLocalVariableLabelPrefix; // e.g. Merlin 32 puts ']' before var names - public string mNonUniqueLabelPrefix; // e.g. ':' or '@' before local label + /// <summary>Omit '$' before hex digits?</summary> + public bool SuppressHexNotation { get; set; } = false; + /// <summary>Emit just "LSR" rather than "LSR A"?</summary> + public bool SuppressImpliedAcc { get; set; } = false; + /// <summary>Use '`' rather than '^' for bank selector?</summary> + public bool BankSelectBackQuote { get; set; } = false; - public string mEndOfLineCommentDelimiter; // usually ';' - public string mFullLineCommentDelimiterBase; // usually ';' or '*', WITHOUT extra space - public string mBoxLineCommentDelimiter; // usually blank or ';' + /// <summary>String to prefix operand with to force DP addressing.</summary> + public string ForceDirectOperandPrefix { get; set; } = string.Empty; + /// <summary>String to suffix opcode with to force abs addressing.</summary> + public string ForceAbsOpcodeSuffix { get; set; } = string.Empty; + /// <summary>String to prefix operand with to force abs addressing.</summary> + public string ForceAbsOperandPrefix { get; set; } = string.Empty; + /// <summary>String to suffix opcode with to force DP addressing.</summary> + public string ForceDirectOpcodeSuffix { get; set; } = string.Empty; + /// <summary>String to suffix opcode with to force long addressing.</summary> + public string ForceLongOpcodeSuffix { get; set; } = string.Empty; + /// <summary>String to prefix operand with to force long addressing.</summary> + public string ForceLongOperandPrefix { get; set; } = string.Empty; - // delimiter patterns for single character constants - public DelimiterSet mCharDelimiters; - public DelimiterSet mStringDelimiters; + /// <summary>String to prefix label with to indicate a local var.</summary> + public string LocalVariableLabelPrefix { get; set; } = string.Empty; + /// <summary>String to prefix label with to indicate a non-unique label.</summary> + public string NonUniqueLabelPrefix { get; set; } = string.Empty; - // point at which we wrap long operands; zero uses default - public int mOperandWrapLen; + /// <summary>String to prefix an end-of-line comment.</summary> + public string EndOfLineCommentDelimiter { get; set; } = string.Empty; + /// <summary>String to prefix a full-line comment.</summary> + public string FullLineCommentDelimiterBase { get; set; } = string.Empty; + /// <summary>String to prefix a box comment line.</summary> + public string BoxLineCommentDelimiter { get; set; } = string.Empty; - // miscellaneous - public bool mSpacesBetweenBytes; // "20edfd" vs. "20 ed fd" - public bool mCommaSeparatedDense; // "20edfd" vs. "$20,$ed,$fd" + /// <summary>Delimiter patterns for single-character constants.</summary> + public DelimiterSet CharDelimiters { get; set; } = new DelimiterSet(); + /// <summary>Delimiter patterns for string constants.</summary> + public DelimiterSet StringDelimiters { get; set; } = new DelimiterSet(); - // hex dumps - public bool mHexDumpAsciiOnly; // disallow non-ASCII chars in hex dumps? + // + // Miscellaneous. + // + + /// <summary>Character position at which operands wrap; 0 == default.</summary> + public int OperandWrapLen = DEFAULT_OPERAND_WRAP_LEN; + + /// <summary>Add spaces between bytes in the Bytes column?</summary> + public bool SpacesBetweenBytes { get; set; } = false; // "20edfd" vs. "20 ed fd" + /// <summary>Use comma-separated hex values for dense hex format?</summary> + public bool CommaSeparatedDense { get; set; } = false; // "20edfd" vs. "$20,$ed,$fd" + + /// <summary>Use only ASCII characters in hex dumps (e.g. no middle-dots)?</summary> + public bool HexDumpAsciiOnly { get; set; } = false; public enum CharConvMode { // TODO(maybe): just pass in a CharEncoding.Convert delegate Unknown = 0, @@ -101,12 +136,67 @@ namespace Asm65 { C64Petscii, C64ScreenCode }; - public CharConvMode mHexDumpCharConvMode; // character conversion mode for dumps + /// <summary>Character conversion mode for hex dumps.</summary> + public CharConvMode HexDumpCharConvMode = CharConvMode.Unknown; - // This determines what operators are available and what their precedence is. - // Hopefully we don't need a separate mode for every assembler in existence. public enum ExpressionMode { Unknown = 0, Common, Cc65, Merlin }; - public ExpressionMode mExpressionMode; // symbol rendering mode + /// <summary> + /// This determines what operators are available and what their precedence is. Used + /// when generating expressions for operands. + /// </summary> + public ExpressionMode ExprMode = ExpressionMode.Unknown; + + + /// <summary> + /// Constructor. All booleans default to false, all strings to empty. + /// </summary> + public FormatConfig() { } + + /// <summary> + /// Copy constructor. + /// </summary> + /// <param name="src">Source format config object.</param> + public FormatConfig(FormatConfig src) { + UpperHexDigits = src.UpperHexDigits; + UpperOpcodes = src.UpperOpcodes; + UpperPseudoOpcodes = src.UpperPseudoOpcodes; + UpperOperandA = src.UpperOperandA; + UpperOperandS = src.UpperOperandS; + UpperOperandXY = src.UpperOperandXY; + + AddSpaceLongComment = src.AddSpaceLongComment; + + SuppressHexNotation = src.SuppressHexNotation; + SuppressImpliedAcc = src.SuppressImpliedAcc; + BankSelectBackQuote = src.BankSelectBackQuote; + + ForceDirectOperandPrefix = src.ForceDirectOperandPrefix; + ForceAbsOpcodeSuffix = src.ForceAbsOpcodeSuffix; + ForceAbsOperandPrefix = src.ForceAbsOperandPrefix; + ForceDirectOpcodeSuffix = src.ForceDirectOpcodeSuffix; + ForceLongOpcodeSuffix = src.ForceLongOpcodeSuffix; + ForceLongOperandPrefix = src.ForceLongOperandPrefix; + + LocalVariableLabelPrefix = src.LocalVariableLabelPrefix; + NonUniqueLabelPrefix = src.NonUniqueLabelPrefix; + + EndOfLineCommentDelimiter = src.EndOfLineCommentDelimiter; + FullLineCommentDelimiterBase = src.FullLineCommentDelimiterBase; + BoxLineCommentDelimiter = src.BoxLineCommentDelimiter; + + CharDelimiters = new DelimiterSet(src.CharDelimiters); + StringDelimiters = new DelimiterSet(src.StringDelimiters); + + OperandWrapLen = src.OperandWrapLen; + + SpacesBetweenBytes = src.SpacesBetweenBytes; + CommaSeparatedDense = src.CommaSeparatedDense; + + HexDumpAsciiOnly = src.HexDumpAsciiOnly; + HexDumpCharConvMode = src.HexDumpCharConvMode; + + ExprMode = src.ExprMode; + } // Deserialization helper. public static ExpressionMode ParseExpressionMode(string str) { @@ -118,47 +208,6 @@ namespace Asm65 { } return em; } - - // TODO: FormatConfig should be a class with properties so we can avoid this nonsense - public void Normalize() { - if (mForceDirectOperandPrefix == null) { - mForceDirectOperandPrefix = string.Empty; - } - if (mForceAbsOpcodeSuffix == null) { - mForceAbsOpcodeSuffix = string.Empty; - } - if (mForceAbsOperandPrefix == null) { - mForceAbsOperandPrefix = string.Empty; - } - if (mForceDirectOpcodeSuffix == null) { - mForceDirectOpcodeSuffix = string.Empty; - } - if (mForceLongOpcodeSuffix == null) { - mForceLongOpcodeSuffix = string.Empty; - } - if (mForceLongOperandPrefix == null) { - mForceLongOperandPrefix = string.Empty; - } - if (mLocalVariableLabelPrefix == null) { - mLocalVariableLabelPrefix = string.Empty; - } - if (mNonUniqueLabelPrefix == null) { - mNonUniqueLabelPrefix = string.Empty; - } - if (mEndOfLineCommentDelimiter == null) { - mEndOfLineCommentDelimiter = string.Empty; - } - if (mFullLineCommentDelimiterBase == null) { - mFullLineCommentDelimiterBase = string.Empty; - } - if (mBoxLineCommentDelimiter == null) { - mBoxLineCommentDelimiter = string.Empty; - } - - if (mOperandWrapLen == 0) { - mOperandWrapLen = DEFAULT_OPERAND_WRAP_LEN; - } - } } #region Text Delimiters @@ -239,13 +288,34 @@ namespace Asm65 { private Dictionary<CharEncoding.Encoding, DelimiterDef> mDelimiters = new Dictionary<CharEncoding.Encoding, DelimiterDef>(); + /// <summary> + /// Constructor. Set is initially empty. + /// </summary> + public DelimiterSet() { } + + /// <summary> + /// Copy constructor. + /// </summary> + /// <param name="src">Source set.</param> + public DelimiterSet(DelimiterSet src) { + foreach (KeyValuePair<CharEncoding.Encoding, DelimiterDef> kvp in src.mDelimiters) { + mDelimiters[kvp.Key] = kvp.Value; + } + } + /// <summary> /// Returns the specified DelimiterDef, or null if not found. /// </summary> + /// <param name="enc">Delimiter encoding to retrieve.</param> public DelimiterDef Get(CharEncoding.Encoding enc) { mDelimiters.TryGetValue(enc, out DelimiterDef def); return def; } + /// <summary> + /// Sets the specified DelimiterDef. + /// </summary> + /// <param name="enc">Delimiter encoding to change.</param> + /// <param name="def">New delimiter definition.</param> public void Set(CharEncoding.Encoding enc, DelimiterDef def) { mDelimiters[enc] = def; } @@ -377,7 +447,6 @@ namespace Asm65 { public override int GetHashCode() { return mDelimiters.GetHashCode(); } - } #endregion Text Delimiters @@ -397,7 +466,7 @@ namespace Asm65 { /// <summary> /// Get a copy of the format config. /// </summary> - public FormatConfig Config { get { return mFormatConfig; } } + public FormatConfig Config { get { return new FormatConfig(mFormatConfig); } } // Cached bits and pieces. char mHexFmtChar; @@ -446,7 +515,7 @@ namespace Asm65 { /// </summary> public char[] HexDigits { get { - return mFormatConfig.mUpperHexDigits ? sHexCharsUpper : sHexCharsLower; + return mFormatConfig.UpperHexDigits ? sHexCharsUpper : sHexCharsLower; } } @@ -454,7 +523,7 @@ namespace Asm65 { /// String to put between the operand and the end-of-line comment. /// </summary> public string EndOfLineCommentDelimiter { - get { return mFormatConfig.mEndOfLineCommentDelimiter; } + get { return mFormatConfig.EndOfLineCommentDelimiter; } } /// <summary> @@ -470,14 +539,14 @@ namespace Asm65 { /// as a comment. /// </summary> public string BoxLineCommentDelimiter { - get { return mFormatConfig.mBoxLineCommentDelimiter; } + get { return mFormatConfig.BoxLineCommentDelimiter; } } /// <summary> /// Prefix for non-unique address labels. /// </summary> public string NonUniqueLabelPrefix { - get { return mFormatConfig.mNonUniqueLabelPrefix; } + get { return mFormatConfig.NonUniqueLabelPrefix; } } /// <summary> @@ -486,14 +555,14 @@ namespace Asm65 { /// assume the assembler shifts the operand before applying the adjustment. /// </summary> public FormatConfig.ExpressionMode ExpressionMode { - get { return mFormatConfig.mExpressionMode; } + get { return mFormatConfig.ExprMode; } } /// <summary> /// Point at which to wrap long operands, such as strings and dense hex. /// </summary> public int OperandWrapLen { - get { return mFormatConfig.mOperandWrapLen; } + get { return mFormatConfig.OperandWrapLen; } } @@ -502,18 +571,16 @@ namespace Asm65 { /// do as much work as possible here. /// </summary> public Formatter(FormatConfig config) { - mFormatConfig = config; // copy struct + mFormatConfig = new FormatConfig(config); // make a copy - mFormatConfig.Normalize(); - - if (string.IsNullOrEmpty(mFormatConfig.mNonUniqueLabelPrefix)) { - mFormatConfig.mNonUniqueLabelPrefix = "@"; + if (string.IsNullOrEmpty(mFormatConfig.NonUniqueLabelPrefix)) { + mFormatConfig.NonUniqueLabelPrefix = "@"; } - if (mFormatConfig.mAddSpaceLongComment) { - mFullLineCommentDelimiterPlus = mFormatConfig.mFullLineCommentDelimiterBase + " "; + if (mFormatConfig.AddSpaceLongComment) { + mFullLineCommentDelimiterPlus = mFormatConfig.FullLineCommentDelimiterBase + " "; } else { - mFullLineCommentDelimiterPlus = mFormatConfig.mFullLineCommentDelimiterBase; + mFullLineCommentDelimiterPlus = mFormatConfig.FullLineCommentDelimiterBase; } // Prep the static parts of the hex dump buffer. @@ -524,31 +591,31 @@ namespace Asm65 { mHexDumpBuffer[6] = ':'; // Resolve boolean flags to character or string values. - if (mFormatConfig.mUpperHexDigits) { + if (mFormatConfig.UpperHexDigits) { mHexFmtChar = 'X'; } else { mHexFmtChar = 'x'; } - if (mFormatConfig.mSuppressHexNotation) { + if (mFormatConfig.SuppressHexNotation) { mHexPrefix = ""; } else { mHexPrefix = "$"; } - if (mFormatConfig.mSuppressImpliedAcc) { + if (mFormatConfig.SuppressImpliedAcc) { mAccChar = ""; - } else if (mFormatConfig.mUpperOperandA) { + } else if (mFormatConfig.UpperOperandA) { mAccChar = "A"; } else { mAccChar = "a"; } - if (mFormatConfig.mUpperOperandXY) { + if (mFormatConfig.UpperOperandXY) { mXregChar = 'X'; mYregChar = 'Y'; } else { mXregChar = 'x'; mYregChar = 'y'; } - if (mFormatConfig.mUpperOperandS) { + if (mFormatConfig.UpperOperandS) { mSregChar = 'S'; } else { mSregChar = 's'; @@ -560,13 +627,13 @@ namespace Asm65 { } // process the delimiter patterns - DelimiterSet chrDelim = mFormatConfig.mCharDelimiters; + DelimiterSet chrDelim = mFormatConfig.CharDelimiters; if (chrDelim == null) { Debug.WriteLine("NOTE: char delimiters not set"); chrDelim = DelimiterSet.GetDefaultCharDelimiters(); } - switch (mFormatConfig.mHexDumpCharConvMode) { + switch (mFormatConfig.HexDumpCharConvMode) { case FormatConfig.CharConvMode.Ascii: mHexDumpCharConv = CharEncoding.ConvertAscii; break; @@ -676,7 +743,7 @@ namespace Asm65 { return FormatHexValue(value, 2); } - DelimiterDef delimDef = mFormatConfig.mCharDelimiters.Get(enc); + DelimiterDef delimDef = mFormatConfig.CharDelimiters.Get(enc); if (delimDef == null) { return FormatHexValue(value, 2); } @@ -738,8 +805,8 @@ namespace Asm65 { /// specified. /// </summary> public string FormatVariableLabel(string label) { - if (!string.IsNullOrEmpty(mFormatConfig.mLocalVariableLabelPrefix)) { - return mFormatConfig.mLocalVariableLabelPrefix + label; + if (!string.IsNullOrEmpty(mFormatConfig.LocalVariableLabelPrefix)) { + return mFormatConfig.LocalVariableLabelPrefix + label; } else { return label; } @@ -806,22 +873,22 @@ namespace Asm65 { public string FormatMnemonic(string mnemonic, OpDef.WidthDisambiguation wdis) { string opcodeStr = mnemonic; if (wdis == OpDef.WidthDisambiguation.ForceDirect) { - if (!string.IsNullOrEmpty(mFormatConfig.mForceDirectOpcodeSuffix)) { - opcodeStr += mFormatConfig.mForceDirectOpcodeSuffix; + if (!string.IsNullOrEmpty(mFormatConfig.ForceDirectOpcodeSuffix)) { + opcodeStr += mFormatConfig.ForceDirectOpcodeSuffix; } } else if (wdis == OpDef.WidthDisambiguation.ForceAbs) { - if (!string.IsNullOrEmpty(mFormatConfig.mForceAbsOpcodeSuffix)) { - opcodeStr += mFormatConfig.mForceAbsOpcodeSuffix; + if (!string.IsNullOrEmpty(mFormatConfig.ForceAbsOpcodeSuffix)) { + opcodeStr += mFormatConfig.ForceAbsOpcodeSuffix; } } else if (wdis == OpDef.WidthDisambiguation.ForceLong || wdis == OpDef.WidthDisambiguation.ForceLongMaybe) { - if (!string.IsNullOrEmpty(mFormatConfig.mForceLongOpcodeSuffix)) { - opcodeStr += mFormatConfig.mForceLongOpcodeSuffix; + if (!string.IsNullOrEmpty(mFormatConfig.ForceLongOpcodeSuffix)) { + opcodeStr += mFormatConfig.ForceLongOpcodeSuffix; } } else { Debug.Assert(wdis == OpDef.WidthDisambiguation.None); } - if (mFormatConfig.mUpperOpcodes) { + if (mFormatConfig.UpperOpcodes) { opcodeStr = opcodeStr.ToUpperInvariant(); } return opcodeStr; @@ -839,16 +906,16 @@ namespace Asm65 { string wdisStr = string.Empty; if (wdis == OpDef.WidthDisambiguation.ForceDirect) { - if (!string.IsNullOrEmpty(mFormatConfig.mForceDirectOperandPrefix)) { - wdisStr = mFormatConfig.mForceDirectOperandPrefix; + if (!string.IsNullOrEmpty(mFormatConfig.ForceDirectOperandPrefix)) { + wdisStr = mFormatConfig.ForceDirectOperandPrefix; } } else if (wdis == OpDef.WidthDisambiguation.ForceAbs) { - if (!string.IsNullOrEmpty(mFormatConfig.mForceAbsOperandPrefix)) { - wdisStr = mFormatConfig.mForceAbsOperandPrefix; + if (!string.IsNullOrEmpty(mFormatConfig.ForceAbsOperandPrefix)) { + wdisStr = mFormatConfig.ForceAbsOperandPrefix; } } else if (wdis == OpDef.WidthDisambiguation.ForceLong) { - if (!string.IsNullOrEmpty(mFormatConfig.mForceLongOperandPrefix)) { - wdisStr = mFormatConfig.mForceLongOperandPrefix; + if (!string.IsNullOrEmpty(mFormatConfig.ForceLongOperandPrefix)) { + wdisStr = mFormatConfig.ForceLongOperandPrefix; } } else if (wdis == OpDef.WidthDisambiguation.ForceLongMaybe) { // Don't add a width disambiguator to an operand that is unambiguously long. @@ -957,7 +1024,7 @@ namespace Asm65 { /// <returns>Formatted string.</returns> public string FormatPseudoOp(string opstr) { if (!mPseudoOpStrings.TryGetValue(opstr, out string result)) { - if (mFormatConfig.mUpperPseudoOpcodes) { + if (mFormatConfig.UpperPseudoOpcodes) { result = mPseudoOpStrings[opstr] = opstr.ToUpperInvariant(); } else { result = mPseudoOpStrings[opstr] = opstr; @@ -975,7 +1042,7 @@ namespace Asm65 { StringBuilder sb = new StringBuilder(len * 7); for (int i = 0; i < len; i++) { - if (i != 0 && mFormatConfig.mSpacesBetweenBytes) { + if (i != 0 && mFormatConfig.SpacesBetweenBytes) { sb.Append(' '); } // e.g. "{0:x2}" @@ -1037,10 +1104,10 @@ namespace Asm65 { /// <returns>Formatted string.</returns> public string FormatEolComment(string comment) { if (string.IsNullOrEmpty(comment) || - string.IsNullOrEmpty(mFormatConfig.mEndOfLineCommentDelimiter)) { + string.IsNullOrEmpty(mFormatConfig.EndOfLineCommentDelimiter)) { return comment; } else { - return mFormatConfig.mEndOfLineCommentDelimiter + comment; + return mFormatConfig.EndOfLineCommentDelimiter + comment; } } @@ -1052,9 +1119,9 @@ namespace Asm65 { /// <param name="length">Number of bytes to print.</param> /// <returns>Formatted data string.</returns> public string FormatDenseHex(byte[] data, int offset, int length) { - char[] hexChars = mFormatConfig.mUpperHexDigits ? sHexCharsUpper : sHexCharsLower; + char[] hexChars = mFormatConfig.UpperHexDigits ? sHexCharsUpper : sHexCharsLower; char[] text; - if (mFormatConfig.mCommaSeparatedDense) { + if (mFormatConfig.CommaSeparatedDense) { text = new char[length * 4 - 1]; for (int i = 0; i < length; i++) { byte val = data[offset + i]; @@ -1086,7 +1153,7 @@ namespace Asm65 { /// </remarks> public int CharsPerDenseByte { get { - if (mFormatConfig.mCommaSeparatedDense) { + if (mFormatConfig.CommaSeparatedDense) { return 4; } else { return 2; @@ -1145,7 +1212,7 @@ namespace Asm65 { const int dataCol = 8; const int asciiCol = 57; - char[] hexChars = mFormatConfig.mUpperHexDigits ? sHexCharsUpper : sHexCharsLower; + char[] hexChars = mFormatConfig.UpperHexDigits ? sHexCharsUpper : sHexCharsLower; char[] outBuf = mHexDumpBuffer; int skip = addr & 0x0f; // we skip this many entries... @@ -1192,7 +1259,7 @@ namespace Asm65 { char ch = mHexDumpCharConv(val); if (ch != CharEncoding.UNPRINTABLE_CHAR) { return ch; - } else if (mFormatConfig.mHexDumpAsciiOnly) { + } else if (mFormatConfig.HexDumpAsciiOnly) { return '.'; } else { // Certain values make the hex dump ListView freak out in WinForms, but work diff --git a/SourceGen/AsmGen/AsmAcme.cs b/SourceGen/AsmGen/AsmAcme.cs index 7ac2fb1..04fa5a1 100644 --- a/SourceGen/AsmGen/AsmAcme.cs +++ b/SourceGen/AsmGen/AsmAcme.cs @@ -230,28 +230,28 @@ namespace SourceGen.AsmGen { /// Configures the assembler-specific format items. /// </summary> private void SetFormatConfigValues(ref Formatter.FormatConfig config) { - config.mSuppressImpliedAcc = true; + config.SuppressImpliedAcc = true; - config.mOperandWrapLen = 64; - config.mForceDirectOpcodeSuffix = "+1"; - config.mForceAbsOpcodeSuffix = "+2"; - config.mForceLongOpcodeSuffix = "+3"; - config.mForceDirectOperandPrefix = string.Empty; - config.mForceAbsOperandPrefix = string.Empty; - config.mForceLongOperandPrefix = string.Empty; - config.mLocalVariableLabelPrefix = "."; - config.mEndOfLineCommentDelimiter = ";"; - config.mFullLineCommentDelimiterBase = ";"; - config.mBoxLineCommentDelimiter = ";"; - config.mNonUniqueLabelPrefix = "@"; - config.mCommaSeparatedDense = false; - config.mExpressionMode = Formatter.FormatConfig.ExpressionMode.Common; + config.OperandWrapLen = 64; + config.ForceDirectOpcodeSuffix = "+1"; + config.ForceAbsOpcodeSuffix = "+2"; + config.ForceLongOpcodeSuffix = "+3"; + config.ForceDirectOperandPrefix = string.Empty; + config.ForceAbsOperandPrefix = string.Empty; + config.ForceLongOperandPrefix = string.Empty; + config.LocalVariableLabelPrefix = "."; + config.EndOfLineCommentDelimiter = ";"; + config.FullLineCommentDelimiterBase = ";"; + config.BoxLineCommentDelimiter = ";"; + config.NonUniqueLabelPrefix = "@"; + config.CommaSeparatedDense = false; + config.ExprMode = Formatter.FormatConfig.ExpressionMode.Common; Formatter.DelimiterSet charSet = new Formatter.DelimiterSet(); charSet.Set(CharEncoding.Encoding.Ascii, Formatter.SINGLE_QUOTE_DELIM); charSet.Set(CharEncoding.Encoding.HighAscii, new Formatter.DelimiterDef(string.Empty, '\'', '\'', " | $80")); - config.mCharDelimiters = charSet; + config.CharDelimiters = charSet; } // IGenerator diff --git a/SourceGen/AsmGen/AsmCc65.cs b/SourceGen/AsmGen/AsmCc65.cs index 1b6e309..4dd1607 100644 --- a/SourceGen/AsmGen/AsmCc65.cs +++ b/SourceGen/AsmGen/AsmCc65.cs @@ -207,25 +207,25 @@ namespace SourceGen.AsmGen { /// Configures the assembler-specific format items. /// </summary> private void SetFormatConfigValues(ref Formatter.FormatConfig config) { - config.mOperandWrapLen = 64; - config.mForceDirectOpcodeSuffix = string.Empty; - config.mForceAbsOpcodeSuffix = string.Empty; - config.mForceLongOpcodeSuffix = string.Empty; - config.mForceDirectOperandPrefix = "z:"; // zero - config.mForceAbsOperandPrefix = "a:"; // absolute - config.mForceLongOperandPrefix = "f:"; // far - config.mEndOfLineCommentDelimiter = ";"; - config.mFullLineCommentDelimiterBase = ";"; - config.mBoxLineCommentDelimiter = ";"; - config.mNonUniqueLabelPrefix = "@"; - config.mCommaSeparatedDense = true; - config.mExpressionMode = Formatter.FormatConfig.ExpressionMode.Cc65; + config.OperandWrapLen = 64; + config.ForceDirectOpcodeSuffix = string.Empty; + config.ForceAbsOpcodeSuffix = string.Empty; + config.ForceLongOpcodeSuffix = string.Empty; + config.ForceDirectOperandPrefix = "z:"; // zero + config.ForceAbsOperandPrefix = "a:"; // absolute + config.ForceLongOperandPrefix = "f:"; // far + config.EndOfLineCommentDelimiter = ";"; + config.FullLineCommentDelimiterBase = ";"; + config.BoxLineCommentDelimiter = ";"; + config.NonUniqueLabelPrefix = "@"; + config.CommaSeparatedDense = true; + config.ExprMode = Formatter.FormatConfig.ExpressionMode.Cc65; Formatter.DelimiterSet charSet = new Formatter.DelimiterSet(); charSet.Set(CharEncoding.Encoding.Ascii, Formatter.SINGLE_QUOTE_DELIM); charSet.Set(CharEncoding.Encoding.HighAscii, new Formatter.DelimiterDef(string.Empty, '\'', '\'', " | $80")); - config.mCharDelimiters = charSet; + config.CharDelimiters = charSet; } // IGenerator diff --git a/SourceGen/AsmGen/AsmMerlin32.cs b/SourceGen/AsmGen/AsmMerlin32.cs index 098368a..e1bcd83 100644 --- a/SourceGen/AsmGen/AsmMerlin32.cs +++ b/SourceGen/AsmGen/AsmMerlin32.cs @@ -192,25 +192,25 @@ namespace SourceGen.AsmGen { /// Configures the assembler-specific format items. /// </summary> private void SetFormatConfigValues(ref Formatter.FormatConfig config) { - config.mOperandWrapLen = 64; - config.mForceDirectOpcodeSuffix = string.Empty; - config.mForceAbsOpcodeSuffix = ":"; - config.mForceLongOpcodeSuffix = "l"; - config.mForceDirectOperandPrefix = string.Empty; - config.mForceAbsOperandPrefix = string.Empty; - config.mForceLongOperandPrefix = string.Empty; - config.mLocalVariableLabelPrefix = "]"; - config.mEndOfLineCommentDelimiter = ";"; - config.mFullLineCommentDelimiterBase = ";"; - config.mBoxLineCommentDelimiter = string.Empty; - config.mNonUniqueLabelPrefix = ":"; - config.mCommaSeparatedDense = false; - config.mExpressionMode = Formatter.FormatConfig.ExpressionMode.Merlin; + config.OperandWrapLen = 64; + config.ForceDirectOpcodeSuffix = string.Empty; + config.ForceAbsOpcodeSuffix = ":"; + config.ForceLongOpcodeSuffix = "l"; + config.ForceDirectOperandPrefix = string.Empty; + config.ForceAbsOperandPrefix = string.Empty; + config.ForceLongOperandPrefix = string.Empty; + config.LocalVariableLabelPrefix = "]"; + config.EndOfLineCommentDelimiter = ";"; + config.FullLineCommentDelimiterBase = ";"; + config.BoxLineCommentDelimiter = string.Empty; + config.NonUniqueLabelPrefix = ":"; + config.CommaSeparatedDense = false; + config.ExprMode = Formatter.FormatConfig.ExpressionMode.Merlin; Formatter.DelimiterSet charSet = new Formatter.DelimiterSet(); charSet.Set(CharEncoding.Encoding.Ascii, Formatter.SINGLE_QUOTE_DELIM); charSet.Set(CharEncoding.Encoding.HighAscii, Formatter.DOUBLE_QUOTE_DELIM); - config.mCharDelimiters = charSet; + config.CharDelimiters = charSet; } // IGenerator; executes on background thread diff --git a/SourceGen/AsmGen/AsmTass64.cs b/SourceGen/AsmGen/AsmTass64.cs index 2dffa52..6eca46e 100644 --- a/SourceGen/AsmGen/AsmTass64.cs +++ b/SourceGen/AsmGen/AsmTass64.cs @@ -253,27 +253,27 @@ namespace SourceGen.AsmGen { /// </summary> private void SetFormatConfigValues(ref Formatter.FormatConfig config) { // Must be lower case when --case-sensitive is used. - config.mUpperOpcodes = false; - config.mUpperPseudoOpcodes = false; - config.mUpperOperandA = false; - config.mUpperOperandS = false; - config.mUpperOperandXY = false; - config.mOperandWrapLen = 64; + config.UpperOpcodes = false; + config.UpperPseudoOpcodes = false; + config.UpperOperandA = false; + config.UpperOperandS = false; + config.UpperOperandXY = false; + config.OperandWrapLen = 64; - config.mBankSelectBackQuote = true; + config.BankSelectBackQuote = true; - config.mForceDirectOpcodeSuffix = string.Empty; - config.mForceAbsOpcodeSuffix = string.Empty; - config.mForceLongOpcodeSuffix = string.Empty; - config.mForceDirectOperandPrefix = string.Empty; - config.mForceAbsOperandPrefix = "@w"; // word - config.mForceLongOperandPrefix = "@l"; // long - config.mEndOfLineCommentDelimiter = ";"; - config.mFullLineCommentDelimiterBase = ";"; - config.mBoxLineCommentDelimiter = ";"; - config.mNonUniqueLabelPrefix = ""; // should be '_', but that's a valid label char - config.mCommaSeparatedDense = true; - config.mExpressionMode = Formatter.FormatConfig.ExpressionMode.Common; + config.ForceDirectOpcodeSuffix = string.Empty; + config.ForceAbsOpcodeSuffix = string.Empty; + config.ForceLongOpcodeSuffix = string.Empty; + config.ForceDirectOperandPrefix = string.Empty; + config.ForceAbsOperandPrefix = "@w"; // word + config.ForceLongOperandPrefix = "@l"; // long + config.EndOfLineCommentDelimiter = ";"; + config.FullLineCommentDelimiterBase = ";"; + config.BoxLineCommentDelimiter = ";"; + config.NonUniqueLabelPrefix = ""; // should be '_', but that's a valid label char + config.CommaSeparatedDense = true; + config.ExprMode = Formatter.FormatConfig.ExpressionMode.Common; } // IGenerator @@ -296,7 +296,7 @@ namespace SourceGen.AsmGen { charDelimSet.Set(CharEncoding.Encoding.HighAscii, new Formatter.DelimiterDef(string.Empty, '\'', '\'', " | $80")); - config.mCharDelimiters = charDelimSet; + config.CharDelimiters = charDelimSet; SourceFormatter = new Formatter(config); diff --git a/SourceGen/AsmGen/GenCommon.cs b/SourceGen/AsmGen/GenCommon.cs index 10f1abb..ed4c7bd 100644 --- a/SourceGen/AsmGen/GenCommon.cs +++ b/SourceGen/AsmGen/GenCommon.cs @@ -295,7 +295,7 @@ namespace SourceGen.AsmGen { } if (gen.Quirks.BankZeroAbsPBRRestrict) { // Hack to avoid having to define a new FormatConfig.ExpressionMode for 64tass. - // Get rid of this 64tass gets its own exp mode. + // Get rid of this if 64tass gets its own exp mode. opFlags |= PseudoOp.FormatNumericOpFlags.Is64Tass; } @@ -494,36 +494,36 @@ namespace SourceGen.AsmGen { /// <param name="config">Format config struct.</param> public static void ConfigureFormatterFromSettings(AppSettings settings, ref Formatter.FormatConfig config) { - config.mUpperHexDigits = + config.UpperHexDigits = settings.GetBool(AppSettings.FMT_UPPER_HEX_DIGITS, false); - config.mUpperOpcodes = + config.UpperOpcodes = settings.GetBool(AppSettings.FMT_UPPER_OP_MNEMONIC, false); - config.mUpperPseudoOpcodes = + config.UpperPseudoOpcodes = settings.GetBool(AppSettings.FMT_UPPER_PSEUDO_OP_MNEMONIC, false); - config.mUpperOperandA = + config.UpperOperandA = settings.GetBool(AppSettings.FMT_UPPER_OPERAND_A, false); - config.mUpperOperandS = + config.UpperOperandS = settings.GetBool(AppSettings.FMT_UPPER_OPERAND_S, false); - config.mUpperOperandXY = + config.UpperOperandXY = settings.GetBool(AppSettings.FMT_UPPER_OPERAND_XY, false); - config.mSpacesBetweenBytes = + config.SpacesBetweenBytes = settings.GetBool(AppSettings.FMT_SPACES_BETWEEN_BYTES, false); - config.mAddSpaceLongComment = + config.AddSpaceLongComment = settings.GetBool(AppSettings.FMT_ADD_SPACE_FULL_COMMENT, true); - config.mOperandWrapLen = + config.OperandWrapLen = settings.GetInt(AppSettings.FMT_OPERAND_WRAP_LEN, 0); - config.mForceAbsOpcodeSuffix = + config.ForceAbsOpcodeSuffix = settings.GetString(AppSettings.FMT_OPCODE_SUFFIX_ABS, string.Empty); - config.mForceLongOpcodeSuffix = + config.ForceLongOpcodeSuffix = settings.GetString(AppSettings.FMT_OPCODE_SUFFIX_LONG, string.Empty); - config.mForceAbsOperandPrefix = + config.ForceAbsOperandPrefix = settings.GetString(AppSettings.FMT_OPERAND_PREFIX_ABS, string.Empty); - config.mForceLongOperandPrefix = + config.ForceLongOperandPrefix = settings.GetString(AppSettings.FMT_OPERAND_PREFIX_LONG, string.Empty); string exprMode = settings.GetString(AppSettings.FMT_EXPRESSION_MODE, string.Empty); - config.mExpressionMode = Formatter.FormatConfig.ParseExpressionMode(exprMode); + config.ExprMode = Formatter.FormatConfig.ParseExpressionMode(exprMode); // Not doing the delimiter patterns here, because what's in the config file is // intended for on-screen display, and hence likely to be unsuited for an assembler. diff --git a/SourceGen/Exporter.cs b/SourceGen/Exporter.cs index 4f978df..bff2d51 100644 --- a/SourceGen/Exporter.cs +++ b/SourceGen/Exporter.cs @@ -159,7 +159,7 @@ namespace SourceGen { // 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. Add one for a trailing "+". - width = mFormatter.Config.mSpacesBetweenBytes ? 12 : 9; + width = mFormatter.Config.SpacesBetweenBytes ? 12 : 9; total = mColStart[(int)Col.Bytes + 1] = total + width + 1; } else { mColStart[(int)Col.Bytes + 1] = total; @@ -232,14 +232,14 @@ namespace SourceGen { StringBuilder sb = new StringBuilder(mParameterStringBase); sb.Append(";byteSpc="); - sb.Append(mFormatter.Config.mSpacesBetweenBytes.ToString()); + sb.Append(mFormatter.Config.SpacesBetweenBytes.ToString()); sb.Append(";commaBulk="); - sb.Append(mFormatter.Config.mCommaSeparatedDense.ToString()); + sb.Append(mFormatter.Config.CommaSeparatedDense.ToString()); sb.Append(";nonuPfx='"); - sb.Append(mFormatter.Config.mNonUniqueLabelPrefix); + sb.Append(mFormatter.Config.NonUniqueLabelPrefix); sb.Append('\''); sb.Append(";varPfx='"); - sb.Append(mFormatter.Config.mLocalVariableLabelPrefix); + sb.Append(mFormatter.Config.LocalVariableLabelPrefix); sb.Append('\''); sb.Append(";labelBrk="); sb.Append(LongLabelNewLine.ToString()); @@ -248,7 +248,7 @@ namespace SourceGen { sb.Append(";gfx="); sb.Append(GenerateImageFiles.ToString()); sb.Append(";opWrap="); - sb.Append(mFormatter.Config.mOperandWrapLen); + sb.Append(mFormatter.Config.OperandWrapLen); // Not included: pseudo-op definitions; delimiter definitions diff --git a/SourceGen/LineListGen.cs b/SourceGen/LineListGen.cs index 6dd92aa..170488a 100644 --- a/SourceGen/LineListGen.cs +++ b/SourceGen/LineListGen.cs @@ -1045,6 +1045,7 @@ namespace SourceGen { // // TODO: integrate into FormattedOperandCache so we don't have to // regenerate them unless they change. Use the MLC as the dependency. + // Better: create FormattedMLCCache, use the MLC and Formatter. if (mProject.Notes.TryGetValue(offset, out MultiLineComment noteData)) { List<string> formatted = noteData.FormatText(mFormatter, "NOTE: "); StringListToLines(formatted, offset, Line.Type.Note, diff --git a/SourceGen/MainController.cs b/SourceGen/MainController.cs index 1439c00..f082fd5 100644 --- a/SourceGen/MainController.cs +++ b/SourceGen/MainController.cs @@ -492,25 +492,25 @@ namespace SourceGen { mFormatterConfig = new Formatter.FormatConfig(); AsmGen.GenCommon.ConfigureFormatterFromSettings(AppSettings.Global, ref mFormatterConfig); - mFormatterConfig.mEndOfLineCommentDelimiter = ";"; - mFormatterConfig.mFullLineCommentDelimiterBase = ";"; - mFormatterConfig.mBoxLineCommentDelimiter = string.Empty; + mFormatterConfig.EndOfLineCommentDelimiter = ";"; + mFormatterConfig.FullLineCommentDelimiterBase = ";"; + mFormatterConfig.BoxLineCommentDelimiter = string.Empty; - mFormatterConfig.mNonUniqueLabelPrefix = + mFormatterConfig.NonUniqueLabelPrefix = settings.GetString(AppSettings.FMT_NON_UNIQUE_LABEL_PREFIX, string.Empty); - mFormatterConfig.mLocalVariableLabelPrefix = + mFormatterConfig.LocalVariableLabelPrefix = settings.GetString(AppSettings.FMT_LOCAL_VARIABLE_PREFIX, string.Empty); - mFormatterConfig.mCommaSeparatedDense = + mFormatterConfig.CommaSeparatedDense = settings.GetBool(AppSettings.FMT_COMMA_SEP_BULK_DATA, true); string chrDelCereal = settings.GetString(AppSettings.FMT_CHAR_DELIM, null); if (chrDelCereal != null) { - mFormatterConfig.mCharDelimiters = + mFormatterConfig.CharDelimiters = Formatter.DelimiterSet.Deserialize(chrDelCereal); } string strDelCereal = settings.GetString(AppSettings.FMT_STRING_DELIM, null); if (strDelCereal != null) { - mFormatterConfig.mStringDelimiters = + mFormatterConfig.StringDelimiters = Formatter.DelimiterSet.Deserialize(strDelCereal); } diff --git a/SourceGen/MultiLineComment.cs b/SourceGen/MultiLineComment.cs index d4dfef8..97759e7 100644 --- a/SourceGen/MultiLineComment.cs +++ b/SourceGen/MultiLineComment.cs @@ -95,7 +95,7 @@ namespace SourceGen { /// <returns>Array of formatted strings.</returns> public List<string> FormatText(Asm65.Formatter formatter, string textPrefix) { const char boxChar = '*'; - const char spcRep = '\u2219'; + const char spcRep = '\u2219'; // BULLET OPERATOR string workString = string.IsNullOrEmpty(textPrefix) ? Text : textPrefix + Text; List<string> lines = new List<string>(); diff --git a/SourceGen/PseudoOp.cs b/SourceGen/PseudoOp.cs index cbf8ce4..5170a85 100644 --- a/SourceGen/PseudoOp.cs +++ b/SourceGen/PseudoOp.cs @@ -468,7 +468,7 @@ namespace SourceGen { FormatDescriptor dfd, byte[] data, int offset, out string popcode) { StringOpFormatter.ReverseMode revMode = StringOpFormatter.ReverseMode.Forward; - Formatter.DelimiterSet delSet = formatter.Config.mStringDelimiters; + Formatter.DelimiterSet delSet = formatter.Config.StringDelimiters; Formatter.DelimiterDef delDef; CharEncoding.Convert charConv; @@ -736,7 +736,7 @@ namespace SourceGen { string selOp; if (dfd.SymbolRef.ValuePart == WeakSymbolRef.Part.Bank) { symbolValue = (sym.Value >> 16) & 0xff; - if (formatter.Config.mBankSelectBackQuote) { + if (formatter.Config.BankSelectBackQuote) { selOp = "`"; } else { selOp = "^"; diff --git a/SourceGen/Tools/WpfGui/HexDumpViewer.xaml.cs b/SourceGen/Tools/WpfGui/HexDumpViewer.xaml.cs index 87c854f..cf58dbe 100644 --- a/SourceGen/Tools/WpfGui/HexDumpViewer.xaml.cs +++ b/SourceGen/Tools/WpfGui/HexDumpViewer.xaml.cs @@ -150,9 +150,9 @@ namespace SourceGen.Tools.WpfGui { // initializing return; } - config.mHexDumpCharConvMode = item.Mode; + config.HexDumpCharConvMode = item.Mode; - config.mHexDumpAsciiOnly = AsciiOnlyDump; + config.HexDumpAsciiOnly = AsciiOnlyDump; // Keep app settings up to date. AppSettings.Global.SetBool(AppSettings.HEXD_ASCII_ONLY, mAsciiOnlyDump); diff --git a/SourceGen/WpfGui/EditAppSettings.xaml.cs b/SourceGen/WpfGui/EditAppSettings.xaml.cs index 75976f5..b157174 100644 --- a/SourceGen/WpfGui/EditAppSettings.xaml.cs +++ b/SourceGen/WpfGui/EditAppSettings.xaml.cs @@ -1171,14 +1171,13 @@ namespace SourceGen.WpfGui { gen.GetDefaultDisplayFormat(out PseudoOp.PseudoOpNames unused, out Asm65.Formatter.FormatConfig formatConfig); - formatConfig.Normalize(); DisplayPresets[i + 2] = new DisplayFormatPreset((int)asmInfo.AssemblerId, - asmInfo.Name, formatConfig.mForceAbsOpcodeSuffix, - formatConfig.mForceLongOpcodeSuffix, formatConfig.mForceAbsOperandPrefix, - formatConfig.mForceLongOperandPrefix, formatConfig.mNonUniqueLabelPrefix, - formatConfig.mLocalVariableLabelPrefix, formatConfig.mCommaSeparatedDense, - formatConfig.mExpressionMode); + asmInfo.Name, formatConfig.ForceAbsOpcodeSuffix, + formatConfig.ForceLongOpcodeSuffix, formatConfig.ForceAbsOperandPrefix, + formatConfig.ForceLongOperandPrefix, formatConfig.NonUniqueLabelPrefix, + formatConfig.LocalVariableLabelPrefix, formatConfig.CommaSeparatedDense, + formatConfig.ExprMode); } }