de     

bmp -- babel macro processor

bmp is a powerful general purpose macro processor that can be used with many languages, e.g. Pascal or C. It was developed as a part of the ZTEX EZ-USB SDK and is used to assemble the firmware for EZ-USB micro controllers.

bmp is also available as a separate package and distributed as Open Source software under GPLv3. It is written in Freepascal and is known to run on Linux and Windows, but should run an every platform that is supported by Freepascal.

Download

The package can be downloaded from

It will contain the source files as well the binaries for Linux and Windows. The binaries are linked statically such that there are no system requirements.

Term definitions

term Definition
Macro Code sequence that is replaced by another code sequence. A macro may have parameters. The replacing process is called macro expansion.
Meta macro Code sequence for the definition of macros, conditional expansion of code, or control of the macro processor

Usage

The usage of bmp is

bmp [<Options>] [<filename1> [<filename2> ...]] .

<filename1>, filename2>, … denote the input files. If none is given, bmp reads from standard input stdin. The supported options are

Option Description
-o <filename> Output file. By default the output is written to standard output stdout.
-p Pascal mode (default), equal to -mm "//" -mo "[" -mc "]" -mp "#"
-c C mode, equal to -mm "#" -mo "[" -mc "]" -mp "$" -l '#line %2 "%1"'
-i Ignore upper/lower case of macros (not for meta macros)
-l Line info (default for C mode: '#line %2 "%1"'). The sequence “%1” is replaced by the file name and “%2” is replaced by the line number.
-I <directory> Include path. May be specified several times. bmp searches for (input) files in that directories.
-D <symbol> Define symbol <symbol>. May be specified several times. -D DEFINE_ME is equal to //define[DEFINE_ME]] in Pascal mode
-mm <string> Meta macro start string
-mo <char> Open bracket
-mc <char> Close bracket
-mp <char> Parameter character
-dd Print all definitions before exiting. This is intended for debug purposes.
-h Help

The syntax of the meta macros depends on four special meta sequences which can be set using the command line parameters -mm, -mo, -mc and -mp. The meaning of these meta sequences is explained in the following example:

A typical meta macro in Pascal mode (parameter -p) looks like

//define[REPLACE_ME(][,#1);][By this: #0 #1]

This defines a macro with two parameters. The same macro in C mode (parameter -c) is defined by

#define[REPLACE_ME(][,$1);][By this: $0 $1]

This example contains all four meta sequences:

Description of the meta sequence Command line parameter In Pascal mode In C Mode
Meta macro start string -mm // #
Open bracket character -mo [ [
Closing bracket character -mc ] ]
Parameter character -mp # $

Each meta macro begins with the meta macro start string at the beginning of a line. If a line begins with meta macro start string the rest of the line is only considered for meta macro expansion. Code and normal macros are skipped.

bmp is able the generate line information. Its syntax is specified using the parameter -l. Line information is used to translate line numbers of the output files to line numbers of the input files. This is required for the backtracing errors in the source code, i.e. in the input files of bmp. Without these line information errors have to be located in the output of bmp.

Line information is evaluated by the compiler/interpreter which means that the compiler has to support this feature and that the syntax must be specified correctly using the -l parameter. The correct setting for most C compilers is -l '#line %2 "%1"'. The resulting line information looks like

#line 123,"source.c"

Meta macros

This section will first give an overview about the meta macros. Detailed descriptions can be found below.

In this section the C mode syntax is used for meta macros.

Overview

Syntax Short description
#define[m] Define symbol m
#define[m][r] Define macro m with replacement r
#define[m][p][r] Define macro m with parameter list p and replacement r
#udefine[m] Revoke last definition of macro or symbol m
#uadefine[m] Revoke all definitions of macros and symbol m
#include[f] Include file f
#ifdef[m] / ifndef[m] Start of conditional expansion if symbol or macro m is defined / not defined
#ifeq[s1][s2] / #ifneq[s1][s2] Start of conditional expansion if strings s1 and s2 are equal / not equal
#else else statement, i.e. invert the condition of the previous if meta macro
#endif End of conditional expansion
#elifdef[m] / #elifndef[m] Similar to #else + #ifdef[s] / ifndef[s] (no additional #end is required)
#elifeq[s1][s2] / #elifndef[s1][s2] Similar to #else + #ifeq[s1][s2] / ifneq[s1][s2] (no additional #end is required)
#noexpand[d] Disable macro expansion until delimiter d is found
#error[s] Generates a user defined preprocessor error with the message s
#warning[s] Generates a user defined preprocessor warning with the message s
#disablaeout / #enableout Suppress / enable the preprocessor output
#ignorecase / #exactcase Switch to ignore/match upper/lowercase mode
#nolf Suppress the previous linefeed
#disablelineinfo Disables line information for the next macro

