- •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
REARRANGING THE STACK
If you want to use the operand stack directly in your program, the chances are you will need to perform some stack manipulation. It’s almost unavoidable. There are a few operators that you will find indispensable for stack manipulation. There are also some techniques worth learning to help you keep bugs out of your stack exercises. Table 6.1 contains a summary of the stack operators in the PostScript language for quick reference. Don’t worry if you don’t understand how to use all the operators in the table; it will become more clear as you read on.
Table 6.1: PostScript Stack Manipulation Operators
Arguments Operator
±| any1 ... anyn clear
mark obj1 ... objn cleartomark
A B C 3 copy B C A B C
±| any1 ... anyn count any1 ... anyn n mark any_objects counttomark mark
any n
any dup any any any1 any2 exch any2 any1
D E F G 2 index D E F G E
± mark mark any pop ±
a b c d e f 3 -2 roll a b c f d e
Action
discard all elements
discard everything through mark duplicate top three elements count elements on stack
count elements down to mark
duplicate top element exchange top two elements
duplicate second element from top (where top is 0th element)
push mark on stack discard top element
take top three elements and roll negative two times
The most important operators for stack manipulation are dup, exch, index, and roll. Of these four operators, dup and exch are fairly easy to understand, since they apply only to the topmost item or items on the stack, but index and roll can be a bit more confusing.
Using the dup and index Operators
Although the dup operator is very simple in its operation, knowing when and how to use it effectively requires some skill in manipulating the operand stack. The index operator has almost exactly the same function as dup, except it will let you duplicate an object further down on the operand stack (dup duplicates only the topmost object). There are two or three places where these operators are used most commonly.
Chapter 6: TRUSTING THE STACK |
71 |
1.If you need to use a piece of data twice, use dup to make a temporary copy of the data. The copy will be used by the first operation, leaving the original data for the second operation.
2.When you are debugging, you can make a temporary copy of an object (using dup) to print or write to a debugging file without disturbing the execution of the program.
3.In a loop where you may need the same piece of data each time around the loop, that data can be left on the operand stack and it can be copied (with dup or index) each time before it is used inside the loop. Just make sure to remove it from the stack when you exit the loop. This technique can be seen in Example 6.2.
Example 6.2: Using index in a Loop Body
/Encoding 256 array def
Encoding % leave on operand stack throughout loop 0 1 255 { %for
1 index exch /.notdef put
} bind for pop
Using the roll Operator
The roll operator is one of the most useful stack operators, and one of the most confusing. Its purpose is to rearrange several of the topmost operands on the stack by rolling them. It takes two operands: one to supply the total number of elements to participate in the roll operation (this total is called the roll group in the following discussion) and the other to indicate how many elements within that total should actually be rolled (called the roll amount).
Let’s look at the anatomy of the roll operator (Figure 6.1).
72 |
Chapter 6: TRUSTING THE STACK |