MainframeMaster

User-Written Exits

User-written exits are programs you code (in Assembler or COBOL) that DFSORT loads and calls during a sort or copy step. You put your logic in the exit—for example, to filter, reformat, or expand records—and tell DFSORT to use it via the MODS control statement. Writing an exit requires following the DFSORT exit interface: the parameter list layout, register conventions, and return codes that DFSORT expects. This page covers how to write and test user exits, where to place the load module, how to debug common problems, and how to use OPTION COPY and STOPAFT when developing.

Other DFSORT Topics
Progress0 of 0 lessons

Following the Exit Interface

DFSORT passes control to your exit with a specific calling convention and parameter list. Your program must use the same convention and interpret the parameter list exactly as documented; otherwise the step can abend or produce wrong results. The DFSORT Application Programming Guide for your product level describes, for each exit type (E15, E35, E32, etc.): the format of the parameter list (e.g. address of record, record length, and often a word reserved for the exit to store a pointer to its own save area), the meaning of each return code (e.g. 12 = use record, 8 = drop record), and how to code the exit in Assembler and in COBOL. You must use the correct return code so DFSORT knows whether to keep, drop, or accept multiple records from the exit.

Parameter List and Return Codes

The parameter list is typically a list of fullwords (or equivalent) passed by DFSORT to your exit. Common elements include the address of the current record, the record length, and a "user exit address constant" word. On the first call, the exit can obtain storage (e.g. via GETMAIN or the equivalent in COBOL) and save the address in that word; on later calls, the same word is passed so the exit can reuse that storage. That lets you maintain state across invocations—for example, a running total or a counter. Return codes are set in a register or in a field that DFSORT reads. Typical values (check your manual for the exact set) include: 12 to indicate "use this record" (as is or as modified), 8 to indicate "drop this record," and 4 (or similar) for one-to-many when the exit returns multiple records. The Application Programming Guide lists all valid return codes and their meanings for each exit type.

Typical E15/E35 return codes (confirm in Application Programming Guide)
Return codeMeaning
12Use the record (pass or modified); normal continue
8Drop/skip this record (do not include in sort or output)
4Used for one-to-many; exit provides additional records (exact usage per Application Programming Guide)

Where to Put the Load Module

DFSORT loads your exit from a load library that the step can access. That is usually a dataset in the STEPLIB DD statement for the sort step, or in JOBLIB if you want the whole job to use it. The MODS statement in SYSIN names the load module (e.g. MODS=(MYE15)); DFSORT looks for a module with that name in the library concatenation. If the module is not found, you get a load failure (e.g. program not found). So after compiling and linking your exit, copy the load module to a PDS or PDSE that is in STEPLIB or JOBLIB for the test job.

Testing with OPTION COPY and STOPAFT

When developing an exit, start with OPTION COPY. With COPY, DFSORT does not sort; it reads from SORTIN, calls your input exit (e.g. E15) for each record, and writes to SORTOUT. That lets you verify that the exit is called, that it receives the record correctly, and that it returns the right code (pass, drop, or multiple records) without the added complexity of sort keys, SUM, or OUTFIL. Once the exit behaves correctly with COPY, add SORT FIELDS and other options. Use OPTION STOPAFT=n to process only the first n records during debugging; for example, STOPAFT=1 or STOPAFT=10 so you can inspect a small amount of output and SYSOUT quickly.

Debugging Tips

If the step abends, check the abend code and the SYSOUT. Many abends in exits are due to incorrect use of the parameter list (e.g. using the wrong offset for the record address or length, or overwriting storage outside the record). Re-read the Application Programming Guide and ensure your code matches the interface. You can write diagnostic data into the record (e.g. a counter or a flag) and inspect the output to confirm the exit is being called and with what data. Some sites use a debugger (e.g. under TSO or in a batch debugging environment) to step through the exit. Keep the first version of the exit simple (e.g. pass through all records with return code 12) and add logic gradually so you can isolate failures.

Assembler vs COBOL

Exits are commonly written in Assembler because the interface is register- and storage-oriented; you have direct control over the parameter list and return codes. COBOL is also supported; the guide describes how to define the parameter list (e.g. LINKAGE SECTION) and set the return code. Choose the language your team maintains more easily. Both must follow the same interface; the guide has examples for each.

State Across Records

The "user exit address constant" (or equivalent) in the parameter list is intended for the exit to save a pointer to its own storage. On the first call, the exit obtains storage (GETMAIN or COBOL equivalent), saves the address in that word, and uses the storage for work areas, counters, or running totals. On subsequent calls, the same word is passed in, so the exit can reload the pointer and reuse the storage. That way you can maintain state across all record calls in the step—for example, for running totals or for conditional logic that depends on previous records.

Explain It Like I'm Five

You are building a helper robot that the sorting machine will call. The machine gives the robot a piece of paper (the record) and a special box (the parameter list) where the robot can put a note for next time. The robot must answer with a secret number: "12" means "use this paper," "8" means "throw it away," and so on. You have to build the robot exactly the way the machine’s manual says, and put the robot in a place where the machine can find it (STEPLIB). When you first test the robot, you tell the machine to only move papers and not sort (COPY), and to only do a few papers (STOPAFT), so you can check that the robot does the right thing.

Exercises

  1. Why must the exit load module be in STEPLIB or JOBLIB?
  2. What is the benefit of testing an E15 exit with OPTION COPY before adding SORT FIELDS?
  3. What is the purpose of the "user exit address constant" word in the parameter list?
  4. Where do you find the exact parameter list layout and return codes for your DFSORT level?

Quiz

Test Your Knowledge

1. Where must the load module for your DFSORT exit reside?

  • In SYSIN
  • In a library in the step's STEPLIB or JOBLIB concatenation so DFSORT can load it
  • In the SORTIN dataset
  • In PARM

2. Why is it recommended to test an E15 exit first with OPTION COPY?

  • COPY is faster
  • COPY runs only the input phase and no sort; you can verify the exit reads and returns records correctly before adding sort/SUM/OUTFIL
  • COPY is required for exits
  • COPY skips the exit

3. What is the purpose of the parameter list passed to an E15 or E35 exit?

  • It contains only the record
  • It provides the record address, length, and control information; the exit uses it to read/modify the record and to return codes to DFSORT
  • It is optional
  • It is the same for all exit types

4. Which languages can you use to write DFSORT exits?

  • REXX only
  • Assembler and COBOL; the program must follow the exit interface (calling convention and parameter list) documented by DFSORT
  • Java only
  • Any language

5. What can you use to limit the number of records processed when debugging an exit?

  • Only JCL
  • OPTION STOPAFT=n processes only the first n records, which helps verify behavior on a small set
  • INCLUDE only
  • Exits cannot be limited