我正在使用 RemObjects(优秀)的 PascalScript 和 SynEdit 编辑器创建一个内置脚本引擎。使用 PascalScript 附带的 IDE 示例和 SynEdit 中的 IDE 示例几乎完成了 - 但是 - 我看不到如何询问 PascalScript 编号的源代码行是否“可执行”。(然后我可以使用它用“Delphi 蓝点”标记 SynEdit 排水沟)。我想我可能需要对 ROPS 输出进行反汇编?
这里有 PascalScript 专家吗?谢谢。布赖恩。
我正在使用 RemObjects(优秀)的 PascalScript 和 SynEdit 编辑器创建一个内置脚本引擎。使用 PascalScript 附带的 IDE 示例和 SynEdit 中的 IDE 示例几乎完成了 - 但是 - 我看不到如何询问 PascalScript 编号的源代码行是否“可执行”。(然后我可以使用它用“Delphi 蓝点”标记 SynEdit 排水沟)。我想我可能需要对 ROPS 输出进行反汇编?
这里有 PascalScript 专家吗?谢谢。布赖恩。
查看Inno Setup的源代码。它确实在 SynEdit 装订线区域中显示了一个小点,用于表示具有可执行代码的行,灰色表示可执行但尚未执行的行,绿色表示已被命中至少一次的行。
可以在 中找到此代码CompForm.pas
,查找TLineState
类型。该信息是在iscbNotifySuccess
编译器回调的状态下设置的,您可以在 IDE 中执行相同的操作。您可能需要调整代码以处理多个源文件,因为 Inno Setup 编译器仅处理单个源文件中的代码片段。
在 Pascal 脚本源中,您应该查看该TPSCustomDebugExec.TranslatePositionEx()
方法 - 它也确实返回源文件的名称。
我不知道它到底是怎么做的,但是 PascalScript 包中的 IDE 项目(在 \samples\debug 下找到)能够提供 Step Into 和 Step Over(F7 和 F8)功能,所以从逻辑上讲它必须有一些将 PS 字节码与脚本代码行关联的方式。试着检查那个项目,看看它是如何做到的。作为奖励,它也使用 SynEdit,因此这些想法很容易适应您自己的系统。
我知道这是一个老问题,但我自己一直在做同样的事情,上面的建议并没有真正帮助。例如 Inno setup 不使用 Synedit,它使用 scintilla 编辑器。
TPSCustomDebugExec.TranslatePositionEx() 也与想要的相反,它从运行时代码位置提供源行号。
在闲逛了一段时间后,我得出结论,最简单的方法是在 Pascalscript 代码中添加一个函数。
新方法被添加到 uPSdebugger 单元中的 TPSCustomDebugExec 类中。
function TPSCustomDebugExec.HasCode(Filename:string; LineNo:integer):boolean;
var i,j:integer; fi:PFunctionInfo; pt:TIfList; r:PPositionData;
begin
result:=false;
for i := 0 to FDebugDataForProcs.Count -1 do
begin
fi := FDebugDataForProcs[i];
pt := fi^.FPositionTable;
for j := 0 to pt.Count -1 do
begin
r:=pt[j];
result:= SameText(r^.FileName,Filename) and (r^.Row=LineNo);
if result then exit
end;
end;
end;
主编辑器窗体中的油漆槽回调如下
procedure Teditor.PaintGutterGlyphs(ACanvas:TCanvas; AClip:TRect;
FirstLine, LastLine: integer);
var a,b:boolean; LH,LH2,X,Y,ImgIndex:integer;
begin
begin
FirstLine := Ed.RowToLine(FirstLine);
LastLine := Ed.RowToLine(LastLine);
X := 14;
LH := Ed.LineHeight;
LH2:=(LH-imglGutterGlyphs.Height) div 2;
while FirstLine <= LastLine do
begin
Y := LH2+LH*(Ed.LineToRow(FirstLine)-Ed.TopLine);
a:= ce.HasBreakPoint(ce.MainFileName,FirstLine);
b:= ce.Exec.HasCode(ce.MainFileName,FirstLine);
if Factiveline=FirstLine then
begin
if a then
ImgIndex := 2 //Blue arrow+red dot (breakpoint and execution point)
else
ImgIndex := 1; //Blue arrow (current line execution point)
end
else
if b then
begin
if a then
ImgIndex := 3 //Valid Breakpoint marker
else
ImgIndex := 0; //blue dot (has code)
end
else
begin
if a then
ImgIndex := 4 //Invalid breakpoint (No code on this line)
else
ImgIndex := -1; //Empty (No code for line)
end;
if ImgIndex >= 0 then
imglGutterGlyphs.Draw(ACanvas, X,Y,ImgIndex);
Inc(FirstLine);
end;
end;
end;
带有行号、代码点、断点、书签和执行点的 Synedit 如下图所示