COBOL COBOL 2014 (ISO/IEC 1989:2014), built with GnuCOBOL 3.x ·
✓ verified by execution on 2026-08-16
In the real world of mainframe execution, job control scripts can get massive. Imagine having a fifty-line script that compiles, binds, and executes a program, and you need to run it for twenty different datasets. Writing out a thousand lines of JCL would be an unmaintainable nightmare.
To solve this, JCL uses Procedures (PROCs). A PROC is a pre-written, reusable segment of JCL that can be invoked repeatedly from different calling jobs using a simple EXEC statement. You can think of a PROC as a function or method in a standard programming language, but for job control.
Symbolic Parameters
When you call a PROC, you often need to change a few details—like what dataset it reads from. JCL accomplishes this through symbolic parameters. A symbolic parameter is a placeholder name preceded by an ampersand (&).
Here is the whole mechanism in two short members. This is real JCL as it would be catalogued on z/OS; it cannot run here, because nothing off the mainframe reads it.
//* ---- the PROC, catalogued once and reused ----//MYPROC PROC INFILE='TEST.DATA.SET'//PSTEP1 EXEC PGM=COBPROG//STEPLIB DD DSN=PROD.LOADLIB,DISP=SHR//INFILE DD DSN=&INFILE,DISP=SHR//SYSOUT DD SYSOUT=*// PEND//*//* ---- a job that calls it, overriding the symbol ----//MYJOB JOB (ACCT01),'NIGHTLY',CLASS=A//STEP1 EXEC PROC=MYPROC,INFILE='PROD.DATA.SET'
The PROC line declares the symbol and gives it a default — TEST.DATA.SET. That default is the safety net: run the PROC with no override and it reads test data, not production. The calling job supplies INFILE='PROD.DATA.SET', which replaces &INFILE everywhere it appears before the step runs.
This is where the classic production incident comes from. Misspell the symbol on the EXEC line — INFIL= instead of INFILE= — and JCL does not stop. The override simply never matches, the default stands, and the nightly job quietly reads the test dataset. Nothing errors, the return code is zero, and the numbers are wrong. The habit that saves you is making the default obviously non-production, exactly as above, so a failed override looks wrong immediately instead of plausibly.
Running locally with GnuCOBOL there is no JCL, but the same shape exists: pass the value as an environment variable and read it with ACCEPT ... FROM ENVIRONMENT.
cobol✓ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. SYMBOL-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 INFILE-PARM PIC X(20). PROCEDURE DIVISION. ACCEPT INFILE-PARM FROM ENVIRONMENT "MY_PARM". IF INFILE-PARM = SPACES DISPLAY "No parameter passed!" ELSE DISPLAY "Processing dataset: " INFILE-PARM END-IF. STOP RUN.
Output
No parameter passed!
Your output
DD Overrides
Sometimes, a PROC is 99% perfect, but you need to change one specific file definition for a single run without altering the reusable PROC itself. You can achieve this using a DD override.
By supplying a DD statement in your calling job that matches the stepname.ddname of the PROC, the mainframe will substitute your custom definition over the PROC’s default. Like symbolic parameters, this allows flexible execution of a single compiled program against many different data sources.
What happens if you use ACCEPT FROM ENVIRONMENT to simulate a numeric variable passing, and do arithmetic on it? Predict the output of this snippet. (Assume VAL is mapped to the string “05”).
Predict the outputcobol
Read the code. What exactly will it print? Commit to an answer before you look.
IDENTIFICATION DIVISION. PROGRAM-ID. PREDICT-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 INPUT-VAL PIC 99. 01 RESULT PIC 99. PROCEDURE DIVISION. ACCEPT INPUT-VAL FROM ENVIRONMENT "VAL". IF INPUT-VAL = 00 MOVE 05 TO INPUT-VAL END-IF. COMPUTE RESULT = INPUT-VAL * 3. DISPLAY RESULT. STOP RUN.
Output
15
You predicted
Because VAL was unassigned in this snippet’s simulated environment, ACCEPT pulls in blanks or zeroes (depending on compiler). The IF block catches the 00 value and assigns 05. 05 * 3 gives 15. This demonstrates how programs can provide fallback defaults when symbolic parameters or overrides are omitted.
Check yourself
What is the primary purpose of a JCL PROC?
Reveal answer
To group reusable JCL statements so they can be invoked repeatedly. — A PROC (Procedure) is a pre-written segment of JCL that can be invoked repeatedly from different calling jobs using a simple EXEC statement, promoting reuse.
Which symbol is used to define a symbolic parameter in JCL?
Reveal answer
Ampersand (&) — Symbolic parameters in JCL use an ampersand (&) followed by the parameter name, like &DSNAME.
When applying a DD override, what determines which DD statement in the PROC is overridden?
Reveal answer
The stepname.ddname specified in the calling job. — A DD override is specified in the calling job by prefixing the DD name with the step name from the PROC, as in //stepname.ddname DD ...
Challenges
Challenge 1 +50 XP
Read the symbolic parameter 'ENV_DSN' from the environment.
cobol✓ solution verified at build time
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real — it came from compiling the solution with GnuCOBOL when this page
was built.
Test 1 — expects " "
Need a hint? (−25% XP)
Use ACCEPT ... FROM ENVIRONMENT to read the simulated parameter.
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real — it came from compiling the solution with GnuCOBOL when this page
was built.
The PROC was supposed to override SYSOUTCLASS, but the override never arrived — so the program routes the report to a blank class instead of failing or defaulting. Make it detect the missing override and fall back to class A.
This code runs. It just does the wrong thing. Read it, find the defect,
fix it — the tests below decide when you are right.
cobol✓ solution verified at build time
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real — it came from compiling the solution with GnuCOBOL when this page
was built.
Test 1 — expects "OVERRIDE NOT SUPPLIED - DEFAULTING\nROUTING REPORT TO CLASS: A\n"
Need a hint? (−25% XP)
An override that did not happen leaves the field exactly as you initialised it. Test for that before using the value.
Show solution (0 XP)
IDENTIFICATION DIVISION. PROGRAM-ID. ProcOverride. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-SYSOUT-CLASS PIC X(1) VALUE SPACE. PROCEDURE DIVISION. ACCEPT WS-SYSOUT-CLASS FROM ENVIRONMENT "SYSOUTCLASS" IF WS-SYSOUT-CLASS = SPACE MOVE "A" TO WS-SYSOUT-CLASS DISPLAY "OVERRIDE NOT SUPPLIED - DEFAULTING" END-IF DISPLAY "ROUTING REPORT TO CLASS: " WS-SYSOUT-CLASS STOP RUN.