seiler@HUDSON.DEC.COM ("LARRY SEILER") (01/15/86)
There's something that's bothered me since I first heard of Postscript, and now that people are doing fancy stuff like N-up headers, it might actually start biting people. Early criticisms of Postscript pointed out things like the absence of any built in accounting, bugs in ROM'd code, and so forth. To each of the criticisms, the reply was that Postscript allows builtin operations to be redefined, so that a piece of patch code can be downloaded to correct known bugs, a site that wants per-page accounting can define a new ShowPage that provides this, and so forth. For bug fixes, this is great. But when it is used to add new features to an existing function, there is trouble. Say that the system redefines ShowPage to include per-page accounting, and I use a header that redefines ShowPage to do 2-up printing. Either I've just defeated the accounting, or else the definition of ShowPage was locked in and my 2-up header fails on this machine. Can any Postscript gurus out there point out a way around this problem? It would suffice in this case to allow ShowPage to be redefined by an N-up header that itself calls the previous definition of ShowPage (not the original version, which might be buggy or might not include desired accounting). Is that possible in PostScript? Can anyone come up with other examples like this where nesting of function redefinitions causes trouble? Larry PS - Please, no straw men: don't say "but you have the same problem in page description languages X, Y, and Z as well." The question is, can PostScript cope with it. ------
evan@SU-CSLI.ARPA (Evan Kirshenbaum) (01/15/86)
>It would suffice in this case to allow ShowPage to be redefined by an N-up >header that itself calls the previous definition of ShowPage (not the >original version, which might be buggy or might not include desired >accounting). Is that possible in PostScript? This is exactly what is done. You do something like: mydict begin /OLDSHOWPAGE /showpage load def ... end /showpage { mydict begin ... OLDSHOWPAGE ... end } def Thus the newly defined version of showpage calls the version most recently defined (at the time of definition). This allows bugfixes to rom code and even allows such redefinitions to be nested. Evan Kirshenbaum -------
reid@SU-GLACIER.ARPA (Brian Reid) (01/15/86)
This is the sort of issue that can be difficult to understand until you fully understand PostScript. Let me offer a brief explanation. (1) PostScript implementations come with a barrier, namely the server loop boundary, inside which the system manager can change things, but the user cannot. So the system manager can redefine "showpage" inside the server loop so that it does whatever kind of accounting he wants, in such a way that nobody can access the original definition of showpage, and therefore there is no way to print a page without calling his redefined version of showpage. This is accomplished by exiting the server loop, retrieving the value of the name "showpage", then defining a new symbol named "showpage" whose contents is some form of accounting followed by an execution of the value that was retrieved from the old showpage operator before it was redefined. If the resulting definition is marked "execute-only", then it cannot be picked apart, and the old value cannot be extracted from it. Once the server loop is re-entered, the new showpage is indistinguishable from the old showpage--it is a "built in" operator, because the user cannot execute a restore that will un-do the redefinition, and cannot get his hands on the old version of the operator. (2) Referring to things like the 2-up header as "redefining" showpage is a bit misleading. It doesn't really redefine the showpage operator, it redefines the meaning of the name "showpage". It does this by stacking a new dictionary on top of the existing dictionary stack, and putting in that new dictionary a function named "showpage". That function will do the necessary 2-up trickery, and then call the "original" showpage. The "original" showpage here means the definition of the operator that was in force at the time the 2-up header dictionary was stacked. This can be accomplished in several different ways; my favorite is for each kind of header (such as the 2-up header) to extract the old definition of showpage and put it in a safe place, then stack a new definition; and at the end pop back to the previous definition. In this way it is easy to take a header that throws decorative borders around the page and combine it with a header that prints in 2-up, each of which relies on a redefinition of the name "showpage", in such a way that the resulting combination prints decorated pages in 2-up, or so that it prints 2-up pages with a combined decorative border, by reversing the order of the two header files. Summary: page accounting changes are done by redefining the OPERATOR that is called "showpage". 2-up printing and other such headers are done by stacking a new definition for the NAME "showpage", regardless of its contents. As long as the 2-up header works by stacking the new definition, rather than overwriting the old one, then it can be arbitrarily combined with other headers. In no event can a header undo the effect of an operator redefinition by the system manager. Brian Reid Stanford
laser-lovers@ucbvax.UUCP (01/16/86)
This is in response to a message from LARRY SEILER <seiler@hudson.dec.com> regarding the PostScript language and the redefining operators, and to some of the subsequent replies. The problem: You want to redefine the `showpage' operator in such a way that a user job downloaded to the PostScript printer will use your version of `showpage' instead of the one in /systemdict, thereby allowing for N-up output, page accounting, etc. You also want to make sure that your version of `showpage' does not replace any existing re-definition of `showpage', but augments it. A solution: The version of /showpage that is in systemdict CANNOT be altered by the user, and will always be the bottom line. Anyone who redefines /showpage in userdict will need to essentially rename the existing /showpage as something else, and then call it. If /showpage has been redefined already, then this routine should be called by the new /showpage as if it were the real showpage. The `exitserver' operator will allow the user (or system manager) to make the operator definition persist from one user job to another, because the definition will take place inside the save/restore construct in the serverloop. There is no other privilege afforded by the `exitserver' operator; the routines in systemdict are in ROM and cannot be altered. If /showpage has not been redefined, then the /showpage in systemdict should be called directly. In order to allow for aribtrary levels of redefinition, a scheme should be used to generate a unique name for the old /showpage (which can be done using the page count, for example, but that is a bit beyond this discussion), then to copy the old showpage under the new name, and call it from the new /showpage you are defining. Below is an example which does not bother to make sure that the name is unique, but otherwise satisfies the problem posed above: %!PS-Adobe-1.0 %%For: redefining the showpage operator /realshowpage /showpage load def /showpage { 90 rotate 0 -612 translate .5 .5 scale realshowpage } def The use of the `load' operator here will look downward through the dictionary stack (in case there are added levels of dictionaries, redefinition, etc. already there) until it finds the `showpage' name, and will push the procedure body onto the stack. In the event that the /showpage routine has not been redefined, then /realshowpage will get the /showpage routine that is in systemdict, which it should. If another job comes along and redefines /showpage again, then it should rename my /realshowpage to something different, and call it the same way: %!PS-Adobe-1.0 %%For: re-redefining the showpage operator /realshowpage.$$ /showpage load def /showpage { 90 rotate 0 -612 translate .5 .5 scale realshowpage.$$ } def In this case, the `/showpage load' will retrieve my version of /showpage from above, which in turn will call /realshowpage, which is actually the /showpage from systemdict. This can go on indefinitely, if you are willing to clutter up userdict with strange names. It basically boils down to a naming problem, not a PostScript problem. Glenn Reid Adobe Systems Incorporated