Debugging 调试后记

Debugging 调试后记,debugging,postscript,Debugging,Postscript,如何在PostScript中进行调试?我可以在Linux上使用GhostView/GhostScript,但我不能查看堆栈、字典等。Emacs包括PostScript工具。它包括用于向postscript解释器发送当前选定文本的工具,您还可以直接向同一解释器输入命令,例如查询操作数堆栈等 不过,这可能不是您想要的,因为它可能比您愿意使用的更难使用。但是,正确地设置,为您想要监视的所有事情使用不同的缓冲区,脚本和宏来执行操作,等等,它将完成您想要的所有事情。我不确定,但是网络上可能有其他东西可以帮

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

Emacs包括PostScript工具。它包括用于向postscript解释器发送当前选定文本的工具,您还可以直接向同一解释器输入命令,例如查询操作数堆栈等

不过,这可能不是您想要的,因为它可能比您愿意使用的更难使用。但是,正确地设置,为您想要监视的所有事情使用不同的缓冲区,脚本和宏来执行操作,等等,它将完成您想要的所有事情。我不确定,但是网络上可能有其他东西可以帮助你设置它

编辑:我使用Emacs调试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>