gpt4 book ai didi

debugging - 调试PostScript

转载 作者:行者123 更新时间:2023-12-03 23:20:59 30 4
gpt4 key购买 nike

如何在PostScript中进行调试?我可以在Linux上使用GhostView / GhostScript,但无法查看堆栈,字典等。

最佳答案

最小调试器

我刚刚发现了一个非常有用的技巧。

<<
/break{ /hook /pause load store }
/cont{ /hook {} store }
/doprompt{
(\nbreak>)print
flush(%lineedit)(r)file
cvx {exec}stopped pop }
/pause{ doprompt }
/hook{}
>> begin


这是一个8行的EMBEDDABLE调试器。我为 8086 emulator做饭。将 hook放入主循环中,将 break放入一个过程中,以在下一个钩子上触发暂停(我将其放入可疑的OPCODE proc中,并且钩子在中断生效的位置)。挂机呼叫暂停和暂停呼叫 doprompt,这将为您提供单行“ break>”提示。在此处键入 cont将清除钩子并继续旋转,直到遇到另一个 break为止,不执行任何暂停。您也可以在提示符下检查值并执行代码,但请注意。当您按Enter键时,执行恢复,因此,如果您需要其他行,请在该行的末尾调用 dopromptpause。执行命令时将忽略错误(您不希望调试器使程序崩溃,这很愚蠢!)。我想我可以结合使用“暂停”和“提示”来消除名字。但是这里的目标不是提高机器效率,而是清晰地收集概念:此代码对于调试其他代码非常有用,需要易于扫描和验证。

这是怎么一个调试器,它只读取一行?

记住,您有 ===来调查值。 forallget破坏数组和内容。要真正找出您所在的位置,请对整个caboodle进行可读的转储 countexecstack array execstack ==。也就是说,执行堆栈中当前位置的回溯,其中包含所有部分执行的过程和文件的尾部,当当前帧返回时,这些尾部等待恢复。



“ printf”

仅通过对程序进行检测(可以说添加 printf),无需调试器本身就可以完成很多调试工作。

刚才我遇到了一个错误,我的调试器无法帮助我,因为调试器本身在某些过于聪明的事情上崩溃了,例如

/E [ 0 0 10 ] def %eye point
/crackE { % set pointers into E
/ex E 0 1 getinterval cvx def
/ey E 1 1 getinterval cvx def
/ez E 2 1 getinterval cvx def
} def crackE


所以我调查的实际错误是

GPL Ghostscript 8.62 (2008-02-29)
Copyright (C) 2008 Artifex Software, Inc. All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Error: /stackunderflow in --forall--
Operand stack:
--nostringval--
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1905 1 3 %oparray_pop 1904 1 3 %oparray_pop 1888 1 3 %oparray_pop 1771 1 3 %oparray_pop --nostringval-- %errorexec_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- 0.238095 0.047619 0.952381 --nostringval-- %for_real_continue 68.5714 17.1429 360.048 --nostringval-- %for_real_continue --nostringval--
Dictionary stack:
--dict:1151/1684(ro)(G)-- --dict:0/20(G)-- --dict:121/200(L)-- --dict:13/20(L)-- --dict:1/2(L)--
Current allocation mode is local
Last OS error: 2
Current file position is 3241
GPL Ghostscript 8.62: Unrecoverable error, exit code 1


我真正需要知道的是操作数堆栈上的 --nostringval--实际是什么。

所以我把它放在程序的开始

/forall { pstack()= forall } bind def


并再次运行它

{MO matmul 0 --get-- --aload-- --pop-- proj action}Error: /stackunderflow in --forall--Operand stack:   --nostringval--...

Just before the error is the final stackdump (using ==) which tells me that I have a procedure body missing its dataset.

pstack is a bit blunt compared to something like this

/args { dup 1 add copy -1 1 { -1 roll ==only ( ) print } for } def
/forall { 2 args (forall)= forall } bind def


这对于在看似有效的代码中跟踪错误数据将更为有用。这也是Distiller的早期版本通过仅定义绘图操作来生成优化的.ps文件的方式。
为了抛弃自己,其余的计算将被“蒸馏掉”。

一些技巧

