Pragmas condicionales

Descripción general

El lenguaje ExST (ST ampliado) admite diversas instrucciones Pragma condicionales que afectan a la generación de código en el proceso de precompilación o compilación.

NOTA: No utilice pragmas condicionales en la parte de declaración. No se tendrán en cuenta.

El código de implementación que se utiliza para la compilación puede depender de las condiciones siguientes:

  • ¿Se trata de determinado tipo de datos o variables declarado?

  • ¿Un tipo o una variable tienen un atributo determinado?

  • ¿Tiene una variable un tipo de datos determinado?

  • ¿Es una POU determinada, una tarea disponible o forma parte de un árbol de llamadas, etc.?

NOTA: Una POU o GVL declaradas en el árbol POU no pueden utilizar un {define...} declarado en una aplicación. Las definiciones en las aplicaciones solo afectarán a interfaces insertadas bajo la aplicación correspondiente.

{define identifier string}

Durante el procesamiento previo, todas las instancias del identificador que se ejecuten a partir de ese momento se sustituirán por la secuencia de tokens en cuestión si la cadena del token no está vacía (está permitida y bien definida). El identificador permanece definido y dentro del ámbito hasta el final del objeto o hasta que esté sin definir en una directiva {undefine} . Se emplea para compilaciones condicionales.

{undefine identifier}

Se eliminará la definición del preprocesador del identifier (por parte de {define}, consulte la primera fila de esta tabla) y, por tanto, el identificador estará sin definir. Si el identificador especificado no está definido actualmente, se ignorará este pragma.

{IF expr}

...

{ELSIF expr}

...

{ELSE}

...

{END_IF}

Estos pragmas se utilizan para compilaciones condicionales. Las expresiones especificadas exprs tienen que ser constantes en el tiempo de compilación; se evalúan en el orden en el que aparecen hasta que una de las expresiones se evalúa como un valor diferente de cero. El texto asociado con la directiva correcta se preprocesa y compila con normalidad y el resto se ignora. Se determina el orden de las secciones; no obstante, las secciones elsif y else son opcionales, y las secciones elsif pueden aparecer de forma arbitraria más a menudo.

Dentro de la constante expr, se pueden utilizar diversos operadores de compilación condicionales.

<expr>

Dentro de la expresión de la constante expr de un pragma de compilación condicional ({if} o {elsif}) (consulte la tabla anterior), se pueden utilizar diversos operadores. Es posible que no se puedan no definir ni redefinir estos operadores mediante {undefine} o {define}, respectivamente.

También puede utilizar estas expresiones, así como la definición completada por {define} en el campo de texto Definiciones de compilador: del cuadro de diálogo Propiedades de un objeto (Ver > Propiedades > Compilación).

defined (identifier)

Este operador hace que la expresión adopte el valor TRUE, en cuanto se haya definido el identifier con una instrucción {define} y no haya sido no definido posteriormente por una instrucción {undefine} . En caso contrario, su valor será FALSE.

Ejemplo de defined (identifier):

Requisito: hay 2 aplicaciones App1 y App2. El identificador pdef1 está definido en la App2, pero no en la 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}

Además, se incluye un ejemplo de un pragma de mensaje:

Solo se muestra la información de pdef1 defined en la vista Mensajes al compilar la aplicación porque pdef1 está definido. El mensaje pdef1 no definido se mostrará cuando pdef1 no esté definido.

defined (variable:<variable name>)

Cuando se aplica a una variable, su valor es TRUE si esta variable en particular está declarada dentro del ámbito actual. De lo contrario, es FALSE.

Ejemplo de defined (variable:<variable name>):

Requisito: hay 2 aplicaciones App1 y App2. La variable g_bTest está declarada en la App2, pero no en la App1.

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

defined (type:identifier)

Cuando se aplica a un identificador de tipo, su valor es TRUE si existe un tipo declarado con ese nombre en particular. De lo contrario, es FALSE.

Ejemplo de defined (type:identifier) :

Requisito: hay 2 aplicaciones App1 y App2. El tipo de datos DUT está definido en la App2, pero no en la App1.

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

defined (pou:pou-name)

Cuando se aplica a un nombre de POU, su valor es TRUE si está disponible uno de los siguientes objetos con el nombre <pou-name>:

  • Bloque de funciones

  • Función

  • Programa

  • Acción

  • Método

  • Interfaz

De lo contrario, es FALSE.

Para obtener más información, consulte el capítulo POU.

Ejemplo de defined (pou: pou-name):

Requisito: hay 2 aplicaciones App1 y App2. La POU CheckBounds está disponible en la App2, pero no en la 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)

La expresión obtiene el valor TRUE si se ha definido una tarea con el nombre <task name>. De lo contrario, es FALSE.

Sintaxis:

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

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

Ejemplo 2:

