Macros are very much like symbols or compile-time variables in their syntax, the difference is that macros have a value whereas a symbol simply is defined or is not defined. Furthermore, following the definition of a macro, any occurrence of the macro in the pascal source will be replaced with the value of the macro (much like the macro support in the C preprocessor). If macro support is required, the -Sm command line switch must be used to switch it on, or the directive must be inserted:
{$MACRO ON}
otherwise macros will be regarded as a symbol.
Defining a macro in a program is done in the same way as defining a symbol; in a {$define} preprocessor statement1:
{$define ident:=expr}
If the compiler encounters ident in the rest of the source file, it will be replaced immediately by expr. This replacement works recursively, meaning that when the compiler expanded one macro, it will look at the resulting expression again to see if another replacement can be made. This means that care should be taken when using macros, because an infinite loop can occur in this manner (recent compiler versions will warn about this).
Here are two examples which illustrate the use of macros:
{$define sum:=a:=a+b;} ... sum { will be expanded to 'a:=a+b;' Note the absence of the semicolon} ... {$define b:=100} sum { Will be expanded recursively to a:=a+100; } ...
The previous example could go wrong:
{$define sum:=a:=a+b;} ... sum { will be expanded to 'a:=a+b;' Note the absence of the semicolon} ... {$define b=sum} { DON'T do this !!!} sum { Will be infinitely recursively expanded... } ...
As of version 3.3.1, the compiler will warn about recursive macros, but previous versions of the compiler would recursively expand the macros till it runs out of memory .
Remark Macros defined in the interface part of a unit are not available outside that unit! They can just be used as a notational convenience, or in conditional compiles.
By default the compiler predefines three macros, containing the version number, the release number and the patch number. They are listed in table (2.1).
Symbol | Contains |
FPC_FULLVERSION | An integer version number of the compiler. |
FPC_VERSION | The version number of the compiler. |
FPC_RELEASE | The release number of the compiler. |
FPC_PATCH | The patch number of the compiler. |
The FPC_FULLVERSION macro contains a version number which always uses 2 digits for the RELEASE and PATCH version numbers. This means that version 2.3.1 will result in FPC_FULLVERSION=20301. This number makes it easier to determine minimum versions.
Remark Don’t forget that macro support isn’t on by default. It must be turned on with the -Sm command line switch or using the {$MACRO ON} directive.
As of version 3.1.1, for embedded targets (such as AVR), the compiler defines several macros defining the memory layout of the target, they are listed in table (2.2). These macros are integer values and can be used in code and in $IF statements.
Symbol | Contains |
FPC_FLASHBASE | Base address of flash memory. |
FPC_FLASHSIZE | Size of flash memory. |
FPC_RAMBASE | Base address of RAM memory. |
FPC_RAMSIZE | Size of RAM memory. |
FPC_BOOTBASE | Base address of boot memory. |
FPC_BOOTSIZE | Size of boot memory. |
FPC_EEPROMBASE | Base address of EEPROM memory. |
FPC_EEPROMSIZE | Size of EEPROM memory. |
1In compiler versions older than 0.9.8, the assignment operator for a macros wasn’t := but =