Example #1
0
        /// <summary>
        /// Creates an UndoableChange for a label update.
        /// </summary>
        /// <param name="offset">Affected offset.</param>
        /// <param name="oldSymbol">Current label.  May be null.</param>
        /// <param name="newSymbol">New label.  May be null.</param>
        /// <returns>Change record.</returns>
        public static UndoableChange CreateLabelChange(int offset, Symbol oldSymbol,
                                                       Symbol newSymbol)
        {
            if (oldSymbol == newSymbol)
            {
                Debug.WriteLine("No-op label change at +" + offset.ToString("x6") +
                                ": " + oldSymbol);
            }

            UndoableChange uc = new UndoableChange();

            uc.Type     = ChangeType.SetLabel;
            uc.Offset   = offset;
            uc.OldValue = oldSymbol;
            uc.NewValue = newSymbol;
            // Data analysis can change if we add or remove a label in a data area.  Label
            // selection can change as well, e.g. switching from an auto-label to a user
            // label with an adjustment.  So renaming a user-defined label doesn't require
            // reanalysis, but adding or removing one does.
            //
            // Do the reanalysis if either is empty.  This will cause an unnecessary
            // reanalysis if we change an empty label to an empty label, but that shouldn't
            // be allowed by the UI anyway.
            Debug.Assert(newSymbol == null || newSymbol.SymbolSource == Symbol.Source.User);
            if ((oldSymbol == null) || (newSymbol == null) /*||
                                                            * (oldSymbol.SymbolSource != newSymbol.SymbolSource)*/)
            {
                uc.ReanalysisRequired = ReanalysisScope.DataOnly;
            }
            else
            {
                uc.ReanalysisRequired = ReanalysisScope.None;
            }
            return(uc);
        }
Example #2
0
        /// <summary>
        /// Creates an UndoableChange that does nothing but force an update.
        /// </summary>
        /// <param name="flags">Desired reanalysis flags.</param>
        /// <returns>Change record.</returns>
        public static UndoableChange CreateDummyChange(ReanalysisScope flags)
        {
            UndoableChange uc = new UndoableChange();

            uc.Type               = ChangeType.Dummy;
            uc.Offset             = -1;
            uc.ReanalysisRequired = flags;
            return(uc);
        }
Example #3
0
        /// <summary>
        /// Creates an UndoableChange for an operand or data format update.
        /// </summary>
        /// <param name="offset">Affected offset.</param>
        /// <param name="oldFormat">Current format.  May be null.</param>
        /// <param name="newFormat">New format.  May be null.</param>
        /// <returns>Change record.</returns>
        public static UndoableChange CreateOperandFormatChange(int offset,
                                                               FormatDescriptor oldFormat, FormatDescriptor newFormat)
        {
            if (oldFormat == newFormat)
            {
                Debug.WriteLine("No-op format change at +" + offset.ToString("x6") +
                                ": " + oldFormat);
            }

            // We currently allow old/new formats with different lengths.  There doesn't
            // seem to be a reason not to, and a slight performance advantage to doing so.
            // Also, if a change set has two changes at the same offset, undo requires
            // enumerating the list in reverse order.

            UndoableChange uc = new UndoableChange();

            uc.Type     = ChangeType.SetOperandFormat;
            uc.Offset   = offset;
            uc.OldValue = oldFormat;
            uc.NewValue = newFormat;

            // Data-only reanalysis is required if the old or new format has a label.  Simply
            // changing from e.g. default to decimal, or decimal to binary, doesn't matter.
            // (The format editing code ensures that labels don't appear in the middle of
            // a formatted region.)  Adding, removing, or changing a symbol can change the
            // layout of uncategorized data, affect data targets, xrefs, etc.
            //
            // We can't only check for a symbol, though, because Numeric/Address will
            // create an auto-label if the reference is within the file.
            //
            // If the number of bytes covered by the format changes, or we're adding or
            // removing a format, we need to redo the analysis of uncategorized data.  For
            // example, an auto-detected string could get larger or smaller.  We don't
            // currently have a separate flag for just that.  Also, because we're focused
            // on just one change, we can't skip reanalysis when (say) one 4-byte numeric
            // is converted to two two-byte numerics.
            if ((oldFormat != null && oldFormat.HasSymbolOrAddress) ||
                (newFormat != null && newFormat.HasSymbolOrAddress))
            {
                uc.ReanalysisRequired = ReanalysisScope.DataOnly;
            }
            else if (oldFormat == null || newFormat == null ||
                     oldFormat.Length != newFormat.Length)
            {
                uc.ReanalysisRequired = ReanalysisScope.DataOnly;
            }
            else
            {
                uc.ReanalysisRequired = ReanalysisScope.None;
            }
            return(uc);
        }
Example #4
0
        /// <summary>
        /// Creates an UndoableChange for an address map update.
        /// </summary>
        /// <param name="offset">Affected offset.</param>
        /// <param name="oldAddress">Previous address map entry, or -1 if none.</param>
        /// <param name="newAddress">New address map entry, or -1 if none.</param>
        /// <returns>Change record.</returns>
        public static UndoableChange CreateAddressChange(int offset, int oldAddress,
                                                         int newAddress)
        {
            if (oldAddress == newAddress)
            {
                Debug.WriteLine("No-op address change at +" + offset.ToString("x6") +
                                ": " + oldAddress);
            }
            UndoableChange uc = new UndoableChange();

            uc.Type               = ChangeType.SetAddress;
            uc.Offset             = offset;
            uc.OldValue           = oldAddress;
            uc.NewValue           = newAddress;
            uc.ReanalysisRequired = ReanalysisScope.CodeAndData;
            return(uc);
        }
