(%stdout)(w)file ゴルフ
PostScript では、普通、標準出力のファイルオブジェクトは
(%stdout) (w) file
などとして作ります。しかし、文字列はバイナリーエンコードの効果が薄いので、"%stdout" "w" の2個の文字列があるこの方法は、ゴルフ向きではありません。標準出力に何か書き出したいときは、出力先が標準出力に決まっていて指定する必要がない =、=only、print を使うことが多くなります。数値や文字列を出力するときは =、=only、print でいいのですが、PostScript で C 言語の putchar に相当する事をやろうとすると、
( ) dup 0 65 put print % A と出力 (%stdout) (w) file 65 write % A と出力 % 出力したい文字がすでにスタックに置かれている場合 65 ( ) dup 0 3 index put print % A と出力、65 はそのまま 65 ( ) dup 0 4 3 roll put print % A と出力、65 は消費される 65 (%stdout) (w) file 1 index write % A と出力、65 はそのまま 65 (%stdout) (w) file exch write % A と出力、65 は消費される
などと、長くなってしまいます。
で、Ghostscript の場合に、標準出力ファイルオブジェクトが短く作って putchar を短くできる(場合がある)方法を思いついたので、書いておきます。
Ghostscript で、スタックが空っぽの時に = を実行すると、エラーが起きてファイルオブジェクトがスタックに積まれます。
# gs -q -dNODISPLAY GS> = Error: /stackunderflow in --execute-- Operand stack: --nostringval-- Execution stack: %interp_exit .runexec2 --nostringval-- (略) Dictionary stack: --dict:1146/1684(ro)(G)-- --dict:0/20(G)-- --dict:70/200(L)-- Current allocation mode is local Last OS error: 2 Current file position is 2 GS<1> == -file-
これはどういうファイルかというと、標準出力です。= は gs_init.ps で
/= { =only (\n) print } bind def /=only { (%stdout) (w) file exch write=only } bind def
と定義されているので、スタックが空っぽの場合、(%stdout) (w) file で標準出力のファイルオブジェクトをスタックにおいた後の exch でスタックアンダーフローし、処理が中断します。この時、標準出力ファイルはスタックに残されたままになります。このエラーを
{ = }stopped
のように stopped で捕まえれば、その後で標準出力ファイルオブジェクトを利用することができます。スタックが空でなければならないので使いづらいですが、数 byte 短くなる場合があります。