Summary:
The preprocessor is used to transform your sources before compilation. It allows you to include other files and to define macros that will be expanded when used in the source. It behaves similar to the C Preprocessor, with some differences.
The preprocessor transforms files as follows:
The preprocessor implements the following features :
There are two kind of macros:
If a preprocessing directive is invalid, the compilers will generate a .err file with the preprocessing error included in the source file at the line position where the problem exists. When using the -M option, preprocessor errors will be printed to stderr, like regular compiler errors.
Preprocessor options can be used with fglcomp and fglform compilers.
-I path
-D identifier
-E
By using the -E option, only the pre-processing phase is done by the compilers. Result is dumped in standard output.
-p [nopp|noln|fglpp]
When using option -p nopp, it disables the preprocessor phase.
By using option -p noln with the -E preprocessing-only option, you can remove line number information and un-necessary empty lines.
By default, the preprocessor expects an ampersand '&' as preprocessor symbol for macros. The option -p fglpp enables the old syntax, using the sharp '#' as preprocessor symbol. Note that the sharp '#' syntax is not compatible with single-line comments.fglcomp -E -D DEBUG -I /usr/sources/headers program.4gl
fglcomp -E -p fglpp -I /usr/sources/headers program.4gl
fglcomp -E -p nopp -I /usr/sources/headers program.4gl
&include "filename"
Source: File A |
|
Source: File B |
|
Result |
|
These preprocessor directives inform the compiler of its current location with special preprocessor comments, so the compiler can provide the right error message when a syntax error occurs.
The preprocessor-generated comments use the following format:
& number "filename"
where:
Recursive inclusions are not allowed. Doing so will fail and output an error message.
The following example is incorrect:
Source: File A |
|
Source: File B |
|
fglcomp -M A.4gl output |
B.4gl:2:1:2:1:error:(-8029) Multiple inclusion of the source file 'A'. |
But including the same file several times is allowed:
Source: File A |
|
Source: File B |
|
Result |
|
&define identifier body
The following example show macro substitution with 2 simple macros:
Source: File A |
|
Result |
|
The macro definition can be continued on multiple lines, but when the macro is expanded, it is joined to a single line as follows:
Source: File A |
|
Result |
|
The source file is processed sequentially, so a macro takes effect at the place it has been written:
Source: File A |
|
Result |
|
The macro body is expanded only when the macro is applied :
Source: File A |
|
Result |
|
In order to prevent infinite recursion, a macro cannot be expanded recursively.
Source: File A |
|
Result |
|
&define identifier( arglist ) body
Source: File A |
|
Result |
|
A function macro can have an empty argument list. In this case, parenthesis are required for the macro to be expanded. As we can see in the next example, line 03 is not expanded because it there is no '()' after foo. The function macro cannot be applied even if it has no arguments.
Source: File A |
|
Result |
|
The comma separates arguments. Macro parameters containing a comma can be used with parenthesis. In the following example Line 02 has been substituted, but line 03 produced an error, because the number of parameters is incorrect.
Source: File A |
|
fglcomp -M output |
source.4gl:3:1:3:1:error:(-8039) Invalid number of parameters for macro one_parameter. |
Macro arguments are completely expanded and substituted before the function macro expansion.
A macro argument can be left empty.
Source: File A |
|
fglcomp -M output |
source.4gl:4:1:4:1:error:(-8039) Invalid number of parameters for macro two_args. source.4gl:5:1:5:1:error:(-8039) Invalid number of parameters for macro two_args. |
Macro arguments appearing inside strings are not expanded.
Source: File A |
|
Result |
|
The stringification transformation allows you to create a string using a macro parameter. When a macro parameter is used with a preceding '#', it is replaced by a string containing the literal text of the argument. The argument is not macro expanded before the substitution.
Source: File A |
|
Result |
|
Line 07 has been split on multiple lines for readability. The preprocessor output is merged on one line.
The operator '##' can be used to merge two tokens while expanding a macro. The two tokens on either side of each '##' are combined to create a single token.
All tokens can not be merged. Usually these tokens are identifiers, or numbers. The concatenation result produces an identifier.
Source: File A |
|
Result |
|
The preprocessor predefines 2 macros:
__LINE__
expands to the current line number. Its definition changes with each new line
of the code.
__FILE__
expands to the name of the current file as a string
constant. Ex : "subdir/file.inc"These macros are often used to generate error messages.
An &include directive changes the values of __FILE__ and __LINE__ to correspond to the included file.
&undef identifier
If a macro is redefined without having been undefined previously, the preprocessor issues a warning and replaces the existing definition with the new one.
Source: File A |
|
Result |
|
Conditional processing is supported with the &ifdef and &ifndef directives.
&ifdef identifier
...
[&else
...]
&endif
&ifndef identifier
...
[&else
...]
&endif
Source: File A |
|
Result |
|