Example in ILE C: Report software error (ILE API with pointers)

This program illustrates how to use APIs to log software errors using FFDC.

This program calls the Report Software Error (QpdReportSoftwareError) API to perform FFDC, and uses pointers. This ILE program sets a pointer, as shown at (2), to point to the same location as in the OPM program at (1).

Note: Read the Code license and disclaimer information for important legal information.
/*********************************************************************/
/*                                                                   */
/*Program Name: FFDCPGM2                                             */
/*                                                                   */
/*Program Language:  ILE C                                           */
/*                                                                   */
/*Description:  This program illustrates how to use APIs to log      */
/*              software errors using FFDC.                          */
/*                                                                   */
/*                                                                   */
/*Header Files Included:  except                                     */
/*                        stdio                                      */
/*                        string                                     */
/*                        qmhchgem                                   */
/*                        qpdsrvpg                                   */
/*                        qusec                                      */
/*                                                                   */
/*APIs Used:     QpdReportSoftwareError                              */
/*                                                                   */
/*********************************************************************/
/*********************************************************************/
/*********************************************************************/
/*                        System Includes                            */
/*********************************************************************/
#include <except.h>                /* from QSYSINC/H                 */
#include <stdio.h>                 /* from QSYSINC/H                 */
#include <string.h>                /* from QSYSINC/H                 */

/*********************************************************************/
/*                    Miscellaneous Includes                         */
/*********************************************************************/
#include <qmhchgem.h>              
#include <qpdsrvpg.h>              
#include <qusec.h>                 

/*********************************************************************/
/* Definitions used for developing key information for FFDC.         */
/*********************************************************************/
#define CHARACTER 'C'
#define MAX_KEYS 3
#define MESSAGE "MSG"
#define MESSAGE_LEN 7
#define MSG_SYMPTOM_LEN 3

/*********************************************************************/
/*                           Structures                              */
/*********************************************************************/
typedef struct {
    void  *parm1;
    void  *parm2;
    char  *pgm_name;
    int    pgm_name_size;
} ffdc_info_t;

/*********************************************************************/
/*                           Prototypes                              */
/*********************************************************************/
void UNEXPECTED_HDLR(_INTRPT_Hndlr_Parms_T *);

/*********************************************************************/
/*   FUNCTION NAME:  main                                            */
/*                                                                   */
/*   FUNCTION:       Generates exception and then passes control     */
/*                   to exception handler.                           */
/*                                                                   */
/*   INPUT:          Two character strings.                          */
/*                                                                   */
/*   OUTPUT:         NONE                                            */
/*                                                                   */
/*   EXCEPTIONS:     CPFxxxx - All unexpected CPF exceptions         */
/*                   MCHxxxx - All unexpected MCH exceptions         */
/*                                                                   */
/*********************************************************************/
void main(int argc, char *argv[])
{
  /*******************************************************************/
  /* NOTE:  argv will contain the parameters passed in to this       */
  /*        function.  In this case, two parameters are passed       */
  /*        in.                                                      */
  /*******************************************************************/
  /*******************************************************************/
  /* The argv parameter contains the parameters that were passed as  */
  /* character arrays.  argv[0] contains the program name, and the   */
  /* parameter(s) starts with argv[1].                               */
  /*******************************************************************/

  char *nulptr;                   /* Pointer used to generate error  */
  char pgm_name[30];              /* Program name                    */
  volatile ffdc_info_t ffdc_info; /* FFDC info for unexpected error  */

  /*******************************************************************/
  /* Set up FFDC information for unexpected error.                   */
  /*******************************************************************/
  ffdc_info.parm1 = argv[1];
  ffdc_info.parm2 = argv[2];
  ffdc_info.pgm_name = pgm_name;
  memcpy(pgm_name, argv[0], strlen(argv[0]));
  ffdc_info.pgm_name_size = strlen(argv[0]);

  /*******************************************************************/
  /* Enable the exception handler, and pass ffdc_info into the       */
  /* exception handler via the communications area so that data      */
  /* can be used for FFDC.                                           */
  /*******************************************************************/

#pragma exception_handler (UNEXPECTED_HDLR, ffdc_info, 0, _C2_MH_ESCAPE)

  /*******************************************************************/
  /* Set the pointer to null, then try to increment.  This will      */
  /* generate an MCH3601 error that will be trapped by the           */
  /* unexpected handler.                                             */
  /*******************************************************************/
  nulptr = NULL;
  nulptr++;

#pragma disable_handler

} /* main */

