[comp.lang.postscript] Alternatives to Adobe's ehandler.ps?

lwv27@CAS.BITNET (Larry W. Virden ext. 2487) (04/24/91)

Are there alternatives out there which provide more info on the
state of affairs than TransScript 2.1 Unix's ehander.ps?  This
one gives a terse one line error msg and a one line data info line...
--
Larry W. Virden                 UUCP: osu-cis!chemabs!lwv27
Same Mbox: BITNET: lwv27@cas    INET: lwv27%cas.BITNET@CUNYVM.CUNY.Edu
Personal: 674 Falls Place,   Reynoldsburg,OH 43068-1614
America Online: lvirden

tim@cs.wisc.edu (Tim Theisen) (04/24/91)

In article <9104231442.AA23295@cas.org>, lwv27@CAS.BITNET (Larry W. Virden ext. 2487) writes:
|> Are there alternatives out there which provide more info on the
|> state of affairs than TransScript 2.1 Unix's ehander.ps?  This
|> one gives a terse one line error msg and a one line data info line...

I clipped this errorhandler from comp.lang.postscript a year ago.  I have
found it to be useful and thought that a repost was in order.

From: fred@nada.kth.se (Fredric Ihren)
Newsgroups: comp.lang.postscript
Subject: more detailed errorhandler
Keywords: errorhandler debugger
Date: 4 Apr 90 22:48:24 GMT
Lines: 218

For me debugging postscript has often involved the location problem -
I know the error and the command, but _where_ in my file did it happen?
Adobe's lib/ehandler.ps program for catching errors in Apple Laser Writers
seems to be well known and used around the world.
I have modified it slightly (with kind permission from Adobe) to make it
present more information about the conditions when the error occurred, so that
the _where_-problem mentioned above can be solved.
The additional information is jobname, execstack and position in file and a
user debug procedure. An added procedure printonly makes it possible to print
the information to stdout instead of wasting a paper.

Here it comes:
-------------------------------- cut here ------------------------------------
%!
% behandler.ps, v1.3, Mar 23 1990, a modified version of Adobe's ehandler.ps
% Original program copyright (c) 1986 Adobe Systems Incorporated
% Modified by Fredric Ihren, for support contact fred@nada.kth.se or write to
%   Fredric Ihren; Moerbydalen 17; S-182 32 D-RYD; Sweden
% Adobe will not keep maintenance of this program.
% Distributed with permission from Adobe Systems Incorporated

