덜 대중적인 언어 중 하나로서 포스트 스크립트 해커의 전위에 관한 문헌을 찾기가 어렵습니다. 그렇다면 골퍼들은 Postscript의 고유 한 세부 표현을 극복하기 위해 스택 모델 (또는 다른 기능)을 활용하기 위해 어떤 발견을 했습니까?
덜 대중적인 언어 중 하나로서 포스트 스크립트 해커의 전위에 관한 문헌을 찾기가 어렵습니다. 그렇다면 골퍼들은 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
있는 정의 .
와 $
상기와 (몇 가지 다른 + 아스키-도달 코드의 범위를 확장하기 위해).
크로스 워드 퍼즐 답변 에 더 자세히 설명되어 있습니다.
아마 오래된 뉴스이지만 방금 배웠습니다. :)
인코딩 필터 및 잘라 내기 및 붙여 넣기와 함께 대화식으로 포스트 스크립트 인터프리터를 사용하여 수행 할 수 있습니다. 그러나 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
기억하십시오 : 이상세두 ... 함께 무리 ! ;)
/a 1 def/b 2 def/c 3 def
와 비교하십시오 <</a 1/b 2/c 3>>begin
. 데프에 더 많은 공간이 필요합니다.
[/a 1/b 2/c 3>>begin
/a{pop 2 mul}def
또는 \b[2 3]def
의는 def
단지 3 자,하지 4. 비용
대부분의 포스트 스크립트 연산자 구문 식별자 (따라서 공간 - (또는 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
이러한 토큰. 어쩌면 몇 가지있다 모드 나 활성화해야합니다. ]
3 -1 roll
또는 3 2 roll
? 내 정신 모델에서 전자는 한 번의 이동만으로 더 효율적이어야합니다. 내 정신 모델이 맞습니까?
https://github.com/luser-dr00g/G
텍스트 파일입니다. 가장 짧은 구문을로드 할 수있는 확장명이 없습니다.
이 203-char Sierpinksi Triangle 프로그램을 허용합니다
[48(0-1+0+1-0)49(11)43(+)45(-)/s{dup
0 eq{exch{[48{1 0 rlineto}49 1 index
43{240 rotate}45{120 rotate}>>exch
get exec}forall}{exch{load
exch 1 sub s}forall}ifelse 1 add}>>begin
9 9 moveto(0-1-1)9 s fill
다음과 같이 151 바이트로 다시 작성됩니다.
3(G)run $
{A - B + A + B - A}
{B B}
{A - B - B}7{[ex{du w{(>K?\2u)$}if}fora]}rep
cvx[/A{3 0 rl}/B 1 in/-{120 rot}/+{-120 rot}>>b
100 200(k?B9)$ showp
약식 시스템 이름 기능을 사용하면 1(G)run
긴 운영자 이름의 부담을 완전히 제거 할 수 있습니다. 운영자 이름은 다른 이름과 구별하기에 충분해야합니다.
그래서
add
된다 ad
mul
된다 mu
index
된다 i
사용 표준 운영자 이름 표에 PLRM 부록 F를 .
그리고 약어 이름을 선택하지 않아도 연산자 문자열의 기능을 사용할 수 있습니다. 베어 라이브러리에는 간단히 추가하여 "기본 수준"이 선택됩니다.(G)run
추가 장식없이 .
기본 레벨에는 새로운 기능이 포함됩니다 .
연산자 (위에서 언급 한 것과 동일한 부록 F)의 정수 코드를 받아 들여서 실행 가 됩니다.
새로운 함수 $
는 문자열을 반복하고 호출합니다..
하고 각각을 합니다. 따라서 ASCII 코드는 숫자로 연산자를 직접 선택합니다.
새로운 기능 @
사용하면 공백 문자 (Ascii 0x20)를 0으로 처리하여 부록 F의 표 하단에 도달 할 수 있습니다.
새로운 함수를 #
사용하면 먼저 95 (0x5F)를 추가하여 테이블에 추가로 도달 할 수 있으므로 공백 char 0x20은 마지막 인쇄 가능한 ASCII 문자 ~
126 (0x7E) 다음에 나오는 다음 코드 인 127 (0x7F)로 처리됩니다 .
두 개의 새로운 함수를 !
사용하면 많은 (및 ) 연산자 의 지루한 표현이 아니라 인덱스 / 키 의 인덱스 배열 을 사용하여 깊게 중첩 된 배열 및 / 또는 dicts 구조에 액세스 할 수 있습니다 .get
put
(G)run
7자는 기본 레벨을 구매합니다.
1(G)run
8 문자는 그와 약어 시스템 이름을 구입합니다.
3(G)run $
9 문자는 즉시 다음 빈 줄까지 소스 행을 스캔 하고 암시 적 절차 블록을 시작 하고 첫 번째 줄을라는 절차 A
로 정의하고 다음 줄은이라는 절차로 정의합니다 B
. 이렇게하면 def
정의하는 데 필요한 대부분이 제거됩니다. 사전에 그것들을 감싸거나 이름을 명시하지 않아도 많은 것들.