plan9port

[fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port # fast
git clone https://src.adamsgaard.dk/plan9port.git # slow
Log | Files | Refs | README | LICENSE Back to index

grabit.ps (12401B)


      1 %
      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
    378 end 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 
    392 OperatorDict	/arc			1 put
    393 OperatorDict	/arcn			1 put
    394 OperatorDict	/ashow			1 put
    395 OperatorDict	/awidthshow		1 put
    396 OperatorDict	/banddevice		1 put
    397 OperatorDict	/begin			1 put
    398 OperatorDict	/charpath		1 put
    399 OperatorDict	/clear			1 put
    400 OperatorDict	/cleardictstack		1 put
    401 OperatorDict	/cleartomark		1 put
    402 OperatorDict	/clip			1 put
    403 OperatorDict	/clippath		1 put
    404 OperatorDict	/closefile		1 put
    405 OperatorDict	/closepath		1 put
    406 OperatorDict	/concat			1 put
    407 OperatorDict	/copypage		1 put
    408 OperatorDict	/curveto		1 put
    409 OperatorDict	/def			1 put
    410 OperatorDict	/end			1 put
    411 OperatorDict	/eoclip			1 put
    412 OperatorDict	/eofill			1 put
    413 OperatorDict	/erasepage		1 put
    414 OperatorDict	/exec			1 put
    415 OperatorDict	/exit			1 put
    416 OperatorDict	/fill			1 put
    417 OperatorDict	/flattenpath		1 put
    418 OperatorDict	/flush			1 put
    419 OperatorDict	/flushfile		1 put
    420 OperatorDict	/for			1 put
    421 OperatorDict	/forall			1 put
    422 OperatorDict	/framedevice		1 put
    423 OperatorDict	/grestore		1 put
    424 OperatorDict	/grestoreall		1 put
    425 OperatorDict	/gsave			1 put
    426 OperatorDict	/handleerror		1 put
    427 OperatorDict	/if			1 put
    428 OperatorDict	/ifelse			1 put
    429 OperatorDict	/image			1 put
    430 OperatorDict	/imagemask		1 put
    431 OperatorDict	/initclip		1 put
    432 OperatorDict	/initgraphics		1 put
    433 OperatorDict	/initmatrix		1 put
    434 OperatorDict	/kshow			1 put
    435 OperatorDict	/lineto			1 put
    436 OperatorDict	/loop			1 put
    437 OperatorDict	/moveto			1 put
    438 OperatorDict	/newpath		1 put
    439 OperatorDict	/nulldevice		1 put
    440 OperatorDict	/pathforall		1 put
    441 OperatorDict	/print			1 put
    442 OperatorDict	/prompt			1 put
    443 OperatorDict	/put			1 put
    444 OperatorDict	/putinterval		1 put
    445 OperatorDict	/quit			1 put
    446 OperatorDict	/rcurveto		1 put
    447 OperatorDict	/renderbands		1 put
    448 OperatorDict	/repeat			1 put
    449 OperatorDict	/resetfile		1 put
    450 OperatorDict	/restore		1 put
    451 OperatorDict	/reversepath		1 put
    452 OperatorDict	/rlineto		1 put
    453 OperatorDict	/rmoveto		1 put
    454 OperatorDict	/rotate			1 put
    455 OperatorDict	/run			1 put
    456 OperatorDict	/scale			1 put
    457 OperatorDict	/setcachedevice		1 put
    458 OperatorDict	/setcachelimit		1 put
    459 OperatorDict	/setcacheparams		1 put
    460 OperatorDict	/setcharwidth		1 put
    461 OperatorDict	/setdash		1 put
    462 OperatorDict	/setdefaulttimeouts	1 put
    463 OperatorDict	/setdostartpage		1 put
    464 OperatorDict	/seteescratch		1 put
    465 OperatorDict	/setflat		1 put
    466 OperatorDict	/setfont		1 put
    467 OperatorDict	/setgray		1 put
    468 OperatorDict	/sethsbcolor		1 put
    469 OperatorDict	/setidlefonts		1 put
    470 OperatorDict	/setjobtimeout		1 put
    471 OperatorDict	/setlinecap		1 put
    472 OperatorDict	/setlinejoin		1 put
    473 OperatorDict	/setlinewidth		1 put
    474 OperatorDict	/setmargins		1 put
    475 OperatorDict	/setmatrix		1 put
    476 OperatorDict	/setmiterlimit		1 put
    477 OperatorDict	/setpacking		1 put
    478 OperatorDict	/setpagetype		1 put
    479 OperatorDict	/setprintname		1 put
    480 OperatorDict	/setrgbcolor		1 put
    481 OperatorDict	/setsccbatch		1 put
    482 OperatorDict	/setsccinteractive	1 put
    483 OperatorDict	/setscreen		1 put
    484 OperatorDict	/settransfer		1 put
    485 OperatorDict	/show			1 put
    486 OperatorDict	/showpage		1 put
    487 OperatorDict	/start			1 put
    488 OperatorDict	/stop			1 put
    489 OperatorDict	/store			1 put
    490 OperatorDict	/stroke			1 put
    491 OperatorDict	/strokepath		1 put
    492 OperatorDict	/translate		1 put
    493 OperatorDict	/widthshow		1 put
    494 OperatorDict	/write			1 put
    495 OperatorDict	/writehexstring		1 put
    496 OperatorDict	/writestring		1 put
    497 
    498 end 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