Bud Utility © 2006, Derek Parnell, Melbourne
(table of contents)

Topic: Macros

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.

Generated by Ddoc, Mon Oct 16 11:03:25 2006