Skip to main content

Conditional Pragmas

Restriction in the case of conditional pragmas

Use pragmas for conditional compiling only in implementations of POUs. In declarations, these pragmas are ignored, not evaluated.

Note the following exception: The IF pragma with the project_defined operator can be inserted into declarations. For more information, see the following: IF pragma with project_defined (<global define>)

The pragmas are evaluated by the compiler during the pre-compile operation and during the compile operation. This operation is called conditional compile. The ST implementation language supports these pragmas.

The {IF<expression> } pragmas together with {ELSIF<expression> }, {ELSE}, and the concluding {END_IF} indicate code in implementations which is retained or ignored depending on the specified conditions. The conditions specified in <expression> are integer constant expressions which can be composed of different operands and operators.

When compiling, the first expression in the <{IF <expression>} is evaluated. If its return value is FALSE, then branching will occur in the next {ELSIF <expression>} segment and the expression evaluated there until a segment returns an expression with TRUE. The expressions are thus evaluated successively until one returns a value other than 0. Only this one code segment associated with a positive expression will be compiled. The others are ignored. If all expressions return 0, then branching occurs after {ELSE}. If the {ELSE} pragma is missing, then it may happen that no code segment is compiled.

Syntax

Example of Code Fragment

Description

{IF <expression> }

{IF defined (DEF0815)}
{info 'DEF0815 has been defined'}
Cnt0815 := iCnt0815 + 1;

Labels the beginning of the code segment which is compiled in the case of a valid <expression> condition.

{ELSIF <expression> }

{ELSIF defined (DEF0816)}
{info 'DEF0815 has been defined'}
iCnt0816 := iCnt0816 + 1;

None, one, or multiple)

Branch which labels the alternative code segment if a valid <expression> condition

{ELSE}

{ELSE}
{info 'DEF0815 not defined'}
iCnt0 := iCnt0 - 1;

Optional

Branch which labels the code segment which is compiled if the previous conditions have not been met

{END_IF}

{END_IF}

Labels the end of the conditional code segment

<expression>

defined (DEF0815)

Condition

Integer expression which is constant at compile time and can be composed of operators and operands, such as compiler defines, variables, or literals

Compiler define

Compiler defines are used as labels for specific states in the code. A compiler define can be set, deleted, or checked by using the defined operators.

Syntax

Example

Description

{define <name> }

{define DEF0815}

Defines the compiler define <name> with type BOOL

Note

The compiler define <name> is subject to the rules for valid identifiers.

{define <name> <string> }

{define DEF0123 '123'}

Defines the compiler define <name> and assigns the string literal <string> as a value

{undefine <name>}

{undefine DEF0815}

Removes the compiler define <name>

As a result, the identifier is undefined. A pragma with an undefined compiler define is ignored.

Tip

Alternatively, you could also define expressions and compiler defines locally in the properties of a POU, or application-wide in the properties of the superordinate application.

To do this, select the POU or the superordinate application in the device tree. In the context menu, click Properties and then select the Build tab. In the Compiler-Defines input field, you can define a literal or an expression (example: DEF0815). The input field does not expect a pragma statement like {define }, but simply a name.

You can specify multiple compiler defines separated by commas.

Operators

defined (variable: <variable name> )

The operator causes the expression to be given the value TRUE when the variable <variable name> is declared within the current scope. Otherwise FALSE is returned.

Example 293. Example

Requirement: The two applications App1 and App2 exist. The variable g_bTest is declared in App1, but not in App2.

{IF defined (variable: g_bTest)}
    (* the following code is only processed in App2*)
    g_bTest := x > 300;
{END_IF}


defined (<identifier>)

The operator causes the expression to be given the value TRUE. The requirement is that the identifier <identifier> has been defined by means of a {define} statement and not undefined afterwards with an {undefine} statement. Otherwise FALSE is returned.

Requirement: The applications App1 and App2 exist. The pdef1 variable is defined by a {define} statement in App1, but not in App2.

{IF defined (pdef1)}
(* This code is processed in App1 *)
{info 'pdef1 defined'}
    hugo := hugo + SINT#1;
{ELSE}
(* the following code is only processed in App2 *)
{info 'pdef1 not defined'}
    hugo := hugo - SINT#1;
{END_IF}

This also includes an example of a message pragma: Only the message pdef1 defined is displayed in the message view when the application is compiled because pdef1 is actually defined. The message pdef1 not defined is displayed when pdef1 is not defined.

