- 1. Error Handling
1. Error Handling
Error handling is a fundamental aspect of writing robust PostScript programs. This guide provides an overview of error handling strategies and best practices suitable for all skill levels.
1.1. Overview
Error handling in PostScript involves:
-
Understanding errors - Types and causes
-
Detecting errors - Catching and identifying issues
-
Recovering from errors - Graceful degradation
-
Preventing errors - Defensive programming
-
Reporting errors - Clear diagnostics
Good error handling makes programs more reliable and easier to debug.
1.2. Common Error Types
1.2.1. Operational Errors
Errors that occur during normal operation:
% stackunderflow - not enough operands
pop % ERROR: empty stack
% typecheck - wrong type
5 (text) add % ERROR: incompatible types
% rangecheck - value out of range
-5 array % ERROR: negative size
% undefinedresult - invalid operation
1 0 div % ERROR: division by zero
1.3. Basic Error Handling
1.3.1. The stopped Operator
Primary error catching mechanism:
% stopped: mark proc stopped -> true | false
{
% Code that might error
1 0 div
} stopped {
% Error occurred
(Error: Division by zero) print
} {
% Success
(Division succeeded) print
} ifelse
1.4. Error Prevention
1.4.1. Input Validation
/divide { % a b -> result
% Validate input
dup 0 eq {
pop pop
(Error: divisor cannot be zero) print
/divisionbyzero cvx
} {
div
} ifelse
} def
1.5. Error Reporting
1.6. Practical Error Handling
1.6.1. File Operations
/safeFileRead { % filename -> content true | false
{
(r) file
dup 1024 string exch readstring pop
exch closefile
true
} stopped {
pop
(Could not read file) print
false
} ifelse
} def
% Usage
(data.txt) safeFileRead {
(File contents: ) print print
} {
(Using default data) print
} ifelse
1.6.2. Array Operations
/safeArrayAccess { % array index -> element true | false
{
get
true
} stopped {
pop pop
false
} ifelse
} def
% Usage
[10 20 30] 5 safeArrayAccess {
= % Got element
} {
(Index out of range) print
} ifelse
1.6.3. Calculation Safety
/safeCalculate { % proc -> result true | errorMessage false
{
exec
true
} stopped {
$error /errorname get
=string cvs
( error occurred) concatstrings
false
} ifelse
} def
% Usage
{ 10 5 div } safeCalculate {
(Result: ) print =
} {
(Calculation failed: ) print print
} ifelse
1.7. Error Handling Patterns
1.7.1. Try-Catch Pattern
/try { % tryProc catchProc -> -
exch
{
exec
} stopped {
exec
} if
pop
} def
% Usage
{
% Try this
1 0 div
} {
% Catch errors here
(Caught division error) print
} try
1.7.2. Default Value Pattern
/getOrDefault { % proc defaultValue -> result
exch
{
exec
} stopped {
% Return default on error
} if
} def
% Usage
{ nonexistent_variable } 42 getOrDefault
% Returns 42 if variable doesn't exist
1.7.3. Retry Pattern
/retry { % proc maxAttempts -> result
1 dict begin
/attempts exch def
/proc exch def
1 1 attempts {
/attempt exch def
{
proc exec
exit % Success
} stopped {
attempt attempts lt {
(Retry attempt ) print attempt 1 add =
} {
(All attempts failed) print
stop
} ifelse
} ifelse
} for
end
} def
1.8. Best Practices
1.8.1. Always Handle Errors
% Good: error handled
{
risky_operation
} stopped {
(Operation failed, using fallback) print
} if
% Bad: error ignored
risky_operation % Might crash program
1.8.2. Provide Clear Messages
% Good: descriptive error
dup 0 eq {
(Error: Cannot divide ) print
2 index =string cvs print
( by zero) print
stop
} if
% Bad: generic error
dup 0 eq { stop } if
1.9. Testing Error Handling
1.10. Common Pitfalls
1.10.1. Swallowing Errors
% Wrong: hides problems
{ operation } stopped pop
% Correct: log or handle
{ operation } stopped {
(Error occurred) print
} if
1.10.2. Not Checking Return Values
% Wrong: assumes success
file string readline pop
% Correct: check boolean
file string readline {
% Success - got line
} {
% EOF or error
} ifelse
1.10.3. Incomplete Error Handling
% Wrong: only handles one error
{ operation } stopped {
$error /errorname get /ioerror eq {
(IO error) print
} if
% Other errors ignored!
} if
% Correct: handle all cases
{ operation } stopped {
$error /errorname get
dup /ioerror eq {
(IO error) print
} {
(Other error: ) print =
} ifelse
} if
1.11. Quick Reference
1.11.1. Error Types
% Common errors:
% - stackunderflow: not enough values
% - typecheck: wrong type
% - rangecheck: out of range
% - undefined: name not found
% - VMerror: out of memory
% - ioerror: file error
% - syntaxerror: syntax error
1.12. Next Steps
For more detailed error handling:
-
Debugging - See Debugging Guide for debugging techniques
-
Advanced Error Handling - See Advanced Error Handling for complex scenarios
-
Resource Management - See Resource Management for resource-related errors
1.13. See Also
-
Debugging - Debugging techniques
-
Advanced Error Handling - Detailed error handling
-
File Operations - File error handling
-
Stack Operations - Stack error prevention
-
stopped command - Error catching operator