
- •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

be all you need to avoid syntactic problems when you are writing PostScript programs.
Here are some general rules of thumb to help you with PostScript language syntax. These rules should help you avoid common pitfalls.
•Make sure all your delimiters match; for instance, { }, ( ), and [ ]. Using good indentation style will help you avoid the problems of mismatched or missing delimiters.
•Use parentheses for string delimiters (rather than quotation marks, as used in other languages). If your string contains parentheses or backslashes, quote them with a backslash, as in the following string:
( this string contains two parens \) and \( a backslash \\ )
•Always use a slash that leans to the right for literal names, as in
/Palatino-Roman or /MyEncoding. There is nothing special about the slash, it just keeps the name from getting executed immediately. Instead, it lets the name be put on the operand stack.
•Remember that the operators always come after the operands (postfix notation). The order of the operands on the stack makes the rightmost operand the one at the top of the stack (closest to the operator itself).
•Spaces, tabs, and newlines are all treated as white space. Use them wisely to make your program layout more readable.
•Anything following a % (through the end of the line) is treated as a comment, unless the % is inside a string body (in parentheses).
In practice, you will probably not encounter very many syntax errors. It is much more likely that the execution of your program will go astray with a typecheck or stackunderflow error, indicating that you gave the wrong arguments to some operator. If you can look at the contents of the operand stack when the error occurs, you will usually be able to find the problem quickly.
SIMPLE PROGRAM STRUCTURE
There is no enforced structure to a PostScript program. You don’t need to start the program with a magic word like Begin, nor end it with anything special. You don’t have to declare variables at the beginning of the file,
20 |
Chapter 3: FOUNDATIONS |

you don’t have to declare procedures in any particular order. The only checking is done when you run the program. If it works, it works. If it doesn’t, you will get an error message explaining why it doesn’t work.
However, since most people who read your program (including you, most likely) are used to seeing some structure in code, there is a strong case for structuring your program carefully. If nothing else, it will help you to maintain the program, to update it and revise it as necessary.
Make Definitions First
Typically, a PostScript program contains a fair number of definitions, either procedure definitions or variables of some kind. In general, you should define these up front in the PostScript program. A good approach is to set up all the named objects you will need at the beginning of the program, then set up all the procedures, then begin to call them by name at the appropriate time. This is in fact very similar to the traditional structure found in other programming languages, where the definitions must come before the procedures. Example 3.2 shows some definitions of objects that can then be referenced by name later in the program.
Example 3.2: Defining and Using Named Objects
%an often-used font stored as a named object /headerfont /Times-Bold findfont 24 scalefont def
%using the named font object
headerfont setfont 72 600 moveto (Section 1.1) show
For PostScript page descriptions (documents), Adobe Systems has defined PostScript Document Structuring Conventions that break a document file down into several components. The first component, the prologue, consists only of definitions that may be referenced by the rest of the document. The rest of the document is composed of pages, with an optional setup section before the pages. These structuring conventions make it easier for post-processing programs such as print spoolers to manipulate the files in helpful ways.
In a PostScript program that is not a page description, these delineations don’t make quite as much sense, but it is still helpful to make the
Chapter 3: FOUNDATIONS |
21 |

definitions at the beginning of the program. An exception to this rule is that if a procedure requires some data structures for its operation but they must be defined outside the procedure, it is often best to group them with the procedure, to make the program easier to maintain (see Example 3.3).
Example 3.3: Keeping Variables with Procedure Definitions
/filebuff 1024 string def /countlines { %def
0 % counter on stack /fd (filename) (r) file def
{ %loop
fd filebuff readline { %ifelse pop 1 add
}{ %else
pop 1 add exit
} ifelse
}loop
}bind def
/specialchar (\037) def /parsestring { %def
specialchar search { pop pop
(after special char: ) print =
}{
(no special chars found: ) =
}ifelse
}bind def
Indentation Style
The single most important step you can take to make your program readable is to adopt a good indentation style. The PostScript language is very unstructured, and without proper indentation, it can be made quite impossible to read or maintain.
There are a few basic rules of indentation that you should observe, based on the structure of your program:
•Wherever one part of your program is contained within some clear beginning and ending constructs (such as gsave and grestore, begin and end, or curly braces), you should indent all of the included program text an equal amount.
22 |
Chapter 3: FOUNDATIONS |

•Use indentation to make it easy to find the beginning and ending of any matched construct visually.
•Be careful that adding and deleting lines from inside a structural element does not disturb the structure or readability of the program.
The indentation style used in the examples in this book is one developed over several years of maintaining programs, and it works well. There are other approaches, of course. The most common alternative to the method used in this book is to move the opening delimiters to a new line; this provides a much better balance, visually, to the delimiters, but it costs an extra line in the program (see Example 3.4). Extra lines don’t consume much space, but editing a program is much easier when you can see more of the program at once in the screen of your text editor.
Example 3.4: Alternative Indentation Style for Procedures
/mapgray |
% -mapgray - |
{ %def |
|
currentgray 0.5 gt |
|
{%ifelse
1.0setgray
}
{%else
0.0setgray
} ifelse
}bind def
It is also a good idea to indent other program elements that have distinct beginning and endings, such as begin and end with dictionaries, save and restore, gsave and grestore, [ and ]. Example 3.5 shows some of these indentation styles in a dummy program.
Chapter 3: FOUNDATIONS |
23 |