Subsections

- 1 Conditionals
  - 1 Predefined symbols
- 2 Messages
- 3 Macros

#
2 Using conditionals, messages and macros

The Free Pascal compiler supports conditionals as in normal Turbo Pascal. It does, however, more than that. It allows you to make macros which can be used in your code, and it allows you to define messages or errors which will be displayed when compiling.

#
1 Conditionals

The rules for using conditional symbols are the same as under Turbo Pascal. Defining a symbol goes as follows:

    {$define Symbol}

From this point on in your code, the compiler knows the symbol `Symbol`. Symbols are, like the Pascal language, case insensitive.

You can also define a symbol on the command line. the `-dSymbol` option defines the symbol `Symbol`. You can specify as many symbols on the command line as you want.

Undefining an existing symbol is done in a similar way:

    {$undef Symbol}

If the symbol didn't exist yet, this doesn't do anything. If the symbol existed previously, the symbol will be erased, and will not be recognized any more in the code following the `{$undef \dots}` statement.

You can also undefine symbols from the command line with the `-u` command-line switch.

To compile code conditionally, depending on whether a symbol is defined or not, you can enclose the code in a `{$ifdef Symbol}` ...`{$endif}` pair. For instance the following code will never be compiled:

    {$undef MySymbol}
    {$ifdef Mysymbol}
      DoSomething;
      ...
    {$endif}

Similarly, you can enclose your code in a `{$ifndef Symbol}` ...`{$endif}` pair. Then the code between the pair will only be compiled when the used symbol doesn't exist. For example, in the following example, the call to the `DoSomething` will always be compiled:

    {$undef MySymbol}
    {$ifndef Mysymbol}
      DoSomething;
      ...
    {$endif}

You can combine the two alternatives in one structure, namely as follows

    {$ifdef Mysymbol}
      DoSomething;
    {$else}
      DoSomethingElse
    {$endif}

In this example, if `MySymbol` exists, then the call to `DoSomething` will be compiled. If it doesn't exist, the call to `DoSomethingElse` is compiled.

Except for the Turbo Pascal constructs the Free Pascal compiler also supports a stronger conditional compile mechanism: The `{$if}` construct.

The prototype of this construct is as follows:

    {$if expr}
      CompileTheseLines;
    {$else}
      BetterCompileTheseLines;
    {$endif}

In this directive `expr` is a Pascal expression which is evaluated using strings, unless both parts of a comparision can be evaluated as numbers, in which case they are evaluated using numbers. If the complete expression evaluates to `'0'`, then it is considered false and rejected. Otherwise it is considered true and accepted. This may have unexpected consequences:

    {$if 0}

will evaluate to `False` and be rejected, while

    {$if 00}

will evaluate to `True`.

You can use any Pascal operator to construct your expression: `=, <>, >, <, >=, <=, AND, NOT, OR` and you can use round brackets to change the precedence of the operators.

