示例#1
0
        /// <summary>
        /// Creates one or more FormatDescriptor entries for the specified range, adding them
        /// to the Results list.
        /// </summary>
        /// <param name="low">Offset of first byte in range.</param>
        /// <param name="high">Offset of last byte in range.</param>
        /// <param name="subType">String sub-type.</param>
        private void CreateLengthStringEntries(int low, int high,
                                               FormatDescriptor.SubType subType)
        {
            int i;

            for (i = low; i <= high;)
            {
                int length = mFileData[i];
                if (subType == FormatDescriptor.SubType.L16String)
                {
                    length |= mFileData[i + 1] << 8;
                    length += 2;
                }
                else
                {
                    length++;
                }
                // Zero-length strings are allowed.
                FormatDescriptor dfd = FormatDescriptor.Create(length,
                                                               FormatDescriptor.Type.String, subType);
                Results.Add(i, dfd);
                i += length;
            }

            Debug.Assert(i == high + 1);
        }
示例#2
0
        /// <summary>
        /// Creates one or more FormatDescriptor entries for the specified range, adding them
        /// to the Results list.
        ///
        /// This will either create one entry that spans the entire range (for e.g. strings
        /// and bulk data), or create equal-sized chunks.
        /// </summary>
        /// <param name="type">Region data type.</param>
        /// <param name="subType">Region data sub-type.</param>
        /// <param name="chunkLength">Length of a chunk, or -1 for full buffer.</param>
        /// <param name="symbolRef">Symbol reference, or null if not applicable.</param>
        /// <param name="low">Offset of first byte in range.</param>
        /// <param name="high">Offset of last byte in range.</param>
        private void CreateSimpleEntries(FormatDescriptor.Type type,
                                         FormatDescriptor.SubType subType, int chunkLength,
                                         WeakSymbolRef symbolRef, int low, int high)
        {
            if (chunkLength == -1)
            {
                chunkLength = (high - low) + 1;
            }
            Debug.Assert(((high - low + 1) / chunkLength) * chunkLength == high - low + 1);

            // Either we have one chunk, or we have multiple chunks with the same type and
            // length.  Either way, we only need to create the descriptor once.  (This is
            // safe because FormatDescriptor instances are immutable.)
            //
            // Because certain details, like the fill byte and high-vs-low ASCII, are pulled
            // out of the data stream at format time, we don't have to dig for them now.
            FormatDescriptor dfd;

            if (subType == FormatDescriptor.SubType.Symbol)
            {
                dfd = FormatDescriptor.Create(chunkLength, symbolRef,
                                              type == FormatDescriptor.Type.NumericBE);
            }
            else
            {
                dfd = FormatDescriptor.Create(chunkLength, type, subType);
            }

            while (low <= high)
            {
                Results.Add(low, dfd);
                low += chunkLength;
            }
        }
示例#3
0
        /// <summary>
        /// Creates a format descriptor for a single-byte numeric value.
        /// </summary>
        /// <param name="offset">File offset.</param>
        /// <param name="subType">How to format the item.</param>
        private void CreateByteFD(int offset, FormatDescriptor.SubType subType)
        {
            FormatDescriptor dfd = FormatDescriptor.Create(1,
                                                           FormatDescriptor.Type.NumericLE, subType);

            Results.Add(offset, dfd);
        }
示例#4
0
        private void okButton_Click(object sender, EventArgs e)
        {
            bool isConstant = constantRadioButton.Checked;

            ParseValue(out int value, out int numBase);
            FormatDescriptor.SubType subType = FormatDescriptor.GetSubTypeForBase(numBase);
            DefSym = new DefSymbol(labelTextBox.Text, value, Symbol.Source.Project,
                                   isConstant ? Symbol.Type.Constant : Symbol.Type.ExternalAddr,
                                   subType, commentTextBox.Text, string.Empty);
        }
示例#5
0
 /// <summary>
 /// Constructor.  Used for platform symbol files.
 /// </summary>
 /// <param name="loadOrdinal">Indicates the order in which the defining platform
 ///   symbol file was loaded.  Higher numbers indicate later loading, which translates
 ///   to higher priority.</param>
 /// <param name="fileIdent">Platform symbol file identifier, for the Info panel.</param>
 public DefSymbol(string label, int value, Source source, Type type,
                  FormatDescriptor.SubType formatSubType, int width, bool widthSpecified,
                  string comment, DirectionFlags direction, MultiAddressMask multiMask, string tag,
                  int loadOrdinal, string fileIdent)
     : this(label, value, source, type, formatSubType, width, widthSpecified,
            comment, direction, multiMask, tag)
 {
     LoadOrdinal    = loadOrdinal;
     FileIdentifier = fileIdent;
 }
