Bedingte Pragmas

Überblick

Die Sprache ExST (Extended ST) unterstützt mehrere bedingte Pragma Anweisungen, die sich auf die Codegenerierung im Vorkompilierungs- oder Kompilierungsprozess auswirken.

HINWEIS: Verwenden Sie keine bedingten Pragmas im Deklarationsteil. Sie werden nicht beachtet.

Ob ein Implementierungscode bei der Kompilierung berücksichtigt wird, kann von den nachstehenden Bedingungen abhängig sein, nämlich ob:

  • ein bestimmter Datentyp oder eine bestimmte Variable deklariert ist

  • ein Datentyp oder eine Variable ein bestimmtes Attribut hat

  • eine Variable einen bestimmten Datentyp hat

  • eine bestimmte POU oder eine Task vorhanden bzw. Teil des Aufrufbaums ist usw.

HINWEIS: Für eine POU oder GVL, die in der POU-Baumstruktur deklariert ist, ist es nicht möglich, ein in einer Anwendung deklariertes {define...} zu verwenden. Definitionen in Anwendungen wirken sich nur auf Schnittstellen unterhalb der entsprechenden Anwendung aus.

{define identifier string}

Während des Vorompilierungsprozesses werden alle nachfolgenden Instanzen des Bezeichners (Kennung) durch die angegebene Zeichenfolge (String) ersetzt, wenn diese nicht leer ist (was erlaubt ist). Der Bezeichner bleibt definiert und im Gültigkeitsbereich bis zum Ende des Objekts oder bis seine Definition in einer {undefine} -Direktive aufgehoben wird. Wird für eine bedingte Kompilierung verwendet.

{undefine identifier}

Die Vorprozessordefinition des identifier (über {define}, siehe erste Zeile in dieser Tabelle) wird entfernt, und der Bezeichner ist daher nicht definiert. Wenn der angegebene Bezeichner derzeit nicht definiert ist, wird dieses pragma ignoriert.

{IF expr}

...

{ELSIF expr}

...

{ELSE}

...

{END_IF}

Dies sind pragmas für die bedingte Kompilierung. Die angegebenen Ausdrücke exprs müssen zur Kompilierungszeit konstant sein. Sie werden in der Reihenfolge ausgewertet, in der sie auftreten, bis einer der Ausdrücke einen Wert ungleich null ergibt. Der mit der Anweisung verknüpfte Text wird vorverarbeitet und dann übersetzt; die anderen Zeilen werden ignoriert. Die Reihenfolge der Sections ist festgelegt. Die Sections elsif und else optional jedoch sind und elsif-Sections können beliebig oft angezeigt werden.

Innerhalb der Konstante expr können Sie mehrere bedingte Kompilierungsoperatoren verwenden.

<expr>

Im Konstantenausdruck expr einer bedingten Kompilierung pragma ({if} oder {elsif}) (siehe vorherige Tabelle) können Sie mehrere Operatoren verwenden. Diese Operatoren dürfen nicht über {undefine} bzw. {define} undefiniert oder neu definiert werden.

Sie können diese Ausdrücke sowie die Definition, vervollständigt mit {define}, auch im Textfeld Compiler definiert: im Dialogfeld Eigenschaften eines Objekts verwenden (Ansicht > Eigenschaften > Generieren).

defined (identifier)

Dieser Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, sobald identifier mit einer {define} -Anweisung definiert und die Definition später nicht durch eine {undefine} -Anweisung aufgehoben wird. Andernfalls wird der Wert FALSE ausgeliefert.

Beispiel für defined (identifier):

Voraussetzung: Es gibt 2 Anwendungen App1 und App2. Bezeichner pdef1 ist definiert in App2, aber nicht in App1.

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

Zusätzlich ist ein Beispiel für eine Meldung pragma enthalten:

Nur Informationen pdef1 defined werden in der Ansicht Meldungen angezeigt, wenn die Anwendung kompiliert wird, da pdef1 definiert ist. Die Meldung pdef1 nicht definiert wird angezeigt, wenn pdef1 nicht definiert ist.

defined (variable:<variable name>)

Bei einer Anwendung auf eine Variable bewirkt dieser Operator, dass der Ausdruck den Wert TRUE erhält, wenn diese Variable im aktuellen Bereich deklariert ist. Andernfalls entspricht der Wert FALSE.

Beispiel für defined (variable:<variable name>):

Voraussetzung: Es gibt 2 Anwendungen App1 und App2. Variable g_bTest ist deklariert in App2, aber nicht in App1.

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

defined (type:identifier)

