In this section: |
You can write a subroutine in any language that supports subroutines. If you intend to make your subroutine available to other users, be sure to document what your subroutine does, what the arguments are, what formats they have, and in what order they must appear in the subroutine call.
When you write a subroutine you need to consider the requirements and limits that affect it. These are:
If you write a program named INTCOMP that calculates the amount of money in an account earning simple interest, the program reads a record, tests if the data is acceptable, and then calls a subroutine called SIMPLE that computes the amount of money. The program and the subroutine are stored together in the same file.
The program and the subroutine shown here are written in pseudocode (a method of representing computer code in a general way):
Begin program INTCOMP. Execute this loop until end-of-file. Read next record, fields: PRINCPAL, DATE_PUT, YRRATE. If PRINCPAL is negative or greater than 100,000, reject record. If DATE_PUT is before January 1, 1975, reject record. If YRRATE is negative or greater than 20%, reject record. Call subroutine SIMPLE (PRINCPAL, DATE_PUT, YRRATE, TOTAL). Print PRINCPAL, YEARRATE, TOTAL. End of loop. End of program.
Subroutine SIMPLE (AMOUNT, DATE, RATE, RESULT). Retrieve today's date from the system. Let NO_DAYS = Days from DATE until today's date. Let DAY_RATE = RATE / 365 days in a year. Let RESULT = AMOUNT * (NO_DAYS * DAY_RATE + 1). End of subroutine.
If you move the SIMPLE subroutine into a file separate from the main program and compile it, you can call the subroutine. The following report request shows how much money employees would accrue if they invested salaries in accounts paying 12%:
TABLE FILE EMPLOYEE PRINT LAST_NAME DAT_INC SALARY AND COMPUTE INVESTED/D10.2 = SIMPLE(SALARY, DAT_INC, 0.12, INVESTED); BY EMP_ID END
Note: The subroutine is designed to return only the amount of the investment, not the current date because a subroutine can return only a single value each time it is called.
A subroutine name can be up to eight characters long unless the language you are using to write the subroutine requires a shorter name. A name must start with a letter and can consist of a combination of letters and/or numbers. Special symbols are not permitted.
When you create arguments for a subroutine, you must consider the following issues:
You should not assume that input parameters are stored in contiguous memory.
The lengths of the calling arguments as defined in WebFOCUS must match the lengths of the corresponding arguments defined in the subroutine.
Any deviation from these rules may result in problems in using the subroutine. Information Builders recommends that you modify the subroutine to conform to the stated rules and then link it above the line. In order to load subroutines above the line, the following are the required link-edit options for compiling and storing the subroutine:
When writing a subroutine, you must consider the following language issues:
Language and memory. If you write a subroutine in a language that brings libraries into memory (for example, FORTRAN and COBOL), the libraries reduce the amount of memory available to the subroutine.
FORTRAN. TSO supports FORTRAN input/output operations.
COBOL. When writing a subroutine in COBOL:
WebFOCUS Format |
Picture |
---|---|
An |
Xn |
I |
S9(9) COMP |
P |
S9(n)[V9(m)] where: (1+n+m)/2 = 8 for small packed numbers. (1+n+m)/2 = 16 for large packed numbers. |
D |
COMP-2 |
F |
COMP-1 |
PL/I. When writing a subroutine in PL/I:
OPTIONS (COBOL)
CHARACTER (n)
where:
Is the field length as defined by the request. Do not use the VARYING attribute.
DECIMAL FLOAT (16)
or
BINARY FLOAT (53)
WebFOCUS Format |
PL/I Declaration for Output |
---|---|
An |
CHARACTER (n) |
I |
BINARY FIXED (31) |
F |
DECIMAL FLOAT (6) or BINARY FLOAT (21) |
D |
DECIMAL FLOAT (16) or BINARY FLOAT (53) |
P |
DECIMAL FIXED (15) (for small packed numbers, 8 bytes) DECIMAL FIXED (31) (for large packed numbers, 16 bytes) |
C language. When writing a subroutine in C:
WebFOCUS Format |
C Declaration for Output |
---|---|
An |
char *xxx n Alphanumeric fields are not terminated with a null byte and cannot be processed by many of the string manipulation subroutines in the run-time library. |
I |
long *xxx |
F |
float *xxx |
D |
double *xxx |
P |
No equivalent in C. |
In this section: |
Consider the following when planning your programming requirements:
You can add flexibility to your subroutine by using a programming technique. A programming technique can be one of the following:
How to: |
A subroutine is usually executed starting from the first statement. However, a subroutine can be executed starting from any place in the code designated as an entry point. This enables a subroutine to use one basic algorithm to produce different results. For example, the DOWK subroutine calculates the day of the week on which a date falls. By specifying the subroutine name DOWK, you obtain a 3-letter abbreviation of the day. If you specify the entry name DOWKL, you obtain the full name. The calculation, however, is the same.
Each entry point has a name. To execute a subroutine at an entry point, specify the entry point name in the subroutine call instead of the subroutine name. How you designate an entry point depends on the language you are using.
{subroutine|entrypoint} (input1, input2,...outfield)
where:
Is the name of the subroutine.
Is the name of the entry point to execute the subroutine at.
Are the subroutine's arguments.
Is the field that contains the result, or the format of the output value enclosed in single quotation marks.
In Dialogue Manager, you must specify the format. In Maintain Data, you must specify the name of the field.
The FTOC subroutine, written in pseudocode below, converts Fahrenheit temperature to Centigrade. The entry point FTOK (designated by the Entry command) sets a flag that causes 273 to be subtracted from the Centigrade temperature to find the Kelvin temperature. The subroutine is:
Subroutine FTOC (FAREN, CENTI). Let FLAG = 0. Go to label X. Entry FTOK (FAREN, CENTI). Let FLAG = 1. Label X. Let CENTI = (5/9) * (FAREN - 32). If FLAG = 1 then CENTI = CENTI - 273. Return. End of subroutine.
The following is a shorter way to write the subroutine. Notice that the kelv output argument listed for the entry point is different from the centi output argument listed at the beginning of the subroutine:
Subroutine FTOC (FAREN, CENTI). Entry FTOK (FAREN, KELV). Let CENTI = (5/9) * (FAREN - 32). KELV = CENTI - 273. Return. End of Subroutine.
To obtain the Centigrade temperature, specify the subroutine name FTOC in the subroutine call. The subroutine processes as:
CENTIGRADE/D6.2 = FTOC (TEMPERATURE, CENTIGRADE);
To obtain the Kelvin temperature, specify the entry name FTOK in the subroutine call. The subroutine processes as:
KELVIN/D6.2 = FTOK (TEMPERATURE, KELVIN);
How to: |
A subroutine can specify a maximum of 200 arguments including the output argument. To process more than 200 arguments, the subroutine must specify two or more call statements to pass the arguments to the subroutine.
Use the following technique for writing a subroutine with multiple calls:
The argument list in the beginning of your subroutine must represent the same number of arguments in the subroutine call, including a call number argument and an output argument.
Each call contains the same number of arguments. This is because the argument list in each call must correspond to the argument list in the beginning of the subroutine. You may process some of the arguments as dummy arguments if you have an unequal number of arguments. For example, if you divide 32 arguments among six segments, each segment processes six arguments; the sixth segment processes two arguments and four dummy arguments.
Subroutines may require additional arguments as determined by the programmer who creates the subroutine.
End each segment with a command returning control back to the request (RETURN command).
You can also use the entry point technique to write subroutines that process more than 200 arguments. For details, see Executing a Subroutine at an Entry Point.
field = subroutine (1, group1, field) ;field = subroutine (2, group2, field); . . .outfield = subroutine (n, groupn, outfield);
where:
Is the name of the field that contains the result of the segment or the format of the field enclosed in single quotation marks. This field must have the same format as outfield.
Do not specify field for the last call statement; use outfield.
Is the name of the subroutine up to eight characters long.
Is a number that identifies each subroutine call. It must be the first argument in each subroutine call. The subroutine uses this call number to branch to segments of code.
Are lists of input arguments passed by each subroutine call. Each group contains the same number of arguments, and no more than 26 arguments each.
The final group may contain dummy arguments.
Is the field that contains the result, or the format of the output value enclosed in single quotation marks.
In Dialogue Manager, you must specify the format. In Maintain Data, you must specify the name of the field.
The ADD32 subroutine, written in pseudocode, sums 32 numbers. It is divided into six segments, each of which adds six numbers from a subroutine call. (The total number of input arguments is 36 but the last four are dummy arguments.) The sixth segment adds two arguments to the SUM variable and returns the result. The sixth segment does not process any values supplied for the four dummy arguments.
The subroutine is:
Subroutine ADD32 (NUM, A, B, C, D, E, F, TOTAL). If NUM is 1 then goto label ONE else if NUM is 2 then goto label TWO else if NUM is 3 then goto label THREE else if NUM is 4 then goto label FOUR else if NUM is 5 then goto label FIVE else goto label SIX. Label ONE. Let SUM = A + B + C + D + E + F. Return. Label TWO Let SUM = SUM + A + B + C + D + E + F Return Label THREE Let SUM = SUM + A + B + C + D + E + F Return Label FOUR Let SUM = SUM + A + B + C + D + E + F Return Label FIVE Let SUM = SUM + A + B + C + D + E + F Return Label SIX LET TOTAL = SUM + A + B Return End of subroutine
To use the ADD32 subroutine, list all six call statements, each call specifying six numbers. The last four numbers, represented by zeros, are dummy arguments. The DEFINE command stores the total of the 32 numbers in the SUM32 field.
DEFINE FILE EMPLOYEE DUMMY/D10 = ADD32 (1, 5, 7, 13, 9, 4, 2, DUMMY); DUMMY/D10 = ADD32 (2, 5, 16, 2, 9, 28, 3, DUMMY); DUMMY/D10 = ADD32 (3, 17, 12, 8, 4, 29, 6, DUMMY); DUMMY/D10 = ADD32 (4, 28, 3, 22, 7, 18, 1, DUMMY); DUMMY/D10 = ADD32 (5, 8, 19, 7, 25, 15, 4, DUMMY); SUM32/D10 = ADD32 (6, 3, 27, 0, 0, 0, 0, SUM32); END