Pragmas conditionnels

Présentation

Le langage ST étendu (ExST) prend en charge plusieurs Instructions Pragma conditionnelles qui affectent la génération du code pendant le processus de précompilation ou de compilation.

NOTE : n'ajoutez aucun pragma conditionnel dans la partie déclaration. Ces pragmas sont ignorés.

Le code d'implémentation pris en compte pour la compilation varie en fonction des conditions suivantes :

  • Un type de données ou une variable spécifique a-t-il été déclaré ?

  • Un attribut spécifique est-il associé à un type ou une variable ?

  • Une variable est-elle associée à un type de données spécifique ?

  • Un POU ou une tâche spécifique est-il disponible ou fait-il partie de l'arborescence d'appels, etc.

NOTE : Un POU ou une GVL déclaré(e) dans l'arborescence POU ne peut pas utiliser de {define...} déclaré dans une application. Les définitions des applications n'affectent que les interfaces insérées sous l'application correspondante.

{define identifier string}

Lors du prétraitement, toutes les instances suivantes de l'identificateur sont remplacées par la séquence indiquée de jetons, dans le cas où la chaîne de jeton n'est pas vide (ce qui est autorisé et clairement défini). L'identificateur reste défini et dans le domaine de validité jusqu'à la fin de l'objet ou jusqu'à ce que sa définition soit annulée dans une directive {undefine} . Usage : compilation conditionnelle.

{undefine identifier}

La définition du identifier au sein du préprocesseur (par {define}, voir la première ligne de ce tableau) sera supprimée et l'identificateur ne sera donc plus défini. Si l'identificateur spécifié n'est pas actuellement défini, ce pragma est ignoré.

{IF expr}

...

{ELSIF expr}

...

{ELSE}

...

{END_IF}

Ces pragmas s'appliquent à la compilation conditionnelle. Les expressions exprs spécifiées doivent être constantes lors de la compilation ; elles sont évaluées dans leur ordre d'apparition jusqu'à ce que l'une des expressions renvoie une valeur non nulle. Le texte associé à la directive qui a abouti est alors prétraité et compilé normalement, les autres étant ignorées. L'ordre des sections est déterminé ; toutefois, les sections elsif et else sont facultatives et les sections elsif peuvent apparaître plus souvent de façon arbitraire.

Dans l'expression constante expr, vous pouvez utiliser plusieurs opérateurs de compilation conditionnelle.

<expr>

L'expression constante expr d'un pragma de compilation conditionnelle ({if} ou {elsif}, voir tableau précédent), accepte plusieurs opérateurs. La définition de ces opérateurs ne peut pas être annulée ou revue via (respectivement) {undefine} ou {define}.

Vous pouvez également utiliser ces expressions ainsi que la définition réalisée par {define} dans la zone de texte Définitions compilateur de la boîte de dialogue Propriétés d'un objet (Afficher > Propriétés > Compiler).

defined (identifier)

Avec cet opérateur, l'expression prend la valeur TRUE dès lors que identifier a été défini via une instruction {define} et que cette définition n'a pas été annulée ultérieurement via une instruction {undefine} . Sinon, elle prend la valeur FALSE.

Exemple pour defined (identifier) :

Conditions préalables : Il y a 2 applications App1 et App2. L'identificateur pdef1 est défini dans App2, mais pas dans 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}

Un exemple de pragma de message est également inclus :

Seules les informations pdef1 defined s'affichent dans la vue Messages lors de la compilation de l'application, car pdef1 est défini. Le message pdef1 non défini s'affiche lorsque pdef1 n'est pas défini.

defined (variable:<variable name>)

Lorsque l'opérateur s'applique à une variable, l'expression prend la valeur TRUE si la variable est déclarée au sein du domaine de validité en cours. Sinon, elle prend la valeur FALSE.

Exemple pour defined (variable:<variable name>) :

Conditions préalables : Il y a 2 applications App1 et App2. La variable g_bTest est déclarée dans App2, mais pas dans App1.

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

defined (type:identifier)

Lorsque l'opérateur s'applique à un identificateur de type, l'expression prend la valeur TRUE si un type portant ce nom est déclaré. Sinon, la valeur est FALSE.

Exemple pour defined (type:identifier)  :

Conditions préalables : Il y a 2 applications App1 et App2. Le type de données DUT est défini dans App2, mais pas dans App1.

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

defined (pou:pou-name)

Lors de son application à un nom de POU, la valeur est TRUE si l'un des objets suivants porte le nom <pou-name> :

  • Bloc fonction

  • Fonction

  • Programme

  • Action

  • Méthode

  • Interface

Sinon, la valeur est FALSE.

Pour plus d'informations, reportez-vous au chapitre POU.

Exemple pour defined (pou: pou-name) :

Conditions préalables : Il y a 2 applications App1 et App2. Le POU CheckBounds est disponible dans App2, mais pas dans 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)

L'expression prend la valeur TRUE si une tâche est définie avec le nom <task name>. Sinon, la valeur est FALSE.

Syntaxe :

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

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