示例#6
0
        /// <summary>
        /// Creates one or more FormatDescriptor entries for the specified range, adding them
        /// to the Results list.
        /// </summary>
        /// <param name="low">Offset of first byte in range.</param>
        /// <param name="high">Offset of last byte in range.</param>
        /// <param name="subType">String sub-type.</param>
        private void CreateMixedStringEntries(int low, int high,
                                              FormatDescriptor.SubType subType)
        {
            int stringStart = -1;
            int highBit     = 0;
            int cur;

            for (cur = low; cur <= high; cur++)
            {
                byte val = mFileData[cur];
                if (CommonUtil.TextUtil.IsHiLoAscii(val))
                {
                    // is ASCII
                    if (stringStart >= 0)
                    {
                        // was in a string
                        if (highBit != (val & 0x80))
                        {
                            // end of string due to high bit flip, output
                            CreateStringOrByte(stringStart, cur - stringStart, subType);
                            // start a new string
                            stringStart = cur;
                        }
                        else
                        {
                            // still in string, keep going
                        }
                    }
                    else
                    {
                        // wasn't in a string, start one
                        stringStart = cur;
                    }
                    highBit = val & 0x80;
                }
                else
                {
                    // not ASCII
                    if (stringStart >= 0)
                    {
                        // was in a string, output it
                        CreateStringOrByte(stringStart, cur - stringStart, subType);
                        stringStart = -1;
                    }
                    // output as single byte
                    CreateByteFD(cur, FormatDescriptor.SubType.Hex);
                }
            }
            if (stringStart >= 0)
            {
                // close out the string
                CreateStringOrByte(stringStart, cur - stringStart, subType);
            }
        }
示例#7
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="label">Symbol's label.</param>
        /// <param name="value">Symbol's value.</param>
        /// <param name="source">Symbol source (general point of origin).</param>
        /// <param name="type">Symbol type.</param>
        /// <param name="formatSubType">Format descriptor sub-type, so we know how the
        ///   user wants the value to be displayed.</param>
        /// <param name="comment">End-of-line comment.</param>
        /// <param name="tag">Symbol tag, used for grouping platform symbols.</param>
        public DefSymbol(string label, int value, Source source, Type type,
                         FormatDescriptor.SubType formatSubType, string comment, string tag)
            : this(label, value, source, type)
        {
            Debug.Assert(comment != null);
            Debug.Assert(tag != null);

            // Length doesn't matter; use 1 to get prefab object.
            DataDescriptor = FormatDescriptor.Create(1,
                                                     FormatDescriptor.Type.NumericLE, formatSubType);

            Comment = comment;
            Tag     = tag;
        }
示例#8
0
        private void OkButton_Click(object sender, RoutedEventArgs e)
        {
            ParseValue(out int value, out int numBase);
            FormatDescriptor.SubType subType = FormatDescriptor.GetSubTypeForBase(numBase);
            int width = -1;

            if (IsConstant && !IsVariable)
            {
                // width field is ignored, don't bother parsing
            }
            else if (!string.IsNullOrEmpty(VarWidth))
            {
                bool ok = Asm65.Number.TryParseInt(VarWidth, out width, out int unusedNumBase);
                Debug.Assert(ok);
            }

            DefSymbol.DirectionFlags direction;
            if (IsReadChecked && IsWriteChecked)
            {
                direction = DefSymbol.DirectionFlags.ReadWrite;
            }
            else if (IsReadChecked)
            {
                direction = DefSymbol.DirectionFlags.Read;
            }
            else if (IsWriteChecked)
            {
                direction = DefSymbol.DirectionFlags.Write;
            }
            else
            {
                Debug.Assert(false);
                direction = DefSymbol.DirectionFlags.None;
            }

            // Parse and strip the annotation.
            string trimLabel = Symbol.TrimAndValidateLabel(Label, string.Empty, out bool unused1,
                                                           out bool unused2, out bool unused3, out bool unused4,
                                                           out Symbol.LabelAnnotation anno);

            NewSym = new DefSymbol(trimLabel, value,
                                   IsVariable ? Symbol.Source.Variable : Symbol.Source.Project,
                                   IsConstant ? Symbol.Type.Constant : Symbol.Type.ExternalAddr, anno,
                                   subType, width, width > 0, Comment, direction, null, string.Empty);

            DialogResult = true;
        }
示例#9
0
 /// <summary>
 /// Creates a format descriptor for ASCII data.  If the data is only one byte long,
 /// a single-byte ASCII char item is emitted instead.
 /// </summary>
 /// <param name="offset">Offset of first byte.</param>
 /// <param name="length">Length of string.</param>
 /// <param name="subType">String sub-type.</param>
 private void CreateStringOrByte(int offset, int length,
                                 FormatDescriptor.SubType subType)
 {
     Debug.Assert(length > 0);
     if (length == 1)
     {
         // single byte, output as single ASCII char rather than 1-byte string
         CreateByteFD(offset, FormatDescriptor.SubType.Ascii);
     }
     else
     {
         FormatDescriptor dfd;
         dfd = FormatDescriptor.Create(length,
                                       FormatDescriptor.Type.String, subType);
         Results.Add(offset, dfd);
     }
 }
