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

Example 8.1: Simple Loop to Draw an Octagon
4 setlinewidth
300 200 moveto
7 { %repeat
0 100 rlineto
45rotate
}bind repeat closepath stroke
Figure 8.1: Output of Example 8.1
output page
starting point 300,200
USING THE LOOP INDEX
Looping operators are useful because they let a task be performed more than once. They can be even more useful when you keep track of the loop index and use it effectively.
Chapter 8: USING LOOPING CONSTRUCTS |
95 |

Example 8.2: Ignoring Loop Index
gsave
250 250 translate
0 10 360 { %for
pop % do not use loop index this time 0 -50 moveto 200 0 lineto 0 50 lineto
10 rotate
} for stroke
grestore
Example 8.2 sets up the loop index to give 10-degree increments around a circle, but actually does not use the loop index explicitly within the loop. The results are shown in Figure 8.2.
Figure 8.2:Output of Example 8.2
output page
In Example 8.3 is a short program that uses the loop index to set the line weight of a series of stroked lines and to control their spacing; its results are shown in Figure 8.3.
96 |
Chapter 8: USING LOOPING CONSTRUCTS |

Example 8.3: Using Loop Index for Line Weight
00 100 translate
2 3 div setgray 0 0 612 250 rectfill
0 setgray
2 2 20 { %for
dup setlinewidth % use loop index as line weight 0 exch 12 mul moveto% and use for line spacing 612 0 rlineto
stroke
} for
Figure 8.3: Output of Example 8.3
output page
When using a loop index, make sure you either pop the unwanted data off the stack or use it within the loop body, or you will leave unwanted data on the operand stack which may affect other portions of the program.
Several looping operators push data onto the stack each time around the loop. In particular, the forall operator pushes each element of an array or string onto the stack; it pushes both the key and value for each dictionary entry onto the stack. Table 8.2 provides a summary of each looping operator and the data that are pushed onto the stack for each iteration of the loop.
Chapter 8: USING LOOPING CONSTRUCTS |
97 |

TIP |
Don’t forget that the for, forall, kshow, and filenameforall looping oper- |
|
|
ators push values onto the operand stack that must either be used or |
|
|
popped from the stack. |
|
|
|
|
|
Table 8.2: Arguments Supplied by Looping Operators |
|
|
Operator |
Data Pushed onto Operand Stack for Each Iteration |
|
for |
loop index (integer) |
|
forall |
for strings: integer ASCII code for each byte of string |
|
|
for arrays: each element of the array, of arbitrary type |
|
|
for dictionaries: both the key and the value for each entry |
|
kshow |
character code for character just printed and for the |
|
|
character about to be printed |
|
loop |
none |
|
repeat |
none |
|
filenameforall |
a string containing each file name that matches the pattern |
Example 8.4 shows both a forall loop and a filenameforall loop being used to find out all the font names defined in FontDirectory and on the disk of a printer. Notice the way that the data are used inside the loop bodies.
Example 8.4: Finding Font Names with Looping Operators
/scratch 128 string def FontDirectory { %forall
pop % get rid of “value” part of dictionary entry scratch cvs print (\n) print
} bind forall
(fonts/*) { %filenameforall
dup length 6 sub 6 exch getinterval print (\n) print } scratch filenameforall
As you can see, there are a lot of ways to use the looping operators effectively, especially if you take advantage of the operators that push data onto the operand stack during execution of the loop body.
98 |
Chapter 8: USING LOOPING CONSTRUCTS |