This program demonstrates some typical steps in creating a program that uses several ILE and OPM programming languages.
The program is a small transaction-processing program that takes as input the item name, price, and quantity for one or more products. As output, the program displays the total cost of the items specified on the display and writes an audit trail of the transactions to a file.
Figure 270 shows the basic flow of the program.
Figure 270. ILE-OPM CL Example: Basic Program Structure
![]() |
The program consists of these components:
The ILE C++ program T2123IC5 is created with the CRTPGM default for the ACTGRP parameter, ACTGRP(*NEW). When the CL program calls the ILE C++ program, a new activation group is started.
The OPM CL, COBOL, and RPG programs are activated within the OPM default activation group.
Figure 271 shows the structure of this program in ILE.
Figure 271. Structure of the Program in ILE C++
![]() |
The source code for each of the files that compose this program are an externally described file, a CL program, a CL command prompt, a C++ source file, and OPM COBOL program and an OPM RPG program.
The file T2123DD2 contains the audit trail for the C++ program T2123IC5. The DDS source defines the fields for the audit file:
R T2123DD2R USER 10 COLHDG('User') ITEM 20 COLHDG('Item name') PRICE 10S 2 COLHDG('Unit price') QTY 4S COLHDG('Number of items') TXRATE 2S 2 COLHDG('Current tax rate') TOTAL 21 COLHDG('Total cost') DATE 6 COLHDG('Transaction date') K USER
The CL program T2123CL2 passes the CL variables item_name, price, quantity and user_id by reference to an ILE C++ program T2123IC5.
PGM PARM(&ITEMIN &PRICE &QUANTITY) DCL VAR(&USER) TYPE(*CHAR) LEN(10) DCL VAR(&USEROUT) TYPE(*CHAR) LEN(11) DCL VAR(&ITEMIN) TYPE(*CHAR) LEN(20) DCL VAR(&ITEMOUT) TYPE(*CHAR) LEN(21) DCL VAR(&PRICE) TYPE(*DEC) LEN(10 2) DCL VAR(&QUANTITY) TYPE(*DEC) LEN(2 0) DCL VAR(&NULL) TYPE(*CHAR) LEN(1) VALUE(X'00') /* ADD NULL TERMINATOR FOR THE ILE C PROGRAM */ CHGVAR VAR(&ITEMOUT) VALUE(&ITEMIN *TCAT &NULL) CHGVAR VAR(&USEROUT) VALUE(&USER *TCAT &NULL) /* GET THE USERID FOR THE AUDIT FILE */ RTVJOBA USER(&USER) /* ENSURE AUDIT RECORDS WRITTEN TO CORRECT AUDIT FILE MEMBER */ OVRDBF FILE(T2123DD2) TOFILE(*LIBL/T2123DD2) + MBR(T2123DD2) OVRSCOPE(*CALLLVL) SHARE(*NO) CALL PGM(T2123IC5) PARM(&ITEMOUT &PRICE &QUANTITY + &USEROUT) DLTOVR FILE(*ALL) ENDPGM
The Retrieve Job Attributes (RTVJOBA) command obtains the user ID for the audit trail. Arguments are passed by reference. They can be changed by the receiving ILE C++ program. The variables containing the user and item names are explicitly null-terminated in the CL program.
Notes:
You use the CL command prompt T2123CM2 to prompt the user to enter item names, prices, and quantities that will be used by the C++ program T2123IC5.
CMD PROMPT('CALCULATE TOTAL COST') PARM KWD(ITEM) TYPE(*CHAR) LEN(20) RSTD(*NO) + MIN(1) ALWUNPRT(*NO) PROMPT('Item name' 1) PARM KWD(PRICE) TYPE(*DEC) LEN(10 2) RSTD(*NO) + RANGE(0.01 99999999.99) MIN(1) + ALWUNPRT(*YES) PROMPT('Unit price' 2) PARM KWD(QUANTITY) TYPE(*INT2) RSTD(*NO) RANGE(1 + 9999) MIN(1) ALWUNPRT(*YES) + PROMPT('Number of items' 3)
The C++ source file T2123IC5 contains a main() function which receives the incoming arguments from the CL program T2123CL2. These arguments have been verified by the CL command prompt T2123CM2 and null-terminated within the CL program T2123CL2. All the incoming arguments are pointers.
The main() function calls the function CalcAndFormat() which is mapped to a COBOL name. It passes the price, quantity, taxrate, formatted_cost, and a success_flag to the OPM COBOL program T2123CB1 using the extern "OS nowiden" linkage specification, because the OPM COBOL program is not expecting widened parameters.
The formatted_cost and the success_flag values are updated in the C++ program T2123IC5.
If CalcAndFormat() returns successfully, a record is written to the audit trail by WriteAuditTrail() in the OPM RPG program.
The main() function in program T2123IC5 calls WriteAuditTrail() which is mapped to an RPG program name, and passes the user_id, item_name, price, quantity, taxrate, and formatted_cost, using the extern "OS" linkage specification.
// This program is called by a CL program that passes an item // name, price, quantity and user ID. // COBOL is called to calculate and format the total cost. // RPG is called to write an audit trail. #include <iostream.h> #include <stdlib.h> #include <string.h> #include <bcd.h> // The #pragma map directive maps a new program name to the existing // program name so that the purpose of the program is clear. // Tell the compiler that there are dynamic program calls so // arguments are passed by value-reference. extern "OS nowiden" void CalcAndFormat(_DecimalT <10,2>, short int, _DecimalT<2,2>, char[], char *); #pragma map(CalcAndFormat,"T2123CB1") extern "OS" void WriteAuditTrail(char[], char[] , _DecimalT<10,2>, short int, _DecimalT<2,2>, char[]); #pragma map(WriteAuditTrail,"T2123RP1") int main(int argc, char *argv[]) { // Incoming arguments from a CL program have been verified by // the *CMD and null-terminated within the CL program. // Incoming arguments are passed by reference from a CL program. char *user_id; char *item_name; short int quantity; _DecimalT <10, 2> price; _DecimalT <2,2> taxrate = __D(".15"); char formatted_cost[22]; // Remove null terminator for RPG program. Item name is null // terminated for C++. char rpg_item_name[20]; char null_formatted_cost[22]; char success_flag = 'N'; int i; // Incoming arguments are all pointers. item_name = argv[1]; price = *((_DecimalT<10, 2> *) argv[2]); quantity = *((short *) argv[3]); user_id = argv[4]; // Call the COBOL program to do the calculation, and return a // Y/N flag, and a formatted result. CalcAndFormat(price, quantity, taxrate, formatted_cost, &success_flag); memcpy(null_formatted_cost,formatted_cost,sizeof(formatted_cost)); // Null terminate the result. formatted_cost[21] = '\0'; if (success_flag == 'Y') { for (i=0; i<20; i++) { // Remove null terminator for the RPG program. if (*(item_name+i) == '\0') { rpg_item_name[i] = ' '; } else { rpg_item_name[i] = *(item_name+i); } } // Call an RPG program to write audit records. WriteAuditTrail(user_id, rpg_item_name, price, quantity, taxrate, formatted_cost); cout <<quantity <<item_name << "plus tax =" <<null_formatted_cost <<endl; } else { cout <<"Calculation failed" <<endl; } }
The OPM COBOL program T2123CB1 receives pointers to the values of the variables price, quantity and taxrate, and pointers to formatted_cost and success_flag.
The CalcAndFormat() function in program T2123CB1 calculates and formats the total cost. Parameters are passed from the ILE C++ program to the OPM COBOL program to do the tax calculation.
IDENTIFICATION DIVISION. PROGRAM-ID. T2123CB1. ****************************************************** * parameters: * * incoming: PRICE, QUANTITY * * returns : TOTAL-COST (PRICE*QUANTITY*1.TAXRATE) * * SUCCESS-FLAG. * ****************************************************** ENVIRONMENT DIVISION. 0 CONFIGURATION SECTION. 0 SOURCE-COMPUTER. IBM-ISERIES. 0 OBJECT-COMPUTER. IBM-ISERIES. 0 DATA DIVISION. 0 WORKING-STORAGE SECTION. 01 WS-TOTAL-COST PIC S9(13)V99 COMP-3. 01 WS-TAXRATE PIC S9V99 COMP-3. LINKAGE SECTION. 01 LS-PRICE PIC S9(8)V9(2) COMP-3. 01 LS-QUANTITY PIC S9(4) COMP-4. 01 LS-TAXRATE PIC SV99 COMP-3. 01 LS-TOTAL-COST PIC $$,$$$,$$$,$$$,$$$.99 DISPLAY. 01 LS-OPERATION-SUCCESSFUL PIC X DISPLAY. PROCEDURE DIVISION USING LS-PRICE 0 LS-QUANTITY LS-TAXRATE LS-TOTAL-COST LS-OPERATION-SUCCESSFUL. MAINLINE. MOVE "Y" TO LS-OPERATION-SUCCESSFUL. PERFORM CALCULATE-COST. PERFORM FORMAT-COST. EXIT PROGRAM. CALCULATE-COST. MOVE LS-TAXRATE TO WS-TAXRATE. ADD 1 TO WS-TAXRATE. COMPUTE WS-TOTAL-COST ROUNDED = LS-QUANTITY * LS-PRICE * WS-TAXRATE ON SIZE ERROR MOVE "N" TO LS-OPERATION-SUCCESSFUL END-COMPUTE. FORMAT-COST. MOVE WS-TOTAL-COST TO LS-TOTAL-COST.
The OPM RPG program T2123RP1 contains the WriteAuditTrail() function which writes the audit trail for the program.
FT2123DD2O E DISK A F T2123DD2R KRENAMEDD2R IQTYIN DS I B 1 40QTYBIN C *ENTRY PLIST C PARM USER 10 C PARM ITEM 20 C PARM PRICE 102 C PARM QTYIN C PARM TXRATE 22 C PARM TOTAL 21 C EXSR ADDREC C SETON LR C ADDREC BEGSR C MOVELUDATE DATE C MOVE QTYBIN QTY C WRITEDD2R C ENDSR
To enter data for the program T2123IC5 enter the command T2123CM2 and press F4 (Prompt).
You can enter this data into T2123CM2:
Hammers 1.98 5000 Nails 0.25 2000
The output is:
+--------------------------------------------------------------------------------+ | 5000 HAMMERS plus tax = $11,385.00 | | Press ENTER to end terminal session. | |> | | 2000 NAILS plus tax = $575.00 | | Press ENTER to end terminal session. | +--------------------------------------------------------------------------------+
The physical file T2123DD2 contains this data:
SMITHE HAMMERS 0000000198500015 $11,385.0007 2893 SMITHE NAILS 0000000025200015 $575.0007 2893
(C) Copyright IBM Corporation 1992, 2005. All Rights Reserved.