示例#10
0
        /// <summary>
        /// Creates one or more FormatDescriptor entries for the specified range, adding them
        /// to the Results list.
        /// </summary>
        /// <param name="low">Offset of first byte in range.</param>
        /// <param name="high">Offset of last byte in range.</param>
        /// <param name="subType">String sub-type.</param>
        private void CreateDciStringEntries(int low, int high,
                                            FormatDescriptor.SubType subType)
        {
            int start, end, adj, endMask;

            if (subType == FormatDescriptor.SubType.Dci)
            {
                start = low;
                end   = high + 1;
                adj   = 1;
            }
            else if (subType == FormatDescriptor.SubType.DciReverse)
            {
                start = high;
                end   = low - 1;
                adj   = -1;
            }
            else
            {
                Debug.Assert(false);
                return;
            }

            // Zero-length strings aren't a thing for DCI.  The analyzer requires that all
            // strings in a region have the same polarity, so just grab the last byte.
            endMask = mFileData[end - 1] & 0x80;

            int stringStart = start;

            for (int i = start; i != end; i += adj)
            {
                byte val = mFileData[i];
                if ((val & 0x80) == endMask)
                {
                    // found the end of a string
                    int length           = (i - stringStart) * adj + 1;
                    FormatDescriptor dfd = FormatDescriptor.Create(length,
                                                                   FormatDescriptor.Type.String, subType);
                    Results.Add(stringStart < i ? stringStart : i, dfd);
                    stringStart = i + adj;
                }
            }

            Debug.Assert(stringStart == end);
        }
示例#11
0
        /// <summary>
        /// Converts a FormatDescriptor SubType to a CharEncoding.Encoding value.
        /// </summary>
        /// <param name="subType">FormatDescriptor sub-type.</param>
        /// <returns>The corresponding CharEncoding.Encoding value, or Encoding.Unknown
        ///   if the sub-type isn't a character encoding.</returns>
        public static CharEncoding.Encoding SubTypeToEnc(FormatDescriptor.SubType subType)
        {
            switch (subType)
            {
            case FormatDescriptor.SubType.Ascii:
                return(CharEncoding.Encoding.Ascii);

            case FormatDescriptor.SubType.HighAscii:
                return(CharEncoding.Encoding.HighAscii);

            case FormatDescriptor.SubType.C64Petscii:
                return(CharEncoding.Encoding.C64Petscii);

            case FormatDescriptor.SubType.C64Screen:
                return(CharEncoding.Encoding.C64ScreenCode);

            default:
                return(CharEncoding.Encoding.Unknown);
            }
        }
示例#12
0
        /// <summary>
        /// Constructor.  General form.
        /// </summary>
        /// <param name="label">Symbol's label.</param>
        /// <param name="value">Symbol's value.</param>
        /// <param name="source">Symbol source (general point of origin).</param>
        /// <param name="type">Symbol type.</param>
        /// <param name="formatSubType">Format descriptor sub-type, so we know how the
        ///   user wants the value to be displayed.</param>
        /// <param name="width">Variable width.</param>
        /// <param name="widthSpecified">True if width was explicitly specified.  If this is
        /// <param name="comment">End-of-line comment.</param>
        /// <param name="direction">I/O direction.</param>
        /// <param name="multiMask">Bit mask to apply before comparisons.</param>
        /// <param name="tag">Symbol tag, used for grouping platform symbols.</param>
        ///   false, the value of the "width" argument is ignored.</param>
        public DefSymbol(string label, int value, Source source, Type type,
                         LabelAnnotation labelAnno, FormatDescriptor.SubType formatSubType,
                         int width, bool widthSpecified, string comment,
                         DirectionFlags direction, MultiAddressMask multiMask, string tag)
            : this(label, value, source, type, labelAnno)
        {
            Debug.Assert(comment != null);
            Debug.Assert(tag != null);

            if (widthSpecified && type == Type.Constant && source != Source.Variable)
            {
                // non-variable constants don't have a width; override arg
                Debug.WriteLine("Overriding constant DefSymbol width");
                widthSpecified = false;
            }
            HasWidth = widthSpecified;
            if (!widthSpecified)
            {
                width = DEFAULT_WIDTH;
            }
            Debug.Assert(width >= MIN_WIDTH && width <= MAX_WIDTH);

            DataDescriptor = FormatDescriptor.Create(width,
                                                     FormatDescriptor.Type.NumericLE, formatSubType);
            Comment = comment;

            Debug.Assert(((int)direction & ~(int)DirectionFlags.ReadWrite) == 0);
            Direction = direction;

            // constants don't have masks
            if (type != Type.Constant)
            {
                MultiMask = multiMask;
            }

            Tag = tag;
        }
