OpenBoot provides the ability to change the definition of a previously compiled Forth word using high-level Forth language. While the changes will typically be made in the appropriate source code, the patch facility provides a means of quickly correcting errors uncovered during debugging.
patch reads the input stream for the following information:
The name of the new code to be inserted.
The name of the old code to be replaced.
The name of the word containing the old code.
For example, consider the following example in which the word test is replaced with the number 555:
ok : patch-me test 0 do i . cr loop ; ok patch 555 test patch-me ok see patch-me : patch-me h# 555 0 do i . cr loop ;
When using patch, some care must be taken to select the right word to replace. This is especially true if the word you are replacing is used several times within the target word and the occurrence of the word that you want to replace is not the first occurrence within the target word. In such a case, some subterfuge is required.
ok : patch-me2 dup dup dup ( This third dup should be drop) ; ok : xx dup ; ok patch xx dup patch-me2 ok patch xx dup patch-me2 ok patch drop dup patch-me2 ok see patch-me2 : patch-me2 xx xx drop ;
Another use for patch is the case where the word to be patched contains some functionality that needs to be completely discarded. In this case, the word exit should be patched over the first word whose functionality is to be eliminated. For example, consider a word whose definition is:
ok : foo good bad unneeded ;
In this example, the functionality of bad is incorrect and the functionality of unneeded should be discarded. A first attempt to patch foo might be:
ok : right this that exit ; ok patch right bad foo
on the expectation that the use of exit in the word right would prevent the execution of unneeded. Unfortunately, exit terminates the execution of the word which contains it, in this case right. The correct way to patch foo is:
ok : right this that ; ok patch right bad foo ok patch exit unneeded foo
(patch) is similar to patch except that (patch) obtains its arguments from the stack. The stack diagram for (patch) is:
( new-n1 num1? old-n2 num2? xt -- )
where:
new-n1 and old-n2 can be either execution tokens or literal numbers.
num1? and num2? are flags indicating whether new-n1 or old-n2, respectively, are numbers.
xt is the execution token of the word to be patched.
For example, consider the following example in which we reverse the affect of our first patch example by replacing the number 555 with test:
ok see patch-me : patch-me h# 555 0 do i . cr loop ; ok ['] test false 555 true ['] patch-me (patch) ok see patch-me : patch-me test 0 do i . cr loop ;