When your telephone rings and someone at the other end starts talking without identifying himself or herself, you have every bit of right to feel annoyed. It's only common courtesy to at least say, "My name is so-and-so." After that, the caller can start with the business at hand since the formalities have been complied with.
AS/400 programs aren't so polite. When program A calls program B, program A is ordering program B to run; yet program B has no direct way of knowing who called it. Sometimes this information would be useful. The Retrieve Previous Program (RTVPRVPGM) command shown in Figures 1a and 1b satisfies this need.
To give you an idea of its usefulness, you may have created a single program that performs one function nine times out of ten. The remaining time, it still performs the same function-with a slight alteration to accommodate different requirements. Granted, you probably should have created two different programs (that's what the basic tenets of modular programming would advise), but in real life this is not always practical.
If your CL program needs to know what program called it, include the RTVPRVPGM command in the CL program, as follows:
RTVPRVPGM LEVELS(1) + RTNPGM(&CALLER)
Variable &CALLER must be declared as a 10-character string. The LEVELS parameter indicates how many levels to go back in the program stack. You can put LEVELS(2) if you want to know the caller's caller's name, for instance.
If the program that needs the caller's name is written in RPG/400 you can call the program activated by the RTVPRVPGM command directly. Just include the code from 1c in your program.
If the program that needs the caller's name is written in RPG/400 you can call the program activated by the RTVPRVPGM command directly. Just include the code from Figure 1c in your program.
This utility does its work by sending an *INFO message to *PRV (the caller of PRV001CL) and obtaining the key of this message. Then the message is received by key and erased, obtaining the sender information structure in &SENDER. Part of the information structure is the name of the program that actually received the message-which will be the name of the program from which you used this utility command.
Next, we repeat the cycle, using the program name retrieved in the first cycle as the basis for another SNDPGMMSG to *PRV and RCV-MSG with the &SENDER option, which obtains the name of your program's caller. The process is repeated the number of times indicated by the LEVELS parameter. It's pretty simple and very efficient.
Now, if only we could do the same on the telephone, perhaps those pesky, malicious callers (who love to call at 3 a.m. just to hang up on you) would think twice about it!
TechTalk: Who's Calling Please?
Figure 1A Command RTVPRVPGM
RTVPRVPGM: CMD PROMPT('Retrieve Previous Program') PARM KWD(LEVELS) TYPE(*DEC) LEN(3 0) DFT(1) + RANGE(1 100) PROMPT('Number of levels to + backtrack') PARM KWD(RTNPGM) TYPE(*CHAR) LEN(10) RTNVAL(*YES) + PROMPT('Program name (10)')
TechTalk: Who's Calling Please?
Figure 1B CL program PRV001CL
PRV001CL: + PGM PARM(&LEVELS &RTNPGM) DCL VAR(&CALLER) TYPE(*CHAR) LEN(10) DCL VAR(&COUNTER) TYPE(*DEC) LEN(3 0) DCL VAR(&LEVELS) TYPE(*DEC) LEN(3 0) DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(132) DCL VAR(&MSGF) TYPE(*CHAR) LEN(10) DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10) DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) DCL VAR(&MSGKEY) TYPE(*CHAR) LEN(4) DCL VAR(&RTNPGM) TYPE(*CHAR) LEN(10) DCL VAR(&SENDER) TYPE(*CHAR) LEN(80) MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) SNDPGMMSG MSG(X) TOPGMQ(*PRV *) MSGTYPE(*INFO) KEYVAR(&MSGKEY) RCVMSG PGMQ(*PRV *) MSGKEY(&MSGKEY) RMV(*YES) SENDER(&SENDER) CHGVAR VAR(&CALLER) VALUE(%SST(&SENDER 56 10)) LOOP: + SNDPGMMSG MSG(X) TOPGMQ(*PRV &CALLER) MSGTYPE(*INFO) + KEYVAR(&MSGKEY) RCVMSG PGMQ(*PRV &CALLER) MSGKEY(&MSGKEY) RMV(*YES) SENDER(&SENDER) CHGVAR VAR(&COUNTER) VALUE(&COUNTER + 1) IF COND(&COUNTER *EQ &LEVELS) THEN(DO) CHGVAR VAR(&RTNPGM) VALUE(%SST(&SENDER 56 10)) RETURN ENDDO ELSE CMD(DO) CHGVAR VAR(&CALLER) VALUE(%SST(&SENDER 56 10)) GOTO CMDLBL(LOOP) ENDDO ERROR: + RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) + MSGFLIB(&MSGFLIB) SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) MSGDTA(&MSGDTA) + MSGTYPE(*ESCAPE) ENDPGM
TechTalk: Who's Calling Please?
Figure 1C Using RTVPRVPGM in RPG/400
Figure 1c: Using RTVPRVPGM in RPG/400 ... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 C CALL 'PRV001CL' C PARM 1 LEVELS 30 C PARM RTNPGM 10
LATEST COMMENTS
MC Press Online