示例#13
0
        /// <summary>
        /// Creates one or more FormatDescriptor entries for the specified range, adding them
        /// to the Results list.
        /// </summary>
        /// <param name="low">Offset of first byte in range.</param>
        /// <param name="high">Offset of last byte in range.</param>
        /// <param name="subType">String sub-type.</param>
        private void CreateCStringEntries(int low, int high,
                                          FormatDescriptor.SubType subType)
        {
            int startOffset = low;

            for (int i = low; i <= high; i++)
            {
                if (mFileData[i] == 0x00)
                {
                    // End of string.  Zero-length strings are allowed.
                    FormatDescriptor dfd = FormatDescriptor.Create(
                        i - startOffset + 1, FormatDescriptor.Type.String, subType);
                    Results.Add(startOffset, dfd);
                    startOffset = i + 1;
                }
                else
                {
                    // keep going
                }
            }

            // Earlier analysis guaranteed that the last byte in the buffer is 0x00.
            Debug.Assert(startOffset == high + 1);
        }
示例#14
0
        /// <summary>
        /// Converts a collection of bytes that represent a string into an array of characters,
        /// stripping the high bit.  Framing data, such as leading lengths and trailing nulls,
        /// are not shown.
        /// </summary>
        /// <param name="formatter">Formatter object.</param>
        /// <param name="subType">String sub-type.</param>
        /// <param name="data">File data.</param>
        /// <param name="offset">Offset, within data, of start of string.</param>
        /// <param name="length">Number of bytes to convert.</param>
        /// <param name="popcode">Pseudo-opcode string.</param>
        /// <param name="showHexZeroes">If nonzero, show 1+ zeroes (representing a leading
        ///     length or null-termination) instead of an empty string.</param>
        /// <returns>Array of characters with string data.</returns>
        private static char[] BytesToChars(Formatter formatter, PseudoOpNames opNames,
                                           FormatDescriptor.SubType subType, byte[] data, int offset, int length,
                                           out string popcode, out int showHexZeroes)
        {
            Debug.Assert(length > 0);

            // See also GenMerlin32.OutputString().
            int  strOffset = offset;
            int  strLen    = length;
            bool highAscii = false;
            bool reverse   = false;

            showHexZeroes = 0;

            switch (subType)
            {
            case FormatDescriptor.SubType.None:
                // High or low ASCII, full width specified by formatter.
                highAscii = (data[offset] & 0x80) != 0;
                popcode   = highAscii ? opNames.StrGenericHi : opNames.StrGeneric;
                break;

            case FormatDescriptor.SubType.Dci:
                // High or low ASCII, full width specified by formatter.
                highAscii = (data[offset] & 0x80) != 0;
                popcode   = highAscii ? opNames.StrDciHi : opNames.StrDci;
                break;

            case FormatDescriptor.SubType.Reverse:
                // High or low ASCII, full width specified by formatter.  Show characters
                // in reverse order.
                highAscii = (data[offset + strLen - 1] & 0x80) != 0;
                popcode   = highAscii ? opNames.StrReverseHi : opNames.StrReverse;
                reverse   = true;
                break;

            case FormatDescriptor.SubType.DciReverse:
                // High or low ASCII, full width specified by formatter.  Show characters
                // in reverse order.
                highAscii = (data[offset + strLen - 1] & 0x80) != 0;
                popcode   = highAscii ? opNames.StrDciReverseHi : opNames.StrDciReverse;
                reverse   = true;
                break;

            case FormatDescriptor.SubType.CString:
                // High or low ASCII, with a terminating null.  Don't show the null.  If
                // it's an empty string, just show the null byte as hex.
                highAscii = (data[offset] & 0x80) != 0;
                popcode   = highAscii ? opNames.StrNullTermHi : opNames.StrNullTerm;
                strLen--;
                if (strLen == 0)
                {
                    showHexZeroes = 1;
                }
                break;

            case FormatDescriptor.SubType.L8String:
                // High or low ASCII, with a leading length byte.  Don't show the null.
                // If it's an empty string, just show the length byte as hex.
                strOffset++;
                strLen--;
                if (strLen == 0)
                {
                    showHexZeroes = 1;
                }
                else
                {
                    highAscii = (data[strOffset] & 0x80) != 0;
                }
                popcode = highAscii ? opNames.StrLen8Hi : opNames.StrLen8;
                break;

            case FormatDescriptor.SubType.L16String:
                // High or low ASCII, with a leading length word.  Don't show the null.
                // If it's an empty string, just show the length word as hex.
                Debug.Assert(strLen > 1);
                strOffset += 2;
                strLen    -= 2;
                if (strLen == 0)
                {
                    showHexZeroes = 2;
                }
                else
                {
                    highAscii = (data[strOffset] & 0x80) != 0;
                }
                popcode = highAscii ? opNames.StrLen16Hi : opNames.StrLen16;
                break;

            default:
                Debug.Assert(false);
                popcode = ".!!!";
                break;
            }

            char[] text = new char[strLen];
            if (!reverse)
            {
                for (int i = 0; i < strLen; i++)
                {
                    text[i] = (char)(data[i + strOffset] & 0x7f);
                }
            }
            else
            {
                for (int i = 0; i < strLen; i++)
                {
                    text[i] = (char)(data[strOffset + (strLen - i - 1)] & 0x7f);
                }
            }

            return(text);
        }
