Unrolling PostScript "for" loops

Sun Aug 29 15:39:40 BST 2016

The three files that relate to the video on unrolling PostScript for loops are:

original PostScript program called "computerphile.ps"

An unrolled version of "computerphile.ps" called flattened.ps

the PostScript program "transform.ps" that does the unrolling

Here are some notes on executing these programs on UNIX/Linux, using Peter Deutsch's "GhostScript" - a widely available and reliable PostScript clone. Ghostscript is also available for Windows PCs but the Windows namings for the GhostScript/Ghostview commands may differ slightly from the UNIX/Linux versions shown below.

On UNIX/Linux

The GhostScript (gs) program is widely distributed and may even be already installed. A popular viewing program that sits on top of the basic gs engine is called GhostView ( gv). The graphic effect of the original program can be seen by doing:
$ gv computerphile.ps

from the command line.

Equally the flattened version can be executed via:

$ gv flattened.ps

GhostScript is configured via the shell variable GS_FONTPATH as to where it searches for fonts. The program asks for the OCR-A font (with internal font name of OCRA). If this is unavailable the screen display will (probably) use Courier.

To run the transformation script you need (preferably) to turn off the graphic display, run in quiet mode and collect the standard output from gs. I achieved this via:

$ gs -dNODISPLAY -q transform.ps > unrolled.ps
from the command line. Notice that the gs program, even in quiet mode, wants to prompt you for more input if it runs off the end of your PostScript input file. The PostScript quit command within transform.ps stops it doing this.

If you now do

$ gv unrolled.ps
you should find that it gives you exactly the same graphical effects, when executed, as the original computerphile.ps did. Moreover, the unrolled.ps you have created should be identical to the file flattened.ps that I have supplied.

How does 'transform' work?

The overall idea is to identify the operators that actually have a graphic effect when they are executed. In the present case these are moveto, show, selectfont and showpage. We then use PostScript's very handy capability of allowing operators to be redefined.

You will notice, at the top of transform.ps, that these four operators have been altered so that they no longer perform the usual graphic effect. Instead they write onto the standard output a copy of how they were called, thereby creating a sort of "execution trace" rather than actually doing the graphic execution. In the redefinitions, the opportunity is taken to use abbreviations. Hence, for example, show becomes s and moveto becomes m.

The next step in transform's operation is to encounter what appears to be further definitions for things like s and m.

But these are NOT redefinitions! The '=' sign at the end of the line is a PostScript command to print out, to standard output, everything that precedes it on the line.

The net result therefore is that unrolled.ps -- the output file created by transform.ps -- begins with definitions for /s, /m, /sf and /sp and then contains six lines produced by traversing the inner for loop in an environment where the moveto and show operations within that loop have been redefined so that they don't have any graphic effects. Instead they simply write out, into unrolled.ps, calls to invoke the newly defined /s and /m.

Finally the showpage operation at the bottom of computerphile.ps is abbreviated to a call of sp, which is, in turn, defined so as to execute a showpage anyway .

So if unrolled.ps is now executed using gv the graphical effect of the linearized code should be exactly the same as the original for loop version and exactly the same as the supplied file flattened.ps.

Note that linearizing the code -- as in this example -- can be extended to removing if statements and procedure calls. Provided all the needed data is present the execution will follow a path through the program that is determined by that data. As we have seen above, all that is necessary is to redefine, and to write out an execution trace, for all those operators that alter the graphic state. The written out execution trace is itself a linearized and executable PostScript program.