Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Reid G.C.Thinking in PostScript.1990.pdf
Скачиваний:
17
Добавлен:
23.08.2013
Размер:
846.44 Кб
Скачать

REDEFINING OPERATORS

There are very often instances in which you want to change the behavior of your program, even just temporarily, by redefining some of the names in it before the program executes. This has many possible uses, for debugging, page accounting, distilling documents into another form, or adding to the functionality of an existing program.

As you have learned, name lookup is done in the context of the dictionary stack. There are correspondingly two basic ways to redefine a name nondestructively.

Make a simple redefinition in the current dictionary with def.

Push a special dictionary onto the dictionary stack into which the redefinitions are placed.

If you put the redefinitions in a separate dictionary, then it is easy to put them in place or remove them temporarily, simply by pushing or popping the dictionary from the dictionary stack. However, this method is a little bit more subject to problems, since the program may inadvertently remove your special dictionary from the dictionary stack, or try to write into it as if it were its own dictionary.

Changing the Behavior of Operators

When you redefine an operator to have some other behavior beyond or instead of its default, you must take care to preserve at least the way in which the operator interacts with the operand stack, and you probably need to simulate some of the side effects, as well. For example, the moveto operator pops two numbers off the stack and installs a current point into the graphics state. If you redefine moveto, you should at least make sure to pop exactly two numbers from the stack, and you probably ought to establish a current point while you’re at it, if you want the program to continue to execute beyond the next instruction or so (without generating a nocurrentpoint error). One very good way to accomplish this is simply to invoke the original definition of the name when you are finished with your extensions. Example 10.11 shows a redefinition of showpage that adds a “draft” notice onto the edge of the document as it is being printed. The original (or previous, to be more accurate) definition of

130

Chapter 10: USING DICTIONARIES

showpage is loaded at the beginning, and is executed from within the redefined showpage procedure:

Example 10.11: Redefining showpage to Print Draft Notice

/startingCTM matrix currentmatrix def /old_showpage /showpage load def /showpage % - showpage - { %def

gsave

startingCTM setmatrix 90 rotate 30 -590 moveto

/Helvetica-Bold findfont 24 scalefont setfont (DRAFT document. Please destroy promptly.) show

grestore old_showpage

} bind def

Debugging with Redefined Names

A very good way to track the execution of your program is to redefine one of the operations in it to produce some extra tracking information as it is being called. For instance, you could redefine the show operator to echo each string back to the standard output file as it is being printed, or you could redefine the moveto operator to watch for coordinates that are off the page and to warn you. Then, once you get the program working, you can simply remove your redefinitions, and the program should work without further modification.

Example 10.12 contains a simple redefinition of the show operator that will track each string as it is being printed.

Example 10.12: Redefining show to Help Debugging

/old_show /show load def

/show % (string) show - { %def

dup == flush old_show

} bind def

Chapter 10: USING DICTIONARIES

131