#define[m]

This defines the symbol m. Unlike macros, symbols are not expanded. They are used in combination with #ifdef / #ifndef.

See #ifdef[m] / #ifndef[m] for a detailed description.

#define[m][r]

This defines the macro m. If m occurs somewhere in the input code, it is replaced by r. Macros and meta macros in r are expanded. If m occurs in r, m is replaced by the previous definition, see the second example below. This allows recursive expansion of macros.

Example 1:

#define[m1][r1]
#define[m2][m1]
#define[m4][#define[m3][r3]]
--
m1
--
m2
--
m3
--
m4
m3
--

is expanded to (bmp -c -l ””):

--
r1
--
r1
--
m3
--
r3
--

Example of a recursive macro:

--
#define[m1][m1+1]
m1
----
#define[m1][m1+2]
m1
--
#define[m1][m1+3]
m1
--

is expanded to (bmp -c -l ””):

--
m1+1
----
m1+1+2
--
m1+1+2+3
--

#define[m][p][r]

This defines the parametrized macro m with the prameterlist p. If m occurs somewhere in the input code, it is replaced by r which usually depends from the parameters. Macros and meta macros in r are expanded as in #define[m][r] .

The syntax of the parameter list is

<d0>[$1<d2>[$2...[$9<d9>[$a<da>...[$z<dz>]...]]...]]

The parts within [ and ] are optional. <d0><d9>,<da><dz> denote delimiters and $0$9,$a$z denote parameters. A delimter can be any string. The maximum amount of parameters is 27.

If a parameterized macro is found, the input between the end of the macro name m and first delimiter <d0> is stored in $0, the input between <d0> and <d1> is stored in $1, and so on. Note that $0 is not specified in the paramter list p. In r the occurrences of $0, $1, … are replaced by their contents, i.e. by the argument of the respective parameter.

Example:

#define[m1(][,$1,$2)][Parameter 1: $0
Parameter 2: $1
Parameter 3: $2]
#define[Example of ][ a long delimiter $1 an even longer delimiter $2.][$0+$1=$2]
--
m1(a,b,c)
--
Example of 1 a long delimiter 2 an even longer delimiter 3.
--

is expanded to (bmp -c -l ””):

--
Parameter 1: a
Parameter 2: b
Parameter 3: c
--
1+2=3
--

Example of a recursive macro:

--
#define[m2][1]
#define[add(][)][#define[m2][m2+$0]]
m2
--
add(2)
m2
--
add(3)
m2
--

is expanded to (bmp -c -l ””):

--
1
--
1+2
--
1+2+3
--

#udefine[m]

This meta macro revokes the last definition of a macro or a symbol m. See also #uadefine[m] which revokes all definitions.

Example:

#define[m1][r1a]
#define[m1][r1b]
#define[m2]
#define[m3][#ifdef[m2]
m2 defined
#else
m2 not defined
#endif]
--
m1
m3
--
#udefine[m1]
#udefine[m2]
m1
m3
--
#udefine[m1]
m1
--

is expanded to (bmp -c -l ””):

--
r1b
m2 defined
--
r1a
m2 not defined
--
m1
--

#uadefine[m]

This meta macro revokes the all definitions of a macro or a symbol m. See also #udefine[m] which revokes only the last definition.

Example:

#define[m1][r1a]
#define[m1][r1b]
#define[m2]
#define[m3][#ifdef[m2]
m2 defined
#else
m2 not defined
#endif]
--
m1
m3
--
#uadefine[m1]
#uadefine[m2]
m1
m3
--

is expanded to (bmp -c -l ””):

--
r1b
m2 defined
--
m1
m2 not defined
--

#include[f]

This meta macro includes the file f. f is searched first in the directory of the current file, and then in the directory given by the -I parameters.

#if statements

The structure of if statements is

#if<condition>
<code1>
#endif

or

#if<condition>
<code1>
#else
<code2>
#endif

If the condition (denoted by <condition>) is true, <code1> is expanded, i.e. the section starting from #if and ending with #endif is replaced by <code1>. In the second version (with #else) <code2> is expanded if the condition is false. Both, macros and meta macros are expanded in <code1> and <code2>.

Valid conditions are

Condition Short description
def[m] / ndef[m] true, if macro m is defined / not defined
eq[s1][s2] / neq[s1][s2] true, if strings s1 and s2 are equal / not equal

