VFX Forth implements text macro substitution, where a text macro
named FOO
my be substituted in a string. When referenced in a
string the macro name must be surrounded by % characters. If a %
character is needed in a string it must be entered as %%.
Thus if FOO
is defined as "c:\apps\vfxforth" then the string
"Error in file %FOO%\myfile.fth at line "
would be expanded to
"Error in file c:\apps\vfxforth\myfile.fth at line "
Macros are defined in the Substitutions
vocabulary
which is searched when the string is expanded. When executed
these words return the address of a counted string for the
text to substitute.
TextMacro: <name>
defines an empty macro with a 255
character buffer in the Substitutions
vocabulary.
<string> SETMACRO <name>
sets the given string into the
required macro <name>
. If <name>
does not exist in
the Substitutions
vocabulary an error is reported.
SETMACRO
may also be used in colon definitions, providing
that the macro name already exists. If a colon definition needs
to create a new macro name it should use $SETMACRO
instead.
TEXTMACRO: FOO
C" c:\apps\vfxforth" SETMACRO FOO
: BAR \ --
C" h:\myapp" SETMACRO FOO
;
$100 buffer: temp
<source> <dest> $EXPAND \ expand source string into destination
: substitute \ src slen dest dlen -- dest dlen' n ; 17.6.2.2255
Expand the source string using text macro substitutions,
placing the result in the buffer dest/dlen and
returning the destination string dest/dlen' and the
number n of substitutions made. If an error occurred,
n is negative. Ambiguous conditions occur if the
result of a substitution is too long to fit into the given
buffer or the source and destination buffers are the same.
Substitution occurs left to right from the start of src/slen
in one pass and is non-recursive. When text of a potential
substitution name, surrounded by ?%? (ASCII $25) delimiters
is encountered by SUBSTITUTE
, the following occurs:
a) If the name is null, a single delimiter character is passed
to the output, i.e., %% is replaced by %. The current number
of substitutions is not changed.
b) If the text is a valid substitution name, the leading and
trailing delimiter characters and the enclosed substitution
name are replaced by the substitution text. The current number
of substitutions is incremented.
c) If the text is not a valid substitution name, the name with
leading and trailing delimiters is passed unchanged to the
output. The current number of substitutions is not changed.
d) Parsing of the input string resumes after the trailing delimiter.
: substituteC \ src slen dest dlen --
Expand the source string using text macro substitutions,
placing the result as a counted string at dest/dlen.
If an error occurred, the length of the counted string
is zero.
: substituteZ \ src slen dest dlen --
Expand the source string using text macro substitutions,
placing the result as a zero terminated string at dest/dlen.
If an error occurred, the length of the string is zero.
: replaces \ text tlen name nlen -- ; 17.6.2.2141
Define the string text/tlen as the text to substitute for the
substitution named name/nlen. If the substitution does not
exist it is created.
: subsitute-safe \ c-addr1 len1 c-addr2 len2 -- c-addr2 len3 ior
Replace each '%' character in the input string c-addr1/len1
by two '%' characters. The output buffer is represented by
caddr2/len2. The output is caddr2/len3 and ior
is zero on success.
If you pass a string through SUBSITUTE-SAFE
and then
SUBSTITUTE
, you get the original string.
: unescape \ caddr1 len1 caddr2 -- caddr2 len2 ; 17.6.2.2375
Replace each '%' character in the input string caddr1/len1
by two '%' characters. The output is represented by caddr2/len2.
The buffer at caddr2 shall be big enough to hold the
unescaped string. An ambiguous condition occurs if the
resulting string will not fit into the destination buffer
caddr2.
: MacroExists? \ caddr -- xt nz | 0
If a macro of the given name exists, return its xt and a
non-zero flag, otherwise just return zero. The name is a
counted string.
: MacroSet? \ caddr -- flag
If a macro of the given name exists and text has been set
for it, return true. Often used to find out if a macro has
been set, so that a sensible default can be defined. In the
following example, IDIR
is the current include directory
and MC"
is a version of C"
that expands macros.
c" GuiLib" MacroSet? 0= [if]
mc" %IDIR%" SetMacro GuiLib
[then]
: TextMacro: \ <"name"> --
Builds a new text-macro with an empty macro string.
TextMacro: Foo
: setMacro \ string "<name>" --
Reset/Create a text macro. Used in the form:
C" abcd" SETMACRO <name>
For historical reasons, this word can be used inside a colon definition in the form:
C" abcd" SETMACRO <name>
If you want to use setMacro
as a factor in another word,
you probably want the interpretation action, so use:
... [INTERP] setMacro ...
rather than
... setMacro ...
: $setmacro \ string name --
This version of SETMACRO
takes both the string and
macro name as counted strings.
: getTextMacro \ caddr len -- macro$
Given a macro name, return the address of its text (a counted
string). If the name cannot be found the null counted string
cNull
is returned.
: .macros \ --
Display all text macros by macro name.
: .macro \ "<name>" -- ; .MACRO <name>
Display the text for macro <name>
.
: ShowMacros \ --
Display all macro names and text.
: Expand \ caddr len -- caddr' len'
Macro expand the given string, returning a global buffer
containing the expanded string. The string is zero-terminated
and has a count byte before caddr'. If len is longer
than 254 bytes only the first 254 bytes will be processed.
: $expand \ $source $dest --
Macro expand a counted string at $source to a counted
string at $dest. The returned string is counted and
zero terminated.
: $ExpandMacros \ $ -- $'
Macro expand a counted string. Note that the returned string
buffer is in a global buffer.
: z$ExpandMacros \ z$ -- 'z$
Macro expand a 0 terminated string. The
returned string buffer is a global buffer.
: ExpandMacro \ c-addr len buff -- 'buff len'
Perform TextMacro expansion on a string in c-addr u with
the result being placed as a counted string at buff. The
address and length of the expanded string are returned. The
string at buff' is zero terminated.
: M", \ "text" --
Compile the text string up to the closing quote into the
dictionary as a counted string, expanding text macros as
M",
executes, usually at compile time.
The end of the string is aligned.
: MS" \ Comp: "<quote>" -- ; Run: -- c-addr u
Like S"
but expands text macros. Text is taken up to
the next double-quotes character. Text macros are expanded
at compile time. The address and length of the string are
returned. To expand macros at run time, use:
s" <string>" expand
: MC" \ Comp: "<quote>" -- ; Run: -- c-addr
Like C"
but expands text macros. Text is taken up to
the next double-quotes character. Text macros are expanded at
compile time. At run-time the address of the counted string
is returned. To expand macros at run time, use:
c" <string>" $ExpandMacros
The following text macros are defined by the system and are
always available. They are implemented as words in the
substitutions
vocabulary.
create VfxPath ( -- c$ ) 0 c, $FF allot
The path containing the VFX Forth source code.
For most users, this is the root
folder of the VFX Forth installation; however for Mission
and Ultimate edition users, VfxPath
must be set to
the Sources folder of the VFX Forth installation.
You must set this yourself. It is preserved in the INI
file.
create BasePath ( -- c$ ) 0 c, $FF allot
The root folder of the VFX Forth installation. You
must set this yourself. It is preserved in the INI
file. Do not use BasePath
as the root of the VFX
source tree.
create DevPath ( -- c$ ) 0 c, $FF allot
The path containing the developer's application source.
If selected by setting BuildLevel
to -1, the contents
of this macro will be prepended to source file names in
the SOURCEFILES
vocabulary.
create LOCATE_PATH ( -- c$ ) 0 c, $FF allot
The name of the current/last file to be compiled.
Used by LOCATE
and friends.
create LOCATE_LINE ( -- c$ ) 0 c, $FF allot
The line number of the line in the current file being compiled.
Used by LOCATE
and friends.
: f locate_path ;
The name of the current/last file to be compiled.
A synonym for LOCATE_PATH
. Used by LOCATE
and friends.
: l locate_line ;
The line number of the line in the current file being compiled.
A synonym for LOCATE_LINE
. Used by LOCATE
and friends.
create LIBRARYDIR ( -- c$ ) 0 c, $FF allot
The pathname of the VFX Forth Lib directory.
: lib LIBRARYDIR ;
A synonym for LIBRARYDIR
above, which returns
the pathname of the VFX Forth Lib directory.
create LOAD_PATH ( -- c$ ) 0 c, $FF allot
The directory containg the running program's executable.
: bin LOAD_PATH ;
The directory containing the VFX Forth executables.
A synonym for LOAD_PATH
.
: idir \ -- c$
The current include directory. This string is '.' if no file
is being INCLUDE
d and allows a load file to be
in the form below. The load file can then be referenced
from any other directory.
\ include \dir1\dir2\dir3\loadfile.fth
\ in loadfile.fth
include %idir%\file1.fth \ file1 in dir3
include %idir%\file2.fth \ file2 in dir3
...
create wd \ -- c$
The working directory. Under Windows, DOS, Unices and OS X
this is ".". Do not change this macro.
LOAD_PATH constant Forth-Buff \ -- caddr
Returns the address of a counted string holding the directory
from which the application was loaded. This gives programs
easy access to the LOAD_PATH
macro.
The code described here is specific to VFX Forth for MacOS. Do not rely on any of the words documented here being present in any other VFX Forth implementation.
: GetExeNameZ \ zaddr --
Get the fully qualified name of the executable. It is saved
as a 0 terminated string at zaddr. The buffer is assumed to
be at least 1024 characters long.
: InitMacros \ --
Initialises the directory macros. Run at start up.
#256 buffer: editor$ \ -- addr
A buffer holding the path and name of the preferred editor
as a counted string, e.g.
/bin/vi
0 value EditOnError? \ -- flag
Set true to call the editor on an error.
: editor-is \ "<editor-name>" --
Set your preferred editor, e.g.
editor-is /bin/vi
editor-is /Applications/UltraEdit.app/Contents/MacOS/UltraEdit
editor-is edit
: .ed \ --
Display the name of your preferred editor
#256 buffer: locate$ \ -- addr
A buffer holding the macro expansion required to edit a
specific line of a file. This information is used by
LOCATE
. In the example below the macros
%f% and %l% will be replaced by the file name and
line number.
%f% -# %l%
-- "%f%" --lc%l%:1 &
+%l% "%f%" &
: edit$ \ -- cstring
If the preferred editor has been set, return the program name,
otherwise return the default editor string for nano.
0 value DebugLocate? \ -- x
If non-zero, the string passed to the shell for LOCATE
is displayed before the system is called.
: $edit \ cstring --
Edit the file provided as a counted string.
: edit \ "<filename>" --
Edit the file whose name follows in the input stream, e.g.
EDIT release.txt
: (EditOnError) \ -- ; run editor on error
Edit the file at an error, using the contents of the variables
'SOURCEFILE
and LINE#
.
: SetLocate \ --
Tells VFX Forth how your editor can be called to go a
particular file and line. Use in the form
SetLocate <rest of line>
where the text after SetLocate
is used to define
how parameters are passed to the editor, e.g. for Emacs,
use
SetLocate +%l% "%f%" &
The rest of line following SetLocate
is used as the
editor configuration string. Within the editor configuration
string 'f' will be replaced by the file name and 'l' will be
replaced by the line number. If you use file names with spaces,
you should put quotation marks around the %f%
text macro.
You must finish the line with " &" to run the editor
detached from VFX Forth - LOCATE
adds this for you.