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)