()= %print a newline
=string %built-in 128-byte buffer used by = and ==
/object =string cvs print %convert object to string and print without newline
/stack { count dup 1 add copy { = } repeat pop } def % this is the code for the stack operator
66 (#) dup 0 3 index put print %m non-destructively print a "char"


[我在前面写了'='而不是'stack'。严重的错误。编辑:将缺少的 pop添加到 /stack。]



errordict骇客

研究错误的另一种方法是更改​​错误处理程序。为了研究上述的 /stackunderflow错误,我可以使用

errordict/stackunderflow{dup == /stackunderflow signalerror}put


而不是专门 forall。要了解后记的这个相当神秘的方面,请阅读 errordict stopstopped。并以交互方式看一下 errordict{exch =only ==}forall。 ghostscript中的 signalerror在Adobe解释器中称为 .error。它的工作是获取堆栈的快照,然后调用 stop弹出执行堆栈。因此,此处的 dup ==和上面的 pstack本质上是错误的相同“时刻”,位于 stop之前。您的交互式会话(以及之前处于gs正常模式下的程序)在exec堆栈中用 //your-program stopped { handleerror } if括起来更深的括号。 handleerror使用快照(以其他方式清除程序后)以错误的堆栈打印输出来打印错误报告。

您可以找到 handleerror的替代品,您可以在错误程序的开头 (ehandle.ps)run来生成不同样式的错误报告。

检查$ error

我刚刚在这里重新阅读示例时发现了这一点。如果解释器仍在提示您,您还可以在错误发生后检查堆栈。错误信息将保存在 $error词典中,包括堆栈的快照。

GS>[ 1 2 3 ] [4 5 6] bogus
Error: /undefined in bogus
Operand stack:
--nostringval-- --nostringval--
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- %loop_continue --nostringval-- --nostringval-- false 1 %stopped_push .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval--
Dictionary stack:
--dict:1168/1684(ro)(G)-- --dict:0/20(G)-- --dict:77/200(L)--
Current allocation mode is local
Current file position is 24
GS<2>

GS<2>$error{pop ==}forall
/dstack
/recordstacks
/globalmode
/newerror
/.nosetlocal
/estack
/errorinfo
/.inerror
/SubstituteFont
/position
/binary
/ostack
/command
/errorname
GS<2>$error/ostack get ==
[[1 2 3] [4 5 6]]
GS<2>


当然,这里的对象仍在堆栈中。但是 $error在那里可以窥见。不要尝试以下操作: $error ===。 TMI。

您可以从 $error获得的非常有用的信息是 /estack的精美印刷品,即错误点处执行堆栈的副本。

PS<3>$error /estack get ==
[ --quit--{ pop --quit--} false { quitflag false --def---dict- /
execdepth 2 --copy----get--1 --sub----put----end---dict- /doclose false
--put--interrupt } --loop----cvx--[ /quitflag false --def---dict- /
newerror false --put--/prompt --load----stopped--{ (
Error during prompt execution
)--print--handleerror --exit--} --if--{
mark /stmtfile (%statementedit)(r)--file----def--} --stopped--{ --
cleartomark---dict- /newerror --get--{ -dict- /errorname --get--/
undefinedfilename --ne--{ handleerror } --if---dict- /newerror false --
put----exit--} --if--} { --pop--stmtfile --end--{ --cvx----exec--} --
stopped---dict- --begin--{ handleerror stmtfile --closefile--} --if--}
--ifelse--checkquit ] { checkquit } { -dict- --begin--{ handleerror
stmtfile --closefile--} --if--} false -file- -file- -file- --repeat----
cvx--[ randcurve randwidth randcolor stroke ] 1 { flushpage newpath } {
newpath } --forall----cvx--[ dup length 2 gt { [ currentcolordict DEVICE
/nativecolorspace get get exec counttomark 2 add -1 roll DEVICE dup /
FillPoly get exec pop pstack ()= flushpage } { pop } ifelse ] [ ] { pop
pstack ()= flushpage } { x_max width 0.50 add def (
intersect polygon edges with scanlines)= /P poly poly length 1 sub get
def [ poly { Q exch def x_max miny floor cvi 0.50 add 1 maxy ceiling cvi
0.50 sub { 1 index exch -0.50 1 index 4 2 roll P aload pop Q aload pop
.intersect { 2 array astore exch } if } for pop /P Q def } forall ] (
sort scanline intersection list)= dup { 1 index 1 get 1 index 1 get eq
{ exch 0 get exch 0 get lt } { exch 1 get exch 1 get lt } ifelse } qsort
(set pixels on each scanline)= aload length 2 idiv { exch aload pop 3 2
roll aload pop /USEDRAWLINE where { pop r g b 7 3 roll currentdict
DrawLine } { pop 3 2 roll exch 1 exch dup width ge { pop width 1 sub }
if { r g b 4 3 roll 2 index currentdict PutPix } for pop } ifelse }
repeat end } --forall----cvx--[ aload pop .maxmin ] [ [ 16 154 ] [ 16
154 ] ] { pop .maxmin } ]
PS<3>


现在,大多数内容可能会变得乱七八糟,而最上面的几篇甚至可能都不可读。此输出来自我自己的Postscript解释器,该解释器正在构建中,所有对象都具有完全访问权限。但是不要看顶部。看底部。数组的最后一个元素是堆栈的最高元素。如果没有 /command并没有完成 /errorname,那么接下来的代码片段。那个小的后记片段可以帮助您找到问题所在的源。在上述情况下,无论错误是什么,我都需要在源中搜索以 .maxmin开头,以 pop开头,..开头的调用。

致电 executive以获得提示

如果您与打印机中的解释器进行串行或telnet会话,则可以键入 executive并按回车几次。键入时,它可能不会回显 executive的字母。不要害怕,但要正确拼写。它应该给您打招呼和提示。

使用ghostscript,不带参数运行程序将为您提供相同类型的执行会话。然后,您可以 (yourfile)run,并且在出现错误后仍应获得提示,从而可以如上所述检查$ error。

如果这不起作用,则可以尝试两次运行 executive。这增加了错误处理的额外级别(exec堆栈上的另一个 stopped {handlerror} if)。这可能有助于寻找更多奇怪的错误。

逐步调试器

我有一个 source-level stepwise debugger,它可以在任何符合Level 2的PostScript解释器中运行。

answer on TeX.SE所示,它也可以用于生成堆栈跟踪。

关于debugging - 调试PostScript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12379122/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com