MODS programming is the practice of using the MODS control statement to plug your own exit routines into a DFSORT step and of structuring your JCL and code so that the step finds and runs those exits correctly. This includes choosing MODS syntax (one module vs separate modules for E15 and E35), ensuring the load library is available via STEPLIB or JOBLIB, and understanding how your exits interact with INREC, OUTREC, and other control statements. This page focuses on programming practices: MODS syntax options, using E15 and E35 together, JCL setup, and when to prefer exits vs built-in reformatting.
The MODS statement tells DFSORT which load module(s) contain your exit code. Exact syntax depends on your DFSORT (or SyncSort) product and release. Common forms include: a single module name (e.g. MODS=(MYEXIT)), which may be used for a default exit type or when one module contains multiple exit entry points; and the form that assigns modules by exit type (e.g. MODS=(E15=MYE15,E35=MYE35)), which explicitly ties each exit to a load module. If you use one module for both E15 and E35, the product may expect specific entry point names or a single entry that handles both; check the product manual. Prefer the E15= and E35= form when you have separate modules so it is clear which program runs at input and which at output.
You can put the E15 and E35 logic in a single load module (with two entry points, if the product supports it) or in two (or more) separate modules. Using separate modules has advantages: you can change or fix the E15 without relinking the E35, you can test one exit in isolation, and you can reuse the same E15 or E35 in different jobs. A single module can be simpler to deploy (one member to copy) but ties the two exits together. Choose based on how your site manages load libraries and how often you expect to change each exit.
DFSORT loads the module(s) named in MODS from the step’s library concatenation. That is usually the STEPLIB DD statement for the sort step—for example, a PDS or PDSE containing your exit load modules. If you put STEPLIB on the JOB statement (as JOBLIB), all steps in the job can use it. The system searches the concatenation in order; the first matching member name is loaded. So ensure the dataset that contains your exit is in STEPLIB (or JOBLIB) and that the member name matches exactly what you coded in MODS. Case and length matter: MODS=(MYE15) looks for a member named MYE15.
A typical pattern is: a STEPLIB DD that points to your load library, SORTIN and SORTOUT (and optionally SORTWKnn for sort work), and SYSIN with your control statements including MODS. The following is a simplified example; adjust dataset names and MODS syntax to your product.
123456789//SORTSTEP EXEC PGM=SORT //STEPLIB DD DSN=MY.USER.LOAD,DISP=SHR //SORTIN DD DSN=MY.INPUT,DISP=SHR //SORTOUT DD DSN=MY.OUTPUT,DISP=(NEW,CATLG),... //SYSIN DD * MODS=(E15=MYE15,E35=MYE35) SORT FIELDS=(1,10,CH,A) OPTION COPY /*
Here, STEPLIB tells the step where to find MYE15 and MYE35. MODS names both modules; OPTION COPY is often used during testing so only the exit and copy logic run. Replace OPTION COPY with a real sort when you are done testing.
In the same step you can specify both an E15 and an E35. E15 runs during the input phase: each time a record is read, DFSORT calls your E15 so you can pass, modify, drop, or expand it. E35 runs during the output phase: each time a record is about to be written, DFSORT calls your E35 so you can modify or drop it. So you can do input-side logic (e.g. parse and filter) in E15 and output-side logic (e.g. format or suppress) in E35. They do not share storage unless you arrange it (e.g. via a common table or dataset); each is called independently with its own parameter list.
You can use MODS in the same step as INREC, OUTREC, INCLUDE, OMIT, OUTFIL, and other control statements. The order in which DFSORT applies them is defined by the product: for example, E15 might run before or after INREC and INCLUDE/OMIT, and E35 might run before or after OUTREC. The DFSORT Application Programming Guide (or equivalent for your product) describes the exact processing order. In general, E15 is on the input side and E35 on the output side, so your exit and the built-in reformatting can both affect the data at different stages. Design your exit assuming it will see the record in the format present at that stage; if INREC has already reformatted the record before E15 runs, your exit sees the reformatted record.
Use INREC and OUTREC when they can do the job: they are easier to change (no compile/link), and they are self-documenting in SYSIN. Use MODS and user exits when you need logic that cannot be expressed with built-in operators—variable-length parsing, one-to-many record creation, calls to other programs or tables, or complex stateful logic. Once you introduce MODS, you also need to manage load libraries and the exit interface; use it when the requirement justifies that extra complexity.
If the step fails with a load error (e.g. "program not found" or an abend indicating the module could not be loaded), the usual cause is that the module is not in the library concatenation or the name in MODS does not match the member name. Check that STEPLIB (or JOBLIB) includes the dataset that contains the member, that the member name matches MODS exactly (including length and case if applicable), and that the dataset is not empty or corrupted. If you use multiple libraries in the concatenation, ensure the correct one is first if the same member name could exist in more than one library.
MODS programming is like telling the sorting machine: "When you work, call these two helpers by name—one when you read a card (E15) and one when you write a card (E35)." You have to put the helpers in a box (the load library) that the machine can open (STEPLIB), and you have to use the exact names (MODS syntax) so the machine knows who to call. If the names or the box are wrong, the machine says "I can't find your helper" and stops.
1. Can you use both an E15 and an E35 exit in the same DFSORT step?
2. Why would you put E15 and E35 in separate load modules?
3. What is the purpose of STEPLIB in a job that uses MODS?
4. How does MODS interact with INREC and OUTREC?
5. What should you do if the job fails with "program not found" when using MODS?