• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • 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

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    Raz-Lee Security

    Start your Road to Zero Trust!

    Firewall Network security, controlling Exit Points, Open DB’s and SSH. Rule Wizards and graphical BI.

    Request Demo

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Sponsored Links

    System i Developer:  RPG & DB2 Summit - October 4-6 2016 in Chicago. Register now!
    Four Hundred Monitor Calendar:  Latest info on national conferences, local events, & Webinars.
    Manta Technologies Inc.:  The Leader in IBM i Education! Download catalog and take sample sessions!

    Clouds Grow, But Can IBM i Follow? The IBMer Who Decoded Bernie Madoff’s RPG

    Leave a Reply Cancel reply

Volume 16, Number 19 -- August 30, 2016
THIS ISSUE SPONSORED BY:

T.L. Ashford
New Generation Software
WorksRight Software

Table of Contents

  • Easy Printing from CL, Take Two
  • Message Data Data Structures
  • Getting Started With IBM i, .Net, and XMLSERVICE Remote Commands

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • Public Preview For Watson Code Assistant for i Available Soon
  • COMMON Youth Movement Continues at POWERUp 2025
  • IBM Preserves Memory Investments Across Power10 And Power11
  • Eradani Uses AI For New EDI And API Service
  • Picking Apart IBM’s $150 Billion In US Manufacturing And R&D
  • FAX/400 And CICS For i Are Dead. What Will IBM Kill Next?
  • Fresche Overhauls X-Analysis With Web UI, AI Smarts
  • Is It Time To Add The Rust Programming Language To IBM i?
  • Is IBM Going To Raise Prices On Power10 Expert Care?
  • IBM i PTF Guide, Volume 27, Number 20

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle