Compiler Listing Read user exit

The following describes the Compiler Listing Read user exit.

Purpose

This exit can be used to obtain source code information from sources other than compiler listings or Fault Analyzer side files stored as members in the usual IDI data sets (IDILANGX, IDILCOB, IDILPLI, and so on). For example, compiler listings that are stored in a compressed format, or that are accessible only via a proprietary access method.

Whenever source code information is required by Fault Analyzer, the steps shown in Locating compiler listings or side files are performed. When the Compiler Listing Read user exit is shown invoked, this implies all specified and available exits. That is, all exits are first invoked to provide a side file and later, if necessary, all exits are invoked to provide a compiler listing. Only the last side file or compiler listing provided by any exit is used.

Fault Analyzer provides the following information to the Compiler Listing Read user exit about the required source code information:
  • The load module name. This name is available in the LST.MODULE_NAME data area field. See Parameters for references to the LST data area.
  • The load module data set name in the LST.LOAD_MODULE_DSN data area field.
  • The CSECT name. This name is available in the LST.CSECT_NAME data area field.
  • The entry-point name. This name is available in the LST.EP_NAME data area field, truncated to a maximum of 256 characters. If truncated, the first 254 characters of the entry-point name is followed by a tilde ('~') and the last character of the untruncated entry-point name.
  • The compile date. This date is available in the LST.COMPILE_DATE data area field, in the format YYYY/MM/DD.
  • The compile time. This time is available in the LST.COMPILE_TIME data area field, in the format HH:MM:SS.
  • The listing type. This type is available in the LST.LISTING_TYPE data area field, as one of the following:
    L
    Compiler listing or assembler SYSADATA file
    S
    Fault Analyzer side file

    The source code information passed back to Fault Analyzer must be of the type specified in this field.

  • The language type. This type is available in the LST.LANGUAGE_TYPE data area field, as one of the following:
    • Assembler
    • C/C++
    • COBOL
    • OS/VS COBOL
    • PL/I
  • The expected record format of listings or side files provided by the exit. This format is available in the LST.RECFM data area field, as V, VB, VBA, F, FB, FBA, and so on.
  • The expected logical record length of listings or side files provided by the exit. This length is available in the LST.LRECL data area field, in decimal character format.
Based on the above information, a user exit can provide the requested listing or side file. This provision is done in one of the following ways:
  • By passing one record at a time to Fault Analyzer via the LST data area:
    • Unless the name of a variable containing the listing record is passed on the IDIWRITE command in a REXX EXEC, the listing or side file data record must be provided in the DATA_BUFFER field.
    • For variable-length records, the length of the record in DATA_BUFFER must be provided in the DATA_LENGTH field in decimal character format. This length is not inclusive of any variable-length record descriptor word and must be less than or equal to the value in the LRECL field minus 4 bytes.
    • For fixed-length records, the length of the record in DATA_BUFFER is expected to match the LRECL field. Any value provided in the DATA_LENGTH field is ignored.
    or
  • By placing the name of a sequential data set or a PDS or PDSE with member specification in the DATA_BUFFER field and setting DATA_BUFFER_DSN to Y. The data set name must be uppercased, must start at offset zero into the DATA_BUFFER field, must be fully qualified, and must not contain surrounding quotes. Examples of valid data set names are:
    MY.SEQ.DS
    MY.PDS.DS(MBR)

    No characters other than blanks must follow the data set name (the DATA_BUFFER field is initialized to blanks before the user exit is invoked).

If not providing a data set name, but instead passing back individual data records, then, having updated the LST data area with the data record information, two different methods are available for passing the data to Fault Analyzer depending on the exit type:
REXX
The Fault Analyzer environment IDIWRITE command is used. To use this command, code a REXX statement as follows:
ADDRESS FAULTA 'IDIWRITE [var-name]'

Successful completion of the IDIWRITE command is indicated by a zero return code.

For detailed information about the IDIWRITE command, see IDIWRITE command.

Load module
The address of a write routine is available in the ENV.WRITE_ROUTINE_EP data area field, as a hexadecimal 31-bit address.

This routine must be invoked with R1 pointing to a fullword containing the address of the ENV data area. For example, the following code fragments of user exits in different programming languages could be used to invoke the write routine:

