Message Data Data Structures
August 30, 2016 Hey, Ted
| 
 
 
 Sending Escape Messages from RPG is a great article. Your program defines the message data parameter as 80 bytes of character data, but the IBM Knowledge Center defines MSGDTA as char(*) with notes saying it can be up to 32,767 bytes. I would like a variable longer than 80 bytes, but instead of coding 100 today, 120 next project, and so on, how could I code it to take full advantage of the API? –Glenn You’re right that the API can handle up to 32K of data, but you need only define MsgDta as large as you need it to be for the message you’re sending. For all practical purposes, 32K is infinity. I can’t imagine a message with that much data. Here are a few ways to take advantage of this API. 1. Put the prototype in a copybook. Some APIs are prototyped in the QSYSINC library, but I didn’t find one for QMHSNDPM. 2. Define the message data with a length of 32,767, and add OPTIONS(*VARSIZE). That allows you to pass shorter variables when you call the program. 3. In my example, I used a scalar variable, since message CPF9898 only has one substitution value. What makes more sense (to me, anyway) is to create a data structure for the message data. Each subfield of the data structure represents one of the substitution values in the message description. You might want to put these definitions in a copybook (or copybooks) as well. Here’s an RPG example that incorporates those ideas. First, a message description. 
ADDMSGD MSGID(HHH9015) MSGF(HHHMSGF) +
           MSG('Work order &1, operation &2 could not be completed.  +
                Status is &3.') +
           FMT((*CHAR 8) (*CHAR 3) (*DEC 3))  
Notice the three data values are defined as character 8, character 3, and packed 3. Next, the prototype for QMHSNDPM: 
D QMHSNDPM        pr                  extpgm('QMHSNDPM')     
D   MsgID                        7    const                  
D   MsgFile                     20    const                  
D   MsgDta                   32767    const options(*varsize)
D   MsgDtaLen                   10i 0 const                  
D   MsgType                     10    const                  
D   MsgQ                        10    const                  
D   MsgQNbr                     10i 0 const                  
D   MsgKey                       4                           
D   ErrorDS                     16                           
Next, appropriate fragments of the program. 
/copy prototypes,qmhsndpm
D ErrorDS         ds            16    qualified inz
D   BytesProv                   10i 0
D   BytesAvail                  10i 0
D MsgDta          s             80
D MsgKey          s              4
D HHH9015         ds                  qualified
D   WorkOrder                    8a
D   Operation                    3a
D   Status                       3p 0
        HHH9015 . WorkOrder    = WrkOrdr;
        HHH9015 . Operation    = OperNo;
        HHH9015 . Status       = LastStatus;
        QMHSNDPM ('HHH9015': 'HHHMSGF   *LIBL':
                  HHH9015  : %len(HHH9015):
                  '*ESCAPE': '*' : 2:
                   MsgKey: ErrorDS);
Notice the HHH9015 data structure–character 8, character 3, packed 3. Do you see that the subfields correspond to the data definitions in the HHH9015 message description? Notice also the length function (%LEN) in the fourth argument. %len(HHH9015) That’s the reason you can define the message data as 32,767 and yet pass shorter values without the API reading a lot of garbage from memory. The message looks like this: Work order T4168872, operation 210 could not be completed. Status is 400. Even though CL doesn’t have data structures, you can accomplish the same sort of thing by using defined variables. Here’s a CL example. First, two message descriptions: 
   AddMsgD   MsgID(GGG1010) msgf(GGGMSGF) +
                Msg('&3 posting is complete for company &1, period &2.') +
                fmt((*dec 3) (*dec 2) (*char 32))
                /* &1 = company   */
                /* &2 = period    */
                /* &3 = type of posting */
   AddMsgD   MsgID(GGG9990) msgf(GGGMSGF) +
                Msg('Posting option &1 is invalid. Job canceled.') +
                fmt((*char 3))
Now, the program. 
pgm  parm(&inCompany &inPeriod &inOption)
   dcl &inCompany      *dec    3
   dcl &inPeriod       *dec    2
   dcl &inOption       *char   3
   dcl   &PostType     *char  32
   dcl &GGG1010        *char  36
   dcl   &Company_1    *dec    3 stg(*defined) defvar(&GGG1010 1)
   dcl   &Period_1     *dec    2 stg(*defined) defvar(&GGG1010 3)
   dcl   &PostType_1   *char  32 stg(*defined) defvar(&GGG1010 5)
   dcl &GGG9990        *char   7
   dcl   &Option_2     *char   3 stg(*defined) defvar(&GGG9990 1)
   select
      when (&inOption *eq EOD) +
               then(ChgVar &PostType 'End of day')
      when (&inOption *eq EOW) +
               then(ChgVar &PostType 'End of week')
      when (&inOption *eq EOM) +
               then(ChgVar &PostType 'End of month')
      when (&inOption *eq EOY) +
               then(ChgVar &PostType 'End of year')
      when (&inOption *eq Cus) +
               then(ChgVar &PostType 'Custom')
      otherwise do
         chgvar      &Option_2      &inOption
         SndPgmMsg   MsgID(GGG9990) Msgf(GGgMsgf) MsgDta(&GGG9990) +
                        MsgType(*escape)
         enddo
   endselect
   call  ggg002r parm(&inCompany &inPeriod &inOption)
   call  ggg003r parm(&inCompany &inPeriod &inOption)
   call  ggg004r parm(&inCompany &inPeriod &inOption)
   chgvar     &Company_1     &inCompany
   chgvar     &Period_1      &inPeriod
   chgvar     &PostType_1    &PostType
   SndPgmMsg   MsgID(GGG1010) Msgf(GGgMsgf) MsgDta(&GGG1010) +
                  MsgType(*comp)
Endpgm
Notice the GGG1010 and GGG9990 variables. Both are overlaid with other variables in accordance with the data values in the message descriptions. The user sees messages like these: End of month posting is complete for company 1, period 11. Posting option EAR is invalid. Job canceled. I’ve had good success using data structures that correspond to message descriptions. This practice and a generous use of copybooks have helped me easily integrate message-handling into applications. –Ted Ted Holt welcomes your comments and questions. Email him through the IT Jungle Contacts page. RELATED STORY Sending Escape Messages from RPG 
 | 

 
							  
								 
					