I don't know how the title of this question should be...
I'm working on an interpreter, currently I was looking at error handling. I've seen that there is an $error and errordict dictionary which are stored in systemdict.
The PLRM contains information on which errors may occur and a few steps to handle them. However when I execute this command in ghostscript:
errordict /stackoverflow get ==
I receive this information:
{/stackoverflow {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--}
And this seems to be a packedarray:
errordict /stackoverflow get type pstack
result:
packedarraytype
Now where do I find this kind of information (which manual?)? Where are these procedures described so that I can implement them.
It is not only for errors, but other operators also seem to have a packedarray (procedure) as the value, but I can't find the implementation of this procedures in the PLRM.
This will become more clear once you get the book Inside Postscript, but I can summarize somewhat.
It's hard to see just from the dump above, but if you dump several error handlers the same way, it would become obvious that the big procedure body in the middle is the same for all the handlers, and all handlers follow the same pattern of passing the error name to this procedure (with one exception for the
timeouterror). And you'd actually implement the above like this:Where
signalerrorimplements the common code. For thetimeouterror (if you choose to implement that one), there is no command to be placed on the stack, so itserrordictprocedure is slightly different.signalerror(or.erroris the name described in the book) takes snapshots of all the stacks and saves them in the$errordictionary.So the sequence for an error is usually:
errordictand executing this procedure.errordictprocedure callssignalerror, passing it the error name.signalerrortakes snapshots of the stacks, saving the snapshots in$error, and then callsstop.stoppops the exec stack until the nearest enclosing stopped context established by thestoppedoperator.stopped { handleerror } ifwhich was called by the startup code to bracket the whole user program.handleerroruses the information in$errorto print an error report.BTW, you can implement
packedarrayas read-only arrays. They were needed in the earliest implementations on memory-constrained printers, but I found it too complicated to design a more compact representation of objects. Behaviorally, the only difference from a regular array is that packed arrays must be read-only.