Requisito: hay 2 aplicaciones App1 y App2. La tarea PLC_PRG_Task está definida en la App1, pero no en la 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)

Cuando se aplica a una POU, su valor es TRUE si ese attribute en concreto se ha especificado en la primera línea de la parte de declaración de la POU.

Ejemplo de hasattribute (pou: pou-name, attribute):

Requisito: hay 2 aplicaciones App1 y App2. La función fun1 está definida en la App1 y la App2, pero en la App1 tiene un atributo vision:

Definición de fun1 en la App1:

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

Definición de fun1 en la App2:

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

Instrucción Pragma

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

hasattribute (variable: variable, attribute)

Cuando se aplica a una variable, su valor es TRUE si este atributo determinado se especifica mediante la instrucción {attribute} una línea antes de la declaración de la variable.

Ejemplo de hasattribute (variable: variable, attribute):

Requisito: hay 2 aplicaciones App1 y App2. La variable g_globalInt se usa en la App1 y la App2, pero en la App1 tiene un atributo DoCount:

Declaración de g_globalInt en la App1

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

Declaración de g_globalInt en la App2

VAR_GLOBAL
g_globalInt : INT;
g_multiType : STRING;
END_VAR

Instrucción 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)

Cuando se aplica a una variable, su valor es TRUE si esta variable en concreto tiene type-spec especificado. De lo contrario, es FALSE.

Tipos de datos disponibles de 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

Ejemplo en el operador hastype (variable: variable, type-spec):

Requisito: hay 2 aplicaciones App1 y App2. La variable g_multitype se declara en App1 con el tipo LREAL y en la aplicación App2 con el tipo 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 el definidor (define-ident) está definido y tiene el valor especificado (char-string), entonces su valor es TRUE. De lo contrario, es FALSE.

Ejemplo de hasvalue (define-ident, char-string):

Requisito: la variable test se usa en las aplicaciones App1 y App2. Obtiene el valor 1 en la App1 y el valor 2 en la 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>')

La modalidad de paquete que se comprueba depende de la descripción del dispositivo, no del pragma que se pueda especificar para los diferentes DUT.

hasvalue (RegisterSize, '<register size>')

<register size>: define el tamaño de un registro de CPU (en bits).

Cuando el tamaño de un registro de CPU es igual a <register size>, la expresión devuelve el valor TRUE.

<register size> puede presentar los siguientes valores:

  • 16 para C16x

  • 64 para X86-64 bits

  • 32 para X86-32 bits

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

El operador comprueba si la constante, que se define con <constant name>, se ha reemplazado. El segundo parámetro (valor booleano) controla lo que se comprueba:

  • TRUE: comprueba si se ha reemplazado la constante.

  • FALSE: comprueba si se ha reemplazado la constante.

Si se detecta el caso correspondiente, el operador devuelve TRUE.

Sintaxis:

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

Ejemplo:

{IF hasconstanttype(PLC_PRG.aConst, TRUE)}

El reemplazo automático de constantes depende de lo siguiente:

  • La opción de compilación Reemplazar constantes

  • El tipo de constante (los tipos STRING, por ejemplo, no se reemplazan)

  • El uso del atributo {attribute 'const_non_replaced'}

  • El uso del atributo {attribute 'const_replaced'}

Ejemplo:

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

El operador compara el valor de la constante, que se define con <constant name>, con el valor del segundo parámetro. El segundo parámetro se puede especificar como literal <literal> o como variable <variable name>.

Se admiten los siguientes operadores de comparación <comparison operator>:

  • Mayor que (>)

  • Mayor o igual que (>=)

  • Igual a (=)

  • Distinto de (<>)

  • Menor o igual que (<=)

  • Menor que (<)

Sintaxis:

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

Ejemplo 1:

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

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

Ejemplo 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

La expresión obtiene el valor TRUE cuando el valor invertido del operator es TRUE. operator puede ser uno de los operadores descritos en este capítulo.

Ejemplo de NOT operator:

Requisito: hay 2 aplicaciones App1 y App2. La POU PLC_PRG1 se usa en la App1 y la App2. La POU CheckBounds solo está disponible en la 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

La expresión obtiene el valor TRUE si ambos operadores son TRUE. operator puede ser uno de los operadores enumerados en esta tabla.

Ejemplo de AND operator:

Requisito: hay 2 aplicaciones App1 y App2. La POU PLC_PRG1 se usa en las aplicaciones App1 y App2. La POU CheckBounds solo está disponible en la 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

La expresión es TRUE si uno de los operadores es TRUE. operator puede ser uno de los operadores descritos en este capítulo.

Ejemplo de OR operator:

Requisito: La POU PLC_PRG1 se usa en las aplicaciones App1 y App2. La POU CheckBounds solo está disponible en la 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) incluye entre paréntesis los operadores.