0000 % serverloop password
/$brkpage where not {
  dup serverdict begin statusdict begin checkpassword
    { (Error Handler downloaded.\n) print flush exitserver }
    { pop (Bad Password on loading error handler.\n) print flush stop }
  ifelse
} {
  pop pop (Error Handler in place - not loaded again\n) print flush stop
} ifelse
/$brkpage 64 dict def
$brkpage begin
  /== { /cp 0 def typeprint nl } def
  /printpage {
    /prnt {
      dup type /stringtype ne { =string cvs } if dup length 6 mul /tx exch def
      /ty 10 def currentpoint /toy exch def /tox exch def 1 setgray newpath
      tox toy 2 sub moveto 0 ty rlineto tx 0 rlineto 0 ty neg rlineto
      closepath fill tox toy moveto 0 setgray show
    } bind def
    /nl { currentpoint exch pop lmargin exch moveto 0 -10 rmoveto } def
    /doshowpage systemdict /showpage get def
  } def
  /printonly {
    /nl { (\n) print } def
    /prnt { dup type /stringtype ne { =string cvs } if print } def
    /doshowpage null cvx def
  } def
  printpage
  /typeprint { dup type dup currentdict exch known
    { exec } { unknowntype } ifelse
  } def
  /lmargin 72 def /rmargin 72 def
  /tprint { dup length cp add rmargin gt { nl /cp 0 def } if
    dup length cp add /cp exch def prnt
  } def
  /cvsprint { =string cvs tprint( ) tprint } def
  /unknowntype { exch pop cvlit (??) tprint cvsprint } def
  /integertype { cvsprint } def
  /realtype { cvsprint } def
  /booleantype { cvsprint } def
  /operatortype { (//) tprint cvsprint } def
  /marktype { pop (-mark- ) tprint } def
  /dicttype { pop (-dictionary- ) tprint } def
  /nulltype { pop (-null- ) tprint } def
  /filetype { pop (-filestream- ) tprint } def
  /savetype { pop (-savelevel- ) tprint } def
  /fonttype { pop (-fontid- ) tprint } def
  /nametype { dup xcheck not { (/) tprint } if cvsprint } def
  /stringtype {
    dup rcheck
      { (\() tprint tprint (\)) tprint }
      { pop (-string- ) tprint }
    ifelse
  } def
  /arraytype {
    dup rcheck { dup xcheck
      { ({) tprint { typeprint } forall (}) tprint }
      { ([) tprint { typeprint } forall (]) tprint }
    ifelse } { pop (-array- ) tprint } ifelse
  } def
  /packedarraytype {
    dup rcheck { dup xcheck
      { ({) tprint { typeprint } forall (}) tprint }
      { ([) tprint { typeprint } forall (]) tprint }
    ifelse } { pop (-packedarray- ) tprint } ifelse
  } def
  /stackmax 10 def
  /execmax 5 def
  /filemax 5 def
  /courier /Courier findfont 10 scalefont def
  /OLDhandleerror errordict /handleerror get def
end %$brkpage
errordict /handleerror {
  systemdict begin $error begin $brkpage begin newerror {
    {
      /newerror false store
      vmstatus pop pop 0 ne { grestoreall } if initgraphics courier setfont
      lmargin 750 moveto
      statusdict /jobname get dup null ne
        { (Jobname: ) prnt prnt nl } { pop } ifelse
      (Error: ) prnt errorname prnt nl
      (Command: ) prnt /command load ==
      $error /ostack known {
        $error /ostack get dup length 0 ne {
          (Stack \() prnt
          aload length dup prnt (\):) prnt nl
          /i 0 def
          { /i i 1 add def i stackmax le { == } { pop } ifelse }
          repeat
        } { pop } ifelse
      } if
      $error /estack known {
        $error /estack get dup dup length 1 sub get type /filetype ne {
          (Execstack \() prnt
          aload length dup prnt (\):) prnt nl
          /i 0 def
          { /i i 1 add def dup type /filetype eq { /i 99 def } if
            i execmax le { == } { pop } ifelse
          } repeat
        } { pop } ifelse
      } if
      (%stdin) (r) file
      dup =string readline {
        (File:) prnt nl prnt nl
        filemax 1 sub { dup =string readline { prnt nl } { exit } ifelse }
        repeat
      } if pop
      userdict /debug known {
        (Debug:) prnt nl
        userdict /debug get stopped pop nl
      } if
    } stopped pop
    doshowpage
    /newerror true store
    /OLDhandleerror load end end end exec
  } { end end end }
  ifelse
} dup 0 systemdict put dup 4 $brkpage put bind put
-------------------------------- cut here ------------------------------------
Notes about the use of it:
(A) The following information will be printed on the break page:
    1) jobname
       (useful in a multiuser environment)
       It will be printed if the program has set it like this:
         statusdict /jobname (informative string) def
    2) error, the name of the error that terminated your program.
    3) command, the name of the last command
    4) stack
       The top (maximum 10) elements of the operand stack.
       The limit 10 is set by the line
       /stackmax 10 def
       and can be changed by modifying that line.
    5) execstack
       The top (maximum 5) elements of the execstack.
       (For those of you who don't know, that's the stack of objects that
       are currently executing, the part of a procedure that's still to be
       done, the current index of a for-loop, etc)
       To make it minimally confusing, it will not present elements
       beyond a fileobject, so the surrounding server procedures are ignored.
       (The maximum 5 can be changed on the line /execmax 5 def)
    6) file
       The next (maximum 5) lines of the file will be printed if available
       making it possible for you to localise the error.
       This is read from a stdin-file and I guess that it might not work for
       some io-arrangements.
       Lines longer than 128 characters will be not be read.
       (The maximum 5 can be changed on the line /filemax 5 def)
    7) debug
       If a procedure /debug is found in userdict, it will be executed.
       It can use the break page procedure == to present its information.
       It might for instance print the value of a variable /counter like this:
       /debug {
         counter ==
       } def

(B) By default the break-page handler will be downloaded, that is it will
    be read in to printer memory and stay there until poweroff.
    Commenting or removing the lines before /$brkpage 64 dict def
    will make it volatile: append your file to the end of it and the
    error handler will only affect this job only.