示例#15
0
        /// <summary>
        /// Loads platform symbols.
        /// </summary>
        /// <param name="fileIdent">Relative pathname of file to open.</param>
        /// <param name="report">Report of warnings and errors.</param>
        /// <returns>True on success (no errors), false on failure.</returns>
        public bool LoadFromFile(string fileIdent, string projectDir, out FileLoadReport report)
        {
            // These files shouldn't be enormous.  Do it the easy way.
            report = new FileLoadReport(fileIdent);

            ExternalFile ef = ExternalFile.CreateFromIdent(fileIdent);

            if (ef == null)
            {
                report.Add(FileLoadItem.Type.Error,
                           CommonUtil.Properties.Resources.ERR_FILE_NOT_FOUND + ": " + fileIdent);
                return(false);
            }

            string pathName = ef.GetPathName(projectDir);

            if (pathName == null)
            {
                report.Add(FileLoadItem.Type.Error,
                           Properties.Resources.ERR_BAD_IDENT + ": " + fileIdent);
                return(false);
            }
            string[] lines;
            try {
                lines = File.ReadAllLines(pathName);
            } catch (IOException ioe) {
                Debug.WriteLine("Platform symbol load failed: " + ioe);
                report.Add(FileLoadItem.Type.Error,
                           CommonUtil.Properties.Resources.ERR_FILE_NOT_FOUND + ": " + pathName);
                return(false);
            }

            string tag = string.Empty;

            int lineNum = 0;

            foreach (string line in lines)
            {
                lineNum++;      // first line is line 1, says Vim and VisualStudio
                if (string.IsNullOrEmpty(line) || line[0] == ';')
                {
                    // ignore
                }
                else if (line[0] == '*')
                {
                    if (line.StartsWith(TAG_CMD))
                    {
                        tag = ParseTag(line);
                    }
                    else
                    {
                        // Do something clever with *SYNOPSIS?
                        Debug.WriteLine("CMD: " + line);
                    }
                }
                else
                {
                    MatchCollection matches = sNameValueRegex.Matches(line);
                    if (matches.Count == 1)
                    {
                        //Debug.WriteLine("GOT '" + matches[0].Groups[1] + "' " +
                        //    matches[0].Groups[2] + " '" + matches[0].Groups[3] + "'");
                        string label   = matches[0].Groups[1].Value;
                        bool   isConst = (matches[0].Groups[2].Value[0] == '=');
                        string badParseMsg;
                        int    value, numBase;
                        bool   parseOk;
                        if (isConst)
                        {
                            // Allow various numeric options, and preserve the value.
                            parseOk = Asm65.Number.TryParseInt(matches[0].Groups[3].Value,
                                                               out value, out numBase);
                            badParseMsg =
                                CommonUtil.Properties.Resources.ERR_INVALID_NUMERIC_CONSTANT;
                        }
                        else
                        {
                            // Allow things like "05/1000".  Always hex.
                            numBase = 16;
                            parseOk = Asm65.Address.ParseAddress(matches[0].Groups[3].Value,
                                                                 (1 << 24) - 1, out value);
                            badParseMsg = CommonUtil.Properties.Resources.ERR_INVALID_ADDRESS;
                        }
                        if (!parseOk)
                        {
                            report.Add(lineNum, FileLoadItem.NO_COLUMN, FileLoadItem.Type.Warning,
                                       badParseMsg);
                        }
                        else
                        {
                            string comment = matches[0].Groups[4].Value;
                            if (comment.Length > 0)
                            {
                                // remove ';'
                                comment = comment.Substring(1);
                            }
                            FormatDescriptor.SubType subType =
                                FormatDescriptor.GetSubTypeForBase(numBase);
                            DefSymbol symDef = new DefSymbol(label, value, Symbol.Source.Platform,
                                                             isConst ? Symbol.Type.Constant : Symbol.Type.ExternalAddr,
                                                             subType, comment, tag);
                            if (mSymbols.ContainsKey(label))
                            {
                                // This is very easy to do -- just define the same symbol twice
                                // in the same file.  We don't really need to do anything about
                                // it though.
                                Debug.WriteLine("NOTE: stomping previous definition of " + label);
                            }
                            mSymbols[label] = symDef;
                        }
                    }
                    else
                    {
                        report.Add(lineNum, FileLoadItem.NO_COLUMN, FileLoadItem.Type.Warning,
                                   CommonUtil.Properties.Resources.ERR_SYNTAX);
                    }
                }
            }

            return(!report.HasErrors);
        }