/*********************************************************************/
/*   FUNCTION NAME:  UNEXPECTED_HDLR                                 */
/*                                                                   */
/*   FUNCTION:       Handle unexpected exception.  This exception    */
/*                   handler is used to log the software error via   */
/*                   FFDC.                                           */
/*                                                                   */
/*   INPUT:          Interrupt handler information                   */
/*                                                                   */
/*   OUTPUT:         NONE                                            */
/*                                                                   */
/*   EXCEPTIONS:     CPFxxxx - All unexpected CPF exceptions         */
/*                   MCHxxxx - All unexpected MCH exceptions         */
/*                                                                   */
/*********************************************************************/
void UNEXPECTED_HDLR(_INTRPT_Hndlr_Parms_T *errmsg)
{

  int                    i = 0,
                         MsgLen = 0,
                         number_of_keys = 0;
  char                   pgm_name[30],
                         context_name[30],
                         lib_name[5],
                         symptom_msg_data[MESSAGE_LEN],
                         symptom_msg_keyword[MSG_SYMPTOM_LEN];
  ffdc_info_t            *ffdc_info;
  Qpd_Data_t             data_key,
                         data_key2;
  Qpd_Key_Pointer_t      ffdc_keys[MAX_KEYS];
  Qpd_Suspected_Module_t module_key;
  Qpd_Symptom_t          symptom_msg_key;
  Qus_EC_t               ErrorCode;

  ErrorCode.Bytes_Provided = 0;

  /*******************************************************************/
  /* Getting pointer in local storage to the Communications Area.    */
  /*******************************************************************/
  ffdc_info = (ffdc_info_t *)(errmsg->Com_Area);

  /*******************************************************************/
  /* Need to notify message handler that we will handle the error.   */
  /* Leave the message in the job log, just mark it handled.         */
  /*******************************************************************/
  QMHCHGEM(&(errmsg->Target),             /* Invocation pointer      */
             0,                           /* Call stack counter      */
             (char *)&errmsg->Msg_Ref_Key,/* Message key             */
             "*HANDLE   ",                /* Modification option     */
             "",                          /* Reply text              */
             0,                           /* Reply text length       */
             &ErrorCode);                 /* Error code              */

  /*******************************************************************/
  /* Initialize module suspected key for FFDC.                       */
  /*******************************************************************/
  ffdc_keys[number_of_keys++].Suspected_Module = &module_key;
  module_key.Key = Qpd_Suspected_Module;
  module_key.Module_Name_Length = ffdc_info->pgm_name_size;
  module_key.Library_Name_Length = 7;
  module_key.Module_Name = pgm_name;
  memcpy(pgm_name, ffdc_info->pgm_name, ffdc_info->pgm_name_size);
  module_key.Library_Name = lib_name;
  memcpy(lib_name, "TESTLIB", 7);

  /*******************************************************************/
  /* Initialize symptom keys for FFDC.                               */
  /*******************************************************************/
  ffdc_keys[number_of_keys++].Symptom = &symptom_msg_key;
  symptom_msg_key.Key = Qpd_Symptom;
  symptom_msg_key.Keyword_Length = MSG_SYMPTOM_LEN;
  symptom_msg_key.Data_Length = MESSAGE_LEN;
  symptom_msg_key.Data_Type = CHARACTER;
  memcpy(symptom_msg_keyword, MESSAGE, MSG_SYMPTOM_LEN);
  symptom_msg_key.Keyword = symptom_msg_keyword;
  memcpy(symptom_msg_data, errmsg->Msg_Id, MESSAGE_LEN);
  symptom_msg_key.Data = symptom_msg_data;

  /*******************************************************************/
  /* Parameter 1 information                                         */
  /*******************************************************************/
  ffdc_keys[number_of_keys++].Data = &data_key;
  data_key.Key = Qpd_Data;
  data_key.Data_Length = sizeof(char *);
  data_key.Data_Id = 1;
  data_key.Data = ffdc_info->parm1;                              (2)


  /*******************************************************************/
  /* Parameter 2 information                                         */
  /*******************************************************************/
  ffdc_keys[number_of_keys++].Data = &data_key2;
  data_key2.Key = Qpd_Data;
  data_key2.Data_Length = sizeof(char *);
  data_key2.Data_Id = 1;
  data_key2.Data = ffdc_info->parm2;

  /*******************************************************************/
  /* Call QpdReportSoftwareError to perform FFDC.                    */
  /*******************************************************************/
  ErrorCode.Bytes_Provided = sizeof(ErrorCode);
  QpdReportSoftwareError(ffdc_keys,
                         &number_of_keys,
                         &ErrorCode);

} /* UNEXPECTED_HDLR */