defined (type: <identifier> )

The operator causes the expression to be given the value TRUE when a data type is declared with the identifier <identifier>. Otherwise FALSE is returned.

Example 294. Example

Requirement: The two applications App1 and App2 exist. The data type DUT is declared in App1, but not in App2.

{IF defined (type: DUT)}
    (* the following code is only processed in App1*)
    bDutDefined := TRUE;
{END_IF}


defined (pou: <pou name>)

The operator causes the expression to be given the value TRUE when one of the following objects with name <pou-name> exists:

  • Function block

  • Function

  • Program

  • Action

  • Method

  • Interface

Otherwise FALSE is returned.

Example 295. Example

Requirement: The two applications App1 and App2 exist. The POU CheckBounds exists in App1, but not in App2.

{IF defined (pou: CheckBounds)}
    (* the following code is only processed in App1 *)
    arrTest[CheckBounds(0,i,10)] := arrTest[CheckBounds(0,i,10)] + 1;
{ELSE}
    (* the following code is only processed in App2 *)
    arrTest[i] := arrTest[i]+1;
{END_IF}


defined (resource: <identifier>)

Important

Not implemented yet

The operator causes the expression to be given the value TRUE if a resource object named <identifier> exists for the application; otherwise FALSE is returned.

Requirement: The two applications App1 and App2 exist. A resource object glob_var1 of the global variable list exists for App1, but not for App2.

{IF defined (resource:glob_var1)}
    (* the following code is only processed in App1 *)
    gvar_x := gvar_x + ivar;
{ELSE}
    (* the following code is only processed in App2 *)
    x := x + ivar;
{END_IF}

defined (task: <task name> )

The operator causes the expression to be given the value TRUE when a task is defined with the name <task name>. Otherwise FALSE is returned.

Syntax

