
- •Preface
- •DESIGN FEATURES
- •STRUCTURED PROGRAMMING TECHNIQUES
- •PROGRAMMING TASKS
- •WINDOW SYSTEMS, COMMUNICATIONS, AND DISPLAYS
- •DATA STRUCTURES AND ALGORITHMS
- •CONCLUDING THOUGHTS
- •PostScript is Not Like C
- •COMPARISON OF LANGUAGE MECHANISMS
- •EXPRESSING AN ALGORITHM AS A PROGRAM
- •THE UNIX SHELL AND OPERATING SYSTEM
- •INPUT, OUTPUT, AND THROUGHPUT
- •CONCLUDING THOUGHTS
- •Foundations
- •POSTSCRIPT LANGUAGE SYNTAX
- •SIMPLE PROGRAM STRUCTURE
- •Make Definitions First
- •Indentation Style
- •SETTING UP TEMPLATES
- •DECLARING AND USING VARIABLES
- •Arithmetic with Numeric Variables
- •Using the // Notation for Constants
- •ALLOCATING MEMORY
- •GETTING MEMORY BACK
- •OPENING AND CLOSING FILES
- •COMPARISONS AND EQUALITY OF OBJECTS
- •CONCLUDING THOUGHTS
- •Some Typical Programs
- •A TYPICAL PAGE DESCRIPTION PROGRAM
- •FONT PROGRAMS
- •PROGRAMS THAT READ DATA
- •QUERY PROGRAMS
- •ENCAPSULATED POSTSCRIPT PROGRAMS
- •PERSISTENTLY RESIDENT PROGRAMS
- •CONCLUDING THOUGHTS
- •Understanding the Stack
- •A QUICK OVERVIEW OF DATA TYPES
- •NAME LOOKUP
- •HOW OPERATORS USE THE STACK
- •GROUPING AND VISUAL CHUNKING
- •THINKING BACKWARD AND SIDEWAYS
- •COMPOSITE OBJECTS
- •THE OTHER STACKS
- •The Dictionary Stack
- •The Execution Stack
- •The Graphics State Stack
- •CONCLUDING THOUGHTS
- •Trusting the Stack
- •SAFETY OF DATA ON THE STACK
- •WHERE ARE THE DATA GOING?
- •REARRANGING THE STACK
- •Using the dup and index Operators
- •Using the roll Operator
- •CONDITIONALS AND LOOPS
- •RECURSION AND LOCAL VARIABLES
- •CONCLUDING THOUGHTS
- •Building Conditional Statements
- •SIMPLE CONDITIONALS
- •SETTING UP THE CONDITION
- •CONDITIONALS ARE NOT MAGIC
- •NESTED CONDITIONALS AND ELSE CLAUSES
- •COMPOUND CONDITIONALS
- •CONCLUDING THOUGHTS
- •Using Looping Constructs
- •LOOP BASICS
- •USING THE LOOP INDEX
- •LOOPS ARE PROCEDURE BODIES
- •LOOPS OF INSTRUCTIONS
- •EXITING LOOPS PREMATURELY
- •CONCLUDING THOUGHTS
- •Procedures
- •WHAT EXACTLY IS A PROCEDURE?
- •PARAMETER PASSING
- •CONSTRUCTING GOOD PROCEDURES
- •What to Name Your Procedure
- •A Useful Naming Convention
- •SELF-MODIFYING PROCEDURES
- •CONCLUDING THOUGHTS
- •Using Dictionaries
- •DICTIONARIES FOR NAME SCOPING
- •LOCAL DICTIONARIES
- •GLOBAL DICTIONARIES OF PROCEDURES
- •MAINTAINING THE DICTIONARY STACK
- •INTO AND OUT OF DICTIONARIES
- •LOOKING INTO DICTIONARIES
- •Using the forall Operator
- •Using the where and known Operators
- •REDEFINING OPERATORS
- •Changing the Behavior of Operators
- •Debugging with Redefined Names
- •Proper Nesting of Redefinitions
- •CONCLUDING THOUGHTS
- •Creating and Manipulating Data
- •CONSTRUCTING AN ARRAY
- •CONSTRUCTING A STRING
- •MANIPULATING DATA WITH PUT AND GET
- •CONCATENATING ARRAYS AND STRINGS
- •INPUT AND OUTPUT OF STRING DATA
- •ARRAYS VERSUS DICTIONARIES
- •ADVANCED TECHNIQUES
- •CONCLUDING THOUGHTS
- •Storing and Using Data
- •Data and the Operand Stack
- •Data and Algorithms for Underlining
- •CLASSICAL DATA STRUCTURES
- •Linked Lists
- •Using Arrays to Form Lists
- •Using Dictionaries to Form Lists
- •Queues, Trees, and Other Data Structures
- •CONCLUDING THOUGHTS
- •Program Data and Instructions
- •TURNING DATA INTO INSTRUCTIONS
- •TURNING INSTRUCTIONS INTO DATA
- •DATA CONVERSIONS
- •CONCLUDING THOUGHTS
- •File Objects
- •Streams and Files
- •PostScript File Operators
- •OPENING AND CLOSING FILES
- •READING AND WRITING FILES
- •Reading from a File
- •Writing to a File
- •Copying and Renaming Files
- •WRITING FORMATTED DATA TO FILES
- •Writing Out Various Data Types
- •Spaces, Tabs, Returns, and Special Characters
- •FILE STATUS INFORMATION
- •RANDOM VERSUS SEQUENTIAL ACCESS
- •CONCLUDING THOUGHTS
- •Appendix
- •Answers to Exercises

