Duplicates the top n elements on the operand stack, or copies the value of one composite object into another.
1. Description
The copy operator performs two entirely different functions depending on the type of the topmost operand:
-
Integer form: When the top element is a non-negative integer n,
copyduplicates the top n elements on the operand stack. -
Composite form: When operands are composite objects (arrays, strings, dictionaries, packed arrays, or gstate objects),
copycopies all elements from the first object into the second.
This dual functionality makes copy essential for both stack manipulation and creating independent copies of composite objects.
This is a Level 1 operator, available in all PostScript implementations.
2. Syntax
any1 ... anyn n copy any1 ... anyn any1 ... anyn
array1 array2 copy subarray2
dict1 dict2 copy dict2
string1 string2 copy substring2
packedarray1 array2 copy subarray2
gstate1 gstate2 copy gstate2
2.1. Stack Effect (Integer Form)
| Position | Content |
|---|---|
Top |
|
Top-1 to Top-n |
|
| Position | Content |
|---|---|
Top to Top-n+1 |
|
Top-n to Top-2n+1 |
|
5. Examples
5.1. Basic Usage - Integer Form
% Copy top 2 elements
1 2 3 2 copy % Stack: 1 2 3 2 3
% Copy top 3 elements
1 2 3 3 copy % Stack: 1 2 3 1 2 3
% Copy 0 elements (no-op)
1 2 3 0 copy % Stack: 1 2 3
5.2. Array Copying
% Copy array contents
/a1 [1 2 3] def
/a2 a1 length array def
a1 a2 copy % a2 now contains [1 2 3]
pop % Remove subarray result
% a1 and a2 now have independent values
a1 0 99 put % a1 is [99 2 3]
% a2 is still [1 2 3]
5.3. String Copying
% Copy string
/s1 (hello) def
/s2 s1 length string def
s1 s2 copy % s2 now contains (hello)
pop
% Modify independently
s1 0 72 put % s1 is (Hello) - 72 is 'H'
% s2 is still (hello)
6. Advanced Examples
6.1. Implementing Independent Array Copy
% Create true independent copy of array
/copyArray { % array -> newarray
dup length array copy
} def
[1 2 3] copyArray
% Stack: [1 2 3] (independent copy)
6.2. Duplicating Multiple Stack Items
% Keep top 3 values, duplicate them
/keep3 { % a b c ... -> a b c a b c ...
3 copy
} def
10 20 30 40 50 keep3
% Stack: 10 20 30 40 50 30 40 50
7. Edge Cases and Common Pitfalls
The integer form requires n+1 elements on the stack (n elements to copy plus n itself). Insufficient stack depth causes stackunderflow.
|
7.1. Stack Underflow
% BAD: Not enough elements
clear
1 2 % Only 2 elements
3 copy % ERROR: stackunderflow (needs 3 elements plus n)
7.2. Destination Too Small
% BAD: Destination array too small
[1 2 3 4 5] [1 2] copy % ERROR: rangecheck
% Destination must be at least as large as source
7.3. Type Mismatch
% BAD: Incompatible types
(hello) [1 2 3] copy % ERROR: typecheck
% Can't copy string to array
7.4. Shallow Copy Limitation
% CAUTION: Nested objects are shared
[[1 2] [3 4]] dup length array copy
% Outer array is independent
% But inner arrays are still shared!
0 get 0 99 put
% Modifies both copies' inner array
The composite form of copy performs only one level of copying. Nested composite objects are shared between source and destination.
|
9. PostScript Level
Available in: PostScript Level 1 and higher
The basic functionality is in Level 1. Level 2 adds gstate copying and relaxes some restrictions on dictionary copying.
10. Error Conditions
stackunderflow-
Integer form: The stack contains fewer than n+1 elements. Composite form: The stack contains fewer than 2 elements.
clear 1 2 3 copy % ERROR: stackunderflow stackoverflow-
Integer form: Copying would exceed stack capacity.
% Stack nearly full, copying would overflow rangecheck-
Composite form: Destination object is too small to hold source contents.
[1 2 3] [1] copy % ERROR: rangecheck typecheck-
Integer form: Top operand is not an integer. Composite form: Operands are not compatible types.
(not a number) copy % ERROR: typecheck [1 2] (string) copy % ERROR: typecheck invalidaccess-
Attempting to copy into a read-only object, or copying local VM objects into global VM.
[1 2 3] readonly [4 5 6] exch copy % ERROR: invalidaccess
11. Performance Considerations
Integer form: Very fast O(n) operation, simply duplicates stack references.
Composite form: O(n) where n is the number of elements. For large objects, this can be significant. The operation copies the elements themselves, not just references.
Dictionary copying: More expensive than array/string copying due to hash table operations.
12. Best Practices
-
Use for independent copies: When you need to modify a composite object without affecting the original, use
copy -
Integer form for stack preservation: Use
n copyto preserve stack state before operations that consume elements -
Check sizes: Always ensure destination is large enough when copying composite objects
-
Understand shallow copying: Remember that nested objects are shared after copying
-
Prefer copy over dup for values: Use
copywhen you need an independent value,dupwhen you can share
13. See Also
-
Operators Overview - Understanding PostScript operators
-
Stack Operations Guide - Stack manipulation tutorial
-
Composite Objects - Understanding object copying
-
Stack Manipulation - All stack operators