[comp.lang.postscript] A question about //add

bvs@light.uucp (Bakul Shah) (11/13/90)

All versions of the (Adobe)  PostScript interpreter since version
25.0 provide an immediately evaluated name facility:  When the
scanner encounters a `//name' token, it immediately looks up the
name in the current dictionary stack and substitutes the name's
value for the name[%].  The effect is as if the `load' operator
had been applied to the name (except that this happens in the
scanner).

Now the Question.  If at the top level (i.e. not nested within
any braces) the input is
	1 2 //add
should the operand stack contain
	1 2 --add--
or
	3
? You can test this by feeding
	1 2 //add pstack clear
to your PostScript interprter.

My QMS PS 410 printer (running Adobe PostScript version 52.4) says
the stack has 1 2 --add--.  Initially I thought that was the
correct behavior but L.  Peter Deutsch <ghost@aladdin.com>, the
author of Ghostscript, argues the stack should contain 3 and I
agree with him now.  Is the bug in the interpreter, the Supplement
document (:-) or did we miss something?  Can we get an
*official* clarification?

Our reason for thinking the stack should contain 3 is this:  Since
the scanner hands an *operator* to the interpreter, the
interpreter must execute the -add-- operator, following the rules
on page 42 of the Red Book (see the para. starting with `An
executable operator object...').

Yours in nitpicking

Bakul Shah <bvs@BitBlocks.COM>
or         ..!{ames,att,decwrl,pyramid,sun,uunet}!amdcad!light!bvs

[%] See the Supplement document, available through Adobe's File
Server, for details as this feature is not described in the Red
Book.

glenn@heaven.woodside.ca.us (Glenn Reid) (11/13/90)

In article <1990Nov12.195235.13908@light.uucp> bvs@BitBlocks.COM (Bakul Shah) writes:
>All versions of the (Adobe)  PostScript interpreter since version
>25.0 provide an immediately evaluated name facility:  When the
>scanner encounters a `//name' token, it immediately looks up the
>name in the current dictionary stack and substitutes the name's
>value for the name[%].  The effect is as if the `load' operator
>had been applied to the name (except that this happens in the
>scanner).
>
>Now the Question.  If at the top level (i.e. not nested within
>any braces) the input is
>	1 2 //add
>should the operand stack contain
>	1 2 --add--
>or
>	3
>? You can test this by feeding
>	1 2 //add pstack clear
>to your PostScript interprter.
>
>My QMS PS 410 printer (running Adobe PostScript version 52.4) says
>the stack has 1 2 --add--.  Initially I thought that was the
>correct behavior but L.  Peter Deutsch <ghost@aladdin.com>, the
>author of Ghostscript, argues the stack should contain 3 and I
>agree with him now.

Just as a data point, I tried your program on my (Adobe) Display
PostScript interpreter and got "3" on the stack:

	heaven> /usr/lib/NextStep/WindowServer -e start
	PostScript(r) Version 1006.24
	PS>1 2 //add pstack     
	3 
	PS>quit

I happen to believe that it should leave "1 2 --add--" on the stack,
since there are situations in which executing the "add" operator could
lead to errors, such as the following:

	/proc {
	    one two //add
	} def
	/one 1 def
	/two 2 def
	proc

This actually wouldn't work right with either semantics.  You would
need an "exec" after the "//add" in one case, and you'd get an
"undefined" error on the name "one" in the other case :-)

And, as long as we're nitpicking....

>                           The effect is as if the `load' operator
>had been applied to the name (except that this happens in the
>scanner).

If the effect is *really* as if the `load' operator had been applied,
then you should get "1 2 --add--" in your example.  The real question
hinges on whether the semantics of // are equivalent to `load' or to
the automatic name lookup mechanism.  I prefer the semantics of `load'.

This is further complicated by the fact that // should probably do
different things depending on whether or not it is in deferred execution
mode (inside curly braces).  I would suggest that inside a procedure
body // should produce "1 2 --add--", even if you convince me that
it should produce "3" outside a procedure body.

Now that we have two examples of Adobe implementations that implement
each of the two choices in semantics for your example, we can do one
of three things:

	1) assume that the most recent implementation represents
	   the truth,
	2) wait for the new red book to be published and hope that
	   the semantics are made explicit, or
	3) wait for someone from Adobe to pipe up.

You have posed a most interesting question, and one that I have never
stopped to think about.

% Glenn

-- 
 Glenn Reid				RightBrain Software
 glenn@heaven.woodside.ca.us		PostScript/NeXT developers
 ..{adobe,next}!heaven!glenn		415-851-1785

dcj@decvax.DEC.COM (Dave Jedlinsky) (11/14/90)

-- 
/* Eat this, line-eater! */

Here's another data point.

The Display Postscript X server (Adobe) for Ultrix 4.0 has the
following behaviour:

	PS>version ==
	(1006.5)
	PS>1 2 //add pstack clear
	3
	PS>1 2 /add load pstack clear
	--add--
	2
	1
	PS>{1 2 //add} pstack clear
	{1 2 --add--}
	PS>

I agree that this is inconsistent with the "PostScript Language
Supplement" from Adobe, dated January 9, 1986, page 3:

	"The substitution occurs immediately, regardless of
	whether or not the token appears inside an executable
	array delimited by '{...}'.  Note that this process is
	a substitution and not an execution; that is, the name's
	value is not executed but rather is substituted for the
	name itself, just as if the load operator had been applied
	to the name."


-David Jedlinsky
Digital Equipment Corporation   | 
dcj@decvax.dec.com              | This space intentionally left blank.
...!decwrl!decvax!dcj           | 

korp@atlantis.ees.anl.gov (Peter Korp) (11/14/90)

In article <321@heaven.woodside.ca.us> glenn@heaven.woodside.ca.us (Glenn Reid) writes:
>In article <1990Nov12.195235.13908@light.uucp> bvs@BitBlocks.COM (Bakul Shah) writes:
>>All versions of the (Adobe)  PostScript interpreter since version
>>25.0 provide an immediately evaluated name facility:  When the
>>scanner encounters a `//name' token, it immediately looks up the
>>name in the current dictionary stack and substitutes the name's
>>value for the name[%].  The effect is as if the `load' operator
>>had been applied to the name (except that this happens in the
>>scanner).
>>
>>Now the Question.  If at the top level (i.e. not nested within
>>any braces) the input is
>>	1 2 //add
>>should the operand stack contain
>>	1 2 --add--
>>or
>>	3
>>? You can test this by feeding
>>	1 2 //add pstack clear
>>to your PostScript interprter.
>>
>>My QMS PS 410 printer (running Adobe PostScript version 52.4) says
>>the stack has 1 2 --add--.  Initially I thought that was the
>>correct behavior but L.  Peter Deutsch <ghost@aladdin.com>, the
>>author of Ghostscript, argues the stack should contain 3 and I
>>agree with him now.
>
>Just as a data point, I tried your program on my (Adobe) Display
>PostScript interpreter and got "3" on the stack:
>
>	heaven> /usr/lib/NextStep/WindowServer -e start
>	PostScript(r) Version 1006.24
>	PS>1 2 //add pstack     
>	3 
>	PS>quit
>
[talk of what should be left on stack deleted]

As another point of reference, I trie it in OpenWindows and got:

	tripoli-> psh
	executive
	Welcome to X11/NeWS Version 2
	1 2 //add
	stack
	3 
	quit
	psh: NeWS server disconnected


It is nice to see the PS interpreters agree about what to do! :-)

Peter

bvs@light.uucp (Bakul Shah) (11/14/90)

In article <321@heaven.woodside.ca.us> glenn@heaven.woodside.ca.us (Glenn Reid) writes:
> ...
>If the effect is *really* as if the `load' operator had been applied,
>then you should get "1 2 --add--" in your example.  The real question
>hinges on whether the semantics of // are equivalent to `load' or to
>the automatic name lookup mechanism.  I prefer the semantics of `load'.

The scanner _does_ return 1, 2 and then --add-- to the
interpreter.  So the effect is really as if the `load' operator
was applied by the *scanner*.  The real question was what does the
interpreter do when directly given --add-- (except for //, this
would never happen at the top level).

>This is further complicated by the fact that // should probably do
>different things depending on whether or not it is in deferred execution
>mode (inside curly braces).  I would suggest that inside a procedure
>body // should produce "1 2 --add--", even if you convince me that
>it should produce "3" outside a procedure body.

For // semantics *within* a proc, there are no discrepancies
between the Red Book, the language Supplement (file `language.ps'
from the Adobe File Server), my QMS printer and Ghostscript.  For
example, if the input has
	``{ one two //add }''
all of them say you get an executale array
	{ one two --add-- }
on the operand stack.  The scanner does exactly the same thing
with // in the deferred or immediate execution mode.

>	2) wait for the new red book to be published and hope that
>	   the semantics are made explicit, or

I hope the new red book will also clear up a number of other
imprecisions in the Red Book (like the definition of `=' on page
114 does not mention if a newline is appended), and define minimum
limits every implementation must obey.

>You have posed a most interesting question, and one that I have never
>stopped to think about.

And one I should have never stopped to think about :-)

