: string ( -- c- u ) s" \n" ; ( two characters, \ and an n ) : string ( -- c- u ) s" John 'Maddog' Orwant" ; ( literal single quotes ---------------------------- ) : string ( -- ) cr ; ( a "newline" character, or: ) : string ( -- ) newline type ; ( a "newline" character, or: ) : string ( -- c ) 13 ; ( depending, obviously, on your platform's newline ) ( double quotes must be entered manually ) : put-quote ( c- u -- ) + 34 swap c! ; : string ( -- c- u ) s" Jon Maddog Orwant" over dup 4 put" 11 put" ( literal double quotes ) ; ( no q/ / type quoting options ---------------------------- some words to make a here document: ) : newline? ( c -- f ) dup 10 = swap 13 = or ( or whatever the newline is for your platform ) ; : get-terminator ( -- c- u ) here dup 12 chars allot 12 accept ( change 12 if you absolutely must have a larger EOF marker than 12 characters ) cr ; : get-char ( -- c ) key dup emit dup here 1 chars allot c! ; : line-in ( -- u ) 0 begin 1 + get-char 13 = until 1 - ; : <<< ( -- c- u ) \ A parsing <<< would be cute but I don't want to deal with writing one get-terminator here -rot begin line-in here over - 1 - swap 2over compare not until drop drop here over - ; <<< EOF This is a multiline here document terminated by EOF on a line by itself EOF |
: substr ( c- u u u -- c- u ) dup 0= if drop tuck - else 2dup + 2swap -rot dup -rot > if rot drop 2dup swap - nip else drop swap then then -rot + 0 -rot swap here swap 2dup chars allot drop 0 do over i + c@ over i + c! rot 1+ -rot loop nip swap ; : value string offset count substr ; : value string offset 0 substr ; : reassign ( c- u u u c- u -- c- u ) { addr1 strlen1 offset count addr2 strlen2 } strlen1 count - strlen2 + allocate throw addr1 over offset cmove addr2 over offset chars + strlen2 cmove addr1 offset chars + count chars + over offset chars + strlen2 chars + strlen1 count - offset - cmove strlen1 count - strlen2 + ; string offset count newstring reassign ( ---------------------------- get a 5-byte string, skip 3, then grab 2 8-byte strings, then the rest. ) : unpack ( c- u -- c-1 u1 c-2 u2 c-3 u3 c-4 u4 ) 2>r 5 chars allocate throw 2r@ drop over 5 cmove 5 8 chars allocate throw 2r@ drop 8 chars + over 8 cmove 8 8 chars allocate throw 2r@ drop 16 chars + over 8 cmove 8 2r> 24 - dup chars allocate throw dup 2swap >r r@ swap 24 + -rot cmove r> ; ( split at five byte boundaries ) : fivers ( c- u -- c-1 u1 c-2 u2 ... c-n un ) 5 / 0 do 5 chars allocate throw 2dup swap i 5 * chars + swap 5 cmove 5 rot loop drop ; ( chop string into individual characters ) : chop ( c- u -- c1 c2 ... cn ) 0 do dup i chars + c@ swap loop drop ; ( ---------------------------- ) : string s" This is what you have" ; : first string drop 1 ; ( "T" ) : start string drop 5 chars + 2 ; ( "is" ) : rest string 13 swap over - -rot chars + swap; ( "you have" ) : last string 1 - chars + 1 ; ( "e" ) : end string 4 - chars + 4 ; ( "have" ) : piece string 8 - chars + 3 ; ( "you" ) ( ---------------------------- ) : string s" This is what you have" ; string type ( This is what you have ) string 5 2 s" wasn't" reassign ( change "is" to "wasn't" This wasn't what you have ) string 13 12 s" ondrous" reassign ( replace last 12 characters This wasn't wondrous ) string swap 1 chars + swap 1 - ( delete first character his wasn't wondrous ) string 10 - dup -rot resize throw swap ( delete last 10 characters his wasn' ) ( ---------------------------- TODO RE's ------------------------------ exchange first and last letters in a string ) : a s" make a hat" ; : exchange ( c- u -- ) 1 - 2dup chars + c@ -rot over c@ -rot chars over + rot swap c! c! ; a exchange type ( take a ham ------------------------------ extract column ) : a "To be or not to be" ; : b ( c- u u u -- c- u ) dup chars allocate throw swap ( c- len off cou c-2 ) >r >r nip chars + 2r@ cmove r> r> ; a 6 6 ( skip 6, grab 6 ) b type ( or not ) |
( use b if b is true, else c ) : default ( x a- -- ) dup @ not if ! else 2drop then ; c b default a ! ( set x to y unless x is already true ) : !? dup if ! else drop then ; x dup @ 0= y @ and swap !? |
: swap! ( x x -- ) 2dup @ swap @ rot ! swap ! ; var1 var2 swap! ( ---------------------------- ) variable temp a @ temp ! b @ a ! temp @ b ! ( ---------------------------- ) |
( not an issue, really; a char is just an integer and stored as a cell on the stack ) : ord ( c -- u ) ; : chr ( u -- c ) ; ( or, to see the char ) : chr ( u -- ) emit ; ( but if it's an actual variable rather than a stack element: ) : ord ( c- -- a- ) 1 cells allocate throw swap c@ swap ! ; : chr ( a- -- c- ) 1 chars allocate throw swap @ swap c! ; |
( with a literal word ) : process-string ( c- u -- variable stack effect ) 0 do dup i chars + c@ ( your-word ) swap loop drop ; ( or better yet, with an execution token ) : map-xt ( xt c- u -- variable stack effect ) 0 do 2dup i chars + c@ swap execute loop ; |
: 4dup-nip ( a b c d -- a b c d a b d ) 2over 2over nip ; : c[i]@ ( c- i -- c ) chars + c@ ; : c[i]! ( c- i c -- ) chars + c! ; : -cmove ( c- x c- -- c- x ) over 0 u+do i 4dup-nip 1+ - c[i]@ 2over nip rot c[i]! loop rot drop swap ; : revbytes ( c- x -- c- x ) dup allocate throw -cmove ; : gnirts s" string" revbytes ; : space? 32 = ; : ^? ( c c- a -- c t ) c[i]@ tuck space? not swap space? and ; : -^? ( c c- a -- c t ) c[i]@ tuck space? swap space? not and ; : count-words ( c- x -- x ) 0 -rot 32 swap 0 u+do over i ^? if rot 1+ -rot then loop drop drop ; : last-spaces ( c- x -- x ) 0 -rot begin 1- 2dup c[i]@ space? over 0 >= and while rot 1+ -rot repeat drop drop ; : last-word ( c- x -- x ) 0 -rot begin 1- 2dup c[i]@ space? not over 0 >= and while rot 1+ -rot repeat drop drop ; : back>front ( c- x c- x -- ) 2swap 2dup last-word -rot chars + over chars - swap rot drop rot swap cmove ; : sback>front ( c- x c- x -- ) 2swap 2dup last-spaces -rot chars + over chars - swap rot drop rot swap cmove ; : sdrow ( c- x -- c- x ) 2dup last-spaces - dup >r dup chars allocate throw dup >r over 2swap 2dup count-words 0 u+do 2dup last-word >r 2over 2over 2swap back>front r@ - rot drop dup -rot 2swap r> rot + swap 2swap 2dup last-spaces >r 2over 2over 2swap sback>front r@ - rot drop dup -rot 2swap r> rot + swap 2swap loop 2drop 2drop r> r> ; : count-spaces ( c- x -- x ) 0 -rot 0 u+do dup i c[i]@ space? if swap 1+ swap then loop drop ; : move-if-not-space ( c- c- -- f ) swap c@ dup space? if drop drop false else swap c! true then ; : squash-words ( c- x -- c- x ) 2dup count-spaces over swap - dup chars allocate throw swap >r dup >r -rot 0 u+do 2dup i chars + swap move-if-not-space if swap 1 chars + swap then loop drop drop r> r> ; : confused ( c- x -- c- x ) squash-words revbytes ; 80 constant biggest-word create buff biggest-word 2 + allot : palindrome? ( c- x -- f ) 2dup revbytes compare not ; : chomp ( c- x -- c- x ) 2dup last-spaces - ; s" /usr/share/dict/words" r/o open-file throw value dict : scan-dictionary ( c- x -- ) begin buff biggest-word dict read-line throw while dup buff swap chomp dup 5 > -rot palindrome? and if buff swap type cr else drop then repeat ; |