Subrutinas escritas en REXX

En esta sección:

Cómo:

Referencia:

Las solicitudes pueden llamar a subrutinas codificadas en REXX. Estas subrutinas, también denominadas macros FUSREXX, ofrecen una opción de 4GL para los lenguaje compatibles con subrutinas escritas por los usuarios.

Las subrutinas REXX son compatibles con el entorno z/OS. Las subrutinas REXX contienen el código fuente de REXX. El código REXX compilado no es compatible.

Las subrutinas REXX contienen el código fuente de REXX. El código REXX compilado no es compatible.

Las subrutinas REXX no tienen por qué ser las mismas en todos los entornos operativos. Por tanto, puede que algunos de los ejemplos empleen funciones REXX que no están disponibles en su entorno.

Debido a los requisitos de CPU, el uso de subrutinas REXX en trabajos de producción de gran tamaño debe controlarse minuciosamente.

Para más información sobre las subrutinas REXX, consulte su documentación de REXX.


Principio de página

x
Referencia: Cómo almacenar y buscar una subrutina REXX

Para almacenar una subrutina REXX, DDNAME FUSREXX debe estar asignado a un PDS. Primero se realiza una búsqueda en la biblioteca y después, en el resto de bibliotecas de z/OS.

El orden de búsqueda de las subrutinas REXX es:

  1. FUSREXX.
  2. Orden de búsqueda estándar en z/OS.

Principio de página

x
Sintaxis: Cómo Llamar a una subrutina REXX
DEFINE FILE filename
						 
fieldname/{An|In} = subname(inlen1, inparm1, ..., outlen, outparm);
END

o

{DEFINE|COMPUTE} fieldname/{An|In} = subname(inlen1, inparm1, ...,  
outlen, outparm);

o

-SET &var = subname(inlen1, inparm1, ..., outlen, outparm);

donde:

fieldname

El campo que contiene el resultado.

An, In

El formato del campo que contiene el resultado.

subname

El nombre de la subrutina REXX.

inlen1, inparm1 ...

Los parámetros de entrada. Cada parámetro está compuesto por una longitud y un valor de parámetro alfanumérico. Puede proporcionar el valor, el nombre de un campo alfanumérico que contenga el valor o una expresión que devuelva el valor. Puede usar hasta 13 pares de parámetros. Cada valor de parámetro puede tener hasta 256 bytes.

Dialogue Manager convierte los argumentos numéricos al formato de punto flotante, de doble precisión. Por tanto, sólo puede pasar parámetros de entrada alfanuméricos a la subrutina REXX, mediante -SET.

outlen, outparm

Es la pareja del parámetro de salida: una longitud y un resultado. En la mayoría de los casos, el resultado debe ser alfanumérico, aunque los números enteros también son compatibles. El resultado puede ser un campo o una variable de Dialogue Manager que contenga el valor, o el formato del valor entre comillas simples. La longitud mínima del valor devuelto es de 1 byte, la máxima (en valores alfanuméricos), de 256.

Nota: Si el valor devuelto es un número entero, outlen debe ser 4, ya que WebFOCUS reserva cuatro bytes para los campos de número entero.

&var

El nombre de la variable de Dialogue Manager que contiene el resultado.



Ejemplo: Cómo devolver el día de la semana

La subrutina DOW de REXX devuelve el día de la semana correspondiente a la fecha de contratación de un empleado. La rutina contiene una pareja del parámetro de entrada y una pareja del campo de devolución.

DEFINE FILE EMPLOYEE 
1. AHDT/A6 = EDIT(HIRE_DATE) ; 
2. DAY_OF_WEEK/A9 WITH AHDT = DOW(6, AHDT, 9, DAY_OF_WEEK);
   END
TABLE FILE EMPLOYEE
PRINT LAST_NAME HIRE_DATE DAY_OF_WEEK
END

El procedimiento se procesa del siguiente modo:

  1. La función EDIT convierte HIRE_DATE al formato alfanumérico, y almacena el resultado en un campo con el formato A6.
  2. El resultado queda almacenado en el campo DAY_OF_THE_WEEK, y puede tener hasta nueve bytes de longitud.

La salida es:

LAST_NAME        HIRE_DATE  DAY_OF_WEEK
---------        ---------  -----------
STEVENS           80/06/02  Monday
SMITH             81/07/01  Wednesday
JONES             82/05/01  Saturday
SMITH             82/01/04  Monday
BANNING           82/08/01  Sunday
IRVING            82/01/04  Monday
ROMANS            82/07/01  Thursday
MCCOY             81/07/01  Wednesday
BLACKWOOD         82/04/01  Thursday
MCKNIGHT          82/02/02  Tuesday
GREENSPAN         82/04/01  Thursday
CROSS             81/11/02  Monday

La subrutina REXX aparece más abajo. Lee la fecha de entrada, cambia el formato a MM/DD/YY y devuelve el día de la semana mediante una llamada a REXX DATE.

/* DOW routine. Return WEEKDAY from YYMMDD format date */
Arg ymd .
Return Date('W',Translate('34/56/12',ymd,'123456'),'U')


Ejemplo: Cómo pasar múltiples argumentos a una subrutina REXX

La subrutina INTEREST de REXX tiene cuatro parámetros de entrada.

DEFINE FILE EMPLOYEE 
1. AHDT/A6     = EDIT(HIRE_DATE); 
2. ACSAL/A12   = EDIT(CURR_SAL); 
3. DCSAL/D12.2 = CURR_SAL; 
4. PV/A12    = INTEREST(6, AHDT, 6, '&YMD', 3, '6.5', 12, ACSAL, 12, PV);
   END
 
TABLE FILE EMPLOYEE
PRINT LAST_NAME FIRST_NAME HIRE_DATE DCSAL PV
END

El procedimiento se procesa del siguiente modo:

  1. EDIT convierte HIRE_DATE al formato alfanumérico, y almacena el resultado en AHDT.
  2. EDIT convierte CURR_SAL al formato alfanumérico, y almacena el resultado en ACSAL.
  3. CURR_SAL se convierte en un campo de punto flotante, de doble precisión que incluye comas, y el resultado se almacena en DCSAL.
  4. El segundo campo de entrada tiene seis bytes de longitud. Los datos se pasan como una variable de caracteres &YMD, en el formato YYMMDD.

    El tercer campo de entrada es un valor de caracteres de 6.5, con una longitud de tres bytes, para acomodar el punto decimal de la cadena de caracteres.

    El cuarto campo de entrada es de 12 bytes. Esto sirve para pasar el campo de caracteres ACSAL.

    El campo de devolución puede tener hasta 12 bytes y se llama PV.

La salida es:

LAST_NAME        FIRST_NAME  HIRE_DATE           DCSAL            PV
---------        ----------  ---------           -----            --
STEVENS          ALFRED       80/06/02       11,000.00      14055.14
SMITH            MARY         81/07/01       13,200.00      15939.99
JONES            DIANE        82/05/01       18,480.00      21315.54
SMITH            RICHARD      82/01/04        9,500.00      11155.60
BANNING          JOHN         82/08/01       29,700.00      33770.53
IRVING           JOAN         82/01/04       26,862.00      31543.35
ROMANS           ANTHONY      82/07/01       21,120.00      24131.19
MCCOY            JOHN         81/07/01       18,480.00      22315.99
BLACKWOOD        ROSEMARIE    82/04/01       21,780.00      25238.25
MCKNIGHT         ROGER        82/02/02       16,100.00      18822.66
GREENSPAN        MARY         82/04/01        9,000.00      10429.03
CROSS            BARBARA      81/11/02       27,062.00      32081.82

La subrutina REXX aparece más abajo. El comando REXX Format se usa para aplicar un formato al valor devuelto.

/* Simple INTEREST program. dates are yymmdd format  */
Arg start_date,now_date,percent,open_balance, .
 
begin = Date('B',Translate('34/56/12',start_date,'123456'),'U')
stop  = Date('B',Translate('34/56/12',now_date,'123456'),'U')
valnow = open_balance * (((stop - begin) * (percent / 100)) / 365)
 
Return Format(valnow,9,2)


Ejemplo: Cómo aceptar múltiples tokens en un parámetro