Assembler:
ASMEXIT  CSECT
         …
         L     R2,0(,R1)
         USING ENV,R2
         L     R3,4(,R1)
         USING LST,R3
         …
         L     R15,ENV_WRITE_ROUTINE_EP
         LA    R1,ENV_VERSION
         ST    R1,*+8
         BAL   R1,*+8
         DC    F'0'
         BALR  R14,R15
         …
         COPY  IDISXPLA
         …
C:
#include "SAMPLES(IDISXPLC)"
typedef void WRTN(ENV *pENV);
#pragma linkage(WRTN,OS)
int cexit(ENV *pENV, LST *pLST) {
  …
  WRTN *write_rtn;
  write_rtn = (WRTN *)pENV->WRITE_ROUTINE_EP;
  write_rtn(pENV);
  …
}
COBOL:
       …
       PROGRAM-ID. COBEXIT
       …
       LINKAGE SECTION.
           COPY IDISXPLB IN LIB.
       PROCEDURE DIVISION USING ENV, LST.
       MAIN SECTION.
             …
             CALL WRITE-ROUTINE-EP USING ENV.
             …
       END PROGRAM COBEXIT.
PL/I:
 PLIEXIT: PROC (ENVPTR,LSTPTR)  OPTIONS(BYVALUE,FETCHABLE) ;
 Dcl (Envptr,Lstptr)     Pointer ;
 %include syslib(IDISXPLP) ;
 Dcl IDIWRITE         Entry Variable Options(Asm Byaddr) ;
   …
   Entryaddr(IDIWRITE) = Envptr->Write_Routine_EP ;
   Call IDIWRITE (Envptr->Env) ;
   …
 End PLIEXIT ;

Return codes from the write routine are the same as the return codes from the IDIWRITE REXX command, except that RC=8 (syntax error) cannot be returned. See IDIWRITE command.

An indicator that can be used to cancel the usage of a listing or side file being provided by the user exit is available in the LST data area field DISREGARD_EXIT_LISTING. If this field is set to 'Y', any data records that might have been passed back to Fault Analyzer from the user exit is discarded. By means of this indicator, the user exit can prevent Fault Analyzer from using a partial listing in case errors occur while providing data records.

When invoked

This exit is invoked whenever source code information is required in any Fault Analyzer execution mode.

Parameters

How parameters are passed to the exit depends on the exit type, REXX or load module.

Fault Analyzer initializes the parameter lists using current values for the particular fault and processing options in effect before invoking the Compiler Listing Read user exit.

Example

The following example is a Compiler Listing Read user exit that is written in REXX. The partitioned data set myid.LISTING.TERSE contains compressed compiler listings created by the IBM® AMATERSE utility.

When Fault Analyzer requests a compiler listing file, the exit searches the myid.LISTING.TERSE PDS for a member name that matches the module name. If a matching member is found, the exit decompresses it into a work data set and uses the IDIWRITE command to pass it to Fault Analyzer.
Figure 1. Sample REXX Compiler Listing Read user exit
/* REXX */
if ENV.VERSION <> 5 then
  say 'Note: ENV data area version change - field usage review required!'
if LST.VERSION <> 1 then
  say 'Note: LST data area version change - field usage review required!'
if LST.LISTING_TYPE = 'L' then do
  modnm = strip(LST.MODULE_NAME)
  "IDIALLOC DD(INFILE) DSN(myid.LISTING.TERSE("||modnm||")) SHR"
  if rc = 0 then do
    recfm = strip(LST.RECFM)
    lrecl = strip(LST.LRECL,L,0)
    "IDIALLOC DD(OUTFILE) DSN(myid.TEMP) NEW CATALOG SPACE(1,1) ",
             "RECFM("||recfm||") LRECL("||lrecl||") UNIT(SYSALLDA)"
    address linkmvs "amaterse unpack"
    address mvs "execio * diskr outfile (finis"
    do while queued() <> 0
      parse pull rec
      LST.DATA_LENGTH = length(rec)
      LST.DATA_BUFFER = rec
      "IDIWRITE"
    end
    "IDIFREE DD(INFILE,OUTFILE)"
  end
end
exit 0
If the preceding sample exit exists as member ABC in data set X.Y.Z, you can invoke it by using the following options in either the IDICNF00 configuration member or the IDIOPTS user options file:
DataSets(IDIEXEC(X.Y.Z))
Exits(LISTING(REXX(ABC)))