-- Bakul Shah
  bvs@BitBlocks.COM
  ..!{ames,att,decwrl,pyramid,sun,uunet}!amdcad!light!bvs

flar@bendenweyr.Eng.Sun.COM (Jim Graham) (11/14/90)

Here are the relevant references as I see them:

From "UPDATE for the APPLE LASERWRITER and LASERWRITER PLUS - Revision 2":

	The language syntax has been extended to include a new kind of
	name token, the *immediately evaluated name*.  When the scanner
	encounters the token '//name' (a name preceded by two slashes
	with no intervening spaces), it immediately looks up the name in
	the context of the current dictionary stack and substitutes the
	corresponding value for the name.  If the name is not found, an
	*undefined* error occurs.

	The substitution occurs *immediately*, regardless of whether or
	not the token appears inside an executable array delimited by
	'{...}'.  Note that this process is a substitution and not an
	execution; that is, then name's value is not executed but rather
	is substituted for the name itself, just as if the *load* operator
	hand been applied to the name.

The important points are that the substitution is performed by the
scanner, not by the interpreter.  They qualify that no execution is
performed to clarify that building an array such as:

	{ 1 2 //add }

will not generate:

	{ 3 }

as the scanner only "looked up" the add operator, but did not "execute"
it.  The interpreter will execute the add operator when it encounters
it by executing that array.

In immediate mode, the scanner gives the add operator itself '--add--'
to the interpreter.  The interpreter then executes the add operator
as it does under any other circumstance.

From Section 3.2 - INTERPRETER - of the redbook:

	The PostScript interpreter is the process that executes the
	PostScript language according to the rules given in this chapter.

	...

	The interpreter operates by executing a sequence of objects.

	...

	The objects to be executed by the interpreter come from two
	principal sources.  First, objects previously stored in an
	array in PostScript memory may be executed in sequence.  Such
	an array is conventionally known as a *procedure*.  Second, a
	character stream may be scanned according to the syntax rules
	of the PostScript language, producing a sequence of new objects.
	As each object is scanned it is immediately executed.

This says that the PostScript interpreter treats objects that come from
the scanner just the same as it treats objects that come from a PostScript
array.  When the scanner scans a procedure {...}, that procedure goes on
the operand stack, just as it would if it were encountered while executing
an executable array.  When the scanner scans an operator object (possible
only by using the // syntax since there is no other syntax which can
produce an operator object), the interpreter executes it just as if it
had encountered that object in an executable array.

						...jim

bvs@light.uucp (Bakul Shah) (11/15/90)

In article <8194@adobe.UUCP> orthlieb@adobe.UUCP (Carl Orthlieb) writes:
>
>After talking to our language guru, Ed Taft, it is apparent that the
>// operator acts like a load inside a procedure definition, but outside
>of the definition acts like a load exec.
>
>E.g. 	1 2 //add 
>	stack contains: 3
>
>E.g.	/foo { 1 2 //add } def
>	/foo load
>	stack contains: { 1 2 --add-- }
>
>It is suggested that // not be used, use bind or load depending on the
>effect you want.

Thanks for the clarification.  Any particular reason why // is
discouraged?  Just curious.

>Q. Does the QMS PS410 have an Adobe PostScript interpreter?

PS410 User's Guide says `PostScript licensed by Adobe Systems,
Incorporated' and the initial copyright notice sent back in the
interactive mode says
  PostScript(r) Version 52.4
  Copyright (c) 1984, '85, ... '90 Adobe Systems Incorporated.
  Typefaces Copyright (c) 1918 Linotype AG ...
So it *seems* that they do.

-- Bakul

srwmcln@windy.dsir.govt.nz (11/15/90)

In article <321@heaven.woodside.ca.us>, glenn@heaven.woodside.ca.us (Glenn Reid) writes:
> In article <1990Nov12.195235.13908@light.uucp> bvs@BitBlocks.COM (Bakul Shah) writes:
>>All versions of the (Adobe)  PostScript interpreter since version
>...... 
> This is further complicated by the fact that // should probably do
> different things depending on whether or not it is in deferred execution
> mode (inside curly braces).  I would suggest that inside a procedure
> body // should produce "1 2 --add--", even if you convince me that
> it should produce "3" outside a procedure body.
>
My understanding of // should behave as above,
 1 2 --add-- in a procedure and 3 outside.

This does lead to the need for exec following //'s which are replaced by
procedures rather than operators. ie

/dd {......} def
{//dd exec} true if

On our LaserWriter IINT, from within (v47.0) executive:

1 2 //add pstack       produces 3.

> Now that we have two examples of Adobe implementations that implement
> each of the two choices in semantics for your example, we can do one
> of three things:
> 
> 	1) assume that the most recent implementation represents
> 	   the truth,
> 	2) wait for the new red book to be published and hope that
> 	   the semantics are made explicit, or
> 	3) wait for someone from Adobe to pipe up.
> 
> You have posed a most interesting question, and one that I have never
> stopped to think about.

