blob: dab313c51f69564bca599bffed6d44291c5c3780 [file] [log] [blame]
rsc13f73912004-05-15 23:45:13 +00001%
2% Dump a PostScript object, occasionally in a form that can be sent back
3% through the interpreter. Similiar to Adobe's == procedure, but output
4% is usually easier to read. No binding so operators like rcheck and exec
5% can be conviently redefined.
6%
7
8/GrabitDict 100 dict dup begin
9
10/recursive true def
11/scratchstring 200 string def
12/slowdown 100 def
13
14/column 0 def
15/lastcolumn 80 def
16/level 0 def
17/multiline 100 array def
18/nextname 0 def
19/arraylength 0 def
20/lengthonly false def
21
22/GrabitSetup {
23 counttomark {OmitNames exch true put} repeat pop
24 0 0 moveto % for hardcopy output
25} def
26
27/OmitNames 30 dict def % ignore these names
28/OtherDicts 200 dict def % unrecognized dictionaries
29
30%
31% All strings returned to the host go through Print. First pass through an
32% array has lengthonly set to true.
33%
34
35/Print {
36 dup type /stringtype ne {scratchstring cvs} if
37 lengthonly {
38 length arraylength add /arraylength exch def
39 }{
40 dup length column add /column exch def
41 print flush
42 slowdown {1 pop} repeat
43 } ifelse
44} def
45
46/Indent {level {( ) Print} repeat} def
47/Newline {(\n) Print lengthonly not {/column 0 def} if} def
48
49/NextLevel {/level level 1 add def multiline level 0 put} def
50/LastLevel {/level level 1 sub def} def
51
52%
53% Make a unique name for each unrecognized dictionary and remember the name
54% and dictionary in OtherDicts.
55%
56
57/Register {
58 dup type /dicttype eq {
59 /nextname nextname 1 add def
60 dup (UnknownDict ) dup
61 (UnknownDict) length nextname ( ) cvs putinterval
62 0 (UnknownDict) length nextname ( ) cvs length add getinterval cvn
63 exch OtherDicts 3 1 roll put
64 } if
65} def
66
67%
68% Replace array or dictionary values by known names. Lookups are in the
69% standard PostScript dictionaries and in OtherDicts. If found replace
70% the value by the name and make it executable so nametype omits the
71% leading /.
72%
73
74/Replace {
75 false
76 1 index type /dicttype eq {pop true} if
77 1 index type /arraytype eq 2 index xcheck not and {pop true} if
78 {
79 false
80 [userdict systemdict statusdict serverdict OtherDicts] {
81 {
82 3 index eq
83 {exch pop exch pop cvx true exit}
84 {pop}
85 ifelse
86 } forall
87 dup {exit} if
88 } forall
89 pop
90 } if
91} def
92
93%
94% Simple type handlers. In some cases (e.g. savetype) what's returned can't
95% be sent back through the interpreter.
96%
97
98/booleantype {{(true )}{(false )} ifelse Print} def
99/marktype {pop (mark ) Print} def
100/nulltype {pop (null ) Print} def
101/integertype {Print ( ) Print} def
102/realtype {Print ( ) Print} def
103/filetype {pop (-file- ) Print} def
104/fonttype {pop (-fontID- ) Print} def
105/savetype {pop (-saveobj- ) Print} def
106
107%
108% Special formatting for operators is enabled if the flag in multiline
109% (for the current level) is set to 1. In that case each operator, after
110% being printed, is looked up in OperatorDict. If found the value is used
111% as an index into the OperatorProcs array and the object at that index
112% is retrieved and executed. Currently only used to choose the operators
113% that end a line.
114%
115
116/operatortype {
117 dup Print ( ) Print
118 multiline level get 1 eq {
119 scratchstring cvs cvn dup OperatorDict exch known {
120 OperatorDict exch get
121 OperatorProcs exch get exec
122 }{
123 pop
124 column lastcolumn gt {Newline Indent} if
125 } ifelse
126 }{pop} ifelse
127} def
128
129%
130% Executable names are passed to operatortype. Non-executable names get a
131% leading /.
132%
133
134/nametype {
135 dup xcheck {
136 operatortype
137 }{
138 (/) Print Print ( ) Print
139 } ifelse
140} def
141
142%
143% Arrays are processed in two passes. The first computes the length of the
144% string returned to the host without any special formatting. If it extends
145% past the last column special formatting is enabled by setting a flag in
146% array multiline. Arrays are processed in a for loop so the last element
147% easily recognized. At that point special fortmatting is disabled.
148%
149
150/packedarraytype {arraytype} def
151
152/arraytype {
153 NextLevel
154 lengthonly not {
155 /lengthonly true def
156 /arraylength 0 def
157 dup dup type exec
158 arraylength 20 gt arraylength column add lastcolumn gt and {
159 multiline level 1 put
160 } if
161 /lengthonly false def
162 } if
163
164 dup rcheck not {
165 (-array- ) Print pop
166 }{
167 dup xcheck {({)}{([)} ifelse Print
168 multiline level get 0 ne {Newline Indent}{( ) Print} ifelse
169 0 1 2 index length 1 sub {
170 2 copy exch length 1 sub eq multiline level get 1 eq and {
171 multiline level 2 put
172 } if
173 2 copy get exch pop
174 dup type /dicttype eq {
175 Replace
176 dup type /dicttype eq {
177 dup Register Replace
178 recursive {
179 2 copy cvlit
180 /def load 3 1 roll
181 count 3 roll
182 } if
183 exch pop
184 } if
185 } if
186 dup type exec
187 dup xcheck not multiline level get 1 eq and {
188 0 index type /arraytype eq
189 1 index type /packedarray eq or
190 1 index type /stringtype eq or {Newline Indent} if
191 } if
192 } for
193 multiline level get 0 ne {Newline LastLevel Indent NextLevel} if
194 xcheck {(} )}{(] )} ifelse Print
195 } ifelse
196 LastLevel
197} def
198
199%
200% Dictionary handler. Try to replace the value by a name before processing
201% the dictionary.
202%
203
204/dicttype {
205 dup
206 rcheck not {
207 (-dictionary- ) Print pop
208 }{
209 dup maxlength Print ( dict dup begin) Print Newline
210 NextLevel
211 {
212 1 index OmitNames exch known {
213 pop pop
214 }{
215 Indent
216 Replace % arrays and dicts by known names
217 Register % new dictionaries in OtherDicts
218 exch
219 cvlit dup type exec % key first - force a /
220 dup type exec % then the value
221 (def) Print Newline
222 } ifelse
223 } forall
224 LastLevel
225 Indent
226 (end ) Print
227 } ifelse
228} def
229
230%
231% Strings containing characters not in AsciiDict are returned in hex. All
232% others are ASCII strings and use AsciiDict for character mapping.
233%
234
235/onecharstring ( ) def
236/twocharstring ( ) def
237
238/stringtype {
239 dup
240 rcheck not {
241 (-string- ) Print
242 }{
243 /hexit false def
244 dup {
245 onecharstring 0 3 -1 roll put
246 AsciiDict onecharstring cvn known not {
247 /hexit true def exit
248 } if
249 } forall
250
251 hexit {(<)}{(\()} ifelse Print
252 0 1 2 index length 1 sub {
253 2 copy 1 getinterval exch pop
254 hexit {
255 0 get /n exch def
256 n -4 bitshift 16#F and 16 twocharstring cvrs pop
257 n 16#F and twocharstring 1 1 getinterval 16 exch cvrs pop
258 twocharstring
259 }{cvn AsciiDict exch get} ifelse
260 Print
261 column lastcolumn gt {
262 hexit not {(\\) Print} if
263 Newline
264 } if
265 } for
266 hexit {(> )}{(\) )} ifelse Print
267 } ifelse
268 pop
269} def
270
271%
272% ASCII characters and replacement strings. Ensures the returned string will
273% reproduce the original when passed through the scanner. Strings containing
274% characters not in this list should be returned as hex strings.
275%
276
277/AsciiDict 128 dict dup begin
278 (\n) cvn (\\n) def
279 (\r) cvn (\\r) def
280 (\t) cvn (\\t) def
281 (\b) cvn (\\b) def
282 (\f) cvn (\\f) def
283 ( ) cvn ( ) def
284 (!) cvn (!) def
285 (") cvn (") def
286 (#) cvn (#) def
287 ($) cvn ($) def
288 (%) cvn (\\%) def
289 (&) cvn (&) def
290 (') cvn (') def
291 (\() cvn (\\\() def
292 (\)) cvn (\\\)) def
293 (*) cvn (*) def
294 (+) cvn (+) def
295 (,) cvn (,) def
296 (-) cvn (-) def
297 (.) cvn (.) def
298 (/) cvn (/) def
299 (0) cvn (0) def
300 (1) cvn (1) def
301 (2) cvn (2) def
302 (3) cvn (3) def
303 (4) cvn (4) def
304 (5) cvn (5) def
305 (6) cvn (6) def
306 (7) cvn (7) def
307 (8) cvn (8) def
308 (9) cvn (9) def
309 (:) cvn (:) def
310 (;) cvn (;) def
311 (<) cvn (<) def
312 (=) cvn (=) def
313 (>) cvn (>) def
314 (?) cvn (?) def
315 (@) cvn (@) def
316 (A) cvn (A) def
317 (B) cvn (B) def
318 (C) cvn (C) def
319 (D) cvn (D) def
320 (E) cvn (E) def
321 (F) cvn (F) def
322 (G) cvn (G) def
323 (H) cvn (H) def
324 (I) cvn (I) def
325 (J) cvn (J) def
326 (K) cvn (K) def
327 (L) cvn (L) def
328 (M) cvn (M) def
329 (N) cvn (N) def
330 (O) cvn (O) def
331 (P) cvn (P) def
332 (Q) cvn (Q) def
333 (R) cvn (R) def
334 (S) cvn (S) def
335 (T) cvn (T) def
336 (U) cvn (U) def
337 (V) cvn (V) def
338 (W) cvn (W) def
339 (X) cvn (X) def
340 (Y) cvn (Y) def
341 (Z) cvn (Z) def
342 ([) cvn ([) def
343 (\\) cvn (\\\\) def
344 (]) cvn (]) def
345 (^) cvn (^) def
346 (_) cvn (_) def
347 (`) cvn (`) def
348 (a) cvn (a) def
349 (b) cvn (b) def
350 (c) cvn (c) def
351 (d) cvn (d) def
352 (e) cvn (e) def
353 (f) cvn (f) def
354 (g) cvn (g) def
355 (h) cvn (h) def
356 (i) cvn (i) def
357 (j) cvn (j) def
358 (k) cvn (k) def
359 (l) cvn (l) def
360 (m) cvn (m) def
361 (n) cvn (n) def
362 (o) cvn (o) def
363 (p) cvn (p) def
364 (q) cvn (q) def
365 (r) cvn (r) def
366 (s) cvn (s) def
367 (t) cvn (t) def
368 (u) cvn (u) def
369 (v) cvn (v) def
370 (w) cvn (w) def
371 (x) cvn (x) def
372 (y) cvn (y) def
373 (z) cvn (z) def
374 ({) cvn ({) def
375 (|) cvn (|) def
376 (}) cvn (}) def
377 (~) cvn (~) def
378end def
379
380%
381% OperatorDict can help format procedure listings. The value assigned to each
382% name is used as an index into the OperatorProcs array. The procedure at that
383% index is fetched and executed after the named operator is printed. What's in
384% OperatorDict is a matter of taste rather than correctness. The default list
385% represents our choice of which of Adobe's operators should end a line.
386%
387
388/OperatorProcs [{} {Newline Indent}] def
389
390/OperatorDict 250 dict def
391
392OperatorDict /arc 1 put
393OperatorDict /arcn 1 put
394OperatorDict /ashow 1 put
395OperatorDict /awidthshow 1 put
396OperatorDict /banddevice 1 put
397OperatorDict /begin 1 put
398OperatorDict /charpath 1 put
399OperatorDict /clear 1 put
400OperatorDict /cleardictstack 1 put
401OperatorDict /cleartomark 1 put
402OperatorDict /clip 1 put
403OperatorDict /clippath 1 put
404OperatorDict /closefile 1 put
405OperatorDict /closepath 1 put
406OperatorDict /concat 1 put
407OperatorDict /copypage 1 put
408OperatorDict /curveto 1 put
409OperatorDict /def 1 put
410OperatorDict /end 1 put
411OperatorDict /eoclip 1 put
412OperatorDict /eofill 1 put
413OperatorDict /erasepage 1 put
414OperatorDict /exec 1 put
415OperatorDict /exit 1 put
416OperatorDict /fill 1 put
417OperatorDict /flattenpath 1 put
418OperatorDict /flush 1 put
419OperatorDict /flushfile 1 put
420OperatorDict /for 1 put
421OperatorDict /forall 1 put
422OperatorDict /framedevice 1 put
423OperatorDict /grestore 1 put
424OperatorDict /grestoreall 1 put
425OperatorDict /gsave 1 put
426OperatorDict /handleerror 1 put
427OperatorDict /if 1 put
428OperatorDict /ifelse 1 put
429OperatorDict /image 1 put
430OperatorDict /imagemask 1 put
431OperatorDict /initclip 1 put
432OperatorDict /initgraphics 1 put
433OperatorDict /initmatrix 1 put
434OperatorDict /kshow 1 put
435OperatorDict /lineto 1 put
436OperatorDict /loop 1 put
437OperatorDict /moveto 1 put
438OperatorDict /newpath 1 put
439OperatorDict /nulldevice 1 put
440OperatorDict /pathforall 1 put
441OperatorDict /print 1 put
442OperatorDict /prompt 1 put
443OperatorDict /put 1 put
444OperatorDict /putinterval 1 put
445OperatorDict /quit 1 put
446OperatorDict /rcurveto 1 put
447OperatorDict /renderbands 1 put
448OperatorDict /repeat 1 put
449OperatorDict /resetfile 1 put
450OperatorDict /restore 1 put
451OperatorDict /reversepath 1 put
452OperatorDict /rlineto 1 put
453OperatorDict /rmoveto 1 put
454OperatorDict /rotate 1 put
455OperatorDict /run 1 put
456OperatorDict /scale 1 put
457OperatorDict /setcachedevice 1 put
458OperatorDict /setcachelimit 1 put
459OperatorDict /setcacheparams 1 put
460OperatorDict /setcharwidth 1 put
461OperatorDict /setdash 1 put
462OperatorDict /setdefaulttimeouts 1 put
463OperatorDict /setdostartpage 1 put
464OperatorDict /seteescratch 1 put
465OperatorDict /setflat 1 put
466OperatorDict /setfont 1 put
467OperatorDict /setgray 1 put
468OperatorDict /sethsbcolor 1 put
469OperatorDict /setidlefonts 1 put
470OperatorDict /setjobtimeout 1 put
471OperatorDict /setlinecap 1 put
472OperatorDict /setlinejoin 1 put
473OperatorDict /setlinewidth 1 put
474OperatorDict /setmargins 1 put
475OperatorDict /setmatrix 1 put
476OperatorDict /setmiterlimit 1 put
477OperatorDict /setpacking 1 put
478OperatorDict /setpagetype 1 put
479OperatorDict /setprintname 1 put
480OperatorDict /setrgbcolor 1 put
481OperatorDict /setsccbatch 1 put
482OperatorDict /setsccinteractive 1 put
483OperatorDict /setscreen 1 put
484OperatorDict /settransfer 1 put
485OperatorDict /show 1 put
486OperatorDict /showpage 1 put
487OperatorDict /start 1 put
488OperatorDict /stop 1 put
489OperatorDict /store 1 put
490OperatorDict /stroke 1 put
491OperatorDict /strokepath 1 put
492OperatorDict /translate 1 put
493OperatorDict /widthshow 1 put
494OperatorDict /write 1 put
495OperatorDict /writehexstring 1 put
496OperatorDict /writestring 1 put
497
498end def
499
500%
501% Put an object on the stack and call Grabit. Output continues until stack
502% is empty. For example,
503%
504% /letter load Grabit
505%
506% prints a listing of the letter procedure.
507%
508
509/Grabit {
510 /saveobj save def
511 GrabitDict begin
512 {
513 count 0 eq {exit} if
514 count {dup type exec} repeat
515 (\n) print flush
516 } loop
517 end
518 currentpoint % for hardcopy output
519 saveobj restore
520 moveto
521} def
522