1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-30 22:29:27 +00:00

Invoke extension scripts when labels they care about change

We were failing to update properly when a label changed if the label
was one that a plugin cared about.  The problem is that a label
add/remove operation skips the code analysis, and a label edit skips
everything but the display update.  Plugins only run during the code
analysis pass, so changes weren't being reflected in the display
list until something caused it to refresh.

The solution is to ask the plugin if the label being changed is one
that it cares about.  This allows the plugin to use the same
wildcard-match logic that it uses elsewhere.

For efficiency, and to reduce clutter in plugins that don't care
about symbols, a new interface class has been created to handle the
"here are the symbols" call and the "do you care about this label"
call.

The program in Examples/Scripts has been updated to show a very
simple single-call plugin and a slightly more complex multi-call
plugin.
This commit is contained in:
Andy McFadden 2019-10-13 18:19:28 -07:00
parent 3702448780
commit fac2d6a51f
18 changed files with 337 additions and 118 deletions

View File

@ -29,7 +29,7 @@ namespace PluginCommon {
string Identifier { get; }
/// <summary>
/// Prepares the plugin for action. Called at the start of the code analysis pass.
/// Prepares the plugin for action. Called at the start of every code analysis pass.
///
/// In the current implementation, the file data will be the same every time,
/// because it doesn't change after the project is opened. However, this could
@ -38,11 +38,44 @@ namespace PluginCommon {
/// <param name="appRef">Reference to application interface.</param>
/// <param name="fileData">65xx code and data.</param>
/// <param name="addrMap">Mapping between offsets and addresses.</param>
/// <param name="plSyms">Symbols available to plugins, in no particular order. All
/// platform, project, and user labels are included; auto-generated symbols and
/// local variables are not.</param>
void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans,
List<PlSymbol> plSyms);
void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans);
}
/// <summary>
/// Extension scripts that want to receive the list of symbols must implement this interface.
/// </summary>
public interface IPlugin_SymbolList {
/// <summary>
/// Receives a list of the currently defined platform, project, and user symbols.
/// The list does not include auto-generated labels or local variables.
///
/// This is called immediately after Prepare(), before any other interfaces are
/// invoked, at the start of every code analysis pass.
/// </summary>
/// <param name="plSyms">Symbols available to plugins, in no particular order.</param>
void UpdateSymbolList(List<PlSymbol> plSyms);
/// <summary>
/// Handles a notification that a user symbol has been added, edited, or removed. If the
/// label is of interest to the plugin, e.g. it changes how the plugin formats code or
/// data, the app needs to know.
/// </summary>
/// <remarks>
/// The application does a full re-analysis when project properties change, but not
/// when labels are edited. The CheckJsr/Jsl/Brk methods are only called during code
/// analysis, so if their behavior changes based on the presence or absence of a user
/// label then we need to tell the application that a full re-analysis is needed.
///
/// Plugins that don't care about user symbols, e.g. that just use tagged platform
/// symbols, can simply return false. (Changes to user labels that overlap with
/// project/platform symbols are detected by the app.)
/// </remarks>
/// <param name="beforeLabel">The label before the change, or empty if this is a
/// newly-added label.</param>
/// <param name="afterLabel">The label after the change, or empty if the label was
/// removed.</param>
/// <returns>True if the label change could affect the plugin's actions.</returns>
bool IsLabelSignificant(string beforeLabel, string afterLabel);
}
/// <summary>
@ -128,6 +161,9 @@ namespace PluginCommon {
/// <summary>
/// Data format type.
/// </summary>
/// <remarks>
/// Essentially a clone of FormatDescriptor.Type.
/// </remarks>
public enum DataType {
Unknown = 0,
NumericLE,
@ -145,6 +181,9 @@ namespace PluginCommon {
/// <summary>
/// Data format sub-type.
/// </summary>
/// <remarks>
/// Essentially a clone of FormatDescriptor.SubType.
/// </remarks>
public enum DataSubType {
// No sub-type specified.
None = 0,

View File

@ -154,15 +154,37 @@ namespace PluginCommon {
/// Invokes the Prepare() method on all active plugins.
/// </summary>
/// <param name="appRef">Reference to host object providing app services.</param>
/// <param name="addrEntries">Serialized AddressMap entries.</param>
/// <param name="plSyms">SymbolTable contents, converted to PlSymbol.</param>
public void PreparePlugins(IApplication appRef,
List<AddressMap.AddressMapEntry> addrEntries, List<PlSymbol> plSyms) {
AddressMap addrMap = new AddressMap(addrEntries);
AddressTranslate addrTrans = new AddressTranslate(addrMap);
foreach (KeyValuePair<string, IPlugin> kvp in mActivePlugins) {
kvp.Value.Prepare(appRef, mFileData, addrTrans, plSyms);
IPlugin ipl = kvp.Value;
ipl.Prepare(appRef, mFileData, addrTrans);
if (ipl is IPlugin_SymbolList) {
((IPlugin_SymbolList)ipl).UpdateSymbolList(plSyms);
}
}
}
/// <summary>
/// Returns true if any of the plugins report that the before or after label is
/// significant.
/// </summary>
public bool IsLabelSignificant(string labelBefore, string labelAfter) {
foreach (KeyValuePair<string, IPlugin> kvp in mActivePlugins) {
IPlugin ipl = kvp.Value;
if (ipl is IPlugin_SymbolList &&
((IPlugin_SymbolList)ipl).IsLabelSignificant(labelBefore,
labelAfter)) {
return true;
}
}
return false;
}
#if false
/// <summary>
/// DEBUG ONLY: establish a fast lease timeout. Normally the lease

View File

@ -1970,6 +1970,16 @@ namespace SourceGen {
// to do the refactor here, though we can skip Anattribs work.
Debug.Assert(oldValue == null || newValue == null);
}
// For add/edit/remove, we need to see if what we do will impact
// the behavior of a plugin. We don't need to do this on
// project/platform symbol changes because project property changes
// always update code and data.
if (mScriptManager.IsLabelSignificant((Symbol)oldValue,
(Symbol)newValue)) {
Debug.WriteLine("Plugin claims symbol is significant");
needReanalysis |= UndoableChange.ReanalysisScope.CodeAndData;
}
}
break;
case UndoableChange.ChangeType.SetOperandFormat: {

View File

@ -0,0 +1,74 @@
// Copyright 2019 faddenSoft. All Rights Reserved.
// See the LICENSE.txt file for distribution terms (Apache 2.0).
using System;
using System.Collections.Generic;
using PluginCommon;
namespace ExtensionScriptSample {
/// <summary>
/// Sample class for handling a JSR followed by a string prefixed with a 1-byte length.
/// </summary>
public class InlineL1String: MarshalByRefObject, IPlugin, IPlugin_SymbolList,
IPlugin_InlineJsr {
private IApplication mAppRef;
private byte[] mFileData;
// Only one call.
private const string CALL_LABEL = "PrintInlineL1String";
private int mInlineL1StringAddr; // jsr
public string Identifier {
get {
return "Inline L1 ASCII string handler";
}
}
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
mAppRef = appRef;
mFileData = fileData;
mAppRef.DebugLog("InlineL1String(id=" +
AppDomain.CurrentDomain.Id + "): prepare()");
}
public void UpdateSymbolList(List<PlSymbol> plSyms) {
// reset this every time, in case they remove the symbol
mInlineL1StringAddr = -1;
foreach (PlSymbol sym in plSyms) {
if (sym.Label == CALL_LABEL) {
mInlineL1StringAddr = sym.Value;
break;
}
}
mAppRef.DebugLog(CALL_LABEL + " @ $" + mInlineL1StringAddr.ToString("x6"));
}
public bool IsLabelSignificant(string beforeLabel, string afterLabel) {
return beforeLabel == CALL_LABEL || afterLabel == CALL_LABEL;
}
public void CheckJsr(int offset, out bool noContinue) {
noContinue = false;
int target = Util.GetWord(mFileData, offset + 1, 2, false);
if (target != mInlineL1StringAddr) {
return;
}
if (offset + 3 >= mFileData.Length) {
return; // length byte is off end
}
int len = mFileData[3]; // first byte past JSR
if (offset + 4 + len > mFileData.Length) {
mAppRef.DebugLog("L1 string ran off end of file at +" +
(offset + 4).ToString("x6"));
return;
}
// Assuming ASCII. This can be hard-coded, use auto-detection, or look
// up a value in a project constant.
mAppRef.SetInlineDataFormat(offset + 3, len + 1,
DataType.StringL8, DataSubType.Ascii, null);
}
}
}

View File

@ -1,69 +0,0 @@
// Copyright 2019 faddenSoft. All Rights Reserved.
// See the LICENSE.txt file for distribution terms (Apache 2.0).
using System;
using System.Collections.Generic;
using PluginCommon;
namespace ExtensionScriptSample {
/// <summary>
/// Sample class for handling a JSR followed by an inline null-terminated string.
/// </summary>
public class InlineNullStringHandler : MarshalByRefObject, IPlugin, IPlugin_InlineJsr {
private IApplication mAppRef;
private byte[] mFileData;
private int mInlineNullStringAddr; // jsr
public string Identifier {
get {
return "Inline null-terminated ASCII string handler";
}
}
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans,
List<PlSymbol> plSyms) {
mAppRef = appRef;
mFileData = fileData;
mAppRef.DebugLog("InlineNullStringHandler(id=" +
AppDomain.CurrentDomain.Id + "): prepare()");
// reset this every time, in case they remove the label
mInlineNullStringAddr = -1;
foreach (PlSymbol sym in plSyms) {
if (sym.Label == "PrintInlineZString") {
mInlineNullStringAddr = sym.Value;
break;
}
}
mAppRef.DebugLog("PrintInlineZString @ $" + mInlineNullStringAddr.ToString("x6"));
}
public void CheckJsr(int offset, out bool noContinue) {
noContinue = false;
int target = Util.GetWord(mFileData, offset + 1, 2, false);
if (target == mInlineNullStringAddr) {
// search for the terminating null byte
int nullOff = offset + 3;
while (nullOff < mFileData.Length) {
if (mFileData[nullOff] == 0) {
break;
}
nullOff++;
}
if (nullOff == mFileData.Length) {
mAppRef.DebugLog("Unable to find end of null-terminated string at +" +
(offset+3).ToString("x6"));
return;
}
// Assuming ASCII. This can be hard-coded, use auto-detection, or look
// up a value in a project constant.
mAppRef.SetInlineDataFormat(offset + 3, nullOff - (offset + 3) + 1,
DataType.StringNullTerm, DataSubType.Ascii, null);
}
}
}
}

View File

@ -0,0 +1,77 @@
// Copyright 2019 faddenSoft. All Rights Reserved.
// See the LICENSE.txt file for distribution terms (Apache 2.0).
using System;
using System.Collections.Generic;
using PluginCommon;
namespace ExtensionScriptSample {
/// <summary>
/// Sample class for handling a JSR followed by an inline null-terminated string. Any
/// label that starts with "PrintLineNullString" is matched.
/// </summary>
public class InlineNullTermString : MarshalByRefObject, IPlugin, IPlugin_SymbolList,
IPlugin_InlineJsr {
private IApplication mAppRef;
private byte[] mFileData;
private const string LABEL_PREFIX = "PrintInlineNullString";
private Dictionary<int, PlSymbol> mNullStringAddrs = new Dictionary<int, PlSymbol>();
public string Identifier {
get {
return "Inline null-terminated ASCII string handler";
}
}
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
mAppRef = appRef;
mFileData = fileData;
mAppRef.DebugLog("InlineNullStringHandler(id=" +
AppDomain.CurrentDomain.Id + "): prepare()");
}
public void UpdateSymbolList(List<PlSymbol> plSyms) {
mNullStringAddrs.Clear();
foreach (PlSymbol sym in plSyms) {
if (sym.Label.StartsWith(LABEL_PREFIX)) {
mNullStringAddrs.Add(sym.Value, sym);
}
}
mAppRef.DebugLog(LABEL_PREFIX + " matched " + mNullStringAddrs.Count + " labels");
}
public bool IsLabelSignificant(string beforeLabel, string afterLabel) {
return beforeLabel.StartsWith(LABEL_PREFIX) || afterLabel.StartsWith(LABEL_PREFIX);
}
public void CheckJsr(int offset, out bool noContinue) {
noContinue = false;
int target = Util.GetWord(mFileData, offset + 1, 2, false);
if (!mNullStringAddrs.ContainsKey(target)) {
return;
}
// search for the terminating null byte
int nullOff = offset + 3;
while (nullOff < mFileData.Length) {
if (mFileData[nullOff] == 0) {
break;
}
nullOff++;
}
if (nullOff == mFileData.Length) {
mAppRef.DebugLog("Unable to find end of null-terminated string at +" +
(offset+3).ToString("x6"));
return;
}
// Assuming ASCII. This can be hard-coded, use auto-detection, or look
// up a value in a project constant.
mAppRef.SetInlineDataFormat(offset + 3, nullOff - (offset + 3) + 1,
DataType.StringNullTerm, DataSubType.Ascii, null);
}
}
}

Binary file not shown.

View File

@ -1,8 +1,18 @@
org $1000
jsr PrintInlineZString
asc 'Testing',00
jsr PrintInlineL1String
str 'How long?'
jsr PrintInlineZString1
asc 'Test one',00
jsr PrintInlineZString2
asc 'Test two',00
rts
PrintInlineZString
PrintInlineL1String
rts
PrintInlineZString1
rts
PrintInlineZString2
rts

View File

@ -1,9 +1,9 @@
### 6502bench SourceGen dis65 v1.0 ###
{
"_ContentVersion":2,"FileDataLength":13,"FileDataCrc32":205674068,"ProjectProps":{
"CpuName":"65816","IncludeUndocumentedInstr":false,"EntryFlags":32702671,"AutoLabelStyle":"Simple","AnalysisParams":{
"_ContentVersion":2,"FileDataLength":41,"FileDataCrc32":-1863359703,"ProjectProps":{
"CpuName":"6502","IncludeUndocumentedInstr":false,"TwoByteBrk":false,"EntryFlags":32702671,"AutoLabelStyle":"Simple","AnalysisParams":{
"AnalyzeUncategorizedData":true,"DefaultTextScanMode":"LowHighAscii","MinCharsForString":4,"SeekNearbyTargets":true,"SmartPlpHandling":true},
"PlatformSymbolFileIdentifiers":[],"ExtensionScriptFileIdentifiers":["PROJ:InlineNullTerm.cs"],"ProjectSyms":{
"PlatformSymbolFileIdentifiers":[],"ExtensionScriptFileIdentifiers":["PROJ:InlineL1String.cs","PROJ:InlineNullTermString.cs"],"ProjectSyms":{
}},
"AddressMap":[{
"Offset":0,"Addr":4096}],"TypeHints":[{
@ -16,8 +16,12 @@
"Notes":{
},
"UserLabels":{
"12":{
"Label":"PrintInlineZString","Value":4108,"Source":"User","Type":"LocalOrGlobalAddr"}},
"38":{
"Label":"PrintInlineL1String","Value":4134,"Source":"User","Type":"LocalOrGlobalAddr"},
"39":{
"Label":"PrintInlineNullString1","Value":4135,"Source":"User","Type":"LocalOrGlobalAddr"},
"40":{
"Label":"PrintInlineNullString2","Value":4136,"Source":"User","Type":"LocalOrGlobalAddr"}},
"OperandFormats":{
},
"LvTables":{

View File

@ -34,7 +34,7 @@ using PluginCommon;
*/
namespace RuntimeData.Apple {
public class GSOS : MarshalByRefObject, IPlugin, IPlugin_InlineJsl {
public class GSOS : MarshalByRefObject, IPlugin, IPlugin_SymbolList, IPlugin_InlineJsl {
private const string GSOS_FUNC_TAG = "AppleIIgs-GSOS-Functions"; // tag used in .sym65 file
private bool VERBOSE = false;
@ -48,15 +48,21 @@ namespace RuntimeData.Apple {
}
}
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans,
List<PlSymbol> plSyms) {
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
mAppRef = appRef;
mFileData = fileData;
mAppRef.DebugLog("GSOS(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
//System.Diagnostics.Debugger.Break();
mFunctionList = PlSymbol.GeneratePlatformValueList(plSyms, GSOS_FUNC_TAG, appRef);
}
public void UpdateSymbolList(List<PlSymbol> plSyms) {
// Extract the list of function name constants from the platform symbol file.
mFunctionList = PlSymbol.GeneratePlatformValueList(plSyms, GSOS_FUNC_TAG, mAppRef);
}
public bool IsLabelSignificant(string beforeLabel, string afterLabel) {
return false;
}
public void CheckJsl(int offset, out bool noContinue) {

View File

@ -27,8 +27,8 @@ using PluginCommon;
*/
namespace RuntimeData.Apple {
public class IIgsToolbox : MarshalByRefObject, IPlugin, IPlugin_InlineJsl {
private const string TOOLBOX_FUNC_TAG = "AppleIIgs-Toolbox-Functions"; // tag used in .sym65 file
public class IIgsToolbox : MarshalByRefObject, IPlugin, IPlugin_SymbolList, IPlugin_InlineJsl {
private const string TOOLBOX_FUNC_TAG = "AppleIIgs-Toolbox-Functions"; // tag used in .sym65 file
private bool VERBOSE = false;
private IApplication mAppRef;
@ -41,14 +41,19 @@ namespace RuntimeData.Apple {
}
}
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans,
List<PlSymbol> plSyms) {
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
mAppRef = appRef;
mFileData = fileData;
mAppRef.DebugLog("IIgsToolbox(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
}
mFunctionList = PlSymbol.GeneratePlatformValueList(plSyms, TOOLBOX_FUNC_TAG, appRef);
public void UpdateSymbolList(List<PlSymbol> plSyms) {
// Extract the list of function name constants from the platform symbol file.
mFunctionList = PlSymbol.GeneratePlatformValueList(plSyms, TOOLBOX_FUNC_TAG, mAppRef);
}
public bool IsLabelSignificant(string beforeLabel, string afterLabel) {
return false;
}
public void CheckJsl(int offset, out bool noContinue) {

View File

@ -29,7 +29,7 @@ parm_block
*/
namespace RuntimeData.Apple {
public class ProDOS8 : MarshalByRefObject, IPlugin, IPlugin_InlineJsr {
public class ProDOS8 : MarshalByRefObject, IPlugin, IPlugin_SymbolList, IPlugin_InlineJsr {
private const string P8_MLI_TAG = "ProDOS8-MLI-Functions"; // tag used in .sym65 file
private bool VERBOSE = false;
@ -161,8 +161,7 @@ namespace RuntimeData.Apple {
}
}
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans,
List<PlSymbol> plSyms) {
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
mAppRef = appRef;
mFileData = fileData;
mAddrTrans = addrTrans;
@ -170,8 +169,13 @@ namespace RuntimeData.Apple {
mAppRef.DebugLog("ProDOS(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
//System.Diagnostics.Debugger.Break();
}
public void UpdateSymbolList(List<PlSymbol> plSyms) {
// Extract the list of function name constants from the platform symbol file.
mFunctionList = PlSymbol.GeneratePlatformValueList(plSyms, P8_MLI_TAG, appRef);
mFunctionList = PlSymbol.GeneratePlatformValueList(plSyms, P8_MLI_TAG, mAppRef);
}
public bool IsLabelSignificant(string beforeLabel, string afterLabel) {
return false;
}
public void CheckJsr(int offset, out bool noContinue) {

View File

@ -29,7 +29,7 @@ parm_block
*/
namespace RuntimeData.Apple {
public class SOS : MarshalByRefObject, IPlugin, IPlugin_InlineBrk {
public class SOS : MarshalByRefObject, IPlugin, IPlugin_SymbolList, IPlugin_InlineBrk {
private const string SOS_MLI_TAG = "SOS-MLI-Functions"; // tag used in .sym65 file
private bool VERBOSE = true;
@ -43,15 +43,20 @@ namespace RuntimeData.Apple {
}
}
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans,
List<PlSymbol> plSyms) {
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
mAppRef = appRef;
mFileData = fileData;
mAppRef.DebugLog("SOS(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
//System.Diagnostics.Debugger.Break();
}
mFunctionList = PlSymbol.GeneratePlatformValueList(plSyms, SOS_MLI_TAG, appRef);
public void UpdateSymbolList(List<PlSymbol> plSyms) {
// Extract the list of function name constants from the platform symbol file.
mFunctionList = PlSymbol.GeneratePlatformValueList(plSyms, SOS_MLI_TAG, mAppRef);
}
public bool IsLabelSignificant(string beforeLabel, string afterLabel) {
return false;
}
public void CheckBrk(int offset, bool twoByteBrk, out bool noContinue) {

View File

@ -115,13 +115,6 @@ invoked is not defined.</p>
<h4>Known Issues and Limitations</h4>
<p>Sometimes a manual refresh (F5) is required. Plugins are executed during
the code analysis pass, but SourceGen doesn't perform code analysis on
every change. If you add or change a label that a plugin is looking
for, you won't see the effects until you do something that causes the
code analysis pass to be run. Hitting F5 does this. (There's no easy
way around this -- either we have to re-run code analysis on every label
change, or we need a way to know which labels a plugin is interested in.)</p>
<p>When a project is opened, any errors encountered by the script compiler
are reported to the user. If the project is already open, and a script
is added to the project through the Project Properties editor, compiler

View File

@ -17,8 +17,7 @@ namespace RuntimeData.Test2011 {
}
}
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans,
List<PlSymbol> plSyms) {
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
mAppRef = appRef;
mFileData = fileData;

View File

@ -7,7 +7,8 @@ using System.Collections.Generic;
using PluginCommon;
namespace RuntimeData.Test2022 {
public class Test2022A : MarshalByRefObject, IPlugin, IPlugin_InlineJsr, IPlugin_InlineJsl {
public class Test2022A : MarshalByRefObject, IPlugin, IPlugin_SymbolList,
IPlugin_InlineJsr, IPlugin_InlineJsl {
private IApplication mAppRef;
private byte[] mFileData;
@ -24,13 +25,13 @@ namespace RuntimeData.Test2022 {
}
}
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans,
List<PlSymbol> plSyms) {
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
mAppRef = appRef;
mFileData = fileData;
mAppRef.DebugLog("Test2022-A(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
}
public void UpdateSymbolList(List<PlSymbol> plSyms) {
foreach (PlSymbol sym in plSyms) {
switch (sym.Label) {
case "PrintInline8String":
@ -55,6 +56,11 @@ namespace RuntimeData.Test2022 {
}
}
public bool IsLabelSignificant(string beforeLabel, string afterLabel) {
const string PREFIX = "PrintInline"; // all interesting labels start with this
return (beforeLabel.StartsWith(PREFIX) || afterLabel.StartsWith(PREFIX));
}
public void CheckJsr(int offset, out bool noContinue) {
noContinue = false;
int target = Util.GetWord(mFileData, offset + 1, 2, false);
@ -99,6 +105,9 @@ namespace RuntimeData.Test2022 {
if (target == mInlineL1StringAddr) {
// 0 1 2 3 4 5
// 22 00 10 01 01 66
if (offset + 4 >= mFileData.Length) {
return; // length byte is off end
}
int len = mFileData[offset + 4]; // 1-byte len in first byte past 4-byte JSL
if (offset + 5 + len > mFileData.Length) {
// ran off the end
@ -109,6 +118,9 @@ namespace RuntimeData.Test2022 {
mAppRef.SetInlineDataFormat(offset + 4, len + 1,
DataType.StringL8, DataSubType.Ascii, null);
} else if (target == mInlineL2StringAddr) {
if (offset + 5 >= mFileData.Length) {
return; // length word is off end
}
int len = Util.GetWord(mFileData, offset + 4, 2, false);
if (offset + 6 + len > mFileData.Length) {
// ran off the end
@ -118,7 +130,7 @@ namespace RuntimeData.Test2022 {
}
mAppRef.SetInlineDataFormat(offset + 4, len + 2,
DataType.StringL16, DataSubType.Ascii, null);
} else {
} else if (target == mInlineDciStringAddr) {
// look for the first byte whose high bit doesn't match the first byte's bit
// 0 1 2 3 4 5
// 22 00 30 01 66 c1

View File

@ -18,8 +18,7 @@ namespace RuntimeData.Test2022 {
}
}
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans,
List<PlSymbol> plSyms) {
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
mAppRef = appRef;
mFileData = fileData;
mAddrTrans = addrTrans;

View File

@ -161,7 +161,11 @@ namespace SourceGen.Sandbox {
if (DomainMgr == null) {
AddressTranslate addrTrans = new AddressTranslate(mProject.AddrMap);
foreach (KeyValuePair<string, IPlugin> kvp in mActivePlugins) {
kvp.Value.Prepare(appRef, mProject.FileData, addrTrans, plSyms);
IPlugin ipl = kvp.Value;
ipl.Prepare(appRef, mProject.FileData, addrTrans);
if (ipl is IPlugin_SymbolList) {
((IPlugin_SymbolList)ipl).UpdateSymbolList(plSyms);
}
}
} else {
List<AddressMap.AddressMapEntry> addrEnts = mProject.AddrMap.GetEntryList();
@ -169,6 +173,28 @@ namespace SourceGen.Sandbox {
}
}
/// <summary>
/// Returns true if any of the plugins report that the before or after label is
/// significant.
/// </summary>
public bool IsLabelSignificant(Symbol before, Symbol after) {
string labelBefore = (before == null) ? string.Empty : before.Label;
string labelAfter = (after == null) ? string.Empty : after.Label;
if (DomainMgr == null) {
foreach (KeyValuePair<string, IPlugin> kvp in mActivePlugins) {
IPlugin ipl = kvp.Value;
if (ipl is IPlugin_SymbolList &&
((IPlugin_SymbolList)ipl).IsLabelSignificant(labelBefore,
labelAfter)) {
return true;
}
}
return false;
} else {
return DomainMgr.PluginMgr.IsLabelSignificant(labelBefore, labelAfter);
}
}
/// <summary>
/// Gathers a list of platform symbols from the project's symbol table.
/// </summary>
@ -261,6 +287,9 @@ namespace SourceGen.Sandbox {
// The plugin is actually a MarshalByRefObject, so we can't use reflection
// to gather the list of interfaces.
// TODO(maybe): add a call that does the query on the remote site
if (plugin is PluginCommon.IPlugin_SymbolList) {
sb.Append(" SymbolList");
}
if (plugin is PluginCommon.IPlugin_InlineJsr) {
sb.Append(" InlineJsr");
}