ibm-midrangerpglerpg

Why is SNDPGMMSG not showing messages in a subfile when called from a procedure instead of a subroutine in RPGLE?


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;

SFL Message Successfully displayed

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;

Message is not displayed

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!


Solution

  • 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.