示例#16
0
        /// <summary>
        /// Creates a list of FormatDescriptors, based on the current control configuration.
        ///
        /// The entries in the list are guaranteed to be sorted by start address and not
        /// overlap.
        ///
        /// We assume that whatever the control gives us is correct, e.g. it's not going
        /// to tell us to put a buffer full of zeroes into a DCI string.
        /// </summary>
        /// <returns>Result list.</returns>
        private void CreateDescriptorListFromControls()
        {
            FormatDescriptor.Type    type      = FormatDescriptor.Type.Default;
            FormatDescriptor.SubType subType   = FormatDescriptor.SubType.None;
            WeakSymbolRef            symbolRef = null;
            int chunkLength = -1;

            // Decode the "display as" panel, if it's relevant.
            if (radioSimpleDataHex.Enabled)
            {
                if (radioSimpleDataHex.Checked)
                {
                    subType = FormatDescriptor.SubType.Hex;
                }
                else if (radioSimpleDataDecimal.Checked)
                {
                    subType = FormatDescriptor.SubType.Decimal;
                }
                else if (radioSimpleDataBinary.Checked)
                {
                    subType = FormatDescriptor.SubType.Binary;
                }
                else if (radioSimpleDataAscii.Checked)
                {
                    subType = FormatDescriptor.SubType.Ascii;
                }
                else if (radioSimpleDataAddress.Checked)
                {
                    subType = FormatDescriptor.SubType.Address;
                }
                else if (radioSimpleDataSymbolic.Checked)
                {
                    WeakSymbolRef.Part part;
                    if (radioSymbolPartLow.Checked)
                    {
                        part = WeakSymbolRef.Part.Low;
                    }
                    else if (radioSymbolPartHigh.Checked)
                    {
                        part = WeakSymbolRef.Part.High;
                    }
                    else if (radioSymbolPartBank.Checked)
                    {
                        part = WeakSymbolRef.Part.Bank;
                    }
                    else
                    {
                        Debug.Assert(false);
                        part = WeakSymbolRef.Part.Low;
                    }
                    subType   = FormatDescriptor.SubType.Symbol;
                    symbolRef = new WeakSymbolRef(symbolEntryTextBox.Text, part);
                }
                else
                {
                    Debug.Assert(false);
                }
            }
            else
            {
                subType = 0;        // set later, or doesn't matter
            }

            // Decode the main format.
            if (radioDefaultFormat.Checked)
            {
                // Default/None; note this would create a multi-byte Default format, which isn't
                // really allowed.  What we actually want to do is remove the explicit formatting
                // from all spanned offsets, so we use a dedicated type for that.
                type = FormatDescriptor.Type.REMOVE;
            }
            else if (radioSingleBytes.Checked)
            {
                type        = FormatDescriptor.Type.NumericLE;
                chunkLength = 1;
            }
            else if (radio16BitLittle.Checked)
            {
                type        = FormatDescriptor.Type.NumericLE;
                chunkLength = 2;
            }
            else if (radio16BitBig.Checked)
            {
                type        = FormatDescriptor.Type.NumericBE;
                chunkLength = 2;
            }
            else if (radio24BitLittle.Checked)
            {
                type        = FormatDescriptor.Type.NumericLE;
                chunkLength = 3;
            }
            else if (radio32BitLittle.Checked)
            {
                type        = FormatDescriptor.Type.NumericLE;
                chunkLength = 4;
            }
            else if (radioDenseHex.Checked)
            {
                type = FormatDescriptor.Type.Dense;
            }
            else if (radioFill.Checked)
            {
                type = FormatDescriptor.Type.Fill;
            }
            else if (radioStringMixed.Checked)
            {
                type = FormatDescriptor.Type.String;
            }
            else if (radioStringMixedReverse.Checked)
            {
                type    = FormatDescriptor.Type.String;
                subType = FormatDescriptor.SubType.Reverse;
            }
            else if (radioStringNullTerm.Checked)
            {
                type    = FormatDescriptor.Type.String;
                subType = FormatDescriptor.SubType.CString;
            }
            else if (radioStringLen8.Checked)
            {
                type    = FormatDescriptor.Type.String;
                subType = FormatDescriptor.SubType.L8String;
            }
            else if (radioStringLen16.Checked)
            {
                type    = FormatDescriptor.Type.String;
                subType = FormatDescriptor.SubType.L16String;
            }
            else if (radioStringDci.Checked)
            {
                type    = FormatDescriptor.Type.String;
                subType = FormatDescriptor.SubType.Dci;
                //} else if (radioStringDciReverse.Checked) {
                //    type = FormatDescriptor.Type.String;
                //    subType = FormatDescriptor.SubType.DciReverse;
            }
            else
            {
                Debug.Assert(false);
                // default/none
            }


            Results = new SortedList <int, FormatDescriptor>();

            IEnumerator <TypedRangeSet.TypedRange> iter = Selection.RangeListIterator;

            while (iter.MoveNext())
            {
                TypedRangeSet.TypedRange rng = iter.Current;

                if (type == FormatDescriptor.Type.String)
                {
                    // We want to create one FormatDescriptor object per string.  That way
                    // each string gets its own line.
                    if ((subType == FormatDescriptor.SubType.None ||
                         subType == FormatDescriptor.SubType.Reverse))
                    {
                        CreateMixedStringEntries(rng.Low, rng.High, subType);
                    }
                    else if (subType == FormatDescriptor.SubType.CString)
                    {
                        CreateCStringEntries(rng.Low, rng.High, subType);
                    }
                    else if (subType == FormatDescriptor.SubType.L8String ||
                             subType == FormatDescriptor.SubType.L16String)
                    {
                        CreateLengthStringEntries(rng.Low, rng.High, subType);
                    }
                    else if (subType == FormatDescriptor.SubType.Dci ||
                             subType == FormatDescriptor.SubType.DciReverse)
                    {
                        CreateDciStringEntries(rng.Low, rng.High, subType);
                    }
                    else
                    {
                        Debug.Assert(false);
                        CreateMixedStringEntries(rng.Low, rng.High, subType);   // shrug
                    }
                }
                else
                {
                    CreateSimpleEntries(type, subType, chunkLength, symbolRef, rng.Low, rng.High);
                }
            }
        }
