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

Although the run operator can perform precisely this task, the technique of looping through a file is still useful in many situations.
Example 13.5: Executing Data Found in a File
/datafile (/usr/local/lib/sample.ps) (r) file def /buffer 1024 string def
{ %loop
datafile buffer readline { %ifelse
cvx exec % execute the line of data just read }{ %else
datafile closefile exit
}ifelse
}bind loop
This simplistic program won’t work with all data files, since it attempts to execute exactly one line of the program at a time. If any delimiters such as parentheses or braces are opened on one line but not closed until a subsequent line, the code will not execute correctly.
TURNING INSTRUCTIONS INTO DATA
A good example of turning program instructions into data is the task of listing (or printing out) a PostScript program so you can look at it on paper. You may have already run into this situation if you have worked much with the PostScript language. The previous example program that works as a simple line printer emulator actually does convert PostScript program code into data for typesetting if you should happen to feed it a file that contains PostScript. Example 13.6 shows this same emulator with slightly different data at the end. You might have to look closely to see that last ten lines of the program are not executed, but are printed on the page.
Figure 13.1 shows what the top of the output page would look like when the program in Example 13.6 is executed.
Chapter 13: PROGRAM DATA AND INSTRUCTIONS |
161 |

Example 13.6: Instructions as Data (to be Line Printed)
% even more line printer emulation /left 36 def % margins /bottom 36 def
/top 792 48 sub def /buffer 1024 string def
/setup |
% - setup - |
{ %def |
|
/Courier 12 selectfont left top moveto
} bind def
/emulate % - emulate - { %def
{ %loop
currentfile buffer readline { %ifelse
(X) search { %ifelse
gsave show grestore pop showpage setup
} if
gsave show grestore 0 -14 rmoveto
currentpoint exch pop bottom le { %if showpage setup
} if }{ %else
showpage exit
} ifelse
}loop
}bind def
%everything after the following “setup emulate” line will be printed on
%paper instead of executed:
setup emulate %!
/datafile (/usr/local/lib/sample.ps) (r) file def /buffer 1024 string def
{ %loop
datafile buffer readline { %ifelse
cvx exec % execute the line from the file }{ %else
datafile closefile exit
}ifelse
}bind loop
162 |
Chapter 13: PROGRAM DATA AND INSTRUCTIONS |

Figure 13.1: Output of Example 13.6
output page
%!
/datafile (/usr/local/lib/sample.ps) (r) file def /buffer 1024 string def
{ %loop
datafile buffer readline { %ifelse
cvx exec % execute the line from the file }{ %else
datafile closefile exit
}ifelse
}bind loop
DATA CONVERSIONS
Quite a few PostScript operators convert one data type to another. Once you know that they exist, they are easy enough to use. There are also some fancy ways to accomplish data conversion in the next few sections. But first, some examples of common data conversions using the appropriate PostScript operators (see Example 13.7).
Example 13.7: Converting Strings to Numbers
(12456) cvi |
% 12456 |
(2898.87) cvi |
% 2899 |
(117.5) cvr |
% 117.5 |
(120) cvr |
% 120.0 |
(5837.9) cvx exec |
% 5837.9 |
(612.0) token pop exch pop |
% 612.0 |
(612.0 792.0 moveto) token pop |
|
exch token pop exch pop |
% 612.0 792.0 |
Example 13.8 shows the conversion of decimal numbers to an octal or hexadecimal representation (the result is a string, since octal numbers do not exist in the interpreter except as notation).
Chapter 13: PROGRAM DATA AND INSTRUCTIONS |
163 |

Example 13.8: Converting Decimal Numbers to Octal or Hex
/scratch (0000) def |
|
32 8 scratch cvrs |
% (40) |
193 16 scratch cvrs |
% (C1) |
(y) 0 get 16 scratch cvrs |
% (79) |
The program segments shown in Example 13.9 show how to convert back and forth between name and string data types, which are very similar in content. Remember that the slash (/) character often seen in programs is not really part of the name, but just the syntax used to express a literal name to the interpreter.
Example 13.9: Converting between Names and Strings
/scratch 128 string def |
|
/Palatino-Roman scratch cvs |
% (Palatino-Roman) |
(Palatino-Roman) cvn |
% /Palatino-Roman |
Example 13.10 shows one way to convert an array to a procedure. Since arrays are built in real time, you have to be careful not to accidentally execute something that you intend to be placed on the operand stack.
Example 13.10: Converting Arrays to Procedures
% careful about executable names:
[
0 0 /moveto cvx
/Optima 24.0 /selectfont cvx (Optima sample) /show cvx
] cvx
The cvs operator converts arbitrary data types to strings, which can be useful for printing out data. However, the cvs operator cannot convert composite objects like dictionaries or arrays to a string representation. An example of this simple kind of conversion is given in Example 13.11, with a workaround for composite objects. A better approach would be to use the type operator to explicitly determine the type of the object, then take some appropriate action to convert it to a string. Exercise 3 at the end of this chapter explores this concept more fully.
164 |
Chapter 13: PROGRAM DATA AND INSTRUCTIONS |