blob: 7880374326e57bfab82d13a3a3171dba4c7ea522 [file] [log] [blame]
\ See license at end of file
\ Patch utility. Allows you to make patches to already-defined words.
\ Usage:
\ PATCH new old word-to-patch
\ In the definition of "word-to-patch", replaces the first
\ occurence of "old" with "new". "new" may be either a word
\ or a number. "old" may be either a word or a number.
\
\ n-new n-old NPATCH word-to-patch
\ In the definition of "word-to-patch", replaces the first
\ compiled instance of the number "n-old" with the number
\ "n-new".
\
\ n-new n-old start-adr end-adr (NPATCH
\ replaces the first occurrence of "n-old" in the word "acf"
\ with "n-new"
\
\ acf-new acf-old acf (PATCH
\ replaces the first occurrence of "acf-old" in the word "acf"
\ with "acf-new"
\
\ new new-type old old-type acf (PATCH)
\ replaces the first occurrence of "old" in the word "acf" with "new".
\ If "new-type" is true, "new" is a number, otherwise "new" is an acf.
\ If "old-type" is true, "old" is a number, otherwise "old" is an acf.
\
\ n start-adr end-adr SEARCH
\ searches for an occurrence of "n" between start-adr and
\ end-adr. Leaves the adress where found and a success flag.
\
\ c start-adr end-adr CSEARCH
\ searches for a byte between start-adr and end-adr
\
\ w start-adr end-adr WSEARCH
\ searches for a 16-bit word between start-adr and end-adr
\
\ acf start-adr end-adr TSEARCH
\ searches for a compiled adress between start-adr and end-adr
\
\
decimal
: csearch ( c start end -- loc true | false )
false -rot swap ?do ( c false )
over i c@ = if
drop i swap true leave
then
/c +loop nip
;
: wsearch ( w start end -- loc true | false )
rot n->w \ strip off any high bits
false 2swap swap ?do ( w false )
over i w@ = if
drop i swap true leave
then
/w +loop nip
;
: tsearch ( adr start end -- loc true | false )
false -rot swap ?do ( targ false )
over i token@ = if
drop i swap true leave
then
\ Can't use /token because tokens could be 32-bits, aligned on 16-bit
\ boundaries, with 16-bit branch offsets realigning the token list.
#talign +loop nip
;
: search ( n start end -- loc true | false )
false -rot swap ?do ( n false )
over i @ = if
drop i swap true leave
then
#talign +loop nip
;
headerless
: next-token ( adr -- adr token )
dup token@ ( n adr token )
dup ['] unnest = abort" Can't find word to replace" ( n adr token )
;
\ Can't use ta1+ because tokens could be 32-bits, aligned on 16-bit
\ boundaries, with 16-bit branch offsets realigning the token list.
: talign+ ( adr -- adr' ) #talign + ;
: find-lit ( n acf -- adr )
>body
begin
next-token ( n adr token )
\t16 dup ['] (wlit) = if ( n adr token )
\t16 drop ( n adr )
\t16 2dup ta1+ w@ 1- = if ( n adr )
\t16 nip exit ( adr )
\t16 else ( n adr )
\t16 ta1+ wa1+ ( n adr' )
\t16 then ( n adr )
\t16 else ( n adr token )
dup ['] (lit) = if ( n adr token )
drop ( n adr )
2dup ta1+ @ = if ( n adr )
nip exit ( adr )
else ( n adr )
ta1+ na1+ ( n adr' )
then ( n adr )
else ( n adr token )
['] (llit) = if ( n adr )
2dup ta1+ l@ 1- = if ( n adr )
nip exit ( adr )
else ( n adr )
ta1+ la1+ ( n adr' )
then ( n adr' )
else ( n adr )
talign+ ( n adr' )
then ( n adr' )
then ( n adr' )
\t16 then
again
;
: find-token ( n acf -- adr )
>body
begin
next-token ( n adr token )
2 pick = if nip exit then ( n adr )
talign+ ( n adr' )
again
;
: make-name ( n digit -- adr len )
>r <# u#s ascii # hold r> hold u#> ( adr len )
;
: put-constant ( n adr -- )
over
base @ d# 16 = if
ascii h make-name
else
push-decimal
ascii d make-name
pop-base
then ( n adr name-adr name-len )
\ We don't use "create .. does> @ because we want this word
\ to decompile as 'constant'
warning @ >r warning off
$header ( n adr )
constant-cf swap , ( adr )
r> warning !
lastacf swap token!
;
: put-noop ( adr -- ) ta1+ ['] noop swap token! ;
\t16 : short-number? ( n -- flag ) -1 h# fffe between ;
\t32 : long-number? ( n -- flag ) -1 h# ffff.fffe n->l between ;
headers
: (patch) ( new number? old number? word -- )
swap if ( new number? old acf ) \ Dest. is num
find-lit ( new number? adr )
\t16 dup token@ ['] (wlit) = if ( new number? old ) \ Dest. slot is wlit
\t16 swap if ( new adr ) \ replacement is a number
\t16 over short-number? if ( new adr ) \ replacement is short num
\t16 ta1+ swap 1+ swap w! ( )
\t16 exit
\t16 then ( new adr ) \ Replacement is long num
\t16 tuck put-constant ( adr )
\t16 put-noop ( )
\t16 exit
\t16 then ( new adr ) \ replacement is a word
\t16 tuck token! put-noop ( )
\t16 exit
\t16 then ( new number? adr ) \ Dest. slot is lit
\t32 dup token@ ['] (llit) = if ( new number? old ) \ Dest. slot is wlit
\t32 swap if ( new adr ) \ replacement is a number
\t32 over long-number? if ( new adr ) \ replacement is short num
64\ \t32 ta1+ swap 1+ swap l! ( )
32\ \t32 ta1+ l! ( )
\t32 exit
\t32 then ( new adr ) \ Replacement is long num
\t32 tuck put-constant ( adr )
\t32 put-noop ( )
\t32 exit
\t32 then ( new adr ) \ replacement is a word
\t32 tuck token! put-noop ( )
\t32 exit
\t32 then ( new number? adr ) \ Dest. slot is lit
swap if ta1+ ! exit then ( new adr ) \ replacement is a word
tuck token! ( adr )
32\ \t16 dup put-noop ta1+ ( )
64\ \t16 dup put-noop ta1+ dup put-noop dup put-noop ta1+ ( )
64\ \t32 dup put-noop ta1+
put-noop ( )
exit
then ( new number? old acf ) \ Dest. is token
find-token ( new number? adr )
swap if put-constant exit then ( new adr ) \ replacement is a number
token!
;
headerless
: get-word-type \ word ( -- val number? )
parse-word $find if false exit then ( adr len )
$dnumber? 1 <> abort" ?" true
;
headers
: (npatch ( newn oldn acf -- ) >r true tuck r> (patch) ;
: (patch ( new-acf old-acf acf -- ) >r false tuck r> (patch) ;
\ substitute new for first occurrence of old in word "name"
: npatch \ name ( new old -- )
true tuck ' ( new true old true acf ) (patch)
;
: patch \ new old word ( -- )
get-word-type get-word-type ' (patch)
;
\ LICENSE_BEGIN
\ Copyright (c) 2006 FirmWorks
\
\ Permission is hereby granted, free of charge, to any person obtaining
\ a copy of this software and associated documentation files (the
\ "Software"), to deal in the Software without restriction, including
\ without limitation the rights to use, copy, modify, merge, publish,
\ distribute, sublicense, and/or sell copies of the Software, and to
\ permit persons to whom the Software is furnished to do so, subject to
\ the following conditions:
\
\ The above copyright notice and this permission notice shall be
\ included in all copies or substantial portions of the Software.
\
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\
\ LICENSE_END