Exemple 2 :

Conditions préalables : Il y a 2 applications App1 et App2. La tâche PLC_PRG_Task est définie dans App1, mais pas dans 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)

Lors de l'application à un POU, la valeur est TRUE si le attribute en question est indiqué sur la première ligne de la partie déclarative des POU.

Exemple pour hasattribute (pou: pou-name, attribute) :

Conditions préalables : Il y a 2 applications App1 et App2. La fonction fun1 est définie dans App1 et App2, mais dans App1 elle présente un attribut vision :

Définition de fun1 dans App1 :

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

Définition de fun1 dans App2 :

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

Instruction Pragma

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

hasattribute (variable: variable, attribute)

Lors de l'application à une variable, la valeur est TRUE si l'attribut en question est spécifié via l'instruction {attribute} sur une ligne précédant la déclaration de la variable.

Exemple pour hasattribute (variable: variable, attribute) :

Conditions préalables : Il y a 2 applications App1 et App2. La variable g_globalInt est utilisée dans App1 et App2, mais dans App1 elle présente un attribut DoCount :

Déclaration de g_globalInt dans App1

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

Déclaration de g_globalInt dans App2

VAR_GLOBAL
g_globalInt : INT;
g_multiType : STRING;
END_VAR

Instruction Pragma

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

Lors de l'application à une variable, la valeur est TRUE si la variable en question présente le type-spec spécifié. Sinon, la valeur est FALSE.

Types de données disponibles pour 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

Exemple pour l'opérateur hastype (variable: variable, type-spec) :

Conditions préalables : Il y a 2 applications App1 et App2. La variable g_multitype est déclarée dans App1 avec le type LREAL et dans App2 avec le type 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)

Si define-ident est défini et présente la valeur spécifiée (char-string), la valeur est TRUE. Sinon, la valeur est FALSE.

Exemple pour hasvalue (define-ident, char-string) :

Conditions préalables : La variable test est utilisée dans les applications App1 et App2. Elle prend la valeur 1 dans App1 et la valeur 2 dans 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>')

Le mode de compactage qui est vérifié dépend de la description de l'équipement, et non du pragma qui peut être spécifié pour chaque DUT.

hasvalue (RegisterSize, '<register size>')

<register size> : définit la taille d'un registre CPU (en bits).

Lorsque la taille d'un registre CPU est égale à <register size>, l'expression renvoie la valeur TRUE.

<register size> peut avoir les valeurs suivantes :

  • 16 pour C16x

  • 64 pour X86-64 bits

  • 32 pour X86-32 bits

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

L'opérateur vérifie si la constante définie avec <constant name> a été remplacée. Le deuxième paramètre (valeur booléenne) contrôle ce qui est vérifié :

  • TRUE : vérifie si la constante a été remplacée.

  • FALSE : vérifie si la constante n'a pas été remplacée.

Si le cas concerné est détecté, l'opérateur renvoie TRUE.

Syntaxe :

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

Exemple :

{IF hasconstanttype(PLC_PRG.aConst, TRUE)}

Le remplacement automatique des constantes dépend des éléments suivants :

  • Option de compilation Remplacer les constantes

  • Type de constante (par exemple, les types STRING ne sont pas remplacés)

  • Utilisation de l'attribut {attribute 'const_non_replaced'}

  • Utilisation de l'attribut {attribute 'const_replaced'}

Exemple :

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

L'opérateur compare la valeur de la constante (définie avec <constant name>) à la valeur du deuxième paramètre. Le deuxième paramètre peut être spécifié en tant que littéral (<literal>) ou en tant que variable (<variable name>).

Les opérateurs de comparaison <comparison operator> suivants sont pris en charge :

  • Supérieur à (>)

  • Supérieur ou égal à (>=)

  • Egal à (=)

  • Différent de (<>)

  • Inférieur ou égal à (<=)

  • Inférieur à (<)

Syntaxe :

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

Exemple 1 :

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

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

Exemple 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

L'expression prend la valeur TRUE lorsque la valeur inversée de operator est TRUE. operator peut être l'un des opérateurs décrits dans ce chapitre.

Exemple pour NOT operator :

Conditions préalables : Il y a 2 applications App1 et App2. Le POU PLC_PRG1 est utilisé dans App1 et App2. Le POU CheckBounds n'est disponible que dans 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

L'expression prend la valeur TRUE si les deux opérateurs sont TRUE. operator peut être l'un des opérateurs répertoriés dans ce tableau.

Exemple pour AND operator :

Conditions préalables : Il y a 2 applications App1 et App2. Le POU PLC_PRG1 est utilisé dans les applications App1 et App2. Le POU CheckBounds n'est disponible que dans 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

L'expression est TRUE si l'un des opérateurs est TRUE. operator peut être l'un des opérateurs décrits dans ce chapitre.

Exemple pour OR operator :

Conditions préalables : Le POU PLC_PRG1 est utilisé dans les applications App1 et App2. Le POU CheckBounds n'est disponible que dans 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) met l'opérateur entre parenthèses.