Wil Baden 2000-08-14
These are common tools used in several source files. They are all given here so you can avoid duplicate definitions. Comment out those that you already have or are enhancing. Many of them should be CODE definitions.
0 [IF] is the convention used for commentary, so comment
out with \ or FALSE [IF] or [VOID] [IF].
[VOID] is an immediate constant of FALSE. It is defined
first so it can be used to comment out sections of code.
Definitions in Standard Forth by Wil Baden. Any similarity with anyone else's code is coincidental, historical, or inevitable.
!+ #BACKSPACE-CHAR #CHARS/LINE #EOL-CHAR #TAB-CHAR 'th (.) ++ ," -CELL /SPLIT 2NIP 3DROP 3DUP @+ ANDIF APPEND APPEND-CHAR BACK BL-SCAN BL-SKIP BOUNDS C+! CELL CELL- EMITS EMPTY ENDS? FILE-CHECK FOURTH H# HIWORD IS-ALNUM IS-ALPHA IS-DIGIT IS-WHITE LEXEME LOWORD MAX-N MEMORY-CHECK NEXT-WORD NOT OFF ON ORIF OUT PLACE R'@ REWIND-FILE SCAN SIGN-BIT SKIP SPLIT-NEXT-LINE STARTS? STRING, TEMP THIRD TRIM VIEW-NEXT-LINE VOCABULARY [DEFINED] [UNDEFINED] [VOID] \\[VOID]
( -- flag )
FALSE CONSTANT [VOID] IMMEDIATE
NOT
( x -- flag )
0=, used for program clarity to reverse the
result of a previous test.
[DEFINED]
( "name" -- flag )
[UNDEFINED]
( "name" -- flag )
C+!
( n addr -- )
EMPTY
( -- )
VOCABULARY
( "name" -- )
For potential definitions, see FPH Common Usage.
Program Text 2
\ : NOT ( x -- flag ) S" 0= " EVALUATE ; IMMEDIATE
: [DEFINED] ( "name" -- flag )
BL WORD FIND NIP 0<> ; IMMEDIATE
: [UNDEFINED] ( "name" -- flag )
BL WORD FIND NIP 0= ; IMMEDIATE
\ : C+! ( n addr -- ) DUP >R C@ + R> C! ;
CODE C+! ( n addr -- )
rx 0 rdsp lwz,
ry 0 rtos lbz,
ry ry rx add,
ry 0 rtos stb,
rtos 4 rdsp lwz,
rdsp rdsp 8 addi,
NEXT, END-CODE
: EMPTY ( -- )
S" ANEW --- DECIMAL ONLY FORTH DEFINITIONS " EVALUATE ; IMMEDIATE
[undefined] mfvocabulary [if]
: mfvocabulary vocabulary ;
[then]
: VOCABULARY 400 VOCABULARY ;
BOUNDS
( str len -- str+len str )
OFF
( addr -- )
ON.
ON
( addr -- )
OFF.
: BOUNDS ( str len -- str+len str ) OVER + SWAP ; \ : OFF ( addr -- ) 0 SWAP ! ; \ : ON ( addr -- ) -1 SWAP ! ;
APPEND
( str len add2 -- )
+PLACE.
APPEND-CHAR
( char addr -- )
PLACE
( str len addr -- )
STRING,
( str len -- )
,"
( "<ccc><quote>" -- )
[undefined] mfappend [if]
: mfappend append ;
[then]
: APPEND ( addr1 u addr2 -- )
2DUP 2>R COUNT CHARS + SWAP CHARS MOVE ( ) 2R> C+! ;
: APPEND-CHAR ( char addr -- )
DUP >R COUNT DUP 1+ R> C! + C! ;
: PLACE ( str len addr -- )
2DUP 2>R CHAR+ SWAP CHARS MOVE 2R> C! ;
: STRING, ( str len -- )
HERE OVER 1+ CHARS ALLOT PLACE ;
\ : ," [CHAR] " PARSE STRING, ; IMMEDIATE
THIRD
( x y z -- x y z x )
FOURTH
( w x y z -- w x y z w )
3DUP
( x y z -- x y z x y z )
3DROP
( x y z -- )
2NIP
( w x y z -- y z )
R'@
( -- x )( R: x y -- x y )
These should all be CODE definitions.
Program Text 5
\ : THIRD ( x y z -- x y z x ) 2 PICK ;
CODE THIRD ( x y z -- x y z x )
rtos -4 rdsp stwu,
rtos 8 rdsp lwz,
NEXT, End-Code
\ : FOURTH ( w x y z -- w x y z w ) 3 PICK ;
CODE FOURTH ( x y z w -- x y z w x )
rtos -4 rdsp stwu,
rtos 12 rdsp lwz,
NEXT, End-Code
: 3DUP ( x y z -- x y z x y z ) THIRD THIRD THIRD ;
\ : 3DROP ( x y z -- ) DROP 2DROP ;
CODE 3DROP ( x y z -- )
rtos 8 rdsp lwz,
rdsp 12 addi,
NEXT, End-Code
\ : 2NIP ( w x y z -- y z ) 2SWAP 2DROP ;
CODE 2NIP ( w z y z -- y z )
rx 0 rdsp lwz,
rdsp 8 addi,
rx 0 rdsp stwu,
NEXT, End-Code
\ : R'@ S" 2R@ DROP " EVALUATE ; IMMEDIATE
CODE R'@ ( -- x )( R: x y -- same )
rtos -4 rdsp stwu,
rtos 4 rrsp lwz,
NEXT, End-Code
ANDIF
( p ... -- flag )
p ANDIF q THEN, q will not be performed if
p is false.
ORIF
( p ... -- flag )
p ORIF q THEN, q will not be performed if
p is true.
: ANDIF S" DUP IF DROP " EVALUATE ; IMMEDIATE : ORIF S" DUP 0= IF DROP " EVALUATE ; IMMEDIATE
SCAN
( str len char -- str+i len-i )
SKIP
( str len char -- str+i len-i )
BACK
( str len char -- str len-i )
/SPLIT
( a m a+i m-i -- a+i m-i a i )
[undefined] mfscan [if]
: mfscan scan ;
[then]
\ : SCAN ( str len char -- str+i len-i )
\ >R BEGIN DUP WHILE OVER C@ R@ -
\ WHILE 1 /STRING REPEAT THEN
\ R> DROP ;
CODE SCAN ( str len char -- str+i len-i )
r31 -4 rrsp stwu, r31 rtos move,
poptos, ( str len)
rx 0 rdsp lwz, rx -1 addi, rtos 1 addi,
begin,
rtos -1 addic.,
ry 1 rx lbzu,
gt while,
ry r31 cmp,
eq until,
rx 0 rdsp stw,
r31 0 rrsp stw, rrsp 4 addi,
NEXT, END-CODE
\ : SKIP ( str len char -- str+i len-i )
\ >R BEGIN DUP WHILE OVER C@ R@ =
\ WHILE 1 /STRING REPEAT THEN
\ R> DROP ;
CODE SKIP ( str len char -- str+i len-i )
r31 -4 rrsp stwu, r31 rtos move,
poptos, ( str len)
rx 0 rdsp lwz, rx -1 addi, rtos 1 addi,
begin,
rtos -1 addic.,
ry 1 rx lbzu,
gt while,
ry r31 cmp,
ne until,
rx 0 rdsp stw,
r31 0 rrsp stw, rrsp 4 addi,
NEXT, END-CODE
: BACK ( str len char -- str len-i )
>R BEGIN DUP WHILE
1- 2DUP + C@ R@ =
UNTIL 1+ THEN
R> DROP ;
: /SPLIT ( a m b n -- b n a m-n ) DUP >R 2SWAP R> - ;
IS-WHITE
( char -- flag )
TRIM
( str len -- str len-i )
BL-SCAN
( str len -- str+i len-i )
BL-SKIP
( str len -- str+i len-i )
: IS-WHITE ( char -- flag ) 33 - 0< ;
: TRIM ( str len -- str len-i )
BEGIN DUP WHILE
1- 2DUP + C@ IS-WHITE NOT
UNTIL 1+ THEN ;
\ : BL-SCAN ( str len -- str+i len-i )
\ BEGIN DUP WHILE OVER C@ IS-WHITE NOT
\ WHILE 1 /STRING REPEAT THEN ;
CODE BL-SCAN ( str len -- str+i len-i )
rx 0 rdsp lwz, rx -1 addi, rtos 1 addi,
begin,
rtos -1 addic.,
ry 1 rx lbzu,
gt while,
ry 32 cmpi,
le until,
rx 0 rdsp stw,
NEXT, END-CODE
\ : BL-SKIP ( str len -- str+i len-i )
\ BEGIN DUP WHILE OVER C@ IS-WHITE
\ WHILE 1 /STRING REPEAT THEN ;
CODE BL-SKIP ( str len -- str+i len-i )
rx 0 rdsp lwz, rx -1 addi, rtos 1 addi,
begin,
rtos -1 addic.,
ry 1 rx lbzu,
gt while,
ry 32 cmpi,
gt until,
rx 0 rdsp stw,
NEXT, END-CODE
STARTS?
( str len pattern len2 -- str len flag )
ENDS?
( str len pattern len2 -- str len flag )
: STARTS? ( str len pattern len2 -- str len flag )
DUP >R 2OVER R> MIN COMPARE 0= ;
: ENDS? ( str len pattern len2 -- str len flag )
DUP >R 2OVER DUP R> - /STRING COMPARE 0= ;
IS-DIGIT
( char -- flag )
IS-ALPHA
( char -- flag )
IS-ALNUM
( char -- flag )
: IS-DIGIT ( char -- flag ) [CHAR] 0 - 10 U< ;
: IS-ALPHA ( char -- flag ) 32 OR [CHAR] a - 26 U< ;
: IS-ALNUM ( char -- flag )
DUP IS-ALPHA ORIF DUP IS-DIGIT THEN NIP ;
#BACKSPACE-CHAR
( -- char )
#CHARS/LINE
( -- n )
#EOL-CHAR
( -- char )
#TAB-CHAR
( -- char )
MAX-N
( -- n )
SIGN-BIT
( -- n )
CELL
( -- n )
-CELL
( -- n )
8 CONSTANT #BACKSPACE-CHAR 62 VALUE #CHARS/LINE 13 CONSTANT #EOL-CHAR 9 CONSTANT #TAB-CHAR TRUE 1 RSHIFT CONSTANT MAX-N TRUE 1 RSHIFT INVERT CONSTANT SIGN-BIT 1 CELLS CONSTANT CELL -1 CELLS CONSTANT -CELL
SPLIT-NEXT-LINE
( src . -- src' . str len )
VIEW-NEXT-LINE
( src . str len -- src . str len str2 len2 )
OUT
( -- addr )
TEMP
( -- addr )
: SPLIT-NEXT-LINE ( src . -- src' . str len )
2DUP #EOL-CHAR SCAN DUP >R 1 /STRING 2SWAP R> - ;
: VIEW-NEXT-LINE ( src . str len -- src . str len str2 len2 )
2OVER 2DUP #EOL-CHAR SCAN NIP - ;
VARIABLE OUT
VARIABLE TEMP
NEXT-WORD
( -- str len )
LEXEME
( "name" -- str len )
H#
( "hexnumber" -- n )
\\
( "...<eof>" -- )
: NEXT-WORD ( -- str len )
BEGIN BL WORD COUNT ( str len)
DUP IF EXIT THEN
REFILL
WHILE 2DROP ( ) REPEAT ; ( str len)
: LEXEME ( "name" -- str len )
BL WORD ( addr) DUP C@ 1 =
IF CHAR+ C@ WORD THEN
COUNT ;
: H# ( "hexnumber" -- n ) \ Simplified for easy porting.
0 0 BL WORD COUNT ( str len)
BASE @ >R HEX >NUMBER R> BASE !
ABORT" Not Hex " 2DROP ( n)
STATE @ IF POSTPONE LITERAL THEN
; IMMEDIATE
\ : \\ ( "...<eof>" -- )
\ BEGIN -1 PARSE 2DROP REFILL 0= UNTIL ;
: \\ PRIOR.STREAM ;
FILE-CHECK
( n -- )
MEMORY-CHECK
( n -- )
These words should be tailored for your system.
Program Text 14\ : FILE-CHECK ( n -- ) THROW ; \ : MEMORY-CHECK ( n -- ) THROW ; \ : FILE-CHECK ( n -- ) ABORT" File Access Error " ; \ : MEMORY-CHECK ( n -- ) ABORT" Memory Allocation Error " ; : FILE-CHECK ( n -- ) SHOWERROR ; : MEMORY-CHECK ( n -- ) SHOWERROR ;
++
( addr -- )
@+
( addr -- addr' x )
!+
( addr x -- addr' )
\ : ++ ( addr -- ) 1 SWAP +! ;
CODE ++ ( a -- )
rx 0 rtos lwz,
rx 1 addi,
rx 0 rtos stw,
poptos,
NEXT, End-Code
\ : @+ ( addr -- addr' x ) DUP CELL+ SWAP @ ;
CODE @+ ( a -- a+cell x )
rx rtos 4 addi,
rx -4 rdsp stwu,
rtos 0 rtos lwz,
NEXT, End-Code
\ : !+ ( addr x -- addr' ) OVER ! CELL+ ;
CODE !+ ( a x -- a+cell )
rx 0 rdsp lwz,
rtos 0 rx stw,
rtos rx 4 addi,
rdsp 4 addi,
NEXT, End-Code
'th
( n "addr" -- &addr[n] )
n CELLS addr +.
(.)
( n -- addr u )
.
(dot), returning the address and length of the resulting
string.
CELL-
( addr -- addr' )
EMITS
( n char -- )
HIWORD
( xxyy -- xx )
LOWORD
( xxyy -- yy )
REWIND-FILE
( file-id -- ior )
: 'th ( n "addr" -- &addr[n] )
S" 2 LSHIFT " EVALUATE
BL WORD COUNT EVALUATE
S" + " EVALUATE
; IMMEDIATE
: (.) ( n -- addr u ) DUP ABS 0 <# #S ROT SIGN #> ;
: CELL- ( addr -- addr' ) CELL - ;
: EMITS ( n char -- )
SWAP 0 ?DO DUP EMIT LOOP DROP ;
: HIWORD ( xxyy -- xx ) 16 RSHIFT ;
: LOWORD ( xxyy -- yy ) 65535 AND ;
: REWIND-FILE ( file-id -- ior )
0 0 ROT REPOSITION-FILE ;
MOD
( dividend divisor -- remainder )
MOD.
CODE MOD ( dividend divisor -- remainder )
rtos 0 cmpi,
rx 0 rdsp lwz,
rdsp rdsp 4 addi,
ne if,
ry rx rtos divw,
ry ry rtos mullw,
rtos ry rx subf,
then,
NEXT, End-Code