Debugging 调试后记
如何在PostScript中进行调试?我可以在Linux上使用GhostView/GhostScript,但我不能查看堆栈、字典等。Emacs包括PostScript工具。它包括用于向postscript解释器发送当前选定文本的工具,您还可以直接向同一解释器输入命令,例如查询操作数堆栈等 不过,这可能不是您想要的,因为它可能比您愿意使用的更难使用。但是,正确地设置,为您想要监视的所有事情使用不同的缓冲区,脚本和宏来执行操作,等等,它将完成您想要的所有事情。我不确定,但是网络上可能有其他东西可以帮助你设置它 编辑:我使用Emacs调试postscript的主要方法是执行以下操作: 我可以将程序的粘贴段从文件缓冲区复制到解释器缓冲区,作为一种逐步完成程序的方法。我还可以使用它来告诉我有关操作数堆栈的事情,使用命令打印其内容等等。我还可以将调试语句添加到将输出到解释器缓冲区的代码中(如Debugging 调试后记,debugging,postscript,Debugging,Postscript,如何在PostScript中进行调试?我可以在Linux上使用GhostView/GhostScript,但我不能查看堆栈、字典等。Emacs包括PostScript工具。它包括用于向postscript解释器发送当前选定文本的工具,您还可以直接向同一解释器输入命令,例如查询操作数堆栈等 不过,这可能不是您想要的,因为它可能比您愿意使用的更难使用。但是,正确地设置,为您想要监视的所有事情使用不同的缓冲区,脚本和宏来执行操作,等等,它将完成您想要的所有事情。我不确定,但是网络上可能有其他东西可以帮
dup==
等),因为在使用其他环境执行程序时,我有点不知道如何查看stdout
。minimal debugger
我刚刚发现了一个非常有用的黑客
<<
/break{ /hook /pause load store }
/cont{ /hook {} store }
/doprompt{
(\nbreak>)print
flush(%lineedit)(r)file
cvx {exec}stopped pop }
/pause{ doprompt }
/hook{}
>> begin
所以我调查的实际错误是
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--
...
这对于跟踪显然正在工作的代码中的错误数据更有用。这也是早期版本的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
]
错误入侵 调查错误的另一种方法是更改错误处理程序。为了调查上述
/stackunderflow
错误,我可以使用
errordict/stackunderflow{dup == /stackunderflow signalerror}put
而不是专门针对所有的。要了解postscript这个相当神秘的方面,请阅读errordict
stop
和stopped
。以交互方式,查看所有的errordict{exch=only==}signalerror
在Adobe解释器中被称为。error
。它的工作是获取堆栈的快照,然后调用stop
弹出exec堆栈。因此这里的dup==
和上面的pstack
基本上是相同的错误“时刻”,在停止之前。您的交互式会话(以及gs的正常模式下的前一个程序)在exec堆栈上被更深入地括起来,等价于//您的程序停止了{handleerror}(如果
)。它是handleerror
,它使用快照(在清除程序后)打印错误报告及其非信息堆栈打印输出
您可以为handleerror
找到一些替换项,您可以在出错程序的开始运行(ehandle.ps)以生成不同样式的错误报告
检查$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>
现在大部分内容可能都是胡言乱语,最上面的几篇文章甚至可能不可读。此输出来自我自己的postscript解释器,该解释器正在构建中,所有对象都具有完全访问权限。但是不要看上面。看看底部。数组的最后一个元素是堆栈的最顶层元素。如果/command
没有执行/errorname
,接下来就会出现这段代码。这个小postscript片段可以帮助您找到问题所在的源代码。在我上面的例子中,我需要在源代码中搜索对.maxmin
的调用,前面是pop
前面是。。不管是什么错误
致电executive
获取提示
如果您与打印机中的解释器进行串行或远程登录会话,则可以键入executive
,然后按几次enter键。在您键入时,它可能不会回显executive
的字母。不要害怕,但是拼写正确。它会给你一个问候和提示
使用ghostscript,在没有参数的情况下运行程序将提供相同类型的执行会话。然后,您可以运行(您的文件)
,在出现错误后仍然会得到提示,允许您如上所述检查$error
如果这不起作用,您可以尝试运行executive
两次。这增加了一个额外的错误处理级别(如果exec堆栈上的
已停止{handlerror})。这可能有助于寻找更奇怪的错误
分步调试器
我有一个可用的,应该在任何2级兼容PostScript解释器中运行的
它还可以用来生成堆栈跟踪,如图所示。在OS X 10.7.5上,预览没有提供爆炸时的详细信息,但是/usr/bin/pstopdf
确实给了我一个堆栈转储到stdout,这也是pstack
的地方
如果我在预览中打开pdf文件,则在运行pstopdf
后更改回预览将刷新新创建pdf文件的视图
这不是高科技,但你可以快速迭代。你看到了吗?你看到了吗?有了vi,我可以运行文件(:!gs%
);运行一行,捕获输出(errordict/stackunderflow{dup == /stackunderflow signalerror}put
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>
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>