If the CL procedure is to send a message to an OPM program or another ILE procedure, you must identify the call stack entry to which the message is sent. The message is sent to the call message queue of the identified call stack entry.
The TOPGMQ parameter of the SNDPGMMSG command is used to identify the call stack entry to which a message is sent. Identification of a call stack entry consists of the following two parts:
The specification TOPGMQ(*PRV *) identifies the base entry as being the one in which the procedure using the SNDPGMMSG command is running. The offset is specified as being one entry previous to that base. This specification identifies the caller of the procedure which is using the command.
The offset specification (element 1 of TOPGMQ) identifies if you send the message to the base (*SAME) or if you send the message to the caller of the base (*PRV).
To understand how to identify the base entry, element 2 of TOPGMQ, you also need to understand the call stack when an ILE program is running. Two programs are used to illustrate this. Program CLPGM1 is an OPM CL program and Program CLPGM2 is an ILE program. Since program CLPGM2 is ILE, it can consist of several procedures, such as: CLPROC1, CLPROC2, CLPROC3, and CLPROC4. At runtime the following calls take place:
See Figure 8-1 to understand the structure of the call stack when CLPROC2 calls CLPROC4. This figure illustrates the following considerations:
Following are different ways of specifying the base call stack entry.
Procedure Using the Command as the Base
If the TOPGMQ parameter specifies either TOPGMQ(*SAME *) or TOPGMQ(*PRV *), the entry for the procedure using the SNDPGMMSG command is used as the base. If TOPGMQ(*SAME *) is specified, the procedure will send a message to itself. If TOPGMQ(*PRV *) is specified, the procedure will send a message to the caller.
Figure 8-2 illustrates the results when CLPROC1, CLPROC2, and CLPROC4 each send a message back to the caller of each procedure.
Figure 8-1. Example of runtime call stack
![]() |
Figure 8-2. Example of TOPGMQ(*PRV *)
![]() |
Identifying the Base Entry by Name
You can identify the base entry by providing the name of the OPM program or ILE procedure running in that entry. The name provided is either a simple name (one part) or a complex name (two or three parts). Following are descriptions of the simple and complex names:
A simple name is used to identify an OPM program or an ILE procedure. If the simple name you provide is 10 characters or less in length, it is determined by the system that the name is either an OPM program or an ILE procedure. The base is identified as the most recently called OPM program or ILE procedure by that name.
If the name is longer than 10 characters in length, it is determined by the system that the name is for an ILE procedure (OPM program names cannot be longer than 10 characters). The base is identified as the entry for the most recently called procedure by that name. Entries running OPM programs are not considered.
See Figure 8-3 for an example of sending a message using a simple name. In this example, CLPROC4 is sending a message to CLPROC2 and CLPROC2 is sending a message to CLPGM1.
A complex name consists of two or three parts. They are:
The module name is the name of the module into which the procedure was compiled.
The program name is the name of the program into which the procedure was bound.
When you want to uniquely identify the procedure to which you want to send the message, a complex name can be used in one of the following combinations:
You must specify the module name as *NONE.
If you use a complex name, the base being identified cannot be running an OPM program.
See Figure 8-4 for an example of sending a message using a complex name. In this example, CLPROC4 is sending a message to CLPROC1 using a two part name consisting of (procedure name, program name).
Rather than using the full OPM program name or the full ILE procedure name, you may use partial names. IBM provides online information concerning how to specify partial call stack entry names. Refer to the CL section of the Programming category in the iSeries Information Center for this information.
Figure 8-3. Example of using a simple name
![]() |
Figure 8-4. Example of using a complex name
![]() |
Program Boundary as Base
The special value *PGMBDY is used by itself or with a program name to identify the PEP of a CL program. The entry for the PEP of the identified CL program then is the base entry. This option is useful when you want to send a message from within a CL procedure outside the boundary of the program which contains the procedure.
Refer to Figure 8-5 for an example of sending a message using the special value *PGMBDY. In this example, CLPROC4 is sending a message directly to to CLPGM1 which is the caller of the containing program CLPGM2. CLPROC4 can do this without knowing which program called CLPGM2 or knowing the location of the PEP compared to the procedure sending the message. In this example, *PGMBDY is used without an accompanying program name specified. This means that the program whose boundary is to be identified is the program which contains the procedure that is sending the message.
See Figure 8-6 for an example of sending a message using the special value *PGMBDY and a program name. The following programs and procedures are used in Figure 8-6:
A message is sent from CLPROCA to the caller of CLPGM2 by using the special value *PGMBDY with program name CLPGM2.
In this example, if the TOPGMQ parameter is specified as TOPGMQ(*PRV _CL_PEP), the message is sent to the caller of CLPGM3 rather than the caller of CLPGM2. This occurs because the most recently called procedure by that name is the PEP for CLPGM3.
Figure 8-5. Example 1 of using *PGMBDY
![]() |
Figure 8-6. Example 2 of using *PGMBDY
![]() |
The special value *PGMBDY can also be used with an OPM program. If you specify an OPM program name with *PGMBDY, you have the same results as when only the OPM program name is used. For example, TOPGMQ(*SAME *PGMBDY *NONE opmname) sends the message to the same place as TOPGMQ(*SAME opmname).
The exception to this is when a message is sent to an OPM program that called itself recursively. TOPGMQ(*SAME pgmname) sends the message to the latest recursion level. However, TOPGMQ(*SAME *PGMBDY *NONE pgmname) sends the message to the first recursion level. Figure 8-7 shows how PGM1 is called and proceeds to call itself recursively two more times. At the third recursion level PGM1 calls PGM2. PGM2 then sends a message back to PGM1. If the program is sent using only the name PGM1, the message goes to the third recursion level of PGM1. If the program is sent using the name PGM1 in conjunction with the special value *PGMBDY, the message goes to the first recursion level of PGM1.
Figure 8-7. Example 3 of using *PGMBDY
![]() |
Most Recently called Procedure as Base
Although you may not know the name of a procedure, you may want to send a message back to the most recently called procedure of an ILE program. The special value *PGMNAME is used with a ILE program name to use the base entry name as the name for the most recently called procedure of the identified program. The programs in this example are:
The send is accomplished using the special value *PGMNAME and the program name CLPGM1.
See Figure 8-8. for an example of how to send a message using the special value *PGMNAME.
The special value *PGMNAME is useful if you convert some CL programs, but not all CL programs, to ILE programs. For example, CLPGM1 is an OPM CL program; CLPGM3 sent messages to CLPGM1 and specifies TOPGMQ(*SAME CLPGM1). If CLPGM1 is converted to ILE, only the SNDPGMMSG command in CLPGM3 (OPM) works. CLPGM1 does not work because there was no entry in the call stack for CLPGM1. If you change the command to TOPGMQ(*SAME *PGMNAME *NONE CLPGM1), CLPGM3 sends messages successfully to CLPGM1 regardless of the names you may have used for procedure names.
The special value *PGMNAME can also be used in with an OPM program name. In this case the effect is the same as if you just used the name. For example, TOPGMQ(*SAME *PGMNAME *NONE opmpgm) sends the message to the same place as TOPGMQ(*SAME opmpgm). The use of *PGMNAME should be considered when you cannot determine whether the message is being sent to an OPM program name or and ILE program name.
Using a Control Boundary as a Base
You can identify the base entry as the one at the nearest control boundary by using the special value *CTLBDY. A control boundary exists between two call stack entries if the two entries are running in two different activation groups. The one identified by using this special value is running in the same activation group as the entry that is sending the message.
See Figure 8-9. for an example of sending a message using the special value *CTLBDY. The three programs in this example (CLPGM1, CLPGM2, and CLPGM3) are all ILE programs. CLPGM1 runs in activation group AG1 while both CLPGM2 and CLPGM3 run in activation group AG2. In this example, PROC3A sends a message back to the entry that immediately precedes the boundary for AG2.
Figure 8-8. Example of runtime call stack
![]() |
Figure 8-9. Example of using *CTLBDY
![]() |
Considerations for Service Programs
Previous discussions apply to both ILE programs and ILE service programs. The most important difference between an ILE program and an ILE service program is related to message handling. The service program does not have a PEP.
The PEP is not necessary for any of the options used to identify a base entry. An exception to this is when the name _CL_PEP is used explicitly. For example, TOPGMQ(*PRV *PGMBDY) always sends a message to the caller of the ILE program or service program. If it is an ILE program, the PEP is identified as the base by the *PGMBDY value. If it is an ILE service program, the entry for the first procedure called in the service program is identified by the *PGMBDY value.
(C) Copyright IBM Corporation 1992, 2005. All Rights Reserved.