In-Depth
Codename: Callable - Enhancing COBOL Programs Through Language Environment Callable Services
Language Environment (LE) is IBM’s common runtime environment for programs written in C, COBOL, Fortran, PL/I and Assembler in the OS/390, VM and VSE operating systems. A component of LE is a suite of utility programs referred to as "Callable Services," whose capabilities can be accessed from any supported, higher-level language. There are almost 100 Callable Services listed in the documentation in such areas as date and time conversion, mathematical calculation, storage management, condition handling and message handling.
This article illustrates how to use Language Environment Callable Services in a COBOL program to perform tasks that are otherwise outside the scope of the language. To demonstrate the capabilities of Callable Services, I selected eight tasks for which there is no facility in COBOL. I will provide the data definitions and program code to illustrate how to accomplish these tasks in a COBOL program through the use of Callable Services. This applies to programs executed on the OS/390 and VM operating systems. The coding for COBOL programs executed under VSE is similar.
A batch or CICS program compiled using the COBOL/370, COBOL for MVS & VM, or COBOL for OS/390 & VM compilers can access all LE Callable Services through either a static or dynamic call. According to the IBM documentation, calls to LE from programs compiled using the VS COBOL II compiler are supported only for date and time services, and then only through a dynamic call. Calls to LE from programs compiled using compilers older than VS COBOL II are not supported for any services.
Editor’s Note: You can find IBM’s documentation for Language Environment for OS/390 and VM in the following manuals: SC28-1939 – Language Environment Programming Guide; SC28-1940 – Language Environment Programming Reference; or at www.s390.ibm.com/le/library/library.html. You can find IBM’s documentation for Language Environment for VSE in the following manual: SC26-8065 – Language Environment Programming Guide. The IBM Web site for LE/VSE is www.s390.ibm.com/le_vse.
Invoking LE Callable Service
Callable Service is invoked through a standard COBOL CALL. The documentation for each service specifies the parameters to include in the call. For example, to determine the day of the week on which a date falls, call program ‘CEEDYWK’ and include a field containing the date in Lilian format, a field to receive the day number, and a field to receive the return code from LE.
CALL ‘CEEDYWK’ USING LILIAN-DATE,
DAY-NUMBER,
FEEDBACK-CODE.
The feedback-code field is optional, but I recommend that you include it. You should interrogate the feedback-code in your COBOL program to ascertain whether the LE program you called completed successfully. If you omit the feedback-code and the LE program did not complete successfully, LE will abend your program. IBM defines the feedback-code as follows:
01 FC.
02 Condition-Token-Value.
COPY CEEIGZCT.
03 Case-1-Condition-ID.
04 Severity PIC S9(4) Binary.
04 Msg-No PIC S9(4) Binary.
03 Case-2-Condition-ID
REDEFINES Case-1-Condition-ID.
04 Class-Code PIC S9(4) Binary.
04 Cause-Code PIC S9(4) Binary.
03 Case-Sev-Ctl PIC X.
03 Facility-ID PIC XXX.
02 I-S-Info PIC S9(9) Binary.
In the examples below, only the first two fields are referenced, so the feedback-code is defined as follows:
01 FEEDBACK-CODE.
05 FC-SEVERITY PIC S9(4) Binary.
05 FC-MESSAGE PIC S9(4) Binary.
05 FILLER PIC X(08).
This data definition applies to all the examples below, except #8 where no feedback-code is included.
The LE documentation lists the feedback-codes that can be returned by each service. A value of zero in FC-SEVERITY means the LE program completed successfully. A value other than zero means that the LE program did not complete successfully. If FC-SEVERITY is not zero, then FC-MESSAGE will contain a message number identifying the nature of the problem.
1. Dynamically Acquire and Free Storage
Call program ‘CEEGTST’ to dynamically acquire storage. Include fields specifying the Heap-ID and the number of bytes of storage to acquire, a field to receive the address of the storage, and the feedback-code. (‘Heap-ID’ identifies an area from which requests for storage are satisfied. The default is Heap-ID 0). The field for which you acquire storage must be defined in the Linkage Section, not the Working-Storage Section.
WORKING-STORAGE SECTION.
01 GET-STORAGE-WORK-FIELDS.
05 HEAP-ID PIC S9(9) BINARY VALUE +0.
05 STORAGE-SIZE PIC S9(9) BINARY VALUE +0.
05 STORAGE-ADDRESS POINTER.
LINKAGE SECTION.
01 DYNAMICALLY-ALLOCATED-TABLE.
05 TABLE-DATA OCCURS 10 TIMES PIC X(100).
PROCEDURE DIVISION.
MOVE +0 TO HEAP-ID.
MOVE +1000 TO STORAGE-SIZE.
CALL ‘CEEGTST’ USING HEAP-ID,
STORAGE-SIZE,
STORAGE-ADDRESS,
FEEDBACK-CODE.
IF FC-SEVERITY = +0 AND
FC-MESSAGE = +0
SET ADDRESS OF DYNAMICALLY-ALLOCATED-TABLE
TO STORAGE-ADDRESS
ELSE
PERFORM ERROR-RTN.
Call program ‘CEEFRST’ to free storage acquired by program ‘CEEGTST.’ Include the address of the storage to free and the feedback-code. Storage that you don’t explicitly free is released by LE when the job step ends.
PROCEDURE DIVISION.
CALL ‘CEEFRST’ USING STORAGE-ADDRESS,
FEEDBACK-CODE.
IF FC-SEVERITY = +0 AND
FC-MESSAGE = +0
CONTINUE
ELSE
PERFORM ERROR-RTN.
2. Retrieve PARM String from JCL in a Called Program
Call program ‘CEE3PRM’ to retrieve the PARM string from the JCL. Include an 80 byte field to receive the PARM value, along with the feedback-code. If the PARM is spaces or if there is no PARM included in the JCL, ‘CEE3PRM’ returns spaces and sets FC-SEVERITY to +0. If the PARM is more than 80 bytes, ‘CEE3PRM’ returns the first 80 bytes and sets FC-SEVERITRY to +1. ‘CEE3PRM’ will return spaces in WS-PARM if the program that invokes the called module is not COBOL (e.g., IKJEFT01).
You can also call ‘CEE3PRM’ from a main program (the one whose name appears in the PGM= statement in the JCL) to retrieve the PARM string. It would be simpler, however, to access the PARM in the conventional manner by defining a field to receive the PARM in the Linkage Section and establishing addressability to that area through the USING parameter on the Procedure Division header.
WORKING-STORAGE SECTION.
01 WS-PARM PIC X(80) VALUE SPACES.
PROCEDURE DIVISION.
CALL ‘CEE3PRM’ USING WS-PARM,
FEEDBACK-CODE.
IF FC-SEVERITY = +0 AND
FC-MESSAGE = +0
CONTINUE
ELSE
IF FC-SEVERITY = +1
DISPLAY ‘PARM FROM CEE3PRM WAS TRUNCATED TO 80 BYTES’
ELSE
PERFORM ERROR-RTN.
3. Determine Date Validity
Call program ‘CEEDAYS’ to determine whether a date is valid. Include a field containing the format of the date, a field containing the date itself, a fullword binary field to return the date in Lilian format, and the feedback code.
‘CEEDAYS’ can validate a date in the range of October 15, 1582 through December 31, 9999. A valid date is one in which the year is within a reasonable range, the month is in the range of 01 through 12, and the days are appropriate to the month in question. The purpose of ‘CEEDAYS’ is to convert a date into Lilian format (the number of days since the adoption of the Gregorian calendar on October 15, 1582). As part of the process, ‘CEEDAYS’ first confirms that the date passed to it is valid, and returns +3 in FC-SEVERITY if the date is not valid. You can use this facility as a simple, conclusive means to determine whether a date is valid.
Indicate the format of the date to be validated and the length of the format picture string in the fields under PICTURE-STRING. (The LE documentation explains how to define the format of a date.) Set the length of the date to be validated in CHAR-STRING-LENGTH and move the date to CHAR-STRING-TEXT. The date to be validated must be in display or zoned-decimal format (not binary or packed-decimal).
WORKING-STORAGE SECTION.
01 PICTURE-STRING.
05 PIC-STRING-LENGTH PIC S9(4) BINARY.
05 PIC-STRING-TEXT.
10 PIC-STRING-CHAR PIC X(001)
OCCURS 0 TO 256 TIMES
DEPENDING ON PIC-STRING-LENGTH.
01 CHARACTER-STRING.
05 CHAR-STRING-LENGTH PIC S9(4) BINARY.
05 CHAR-STRING-TEXT.
10 CHAR-STRING-CHAR PIC X(001)
OCCURS 0 TO 256 TIMES
DEPENDING ON CHAR-STRING-LENGTH.
01 LILIAN-DATE PIC S9(9) BINARY.
01 DATE-TO-TEST PIC 9(08).
PROCEDURE DIVISION.
MOVE +8 TO PIC-STRING-LENGTH.
MOVE ‘YYYYMMDD’ TO PIC-STRING-TEXT.
MOVE +8 TO CHAR-STRING-LENGTH.
MOVE DATE-TO-TEST TO CHAR-STRING-TEXT.
CALL ‘CEEDAYS’ USING CHARACTER-STRING,
PICTURE-STRING,
LILIAN-DATE,
FEEDBACK-CODE.
IF FC-SEVERITY = +0 AND
FC-MESSAGE = +0
CONTINUE
ELSE
PERFORM INVALID-DATE-RTN.
4. Convert a Julian or Gregorian Date to Report Format
Call program ‘CEEDATE’ to convert a date to report format. Include a field containing the date in Lilian format, a field describing how the output date should appear, a field to receive the converted date, and the feedback code. Refer to the LE documentation for a complete list of the picture strings you can use with ‘CEEDATE’ to define the appearance of the output date.
WORKING-STORAGE SECTION.
01 PICTURE-STRING.
05 PIC-STRING-LENGTH PIC S9(4) BINARY.
05 PIC-STRING-TEXT.
10 PIC-STRING-CHAR PIC X(001)
OCCURS 0 TO 256 TIMES
DEPENDING ON PIC-STRING-LENGTH.
01 CHARACTER-STRING.
05 CHAR-STRING-LENGTH PIC S9(4) BINARY.
05 CHAR-STRING-TEXT.
10 CHAR-STRING-CHAR PIC X(001)
OCCURS 0 TO 256 TIMES
DEPENDING ON CHAR-STRING-LENGTH.
01 REPORT-DATE PIC X(30).
01 LILIAN-DATE PIC S9(9) BINARY.
01 GREGORIAN-DATE PIC 9(08) VALUE 19990407.
PROCEDURE DIVISION.
*-------------------------------------------------------------------------*
* BEGIN BY CONVERTING THE INPUT DATE FROM GREGORIAN TO LILIAN FORMAT. *
* IF THE INPUT DATE WERE IN JULIAN FORMAT, USE ‘YYYYDDD’ AS THE *
* VALUE IN PIC-STRING-TEXT AND MOVE +7 TO PIC-STRING-LENGTH AND *
* CHAR-STRING-LENGTH. *
*-------------------------------------------------------------------------*
MOVE +8 TO PIC-STRING-LENGTH.
MOVE ‘YYYYMMDD’ TO PIC-STRING-TEXT.
MOVE +8 TO CHAR-STRING-LENGTH.
MOVE GREGORIAN-DATE TO CHAR-STRING-TEXT.
CALL ‘CEEDAYS’ USING CHARACTER-STRING,
PICTURE-STRING,
LILIAN-DATE,
FEEDBACK-CODE.
IF FC-SEVERITY = +0 AND
FC-MESSAGE = +0
CONTINUE
ELSE
PERFORM ERROR-RTN.
*-------------------------------------------------------------------------*
* NOW CONVERT THE DATE TO REPORT FORMAT. HERE ARE EXAMPLES OF PICTURE *
* STRINGS YOU CAN SUPPLY TO ‘CEEDATE’ AND HOW 19990407 WOULD BE CONVERTED*
* FROM LILIAN FORMAT USING THAT STRING: *
* *
* ‘MMMMMMMMM DD, YYYY’ APRIL 07, 1999 *
* ‘MMMMMMMMZ DD, YYYY’ APRIL 07, 1999 *
* ‘MMMMMMMMZ ZD, YYYY’ APRIL 7, 1999 *
* ‘WWW MMM DD, YYYY’ WED APR 07, 1999 *
* ‘WWWWWWWWW MMMMMMMMM DD, YYYY’ WEDNESDAY APRIL 07, 1999 *
* ‘WWWWWWWWZ MMMMMMMMZ ZD, YYYY WEDNESDAY APRIL 7, 1999 *
* ‘Wwwwwwwwz Mmmmmmmmz ZD, YYYY Wednesday April 7, 1999 *
* *
* A VALUE OF ‘M’ IN A PICTURE REPRESENTS MONTH, ‘D’ REPRESENTS DAY, AND *
* ‘Y’ REPRESENTS YEAR. ‘Z’ SUPPRESSES TRAILING SPACES IN THE ‘MONTH’ *
* PICTURE AND LEADING ZEROES IN THE ‘DAY’ PICTURE. *
*-------------------------------------------------------------------------*
MOVE +28
TO PIC-STRING-LENGTH.
MOVE ‘WWWWWWWWZ MMMMMMMMZ ZD,
YYYY’ TO PIC-STRING-TEXT.
CALL ‘CEEDATE’ USING LILIAN-DATE,
PICTURE-STRING,
REPORT-DATE,
FEEDBACK-CODE.
IF FC-SEVERITY = +0 AND
FC-MESSAGE = +0
CONTINUE
ELSE
PERFORM INVALID-DATE-RTN.
5. Get the Current Greenwich Mean Time
Call ‘CEEGMT’ to get the current Greenwich Mean Time. ‘CEEGMT’ returns the Greenwich Mean Time in two formats: Lilian days (the number of days since October 15, 1582) and Lilian seconds (the number of seconds since October 15, 1582.)
Call program ‘CEEDATM’ to convert the Lilian seconds into a date in displayable format.
WORKING-STORAGE SECTION.
01 LILIAN-WORK-FIELDS.
05 LILIAN-DAYS PIC S9(9) BINARY.
05 LILIAN-SECONDS COMP-2.
01 DATE-DISPLAY PIC X(30).
01 PICTURE-STRING.
05 PIC-STRING-LENGTH PIC S9(4) BINARY.
05 PIC-STRING-TEXT.
10 PIC-STRING-CHAR PIC X(001)
OCCURS 0 TO 256 TIMES
DEPENDING ON PIC-STRING-LENGTH.
PROCEDURE DIVISION.
*------------------------------------------------------------------------*
* GET THE GMT IN LILIAN DAYS AND LILIAN SECONDS.*
*------------------------------------------------------------------------*
CALL ‘CEEGMT’ USING LILIAN-DATE,
LILIAN-SECONDS,
FEEDBACK-CODE.
IF FC-SEVERITY = +0 AND
FC-MESSAGE = +0
CONTINUE
ELSE
PERFORM ERROR-RTN.
*-------------------------------------------------------------------------*
• CONVERT THE GMT FROM LILIAN SECONDS INTO A DISPLAYABLE FORMAT. *
• BASED ON THE PATTERN SPECIFIED IN PIC-STRING- TEXT, THE RETURNED *
• DATE WILL LOOK LIKE THIS: 04/07/1999 02:31:02 AM *
*-------------------------------------------------------------------------*
MOVE +22 TO PIC-STRING-LENGTH.
MOVE ‘MM/DD/YYYY HH:MI:SS AP’ TO
PICSTRING-TEXT.
CALL ‘CEEDATM’ USING LILIAN-SECONDS,
PICTURE-STRING,
DATE-DISPLAY,
FEEDBACK-CODE.
IF FC-SEVERITY = +0 AND
FC-MESSAGE = +0
CONTINUE
ELSE
PERFORM ERROR-RTN.
6. Determine the Day of the Week on Which a Date Falls
Call ‘CEEDYWK’ to determine the day of the week on which a date falls. Include a fullword binary field containing the date in Lilian format, a fullword to return the day number, and the feedback-code. ‘CEEDYWK’ returns a number from 1 through 7, where Sunday is 1, Tuesday is 2, Wednesday is 3, etc.
WORKING-STORAGE SECTION.
01 PICTURE-STRING.
05 PIC-STRING-LENGTH PIC S9(4) BINARY.
05 PIC-STRING-TEXT.
10 PIC-STRING-CHAR PIC X(001)
OCCURS 0 TO 256 TIMES
DEPENDING ON PIC-STRING-LENGTH.
01 CHARACTER-STRING.
05 CHAR-STRING-LENGTH PIC S9(4) BINARY.
05 CHAR-STRING-TEXT.
10 CHAR-STRING-CHAR PIC X(001)
OCCURS 0 TO 256 TIMES
DEPENDING ON CHAR-STRING-LENGTH.
01 DATE-WORK-FIELDS.
05 LILIAN-DATE PIC S9(9) BINARY.
05 DAY-NUMBER PIC S9(9) BINARY.
01 DATE-TO-TEST PIC 9(08).
PROCEDURE DIVISION.
*-------------------------------------------------------------------------*
* BEGIN BY CONVERTING DATE-TO-TEST FROM GREGORIAN TO LILIAN FORMAT. *
*-------------------------------------------------------------------------*
MOVE +8 TO PIC-STRING-LENGTH.
MOVE ‘YYYYMMDD’ TO PIC-STRING-TEXT.
MOVE +8 TO CHAR-STRING-LENGTH.
MOVE DATE-TO-TEST TO CHAR-STRING-TEXT.
CALL ‘CEEDAYS’ USING CHARACTER-STRING,
PICTURE-STRING,
LILIAN-DATE,
FEEDBACK-CODE.
IF FC-SEVERITY = +0 AND
FC-MESSAGE = +0
CONTINUE
ELSE
PERFORM ERROR-RTN.
*-------------------------------------------------------------------------*
* NOW DETERMINE ON WHICH DAY OF THE WEEK THIS DATE FALLS. *
*-------------------------------------------------------------------------*
CALL ‘CEEDYWK’ USING LILIAN-DATE,
DAY-NUMBER,
FEEDBACK-CODE.
IF FC-SEVERITY = +0 AND
FC-MESSAGE = +0
CONTINUE
ELSE
PERFORM ERROR-RTN.
7. Generate a Snap Dump
Call ‘CEE3DMP’ to generate a snap dump. (In VSE the program name is ‘CEE5DMP.’) A snap dump is a debugging tool that gives you a snapshot of a program’s storage at a particular point in its processing. After the snap dump is taken, the program resumes executing, as opposed to an abend dump after which the program terminates.
Include a title which appears on the top of each page of the dump with your call to ‘CEE3DMP.’ This is helpful if you decide to generate snap dumps from several points in the program logic. You can also include parameters to tailor the information written to the dump and to specify a DDNAME to which the dump is written. (The documentation for ‘CEE3DMP’ lists the options you can specify.) In the example below, ‘CEE3DMP’ will dump the storage for the current program only (the one which calls ‘CEE3DMP’) and will write the dump to DDNAME ‘SNAPDUMP.’
WORKING-STORAGE SECTION.
01 SNAP-DUMP-FIELDS.
05 DUMP-TITLE PIC X(80) VALUE SPACES.
05 DUMP-OPTIONS PIC X(255) VALUE SPACES.
PROCEDURE DIVISION.
MOVE ‘SNAP DUMP FROM THE END OF THE READ ROUTINE’
TO DUMP-TITLE.
MOVE ‘ENCLAVE(CURRENT) VARIABLES STORAGE FNAME(SNAPDUMP)’
TO DUMP-OPTIONS.
CALL ‘CEE3DMP’ USING DUMP-TITLE,
DUMP-OPTIONS,
FEEDBACK-CODE.
IF FC-SEVERITY = +0 AND
FC-MESSAGE = +0
CONTINUE
ELSE
PERFORM ERROR-RTN.
8. Generate a User Abend of a Program
Call ‘CEE3ABD’ to abnormally end your program. (In VSE the program name is ‘CEE5ABD.’) Include a fullword binary field containing the abend code in the range of 0 thru 4095 and a fullword binary field containing a value of +0 or +1, indicating whether to suppress the Language Environment dump. A value of +0 in ABEND-CLEANUP suppresses the LE dump while a value of +1 permits the dump. In either case, the operating system or third-party dump package such as Abend-Aid will generate its own dump. Don’t include the feedback-code in a call to ‘CEE3ABD.’ ‘CEE3ABD’ will abend your job and control, therefore, will not return to the calling program.
WORKING-STORAGE SECTION.
01 ABEND-FIELDS.
05 ABEND-CODE PIC S9(9) BINARY.
05 ABEND-CLEANUP PIC S9(9) BINARY.
PROCEDURE DIVISION.
*----------------------------------------------------------------------------*
* ABEND THE PROGRAM WITH CODE 1234 AND SUPPRESS THE LE DUMP *
*----------------------------------------------------------------------------*
MOVE +1234 TO ABEND-CODE.
MOVE +0 TO ABEND-CLEANUP.
CALL ‘CEE3ABD’ USING ABEND-CODE,
ABEND-CLEANUP.