I'm a beginner learning RPGLE and display files on IBM i. I’ve created a program that displays a message using a message subfile (SFLMSG) when calling a CL program (MSGSFLCL) via a subroutine, and it works fine.
However, when I refactor that subroutine into a procedure, the message no longer shows up in the subfile, even though everything else remains the same.
Here's what I'm doing:
Display File DDS:
A R MSGSFL SFL
A SFLMSGRCD(24)
A MSGKEY SFLMSGKEY
A PGMQ SFLPGMQ
A R MSGCTL SFLCTL(MSGSFL)
A OVERLAY
A SFLDSP
A SFLDSPCTL
A SFLINZ
A N99 SFLEND
A SFLSIZ(0010)
A SFLPAG(0001)
A PGMQ SFLPGMQ
CL Program (MSGSFLCL
):
PGM PARM(&MSGID &MSGF &MSGOPT)
DCL VAR(&MSGID) TYPE(*CHAR) LEN(7)
DCL VAR(&MSGF) TYPE(*CHAR) LEN(10)
DCL VAR(&MSGOPT) TYPE(*CHAR) LEN(1)
IF COND(&MSGOPT *EQ 'I') THEN(SNDPGMMSG +
MSGID(&MSGID) MSGF(&MSGF) TOPGMQ(*PRV) +
MSGTYPE(*INFO))
IF COND(&MSGOPT *EQ 'C') THEN(RMVMSG PGMQ(*PRV (*)) CLEAR(*ALL))
ENDPGM
RPGLE Program:
**free
ctl-opt dftactgrp(*no) actgrp(*new) option(*srcstmt:*nodebugio);
exec sql
set option commit = *none;
dcl-f Employee Usage(*input) Keyed;
dcl-s RRN packed(4: 0);
dcl-f EMPSFL WorkStn SFILE(SFLDATA: RRN) INFDS(DSPFDS);
dcl-ds MyDs ExtName('EMPLOYEE');
end-ds;
dcl-ds DSPFDS qualified;
MIN_RRN int(5) pos(378);
end-ds;
dcl-ds psds psds;
PgmName char(10);
end-ds;
dcl-s MSGID char(7);
dcl-s MSGF char(10) inz('AF_MSGF'); // Message File
dcl-s MSGOPT char(1);
dcl-pr MSGSFLCL extpgm;
MessageID char(7) const;
MsgF char(10) const;
MsgOpt char(1) const;
end-pr;
RCDNBR = 1;
PGMQ = PgmName;
loadPage();
Dou *In03;
write MSGCTL;
ExFMT SFLCTL;
RCDNBR = DSPFDS.MIN_RRN;
MSGID = 'MSG0001';
exsr sendMessage;
if (*IN05 = *ON);
MSGID = 'MSG0001';
Exsr clearMsg;
EndIf;
EndDo;
*INLR = *ON;
begsr sendMessage;
exsr clearMsg;
MSGOPT = 'I';
MSGF = 'AF_MSGF';
MSGSFLCL(MSGID: MSGF: MSGOPT);
endsr;
dcl-proc loadPage;
clearPr();
loadPr();
write Footer;
end-proc;
dcl-proc clearPr;
*IN50 = *OFF;
Write SFLCTL;
*IN50 = *ON;
RRN = 0;
End-proc;
dcl-proc loadPr;
Exec sql
declare c1 cursor for
select EMPID, NAME, DEPT, SALARY from employee;
Exec sql
open c1;
Exec sql
fetch c1 into :MyDs;
Dow (sqlcode = 0);
RRN = RRN + 1;
Write SFLDATA;
Exec sql
fetch c1 into :MyDs;
EndDo;
End-proc;
In my RPGLE Program, calling this from a subroutine like this works:
begsr sendMessage;
exsr clearMsg;
MSGOPT = 'I';
MSGF = 'AF_MSGF';
MSGSFLCL(MSGID: MSGF: MSGOPT);
endsr;
But calling it from a procedure like this does not display the message:
dcl-proc sendMessage;
MSGID = 'MSG0001';
MSGOPT = 'I';
MSGF = 'AF_MSGF';
MSGSFLCL(MSGID: MSGF: MSGOPT);
end-proc;
I’m calling write MSGCTL;
before exfmt SFLCTL
, and I’ve also set PGMQ = PgmName;
to match the program name.
What could be the reason that the message subfile only works when I use a subroutine but not a procedure?
Any insights are appreciated — thank you!
Subroutine calls aren't true calls. In other words, when you are in them you're still at the call stack level of the program.
Sub-procedures on the other hand, have their own call stack level.
`SNDPGMMSG TOPGMQ(*PRV)` send to the PGM when the CL is called from the subroutine but to the sub-procedure when the CL is called from the sub-procedure.
You're going to need to adjust TOPGMQ.
See the IBM docs for identifying call stack entry
You might also consider calling the Send Program Message API
You'll have the same issue, but in addition to the Call Stack Entry
parameter, there's a Call Stack Counter
parameter available for use.