PostScript 内部错误处理程序的描述

Description of PostScript internal error handler procedures

不知道这个问题的标题应该怎么...

我正在研究解释器,目前正在研究错误处理。我看到有一个 $error 和 errordict 字典存储在 systemdict 中。

PLRM 包含有关可能发生错误的信息以及处理这些错误的几个步骤。但是,当我在 ghostscript 中执行此命令时:

errordict /Whosebug get ==

我收到此信息:

{/Whosebug {1 --.instopped-- {null --eq-- {--pop-- --pop-- --stop--} --if--} --if-- (I) false --.setdebug-- $error /.inerror --get-- 1 --.instopped-- {--pop--} {--pop-- true} --ifelse-- {.unstoppederrorhandler} --if-- $error /globalmode --.currentglobal-- false --.setglobal-- --put-- $error /.inerror true --put-- $error /newerror true --put-- $error --exch-- /errorname --exch-- --put-- $error --exch-- /command --exch-- --put-- $error /errorinfo --known-- --not-- {$error /errorinfo null --put--} --if-- $error /recordstacks --get-- $error /errorname --get-- /VMerror --ne-- --and-- {--count-- --array-- --astore-- --dup-- $error /ostack 4 -1 --roll-- --countexecstack-- --array-- --execstack-- --dup-- --length-- 2 --sub-- 0 --exch-- --getinterval-- $error /estack 3 -1 --roll-- --countdictstack-- --array-- --dictstack-- $error /dstack 3 -1 --roll-- --put-- --put-- --put-- --aload-- --pop--} {$error /dstack --.undef-- $error /estack --.undef-- $error /ostack --.undef--} --ifelse-- $error /position --currentfile-- --status-- {--currentfile-- {--fileposition--} .internalstopped {--pop-- null} --if--} {$error /command --get-- --dup-- --type-- /filetype --eq-- {{--fileposition--} .internalstopped {--pop-- null} --if--} {--pop-- null} --ifelse--} --ifelse-- --put-- $error /globalmode --get-- $error /.nosetlocal --get-- --and-- --.setglobal-- $error /.inerror false --put-- --stop--} --exec--}

这似乎是一个打包数组:

errordict /Whosebug get type pstack

结果:

packedarraytype

现在在哪里可以找到此类信息(哪本手册?)?这些程序在哪里描述,以便我可以实施它们。

不仅仅是报错,其他算子好像也有一个packedarray(procedure)作为value,但是我在PLRM中找不到这个procedure的实现。

一旦你拿到书 Inside Postscript,这会变得更加清楚,但我可以总结一下。

仅从上面的转储很难看出,但是如果您以相同的方式转储多个错误处理程序,很明显中间的大过程主体对于所有处理程序都是相同的,并且所有处理程序都遵循将错误名称传递给此过程的相同模式(timeout 错误除外)。你实际上会像这样实现上面的内容:

errordict /stackunderflow {
    /stackunderflow //signalerror exec
} put

其中 signalerror 实现了公共代码。对于 timeout 错误(如果你选择实现那个),没有 command 放在堆栈上,所以它的 errordict 程序略有不同.

errordict /timeout {
    /timeout /timeout //signalerror exec
} bind put

signalerror(或者.error是书上描述的名字)对所有栈进行快照并保存在$error字典中。

所以错误的顺序通常是:

  1. 错误是通过在errordict中查找错误名称并执行此过程来触发的。
  2. errordict 过程调用 signalerror,将错误名称传递给它。
  3. signalerror 获取堆栈快照,将快照保存在 $error 中,然后调用 stop.
  4. stop 弹出 exec 堆栈,直到最近的封闭 stopped contextstopped 运算符建立。
  5. 如果程序没有建立自己的stopped context来捕获错误,它将被启动调用的外层stopped { handleerror } if捕获包含整个用户程序的代码。
  6. handleerror 使用 $error 中的信息打印错误报告。

顺便说一句,您可以将 packedarray 实现为 只读 数组。在内存受限打印机的最早实现中需要它们,但我发现设计更紧凑的对象表示太复杂了。在行为上,与常规数组的唯一区别是打包数组必须 只读.