In this section: |
How to: |
Reference: |
A request can call a subroutine coded in REXX. These subroutines, also called FUSREXX macros, provide a 4GL option to the languages supported for user-written subroutines.
REXX subroutines are supported in the z/OS environment. A REXX subroutine contains REXX source code. Compiled REXX code is not supported.
A REXX subroutine contains REXX source code. Compiled REXX code is not supported.
REXX subroutines are not necessarily the same in all operating environments. Therefore, some of the examples may use REXX functions that are not available in your environment.
Because of CPU requirements, the use of REXX subroutines in large production jobs should be monitored carefully.
For more information on REXX subroutines, see your REXX documentation.
To store a REXX subroutine, DDNAME FUSREXX must be allocated to a PDS. This library is searched before other z/OS libraries.
The search order for a REXX subroutine is:
DEFINE FILE filename fieldname/{An|In} = subname(inlen1, inparm1, ..., outlen, outparm); END
or
{DEFINE|COMPUTE} fieldname/{An|In} = subname(inlen1, inparm1, ..., outlen, outparm);
or
-SET &var = subname(inlen1, inparm1, ..., outlen, outparm);
where:
Is the field that contains the result.
Is the format of the field that contains the result.
Is the name of the REXX subroutine.
Are the input parameters. Each parameter consists of a length and an alphanumeric parameter value. You can supply the value, the name of an alphanumeric field that contains the value, or an expression that returns the value. Up to 13 input parameter pairs are supported. Each parameter value can be up to 256 bytes long.
Dialogue Manager converts numeric arguments to floating-point double-precision format. Therefore, you can only pass alphanumeric input parameters to a REXX subroutine using -SET.
Is the output parameter pair, consisting of a length and a result. In most cases, the result should be alphanumeric, but integer results are also supported. The result can be a field or a Dialogue Manager variable that contains the value, or the format of the value enclosed in single quotation marks. The return value can be a minimum of one byte long and a maximum (for an alphanumeric value) of 256 bytes.
Note: If the value returned is an integer, outlen must be 4 because WebFOCUS reserves four bytes for integer fields.
Is the name of the Dialogue Manager variable that contains the result.
The REXX subroutine DOW returns the day of the week corresponding to the date an employee was hired. The routine contains one input parameter pair and one return field pair.
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
The procedure processes as follows:
The output is:
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
The REXX subroutine appears below. It reads the input date, reformats it to MM/DD/YY format, and returns the day of the week using a REXX DATE call.
/* DOW routine. Return WEEKDAY from YYMMDD format date */ Arg ymd . Return Date('W',Translate('34/56/12',ymd,'123456'),'U')
The REXX subroutine INTEREST has four input parameters.
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
The procedure processes as follows:
The third input field is a character value of 6.5, which is three bytes long to account for the decimal point in the character string.
The fourth input field is 12 bytes long. This passes the character field ACSAL.
The return field is up to 12 bytes long and is named PV.
The output is:
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
The REXX subroutine appears below. The REXX Format command is used to format the return value.
/* 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)
A REXX subroutine can accept multiple tokens in a parameter. The following procedure passes employee information (PAY_DATE and MO_PAY) as separate tokens in the first parameter. It passes three input parameters and one return field.
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
The procedure processes as follows:
The output is:
EMP_ID FIRST_NAME LAST_NAME DEPARTMENT ------ ---------- --------- ---------- 071382660 ALFRED STEVENS PRODUCTION
The REXX subroutine appears below. Commas separate FUSREXX parameters. The ARG command specifies multiple variable names before the first comma and, therefore, separates the first FUSREXX parameter into separate REXX variables, using blanks as delimiters between the 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
REXX subroutines should use the REXX RETURN subroutine to return data. REXX EXIT is acceptable, but is generally used to end an EXEC, not a 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 |
A REXX subroutine requires input data to be in alphanumeric format. Most output is returned in alphanumeric format. If the format of an input argument is numeric, use the EDIT or FTOA functions to convert the argument to alphanumeric. You can then use the EDIT or ATODBL functions to convert the output back to numeric.
The output length in the subroutine call must be four. Character variables cannot be more than 256 bytes. This limit also applies to REXX subroutines. FUSREXX routines return variable length data. For this reason, you must supply the length of the input arguments and the maximum length of the output data.
A REXX subroutine does not require any input parameters, but requires one return parameter, which must return at least one byte of data. It is possible for a REXX subroutine not to need input, such as a function that returns USERID.
A REXX subroutine does not support WebFOCUS date input arguments. When working with dates you can do one of the following:
Date fields contain the integer number of days since the base date 12/31/1900. REXX has a date function that can accept and return several types of date formats, including one called Base format ('B') that contains the number of days since the REXX base date 01/01/0001. You must account for the difference, in number of days, between the WebFOCUS base date and the REXX base date and convert the result to integer.
The NUMCNT subroutine returns the number of copies of each classic movie in alphanumeric format. It passes one input parameter and one return field.
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
The procedure processes as follows:
The output is:
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
The subroutine is:
/* 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)
In the following example, the NUMDAYS subroutine finds the number of days between HIRE_DATE and DAT_INC and returns the result in integer format.
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
The procedure processes as follows:
The output is:
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
The subroutine appears below. The return value is converted from REXX character to HEX and formatted to be four bytes long.
/* 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)
In the following example, a date is used by passing an alphanumeric field with date options to the DATEREX1 subroutine. DATEREX1 takes two input arguments: an alphanumeric date in A8YYMD format and a number of days in character format. It returns a smart date in YYMD format that represents the input date plus the number of days. The format A8YYMD corresponds to the REXX Standard format ('S').
The number 693959 represents the difference, in number of days, between the WebFOCUS base date and the REXX base date:
/* REXX DATEREX1 routine. Add indate (format A8YYMD) to days */ Arg indate, days . Return D2C(Date('B',indate,'S')+ days - 693959, 4)
The following request uses the DATEREX1 macro to calculate the date that is 365 days from the hire date of each employee. The input arguments are the hire date and the number of days to add. Because HIRE_DATE is in I6YMD format, it must be converted to A8YYMD before being passed to the 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
The output is:
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
In the following example, a date is passed to the subroutine as a smart date converted to alphanumeric format. The DATEREX2 subroutine takes two input arguments: an alphanumeric number of days that represents a smart date, and a number of days to add. It returns a smart date in YYMD format that represents the input date plus the number of days. Both the input date and output date are in REXX base date ('B') format.
The number 693959 represents the difference, in number of days, between the WebFOCUS base date and the REXX base date:
/* REXX DATEREX2 routine. Add indate (original format YYMD) to days */ Arg indate, days . Return D2C(Date('B',indate+693959,'B') + days - 693959, 4)
The following request uses DATEREX2 to calculate the date that is 365 days from the hire date of each employee. The input arguments are the hire date and the number of days to add. Because HIRE_DATE is in I6YMD format, it must be converted to an alphanumeric number of days before being passed to the 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
The output is:
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