示例#17
0
 /// <summary>
 /// Constructor.  Limited form, used in a couple of places, e.g. when we need to start
 /// with a default value.  The symbol will have unspecified width, ReadWrite direction,
 /// and no mask.
 /// </summary>
 /// <param name="label">Symbol's label.</param>
 /// <param name="value">Symbol's value.</param>
 /// <param name="source">Symbol source (general point of origin).</param>
 /// <param name="type">Symbol type.</param>
 /// <param name="formatSubType">Format descriptor sub-type, so we know how the
 ///   user wants the value to be displayed.</param>
 public DefSymbol(string label, int value, Source source, Type type,
                  FormatDescriptor.SubType formatSubType)
     : this(label, value, source, type, formatSubType, -1, false,
            string.Empty, DirectionFlags.ReadWrite, null, string.Empty)
 {
 }
示例#18
0
        /// <summary>
        /// Loads platform symbols.
        /// </summary>
        /// <param name="fileIdent">External file identifier of symbol file.</param>
        /// <param name="projectDir">Full path to project directory.</param>
        /// <param name="loadOrdinal">Platform file load order.</param>
        /// <param name="report">Report of warnings and errors.</param>
        /// <returns>True on success (no errors), false on failure.</returns>
        public bool LoadFromFile(string fileIdent, string projectDir, int loadOrdinal,
                                 out FileLoadReport report)
        {
            report = new FileLoadReport(fileIdent);

            ExternalFile ef = ExternalFile.CreateFromIdent(fileIdent);

            if (ef == null)
            {
                report.Add(FileLoadItem.Type.Error,
                           CommonUtil.Properties.Resources.ERR_FILE_NOT_FOUND + ": " + fileIdent);
                return(false);
            }
            string pathName = ef.GetPathName(projectDir);

            if (pathName == null)
            {
                report.Add(FileLoadItem.Type.Error,
                           Res.Strings.ERR_BAD_IDENT + ": " + fileIdent);
                return(false);
            }

            // These files shouldn't be enormous.  Just read the entire thing into a string array.
            string[] lines;
            try {
                lines = File.ReadAllLines(pathName);
            } catch (IOException ioe) {
                Debug.WriteLine("Platform symbol load failed: " + ioe);
                report.Add(FileLoadItem.Type.Error,
                           CommonUtil.Properties.Resources.ERR_FILE_NOT_FOUND + ": " + pathName);
                return(false);
            }

            string tag = string.Empty;

            DefSymbol.MultiAddressMask multiMask = null;

            int lineNum = 0;

            foreach (string line in lines)
            {
                lineNum++;      // first line is line 1, says Vim and VisualStudio
                if (string.IsNullOrEmpty(line) || line[0] == ';')
                {
                    // ignore
                }
                else if (line[0] == '*')
                {
                    if (line.StartsWith(TAG_CMD))
                    {
                        tag = ParseTag(line);
                    }
                    else if (line.StartsWith(MULTI_MASK_CMD))
                    {
                        if (!ParseMask(line, out multiMask, out string badMaskMsg))
                        {
                            report.Add(lineNum, FileLoadItem.NO_COLUMN, FileLoadItem.Type.Warning,
                                       badMaskMsg);
                        }
                        //Debug.WriteLine("Mask is now " + mask.ToString("x6"));
                    }
                    else
                    {
                        // Do something clever with *SYNOPSIS?
                        Debug.WriteLine("Ignoring CMD: " + line);
                    }
                }
                else
                {
                    MatchCollection matches = sNameValueRegex.Matches(line);
                    if (matches.Count == 1)
                    {
                        string label      = matches[0].Groups[GROUP_NAME].Value;
                        char   typeAndDir = matches[0].Groups[GROUP_TYPE].Value[0];
                        bool   isConst    = (typeAndDir == '=');
                        DefSymbol.DirectionFlags direction = DefSymbol.DirectionFlags.ReadWrite;
                        if (typeAndDir == '<')
                        {
                            direction = DefSymbol.DirectionFlags.Read;
                        }
                        else if (typeAndDir == '>')
                        {
                            direction = DefSymbol.DirectionFlags.Write;
                        }

                        string badParseMsg;
                        int    value, numBase;
                        bool   parseOk;
                        string valueStr = matches[0].Groups[GROUP_VALUE].Value;
                        if (isConst)
                        {
                            // Allow various numeric options, and preserve the value.  We
                            // don't limit the value range.
                            parseOk     = Asm65.Number.TryParseInt(valueStr, out value, out numBase);
                            badParseMsg =
                                CommonUtil.Properties.Resources.ERR_INVALID_NUMERIC_CONSTANT;
                        }
                        else if (valueStr.ToUpperInvariant().Equals(ERASE_VALUE_STR))
                        {
                            parseOk     = true;
                            value       = ERASE_VALUE;
                            numBase     = 10;
                            badParseMsg = CommonUtil.Properties.Resources.ERR_INVALID_ADDRESS;
                        }
                        else
                        {
                            // Allow things like "05/1000".  Always hex.
                            numBase = 16;
                            parseOk = Asm65.Address.ParseAddress(valueStr, (1 << 24) - 1,
                                                                 out value);
                            // limit to positive 24-bit values
                            parseOk    &= (value >= 0 && value < 0x01000000);
                            badParseMsg = CommonUtil.Properties.Resources.ERR_INVALID_ADDRESS;
                        }

                        int    width    = -1;
                        string widthStr = matches[0].Groups[GROUP_WIDTH].Value;
                        if (parseOk && !string.IsNullOrEmpty(widthStr))
                        {
                            parseOk = Asm65.Number.TryParseInt(widthStr, out width,
                                                               out int ignoredBase);
                            if (parseOk)
                            {
                                if (width < DefSymbol.MIN_WIDTH || width > DefSymbol.MAX_WIDTH)
                                {
                                    parseOk     = false;
                                    badParseMsg = Res.Strings.ERR_INVALID_WIDTH;
                                }
                            }
                            else
                            {
                                badParseMsg =
                                    CommonUtil.Properties.Resources.ERR_INVALID_NUMERIC_CONSTANT;
                            }
                        }

                        if (parseOk && multiMask != null && !isConst)
                        {
                            // We need to ensure that all possible values fit within the mask.
                            // We don't test AddressValue here, because it's okay for the
                            // canonical value to be outside the masked range.
                            int testWidth = (width > 0) ? width : 1;
                            for (int testValue = value; testValue < value + testWidth; testValue++)
                            {
                                if ((testValue & multiMask.CompareMask) != multiMask.CompareValue)
                                {
                                    parseOk     = false;
                                    badParseMsg = Res.Strings.ERR_VALUE_INCOMPATIBLE_WITH_MASK;
                                    Debug.WriteLine("Mask FAIL: value=" + value.ToString("x6") +
                                                    " width=" + width +
                                                    " testValue=" + testValue.ToString("x6") +
                                                    " mask=" + multiMask);
                                    break;
                                }
                            }
                        }

                        if (!parseOk)
                        {
                            report.Add(lineNum, FileLoadItem.NO_COLUMN, FileLoadItem.Type.Warning,
                                       badParseMsg);
                        }
                        else
                        {
                            string comment = matches[0].Groups[GROUP_COMMENT].Value;
                            if (comment.Length > 0)
                            {
                                // remove ';'
                                comment = comment.Substring(1);
                            }
                            FormatDescriptor.SubType subType =
                                FormatDescriptor.GetSubTypeForBase(numBase);
                            DefSymbol symDef = new DefSymbol(label, value, Symbol.Source.Platform,
                                                             isConst ? Symbol.Type.Constant : Symbol.Type.ExternalAddr,
                                                             subType, width, width > 0, comment, direction, multiMask,
                                                             tag, loadOrdinal, fileIdent);
                            if (mSymbols.ContainsKey(label))
                            {
                                // This is very easy to do -- just define the same symbol twice
                                // in the same file.  We don't really need to do anything about
                                // it though.
                                Debug.WriteLine("NOTE: stomping previous definition of " + label);
                            }
                            mSymbols[label] = symDef;
                        }
                    }
                    else
                    {
                        report.Add(lineNum, FileLoadItem.NO_COLUMN, FileLoadItem.Type.Warning,
                                   CommonUtil.Properties.Resources.ERR_SYNTAX);
                    }
                }
            }

            return(!report.HasErrors);
        }