Detailed descriptions if the conditions follow below.

#ifdef[m] / #ifndef[m]

Expands (see #if), if symbol or macro m is defined / not defined.

Example:

#define[m1]
#define[m3][r3]
--
#ifdef[m1]
m2
#else
m3
#endif
--
#ifdef[m2]
m1
#else
m3
#endif
--
#ifndef[m2]
m1
#else
m3
#endif
--

is expanded to (bmp -c -l “”):

--
m2
--
r3
--
m1
--

#ifeq[s1][s2] / #ifneq[s1][s2]

Expands (see #if), if strings s1and s2 are equal / not equal. Macros within s1/s2 are expanded. Except of #noexpand[d] , meta macros are not expanded.

Example:

#define[m1][r1]
#define[m2(][,$1)][$0+$1]
#define[m3][m3]
#define[m4(][)][#ifeq[$0][6]
equal 6
#else
not equal 6
#endif]
--
#ifeq[abc][abc]
euqal 1
#endif
----
#ifneq[abc][def]
not euqal 2
#endif
--
#ifeq[m1][r1]
equal 3
#endif
--
#ifeq[b+m2(a,b)][m2(b,a)+b]
equal 4
#endif
--
#ifeq[#noexpand[$]m3$][m3]
equal 5
#endif
--
m4(6)
--
m4(7)
--

is expanded to (bmp -c -l “”):

--
euqal 1
----
not euqal 2
--
equal 3
--
equal 4
--
equal 5
--
equal 6
--
not equal 6
--

#elif statements

#elif<condition> statements are equal to #else#if<condition> statements except that not additional #end is required. The valid conditons (denoted by <condition>) are the same as for #if.

Example:

#ifeq[m1][1]
1
#else
#ifeq[m1][2]
2
#else
Neither 1 nor 2
#endif
#endif

is the same as

#ifeq[m1][1]
1
#elifeq[m1][2]
2
#else
Neither 1 nor 2
#endif

#noexpand[d]

Disables the expansion of macros and meta macro up to the delimiter sequence d.

Example:

#define[m1][r1]
#define[m2(][,$1)][$0+$1]
#define[m3][m3]
--
m1
--
#noexpand[!]m1!
--

is expanded to (bmp -c -l “”):

--
r1
--
m1
--

#error[s]

This meta macro generates a user defined preprocessor error with the message string s. Neither macros nor meta macros within the string s are expanded. bmp exits after the occurrence of #error.

An example can be found in below

#warning[s]

This meta macro generates a user defined preprocessor warning with the message string s. Neither macros nor meta macros within the string s are expanded.

Example:

#define[m1][r1]
#warning[#noexpand[!]m1! (macros and meta macros in the message string are not expanded)]
#error[This is an error message]
#error[This error message will never be printed]

is expanded to (bmp -c -l “” tmp.bmp):

tmp.bmp(2):
  Warning: #noexpand[!]m1! (macros and meta macros in the message string are no expanded)
tmp.bmp(3):
  Error: This is an error message

#disableout / #enableout

These meta macros are be used to skip code. After #disableout and #enablout occurs, bmp switches the output on and off, respectively.

Example:

#define[def][#enableout
]
#define[stu][
#disableout]
#disableout
abcdefghijklmnopqrstuvwxyz

is expanded to (bmp -c -l “”):

ghijklmnopqr

#ignorecase / #exactcase

These meta macros switches ignore upper/lower case mode for macros on and off, respectively.

Example:

#define[m1][r1]
M1
#ignorecase
M1
#exactcase
M1

is expanded to (bmp -c -l “”):

M1
r1
M1

#nolf

This meta macro is used to suppress a previous linefeed. This is mainly intended to pretty up the output.

Example:

#define[m1][
#nolf
r1]
#define[m2][
r2]
#define[m3][r3]
--
m1
--
m2
--
m3
--

is expanded to (bmp -c -l “”):

--
r1
--

r2
--
r3
--

#disablelineinfo

This meta macro disable line information for the next macro. This can be used to suppress macro-defined comments.

Predefined macros

The following symbols are defined by default depending on certain conditions:

Symbol defined if …
UNIX Operating system is a Unix (including Linux)
LINUX Operating system is Linux
WINDOWS Operating system is Windows
 
en/software/compilation/bmp.txt · Last modified: 2015/05/20 17:17 by stefan
 
Recent changes RSS feed Creative Commons License Powered by PHP Debian Driven by DokuWiki
[ZTEX Home] [Imprint] [Privacy policy]