COBOL COBOL 2014 (ISO/IEC 1989:2014), built with GnuCOBOL 3.x Β·
β verified by execution on 2026-08-16
Producing a printed report is one of the most common tasks in a mainframe batch job, and the fiddly part is not the data β it is the paper. Every page needs a heading, every page has a fixed number of usable lines, and something has to notice when the current page is full. Doing that by hand means a line counter threaded through your entire program, incremented in a dozen places and wrong in one of them. COBOL has a built-in answer: the LINAGE clause.
The LINAGE clause allows COBOL to automatically format a sequential file into pages by specifying the logical page size. It also defines margins and footing areas to trigger page breaks.
The LINAGE Clause
When you add the LINAGE clause to a File Description (FD), you define the structure of a page. You can specify the total lines, a top margin, a bottom margin, and a footing area.
A logical page defined by the LINAGE clause. The top and bottom margins are skipped, and the footing area triggers the END-OF-PAGE condition.
Here is a basic example setting up a page with 20 lines, a footing starting at line 18, and margins at the top and bottom. The LINES AT TOP and LINES AT BOTTOM phrases define blank margins that COBOL automatically skips when advancing to a new page or reaching the end of the page body.
cobolβ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. LINAGE-BASIC. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT REPORT-FILE ASSIGN TO "report.txt" ORGANIZATION IS LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD REPORT-FILE LINAGE IS 20 LINES WITH FOOTING AT 18 LINES AT TOP 2 LINES AT BOTTOM 3. 01 REPORT-RECORD PIC X(80). WORKING-STORAGE SECTION. 01 WS-LINE PIC X(80) VALUE "This is a test line.". PROCEDURE DIVISION. OPEN OUTPUT REPORT-FILE WRITE REPORT-RECORD FROM WS-LINE WRITE REPORT-RECORD FROM WS-LINE WRITE REPORT-RECORD FROM WS-LINE AFTER ADVANCING PAGE CLOSE REPORT-FILE STOP RUN.
Output
Your output
The LINAGE-COUNTER Register
When the LINAGE clause is specified, COBOL maintains a special register called LINAGE-COUNTER that tracks the current line number on the page. You do not need to define this in WORKING-STORAGEβCOBOL manages it automatically.
cobolβ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. LINAGE-COUNTER-TEST. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT REPORT-FILE ASSIGN TO "report.txt" ORGANIZATION IS LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD REPORT-FILE LINAGE IS 5 LINES WITH FOOTING AT 4. 01 REPORT-RECORD PIC X(80). WORKING-STORAGE SECTION. 01 WS-LINE PIC X(80) VALUE "Test.". PROCEDURE DIVISION. OPEN OUTPUT REPORT-FILE WRITE REPORT-RECORD FROM WS-LINE DISPLAY LINAGE-COUNTER WRITE REPORT-RECORD FROM WS-LINE DISPLAY LINAGE-COUNTER CLOSE REPORT-FILE STOP RUN.
Output
0000000002
0000000003
Your output
Using WRITE ... AFTER ADVANCING PAGE automatically spaces to the top of the next page and resets LINAGE-COUNTER to 1.
cobolβ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. ADV-PAGE-TEST. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT REPORT-FILE ASSIGN TO "report.txt" ORGANIZATION IS LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD REPORT-FILE LINAGE IS 5 LINES. 01 REPORT-RECORD PIC X(80). WORKING-STORAGE SECTION. 01 WS-LINE PIC X(80) VALUE "Page test". PROCEDURE DIVISION. OPEN OUTPUT REPORT-FILE WRITE REPORT-RECORD FROM WS-LINE DISPLAY LINAGE-COUNTER WRITE REPORT-RECORD FROM WS-LINE AFTER ADVANCING PAGE DISPLAY LINAGE-COUNTER CLOSE REPORT-FILE STOP RUN.
Output
0000000002
0000000001
Your output
Catching the End of the Page
The WITH FOOTING AT phrase defines a footing area at the bottom of the page. Writing into this area triggers the END-OF-PAGE (or EOP) condition, allowing you to print footers or trigger a new page.
Predict the Output
A common misconception is that END-OF-PAGE only triggers exactly when LINAGE-COUNTER reaches the maximum lines of the page. In reality, it triggers on anyWRITE that advances the counter into the footing area or occurs within the footing area.
Read this code carefully. At what line count will the END-OF-PAGE message first appear?
Predict the outputcobol
Read the code. What exactly will it print? Commit to an answer before you look.
IDENTIFICATION DIVISION. PROGRAM-ID. P. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT F ASSIGN "r" ORGANIZATION LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD F LINAGE 5 WITH FOOTING 4. 01 R PIC X. WORKING-STORAGE SECTION. 01 C PIC 9 VALUE 1. PROCEDURE DIVISION. OPEN OUTPUT F. PERFORM 5 TIMES WRITE R FROM "X" AT END-OF-PAGE DISPLAY "EOP " C END-WRITE ADD 1 TO C END-PERFORM. CLOSE F. STOP RUN.
Output
EOP 3
EOP 4
EOP 5
You predicted
Because the footing starts at line 4, writing the third line advances the counter into the footing, triggering the condition. Lines 4 and 5 also occur within the footing, so they trigger it as well.
Printing Page Headings
When formatting a report you will frequently print a page heading at the top of each new page. ADVANCING PAGE handles the form feed for you.
cobolβ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. PAGE-HEADING. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT REPORT-FILE ASSIGN TO "report.txt" ORGANIZATION IS LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD REPORT-FILE LINAGE IS 20 LINES. 01 REPORT-RECORD PIC X(80). WORKING-STORAGE SECTION. 01 WS-HEADING PIC X(80) VALUE "*** MONTHLY SALES REPORT ***". 01 WS-DETAIL PIC X(80) VALUE "Item 1: $100.00". PROCEDURE DIVISION. OPEN OUTPUT REPORT-FILE WRITE REPORT-RECORD FROM WS-HEADING AFTER ADVANCING PAGE WRITE REPORT-RECORD FROM WS-DETAIL AFTER ADVANCING 2 LINES CLOSE REPORT-FILE STOP RUN.
Output
Your output
You can combine END-OF-PAGE with ADVANCING PAGE to automatically print headers on each new page when the page becomes full.
cobolβ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. FOOTING-HEADER. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT REPORT-FILE ASSIGN TO "report.txt" ORGANIZATION IS LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD REPORT-FILE LINAGE IS 5 LINES WITH FOOTING AT 5. 01 REPORT-RECORD PIC X(80). WORKING-STORAGE SECTION. 01 WS-HEADING PIC X(80) VALUE "*** NEW PAGE ***". 01 WS-DETAIL PIC X(80) VALUE "Detail line". PROCEDURE DIVISION. OPEN OUTPUT REPORT-FILE PERFORM 5 TIMES WRITE REPORT-RECORD FROM WS-DETAIL AT END-OF-PAGE WRITE REPORT-RECORD FROM WS-HEADING AFTER ADVANCING PAGE END-WRITE END-PERFORM CLOSE REPORT-FILE STOP RUN.
Output
Your output
Edge Cases
Writing a record when LINAGE-COUNTER is already at the maximum LINAGE lines will roll it over to 1 and start a new page automatically.
A WRITE statement with BEFORE ADVANCING may still trigger END-OF-PAGE if the subsequent advance pushes the counter into the footing.
Check yourself
How does COBOL know when to automatically generate the LINAGE-COUNTER special register?
Reveal answer
It is generated automatically whenever you add the LINAGE clause to a file description entry β If you use the LINAGE clause, COBOL automatically creates and maintains the LINAGE-COUNTER special register for you. LINAGE is part of standard sequential file I/O and does not require the Report Writer module.
When does the END-OF-PAGE condition trigger during a WRITE?
Reveal answer
Any time a WRITE occurs within or advances into the footing area β END-OF-PAGE triggers on any WRITE that advances the counter into the footing area (defined by WITH FOOTING AT) or occurs within the footing area.
What does WRITE ... AFTER ADVANCING PAGE actually do to the file?
Reveal answer
It sends a form-feed character (or blank lines) to start a new logical page and resets LINAGE-COUNTER β ADVANCING PAGE sends a form-feed character (or pads with blank lines) to start a new logical page and resets LINAGE-COUNTER.
Can you use the LINAGE clause in a standard sequential file without using the Report Writer module?
Reveal answer
Yes, LINAGE is part of standard sequential file I/O β LINAGE is part of standard sequential file I/O and does not require the Report Writer module.
Challenges
Challenge 1 +15 XP
Fix the FD so that the report has 30 lines per page, a footing starting at line 25, a top margin of 3 lines, and a bottom margin of 2 lines.
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 LINAGE IS ... WITH FOOTING AT ... LINES AT TOP ... LINES AT BOTTOM ...
Show solution (0 XP)
IDENTIFICATION DIVISION. PROGRAM-ID. CHALLENGE. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT RPT-FILE ASSIGN TO "report.txt" ORGANIZATION IS LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD RPT-FILE LINAGE IS 30 LINES WITH FOOTING AT 25 LINES AT TOP 3 LINES AT BOTTOM 2. 01 RPT-REC PIC X(80). PROCEDURE DIVISION. STOP RUN.
π Bug Hunt+15 XP
Complete the WRITE statement to display 'FOOTING REACHED' when the end-of-page condition occurs. There is a bug in the starter codeβfix it so it correctly detects the footing.
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 "FOOTING REACHED\nFOOTING REACHED\n"
Need a hint? (β25% XP)
Use AT END-OF-PAGE instead of AT END-OF-FILE to detect when the LINAGE-COUNTER enters the footing area.
Show solution (0 XP)
IDENTIFICATION DIVISION. PROGRAM-ID. CHALLENGE. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT RPT-FILE ASSIGN TO "report.txt" ORGANIZATION IS LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD RPT-FILE LINAGE IS 5 LINES WITH FOOTING AT 4. 01 RPT-REC PIC X(80). WORKING-STORAGE SECTION. 01 WS-LINE PIC X(80) VALUE "Line". PROCEDURE DIVISION. OPEN OUTPUT RPT-FILE PERFORM 4 TIMES WRITE RPT-REC FROM WS-LINE AT END-OF-PAGE DISPLAY "FOOTING REACHED" END-WRITE END-PERFORM CLOSE RPT-FILE STOP RUN.