{ IF defined (task: <task name> }
{ ELSIF defined (task: <task name> }
Example 296. Example
{IF defined (task: Task_D)}


Example 297. Example

Requirement: The two applications App1 and App2 exist. The task PLC_PRG_Task is defined in App1, but not in App2.

{IF defined (task: PLC_PRG_Task)}
    (* the following code is only processed in App1 *)
    erg := plc_prg.x;
{ELSE}
    (* the following code is only processed in App2 *)
    erg := prog.x;
{END_IF}


defined (IsLittleEndian)

The operator causes the expression to be given the value FALSE when the CPU memory is organized in Big Endian (Motorola byte order).

defined (IsSimulationMode)

The operator causes the expression to be given the value TRUE when the application runs on a simulated device (in simulation mode).

For more information, see: Testing in Simulation Mode

defined (IsFPUSupported)

If the expression returns the value TRUE, then the code generator produces an FPU code (for the floating-point unit processor) when calculating with REAL values. Otherwise the FPU operations are emulated, which is much slower.

hasattribute (pou: <pou name>, ' <attribute name> ')

The operator causes the expression to be given the value TRUE when the attribute <attribute> is specified in the first line of the declaration part of the function block <pou name>. Otherwise FALSE is returned.

Example 298. Example

Requirement: The two applications App1 and App2 exist. The function fun1 is declared in App1 and App2. However, in App1 it is also provided with the pragma {attribute 'vision'}.

In App1:

{attribute 'vision'}
FUNCTION fun1 : INT
VAR_INPUT
    i : INT;
END_VAR
VAR
END_VAR

In App2:

FUNCTION fun1 : INT
VAR_INPUT
    i : INT;
END_VAR
VAR
END_VAR

Pragma statement:

{IF hasattribute (pou: fun1, 'vision')}
    (* the following code is only processed in App1 *)
    ergvar := fun1(ivar);
{END_IF}


hasattribute (variable: <variable name> , ' <attribute name> ')

The operator causes the expression to be given the value TRUE when the pragma {attribute '<attribute>'} is assigned to the variable in the line before the variable declaration. Otherwise FALSE is returned.

Example 299. example

Requirement: The two applications App1 and App2 exist. The variable g_globalInt is used in App1 and App2, but in App1 the attribute 'DoCount' is also assigned to it.

Declaration of g_GlobalInt in App1

VAR_GLOBAL
    {attribute 'DoCount'}
    g_globalInt : INT;
    g_multiType : STRING;
END_VAR

Declaration g_GlobalInt in App2:

VAR_GLOBAL
    g_globalInt : INT;
    g_multiType : STRING;
END_VAR

Pragma statement:

{IF hasattribute (variable: g_globalInt, 'DoCount')}
    (* the following code is only processed in App1 *)
    g_globalInt := g_globalInt + 1;
{END_IF}


hasconstanttype( <constant name> , <boolean literal> )

The operator checks whether or not the constant, which is identified with <constant name>, has been replaced. The second parameter (Boolean value) controls what is checked:

  • TRUE: Checks if the constant has been replaced

  • FALSE: Checks if the constant has not been replaced

When the respective case occurs, the operator returns TRUE.

Syntax

{ IF hasconstanttype( <constant namne> , <boolean literal> ) }

{ ELSIF hasconstanttype( <constant namne> , <boolean literal> ) }

Example 300. Example
 {IF hasconstanttype(PLC_PRG.aConst, TRUE)}


. The automatic replacement of constants in principle depends on the following:
  • Compile option Replace constants

  • Constant type (For example, STRING types are never replaced.)

  • Usage of the attribute {attribute 'const_non_replaced'}

  • Usage of the attribute {attribute 'const_replaced'}

Example 301. example
VAR
    iCntMAXIsReplaced: INT;
    xErrorOccured : BOOL;
END_VAR
VAR CONSTANT
    c_iMAX: INT := 99;
END_VAR

{IF hasconstanttype(c_iMAX, TRUE)}
    iCntMAXIsReplaced := iCntMAXIsReplaced + 1;
{ELSE}
    xErrorOccured := FALSE;
{END_IF}


hasconstantvalue( <constant name> , <variable name> , <comparison operator> )

The operator compares the value of the constant, which is identified with <constant name>, with the value of the second parameter. The second parameter can be specified either as a literal <literal> or as a variable <variable name>.

. Comparison operators <comparison operator>:
  • Greater than (>)

  • Greater than or equal to (>=)

  • Equal to (=)

  • Not equal to (<>)

  • Less than or equal to (<=)

  • Less than (<)

Syntax

{ IF hasconstantvalue( <constant name> , <variable name> , <comparison operator> )

{ IF hasconstantvalue( <constant name> , <literal> , <comparison operator> )

{ ELSIF hasconstantvalue( <constant name> , <variable name> , <comparison operator> )

{ ELSIF hasconstantvalue( <constant name> , <literal> , <comparison operator> )

Example 302. Example
{IF hasconstantvalue(PLC_PRG.aConst, 99, >)}
{ELSIF hasconstantvalue(PLC_PRG.aConst, GVL.intconst99, =)}


Example 303. Example
PROGRAM PRG_ConditionConstantValue
VAR
    iCntMAX: INT;
    iCntGlobalMAX : INT;
    iCntABC: INT;
    iCntGlobalABC : INT;
    xErrorOccured : BOOL;
END_VAR
VAR CONSTANT
    c_iMAX: INT := 999;
    c_sABC: STRING := 'ABC';
    {attribute 'const_non_replaced'}
    c_iNonReplaceable: INT := 888;
END_VAR

{IF hasconstantvalue(c_iMAX, 999, =)}
    iCntMAX := iCntMAX + 1;
{ELSE}
    xErrorOccured := FALSE;
{END_IF}

{IF hasconstantvalue(c_iMAX, GVL.gc_iMAX, =)}
    iCntGlobalMAX := iCntGlobalMAX + 1;
{ELSE}
    xErrorOccured := FALSE;
{END_IF}

{IF hasconstantvalue(c_sABC, 'ABC', =)}
    iCntABC := iCntMAX + 1;
{ELSE}
    xErrorOccured := FALSE;
{END_IF}
{IF hasconstantvalue(c_sABC, GVL.gc_sABC, =)}
    iCntGlobalABC := iCntMAX + 1;
{ELSE}
    xErrorOccured := FALSE;
{END_IF}


hastype (variable: <variable name>, <data type> )

The operator causes the expression to be given the value TRUE when the variable <variable> is of the data type <type-spec>. Otherwise FALSE is returned.

Possible data types:

BOOL | BYTE | DATE | DATE_AND_TIME | DT | DINT | DWORD | INT | LDATE | LDATE_AND_TIME | LDT | LINT | LREAL | LTIME | LTIME_OF_DAY | LTOD | LWORD | REAL | SINT | STRING | TIME | TIME_OF_DAY | TOD | ULINT | UDINT | UINT | USINT | WORD | WSTRING

Example 304. Example

Requirement: The two applications App1 and App2 exist. The variable g_multitype is declared in App1 with data type LREAL, in App2 with data type STRING.

{IF (hastype (variable: g_multitype, LREAL))}
    (*  the following code is only processed in App1 *)
    g_multitype := (0.9 + g_multitype) * 1.1;
{ELSIF (hastype (variable: g_multitype, STRING))}
    (* the following code is only processed in App2 *)
    g_multitype := 'this is a multitalent';
{END_IF}


hasvalue (PackMode, ' <pack mode value> ')

The checked pack mode depends on the device description, not on the pragma that can be specified for individual DUTs.

hasvalue (RegisterSize, ' <register size> ')

<register size>: Size of a CPU register (in bits)

The operator causes the expression to return the value TRUE when the size of a CPU register is equal to <register size>.

Possible values for <register size>

  • 16 for C16x,

  • 64 for X86-64 bit

  • 32 for X86-32 bit

hasvalue (<define-ident>, ' <character string> ')

The operator causes the expression to be given the value TRUE when a variable is defined with the identifier <define-ident> and has the value <char-string>. Otherwise FALSE is returned.

Example 305. Example

Requirement: The two applications App1 and App2 exist. The variable test is used in the applications App1 and App2. In App1, it is given the value 1. In App2, it is given the value 2.

{IF hasvalue(test,'1')}
    (*  the following code is only processed in App1 *)
    x := x + 1;
{ELSIF hasvalue(test,'2')}
    (*  the following code is only processed in App2 *)
        x := x + 2;
{END_IF}


project_defined (<global define>)

This operator is available as of CODESYS V3.5 SP20.

The operator causes the expression to receive the value TRUE if the global define <global define> is included in the list of global defines in the Compile options of the project settings.

The operator is specified as a condition of an IF statement and can be used both in the implementation part and in the declaration part of ST POUs and libraries. They can be combined with other defines by means of the AND and OR operators if these are allowed at the respective position.

In the declaration part of POUs, IF statements with the operator project_defined (<global define>) can contain the following constructs:

  • Variable Declarations

    Example:

    {If project_defined(define1)}
        x : DINT;
    {END_IF}
  • Comments

  • Attribute declarations

  • Pragma statements

The following constructs are not possible:

  • Full variable declarations

    Example

    {If project_defined(define1)}
    VAR
        x : DINT;
    END_VAR
    {END_IF}
  • Full declarations from POUs

    Example:

    {If project_defined(define1)}
    FUNCTION POU : BOOL
    VAR_INPUT
        x : INT;
    END_VAR
    {END_IF}
  • Scopes: VAR_INPUT, VAR_OUTPUT, VAR_IN_OUT

NOT <operator>

The expression is given the value TRUE when the reverse value of <operator> returns the value TRUE. <operator> can be one of the operators described in this chapter.

Example 306. example

Requirement: The two applications App1 and App2 exist. PLC_PRG1 exists in App1 and App2, and the POU CheckBounds exists only in App1.

{IF defined (pou: PLC_PRG1) AND NOT (defined (pou: CheckBounds))}
    (* the following code is only processed in App2 *)
    bANDNotTest := TRUE;
{END_IF}


<operator> AND <operator>

The expression is given the value TRUE when the two specified operators return TRUE. <operator> can be one of the operators described in this chapter.

Example 307. Example

Requirement: The applications App1 and App2 exist. PLC_PRG1 exists in App1 and App2, and the POU CheckBounds exists only in App1.

{IF defined (pou: PLC_PRG1) AND (defined (pou: CheckBounds))}
    (* the following code is only processed in App1 *)
    bANDTest := TRUE;
{END_IF}


<operator> OR <operator>

The expression returns TRUE when one of the two specified operators returns TRUE. <operator> can be one of the operators described here.

Example 308. example

Requirement: The two applications App1 and App2 exist. The POU PLC_PRG1 exists in App1 and App2, and the POU CheckBounds exists only in App1.

{IF defined (pou: PLC_PRG1) OR (defined (pou: CheckBounds))}
    (* the following code is only processed in App1 and in App2 *)
    bORTest := TRUE;
{END_IF}


(<operator>)

() brackets the operators.