Bei einer Anwendung auf einen Datentypbezeichner bewirkt dieser Operator, dass der Ausdruck den Wert TRUE erhält, wenn ein Datentyp mit diesem bestimmten Namen deklariert ist. Andernfalls entspricht der Wert FALSE.

Beispiel für defined (type:identifier) :

Voraussetzung: Es gibt 2 Anwendungen App1 und App2. Datentyp DUT ist definiert in App2, aber nicht in App1.

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

defined (pou:pou-name)

Bei einer Anwendung auf einen POU-Namen lautet der Wert TRUE, wenn eines der folgenden Objekte mit dem Namen <pou-name> verfügbar ist:

  • Funktionsbaustein

  • Funktion

  • Programm

  • Aktion

  • Methode

  • Schnittstelle

Ansonsten ist er FALSE.

Weitere Informationen finden Sie im Kapitel POU.

Beispiel für defined (pou: pou-name):

Voraussetzung: Es gibt 2 Anwendungen App1 und App2. POU CheckBounds ist verfügbar in App2, aber nicht in App1.

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

defined (task:task-name)

Der Ausdruck erhält den Wert TRUE, wenn eine Task mit dem Namen <task name> definiert ist. Ansonsten ist er FALSE.

Syntax:

{ IF defined (task: <task name> }
{ ELSIF defined (task: <task name> }

Beispiel 1: {IF defined (task: Task_D)}

Beispiel 2:

Voraussetzung: Es gibt 2 Anwendungen App1 und App2. Die Task PLC_PRG_Task ist definiert in App1, aber nicht 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} 

hasattribute (pou: pou-name, attribute)

Bei einer Anwendung auf eine POU bewirkt dieser Operator, dass der Ausdruck den Wert TRUE erhält, wenn dieses attribute in der ersten Zeile des POU-Deklarationsteils angegeben wird.

Beispiel für hasattribute (pou: pou-name, attribute):

Voraussetzung: Es gibt 2 Anwendungen App1 und App2. Funktion fun1 ist definiert in App1 und App2, aber hat in App1 ein Attribut vision:

Definition von fun1 in App1:

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

Definition von fun1 in App2:

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

Pragma-Anweisung

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

hasattribute (variable: variable, attribute)

Bei einer Anwendung auf eine variable ist der Wert TRUE, wenn dieses Attribut über die {attribute}-Anweisung in einer Zeile vor der Deklaration der Variablen angegeben wird.

Beispiel für hasattribute (variable: variable, attribute):

Voraussetzung: Es gibt 2 Anwendungen App1 und App2. Variable g_globalInt wird verwendet in App1 und App2, aber hat in App1 ein Attribut DoCount:

Deklaration von g_globalInt in App1

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

Deklaration von g_globalInt in App2

VAR_GLOBAL
g_globalInt : INT;
g_multiType : STRING;
END_VAR

Pragma-Anweisung

{IF hasattribute (variable: g_globalInt, 'DoCount')}
(* the following code line will only be processed in App1, because there variable g_globalInt has got the attribute 'DoCount' *)
g_globalInt := g_globalInt + 1;
{END_IF}

hastype (variable:variable, type-spec)

Bei einer Anwendung auf eine variable ist der Wert TRUE, wenn diese Variable den angegebenen type-spec aufweist. Andernfalls entspricht der Wert FALSE.

Verfügbare Datentypen von type-spec

  • BOOL

  • BYTE

  • DATE

  • DATE_AND_TIME

  • DINT

  • DWORD

  • INT

  • LDATE

  • LDATE_AND_TIME (LDT)

  • LINT

  • LREAL

  • LTIME

  • LTIME_OF_DAY (LTOD)

  • LWORD

  • REAL

  • SINT

  • STRING

  • TIME

  • TIME_OF_DAY (TOD)

  • UDINT

  • UINT

  • ULINT

  • USINT

  • WORD

  • WSTRING

Beispiel für Operator hastype (variable: variable, type-spec):

Voraussetzung: Es gibt 2 Anwendungen App1 und App2. Variable g_multitype wird deklariert in App1 mit Typ LREAL und in der Anwendung App2 mit Typ STRING:

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

hasvalue (define-ident, char-string)

Wenn der Definierer (define-ident) definiert ist und den angegebenen Wert (char-string) hat, dann ist der Wert TRUE. Andernfalls entspricht der Wert FALSE.

Beispiel für hasvalue (define-ident, char-string):

Voraussetzung: Variable test wird verwendet in Anwendungen App1 und App2. Es erhält den Wert 1 in App1 und den Wert 2 in App2:

{IF hasvalue(test,'1')}
(* the following code line will be processed in App1, because there variable test has value 1 *)
x := x + 1;
{ELSIF hasvalue(test,'2')}
(* the following code line will be processed in App1, because there variable test has value 2 *)
x := x + 2;
{END_IF}

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

Der geprüfte Packungsmodus hängt von der Gerätebeschreibung ab und nicht von dem Pragma, das für einzelne DUTs angegeben werden kann.

hasvalue (RegisterSize, '<register size>')

<register size>: Definiert die Größe eines CPU-Registers (in Bits).

Wenn die Größe eines CPU-Registers gleich <register size> ist, gibt der Ausdruck den Wert TRUE zurück.

<register size> kann die folgenden Werte haben:

  • 16 für C16x

  • 64 für X86-64 Bit

  • 32 für X86-32 Bit

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

Der Operator prüft, ob die Konstante, die mit <constant name> definiert ist, ersetzt wurde. Der zweite Parameter (boolescher Wert) steuert, was überprüft wird:

  • TRUE: Überprüft, ob die Konstante ersetzt wurde.

  • FALSE: Überprüft, ob die Konstante nicht ersetzt wurde.

Wenn der entsprechende Fall erkannt wird, gibt der Operator TRUE zurück.

Syntax:

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

Beispiel:

{IF hasconstanttype(PLC_PRG.aConst, TRUE)}

Das automatische Ersetzen von Konstanten hängt von folgenden Faktoren ab:

  • Compiler-Option Konstanten ersetzen

  • Konstantentyp (STRING-Typen z. B. werden nicht ersetzt)

  • Verwendung des Attributs {attribute 'const_non_replaced'}

  • Verwendung des Attributs {attribute 'const_replaced'}

Beispiel:

VAR
    iCntMAXIsReplaced: INT;
    xErrorOccured : BOOL;
END_VAR
VAR CONSTANT
    c_iMAX: INT := 99;
END_VAR

{IF hasconstanttype(c_iMAX, TRUE)}
    iCntMAXIsReplaced := iCntMAXIsReplaced + 1;  // E.g. this code will be executed in case Project Settings – Compile options – Replace constants was activated
{ELSE}
    xErrorOccured := FALSE;;                    // E.g. this code will be executed in case Project Settings – Compile options – Replace constants was deactivated
{END_IF}

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

Der Operator vergleicht den Wert der Konstante, der mit <constant name> definiert ist, mit dem Wert des zweiten Parameters. Der zweite Parameter kann als Literal <literal> oder als Variable <variable name> angegeben werden.

Die folgenden Vergleichsoperatoren <comparison operator> werden unterstützt:

  • Größer als (>)

  • Größer oder gleich (>=)

  • Gleich (=)

  • Ungleich (<>)

  • Kleiner oder gleich (<=)

  • Kleiner als (<)

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> )

