Bud Utility © 2006, Derek Parnell, Melbourne
(table of contents)
The macro system in Bud works by transforming the contents of a file,
via the use of special commands, into a new file that will be
compiled.
The macro system is fairly restricted for now but a much more powerful
facility will be available in subsequent releases of Bud. However, in spite
of this, a lot can be achieved by the current macro facility.
How it Works
Bud firstly examines the default Macro Definition File (MDF)
and preprocesses
the defined special commands in preparation for any macro files it may be
presented with. Next, whenever it encounters a macro file on the command
line or response file, it transforms the macro file, based on the commands
from the MDF and any embedded commands, into a file that is later compiled.
Macro Definition File
The format of the MDF is a text file that can contain any number of
defined commands and comments. Comments start with a
#
(hash symbol) and extend to the end of the line. Blank lines
are ignored also. Commands take the form ...
<action><pattern>=<replacement>
where <action> can be
The action
"replace" will replace all occurances of
<pattern> with the
<replacement> text. The <pattern>
can take two forms: a quoted string, or an unquoted set of words. If the
pattern is enclosed in quotes it represents a literal string of characters
to be replaced wherever it is found in the macro file. If the pattern is
not enclosed in quotes it represents a set of adjacent words to be found
and replaced by the replacement text.
Example: Word replacement
replace endproc=}
will match
"endproc" and
"endproc",
but will not match any of
"bendproc",
"endprocedure", or
"end.proc ".
Example: Text replacement
replace "endproc"=}
will match any of
"endproc",
"bendproc",
"endprocedure",
but will not match
"endproc" or
"end.proc "
The <replacement> text will have to be quoted if it must begin or end
with spaces.
Example: Leading and trailing blanks in replacement text
replace vernote="Version1.0,"
The action
"regexp" will replace all occurances of
<pattern> with the
<replacement> text. The <pattern>
is a regular expression.
Example: Regular Expression replacement
regexp inc\s+(\w+) = $1++
will match "inc" followed by one or more spaces followed by one or more
'word' characters such as
"incmyvar" and replace the matching
pattern with the word in the pattern followed by "++". In this case it would
be replaced by
"myvar++".
Example: C-style assert
regexp assert\((.*),(.*)\); = if (!()) {writefln(`%%s:%%s`, ``, ); assert(0);}
// usage
assert(somefield > 3, "More than 4 is required");
// transformation
if (!(somefield > 3)) {writefln(`%s:%s`, `somefield > 3`, "More than 4 is required"); assert(0);}
The <replacement> text will have to be quoted if it must begin or end
with spaces.
Example: Leading and trailing blanks in replacement text
regexp (Version\s)(\?) = "$15.0"
There are some special tokens that can be in the
replacement text.
\n | New Line | An end-of-line marker replaces this token. |
\t | Tab | A tabulator character (ASCII 09) replaces this token. |
\s | Conditional Space | If the previous output character
is not a space then a space
character replaces this token
otherwise the token is removed. |
Sometimes, it will be necessary to have one of the
delimiter characters, such as the
quote character
or the
equals symbol, as a part of the pattern or replacement text.
In order to allow this, the MDF can contain override commands that specify
alternatives to use for the rest of the MDF or another override.
The override command has the format
delim<type>=<alternative>
where <type> can be
Type | Description | Example | Default |
open | Begins a pattern or replacement text | open=< | " |
close | Ends a pattern or replacement text | close=> | " |
escapeopen | Begins a special token | escapeopen=% | \ |
escapeclose | Ends a special token | escapeclose=% | |
comment | Defines the comment leading text | comment=; | # |
equate | Defines the 'equals' symbol | equate=: | = |
Another form of the
delim command is
delim std
which restores all the default delimiter values.
All the commands above can be embedded inside a macro file. To do this,
the commands must be prefixed with an
'@' symbol and start on
first column.
Example:
@replace becos because
Additionally there is another command that is only recognized when embedded
in a macro file. This is the
output command. It tells
Bud what
name to use for the transformed file.
Example: Send output to another file
@output ../result/mytest.d
If the
output command is not found in a file, the transformed file
is assumed to tbe the same name as the macro file but with ".d" as
the extension. In other words, "test.mac" when transformed becomes "test.d".
It is important to note that
all embedded macro commands are removed from
the transformed file and that no embedded macro command can modify any other
embedded macro command.