Adobe implementations can only be taken as a guide to the correct semantics.

Clive.

orthlieb@adobe.COM (Carl Orthlieb) (11/16/90)

Correction to my previous post:

After talking to our language guru, it is apparent that the // operator
acts in the following manner: outside brackets, it acts like a load exec,
the operator is looked up and then immediately executed, inside brackets
it acts like a load.

E.g.	1 2 //add
	stack contains: 3

E.g.	/d { 1 2 //add } def
	d load
	stack contains: { 1 2 --add-- }

The // operator should be conditionally used, interpreters prior
to version 25.0 do not support this operator.

The current version of the QMS-PS410 Adobe PostScript interpreter (52.4) 
does contain a bug which causes // to be interpreted improperly outside 
of brackets. This bug is fixed in the version of the PS 410 firmware which
is completing testing and will begin shipping soon.

For more information on when the new version will be available, please contact
QMS technical support at (205) 633-4500.

Thanks, Carl

woody@chinacat.Unicom.COM (Woody Baker @ Eagle Signal) (11/18/90)

In article <8278@adobe.UUCP>, orthlieb@adobe.COM (Carl Orthlieb) writes:
> 
> The current version of the QMS-PS410 Adobe PostScript interpreter (52.4) 
> does contain a bug which causes // to be interpreted improperly outside 
> of brackets. This bug is fixed in the version of the PS 410 firmware which
> is completing testing and will begin shipping soon.
O.k., what about other 52.4 interpreters?  Is this a common bug for
them as well?  It seems funny that a bug like this all of a sudden
shows up in a feature that was put in many versions ago, and that
one would presume would not change.  I was under the impression that the
core interpreter pretty much stayed the same from manufacturer to manufacturer
as long as it was the same revision number, and the main diffrence was the
actual hardware interface and resolution modules.  Bugs do occur,
more often than not 8) in everyones code.  It seems to me that it would
be very nice if Adobe published a comprehensive list of the various
bugs in the various versions of the interpreter.  I do not think that
it would hurt thier reputation any at all.  There is no such thing as
a complex program that is totaly bug free.