Beispiel 1:

{IF hasconstantvalue(PLC_PRG.aConst, 99, >)}

{ELSIF hasconstantvalue(PLC_PRG.aConst, GVL.intconst99, =)}

Beispiel 2:

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}

NOT operator

Der Ausdruck erhält den Wert TRUE, wenn der invertierte Wert von operator TRUE ist. operator kann einer der in diesem Kapitel beschriebenen Operatoren sein.

Beispiel für NOT operator:

Voraussetzung: Es gibt 2 Anwendungen App1 und App2. POU PLC_PRG1 wird verwendet in App1 und App2. POU CheckBounds ist nur verfügbar in App1:

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

AND operator

Der Ausdruck erhält den Wert TRUE, wenn beide Operatoren TRUE sind. operator kann einer der in dieser Tabelle aufgeführten Operatoren sein.

Beispiel für AND operator:

Voraussetzung: Es gibt 2 Anwendungen App1 und App2. POU PLC_PRG1 wird verwendet in Anwendungen App1 und App2. POU CheckBounds ist nur verfügbar in App1:

{IF defined (pou: PLC_PRG1) AND (defined (pou: CheckBounds))}
(* the following code line will be processed only in applications App1, because only there "PLC_PRG1" and "CheckBounds" are defined *)
bORTest := TRUE;
{END_IF}

OR operator

Der Ausdruck ist TRUE, wenn einer der Operatoren TRUE ist. operator kann einer der in diesem Kapitel beschriebenen Operatoren sein.

Beispiel für OR operator:

Voraussetzung: POU PLC_PRG1 wird verwendet in Anwendungen App1 und App2. POU CheckBounds ist nur verfügbar in App1:

{IF defined (pou: PLC_PRG1) OR (defined (pou: CheckBounds))}
(* the following code line will be processed in applications App1 and App2, because both contain at least one of the POUs "PLC_PRG1" and "CheckBounds" *)
bORTest := TRUE;
{END_IF}

(operator)

(operator) klammert die Operatoren.