Fast/Unload customer-written assembler function packages
You can extend the set of #functions available at your site by writing one or more collections of them and making them available to FUEL. The items enabling you to do this are:
- The FUNCTIONS statement has been added to FUEL to identify the location of #functions you have written.
- An efficient, easy-to-use interface has been designed for matching a #function name to the code implementing that #function.
- An efficient, easy-to-use interface has been designed for performing common operations needed by #functions, such as obtaining the value of arguments and setting the result value and output arguments.
- The interfaces have been designed with compatibility in mind; with new releases of Fast/Unload you will not even need to reassemble your #functions.
Members of SIRIUS.OBJLIB used in coding #functions
Some assembler language source files are included in your Fast/Unload distribution tape to assist you in developing #functions. They are described in this section.
Run-time interface symbols: FUNCEQU COPY
This COPY member should be made available in a MACLIB to assemble any #functions you write. The symbols defined in it consist of the values you can pass to the Fast/Unload #function service routine, for the various services being requested. The only value defined in this COPY member which will change is the symbol FUNQX, which will increase when additional services are added to the interface.
Note: Prior to the release of version 4.0 of Fast/Unload, one of the symbols, FUNQAFS, was incorrectly defined. Be sure you are using the corrected FUNCEQU COPY, which contains the following assembler statement:
FUNQAFS EQU 11 Assign float to arg...
Example #function package: UFUN ASSEMBLE
This ASSEMBLE program contains the package-searching code, along with one sample #function available in the package. You can modify this program to write a #function package, using your own #function names in the table.
Since future versions of Fast/Unload may contain new standard #functions, you should choose a naming convention for your #functions which is not likely to overlap the standard #functions.
Compiler call to package to locate #function
When a #function call is compiled in a FUEL program, if the #function name is not one of the standard Fast/Unload #functions, all #function packages are dynamically loaded and called, in the order specified, until the #function name is in the package.
The registers passed to the #function package are:
R1 | The address of a byte, which contains the length of the #function name, followed by the #function name, blank padded to 255 bytes. |
---|---|
R6 | The address of a 4096 byte work area which is passed to all #function packages and to all #functions. This area is initally all binary zeroes and is aligned on a doubleword boundary. Fast/Unload does not modify this area. |
R13 | The address of a 4096 byte work area which is passed only to this #function package and to all #functions within this package. This area is initially all binary zeroes and is aligned on a doubleword boundary. Fast/Unload does not modify this area. |
R14 | The return address. |
R15 | The entry point of the #function package. |
The registers returned by the #function package are:
R0 | Must contain 0. |
---|---|
R1 | One of the following two cases:
|
R2 | A bit mask, to indicate which arguments are required. For example, X'A0000000' indicates the first and third arguments are required (a rather strange example). |
R3 | A bit mask, to indicate which arguments, if specified, must be %variables (i.e., available as output). For example, X'30000000' indicates the third and fourth arguments are output arguments. |
R4 | Maximum number of arguments the #function can accept. |
R5-R15 | Need not be restored, can contain any value. |
Run-time invocation of #function
This section describes the registers passed to a #function (none need be returned by the #function), and the services that Fast/Unload makes available for use by a #function.
The registers passed to a #function are:
R5 | The address of a service routine to retrieve from or assign to the #function arguments or perform other services. See the description of the interface to the service routine, presented next in this section. |
---|---|
R6 | The address of a 4096 byte work area which is passed to all #function packages and all to #functions. Fast/Unload does not modify this area. |
R13 | The address of a 4096 byte work area which is passed only to a given #function package and to all #functions which were resolved by a call to that package. Fast/Unload does not modify this area. |
R14 | The return address. |
R15 | The entry point of the #function. |
The argument values can be returned by the service routine; various values (FUNQ2xxx) are used for different types.
There is no information returned from a #function in the registers. No registers need be restored; they can contain any value. The result value and output arguments of a #function are set by passing various values (FUNQ2xxx) to the service routine.
The service routine which is passed to a #function in register R5 is used to retrieve the value of or perform assignment into the #function arguments or result, issue error messages, terminate Fast/Unload, and manage memory.
The registers at entry to the service routine are described below; individual services have some exceptions, which are explained in the description of the services in this section.
R0 | Unless specified otherwise, the argument number for the service. Argument number 0 designates the #function result. |
---|---|
R1 | A code indicating the service required (symbols for this code are defined in FUNCQEU COPY). |
R2 | As described for individual service descriptions in this section. |
F0 | (Floating point register 0); as described for individual service descriptions in this section. |
R14 | The return address. |
The registers on return from the service routine are explained in the description of the services in this section. For all services, the registers on return from the service routine are:
R0-R2 | Unless specified for an individual service, unpredictable. |
---|---|
R3-R14 | Unchanged from values at entry. |
R15 | Usually a return code; if not specified by the service routine description, unpredictable. |
Get information about #function argument(s)
This service obtains the number of arguments to the #function and optionally the type (omitted/present, MISSING value or not, and output or not) of a specified argument.
This service is most often invoked for #functions which have a variable number of arguments (such as #CONCAT). For a different usage example, it can be invoked as follows to see if a particular argument is an output argument (although the function package makes sure that if an argument is declared as output, any function call using that argument is a %variable):
LA R0,xxx Get info about arg xxx LA R1,FUNQAI Get service number BALR R14,R5 Call service LTR R15,R15 Is arg an output arg? BP ... No, handle condition
Special input registers for this service are:
R0 | Argument number (0 means don't get single arg info). |
---|
Output registers for this service are:
R0 | Number of arguments (including omitted arguments after a comma) (i.e., 0 if no args, else 1 + number of commas). :lp.Following output registers only apply if this service is called with R0 > 0: |
---|---|
R1 | 0: Argument has a value. 4: Argument is not present. 8: Argument is present but value is MISSING. |
R15 | 0: Argument is an output arg; assignment will be OK. 4: Argument is not present. 8: Argument present but not an output arg. |
Get string value of argument
This pair of services obtains the string value of a specified argument. The strict service (FUNQ2SS) will terminate if the argument is omitted. The conditional service (FUNQ2SC) will allow all argument cases. Either service will reflect exception argument cases by a return code in register R15 and a zero length in register R0.
For example, they can be invoked as follows:
LA R0,xxx Get value of arg xxx LA R1,FUNQ2SS Service number: omitted CANCEL BALR R14,R5 Call service * Omit following two lines if null for MISSING is OK: CH R15,=H'8' Is value MISSING? BE ... Yes, handle condition LTR R15,R0 Is string zero-length? BZ ... Yes, handle condition BCTR R15,0 No, get length - 1 EX R15,MVCA MVC xx(0,R13),0(R1) Copy to work area
or
LA R0,xxx Get value of arg xxx LA R1,FUNQ2SC Get service number - allow errors BALR R14,R5 Call service CH R15,=H'4' Is arg present? BE ... No, handle condition LTR R15,R0 Is string zero-length? BZ ... Yes, handle condition BCTR R15,0 No, get length - 1 EX R15,MVCA MVC xx(0,R13),0(R1) Copy to work area * Omit following two lines if no DBCS data handled: LTR R2,R2 Is string DBCS? BC ... Handle condition
These services have no special input registers.
Output registers for these services are:
R0 | Length of string value (0 if omitted or MISSING value). |
---|---|
R1 | Address of string value. |
R2 | 0: Not a DBCS string or not DBCS run > 0: Mixed DBCS string < 0: Pure DBCS string |
R15 | 0: Argument contains string value. 4: Argument is not present. 8: Argument present but value is MISSING. |
Get float value of argument
This pair of services obtains the 8 byte floating point value of a specified argument. The strict service (FUNQ2FS) will terminate if the argument is omitted, has a non-numeric value, or has a value too large in absolute value to store in an eight byte floating point number (insignificant fractions will be truncated without error). The conditional service (FUNQ2FC) will allow all argument cases. Either service will reflect exception argument cases by a return code in register R15 and a zero in float register F0.
For example, they can be invoked as follows:
LA R0,xxx Get value of arg xxx LA R1,FUNQ2FS Service num: omit/non-num CANCEL BALR R14,R5 Call service * Omit following two lines if zero for MISSING is OK: CH R15,=H'8' Is value MISSING? BE ... Yes, handle condition STD F0,xxx(,R13) Save value in work area
or
LA R0,xxx Get value of arg xxx LA R1,FUNQ2FC Get service number - allow errors BALR R14,R5 Call service B *+4(R15) Handle conditions B OK Handle success B ... Handle arg omitted B ... Handle MISSING value B ... Handle conversion error OK STD F0,xxx(,R13) Save value in work area
These services have no special input registers.
Output registers for these services are:
F0 | Float value (0 if omitted/unconvertible). |
---|---|
R15 | 0: Argument contains float value. 4: Argument is not present. 8: Argument present but value is MISSING. 12: Argument value can't be converted to float. |
Get fixed value of argument
This pair of services obtains the 4 byte binary integer value of a specified argument. The strict service (FUNQ2BS) will terminate if the argument is omitted, has a non-numeric value, or has a value too large (positive) or too small (negative) to store in a four byte signed binary number (fractions will be truncated without error). The conditional service (FUNQ2FC) will allow all argument cases. Either service will reflect exception argument cases by a return code in register R15 and a zero in register R1.
For example, they can be invoked as follows:
LA R0,xxx Get value of arg xxx LA R1,FUNQ2BS Service num: omit/non-num CANCEL BALR R14,R5 Call service * Omit following two lines if zero for MISSING is OK: CH R15,=H'8' Is value MISSING? BE ... Yes, handle condition ST R1,xxx(,R13) Save value in work area
or
LA R0,xxx Get value of arg xxx LA R1,FUNQ2BC Get service number - allow errors BALR R14,R5 Call service B *+4(R15) Handle conditions B OK Handle success B ... Handle arg omitted B ... Handle MISSING value B ... Handle conversion error OK ST R1,xxx(,R13) Save value in work area
These services have no special input registers.
Output registers for these services are:
R1 | Binary value (0 if omitted/unconvertible). |
---|---|
R15 | 0: Argument contains integer value (maybe truncated). 4: Argument is not present. 8: Argument present but value is MISSING. 12: Argument value can't be converted to fullword int. |
Assign string value to argument
This pair of services sets the value of a specified argument to a specified byte string. The strict service (FUNQASS) will terminate if the argument is omitted or is not an output argument. The conditional service (FUNQASC) will reflect these errors by a return code in register R15.
They are invoked as follows:
LA R0,xxx Set value of arg xxx LA R1,FUNQASS Get service number - errors CANCEL LA R2,... Address of string to assign set R3,... Length of string to assign * Omit following line if no DBCS data handled: set R4,... Indicate DBCS string type BALR R14,R5 Call service
or
LA R0,xxx Set value of arg xxx LA R1,FUNQASC Get service number - allow errors LA R2,... Address of string to assign LA R3,... Length of string to assign * Omit following line if no DBCS data handled: set R4,... Indicate DBCS string type BALR R14,R5 Call service CH R15,=H'4' Is arg present/output? BC ... Handle condition
Special input registers for these services are:
R2 | Address of value to assign. |
---|---|
R3 | Length of value to assign (must be < 256). |
R4 | If a DBCS run: 0: Not a DBCS string > 0: Mixed DBCS string < 0: Pure DBCS string |
Output registers for these services are:
R15 | 0: Assignment successful. 4: Assignment failed: arg omitted. 8: Assignment failed: arg is not output. |
---|
For FUNQASS, since the non-0 cases for R15 cause the Fast/Unload program to be terminated, if the service returns then R15 will be 0.
Assign float value to argument
This pair of services sets the value of a specified argument to a specified 8 byte floating point value. The strict service (FUNQAFS) will terminate if the argument is omitted or is not an output argument. The conditional service (FUNQAFC) will reflect these errors by a return code in register R15.
They are invoked as follows:
LA R0,xxx Set value of arg xxx LA R1,FUNQAFS Get service number - errors CANCEL LD F0,... Value to assign BALR R14,R5 Call service
or
LA R0,xxx Set value of arg xxx LA R1,FUNQAFC Get service number - allow errors LD F0,... Value to assign BALR R14,R5 Call service CH R15,=H'4' Is arg present/output? BC ... Handle condition
Special input registers for these services are:
F0 | Value to assign. |
---|
Output registers for these services are:
R15 | 0: Assignment successful. 4: Assignment failed: arg omitted. 8: Assignment failed: arg is not output. |
---|
For FUNQAFS, since the non-0 cases for R15 cause the Fast/Unload program to be terminated, if the service returns then R15 will be 0.
Note: Prior to the release of version 4.0 of Fast/Unload, FUNQAFS was incorrectly defined. Be sure you are using the corrected FUNCEQU COPY, which contains the following assembler statement:
FUNQAFS EQU 11 Assign float to arg...
Assign fixed value to argument
This pair of services sets the value of a specified argument to a specified 4 byte binary integer value. The strict service (FUNQABS) will terminate if the argument is omitted or is not an output argument. The conditional service (FUNQABC) will reflect these errors by a return code in register R15.
They are invoked as follows:
LA R0,xxx Set value of arg xxx LA R1,FUNQABS Get service number - errors CANCEL L R2,... Value to assign BALR R14,R5 Call service
or
LA R0,xxx Set value of arg xxx LA R1,FUNQABC Get service number - allow errors L R2,... Value to assign BALR R14,R5 Call service CH R15,=H'4' Is arg present/output? BC ... Handle condition
Special input registers for these services are:
R2 | Value to assign. |
---|
Output registers for these services are:
R15 | 0: Assignment successful. 4: Assignment failed: arg omitted. 8: Assignment failed: arg is not output. |
---|
For FUNQABS, since the non-0 cases for R15 cause the Fast/Unload program to be terminated, if the service returns then R15 will be 0.
Allocate storage
This pair of services allocates dynamic storage, above (FUNQGMA) or below (FUNQGMB) the 16 meg line, respectively.
They are invoked as follows:
LA R0,... Length of storage to allocate LA R2,=C'... Label for storage LA R1,FUNQGMB Get service number - below 16 MB BALR R14,R5 Call service
or
LA R0,... Length of storage to allocate LA R2,=C'... Label for storage LA R1,FUNQGMA Get service number - above 16 MB BALR R14,R5 Call service
Special input registers for these services are:
R0 | Length of storage in bytes. |
---|---|
R2 | Address of 8 character eyecatcher for storage. |
Output registers for these services are:
R1 | Address of storage allocated. |
---|
If the storage is not available, the FUEL program is terminated (i.e., the service does not return).
Release storage
This service releases a block of storage which was previously allocated (partial blocks may not be released).
It is invoked as follows:
LR R0,... Address of storage to release LA R1,FUNQFM Get service number BALR R14,R5 Call service
Special input registers for this service are:
R0 | Address of storage to release. |
---|
This service has no output registers.
Issue an error message and/or set return code
This service issues the FUNL0111 message, with the specified text, and/or changes the Fast/Unload program return code.
The FUNQMSG service is invoked in a variety of ways. To issue a message without changing the current return code:
LA R0,MSG Address of message text LA R1,FUNQMSG Get service number LA R2,L'MSG Length of message text SLR R3,R3 Indicate no change to return code BALR R14,R5 Call service
To issue a message and ensure that the return code is set at least as large as a supplied value:
LA R0,MSG Address of message text LA R1,FUNQMSG Get service number LA R2,L'MSG Length of message text LA R3,value Set minimum return code BALR R14,R5 Call service ST R15,xxx(,RD) Save prior value of return code
To ensure that the return code is set at least as large as a supplied value, without printing a message:
LA R1,FUNQMSG Get service number SLR R2,R2 Indicate no message text BCTR R2,0 Optionally suppress FUNL0111 LA R3,value Set minimum return code BALR R14,R5 Call service ST R15,xxx(,RD) Save prior value of return code
To force return code to specific value, without regard to previous value, with or without printing a message:
LA R1,FUNQMSG Get service number IF ... Message desired LA R0,MSG Address of message text LA R2,L'MSG Length of message text ELSE , No message SLR R2,R2 No message text, but FUNL0111 BCTR R2,0 Eliminate FUNL0111 header as well ENDIF , LH R3,=H'-1' Change return code in any case LA R4,value Set new return code BALR R14,R5 Call service ST R15,xxx(,RD) Save prior value of return code
Special input registers for this service are:
R0 | Address of message. |
---|---|
R2 | Length of message; if less than 0, message not issued. Must be less than 256. Trailing blanks preserved. |
R3 | 0: do not change return code. > 0: change return code to this value if it is less than that value. < 0: change return code to value in R4, regardless. |
R4 | New return code, if R3 less than 0. |
Output registers for this service are:
R15 | Prior value of return code. |
---|
Terminate Fast/Unload., optionally set return code
This service terminates Fast/Unload, and optionally changes the Fast/Unload program return code.
The FUNQTRM service is invoked in a variety of ways. To terminate the current run without changing the return code:
LA R1,FUNQTRM Get service number SLR R3,R3 Indicate no change to return code BALR R14,R5 Call service
To terminate the current run and ensure that the return code is at least as high as a provided number:
LA R1,FUNQTRM Get service number LA R3,value Set minimum return code BALR R14,R5 Call service
To terminate the current run and set the return code to a given value without regard to its previous value:
LA R1,FUNQTRM Get service number LH R3,=H'-1' Change return code in any case LA R4,value Set return code BALR R14,R5 Call service
Special input registers for this service are:
R0 | Unused. |
---|---|
R3 | 0: do not change return code. > 0: change return code to value in R3 if it is less than that value. < 0: change return code to value in R4, regardless. |
R4 | New return code, if R3 less than 0. |
This service does not return.
Example - z/OS
This example demonstrates use of the sample #function package contained on the distribution tape, in the z/OS environment.
Installing a #function package
This step consists of assembling and link-editing a #function package.
//ASMLINK EXEC ASMCL //ASM.SYSIN DD DISP=SHR,DSN=SIRIUS.LIB(UFUN) Sample package //ASM.SYSLIB DD DISP=SHR,DSN=SIRIUS.LIB FUNCEQU macro //LINK.SYSLMOD DD DISP=(NEW,CATLG),DSN=USER.FUNCPKG //LINK.SYSIN DD * NAME LOCFUNCS(R) /*
Using a #function package
Shown here are the changes to the Fast/Unload JCL and FUEL needed to use a #function package.
//FUNLOAD EXEC PGM=FUNLOAD //... Normal JCL //FUNCPKG DD DISP=SHR,DSN=USER.FUNCPKG Custom package //FUNIN DD * FUNCTIONS IN FUNCPKG LOCFUNCS OPEN PEOPLE FOR EACH RECORD %PALINDROME = #RVRSTR(NAME) %PALINDROME = #CONCAT(NAME, %PALINDROME) PUT %PALINDROME OUTPUT END FOR
Example - CMS
This example demonstrates use of the sample #function package contained on the distribution tape, in the CMS environment.
Installing a #function package
This step consists of assembling a #function package.
* Create a macro library with FUNCEQU: MACLIB GEN FUNLOAD FUNCEQU * Assemble the package: GLOBAL MACLIB FUNCEQU HASM UFUN
Using a #function package
If the TEXT file created in the preceding step is on an accessed CMS minidisk, you can use the following FUNIN file:
FUNCTIONS UFUN OPEN PEOPLE FOR EACH RECORD %PALINDROME = #RVRSTR(NAME) %PALINDROME = #CONCAT(NAME, %PALINDROME) PUT %PALINDROME OUTPUT END FOR