Handling Strings in Forth

A Stringstack

This article is from German FIG Forth society (Forthgesellschaft)

link http://forth-ev.de/filemgmt/singlefile.php?lid=474

download --> the win32forth source

-------------------------------------

\ string stack geforth 6.3.2013, f83 1986 mka

\ 09.03.2013 geht im Prinzip wieder. debugging needed.

\ 10.03.2013 alles ok

\ works ok on Win32forth PeterForth --2019

: -- bye ;

\ : ok ; \ tested ok

vocabulary stringstackwords stringstackwords definitions

decimal


: ($ postpone ( ; immediate


false [if] Stringstack structure


Stack is growing down in memory space.

---------------------------------------------------


here3 (bot$) <-- bot$ is saved here

here2: sp$ <-- 'SP$ is pointing there

top of stack: s0 top$

s1 sec$

...

sn

bot of stack: her0+cell bot$ <-- end of string stack

here0: (sp$) <-- sp$ location is saved here

header: <name>


---------------------------------------------------

[then]



variable 'SP$ \ holds string stack pointer location.

variable CSP$ \ store a current stackpointer there. Stringstack "marker".

: create-stringstack ( "name n -- )

create

here 0 , ( -- n here0 )

swap allot align ( -- here0 )

here over ! \ save sp$ adr to her0

here 'sp$ ! \ init 'pointer

here , \ init sp$ to itself

cell+ , \ save bottom adr

does> @ 'sp$ ! ;


1000 create-stringstack $S


\ stringstack basics (stringstack unchanged).


: SP$ ( -- adr ) 'sp$ @ ;

: TOS$ ( -- adr ) sp$ @ ;

: BOT$ ( -- adr ) sp$ cell+ @ ;


: !CSP$ ( -- ) tos$ csp$ ! ; \ store current stack pointer


: ?CSP$ ( -- ) tos$ csp$ @ <> abort" $stack changed" ;

: ?OFL ( adr -- ) bot$ u< abort" $overflow" ;

: ?LIM ( len -- ) $FF00 and abort" $toolong" ; ( ???)

: ?MTY ( adr -- ) sp$ >= abort" $underflow" ;

: ?FIT ( len -- ) tos$ c@ u> abort" $does'nt fit in tos$ " ;


: SKIP$ ( adr1 -- adr2 ) count + ;

: PICK$ ( nth -- adr )

tos$ begin dup ?mty swap ?dup while 1- swap skip$ repeat ;


: TOP$ ( -- adr ) 0 pick$ ;

: SEC$ ( -- adr ) 1 pick$ ;

: DEPTH$ ( -- n ) ($ sn..s0 )

0 tos$ begin dup sp$ - while skip$ swap 1+ swap repeat drop ;

: LAST$ ( -- adr ) depth$ 1- pick$ ;


\ ----------------------------------------- adressing top string -----------------------------------

: TOPCOUNT$ ( -- adr+1 len ) ($ -- ) top$ count ;

: TOPLENGTH$ ( -- len ) ($ -- ) top$ c@ ;

: TOPLOC$ ( +n -- adr ) ($ -- ) top$ + ;


: GET$ ( n -- char ) toploc$ c@ ;

: PUT$ ( char n -- ) toploc$ c! ;


\ ------------------------- use to move part of strings around -----------------------------

: EXTRACT$ ( n1 n2 -- from.adr len )

toplength$ umin over - 1+ swap toploc$ swap ;

: PATCH$ ( len n -- to.adr len )

2dup + ?fit toploc$ swap ;

\ ok

\ ----------------- move strings to and from top of stringstack ------------------------

\ (number of items on stringstack changed!)


: "PUSH ( from.adr len -- ) ($ -- s ) \ push string to stringstack.

dup ?lim tos$ over - 1- dup ?ofl dup sp$ ! place ;

: "POP ( -- from.adr len ) ($ s -- )

topcount$ 2dup + sp$ ! ;

: "CHAR ( char -- ) ($ -- s ) here ( dumy adr) 1 "push topcount$ drop c! ;


: "@ ( from.buffer -- ) ($ -- s ) count "push ;

: "! ( to.buffer -- ) ($ s -- ) "pop rot place ;


: "COPY ( to.buffer -- ) ($ s -- s ) \ non destructive

topcount$ rot place ;

\ -------------------------------- stringstack operators -----------------------------------

: "EMPTY ( -- ) ($ sn..s0 -- ) sp$ dup ! ;

: "CLEAR ( -- ) ($ sn..sm..s0 -- sn..sm ) csp$ @ sp$ ! ;

: "DROP ( -- ) ($ s -- ) "pop 2drop ;

: "PICK ( n -- ) ($ sm..sn..s0 -- sm..sn..s0 sn ) pick$ "@ ;

: "DUP ( -- ) ($ s -- s s ) 0 "pick ;

: "OVER ( -- ) ($ a b -- a b a ) 1 "pick ;

: "ROLL ( n -- ) ($ sn..s0 -- sn-1..s0 sn )

pick$ dup "@ tos$ tuck - "pop + swap cmove> ;

: "ROLLDOWN ( n -- ) ($ sn..s1 s0 -- s0 sn .. s1 )

pick$ skip$ dup topcount$ + tuck - tos$ swap

"dup cmove "pop rot over - 1- place ;

: "SWAP ( -- ) ($ a b -- b a ) 1 "roll ;

: "ROT ( -- ) ($ a b c -- b c a ) 2 "roll ;




\ manipulate top strings

: "JOIN ( -- ) ($ a b -- ab )

tos$ dup >r "pop dup toplength$ + r> c! over sp$ ! 1+ cmove> ;

: "SPLIT ( n -- ) ($ ab -- a b )

toplength$ over - over toploc$ >r >r

"pop drop swap over 2 - dup sp$ ! place r> r> c! ;

: "PATCH ( n -- ) ($ abcd xx -- axxd ) "pop rot patch$ cmove ;

: "EXTRACT ( n1 n2 -- ) ($ asb -- s ) extract$ "drop "push ;

: "INSERT ( n -- ) ($ ab s -- asb )

"swap "split "rot "swap "join "join ;


\ change top string

: "FILL ( c -- ) ($ s -- cc ) \ replace characters with c

topcount$ rot fill ;

: "BLANK ( -- ) ($ s -- bl ) \ replace characters with blanks

bl "fill ;

\ 46 "fill ; \ testing


: "APPEND ( char -- ) ($ s1 -- s2 ) "char "swap "join ;

: "INFRONT ( char -- ) ($ s1 -- s2 ) "char "join ;

: "ENROL ( char -- ) ($ s - s' )

topcount$ 1- 2dup >r dup 1+ swap r> cmove + c! ;

: "BLANKS ( len -- ) ($ -- s ) \ make blank string

here swap "push "blank ;

: "SUPP ( len -- ) ($ s -- s bl ) \ make supplement blank string

toplength$ - 0 max "blanks ;

: "L ( len -- ) ($ s -- s_bl ) "supp "swap "join ;

: "R ( len -- ) ($ s -- bl_s ) "supp "join ;




\ special string types

\ : "" ( -- ) ($ -- s ) 0 0 "push ;

\ : "D ( d -- ) ($ -- s ) (d.) "push ;

\ : "0 ( -- ) ($ -- s ) 0 0 "d ;

\ : "NUMBER ( -- d ) ($ s -- )

\ lenght$ toploc$ c@ bl = not IF bl "append THEN

\ "pop drop number ;

\ : (D.PRICE) ( d -- adr len )

\ tuck dabs <# # # ascii . hold #s rot sign #> ;

\ : "PRICE ( -- ) ($ s -- $US ) "number (d.price) "push ;




\ string comparators

: COMPARE$ ( -- n ) ($ s1 s0 -- s1 s0 ) ok

top$ count sec$ count compare ;

: "COMPARE ( --- n ) ($ s1 s2 -- ) compare$ "drop "drop ; ok

: "= ( -- f ) ($ s1 s2 -- ) "compare 0= ;

: "< ( -- f ) ($ s1 s2 -- ) "compare 0< ;

: "<= ( -- f ) ($ s1 s2 -- ) "compare dup 0< swap 0= or ;

ok




\ string compiling layer ( not implemented here)

\ string definig words ( not done here )




\ stringstack I/O

: "TYPE ( -- ) ($ s -- s ) \ non destructive info of tos$.

topcount$ type ; ok

: ". ( -- ) ($ s -- ) "pop type ;

: "AT ( col row -- ) ($ s -- ) at-xy ". ;

: ".R ( len -- ) ($ s -- ) "R ". ;

: ".L ( len -- ) ($ s -- ) "L ". ;

: "EXPECT ( len -- ) ($ -- s )

"blanks topcount$ expect "pop drop span @ "push ;




\ string input special ( no)




\ string debugging toolbox

defer (.s$)

: ".S ( -- ) ($ -- ) \ show strings on stringstack

depth$ 0= IF ." Empty$ " exit then

tos$ BEGIN depth$ while (.s$) REPEAT sp$ ! space ;

: "PRINTLINE ( -- ) cr ". ;

' "printline is (.s$)


: ?$ ( adr -- ) ($ s -- s ) \ check whats there

count type ;

: "DUMP ( -- ) ($ s -- s ) \ dump top of stringstack

top$ toplength$ 1+ dump ;


\ F83 trace not implemented


\ words cr cr

\ ------------------------------------- use --------------------------------------------------------------------------------


true [if] \ examples


s" eins = one " "push

s" zwei = two " "push

s" drei = three " "push

s" vier = four " "push

".s .s

[then]

( finis)






original document : -- Michael Kalus Forthgesellschaft -- web adaption by PeterForth 2019