Cheers
Woody

that was put in place many versions ago,

shiva@well.sf.ca.us (Kenneth Porter) (11/21/90)

orthlieb@adobe.UUCP (Carl Orthlieb) writes:
 
> It is suggested that // not be used, use bind or load
> depending on the effect you want.
 
// is particularly useful for re-defining system operators in
heavily nested situations:
 
/showpage { stuff //showpage more-stuff } def
 
The problem here is that one has to test for whether the system operator
has be re-defined before;  if so, then an exec has to be added after
the name:
 
/systemname load operatortype { /systemname { //systemname } def } if
 
Ken (shiva@well.sf.ca.us)

flar@bendenweyr.Eng.Sun.COM (Jim Graham) (11/22/90)

In article <21745@well.sf.ca.us>, shiva@well.sf.ca.us (Kenneth Porter) writes:

|> orthlieb@adobe.UUCP (Carl Orthlieb) writes:
|>  
|> > It is suggested that // not be used, use bind or load
|> > depending on the effect you want.
|>  
|> // is particularly useful for re-defining system operators in
|> heavily nested situations:
|>  
|> /showpage { stuff //showpage more-stuff } def
|>  
|> The problem here is that one has to test for whether the system operator
|> has be re-defined before;  if so, then an exec has to be added after
|> the name:
|>  
|> /systemname load operatortype { /systemname { //systemname } def } if

A robust method for performing this overriding behaviour would be the
following (assuming you are writing a package referred to as "AA"):

/preAAshowpage	/showpage load def

/showpage {stuff preAAshowpage morestuff} bind def

If showpage were an operator prior to this code, then bind would
still bind the operator into the procedure (in which case
"/preAAshowpage" would be wasted").  If it were not an operator,
then the new showpage procedure would still execute correctly.

This technique adds to your userdict size more, but it eliminates
unnecessary tests and "exec" operators in the overriden operator
procedures.

					...jim

glenn@heaven.woodside.ca.us (Glenn Reid) (11/24/90)

In article <21745@well.sf.ca.us> shiva@well.sf.ca.us (Kenneth Porter) writes:
>// is particularly useful for re-defining system operators in
>heavily nested situations:
> 
>/showpage { stuff //showpage more-stuff } def
> 
>The problem here is that one has to test for whether the system operator
>has be re-defined before;  if so, then an exec has to be added after
>the name:
> 
>/systemname load operatortype { /systemname { //systemname } def } if

This second bit of code doesn't work, for one thing; you need to use
the "type" operator:

/systemname load type /operatortype eq { ... } if

And for another thing, it's not a particularly good idea.  You're
changing "systemname" from being an operator into being a procedure
that calls only a single operator, which is less efficient.  You're
much better off with "bind" in your "showpage" example; it has the
same strengths (and weaknesses, in that you have to make sure
"showpage" hasn't already been redefined).

Heavily-nested situations don't affect "bind"; it is applied recursively
to all the procedures nested within the outermost procedure.

In general, // is more dangerous than "bind" or "load".  The only situation
where I use it is if I have some constants that I want to define up front
in the program for readability (rather than hard-wiring them into the
code) but I don't want to suffer name lookup time whenever the constants
are used.  As long as they're my own names, I don't have to worry about
their having been redefined.  For example:

    /leftmargin 72 def
    /topmargin 792 72 sub def

    /startpage {
	//leftmargin //topmargin moveto
	/Times-Roman 12 selectfont
    } bind def

% Glenn

-- 
 Glenn Reid				RightBrain Software
 glenn@heaven.woodside.ca.us		PostScript/NeXT developers
 ..{adobe,next}!heaven!glenn		415-851-1785

shiva@well.sf.ca.us (Kenneth Porter) (11/29/90)

flar@bendenweyr.Eng.Sun.COM (Jim Graham) writes:
 
> A robust method for performing this overriding behaviour would be the
> following (assuming you are writing a package referred to as "AA"):
> 
> /preAAshowpage	/showpage load def
> 
> /showpage {stuff preAAshowpage morestuff} bind def
> 
> If showpage were an operator prior to this code, then bind would
> still bind the operator into the procedure (in which case
> "/preAAshowpage" would be wasted").  If it were not an operator,
> then the new showpage procedure would still execute correctly.
 
This doesn't work if you nest the same file twice and the original
showpage has been redefined before:
 
% (in exit-server job)
/showpage {{sysop stuff} original-showpage} def
 
% (in user job)
/preAAshowpage	/showpage load def
/showpage {stuff preAAshowpage morestuff} bind def
/preAAshowpage	/showpage load def
/showpage {stuff preAAshowpage morestuff} bind def
 
The new showpage is now recursive:
 
{stuff {stuff ... preAAshowpage ... morestuff} morestuff}
 
Here's an nup script that illustrates a case where nesting is
necessary:
 
------------------------------nup.sh------------------------------
#!/bin/csh -f
# change following line to point to correct path for next file
set twoup=/home/ken/psfonts/ps/twoup.ps
set n=$argv[1]
set logn=0
while ($n > 1)
	@ logn++
	@ n /= 2
end
echo logn = $logn
cp /dev/null /tmp/nup.$$
while ($logn > 0)
	cat $twoup >> /tmp/nup.$$
	@ logn--
end
foreach i ($argv[2-])
	echo $i
	cat /tmp/nup.$$ $i | lpr
end
----------------------------twoup.ps----------------------------
%!  Two-up filter
% Redefine showpage to collect two pages per page.
% Make showpage a procedure if it's an operator.
% This allows us to use // unconditionally to replace
% showpage below with "//showpage exec".
 
/showpage load type /operatortype eq { /showpage { //showpage } bind def } if
 
% Support routines in private dictionary
 
/twoupdict 6 dict def
 
twoupdict begin
 
/inch { 72 mul } bind def
 
/rightpage false def		% doing right half of page
 
/twoupscale 5.5 8.5 div def
 
/offset				% fudge factor to center on half page
  11 4 div			% half page width
  8.5 twoupscale mul 2 div	% half scaled page width
  sub inch
def
 
/setup {			% This does the real work
  grestore
% matrix currentmatrix == flush	% observe previous transform for debugging
  gsave				% restore initial coords
  90 rotate
  -8.25 inch translate		% this eats argument
  offset 0 translate
  twoupscale dup scale
  0 0 moveto 8.5 inch 0 lineto 8.5 inch 11 inch lineto
  0 11 inch lineto closepath clip newpath
} bind def
 
/dofile {			% init and cleanup code
  gsave
  //twoupdict begin 0 setup end
  % this is how to do an end-of-file handler
  currentfile cvx exec		% process client file
  % issue paper for last page if necessary
  //twoupdict begin rightpage { //showpage exec } if end
} bind def
 
end				% close dictionary before running
 
% new two-up showpage
 
/showpage {
  //twoupdict begin
    /rightpage
      rightpage dup
      { grestore //showpage exec gsave 0 setup } { 5.5 inch setup } ifelse
    not def
  end
} def
 
twoupdict /dofile get exec
----------------------------------------------------------------
 
Ken (shiva@well.sf.ca.us)

P.S. Mention my name and email address when you distribute this --
my ego needs it :-)

shiva@well.sf.ca.us (Kenneth Porter) (12/06/90)

glenn@heaven.woodside.ca.us (Glenn Reid) writes:
 
> In article <21745@well.sf.ca.us> shiva@well.sf.ca.us (Kenneth Porter)
writes:
> >/systemname load operatortype { /systemname { //systemname } def } if
> 
> This second bit of code doesn't work, for one thing; you need to use
> the "type" operator:
> 
> /systemname load type /operatortype eq { ... } if
 
Thanks for catching my error.  As you can see from my nup posting,
this is a case of failing memory. :-)
 
Bind doesn't seem to do what I want:  it doesn't replace names
that evaluate as procedures, only those that evaluate as
operators. Or am I reading the book wrong?
 
Ken (shiva@well.sf.ca.us)