
- •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 11.3: Creating and Filling an Empty Array
10 array dup
/one /one /one (four) /five
6 /seven { 8 (the whole procedure) } 9 10 astore
CONSTRUCTING A STRING
Strings can be constructed in much the same way as arrays. You can create one at run-time in the original input program by using the notation found in Example 11.4 for simple strings or hexadecimal strings (also called hex strings).
Example 11.4: Creating Strings with the Scanner
(This is a string created at run-time; following is a hex string:) <a32989e4ff>
Hexadecimal strings are scanned two bytes at a time to create the single byte represented by the 8-bit number. (One byte of hexadecimal, since it is base 16, provides only 4 bits of data; it requires two bytes of hexadecimal to represent a full 8 bits.) Hex strings are generally used only for image data, strings for Kanji character sets, or other places where full 8-bit string data must be used. The string operator can also be used to create an empty string body, and you can use put or putinterval to put bytes into the string.
MANIPULATING DATA WITH PUT AND GET
Strings and arrays are composite data structures. They are both represented by single objects, but really they are composed of collections of objects. There are a few different ways to read and write the contents of these composite data structures, included in Table 11.1. The fundamental mechanism is the family of put and get operators. We’ll start with the simplest ones.
Chapter 11: CREATING AND MANIPULATING DATA |
137 |

Table 11.1: Operators to put and get Data
Arguments Operator |
Action |
|
array |
length int |
number of elements in array |
array index |
get any |
get array element indexed by index |
array index any |
put ± |
put any into array at index |
array index count |
getinterval subarray |
subarray of array starting at |
|
putinterval ± |
index for count elements |
array1 index array2 |
replace subarray of array1 starting |
|
|
aload a0...an-1 array |
at index by array2 |
array |
push all elements of array on stack |
|
any0 ... anyn-1 array |
astore array |
pop elements from stack into array |
array1 array2 |
copy subarray2 |
copy elements of array1 to initial |
|
forall ± |
subarray of array2 |
array proc |
execute proc for each element of |
|
|
|
array |
int |
string string |
create string of length int |
string |
length int |
returns the number of elements in |
|
|
string |
string index |
get int |
get string element indexed by index |
string index int |
put ± |
put int into string at index |
string index count |
getinterval substring |
substring of string starting at index |
|
putinterval ± |
for count elements |
string1 index string2 |
replace substring of string1 starting |
|
|
copy substring2 |
at index by string2 |
string1 string2 |
copy elements of string1 to initial |
|
|
|
substring of string2 |
The put operator requires three arguments: the thing you want data put into, the key or position in that composite data structure where you want the data put, and finally the piece of data itself that is to be added (see Example 11.5).
Example 11.5: Anatomy of the put Operator
% data_structure position_key new_data put currentdict /key (value) put
10 array 0 (first element) put (XXXXX) 4 (a) put
The putinterval operator is similar to put, but the piece of data you supply needs to be of the same type as the data structure into which you are putting it. The data gets copied from the supplied data into the destination, rather than putting just one piece of data (see Example 11.6).
138 |
Chapter 11: CREATING AND MANIPULATING DATA |