Las subrutinas REXX pueden aceptar varios tokens en un parámetro. El siguiente procedimiento pasa la información del empleado (PAY_DATE y MO_PAY) como tokens independientes, en el primer parámetro. Pasa tres parámetros de entrada y un campo devuelto.

DEFINE FILE EMPLOYEE 
1.  COMPID/A256 = FN | ' ' | LN | ' ' |  DPT | ' ' | EID ; 
2.  APD/A6 = EDIT(PAY_DATE); 
3.  APAY/A12 = EDIT(MO_PAY); 
4.  OK4RAISE/A1 = OK4RAISE(256, COMPID, 6, APD, 12, APAY, 1, OK4RAISE);
    END
 
TABLE FILE EMPLOYEE
PRINT EMP_ID FIRST_NAME LAST_NAME DEPARTMENT
IF OK4RAISE EQ '1'
END

El procedimiento se procesa del siguiente modo:

  1. COMPID es la concatenación de varios campos de caracteres, pasados como el primer parámetro y almacenados en un campo con el formato A256. Cada parámetro es un argumento individual.
  2. EDIT convierte PAY_DATE al formato alfanumérico.
  3. EDIT convierte MO_PAY al formato alfanumérico.
  4. Se ejecuta OK4RAISE y el resultado se almacena en OK4RAISE.

La salida es:

EMP_ID     FIRST_NAME         LAST_NAME      DEPARTMENT
------     ----------         ---------      ----------
071382660  ALFRED             STEVENS        PRODUCTION

La subrutina REXX aparece más abajo. Los parámetros FUSREXX se separan mediante comas. El comando ARG especifica múltiples nombres de variables antes de la primera coma y, por tanto, separa el primer parámetro FUSREXX en distintas variables REXX, utilizando espacios en blanco como delimitadores entre las variables.

/* OK4RAISE routine. Parse separate tokens in the 1st parm, */
/* then more parms */
 
Arg fname lname dept empid,  pay_date,  gross_pay, .
 
If dept = 'PRODUCTION' & pay_date < '820000'
Then retvalue = '1'
Else retvalue = '0'
 
Return retvalue

Las subrutinas REXX deben usar la subrutina REXX RETURN para devolver datos. REXX EXIT es válido, aunque se suele utilizar para finalizar un EXEC, no una FUNCTION.

Correct
/* Some FUSREXX function */
Arg input
some rexx process ...
Return data_to_WebFOCUS
Not as Clear
/* Another FUSREXX function */
Arg input
some rexx process ...
Exit 0


x
Formatos y subrutinas REXX

Las subrutinas REXX requieren que los datos de entrada estén en formato alfanumérico. La mayor parte de la salida se devuelve en este formato. Si el formato de un argumento de entrada es numérico, use las funciones EDIT o FTOA para convertirlo en alfanumérico. A partir de ese momento, podrá utilizar las funciones EDIT o ATODBL para reconvertir la salida a numérico.

La longitud de salida en la llamada de subrutina debe ser de cuatro. Las variables de caracteres no pueden tener más de 256 bytes. Este límite también se aplica a las subrutinas REXX. Las subrutinas FUSREXX devuelven datos de longitud variable. Por esta razón, debe proporcionar la longitud de los argumentos de entrada y la longitud máxima de los datos de salida.

Las subrutinas REXX no requieren parámetros de entrada, aunque sí uno devuelto, que debe incluir al menos un byte de datos. Puede haber casos en que una subrutina no necesite entrada, como una función que devuelve USERID.

Las subrutinas REXX no son compatibles con los argumentos de entrada de fechas de WebFOCUS. Si está trabajando con fechas, puede seguir uno de estos métodos:



Ejemplo: Cómo devolver un resultado en formato alfanumérico

La subrutina NUMCNT devuelve el número de copias de cada película clásica en formato alfanumérico. Pasa un parámetro de entrada y un campo devuelto.

TABLE FILE MOVIES 
   PRINT TITLE AND COMPUTE  
1. ACOPIES/A3 = EDIT(COPIES); AS 'COPIES'
   AND COMPUTE 
2. TXTCOPIES/A8 = NUMCNT(3, ACOPIES, 8, TXTCOPIES);
   WHERE CATEGORY EQ 'CLASSIC'
   END

