\ substitute stuff
require string.fs
wordlist AConstant macros-wordlist
: macro: ( addr u -- ) Create here 0 , $! DOES> $@ ;
: replaces ( addr1 len1 addr2 len2 -- )
\G create a macro with name @var{addr2 len2} and content @var{addr1 len1}.
\G if the macro already exists, just change the content.
2dup macros-wordlist search-wordlist
IF nip nip >body $!
ELSE
get-current >r macros-wordlist set-current
['] macro: execute-parsing
r> set-current
THEN ;
Variable macro$
: $substitute ( addr1 len1 -- addr2 len2 n )
\G substitute all macros in text @var{addr1 len1}.
\G @var{n} is the number of substitutions, @var{addr2 len2} the result.
s" " macro$ $! 0 >r
BEGIN dup WHILE '%' $split
2swap macro$ $+! dup IF
over c@ '%' = IF
over dup 1+ over - macro$ $+! 1 /string
ELSE
'%' $split 2swap dup 0= IF
2drop s" %" macro$ $+! r> 1+ >r
ELSE
macros-wordlist search-wordlist IF
-rot 2>r execute macro$ $+! 2r> r> 1+ >r
THEN
THEN
THEN
THEN
REPEAT 2drop macro$ $@ r> ;
: substitute ( addr1 len1 addr2 len2 -- addr2 len3 n )
\G substitute all macros in text @var{addr1 len1}, and copy the
\G result to @var{addr2 len2}. @var{n} is the number of
\G substitutions, @var{addr2 len3} the result. If
\G @var{len2}=@var{len3}, it is likely that the string did not fit.
2swap $substitute >r
2swap rot umin 2dup >r >r move r> r> r> ;
: unescapes ( addr1 u1 dest -- dest u2 )
\G double all delimiters in @var{addr1 u1}, so that substitute
\G will result in the original text. Note that the buffer
\G @var{dest} does not have a size, as in worst case, it will need
\G just twice as many characters as @var{u1}. @{dest u2} is the
\G resulting string.
dp @ >r dup >r dp !
bounds ?DO
I c@ dup '%' = IF dup c, THEN c,
LOOP r> here over - r> dp ! ;