덜 대중적인 언어 중 하나로서 포스트 스크립트 해커의 전위에 관한 문헌을 찾기가 어렵습니다. 그렇다면 골퍼들은 Postscript의 고유 한 세부 표현을 극복하기 위해 스택 모델 (또는 다른 기능)을 활용하기 위해 어떤 발견을 했습니까?
답변
임베디드 디코더
포스트 스크립트 프로그램에는 고유 한 (?) 기능이있어 자체 프로그램 텍스트를 데이터로 읽을 수 있습니다. 이는 일반적으로 사용되는 image
수신 연산자 데이터 수집 – 절차를 입력으로하고,이 과정은 종종 용도 currentfile
이어서 readline
, readstring
또는 readhexstring
. 그러나 다른 방법으로 보아도, image
또 다른 반복 연산자이므로 모든 루프가 미리 읽을 수 있습니다 . Green Book의 라인 프린터 에뮬레이터를 예로들 수 있습니다.
token
연산자를 사용하면 파일이나 문자열에서 스캐너를 호출하여 숫자 나 공백을 제거합니다 (또는 다른 답변 참조)-구분 된 이름.
PS의 간단한 PS 인터프리터 :
{currentfile token not {exit} if dup type /arraytype ne {exec} if }loop
이진 연산자 문자열 디코더
원시 바이너리 토큰 을 얻을 수없는 것처럼 보이므로 (다른 답변 참조) 바이너리 토큰 메커니즘을 이용하여 코드를 8 비트 문자열로 압축하는 “임베디드 디코딩”아이디어를 사용했습니다 문자열 에서 즉시 명령을 조작하고 구문 분석합니다 .
/.{
<920> % two-byte binary-encoded name template with 0x92 prefix
dup 1 4 3 roll put % insert number into string
cvx exec % and execute it
}def
/${
//. %the /. procedure body defined above
73 . %"forall" (by code number)
}def
.
절차는 2 바이트 스트링 스택와 두번째 바이트로서 삽입을 행 번호를 얻어, 실행 시스템의 이름을 지정하는 바이너리 토큰 프리픽스 바이트, 상기 제 1 바이트. 16 진수 문자열의 홀수 개의 니블이 추가 0 니블로 채워지는 스캐너 규칙을 사용하여 16 진 문자열의 바이트를 저장하므로 3 개의 16 진 니블은 2 바이트 문자열을 생성합니다. 그런 다음 문자열을 실행 파일 로 표시 하고 exec
호출하여 스캐너를 호출하고 원하는 실행 시스템 이름을 생성 한 다음 이름을로드하고 연산자를 실행합니다. 은 $
은 USING, 스택 스트링의 각 바이트에이를 수행 .
절차를 두번 루핑 조작을 실행 한 후 일단 루프 체로서, 및 forall
숫자로.
보다 간결하게,이 절차는 다음과 같습니다.
/.{<920>dup 1 4 3 roll put cvx exec}def/${//. 73 .}def
%123457890123456789012345678901234567890123456789012345
% 1 2 3 4 5
따라서 55 문자는 이진 토큰 문자열을 구입합니다. 또는 문자 (당신이 공간을 종료하면 아마 7) 6, 당신은로드 할 수 있습니다에 대한 G 라이브러리 에 (G)run
있는 정의 .
와 $
상기와 (몇 가지 다른 + 아스키-도달 코드의 범위를 확장하기 위해).
크로스 워드 퍼즐 답변 에 더 자세히 설명되어 있습니다.
답변
그래픽 출력을 생성하고 콘솔 출력은 중요하지 않습니다 때 사용하는 =
대신 pop
.
답변
16 진 문자열을 ASCII85로 교체
아마 오래된 뉴스이지만 방금 배웠습니다. 🙂
인코딩 필터 및 잘라 내기 및 붙여 넣기와 함께 대화식으로 포스트 스크립트 인터프리터를 사용하여 수행 할 수 있습니다. 그러나 dc
“손으로” 하는 방법을 보여 드리겠습니다 .
여기에 16 진 문자열이 있습니다. 우리는 이것을 4 바이트 청크로 나눕니다.
95 20 6e d8 d0 59 49 35 50 74 ba c5 08 2d
dc를 시작하면 32 비트 (부호없는) 빅 엔디안 바이트 순서 번호로 입력합니다. 그런 다음 mod -off base-85 자리수 (0이 될 때까지 5가 있어야 함).
0> dc 16i 95206 일체 포함 d85 % n85 / 82 d85 % n85 / 83 d85 % n85 / 82 d85 % n85 / 78 d85 % n85 / 47 d85 % n85 / 0
마지막 청크를 00 00
로 채우면 (소수), 패딩 한 바이트 수를 생략합니다.
47 78 82 83 82 66 81 72 79 83 25 72 82 25 69 2 53 30 [2 53]
인쇄 가능한 ASCII 및 of의 범위로 이동하려면 33을 추가하십시오! ASCII85.
80 111 115 116 115 99 114 105 112 116 58 105 115 58 102 35 86 63 다음
을 디코딩합니다 : Postscript : is : f # V? %%% 죄송합니다! ‘재미’라고 말해야합니다! 나는 어딘가에 망쳤다. 🙂
그것을 감싸면 <~
… ~>
레벨 2 Postscript는 16 진수보다 저렴한 8 비트 데이터에 액세스 할 수 있습니다.
답변
간단한 설명은 다음과 같습니다 . [...>>begin
키워드를 제거하기 위해 여러 정의를 래핑 합니다 def
(nb. [
와 동일 <<
).
def def
[>>begin
기억하십시오 : 이상세두 … 함께 무리 ! 😉
답변
대부분의 포스트 스크립트 연산자 구문 식별자 (따라서 공간 – (또는 otherwise-이어야 함)로 구분), 이름이지만 [
, ]
, <<
, 및 >>
자기 구분하고 스캐너 공간을 개입없이 감지합니다. 같은 이유로 일반적인 /literal
구문 으로 이러한 이름을 참조 할 수 없습니다 (예 /[
: 두 개의 토큰 : 빈 리터럴 이름은에 해당 ()cvn cvlit
하고 실행 파일 이름은에 [
해당 ([)cvn cvx exec
).
이름으로 언급 할 수없는 이러한 이름을 재정의하기 위해 사전에서 키로 사용될 때 암시 적으로 이름으로 변환 된 문자열을 사용할 수 있습니다 (편리한!).
이 예제는 이러한 연산자를 남용하여 산술을 수행하는 것을 보여줍니다.
%!
([)0 def
(])1 def
(<<){add}def
(>>){mul}def
]]<<]]]<<<<>> =
%1 1 add 1 1 1 add add mul = %prints 6
또한 <<
과 [
(와 mark
) 모두 같은 일을 의미한다.
나만의 포스트 스크립트 인터프리터 인 xpost 도 약간의 제한이 있지만 올바른 중괄호를 사용할 수 있습니다. 토론
답변
긴 연산자 이름을 반복해서 사용
이미 <<>>begin
사전을 사용중인 경우 /?{}
재정의 당 4 자의 상수 오버 헤드가 있습니다. 따라서 길이 n의 N 번 반복 연산자는
(4 + n )-( N * ( n -1)) 의 문자 수 변경을 생성합니다 .
이 공식을 0으로 설정하면 손익 분기점 의 방정식이 제공 됩니다. 이것으로부터 우리는 다른 변수와 관련하여 각 변수에 대해
n =-( N -4) / (1- N ) 및
N = (4 + n ) / ( n -1)을 산출 할 수 있습니다 .
“우리는 얼마나 많은 ‘인쇄’를 사용하는 것이 가치가 있는가?”와 같은 질문에 대답 할 수 없습니다. n = 5이므로 N = 9/4입니다. 인쇄를 1/4 번 효과적으로 호출 할 수 없으므로 천장을 가져옵니다. 따라서 3은 3을 사용합니다. 그리고 실제로,
print print print
/P{print}p p p
(물론 이미 <<>>begin
정의를 활성화하는 데 드는 비용을 지불했다고 가정하십시오 ).
물론 이진 토큰은 이런 종류의 똥을 만들어 시스템 이름 테이블에서 처음 255 개의 이름을 2 바이트 (0x92, 0x ??)로 표시합니다. 또한 이진 토큰은 자체적으로 구분되므로 첫 번째 바이트의 높은 비트가 ASCII 범위를 벗어나기 때문에 전후에 공백이 필요하지 않습니다.
답변
이진 토큰
PostScript 프로그램 의 궁극적 인 압축을 위해 최종 프론티어는 더 이상 ASCII 정리 프로그램이 없어도 긴 운영자 이름을 완전히 제거 할 수있는 이진 토큰 입니다.
압축 된 포스트 스크립트 코드 블록으로 시작
[/T[70{R 0 rlineto}48{}49{}43{A rotate}45{A neg rotate}91{currentdict
end[/.[currentpoint matrix currentmatrix]cvx>>begin begin}93{. setmatrix
moveto currentdict end end begin}>>/S{dup B eq{T begin exch{load exec}forall
end}{exch{load exch 1 add S}forall}ifelse 1 sub }>>begin moveto 0 S stroke
PLRM 의 뒷면에있는 모든 이름을 찾습니다 (부록 F, 795-797 페이지).
appearance
in
vim dec meaning
<92> 146 'executable system name' binary token prefix
^A 1 add
^M 13 begin
^^ 30 currentdict
' 39 currentmatrix
( 40 currentpoint
2 50 cvx
8 56 dup
9 57 end
= 61 eq !)
> 62 exch
? 63 exec
I 73 forall
U 85 ifelse
d 100 load
h 104 matrix
k 107 moveto
n 110 neg
<85> 133 rlineto
<88> 136 rotate
§ 167 stroke
© 169 sub
그런 다음 접두사로 146
(소수) 바이트를 입력하십시오. 임의의 바이트를 입력하기위한 vim 도움말
그런 다음 vim에서 압축 파일을 직접 입력 할 수 있습니다.
[/ T [{R 70 0 ^V146 ^V133 48} {49} {43} {A ^V146 ^V136} {A 45 ^V146 ^V110 ^V146 ^V136} 91 { ^V146 ^V30^V 146 ^V57 /. ^V146 ^V40 ^V146 ^V104
^V146 ^V39] ^V146 ^V50 >>
^V146 ^V13 ^V146 ^V13 {93}.
^V146 ^V156
^V146 ^V107 ^V146 ^V30
^V146 ^V57 ^V146 ^V57
^V146 ^V13 >>} / {S ^V146 ^V56 B ^V146 ^V61 {T ^V146 ^V13
^V146 ^V62 { ^V146 ^V100
^V146 ^V63}^V146 ^V73
^V146 ^V57} { ^V146 ^V62 {
^V146 ^V100 ^V146 ^V62
…- ^V
62 를 끝내고 1을 시작하려면 여기에 공백을 입력해야 하지만 나중에 백업하고 삭제할 수 있습니다 …
1 개 ^V146 ^V1S} ^V146 ^V73}
^V146 ^V85
…- ^V
85 를 끝내고 1을 시작하려면 여기에 공백을 입력해야 하지만 나중에 백업하고 삭제할 수 있습니다 …
1 ^V146 ^V169 >>} ^V146 ^V13
^V146 ^V107
… 3 자리 코드의 3 번째 자리는 바이트 입력을 종료하므로 다음 0
은 정상적이고 편리합니다 …
0 S ^V146 ^V167
다음과 같이 화면에 표시됩니다 (vim) :
[/T[70{R 0<92><85>}48{}49{}43{A<92><88>}45{A<92>n<92><88>}
91{<92>^^<92>9[/.[<92>(<92>h<92>']<92>2>>
<92>^M<92>^M}93{.<92><9c><92>k<92>^^<92>9<92>9<92>^M}
>>/S{<92>8B<92>={T<92>^M<92>>{<92>d<92>?}<92>I<92>9}{<92>>
{<92>d<92>>1<92>^AS}<92>I}<92>U1<92>©}>><92>^M
<92>k0 S<92>§
목적이 단지 그림을 보여주는 것이라면 이것은 전적으로 생략 될 수 있습니다. Ghostscript는 필요없이 대부분의 것을 화면에 페인트 showpage
합니다.
¡ 161 showpage
[ 이것은 실제로 작동하지 않습니다. 고스트 스크립트는 나에게주고 undefined
그리고 syntaxerror
이러한 토큰. 어쩌면 몇 가지있다 모드 나 활성화해야합니다. ]