(C) By default the break-page handler will print a page with the information
    (like Abode's program).
    If the procedure printonly is executed, it will print to stdout instead
    of wasting a page.
    This can be downloaded after the break-page-handler with:
-------------------------------- cut here ------------------------------------
%!
% Break-page printonly
0000 % serverloop password
serverdict begin exitserver $brkpage begin printonly
-------------------------------- cut here ------------------------------------
    or made default by changeing the line
    "printpage" to "printonly" in behandler.ps
    or selected for this job only by adding this line to your program:
    $brkpage begin printonly end
    (files needing $brkpage to run should of course not be distributed)

(D) The error handler can be shut-off(on) without power-off-ing the printer by
-------------------------------- cut here ------------------------------------
%!
% Break-page shut-off(on)
0000 % serverloop password
serverdict begin exitserver errordict begin $brkpage begin
/handleerror dup load /OLDhandleerror dup load 4 -1 roll exch store exch store
-------------------------------- cut here ------------------------------------
    or shut-off for this job only by adding this line to your program:
    errordict /handleerror $brkpage /OLDhandleerror get put
    (files needing $brkpage to run should of course not be distributed)

(E) Adobe will not keep maintenance over this program and
    trouble/questions/support-needs should contact me, rather than Adobe.

Enjoy!

Fredric Ihren				 		   Tel. +46 8 755 35 77
fred@nada.kth.se			 Moerbydalen 17, S-182 32 D-RYD, Sweden



-- 
Tim Theisen             Department of Computer Sciences
Systems Programmer      University of Wisconsin-Madison
tim@cs.wisc.edu         1210 West Dayton Street
(608)262-0438           Madison, WI   53706

bradlee@cg-atla.UUCP (Rob Bradlee) (04/25/91)

>
>From: fred@nada.kth.se (Fredric Ihren)
>For me debugging postscript has often involved the location problem -
>I know the error and the command, but _where_ in my file did it happen?
>Adobe's lib/ehandler.ps program for catching errors in Apple Laser Writers
>seems to be well known and used around the world.
>I have modified it slightly (with kind permission from Adobe) to make it
>present more information about the conditions when the error occurred, so that
>the _where_-problem mentioned above can be solved.

I'd just like to cast a vote in favor of this error handler.  I've used
it for the past year developing several PostScript procsets and it has
been invaluable.  I distribute it to all our test systems so that when
EQA has a problem I can download this, resend the file, and get a clear
picture of what went wrong.   It's a great alternative to LaserTalk
and 9 times out of 10 it tells you enough that you can see your error
right away.  You do need to know the password of the printer, however.





					Rob

-- 
Rob Bradlee  w:(508)-658-5600 X5153  h:(617)-944-5595
AGFA Compugraphic Division.    ...!{decvax,samsung}!cg-atla!bradlee
200 Ballardvale St.                        bradlee@cg-atla.agfa.com
Wilmington, Mass. 01887           The Nordic Way: Ski till it hurts!

jwz@lucid.com (Jamie Zawinski) (04/26/91)

In article <9737@cg-atla.UUCP> bradlee@cg-atla.UUCP (Rob Bradlee) wrote:
> 
> I'd just like to cast a vote in favor of this error handler.  I've used
> it for the past year developing several PostScript procsets and it has
> been invaluable.  

By far the best way to debug PostScript is with GhostScript or another
on-screen interpreter.  Though it's nice that PS gives you the ability
to get real error messages out of a piece of printer hardware, that's an
incredibly wasteful way to go about it, in terms of both time and trees.
(On my Sparc2, GS is about 70 times faster than a laserwriter...)

Since GhostScript is free and runs under X11, SunView, and MS-DOS, you
really don't have *any* excuse for killing all of those trees...

	-- Jamie

PS: prep.ai.mit.edu:/pub/gnu/ghostscript-2.1.1.tar.Z

bradlee@cg-atla.UUCP (Rob Bradlee) (04/26/91)

In article <JWZ.91Apr25151652@thalidomide.lucid.com> jwz@lucid.com (Jamie Zawinski) writes:
>In article <9737@cg-atla.UUCP> bradlee@cg-atla.UUCP (Rob Bradlee) wrote:
>> 
>> I'd just like to cast a vote in favor of this error handler.  I've used
>> it for the past year developing several PostScript procsets and it has
>> been invaluable.  
>
>By far the best way to debug PostScript is with GhostScript or another
>on-screen interpreter.  Though it's nice that PS gives you the ability
>to get real error messages out of a piece of printer hardware, that's an
>incredibly wasteful way to go about it, in terms of both time and trees.
>(On my Sparc2, GS is about 70 times faster than a laserwriter...)
>
>Since GhostScript is free and runs under X11, SunView, and MS-DOS, you
>really don't have *any* excuse for killing all of those trees...
>

I should have made my vote clearer.  Yes, a screen interpreter is the
easiest, fastest, and cheapest way to find bugs and we use Xnews and 
Ghostscript for that purpose.  HOWEVER, we are writing software to
drive film recorders (typesetters).    Some things work in Xnews, but
not on the typesetters.   Conversely, some things fail in Xnews that
work on the the typesetter. Also, there are some commands unique to
the typesetter that can only be tested on the box itself.  So..., it's
very handy to have something that prints out a message in the exact
environment that you're coding for.   
	Finally, as for the killing trees problem,  we only use the
error handler when the PS is failing and not getting to showpage.  We
can hook up an ascii terminal to the serial line (PS is sent down via
centronics or ethernet) and the errors come up on the screen not out
on the paper (film).

					Rob

-- 
Rob Bradlee  w:(508)-658-5600 X5153  h:(617)-944-5595
AGFA Compugraphic Division.    ...!{decvax,samsung}!cg-atla!bradlee
200 Ballardvale St.                        bradlee@cg-atla.agfa.com
Wilmington, Mass. 01887           The Nordic Way: Ski till it hurts!