The following example shows you many of the possibilities:

    {$ifdef fpc}

    var
       y : longint;
    {$else fpc}

    var
       z : longint;
    {$endif fpc}

    var
       x : longint;

    begin

    {$if (fpc_version=0) and (fpc_release>6) and (fpc_patch>4)}
    {$info At least this is version 0.9.5}
    {$else}
    {$fatal Problem with version check}
    {$endif}

    {$define x:=1234}
    {$if x=1234}
    {$info x=1234}
    {$else}
    {$fatal x should be 1234}
    {$endif}

    {$if 12asdf and 12asdf}
    {$info $if 12asdf and 12asdf is ok}
    {$else}
    {$fatal $if 12asdf and 12asdf rejected}
    {$endif}

    {$if 0 or 1}
    {$info $if 0 or 1 is ok}
    {$else}
    {$fatal $if 0 or 1 rejected}
    {$endif}

    {$if 0}
    {$fatal $if 0 accepted}
    {$else}
    {$info $if 0 is ok}
    {$endif}

    {$if 12=12}
    {$info $if 12=12 is ok}
    {$else}
    {$fatal $if 12=12 rejected}
    {$endif}

    {$if 12<>312}
    {$info $if 12<>312 is ok}
    {$else}
    {$fatal $if 12<>312 rejected}
    {$endif}

    {$if 12<=312}
    {$info $if 12<=312 is ok}
    {$else}
    {$fatal $if 12<=312 rejected}
    {$endif}

    {$if 12<312}
    {$info $if 12<312 is ok}
    {$else}
    {$fatal $if 12<312 rejected}
    {$endif}

    {$if a12=a12}
    {$info $if a12=a12 is ok}
    {$else}
    {$fatal $if a12=a12 rejected}
    {$endif}

    {$if a12<=z312}
    {$info $if a12<=z312 is ok}
    {$else}
    {$fatal $if a12<=z312 rejected}
    {$endif}

    {$if a12<z312}
    {$info $if a12<z312 is ok}
    {$else}
    {$fatal $if a12<z312 rejected}
    {$endif}

    {$if not(0)}
    {$info $if not(0) is OK}
    {$else}
    {$fatal $if not(0) rejected}
    {$endif}

    {$info *************************************************}
    {$info * Now have to follow at least 2 error messages: *}
    {$info *************************************************}

    {$if not(0}
    {$endif}

    {$if not(<}
    {$endif}

    end.

As you can see from the example, this construct isn't useful when used with normal symbols, only if you use macros, which are explained in section Macros. They can be very useful. When trying this example, you must switch on macro support, with the `-Sm` command-line switch.

## 1 Predefined symbols

The Free Pascal compiler defines some symbols before starting to compile your program or unit. You can use these symbols to differentiate between different versions of the compiler, and between different compilers. To get all the possible defines when starting compilation, see appendix

Remark: Symbols, even when they're defined in the interface part of a unit, are not available outside that unit.

#
2 Messages

Free Pascal lets you define normal, warning and error messages in your code. Messages can be used to display useful information, such as copyright notices, a list of symbols that your code reacts on etc.

Warnings can be used if you think some part of your code is still buggy, or if you think that a certain combination of symbols isn't useful.

Error messages can be useful if you need a certain symbol to be defined, to warn that a certain variable isn't defined, or when the compiler version isn't suitable for your code.

The compiler treats these messages as if they were generated by the compiler. This means that if you haven't turned on warning messages, the warning will not be displayed. Errors are always displayed, and the compiler stops if 50 errors have occurred. After a fatal error, the compiler stops at once.

For messages, the syntax is as follows:

    {$Message Message text}

or

    {$Info Message text}

For notes:

    {$Note Message text}

For warnings:

    {$Warning Warning Message text}

For errors:

    {$Error  Error Message text}

Lastly, for fatal errors:

    {$Fatal  Error Message text}

or

    {$Stop  Error Message text}

The difference between `$Error` and `$FatalError` or `$Stop` messages is that when the compiler encounters an error, it still continues to compile. With a fatal error, the compiler stops.

Remark: You cannot use the '`}`' character in your message, since this will be treated as the closing brace of the message.

As an example, the following piece of code will generate an error when the symbol `RequiredVar` isn't defined:

    {$ifndef RequiredVar}
    {$Error Requiredvar isn't defined !}
    {$endif}

But the compiler will continue to compile. It will not, however, generate a unit file or a program (since an error occurred).

#
3 Macros

Macros are very much like symbols in their syntax, the difference is that macros have a value whereas a symbol simply is defined or is not defined. If you want macro support, you need to specify the `-Sm` command-line switch, otherwise your macro will be regarded as a symbol.

Defining a macro in your program is done in the same way as defining a symbol; in a `{$define}` preprocessor statement:

    {$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 recursive, meaning that when the compiler expanded one of your macros, it will look at the resulting expression again to see if another replacement can be made. You need to be careful with this, because an infinite loop can occur in this manner.

Here are two examples which illustrate the use of macros:

    {$define sum:=a:=a+b;}
    ...
    sum          { will be expanded to 'a:=a+b;'
                   remark 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;'
                   remark the absence of the semicolon}
    ...
    {$define b=sum} { DON'T do this !!!}
    sum          { Will be infinitely recursively expanded \dots }
    ...

On my system, the last example results in a heap error, causing the compiler to exit with a run-time error 203.

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 (DefMacros) .

Table: Predefined macros
Symbol | Contains
`FPC_VERSION` | The version number of the compiler.
`FPC_RELEASE` | The release number of the compiler.
`FPC_PATCH` | The patch number of the compiler.

Remark: Don't forget that macros support isn't on by default. You need to compile with the `-Sm` command-line switch.