El procedimiento se procesa del siguiente modo:

  1. El campo EDIT convierte COPIES al formato alfanumérico, y almacena el resultado en ACOPIES.
  2. El resultado se almacena en un campo alfanumérico de 8 bytes, TXTCOPIES.

La salida es:

TITLE                                    COPIES  TXTCOPIES
-----                                    ------  ---------
EAST OF EDEN                             001     One
CITIZEN KANE                             003     Three
CYRANO DE BERGERAC                       001     One
MARTY                                    001     One
MALTESE FALCON, THE                      002     Two
GONE WITH THE WIND                       003     Three
ON THE WATERFRONT                        002     Two
MUTINY ON THE BOUNTY                     002     Two
PHILADELPHIA STORY, THE                  002     Two
CAT ON A HOT TIN ROOF                    002     Two
CASABLANCA                               002     Two

La subrutina es:

/* NUMCNT routine. */
/* Pass a number from 0 to 10 and return a character value */ 
Arg numbr .
data = 'Zero One Two Three Four Five Six Seven Eight Nine Ten'
numbr = numbr + 1           /* so 0 equals 1 element in array */
Return Word(data,numbr)


Ejemplo: Cómo devolver un resultado en formato de número entero

En el siguiente ejemplo, la subrutina NUMDAYS calcula el número de días entre HIRE_DATE y DAT_INC, y devuelve el resultado en el formato de número entero.

   DEFINE FILE EMPLOYEE 
1. AHDT/A6 = EDIT(HIRE_DATE); 
2. ADI/A6 = EDIT(DAT_INC); 
3. BETWEEN/I6 = NUMDAYS(6, AHDT, 6, ADI, 4, 'I6') ;
   END
 
TABLE FILE EMPLOYEE
PRINT LAST_NAME HIRE_DATE DAT_INC BETWEEN
IF BETWEEN NE 0
END

El procedimiento se procesa del siguiente modo:

  1. EDIT convierte HIRE_DATE al formato alfanumérico, y almacena el resultado en AHDT.
  2. EDIT convierte DAT_INC al formato alfanumérico, y almacena el resultado en ADI.
  3. NUMDAYS calcula el número de días entre AHDT y ADI, y almacena el resultado en el formato de número entero.

La salida es:

LAST_NAME      HIRE_DATE   DAT_INC  BETWEEN
---------      ---------   -------  -------
STEVENS        80/06/02    82/01/01     578
STEVENS        80/06/02    81/01/01     213
SMITH          81/07/01    82/01/01     184
JONES          82/05/01    82/06/01      31
SMITH          82/01/04    82/05/14     130
IRVING         82/01/04    82/05/14     130
MCCOY          81/07/01    82/01/01     184
MCKNIGHT       82/02/02    82/05/14     101
GREENSPAN      82/04/01    82/06/11      71
CROSS          81/11/02    82/04/09     158

La subrutina aparece más abajo. El valor devuelto se convierte del carácter REXX a HEX y se le aplica un formato de cuatro bytes de largo.

/* NUMDAYS routine.  */
/* Return number of days between 2 dates in yymmdd format */
/* The value returned will be in hex format               */
 
Arg first,second .
 
base1 = Date('B',Translate('34/56/12',first,'123456'),'U')
base2 = Date('B',Translate('34/56/12',second,'123456'),'U')
 
Return D2C(base2 - base1,4)


Ejemplo: Cómo pasar un valor de fecha como campo alfanumérico con opciones de fecha

En el siguiente ejemplo, la fecha se utiliza pasando un campo alfanumérico con opciones de fecha a la subrutina DATEREX1. DATEREX1 toma dos argumentos de entrada: una fecha alfanumérica en formato A8 y un número de días en formato de caracteres. Devuelve una fecha inteligente en formato YYMD, que representa la fecha de entrada más el número de días. El formato A8YYMD corresponde al formato REXX estándar ('S').

El número 693959 representa la diferencia en días entre la fecha base de WebFOCUS y la de REXX:

/* REXX DATEREX1 routine. Add indate (format A8YYMD) to days */
Arg indate, days .
Return D2C(Date('B',indate,'S')+ days - 693959, 4)