Example #5
0
        /// <summary>
        /// Creates an UndoableChange for a note update.
        /// </summary>
        /// <param name="offset">Affected offset.</param>
        /// <param name="oldNote">Current note.</param>
        /// <param name="newNote">New note.</param>
        /// <returns>Change record.</returns>
        public static UndoableChange CreateNoteChange(int offset,
                                                      MultiLineComment oldNote, MultiLineComment newNote)
        {
            if (oldNote == newNote)
            {
                Debug.WriteLine("No-op note change at +" + offset.ToString("x6") +
                                ": " + oldNote);
            }

            UndoableChange uc = new UndoableChange();

            uc.Type               = ChangeType.SetNote;
            uc.Offset             = offset;
            uc.OldValue           = oldNote;
            uc.NewValue           = newNote;
            uc.ReanalysisRequired = ReanalysisScope.None;
            return(uc);
        }
Example #6
0
        /// <summary>
        /// Creates an UndoableChange for a long comment update.
        /// </summary>
        /// <param name="offset">Affected offset.</param>
        /// <param name="oldComment">Current comment.</param>
        /// <param name="newComment">New comment.</param>
        /// <returns>Change record.</returns>
        public static UndoableChange CreateLongCommentChange(int offset,
                                                             MultiLineComment oldComment, MultiLineComment newComment)
        {
            if (oldComment == newComment)
            {
                Debug.WriteLine("No-op long comment change at +" + offset.ToString("x6") +
                                ": " + oldComment);
            }

            UndoableChange uc = new UndoableChange();

            uc.Type               = ChangeType.SetLongComment;
            uc.Offset             = offset;
            uc.OldValue           = oldComment;
            uc.NewValue           = newComment;
            uc.ReanalysisRequired = ReanalysisScope.None;
            return(uc);
        }
Example #7
0
        /// <summary>
        /// Creates an UndoableChange for a status flag override update.
        /// </summary>
        /// <param name="offset">Affected offset.</param>
        /// <param name="oldFlags">Current flags.</param>
        /// <param name="newFlags">New flags.</param>
        /// <returns></returns>
        public static UndoableChange CreateStatusFlagChange(int offset, StatusFlags oldFlags,
                                                            StatusFlags newFlags)
        {
            if (oldFlags == newFlags)
            {
                Debug.WriteLine("No-op status flag change at " + offset);
            }
            UndoableChange uc = new UndoableChange();

            uc.Type     = ChangeType.SetStatusFlagOverride;
            uc.Offset   = offset;
            uc.OldValue = oldFlags;
            uc.NewValue = newFlags;
            // This can affect instruction widths (for M/X) and conditional branches.  We
            // don't need to re-analyze for changes to I/D, but users don't really need to
            // change those anyway, so it's not worth optimizing.
            uc.ReanalysisRequired = ReanalysisScope.CodeAndData;
            return(uc);
        }
Example #8
0
        /// <summary>
        /// Creates an UndoableChange for a type hint update.  Rather than adding a
        /// separate UndoableChange for each affected offset -- which could span the
        /// entire file -- we use range sets to record the before/after state.
        /// </summary>
        /// <param name="undoSet">Current values.</param>
        /// <param name="newSet">New values.</param>
        /// <returns>Change record.</returns>
        public static UndoableChange CreateTypeHintChange(TypedRangeSet undoSet,
                                                          TypedRangeSet newSet)
        {
            if (newSet.Count == 0)
            {
                Debug.WriteLine("Empty hint change?");
            }
            UndoableChange uc = new UndoableChange();

            uc.Type     = ChangeType.SetTypeHint;
            uc.Offset   = -1;
            uc.OldValue = undoSet;
            uc.NewValue = newSet;
            // Any hint change can affect whether something is treated as code.
            // Either we're deliberately setting it as code or non-code, or we're
            // setting it to "no hint", which means the code analyzer gets
            // to make the decision now.  This requires a full code+data re-analysis.
            uc.ReanalysisRequired = ReanalysisScope.CodeAndData;
            return(uc);
        }
Example #9
0
        /// <summary>
        /// Creates an UndoableChange for a change to the project properties.
        /// </summary>
        /// <param name="oldNote">Current note.</param>
        /// <param name="newNote">New note.</param>
        /// <returns>Change record.</returns>
        public static UndoableChange CreateProjectPropertiesChange(ProjectProperties oldProps,
                                                                   ProjectProperties newProps)
        {
            Debug.Assert(oldProps != null && newProps != null);
            if (oldProps == newProps)   // doesn't currently work except as reference check
            {
                Debug.WriteLine("No-op property change: " + oldProps);
            }

            UndoableChange uc = new UndoableChange();

            uc.Type     = ChangeType.SetProjectProperties;
            uc.Offset   = -1;
            uc.OldValue = oldProps;
            uc.NewValue = newProps;

            // Project properties could change the CPU type, requiring a full code+data
            // reanalysis.  We could scan the objects to see what actually changed, but that
            // doesn't seem worthwhile.
            uc.ReanalysisRequired = ReanalysisScope.CodeAndData;
            return(uc);
        }