\ File: mstrings-test.fs \ Title: Tests for measured string words \ Author: David N. Williams \ License: Public Domain \ Version: 0.8.4 \ Revised: August 26, 2008 s" testerplus.fs" included true VERBOSE ! \ Uncomment to test with pfe parsing module: \ true value PARSING-EXT \ default in mstrings.fs is FALSE s" mstrings-0end.fs" required s" mstrings-linput.fs" required \ all sublibs now loaded decimal PFE-HOST [IF] cr comment Test host is pfe. [THEN] PARSING-EXT [IF] comment Using pfe parsing module. [ELSE] PFE-HOST 0= [IF] cr [THEN] comment Using parsing.fs. [THEN] [UNDEFINED] cell [IF] 1 cells constant cell [THEN] \ WARNING: In pfe, PAD moves when HERE changes and can get \ unaligned. Use MPAD instead. 256 constant #mpad-chars create mpad #mpad-chars chars cell+ allot \ Useful for inspecting dumps: : 0mpad ( -- ) 0 mpad ! mpad cell+ #mpad-chars 0 fill ; \ Uncomment to check the result of 0MPAD: 0 [IF] 0mpad mpad #mpad-chars chars cell+ dump \\ [THEN] create m"hello" 5 , char h c, char e c, char l c, char l c, char o c, m"hello" cell+ 5 2constant "hello" create m"" 0 , m"" cell+ 0 2constant "" : s= ( s1 s2 -- flag ) compare 0= ; : mpad= ( s -- n ) mpad mcount s= ; : c>/buf ( #chars -- c[#chars]+cell ) chars cell+ ; : s>/buf ( s -- c[s.len]+cell ) nip c>/buf ; { "hello" s" hello" s= -> true } { "hello" s" hell" s= -> false } { "hello" "" s= -> false } { "" s" " s= -> true } TESTING MCOUNT -MCOUNT (M+) (M!) /M MROOM? M+ROOM? M+ M! { m"hello" mcount -> "hello" } { "hello" mpad (m!) mpad mcount -> mpad cell+ "hello" nip } { s" hello" mpad= -> true } \ uses MCOUNT { s" " mpad (m!) mpad mcount -> mpad cell+ 0 } { "hello" -mcount -> m"hello" } \ (m!) ( s a-addr -- ) \ (m+) ( s m -- ) { s" Hello," 2dup mpad (m!) mpad= -> true } { s" world!" mpad (m+) s" Hello, world!" mpad= -> true } { s" " mpad (m+) s" Hello, world!" mpad= -> true } { s" " mpad (m!) s" " mpad= -> true } { s" Hello, world!" 2dup nip mpad ! mpad= -> true } { s" " mpad (m!) s" testing" 2dup mpad (m+) mpad= -> true } \ /m ( len -- c[len]+cell ) { 0 /m -> 1 cells } { 1 /m -> 1 chars cell+ } \ mroom? ( len mbuf /mbuf -- len mbuf flag ) 0 mpad ! { 0 mpad cell 1- mroom? -> 0 mpad false } { 0 mpad cell mroom? -> 0 mpad true } { 1 mpad cell mroom? -> 1 mpad false } { 1 mpad 1 c>/buf mroom? -> 1 mpad true } { 2 mpad 2 c>/buf mroom? -> 2 mpad true } { 3 mpad 2 c>/buf mroom? -> 3 mpad false } { s" " mpad= -> true } \ m+room? ( len mbuf /mbuf -- len mbuf flag ) { 0 mpad cell 1- m+room? -> 0 mpad false } { 0 mpad cell m+room? -> 0 mpad true } { 1 mpad cell m+room? -> 1 mpad false } "hello" mpad (m!) { 0 mpad cell 1- m+room? -> 0 mpad false } { 0 mpad "hello" s>/buf m+room? -> 0 mpad true } { 1 mpad "hello" s>/buf m+room? -> 1 mpad false } { 1 mpad "hello" 1+ s>/buf m+room? -> 1 mpad true } { 2 mpad "hello" 1+ s>/buf m+room? -> 2 mpad false } \ m! ( s mbuf /mbuf -- flag ) { s" testing" mpad over c>/buf m! -> true } { s" testing" mpad over 1- c>/buf m! -> false } { s" " mpad cell m! -> true } { mpad mcount -> mpad cell+ 0 } \ m+ ( s mbuf /mbuf -- flag ) s" Hello," mpad (m!) { s" world!" mpad s" Hello, world!" s>/buf m+ -> true } { s" Hello, world!" mpad= -> true } { s" " mpad s" Hello, world!" s>/buf m+ -> true } { s" Hello, world!" mpad= -> true } s" Hello," mpad (m!) { s" world!" mpad s" Hello, world!" 1- s>/buf m+ -> false } { s" Hello," mpad= -> true } TESTING M, M,S (M+,) ?MCONTIG-DATA M+, 0 value mhere : m= ( s m -- flag ) mcount s= ; : mhere= ( s -- flag ) mhere mcount s= ; : mafter ( m -- m' ) mcount chars + ; \ m, ( s -- ) align \ just in case here to mhere { s" testing" 2dup m, mhere= -> true } { mhere mafter -> here } { here 1 and -> 1 } here to mhere \ unaligned unless trivally aligned { s" 1" 2dup m, mhere aligned m= -> true } { mhere aligned mafter -> here } 1 allot here to mhere { s" " 2dup m, mhere aligned m= -> true } { mhere aligned mafter -> here } \ (m+,) ( s m -- ) align here to mhere s" Hello," m, { s" world!" mhere (m+,) -> } { mhere mafter -> here } { s" Hello, world!" mhere= -> true } { mhere mafter -> here } { here s" " mhere (m+,) -> here } { mhere mafter -> here } { s" Hello, world!" mhere= -> true } align \ m+, ( s m -- ) \ Same tests as for (M+,). align here to mhere s" Hello," m, { s" world!" mhere m+, -> } { mhere mafter -> here } { s" Hello, world!" mhere= -> true } { mhere mafter -> here } { here s" " mhere m+, -> here } { mhere mafter -> here } { s" Hello, world!" mhere= -> true } align \ Uncomment to test noncontiguity abort, ?MCONTIG-DATA: \ here to mhere s" 1234" m, 1 chars allot s" x" mhere m+, \ m,s ( s -- s' ) here to mhere { s" testing" 2dup m,s s= -> true } { mhere mafter -> here } align here to mhere { s" " 2dup m,s s= -> true } { mhere mafter -> here } align 1 chars allot here to mhere { s" 1" m,s -> mhere aligned mcount } { mhere aligned mafter -> here } { s" 1" mhere aligned m= -> true } TESTING (NULL-M+) NULL-M+ NULL-M+, \ (null-m+) ( m -- ) { s" testing" mpad (m!) mpad (null-m+) -> } { mpad mafter c@ -> 0 } { s" " mpad (m!) mpad (null-m+) -> } { mpad mafter c@ -> 0 } \ null-m+ ( mbuf /mbuf -- flag ) { s" testing" 2dup mpad (m!) s>/buf mpad swap null-m+ -> false } { s" testing" 2dup mpad (m!) 1+ s>/buf mpad swap null-m+ -> true } { mpad mafter c@ -> 0 } \ null-m+, ( -- ) s" testing" m,s -mcount to mhere { null-m+, -> } { mhere mcount 1+ chars + -> here } { s" testing" mhere m= -> true } \ INPUT WORDS TESTING EOL-S s" ANSForth-eol-tempfile" m,s 2constant name name r/w open-file nip ( ior) 0= [IF] red-text .( Can't test EOL-S, file already exists: ) blue-text name type cr normal-text [ELSE] name r/w bin create-file throw value id s" " id write-line throw id file-size throw 2drop 0 0 id reposition-file throw mpad 4 id read-file throw ( #chars) { mpad swap eol-s s= -> true } name delete-file throw [THEN] [UNDEFINED] cell [IF] 1 cells constant cell [THEN] eol-s chars constant /eol ( addr) drop \ single line strings s" " m,s 2constant empty-s s" 1" m,s 2constant s1 s" 12" m,s 2constant s2 s" 12345678" m,s 2constant s8 s" 123456789" m,s 2constant s9 \ multiline strings (MPAD has at least 252 chars) : mpad-m,s ( -- ) mpad mcount m,s ; 0 mpad ! s9 mpad (m+) eol-s mpad (m+) s2 mpad (m+) mpad-m,s 2constant ml1 0 mpad ! s8 mpad (m+) eol-s mpad (m+) s1 mpad (m+) mpad-m,s 2constant ml2 0 mpad ! s9 mpad (m+) eol-s mpad (m+) mpad-m,s 2constant ml3 0 mpad ! eol-s mpad (m+) s8 mpad (m+) mpad-m,s 2constant ml4 0 mpad ! eol-s mpad (m+) ml4 mpad (m+) mpad-m,s 2constant ml5 TESTING UPTO-M! UPTO-M+ M!" M!` M+" M+` \ Note that input resumes immediately after the delimiting character. \ DO NOT CHANGE SPACING OR LINE BREAKS FOR INPUT STRINGS! \ upto-m! ( "" mbuf /mbuf char -- room? found? ) \ upto-m+ ( "" mbuf /mbuf char -- room? found? ) { mpad s9 s>/buf char # upto-m! 123456789#-> true true } { s9 mpad= -> true } { mpad ml1 1- s>/buf char 3 upto-m+ 123 -> false true 123 } s9 mpad (m!) { mpad ml1 s>/buf char # upto-m+ 12#-> true true } { ml1 mpad= -> true } 0 mpad ! { mpad ml1 s>/buf char # upto-m+ 123456789 12# -> true true } { ml1 mpad= -> true } { mpad ml1 s>/buf char # upto-m+ # -> true true } { ml1 mpad= -> true } { mpad 8 chars cell+ char 9 upto-m! 0123456789 -> false true 0123456789 } { mpad mcount s" " s= -> true } { mpad ml1 s>/buf char # upto-m! 123456789 12#-> true true } { ml1 mpad= -> true } { mpad ml2 s>/buf char # upto-m! 12345678 1#-> true true } { ml2 mpad= -> true } { mpad ml3 s>/buf char # upto-m! 123456789 #-> true true } { ml3 mpad= -> true } { mpad ml4 s>/buf char # upto-m! 12345678#-> true true } { ml4 mpad= -> true } 0 mpad ! { mpad cell char # upto-m+ # -> true true } { empty-s mpad= -> true } { mpad cell char # upto-m! # -> true true } { empty-s mpad= -> true } { mpad 8 chars cell+ char 9 upto-m! 12345678 19 -> false false 19 } { mpad mcount s" 12345678" s= -> true } { mpad 8 chars cell+ /eol + char 9 upto-m! 12345678 19 -> false true 19 } { mpad mcount ml2 1 cut-last s= -> true } \ Uncomment the following to test for the delimiter not found \ before the end of the file. Note that pfe clears the data \ stack after this test, while gforth leaves the expected output \ of UPTO-M!, ( true false). 0 [IF] 5000 constant /mbuf \ enough to include the rest of this file create mbuf /mbuf allot comment Execute "mbuf mcount type" to see the rest of the file. mbuf /mbuf 0 upto-m! \ null char not in this file [THEN] \ m!" m+" m!` m+` ( "" mbuf /mbuf -- flag ) { mpad s8 s>/buf m!" 12345678" s8 mpad= -> true true } { mpad cell m!" " empty-s mpad= -> true true } { mpad s2 s>/buf cell+ m!` 12` s2 mpad= -> true true } { mpad cell m!` ` empty-s mpad= -> true true } { mpad ml2 s>/buf m!" 12345678 1" ml2 mpad= -> true true } { mpad ml3 s>/buf m!` 123456789 ` ml3 mpad= -> true true } { mpad ml4 s>/buf m!" 12345678" ml4 mpad= -> true true } { mpad ml5 s>/buf m!" 12345678"ml5 mpad= -> true true } s8 mpad (m!) { mpad s8 s>/buf /eol + m+` ` -> true } { mpad dup mcount s>/buf m+` ` -> true } { mpad ml2 s>/buf m+" 1" ml2 mpad= -> true true } 0 mpad ! { mpad cell m+" " -> true } { mpad s9 s>/buf m+" 123456789" -> true } { s9 mpad= -> true } TESTING UPTO-M,S M,S" M,S` M" M` \ DO NOT CHANGE SPACING OR LINE BREAKS FOR INPUT STRINGS! \ upto-m,s ( "" char -- s ) { char # upto-m,s 123456789#s9 s= -> true } { char # upto-m,s # empty-s s= -> true } { char # upto-m,s 123456789 12#ml1 s= -> true } { char # upto-m,s 12345678 1#ml2 s= -> true } { char # upto-m,s 123456789 # ml3 s= -> true } { char # upto-m,s 12345678# ml4 s= -> true } \ Uncomment to test delimiter not found: 0 [IF] \ assume data space can contain the rest of this file 0 upto-m,s \ null char not in this file [THEN] \ m,s" ( "<">" -- s ) \ m,s` ( "<`>" -- s ) \ interpret { m,s" 12345678" s8 s= -> true } { m,s" "empty-s s= -> true } { m,s` 12` s2 s= -> true } { m,s` ` empty-s s= -> true } { m,s" 12345678 1"ml2 s= -> true } { m,s` 123456789 ` ml3 s= -> true } { m,s" 12345678" ml4 s= -> true } \ use in a definition : dfn-m,s" ( "<">" -- s ) m,s" ; : dfn-m,s` ( "<`>" -- s ) m,s` ; { dfn-m,s" 12345678" s8 s= -> true } { dfn-m,s" "empty-s s= -> true } { dfn-m,s` 12` s2 s= -> true } { dfn-m,s` ` empty-s s= -> true } { dfn-m,s" 12345678 1"ml2 s= -> true } { dfn-m,s` 123456789 ` ml3 s= -> true } { dfn-m,s" 12345678" ml4 s= -> true } \ The following is tested implicity through M" and M`: \ m"" \ compile: ( "" char -- ) \ \ run: ( -- s ) : [empty] m" " ; { [empty] s" " s= -> true } : [123] m` 123` ; { [123] s" 123" s= -> true } : [ml1] m" 123456789 12" ; { [ml1] ml1 s= -> true } : [ml2] m` 12345678 1` ; { [ml2] ml2 s= -> true } : [ml3] m" 123456789 " ; { [ml3] ml3 s= -> true } : [ml4] m` 12345678` ; { [ml4] ml4 s= -> true } : [ml5] m" 12345678" ; { [ml5] ml5 s= -> true } \ Uncomment to test interpret mode exception: \ m" 123" TESTING S-UPTO-M,+ S-UPTO-M,S |S|-UPTO-M,S \ s-upto-m+, ( "" pat.s m -- ) \ Across line tests are implicit, through S-UPTO-M,S. here aligned to mhere s" 123" m, { s" 123" mhere= -> true } { s" END" mhere s-upto-m+, 45ENDs" 12345" mhere= -> true } { here dup aligned = -> false } \ Uncomment to test noncontiguity abort: 0 [IF] here to mhere s" 1234" m, 1 chars allot s" END" mhere s-upto-m+, 56END [THEN] \ s-upto-m,s ( "" pat.s -- lines.s ) { s" END" s-upto-m,s 123456789ENDs9 s= -> true } { s" END" s-upto-m,s END empty-s s= -> true } { s" END" s-upto-m,s END eol-s s= -> true } { s" END" s-upto-m,s 123456789 12END ml1 s= -> true } { s" END" s-upto-m,s 12345678 1ENDml2 s= -> true } { s" END" s-upto-m,s 123456789 END ml3 s= -> true } { s" END" s-upto-m,s 12345678END ml4 s= -> true } \ Uncomment to test string not found: 0 [IF] \ assume data space can contain the rest of this file s" nowhere to be found" s-upto-m,s \ should not be in this file [THEN] \ |s|-upto-m,s ( "" pat.s -- lines.s ) { s" END" |s|-upto-m,s 123456789 END s9 s= -> true } { s" END" |s|-upto-m,s END empty-s s= -> true } { s" END" |s|-upto-m,s END eol-s s= -> true } { s" END" |s|-upto-m,s 123456789 12 END ml1 s= -> true } { s" END" |s|-upto-m,s 12345678 1 END ml2 s= -> true } { s" END" |s|-upto-m,s 123456789 END ml3 s= -> true } \ "END" starts text buffer with empty parse area { s" END" |s|-upto-m,s 123456789 END ml3 s= -> true } \ "END" starts text buffer with nonempty parse area { s" END" |s|-upto-m,s 12345678 END ml4 s= -> true } { s" END" |s|-upto-m,s 12END3 END s" 12END3" s= -> true } { s" END" |s|-upto-m,s 12 END3 END s" 12 END3 " s= -> true } { s" END" |s|-upto-m,s 12END 3 END s" 12END 3 " s= -> true } \ Uncomment to test string not found: 0 [IF] \ assume data space can contain the rest of this file s" NTBF" |s|-upto-m,s NTBFis not white delimitedNTBF [THEN] VERBOSE @ [IF] blue-text .( #ERRORS: ) #errors @ . normal-text cr [THEN]