La siguiente solicitud usa el macro DATEREX1 para calcular la fecha que está a 365 días de la fecha de contratación de cada empleado. Los argumentos de entrada son la fecha de contratación y el número de días que se va a añadir. Puesto que HIRE_DATE está en el formato I6YMD, debe convertirse a A8YYMD antes de poder pasarse al macro:

TABLE FILE EMPLOYEE
PRINT LAST_NAME FIRST_NAME HIRE_DATE
AND COMPUTE
  ADATE/YYMD =  HIRE_DATE; NOPRINT
AND COMPUTE
  INDATE/A8YYMD= ADATE; NOPRINT
AND COMPUTE
  NEXT_DATE/YYMD = DATEREX1(8, INDATE, 3, '365', 4, NEXT_DATE);
BY LAST_NAME NOPRINT
END

La salida es:

LAST_NAME        FIRST_NAME  HIRE_DATE  NEXT_DATE 
---------        ----------  ---------  --------- 
BANNING          JOHN         82/08/01  1983/08/01
BLACKWOOD        ROSEMARIE    82/04/01  1983/04/01
CROSS            BARBARA      81/11/02  1982/11/02
GREENSPAN        MARY         82/04/01  1983/04/01
IRVING           JOAN         82/01/04  1983/01/04
JONES            DIANE        82/05/01  1983/05/01
MCCOY            JOHN         81/07/01  1982/07/01
MCKNIGHT         ROGER        82/02/02  1983/02/02
ROMANS           ANTHONY      82/07/01  1983/07/01
SMITH            MARY         81/07/01  1982/07/01
SMITH            RICHARD      82/01/04  1983/01/04
STEVENS          ALFRED       80/06/02  1981/06/02


Ejemplo: Cómo pasar una fecha como convertida al formato alfanumérico

En el siguiente ejemplo, la fecha se ha pasado a la subrutina como fecha inteligente convertida al formato alfanumérico. La subrutina DATEREX2 toma dos argumentos de entrada: un número de días alfanumérico, que representa una fecha inteligente, y el número de días que se va a añadir. Devuelve una fecha inteligente en formato YYMD, que representa la fecha de entrada más el número de días. La fecha de entrada y la de salida están en el formato de fecha estándar de REXX ('B').

El número 693959 representa la diferencia en días entre la fecha base de WebFOCUS y la de REXX:

/* REXX DATEREX2 routine. Add indate (original format YYMD) to days */
Arg indate, days .
Return D2C(Date('B',indate+693959,'B') + days - 693959, 4)

La siguiente solicitud usa el macro DATEREX2 para calcular la fecha que está a 365 días de la fecha de contratación de cada empleado. Los argumentos de entrada son la fecha de contratación y el número de días que se va a añadir. Puesto que HIRE_DATE está en el formato I6YMD, debe convertirse en un número de días alfanumérico antes de ser pasado al macro:

TABLE FILE EMPLOYEE
PRINT LAST_NAME FIRST_NAME HIRE_DATE
AND COMPUTE
  ADATE/YYMD =  HIRE_DATE; NOPRINT
AND COMPUTE
  INDATE/A8 = EDIT(ADATE); NOPRINT
AND COMPUTE
  NEXT_DATE/YYMD = DATEREX2(8,INDATE,3,'365',4,NEXT_DATE);
BY LAST_NAME NOPRINT
END

La salida es:

LAST_NAME        FIRST_NAME  HIRE_DATE  NEXT_DATE 
---------        ----------  ---------  --------- 
BANNING          JOHN         82/08/01  1983/08/01
BLACKWOOD        ROSEMARIE    82/04/01  1983/04/01
CROSS            BARBARA      81/11/02  1982/11/02
GREENSPAN        MARY         82/04/01  1983/04/01
IRVING           JOAN         82/01/04  1983/01/04
JONES            DIANE        82/05/01  1983/05/01
MCCOY            JOHN         81/07/01  1982/07/01
MCKNIGHT         ROGER        82/02/02  1983/02/02
ROMANS           ANTHONY      82/07/01  1983/07/01
SMITH            MARY         81/07/01  1982/07/01
SMITH            RICHARD      82/01/04  1983/01/04
STEVENS          ALFRED       80/06/02  1981/06/02

WebFOCUS