Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
7dc1b62b7b
10
femto.tal
10
femto.tal
|
@ -22,10 +22,10 @@
|
||||||
%cr { #0d18 DEO }
|
%cr { #0d18 DEO }
|
||||||
%crlf { cr nl }
|
%crlf { cr nl }
|
||||||
%ansi { #1b18 DEO #5b18 DEO }
|
%ansi { #1b18 DEO #5b18 DEO }
|
||||||
%alternate-buffer-on { ( \e[?1049h )
|
( \e[?1049h )
|
||||||
ansi #3f18 DEO #3118 DEO #3018 DEO #3418 DEO #3918 DEO #6818 DEO }
|
%alternate-buffer-on { ansi #3f18 DEO #3118 DEO #3018 DEO #3418 DEO #3918 DEO #6818 DEO }
|
||||||
%alternate-buffer-off { ( \e[?1049l )
|
( \e[?1049l )
|
||||||
ansi #3f18 DEO #3118 DEO #3018 DEO #3418 DEO #3918 DEO #6c18 DEO }
|
%alternate-buffer-off { ansi #3f18 DEO #3118 DEO #3018 DEO #3418 DEO #3918 DEO #6c18 DEO }
|
||||||
|
|
||||||
( emit macros )
|
( emit macros )
|
||||||
( )
|
( )
|
||||||
|
@ -732,6 +732,7 @@
|
||||||
|
|
||||||
( execute a search, using the given search string )
|
( execute a search, using the given search string )
|
||||||
@do-search ( -> )
|
@do-search ( -> )
|
||||||
|
;tmp LDA ?{ !return } ( ensure non-empty search string )
|
||||||
.cursor/row LDZ2 .searching/orig-row STZ2
|
.cursor/row LDZ2 .searching/orig-row STZ2
|
||||||
.cursor/col LDZ2 .searching/orig-col STZ2
|
.cursor/col LDZ2 .searching/orig-col STZ2
|
||||||
#0000 .searching/regex STZ2
|
#0000 .searching/regex STZ2
|
||||||
|
@ -752,6 +753,7 @@
|
||||||
( )
|
( )
|
||||||
( TODO: handle invalid regular expressions that fail to compile )
|
( TODO: handle invalid regular expressions that fail to compile )
|
||||||
@do-regex-search ( -> )
|
@do-regex-search ( -> )
|
||||||
|
;tmp LDA ?{ !return } ( ensure non-empty search string )
|
||||||
cur-pos DUP2 .searching/start STZ2 .searching/end STZ2
|
cur-pos DUP2 .searching/start STZ2 .searching/end STZ2
|
||||||
.cursor/row LDZ2 .searching/orig-row STZ2
|
.cursor/row LDZ2 .searching/orig-row STZ2
|
||||||
.cursor/col LDZ2 .searching/orig-col STZ2
|
.cursor/col LDZ2 .searching/orig-col STZ2
|
||||||
|
|
251
tar.tal
251
tar.tal
|
@ -10,7 +10,6 @@
|
||||||
( - handle 'L' entries )
|
( - handle 'L' entries )
|
||||||
( - support creating archives )
|
( - support creating archives )
|
||||||
( - arg validation should depend on mode )
|
( - arg validation should depend on mode )
|
||||||
( - validate checksums )
|
|
||||||
( - better error messages on unsupported files, e.g. symlinks )
|
( - better error messages on unsupported files, e.g. symlinks )
|
||||||
( - better usage message )
|
( - better usage message )
|
||||||
( - support using "-" for stdin/stdout? )
|
( - support using "-" for stdin/stdout? )
|
||||||
|
@ -28,24 +27,33 @@
|
||||||
@panic ( -> $exit )
|
@panic ( -> $exit )
|
||||||
#010e DEO #010f DEO BRK
|
#010e DEO #010f DEO BRK
|
||||||
|
|
||||||
|
@print-usage ( -> )
|
||||||
|
;usage1 print ;usage2 !print
|
||||||
|
|
||||||
( handle all provided command-line arguments )
|
( handle all provided command-line arguments )
|
||||||
@arg-callback ( -> )
|
@arg-callback ( -> )
|
||||||
;arg/count LDA
|
;arg/count LDA
|
||||||
DUP #00 EQU ?&missing-mode
|
DUP #00 GTH ?{ POP ;missing-mode !handle-error }
|
||||||
DUP #01 EQU ?&missing-file
|
DUP #01 GTH ?{ POP ;missing-filename !handle-error }
|
||||||
#02 GTH ?&toomany !run
|
POP !run
|
||||||
&missing-mode ;missing-mode !&error
|
|
||||||
&missing-file ;missing-filename !&error
|
@error-toomany ( -> BRK )
|
||||||
&toomany ;too-many-arguments
|
;too-many-arguments !handle-error
|
||||||
&error print ;usage print #01 !exit
|
|
||||||
|
@error-noinput ( -> BRK )
|
||||||
|
;no-input-arguments !handle-error
|
||||||
|
|
||||||
|
@handle-error ( ;msg -> BRK )
|
||||||
|
print print-usage #01 !exit
|
||||||
|
|
||||||
( run the program )
|
( run the program )
|
||||||
@run ( -> BRK )
|
@run ( -> BRK )
|
||||||
#01 arg/read .File1/name DEO2
|
#01 arg/read .File1/name DEO2
|
||||||
#00 arg/read LDA
|
#00 arg/read LDA
|
||||||
DUP LIT "t NEQ ?{ list-entries #00 !exit }
|
DUP LIT "c NEQ ?{ POP create-archive #00 !exit }
|
||||||
DUP LIT "x NEQ ?{ expand-entries #00 !exit }
|
DUP LIT "t NEQ ?{ POP list-entries #00 !exit }
|
||||||
POP ;invalid-mode print ;usage print #00 !exit
|
DUP LIT "x NEQ ?{ POP expand-entries #00 !exit }
|
||||||
|
POP ;invalid-mode print print-usage #00 !exit
|
||||||
|
|
||||||
( exit normally )
|
( exit normally )
|
||||||
@exit ( code^ -> BRK )
|
@exit ( code^ -> BRK )
|
||||||
|
@ -67,20 +75,72 @@
|
||||||
LDAk #18 DEO INC2 GTH2k ?&loop ( limit* s+1* )
|
LDAk #18 DEO INC2 GTH2k ?&loop ( limit* s+1* )
|
||||||
&done POP2 POP2 JMP2r ( )
|
&done POP2 POP2 JMP2r ( )
|
||||||
|
|
||||||
|
@print-filename ( -> )
|
||||||
|
;header/filename sanitize-path #0064 lprint #0a18 DEO JMP2r
|
||||||
|
|
||||||
|
@print-long ( hi* lo* -> )
|
||||||
|
dump-long #0a18 DEO JMP2r
|
||||||
|
|
||||||
( read 512 bytes of header for the next tar entry. )
|
( read 512 bytes of header for the next tar entry. )
|
||||||
( assumes .File1/name is already set. )
|
( assumes .File1/name is already set. )
|
||||||
@read-header ( -> ok^ )
|
@read-header ( -> ok^ )
|
||||||
#0200 .File1/len DEO2
|
#0200 .File1/len DEO2
|
||||||
;header .File1/r DEO2
|
;header .File1/r DEO2
|
||||||
( TODO validate checksum )
|
|
||||||
.File1/ok DEI2 #0200 EQU2 JMP2r
|
.File1/ok DEI2 #0200 EQU2 JMP2r
|
||||||
|
|
||||||
|
@validate-checksum ( -> ok^ )
|
||||||
|
;header/checksum load-octal6 ( chi* clo* )
|
||||||
|
STH2k SWP2 STH2k SWP2 ( chi* clo* [clo* chi*] )
|
||||||
|
;u-sum compute-sum ( chi* clo* uhi* ulo* [clo* chi*] )
|
||||||
|
u32-eq ?&ok1 ( [clo* chi*] )
|
||||||
|
STH2r STH2r ;s-sum compute-sum ( chi* clo* shi* slo* )
|
||||||
|
u32-eq ?&ok2 ( )
|
||||||
|
;invalid-checksum print ( ; error message )
|
||||||
|
print-filename ( ; filename of affected entry )
|
||||||
|
;expected print ( ; "expected: " )
|
||||||
|
;header/checksum load-octal6 print-long ( ; expected checksum )
|
||||||
|
;found print ( ; "found: " )
|
||||||
|
;u-sum compute-sum print-long ( ; found checksum )
|
||||||
|
#00 JMP2r ( 0^ )
|
||||||
|
&ok1 POP2r POP2r &ok2 #01 JMP2r ( 1^ )
|
||||||
|
|
||||||
|
( maximum checksum is 0001fe00 but in practice )
|
||||||
|
( almost all checksums will fit in 16-bits )
|
||||||
|
@compute-sum ( fn* -> sum0* sum1* )
|
||||||
|
STH2 ;header/checksum ;header STH2kr JSR2 ( n0* [fn*] )
|
||||||
|
#0100 ADD2 ;uheader/end ;header/type STH2r JSR2 ( n1* n2* )
|
||||||
|
OVR2 ADD2 GTH2k #00 SWP ( n1* sum* carry* )
|
||||||
|
ROT2 POP2 SWP2 JMP2r ( carry* sum* )
|
||||||
|
|
||||||
|
@u32-eq ( xhi* xlo* yhi* ylo* -> bool^ )
|
||||||
|
ROT2 EQU2 STH EQU2 STHr AND JMP2r
|
||||||
|
|
||||||
|
( return 16-bit checksum )
|
||||||
|
( technically it should be 17-bit. for simplicity we'll )
|
||||||
|
( just check the lower 16-bits. )
|
||||||
|
@u-sum ( limit* start* -> sum* )
|
||||||
|
LIT2r 0000 ( limit* start* [sum*] )
|
||||||
|
&loop LDAk LITr 00 STH ( limit* start* [sum* n*] )
|
||||||
|
ADD2r INC2 GTH2k ?&loop ( limit* pos+1* [sum+n*] )
|
||||||
|
POP2 POP2 STH2r JMP2r ( sum* )
|
||||||
|
|
||||||
|
( similar to unsigned-sum but treats 8-bit ascii differently )
|
||||||
|
( mostly only used for compatibility with old tar files )
|
||||||
|
@s-sum ( limit* start* -> sum* )
|
||||||
|
LIT2r 0000 ( limit* start* [sum*] )
|
||||||
|
&loop LDAk ( limit* start* c^ [sum*] )
|
||||||
|
DUP #07 SFT #ff MUL SWP STH2 ( limit* start* [sum* n*] )
|
||||||
|
ADD2r INC2 GTH2k ?&loop ( limit* pos+1* [sum+n*] )
|
||||||
|
POP2 POP2 STH2r JMP2r ( sum* )
|
||||||
|
|
||||||
( list all the entries in the tar archive )
|
( list all the entries in the tar archive )
|
||||||
@list-entries ( -> )
|
@list-entries ( -> )
|
||||||
|
;arg/count LDA #02 GTH ?error-toomany
|
||||||
read-header ?{ JMP2r }
|
read-header ?{ JMP2r }
|
||||||
;header/filename LDA ?&non-null
|
;header/filename LDA ?&non-null
|
||||||
#800f DEO BRK
|
#800f DEO BRK
|
||||||
&non-null
|
&non-null
|
||||||
|
validate-checksum ( )
|
||||||
;header/type LDA ( type^ )
|
;header/type LDA ( type^ )
|
||||||
DUP #00 EQU ?list-file ( type^ )
|
DUP #00 EQU ?list-file ( type^ )
|
||||||
DUP LIT "0 EQU ?list-file ( type^ )
|
DUP LIT "0 EQU ?list-file ( type^ )
|
||||||
|
@ -104,8 +164,7 @@
|
||||||
;unsupported print
|
;unsupported print
|
||||||
#18 DEO #2018 DEO
|
#18 DEO #2018 DEO
|
||||||
;header/size load-octal11 dump-longer #2018 DEO
|
;header/size load-octal11 dump-longer #2018 DEO
|
||||||
;header/filename sanitize-path
|
print-filename
|
||||||
#0064 lprint #0a18 DEO
|
|
||||||
;header/size load-octal11 round-up-to-512 skip !list-entries
|
;header/size load-octal11 round-up-to-512 skip !list-entries
|
||||||
|
|
||||||
( verbose file entry listing )
|
( verbose file entry listing )
|
||||||
|
@ -113,7 +172,7 @@
|
||||||
POP
|
POP
|
||||||
LIT "f #18 DEO #2018 DEO
|
LIT "f #18 DEO #2018 DEO
|
||||||
;header/size load-octal11 dump-longer #2018 DEO
|
;header/size load-octal11 dump-longer #2018 DEO
|
||||||
;header/filename #0064 lprint #0a18 DEO
|
print-filename
|
||||||
;header/size load-octal11 round-up-to-512 skip !list-entries
|
;header/size load-octal11 round-up-to-512 skip !list-entries
|
||||||
|
|
||||||
( verbose directory entry listing )
|
( verbose directory entry listing )
|
||||||
|
@ -121,11 +180,12 @@
|
||||||
POP
|
POP
|
||||||
LIT "d #18 DEO #2018 DEO
|
LIT "d #18 DEO #2018 DEO
|
||||||
;header/size load-octal11 dump-longer #2018 DEO
|
;header/size load-octal11 dump-longer #2018 DEO
|
||||||
;header/filename #0064 lprint #0a18 DEO
|
print-filename
|
||||||
!list-entries
|
!list-entries
|
||||||
|
|
||||||
( expand a .tar archive in the current working directory )
|
( expand a .tar archive in the current working directory )
|
||||||
@expand-entries ( -> )
|
@expand-entries ( -> )
|
||||||
|
;arg/count LDA #02 GTH ?error-toomany
|
||||||
read-header ?{ JMP2r }
|
read-header ?{ JMP2r }
|
||||||
;header/filename LDA ?&non-null
|
;header/filename LDA ?&non-null
|
||||||
#800f DEO BRK
|
#800f DEO BRK
|
||||||
|
@ -146,16 +206,14 @@
|
||||||
|
|
||||||
@expand-file ( type^ -> )
|
@expand-file ( type^ -> )
|
||||||
POP
|
POP
|
||||||
;header/filename sanitize-path
|
print-filename
|
||||||
DUP2 #0064 lprint #0a18 DEO
|
|
||||||
.File2/name DEO2
|
.File2/name DEO2
|
||||||
;header/size load-octal11 STH2k write
|
;header/size load-octal11 STH2k write
|
||||||
STH2r remainder-512 skip-lo !expand-entries
|
STH2r remainder-512 skip-lo !expand-entries
|
||||||
|
|
||||||
@expand-dir ( type^ -> )
|
@expand-dir ( type^ -> )
|
||||||
POP
|
POP
|
||||||
;header/filename sanitize-path
|
print-filename
|
||||||
DUP2 #0064 lprint #0a18 DEO
|
|
||||||
.File2/name DEO2
|
.File2/name DEO2
|
||||||
#0004 .File2/len DEO2
|
#0004 .File2/len DEO2
|
||||||
#0001 .File2/w DEO2
|
#0001 .File2/w DEO2
|
||||||
|
@ -164,13 +222,130 @@
|
||||||
@expand-unsupported ( type^ -> )
|
@expand-unsupported ( type^ -> )
|
||||||
;unsupported print
|
;unsupported print
|
||||||
#18 DEO LIT2 ": 18 DEO #2018 DEO
|
#18 DEO LIT2 ": 18 DEO #2018 DEO
|
||||||
;header/filename sanitize-path
|
print-filename
|
||||||
#0064 lprint #0a18 DEO
|
|
||||||
;header/size load-octal11 round-up-to-512 skip !expand-entries
|
;header/size load-octal11 round-up-to-512 skip !expand-entries
|
||||||
|
|
||||||
( src and dst should be paths )
|
@create-archive ( -> )
|
||||||
@compress-entries ( src* dst* -> )
|
;arg/count LDA #03 LTH ?error-noinput
|
||||||
POP2 POP2 JMP2r
|
validate-inputs ?{ print-usage #01 !exit }
|
||||||
|
( ; we know that all input files exist )
|
||||||
|
#01 arg/read DUP2 path-exists ?&dest-exists
|
||||||
|
|
||||||
|
.File1/name DEO2
|
||||||
|
#00 .File1/append DEO
|
||||||
|
;arg/count LDA #02
|
||||||
|
&loop DUP arg/read archive-path INC GTHk ?&loop
|
||||||
|
POP2 JMP2r
|
||||||
|
|
||||||
|
&dest-exists ;destination-exists print
|
||||||
|
print #0a18 DEO print-usage #01 !exit
|
||||||
|
|
||||||
|
@validate-inputs ( -> ok^ )
|
||||||
|
;arg/count LDA #02 LITr 01 ( count^ 2^ [1^] )
|
||||||
|
&loop DUP validate-input ( count^ i^ ok1^ [ok0^] )
|
||||||
|
STH ANDr INC GTHk ?&loop ( count^ i+1^ [ok2^] )
|
||||||
|
POP2 STHr JMP2r ( ok^ )
|
||||||
|
|
||||||
|
@validate-input ( i^ -> ok^ )
|
||||||
|
arg/read DUP2 path-exists ?&ok1
|
||||||
|
;missing-input print print #0a18 DEO #00 JMP2r
|
||||||
|
&ok1 ;long-size LDA LIT "? NEQ ?&ok2
|
||||||
|
;input-toobig print print #0a18 DEO #00 JMP2r
|
||||||
|
&ok2 POP2 #01 JMP2r
|
||||||
|
|
||||||
|
@path-exists ( path* -> )
|
||||||
|
path-read-size ;long-size LDA LIT "! NEQ JMP2r
|
||||||
|
|
||||||
|
@path-read-size ( path* -> )
|
||||||
|
.File2/name DEO2
|
||||||
|
#0008 .File2/len DEO2
|
||||||
|
;long-size .File2/stat DEO2
|
||||||
|
JMP2r
|
||||||
|
|
||||||
|
@archive-dir ( path* -> )
|
||||||
|
POP2 JMP2r
|
||||||
|
|
||||||
|
@archive-path ( path* -> )
|
||||||
|
zero-header DUP2 path-read-size ( path* )
|
||||||
|
;long-size LDA LIT "- EQU ?archive-dir ( path* )
|
||||||
|
LIT2r =header ( path* [h*] )
|
||||||
|
STH2kr LDA LIT "/ NEQ ?&rel-path ( path* [h*] )
|
||||||
|
LIT ". STH2kr STA INC2r ( path* [h+1*] )
|
||||||
|
&rel-path STH2r copy-str ( ; write file name )
|
||||||
|
;default-mode ;header/mode copy-str ( ; write file permissions )
|
||||||
|
;default-id ;header/owner copy-str ( ; write file owner )
|
||||||
|
;default-id ;header/group copy-str ( ; write file group )
|
||||||
|
size-to-octal ( ; write file size )
|
||||||
|
#010e DEO
|
||||||
|
;default-mtime ;header/mtime copy-str ( ; write mtime )
|
||||||
|
LIT "0 ;header/type STA ( ; write '0' for normal file )
|
||||||
|
;u-sum compute-sum ( checksum* )
|
||||||
|
|
||||||
|
@ascii-to-short ( s* -> n* )
|
||||||
|
#0000 SWP2 LITr c0 ( sum* s* [shift^] )
|
||||||
|
&loop LDAk #30 SUB ( sum0* s* digit^ [shift^] )
|
||||||
|
#00 SWP ( sum0* s* digit* [shift^] )
|
||||||
|
STHkr SFT2 ( sum0* s* digit<<shift* [shift^] )
|
||||||
|
ROT2 ADD2 SWP2 ( sum0+digit<<shift* s* [shift^] )
|
||||||
|
STHkr #00 EQU ?&done ( sum1* s* [shift^] )
|
||||||
|
INC2 LITr 40 SUBr !&loop ( sum1* s+1* [shift-64^] )
|
||||||
|
&done POP2 POPr JMP2r ( sum1* )
|
||||||
|
|
||||||
|
@size-to-octal ( -> )
|
||||||
|
;long-size ascii-to-short ( hi* )
|
||||||
|
;long-size/mid ascii-to-short ( hi* lo* )
|
||||||
|
;scratch ( hi* lo* addr* )
|
||||||
|
render-octal32 ( )
|
||||||
|
#000b ;header/size save-octal ( )
|
||||||
|
JMP2r ( )
|
||||||
|
|
||||||
|
@render-octal32 ( hi* lo* addr* -> )
|
||||||
|
short-to-octal STH2 STH ( aaaaaaaa bbbbbbbb [addr+5* 0000000x] )
|
||||||
|
#0000 ROT ( aaaaaaaa 00000000 00000000 bbbbbbbb [addr+5* 0000000x] )
|
||||||
|
#10 SFT2 ( aaaaaaaa 00000000 0000000b bbbbbbb0 [addr+5* 0000000x] )
|
||||||
|
SWP2 #07 SFT2 ( 0000000b bbbbbbb0 0000000a aaaaaaa0 [addr+5* 0000000x] )
|
||||||
|
SWP2 STH ( 0000000a aaaaaaa0 0000000b [addr+5* 0000000x bbbbbbb0] )
|
||||||
|
ORA ORAr STHr ( 0000000a aaaaaaab bbbbbbbx [addr+5*] )
|
||||||
|
STH2r short-to-octal ( 0000000a 0000000z addr+10* )
|
||||||
|
STH2 SWP #10 SFT ORA ( 000000az [addr+10*] )
|
||||||
|
LIT "0 ADD STH2kr STA ( [addr+10*] )
|
||||||
|
STH2r INC2 JMP2r ( addr+11* )
|
||||||
|
|
||||||
|
@short-to-octal ( n* addr* -> n>>15^ addr+5* )
|
||||||
|
byte-to-octal STH2 SWP ( lo>>6^ hi^ [addr+2*] )
|
||||||
|
DUP #01 AND #20 SFT ROT ORA ( hi^ [[hi&1]<<2]|lo>>6 [addr+2*] )
|
||||||
|
LIT "0 ADD STH2kr STA ( hi^ [addr+2*] )
|
||||||
|
#01 SFT INC2r ( hi>>1^ [addr+3*] )
|
||||||
|
STH2r !byte-to-octal ( hi>>7^ addr+5* )
|
||||||
|
|
||||||
|
@byte-to-octal ( n^ addr* -> n>>6^ addr+2* )
|
||||||
|
STH2 DUP #07 AND LIT "0 ADD ( n^ digit1^ [addr*] )
|
||||||
|
STH2kr STA #03 SFT INC2r ( n>>3^ [addr+1*] )
|
||||||
|
DUP #07 AND LIT "0 ADD ( n>>3^ digit2^ [addr+1*] )
|
||||||
|
STH2kr STA #03 SFT INC2r ( n>>6^ [addr+2*] )
|
||||||
|
STH2r JMP2r ( n>>6^ addr+2* )
|
||||||
|
|
||||||
|
@save-octal ( count* addr* -> )
|
||||||
|
LIT2r ffff ( count* addr* [ffff*] )
|
||||||
|
OVR2 ADD2 ( count* addr+count* [ffff*] )
|
||||||
|
STH2 ( count* [ffff* addr+count*] )
|
||||||
|
OVR2r ADD2r ( count* [ffff* h=addr+count-1*] )
|
||||||
|
;scratch SWP2 ( s* count* [ffff* h*] )
|
||||||
|
OVR2 ADD2 SWP2 ( limit=count+s* s* [ffff* h*] )
|
||||||
|
&loop LDAk STH2kr STA ( limit* s* [ffff* h*] ; h<-s )
|
||||||
|
INC2 OVR2r ADD2r GTH2k ?&loop ( limit* s+1* [ffff* h-1*] )
|
||||||
|
POP2 POP2 POP2r POP2r #010e DEO JMP2r ( )
|
||||||
|
|
||||||
|
@copy-str ( s* addr* -> )
|
||||||
|
STH2
|
||||||
|
&loop LDAk DUP ?&next POP POP2 POP2r JMP2r
|
||||||
|
&next STH2kr STA INC2 INC2r !&loop
|
||||||
|
|
||||||
|
( we know header is exactly 512 bytes, an even number )
|
||||||
|
@zero-header ( -> )
|
||||||
|
;uheader/end ;header LIT2r 0000
|
||||||
|
&loop STH2kr OVR2 STA2 INC2 INC2 GTH2k ?&loop
|
||||||
|
POP2r POP2 POP2 JMP2r
|
||||||
|
|
||||||
( writes `n` bytes from File1 to File2 )
|
( writes `n` bytes from File1 to File2 )
|
||||||
( uses a 32k internal buffer )
|
( uses a 32k internal buffer )
|
||||||
|
@ -275,6 +450,14 @@
|
||||||
#10 SFT #01 SFT2 STH2r ( hi* lo* )
|
#10 SFT #01 SFT2 STH2r ( hi* lo* )
|
||||||
JMP2r ( hi* lo* )
|
JMP2r ( hi* lo* )
|
||||||
|
|
||||||
|
( returns values between #0000 #0000 and #0003 #ffff )
|
||||||
|
@load-octal6 ( addr* -> hi* lo* )
|
||||||
|
STH2k LDA octal-digit ( o^ [addr*] )
|
||||||
|
#0001 SFT2 ( o1^ o2^ [addr*] )
|
||||||
|
#0000 ROT SWP2 SWP SWP2 ( o1* o2* [addr*] )
|
||||||
|
STH2r INC2 load-octal5 ( o1* o2* n* )
|
||||||
|
ORA2 JMP2r ( o1* o2|n* )
|
||||||
|
|
||||||
( returns values between #0000 and #7fff )
|
( returns values between #0000 and #7fff )
|
||||||
( )
|
( )
|
||||||
( octal5 of 77777 = #7fff, max value )
|
( octal5 of 77777 = #7fff, max value )
|
||||||
|
@ -350,15 +533,26 @@
|
||||||
JMP2r
|
JMP2r
|
||||||
|
|
||||||
( some handy string constants )
|
( some handy string constants )
|
||||||
@usage "usage: 20 "uxncli 20 "tar.rom 20 "t|x 20 "FILENAME 0a 00
|
@usage1 "usage: 20 "uxncli 20 "tar.rom 20 "t|x 20 "TARFILE 0a 00
|
||||||
|
@usage2 20 20 20 20 20 20 20 "uxncli 20 "tar.rom 20 "c 20 "TARFILE 20 "FILE1 20 "... 0a 00
|
||||||
@missing-mode "error: 20 "missing 20 "mode 0a 00
|
@missing-mode "error: 20 "missing 20 "mode 0a 00
|
||||||
@missing-filename "error: 20 "missing 20 "filename 0a 00
|
@missing-filename "error: 20 "missing 20 "filename 0a 00
|
||||||
@too-many-arguments "error: 20 "too 20 "many 20 "arguments 0a 00
|
@too-many-arguments "error: 20 "too 20 "many 20 "arguments 0a 00
|
||||||
|
@no-input-arguments "error: 20 "no 20 "input 20 "files 0a 00
|
||||||
@invalid-mode "error: 20 "invalid 20 "mode 0a 00
|
@invalid-mode "error: 20 "invalid 20 "mode 0a 00
|
||||||
@read-error "error 20 "reading 20 "data 0a 00
|
@read-error "error 20 "reading 20 "data 0a 00
|
||||||
@write-error "error 20 "writing 20 "data 0a 00
|
@write-error "error 20 "writing 20 "data 0a 00
|
||||||
@unsupported "skipped 20 "unsupported 20 "type 20 00
|
@unsupported "skipped 20 "unsupported 20 "type 20 00
|
||||||
@meta-too-big "extended 20 "metadata 20 "field 20 "too 20 "big: 20 00
|
@meta-too-big "extended 20 "metadata 20 "field 20 "too 20 "big: 20 00
|
||||||
|
@invalid-checksum "error: 20 "invalid 20 "checksum 0a 00
|
||||||
|
@expected "expected: 20 00
|
||||||
|
@found "found: 20 20 20 20 00
|
||||||
|
@missing-input "error: 20 "missing 20 "input 20 "file: 20 00
|
||||||
|
@input-toobig "error: 20 "input 20 "file 20 "too 20 "large: 20 00
|
||||||
|
@destination-exists "error: 20 "destination 20 "already 20 "exists: 20 00
|
||||||
|
@default-mode "0000755 00
|
||||||
|
@default-id "0000000 00
|
||||||
|
@default-mtime "07033241577 00
|
||||||
|
|
||||||
( load argument parser )
|
( load argument parser )
|
||||||
~arg.tal
|
~arg.tal
|
||||||
|
@ -429,8 +623,11 @@
|
||||||
&pad $c ( 0x1f4: padding, 12 bytes )
|
&pad $c ( 0x1f4: padding, 12 bytes )
|
||||||
&end ( 0x200: end of header )
|
&end ( 0x200: end of header )
|
||||||
|
|
||||||
|
( small scratch buffer )
|
||||||
|
|77e8 @scratch $10
|
||||||
|
|
||||||
( up to 8 bytes for long size )
|
( up to 8 bytes for long size )
|
||||||
|77f8 @long-size $8
|
|77f8 @long-size $4 &mid $4
|
||||||
|
|
||||||
( buffer for up to 2048 characters of long names/paths )
|
( buffer for up to 2048 characters of long names/paths )
|
||||||
|7800 @long-buf $800
|
|7800 @long-buf $800
|
||||||
|
|
124
test-regex.tal
124
test-regex.tal
|
@ -1,45 +1,43 @@
|
||||||
%dbg { #ff #0e DEO }
|
%sp { #2018 DEO }
|
||||||
%sp { #20 #18 DEO }
|
%nl { #0a18 DEO }
|
||||||
%nl { #0a #18 DEO }
|
|
||||||
%exit { #01 #0f DEO BRK }
|
|
||||||
|
|
||||||
|0100
|
|0100
|
||||||
;expr1 ;compile JSR2 dbg nl
|
;expr1 compile #010e DEO nl
|
||||||
;emit-stack JSR2 nl
|
emit-stack nl
|
||||||
;emit-arena JSR2 nl
|
emit-arena nl
|
||||||
|
|
||||||
LIT '= ;emit JSR2 sp
|
LIT "= emit sp
|
||||||
#01 ;emit-bool JSR2 sp
|
#01 emit-bool sp
|
||||||
#01 ;emit-bool JSR2 sp
|
#01 emit-bool sp
|
||||||
#00 ;emit-bool JSR2 sp
|
#00 emit-bool sp
|
||||||
#01 ;emit-bool JSR2 sp
|
#01 emit-bool sp
|
||||||
#01 ;emit-bool JSR2 sp
|
#01 emit-bool sp
|
||||||
#00 ;emit-bool JSR2 sp
|
#00 emit-bool sp
|
||||||
#00 ;emit-bool JSR2 sp
|
#00 emit-bool sp
|
||||||
#00 ;emit-bool JSR2 nl
|
#00 emit-bool nl
|
||||||
|
|
||||||
LIT 'A ;emit JSR2 sp
|
LIT "A emit sp
|
||||||
;test1 OVR2k ;match JSR2 ;emit-bool JSR2 sp
|
;test1 OVR2k rx-match emit-bool sp
|
||||||
;test2 OVR2k ;match JSR2 ;emit-bool JSR2 sp
|
;test2 OVR2k rx-match emit-bool sp
|
||||||
;test3 OVR2k ;match JSR2 ;emit-bool JSR2 sp
|
;test3 OVR2k rx-match emit-bool sp
|
||||||
;test4 OVR2k ;match JSR2 ;emit-bool JSR2 sp
|
;test4 OVR2k rx-match emit-bool sp
|
||||||
;test5 OVR2k ;match JSR2 ;emit-bool JSR2 sp
|
;test5 OVR2k rx-match emit-bool sp
|
||||||
;test6 OVR2k ;match JSR2 ;emit-bool JSR2 sp
|
;test6 OVR2k rx-match emit-bool sp
|
||||||
;test7 OVR2k ;match JSR2 ;emit-bool JSR2 sp
|
;test7 OVR2k rx-match emit-bool sp
|
||||||
;test8 OVR2k ;match JSR2 ;emit-bool JSR2 nl
|
;test8 OVR2k rx-match emit-bool nl
|
||||||
|
|
||||||
LIT 'B ;emit JSR2 sp
|
LIT "B emit sp
|
||||||
;test1 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
|
;test1 ;graph1 rx-match emit-bool sp
|
||||||
;test2 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
|
;test2 ;graph1 rx-match emit-bool sp
|
||||||
;test3 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
|
;test3 ;graph1 rx-match emit-bool sp
|
||||||
;test4 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
|
;test4 ;graph1 rx-match emit-bool sp
|
||||||
;test5 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
|
;test5 ;graph1 rx-match emit-bool sp
|
||||||
;test6 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
|
;test6 ;graph1 rx-match emit-bool sp
|
||||||
;test7 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
|
;test7 ;graph1 rx-match emit-bool sp
|
||||||
;test8 ;graph1 ;match JSR2 ;emit-bool JSR2 nl
|
;test8 ;graph1 rx-match emit-bool nl
|
||||||
|
|
||||||
;reset-arena JSR2
|
reset-arena
|
||||||
exit
|
#010f DEO BRK
|
||||||
|
|
||||||
( corresponds to regex: a(b|c)d* )
|
( corresponds to regex: a(b|c)d* )
|
||||||
@expr1 "a(b|c)d* 00
|
@expr1 "a(b|c)d* 00
|
||||||
|
@ -47,12 +45,12 @@
|
||||||
( corresponds to regex: a(b|c)d* )
|
( corresponds to regex: a(b|c)d* )
|
||||||
( accepts "ab" or "ac" followd by any number of d's )
|
( accepts "ab" or "ac" followd by any number of d's )
|
||||||
@graph1
|
@graph1
|
||||||
03 'a :x1
|
03 "a =x1
|
||||||
@x1 04 :x2 :x3
|
@x1 04 =x2 =x3
|
||||||
@x2 03 'b :x4
|
@x2 03 "b =x4
|
||||||
@x3 03 'c :x4
|
@x3 03 "c =x4
|
||||||
@x4 05 :x5 0000
|
@x4 05 =x5 0000
|
||||||
@x5 03 'd :x4
|
@x5 03 "d =x4
|
||||||
|
|
||||||
( test case strings to try matching )
|
( test case strings to try matching )
|
||||||
@test1 "ab 00 ( yes )
|
@test1 "ab 00 ( yes )
|
||||||
|
@ -67,50 +65,50 @@
|
||||||
~regex.tal
|
~regex.tal
|
||||||
|
|
||||||
@emit ( c^ -- )
|
@emit ( c^ -- )
|
||||||
emit JMP2r
|
#18 DEO JMP2r
|
||||||
|
|
||||||
@emit-short ( short* -- )
|
@emit-short ( short* -- )
|
||||||
SWP ;emit-byte JSR2 ;emit-byte JSR2 JMP2r
|
SWP emit-byte emit-byte JMP2r
|
||||||
|
|
||||||
@emit-byte ( byte^ -- )
|
@emit-byte ( byte^ -- )
|
||||||
DUP #04 SFT ,&hex JSR #0f AND ,&hex JMP
|
DUP #04 SFT ,&hex JSR #0f AND !&hex
|
||||||
&hex #30 ADD DUP #39 GTH #27 MUL ADD emit
|
&hex #30 ADD DUP #39 GTH #27 MUL ADD emit
|
||||||
JMP2r
|
JMP2r
|
||||||
|
|
||||||
@emit-bool ( byte^ -- )
|
@emit-bool ( byte^ -- )
|
||||||
LIT '0 ADD emit JMP2r
|
LIT "0 ADD emit JMP2r
|
||||||
|
|
||||||
( print stack size, followed by contents )
|
( print stack size, followed by contents )
|
||||||
@emit-stack ( -> )
|
@emit-stack ( -> )
|
||||||
space LIT 'n emit LIT '= emit ;stack-pos LDA2 ;stack-bot SUB2 #0004 DIV2 ;emit-short JSR2 LIT ': emit
|
sp LIT "n emit LIT "= emit ;stack-pos LDA2 ;stack-bot SUB2 #0004 DIV2 emit-short LIT ": emit
|
||||||
;stack-bot
|
;stack-bot
|
||||||
&loop
|
&loop
|
||||||
DUP2 ;stack-pos LDA2 LTH2 ,&ok JCN
|
DUP2 ;stack-pos LDA2 LTH2 ?&ok
|
||||||
POP2 newline JMP2r
|
POP2 nl JMP2r
|
||||||
&ok
|
&ok
|
||||||
space LDA2k ;emit-short JSR2
|
sp LDA2k emit-short
|
||||||
#0002 ADD2 ,&loop JMP
|
#0002 ADD2 !&loop
|
||||||
|
|
||||||
( emit n bytes from the given address )
|
( emit n bytes from the given address )
|
||||||
@emit-n ( addr* count^ -> addr2* )
|
@emit-n ( addr* count^ -> addr2* )
|
||||||
DUP #00 GTH ( addr count count>0? ) ,&ok JCN ( addr count ) POP newline JMP2r
|
DUP #00 GTH ( addr count count>0? ) ?&ok ( addr count ) POP nl JMP2r
|
||||||
&ok
|
&ok
|
||||||
STH ( addr [count] ) space LDAk ;emit-byte JSR2 INC2 ( addr+1 [count] )
|
STH ( addr [count] ) sp LDAk emit-byte INC2 ( addr+1 [count] )
|
||||||
STHr #01 SUB ( addr+1 count-1 )
|
STHr #01 SUB ( addr+1 count-1 )
|
||||||
;emit-n JMP2
|
!emit-n
|
||||||
|
|
||||||
( emit the arena, with one line per node )
|
( emit the arena, with one line per node )
|
||||||
( parses node type, since node size is dynamic (3-5). )
|
( parses node type, since node size is dynamic (3-5). )
|
||||||
@emit-arena ( -> )
|
@emit-arena ( -> )
|
||||||
;arena-bot
|
;arena-bot
|
||||||
&loop
|
&loop
|
||||||
DUP2 ;arena-pos LDA2 LTH2 ,&ok JCN POP2 JMP2r
|
DUP2 ;arena-pos LDA2 LTH2 ?&ok POP2 JMP2r
|
||||||
&ok
|
&ok
|
||||||
DUP2 ;emit-short JSR2
|
DUP2 emit-short
|
||||||
LIT ': emit space
|
LIT ": emit sp
|
||||||
LDAk #01 NEQ ,&!1 JCN #03 ;emit-n JSR2 ,&loop JMP
|
LDAk #01 NEQ ?&c1 #03 emit-n !&loop
|
||||||
&!1 LDAk #02 NEQ ,&!2 JCN #03 ;emit-n JSR2 ,&loop JMP
|
&c1 LDAk #02 NEQ ?&c2 #03 emit-n !&loop
|
||||||
&!2 LDAk #03 NEQ ,&!3 JCN #04 ;emit-n JSR2 ,&loop JMP
|
&c2 LDAk #03 NEQ ?&c3 #04 emit-n !&loop
|
||||||
&!3 LDAk #04 NEQ ,&!4 JCN #05 ;emit-n JSR2 ,&loop JMP
|
&c3 LDAk #04 NEQ ?&c4 #05 emit-n !&loop
|
||||||
&!4 LDAk #05 NEQ ,&!5 JCN #05 ;emit-n JSR2 ,&loop JMP
|
&c4 LDAk #05 NEQ ?&c5 #05 emit-n !&loop
|
||||||
&!5 ;unknown-node-type ;error! JSR2
|
&c5 ;unknown-node-type errorm
|
||||||
|
|
|
@ -21,7 +21,7 @@ template = '''
|
||||||
;wst print
|
;wst print
|
||||||
|
|
||||||
@dump-wst
|
@dump-wst
|
||||||
#04 DEI #01 GTH ?&next !emit-wst &next STH !dump-wst
|
#04 DEI #00 GTH ?&next !emit-wst &next STH !dump-wst
|
||||||
|
|
||||||
@emit-wst
|
@emit-wst
|
||||||
#05 DEI LIT [ &n $1 ] GTH ?&next #0a18 DEO !start-rst
|
#05 DEI LIT [ &n $1 ] GTH ?&next #0a18 DEO !start-rst
|
||||||
|
@ -34,7 +34,7 @@ template = '''
|
||||||
#05 DEI #00 GTH ?&next !emit-rst &next STHr !dump-rst
|
#05 DEI #00 GTH ?&next !emit-rst &next STHr !dump-rst
|
||||||
|
|
||||||
@emit-rst
|
@emit-rst
|
||||||
#04 DEI #01 GTH ?&next #0a18 DEO #800f DEO BRK
|
#04 DEI #00 GTH ?&next #0a18 DEO #800f DEO BRK
|
||||||
&next emit #2018 DEO !emit-rst
|
&next emit #2018 DEO !emit-rst
|
||||||
|
|
||||||
@print ( addr* -> )
|
@print ( addr* -> )
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
.\" Manpage reference for varvara.
|
||||||
|
.\" by Eiríkr Åsheim
|
||||||
|
.\" Contact d_m@plastic-idolatry.com to correct errors or typos.
|
||||||
|
.TH varvara 7 "14 Nov 2024" "1.0" "Varvara Reference Guide"
|
||||||
|
.SH NAME
|
||||||
|
varvara \- virtual machine for the Uxn CPU
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Varvara is a virtual machine for the Uxn CPU. It provides devices that allow
|
||||||
|
ROMs to perform effects such as I/O, drawing to the screen, playing sounds,
|
||||||
|
and more.
|
||||||
|
|
||||||
|
.SH DEVICES
|
||||||
|
Each device consists of 16 ports, each of which are one byte of device memory. Data can be read from ports with \fBDEI\fP and written to them with \fBDEO\fP.
|
||||||
|
|
||||||
|
.SH TERMS
|
||||||
|
|
||||||
|
.SS Devices
|
||||||
|
|
||||||
|
.SS Ports
|
||||||
|
|
||||||
|
.SS Vectors
|
||||||
|
|
||||||
|
.SS Banks
|
||||||
|
|
||||||
|
.SH DEVICE LAYOUT
|
||||||
|
0x00 \fBSystem\fP 0x80 \fBController\fP
|
||||||
|
0x10 \fBConsole\fP 0x90 \fBMouse\fP
|
||||||
|
0x20 \fBScreen\fP 0xa0 \fBFile 0\fP
|
||||||
|
0x30 \fBAudio 0\fP 0xb0 \fBFile 1\fP
|
||||||
|
0x40 \fBAudio 1\fP 0xc0 \fBDateTime\fP
|
||||||
|
0x50 \fBAudio 2\fP 0xd0 \fB(reserved)\fP
|
||||||
|
0x60 \fBAudio 3\fP 0xe0 \fB(reserved)\fP
|
||||||
|
0x70 \fB(unused)\fP 0xf0 \fB(unused)\fP
|
||||||
|
|
||||||
|
.SH SYSTEM (0x00)
|
||||||
|
|
||||||
|
0x00 \fBvector*\fP 0x08 \fBred*\fP
|
||||||
|
0x01 0x09
|
||||||
|
0x02 \fBexpansion*\fP 0x0a \fBgreen*\fP
|
||||||
|
0x03 0x0b
|
||||||
|
0x04 \fBwst\fP 0x0c \fBblue*\fP
|
||||||
|
0x05 \fBrst\fP 0x0d
|
||||||
|
0x06 \fBmetadata*\fP 0x0e \fBdebug\fP
|
||||||
|
0x07 0x0f \fBstate\fP
|
||||||
|
|
||||||
|
.SS System/vector
|
||||||
|
Currently unused.
|
||||||
|
|
||||||
|
.SS System/expansion
|
||||||
|
Values written to the expansion port will be interpreted as an absolute address pointing to memory containing an expansion command.
|
||||||
|
|
||||||
|
\fBCODE NAME DATA\fP
|
||||||
|
00 \fBfill\fP 00 length* bank* addr* const
|
||||||
|
01 \fBcpyl\fP 01 length* src-bank* src-addr* dst-bank* dst-addr*
|
||||||
|
02 \fBcpyr\fP 02 length* src-bank* src-addr* dst-bank* dst-addr*
|
||||||
|
|
||||||
|
\fBCODE NAME DESC\fP
|
||||||
|
00 \fBfill\fP fill a range of memory with a constant value.
|
||||||
|
01 \fBcpyl\fP copy a range of memory starting from the first byte.
|
||||||
|
02 \fBcpyr\fP copy a range of memory starting from the last byte.
|
||||||
|
|
||||||
|
Each bank contains 64k (65536 bytes) of data. Bank 0 is main memory. Banks are optional but emulators are encouraged to support at least 16 of them when possible.
|
||||||
|
|
||||||
|
.SH CONSOLE (0x10)
|
||||||
|
|
||||||
|
.SH SCREEN (0x20)
|
||||||
|
|
||||||
|
.SH AUDIO (0x30, 0x40, 0x50, 0x60)
|
||||||
|
|
||||||
|
.SH CONTROLLER (0x80)
|
||||||
|
|
||||||
|
.SH MOUSE (0x90)
|
||||||
|
|
||||||
|
.SH FILE (0xa0, 0xb0)
|
||||||
|
|
||||||
|
.SH DATETIME (0xc0)
|
||||||
|
|
||||||
|
.SH RESERVED (0xd0, 0xe0)
|
||||||
|
|
||||||
|
.SH UNUSED (0x70, 0xf0)
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
|
||||||
|
https://wiki.xxiivv.com/site/uxntal_opcodes.html \fIUxntal Opcodes\fP
|
||||||
|
https://wiki.xxiivv.com/site/uxntal_syntax.html \fIUxntal Syntax\fP
|
||||||
|
https://wiki.xxiivv.com/site/uxntal_modes.html \fIUxntal Modes\fP
|
||||||
|
https://wiki.xxiivv.com/site/uxntal_immediate.html \fIImmediate opcodes\fP
|
||||||
|
https://wiki.xxiivv.com/site/varvara.html \fIVarvara\fP
|
Loading…
Reference in New Issue