Program Structure and Divisions
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This page is written against ISO/IEC 1989:2023 (edition 3, January 2023; a 4th edition is upcoming), GnuCOBOL 3.2 and IBM
Enterprise COBOL for z/OS 6.5, checked on 2026-10-20. Every program below was compiled with cobc -x -Wall (GnuCOBOL 3.2.0)
and run. The ones presented as working compiled without warnings (also under -std=ibm), and the deliberately wrong ones
show the real diagnostics. The examples use the Circulation library scenario of this section (BOOKMAST, copybook
BOOKREC).
The page covers the skeleton that every COBOL source file shares: which pieces a program is made of, in which order they appear, and how a program ends. The data descriptions are on Data Division and Level Numbers, the statements start with MOVE and Data Movement, and the column rules that make this text legal are on Reference Format: Fixed and Free. If you have not compiled a COBOL program yet, start with Getting Started.
The hierarchy: divisions down to statements
A COBOL source text is a strict hierarchy. A program has up to four divisions, in a fixed order. Divisions contain sections, sections contain paragraphs, paragraphs contain sentences, and sentences contain statements.
The figure above is the containment tree; the table below says what each level is and how it is written.
| Level | What it is | How it is written |
|---|---|---|
Division |
One of four top-level parts. They must appear in the order identification, environment, data, procedure. |
A header such as |
Section |
A named group of paragraphs (procedure division) or of related entries (the other divisions). |
|
Paragraph |
A named group of sentences. In the procedure division the name is yours and is the target of |
|
Sentence |
One or more statements ended by a period. A period also ends the scope of every open |
Statements followed by |
Statement |
A verb with its operands, such as |
|
Which parts are required differs by standard and compiler. In the ISO standard only PROGRAM-ID is mandatory in the
identification division, and the other three divisions can be left out. In practice a main program always has a procedure
division, and a program that handles files or data has the other two. Section and paragraph names are the targets that PERFORM can name, and they start in Area A like the division headers; the area
rules are on the reference-format page linked above. Procedure division sections are optional: a program can be made of paragraphs
only, or of sections that hold paragraphs. Do not mix the two styles in one division, because paragraphs placed before
the first section header are not allowed once sections are used.
The IDENTIFICATION DIVISION
The identification division names the program. It starts with IDENTIFICATION DIVISION. (in a free-format source, the
abbreviation ID DIVISION. is accepted by Enterprise COBOL and GnuCOBOL) and holds paragraphs. PROGRAM-ID is the only paragraph the
current standard and the compilers require.
PROGRAM-ID
The PROGRAM-ID paragraph gives the program-name and optional attributes. Written readably, the forms used in practice are:
| Form | Meaning |
|---|---|
|
Plain name. This is the name a |
|
Every call starts the program with its data in the state the data division describes (the |
|
The program may call itself directly or indirectly. Each activation gets its own |
|
Only for a nested program: it may be called by every program inside the same containing program, not only by the one that directly contains it. See the nested programs section below. |
|
COBOL 2002 form that gives the external name as a literal, so the name used on a |
A program-name is a user-defined word, with length limits that each compiler documents. The attributes COMMON and INITIAL can
appear together on a nested program, and COMMON and RECURSIVE do not go together because RECURSIVE is for an outermost program.
Obsolete paragraphs
Five old paragraphs exist only to carry text for the human reader: AUTHOR, INSTALLATION, DATE-WRITTEN, DATE-COMPILED and
SECURITY. They are flagged obsolete since COBOL 85, are not read by the compiler (the text is a comment-entry), and are still
accepted so that old programs keep compiling. Use *> or a column-7 * comment and source control instead. GnuCOBOL says so
with the default dialect:
IDENTIFICATION DIVISION.
PROGRAM-ID. OLDSTYLE.
AUTHOR. LIBRARY IT.
DATE-WRITTEN. 1989-03-01.
PROCEDURE DIVISION.
STOP RUN.
author.cob:3: warning: AUTHOR is obsolete in GnuCOBOL [-Wobsolete]
author.cob:4: warning: DATE-WRITTEN is obsolete in GnuCOBOL [-Wobsolete]
This is old code you may meet; the same program compiled with -std=ibm is accepted without a message, because the IBM
dialect still supports the paragraphs. Do not write new programs this way.
Source: GnuCOBOL Manual
The ENVIRONMENT DIVISION
The environment division describes what the program depends on outside itself. It has two sections, both optional:
-
The CONFIGURATION SECTION holds the paragraphs
SOURCE-COMPUTER,OBJECT-COMPUTER,SPECIAL-NAMESandREPOSITORY. -
The INPUT-OUTPUT SECTION holds
FILE-CONTROL(oneSELECTper file) andI-O-CONTROL.
SOURCE-COMPUTER and OBJECT-COMPUTER
These two paragraphs name the machine that compiles and runs the program. They are documentation in nearly every
modern compiler. OBJECT-COMPUTER is where the program collating sequence is selected with PROGRAM COLLATING SEQUENCE IS alphabet-name
(the alphabet is defined in SPECIAL-NAMES). Enterprise COBOL also accepts the WITH DEBUGGING MODE clause on SOURCE-COMPUTER
for the old debugging lines.
SPECIAL-NAMES
SPECIAL-NAMES relates implementor names to your names and sets program-wide conventions. The entries you will meet most are:
| Entry | Purpose |
|---|---|
|
Swaps the roles of the period and the comma in |
|
Chooses the character that the |
|
Defines a user class of characters, usable in a class condition such as |
|
Gives a name to a character by its ordinal position in the collating sequence, which starts at 1. So the byte value is the ordinal minus one. |
|
Defines a character set or collating sequence ( |
mnemonic names, for example |
Relates an implementor-defined device or feature name (printer channel, console, |
|
Screen handling entries; see the console input and output page. |
Here is a complete program that uses three of the entries, with the other divisions kept minimal. It lists the book master using
CLASS for the ISBN check, CURRENCY SIGN for the price and SYMBOLIC CHARACTERS for a separator:
IDENTIFICATION DIVISION.
PROGRAM-ID. BOOKLIST.
* List the Circulation book master with a symbolic currency.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
CURRENCY SIGN IS "#"
CLASS ISBN-CHAR IS "0" THRU "9" "X"
SYMBOLIC CHARACTERS BAR-CHAR ARE 125.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT BOOK-FILE ASSIGN TO "BOOKMAST"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-BOOK-STATUS.
DATA DIVISION.
FILE SECTION.
FD BOOK-FILE.
COPY BOOKREC.
WORKING-STORAGE SECTION.
01 WS-BOOK-STATUS PIC XX.
01 WS-EOF PIC X VALUE "N".
88 END-OF-BOOKS VALUE "Y".
01 WS-PRICE-OUT PIC ###,##9.99.
PROCEDURE DIVISION.
MAIN-LINE SECTION.
MAIN-PARA.
OPEN INPUT BOOK-FILE
PERFORM UNTIL END-OF-BOOKS
READ BOOK-FILE
AT END SET END-OF-BOOKS TO TRUE
NOT AT END PERFORM SHOW-BOOK
END-READ
END-PERFORM
CLOSE BOOK-FILE
STOP RUN.
SHOW-BOOK.
MOVE BOOK-PRICE TO WS-PRICE-OUT
IF BOOK-ISBN IS ISBN-CHAR
DISPLAY BOOK-ID BAR-CHAR BOOK-TITLE BAR-CHAR WS-PRICE-OUT
ELSE
DISPLAY BOOK-ID " bad ISBN"
END-IF.
END PROGRAM BOOKLIST.
It compiled without warnings and printed the real data of the scenario (character 124 is the vertical bar, ordinal 125):
000001|DATA STRUCTURES | #25.00
000002|COBOL BASICS | #19.99
000003|BATCH PROCESSING | #30.50
000004|OLD LEDGERS | #12.00
Three details in that program are common stumbling blocks.
-
PICTUREcharacters such asE,P,S,V,XandZ, and the digits, keep their picture meaning, and the compiler rejects them as a currency sign. The first attempt used"E"; GnuCOBOL answers with real diagnostics:bad-currency.cob:7: warning: separate currency symbol and currency string is not implemented [-Wpending] bad-currency.cob:7: error: invalid character 'E' in currency symbol bad-currency.cob:23: error: invalid PICTURE character 'E' bad-currency.cob:23: error: a Z or * which is before the decimal point cannot follow EThat version was deliberately wrong: it used the
WITH PICTURE SYMBOL "E"form andEin the picture. The symbol must be a character that is not used inPICTUREstrings, and it is written repeated (###,##9.99) in the edited item. -
Ordinal positions start at 1, so
SYMBOLIC CHARACTERS TAB-CHAR ARE 9is the backspace (byte 8), not the tab. The tab is ordinal 10 (byte 9). -
The
CLASSconditionIF BOOK-ISBN IS ISBN-CHARis true only when every character of the field belongs to the class. A field padded with spaces fails it, so test the exact size or a reference-modified part.
Using DECIMAL-POINT IS COMMA shows how much one entry changes. The numeric literal 12,50 and the edited picture
ZZ.ZZ9,99 follow the comma convention, and the program is otherwise unchanged:
IDENTIFICATION DIVISION.
PROGRAM-ID. FINEFMT.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
DECIMAL-POINT IS COMMA.
REPOSITORY.
FUNCTION UPPER-CASE TRIM INTRINSIC.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-NAME PIC X(30) VALUE " Grace Hopper".
01 WS-FINE PIC S9(5)V99 VALUE 12,50.
01 WS-FINE-OUT PIC ZZ.ZZ9,99.
PROCEDURE DIVISION.
MOVE WS-FINE TO WS-FINE-OUT
DISPLAY UPPER-CASE(TRIM(WS-NAME)) " owes " WS-FINE-OUT
STOP RUN.
END PROGRAM FINEFMT.
GRACE HOPPER owes 12,50
Source: GnuCOBOL Manual
REPOSITORY
The REPOSITORY paragraph declares the names of the classes, interfaces, user-defined functions and (in COBOL 2014 and later)
intrinsic functions that the program refers to, optionally mapping each to an external name. In the program above,
FUNCTION UPPER-CASE TRIM INTRINSIC. lets the source use UPPER-CASE(...) and TRIM(...) without the FUNCTION keyword.
Without a REPOSITORY entry (or the FUNCTION ALL INTRINSIC form) every call to an intrinsic function must be written with
FUNCTION, as in FUNCTION UPPER-CASE(WS-NAME). Enterprise COBOL uses REPOSITORY for classes and for FUNCTION-ID
user-defined functions (6.4 and later); see the intrinsic functions page for the function side. The exact list syntax is compiler specific
in GnuCOBOL: the names are listed after one FUNCTION keyword and the list ends with INTRINSIC, and cobc 3.2 reports
expecting intrinsic function name or INTRINSIC when it is left out.
The INPUT-OUTPUT SECTION
FILE-CONTROL has one SELECT entry per file, tying the program’s file name to a physical file and fixing its organization
and access mode; I-O-CONTROL holds rarely used entries such as SAME AREA. The entries are the subject of
File Concepts, SELECT and FD. The program above shows the
shape: SELECT BOOK-FILE ASSIGN TO "BOOKMAST" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WS-BOOK-STATUS.
The DATA DIVISION and the PROCEDURE DIVISION
The data division has up to six sections, in this order when present: FILE SECTION (record layouts of the FD and SD entries),
WORKING-STORAGE SECTION (data allocated once for the run unit), LOCAL-STORAGE SECTION (data allocated afresh on each
invocation), LINKAGE SECTION (the parameters a program receives, and data it addresses), plus the COMMUNICATION SECTION
and REPORT SECTION / SCREEN SECTION where the compiler supports them. A copybook such as BOOKREC is pulled in with COPY
(see Copybooks and REPLACE).
The procedure division holds the executable logic. A main program normally has PROCEDURE DIVISION.. A program that
receives parameters adds USING (and RETURNING), as in PROCEDURE DIVISION USING LK-TOTAL. below. Execution begins at
the first paragraph or section and runs on until a statement stops it or control falls off the end, so every program ends
explicitly, as the last section of this page shows. In the Circulation program above, MAIN-LINE SECTION holds
MAIN-PARA, and SHOW-BOOK is a second paragraph that PERFORM SHOW-BOOK runs. Put loops and tests in separate paragraphs
and call them with PERFORM; the structured style is on
PERFORM and Structured Programming.
A period ends a sentence and, with it, every statement scope still open. Writing scope terminators (END-IF, END-READ,
END-PERFORM) and putting a single period at the end of the paragraph, as the examples do, avoids the classic bug in which a
stray period closes an IF early.
Nested programs, COMMON and several programs in one file
Besides separate source files, COBOL offers a way to keep a small private helper next to its user. A nested program is a complete program (all four divisions) written
inside another program, between its procedure division and its END PROGRAM. A source file may also contain several
programs one after another (a batch compile). Both forms need END PROGRAM name. so the compiler knows where each one stops.
The names are the first rule. A nested program can be called with CALL "name" only by the program that directly contains it,
unless it is declared COMMON, in which case any program inside the same container can call it, including its siblings.
A program cannot call a program that contains it. The second rule is the data: names declared in a program are local to it,
so two programs can each have WS-CALLS, and a nested program can see a name of its container only if that name is declared
GLOBAL. The program below has an outer NIGHTLY program and three nested programs:
-
COUNTERkeeps its data between calls (the default). -
FRESHisINITIAL, so its data is reset on every call. -
SHOWERisCOMMON, and is called by the siblingsCOUNTERandFRESH, not byNIGHTLY.
COUNTER and FRESH end differently on purpose: EXIT PROGRAM and GOBACK, which the next section compares.
IDENTIFICATION DIVISION.
PROGRAM-ID. NIGHTLY.
* Outer program with two nested programs.
PROCEDURE DIVISION.
MAIN-PARA.
CALL "COUNTER"
CALL "COUNTER"
CALL "FRESH"
CALL "FRESH"
STOP RUN.
IDENTIFICATION DIVISION.
PROGRAM-ID. COUNTER.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-CALLS PIC 9(4) VALUE ZERO.
PROCEDURE DIVISION.
ADD 1 TO WS-CALLS
CALL "SHOWER" USING WS-CALLS
EXIT PROGRAM.
END PROGRAM COUNTER.
IDENTIFICATION DIVISION.
PROGRAM-ID. FRESH IS INITIAL.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-CALLS PIC 9(4) VALUE ZERO.
PROCEDURE DIVISION.
ADD 1 TO WS-CALLS
CALL "SHOWER" USING WS-CALLS
GOBACK.
END PROGRAM FRESH.
IDENTIFICATION DIVISION.
PROGRAM-ID. SHOWER IS COMMON.
DATA DIVISION.
LINKAGE SECTION.
01 LK-TOTAL PIC 9(4).
PROCEDURE DIVISION USING LK-TOTAL.
DISPLAY "calls so far: " LK-TOTAL
GOBACK.
END PROGRAM SHOWER.
END PROGRAM NIGHTLY.
calls so far: 0001
calls so far: 0002
calls so far: 0001
calls so far: 0001
COUNTER counts 1 and 2 because its WS-CALLS lives for the whole run unit. FRESH prints 1 twice, because INITIAL gives it a
new copy each time. SHOWER is reached through a COMMON attribute, from two siblings that it does not belong to.
Nested and multiple programs have practical limits you should know:
-
The
END PROGRAMheader is required whenever a file holds more than one program. Leaving it out is an error in GnuCOBOL:noend.cob:11: error: multiple PROGRAM-ID's without matching END PROGRAMThat file was deliberately wrong: two programs,
FIRSTandSECOND, with noEND PROGRAMlines. -
Which program of a multi-program file runs first depends on how the file is built; with
cobc -xit is the first one. The build options are on Getting Started. -
Nested programs share the compilation but not the data, and they cannot be replaced independently. Real systems keep each reusable program in its own source and call it by name (a "dynamic call", see Subprograms, CALL and Linkage); nesting is useful for small private helpers.
-
Enterprise COBOL supports nested programs and batch compilation (several outermost programs in one compilation unit), and enforces the rule that
RECURSIVEappears only on an outermost program.
STOP RUN, GOBACK and EXIT PROGRAM
Three statements end a program, and picking the wrong one is a classic bug in called programs. The IBM documentation gives this
behaviour (the Language Reference tables for STOP, GOBACK and EXIT):
| Statement | In a main program | In a called subprogram |
|---|---|---|
|
Ends the run unit, closes every file of every program in it, and returns to the caller of the run unit (the system, which
ends the application). The |
Ends the whole run unit, not just the subprogram. Control goes to the program that called the main program. |
|
Works like |
Works like |
|
Does not end a main program: control continues with the next statement. Do not use it there. |
Returns to the statement after the |
The practical rule: use GOBACK in every program, because it does the right thing whether the program was started as the
main program or called as a subprogram. Use STOP RUN only in the main program when you want it to be obvious that the program
ends the run, and never in a subprogram that other programs call. EXIT PROGRAM belongs only in called programs. The next program shows what STOP RUN
does in a subprogram. DRIVER calls QUITTER, which ends the run unit, so the message after the CALL is never shown:
IDENTIFICATION DIVISION.
PROGRAM-ID. DRIVER.
PROCEDURE DIVISION.
CALL "QUITTER"
DISPLAY "DRIVER: back from QUITTER"
STOP RUN.
END PROGRAM DRIVER.
IDENTIFICATION DIVISION.
PROGRAM-ID. QUITTER.
PROCEDURE DIVISION.
DISPLAY "QUITTER: about to STOP RUN"
STOP RUN.
END PROGRAM QUITTER.
QUITTER: about to STOP RUN
Source: Enterprise COBOL 6.5 Language Reference: STOP statement, GOBACK statement and EXIT statement
A main program that returns a status to the job passes it through RETURN-CODE before it ends (MOVE 8 TO RETURN-CODE
then GOBACK); the job control language (JCL) on z/OS tests it as the step condition code. The error handling page covers
that convention.
Compiler differences and where the book is outdated
-
Standard. The four-division structure,
PROGRAM-ID, nested programs,COMMON,INITIALandRECURSIVEare in the standard since COBOL 85 (RECURSIVEsince COBOL 2002).REPOSITORYand theFUNCTION ... INTRINSICentries come from COBOL 2002. Free format (no columns) is also from COBOL 2002. The 2014 and 2023 editions leave the program structure the same. -
Enterprise COBOL for z/OS 6.5. It supports nested programs and
END PROGRAM,REPOSITORYfor classes and user-defined functions, and keeps the obsolete identification paragraphs for compatibility. Enterprise COBOL 6.4 addedFUNCTION-IDuser-defined functions. -
GnuCOBOL 3.2. It accepts the structure above, warns about obsolete paragraphs unless
-std=ibmis used, requiresEND PROGRAMfor multiple programs, and does not fully implementCURRENCY SIGN ... WITH PICTURE SYMBOL. Use-std=ibmto check that a program stays within IBM syntax. -
The book. Taulli (Modern Mainframe Development, 2022) introduces the four divisions as a fixed template and leans on Enterprise COBOL 6.3 as the newest compiler. The structure it describes is still correct, but the compiler is two releases behind: 6.5 is current, and the standard it cites stops at COBOL 2002 although 2014 and 2023 were published. Its PC examples were run with OpenCobolIDE, which is no longer maintained; compile with GnuCOBOL 3.2 instead.