mark and boolean are created by the PostScript operators mark, true, or false, or as side effects of some other operators such as known or search.
NAME LOOKUP
|
The standard method for retrieving something that has been stored into a |
|
dictionary is to use the name lookup mechanism. An executable name |
|
encountered by the interpreter is looked up in the context of the current |
|
dictionary stack, and if there is an entry corresponding to that name, the |
|
value will be placed on the operand stack—with one notable exception. If |
|
you happen to retrieve a procedure body (an executable array object) |
|
under the name you look up, that procedure will be placed on the |
|
execution stack and immediately executed, rather than being placed on |
|
the operand stack and treated as data. |
|
|
|
|
TIP |
If you need to retrieve a procedure body that you have stored into a dictio- |
|
nary, but don’t want to execute it just yet, you can get a copy of it onto the |
|
operand stack using the load operator, using the name of your procedure |
|
(with the leading slash, to make it a literal name) as the argument to load. |
|
|
|
|
When a name is looked up, the dictionary stack is searched from the top down, and the first instance of the key that is encountered is the one that is used. That enables you to redefine a name that is already built into the PostScript language, although you should do so with great care (see Redefining Operators in Chapter 10 for further discussion of this topic).
HOW OPERATORS USE THE STACK
The operand stack is a global communication area for all PostScript programs. All operators look for their operands on the stack and produce results there, although they may also produce side effects such as marks on the page, changes to the graphics state, or changes to the contents of memory.
Let’s look at a very simple program to follow the use of the operand stack (See Example 5.1).
Chapter 5: UNDERSTANDING THE STACK |
53 |

|
Example 5.1: Simple Use of the Operand Stack |
|
/Times-Roman 12 selectfont |
|
/Xlocation 100 def |
|
/Ylocation 200 def |
|
Xlocation Ylocation moveto |
|
(text sample) show |
|
This code segment looks like a definition of two variables, Xlocation and |
|
Ylocation, which are then used as the coordinates for the moveto |
|
operator. From the point of view of stack manipulation, the def operator |
|
simply takes two objects from the stack and puts them in the current |
|
dictionary, and the subsequent name lookup of, say, Xlocation, retrieves |
|
the object associated with that key from the current dictionary. As shown |
|
in Figure 5.2, by the time you get to moveto, there are no variables or |
|
anything else left; there are just two numbers on the operand stack, which |
|
is what is required by the moveto operator. So in effect, the numbers 100 |
|
and 200 start out on the operand stack, are stored into a dictionary, |
|
retrieved from that dictionary back onto the operand stack, and used by |
|
the moveto instruction. A variable is a name used to reference data. |
|
|
TIP |
When you define a variable in your PostScript program, you are actually |
|
taking something off the operand stack and putting it into a dictionary. In |
|
order to use the variable, you must always recall it from the dictionary |
|
back onto the operand stack. Be aware that using “variables” is always |
|
somewhat slower than using the operand stack directly. |
|
|
|
To understand how the operand stack works, it is worthwhile to step |
|
through a simple program, executing it in your head. It is important |
|
enough that you might spend some real time at this, until you are |
|
extremely comfortable talking through a program, understanding exactly |
|
what happens to it as it is being executed. |
54 |
Chapter 5: UNDERSTANDING THE STACK |

Figure 5.2: Tracing the Execution of Example 5.1
|
|
|
|
represents the operand stack |
|
|
|
|
|
|
lines from the |
|
|
|
|
|
|
|
|
100 |
|
|
program |
|
|
|
|
|
|
/Xlocation |
|
/Xlocation |
|
|
|
|
|
|
|
|
|
/Xlocation |
100 |
|
def |
|
|
200 |
|
|
/Ylocation |
|
/Ylocation |
|
|
|
|
|
|
|
/Ylocation |
200 |
|
def |
|
|
200 |
|
|
100 |
|
100 |
|
|
|
|
|
|
|
Xlocation |
|
Ylocation |
|
moveto |
(text sample) |
|
(text sample) |
show |
All PostScript operators expect their operands in a particular, fixed order. For example, the put operator requires the following operands:
compositeobject index value put
Chapter 5: UNDERSTANDING THE STACK |
55 |