====== 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 [[http://www.ztex.de/firmware-kit/|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 [[http://www.freepascal.org|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 * [[http://www.ztex.de/downloads/#bmp|ZTEX download section]]. 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 [] [ [ ...]] . '''', ''filename2>'', ... denote the input files. If none is given, bmp reads from standard input stdin. The supported options are ^ Option ^ Description ^ | ''-o'' | 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'' | Include path. May be specified several times. bmp searches for (input) files in that directories. | | ''-D'' | Define symbol . May be specified several times. ''-D DEFINE_ME'' is equal to ''//define[DEFINE_ME]]'' in Pascal mode | | ''-mm'' | Meta macro start string | | ''-mo'' | Open bracket | | ''-mc'' | Close bracket | | ''-mp'' | 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[m] ]]'' | Define symbol ''m'' | | ''[[#define_m_r|#define[m][r] ]]'' | Define macro ''m'' with replacement ''r'' | | ''[[#define_m_p_r|#define[m][p][r] ]]'' | Define macro ''m'' with parameter list ''p'' and replacement ''r'' | | ''[[#udefine_m|#udefine[m] ]]'' | Revoke last definition of macro or symbol ''m'' | | ''[[#uadefine_m|#uadefine[m] ]]'' | Revoke all definitions of macros and symbol ''m'' | | ''[[#include_f|#include[f] ]]'' | Include file ''f'' | | ''[[#ifdef_m_ifndef_m]|#ifdef[m] / ifndef[m] ]]'' | Start of conditional expansion if symbol or macro ''m'' is defined / not defined | | ''[[#ifeq_s1_s2_ifneq_s1_s2|#ifeq[s1][s2] / #ifneq[s1][s2] ]]'' | Start of conditional expansion if strings ''s1'' and ''s2'' are equal / not equal | | ''[[#if_statements|#else]]'' | ''else'' statement, i.e. invert the condition of the previous ''if'' meta macro | | ''[[#if_statements|#endif]]'' | End of conditional expansion | | ''[[#elif_statements|#elifdef[m] / #elifndef[m] ]]'' | Similar to ''#else'' + ''#ifdef[s]'' / ''ifndef[s]'' (no additional ''#end'' is required) | | ''[[#elif_statements|#elifeq[s1][s2] / #elifndef[s1][s2] ]]'' | Similar to ''#else'' + ''#ifeq[s1][s2]'' / ''ifneq[s1][s2]'' (no additional ''#end'' is required) | | ''[[#noexpand_d|#noexpand[d] ]]'' | Disable macro expansion until delimiter ''d'' is found | | ''[[#error_s|#error[s] ]]'' | Generates a user defined preprocessor error with the message ''s'' | | ''[[#warning_s|#warning[s] ]]'' | Generates a user defined preprocessor warning with the message ''s'' | | ''[[#disableout_enableout|#disablaeout / #enableout]]'' | Suppress / enable the preprocessor output | | ''[[#ignorecase_exactcase|#ignorecase / #exactcase]]'' | Switch to ignore/match upper/lowercase mode | | ''[[#nolf|#nolf]]'' | Suppress the previous linefeed | | ''[[#disablelineinfo|#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|#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|#define[m][r] ]]''. The syntax of the parameter list is [$1[$2...[$9[$a...[$z]...]]...]] The parts within ''['' and '']'' are optional. ''''...'''',''''...'''' 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 '''' is stored in ''$0'', the input between '''' and '''' 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|#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|#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 #endif or #if #else #endif If the condition (denoted by '''') is true, is expanded, i.e. the section starting from ''#if'' and ending with ''#endif'' is replaced by . In the second version (with ''#else'') is expanded if the condition is false. Both, macros and meta macros are expanded in and . Valid conditions are ^ Condition ^ Short description ^ | ''[[#ifdef_m_ifndef_m|def[m] / ndef[m] ]]'' | true, if macro ''m'' is defined / not defined | | ''[[#ifeq_s1_s2_ifneq_s1_s2|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_statements|#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_statements|#if]]''), if strings ''s1''and ''s2'' are equal / not equal. Macros within ''s1''/''s2'' are expanded. Except of ''[[#noexpand_d|#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'' statements are equal to ''#else#if'' statements except that not additional ''#end'' is required. The valid conditons (denoted by '''') are the same as for ''[[#if_statements|#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 [[#warning_s|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 | {{indexmenu_n>3000}}