> "The structure of a COBOL program is not merely organizational convenience -- it is the language's philosophy made manifest. Every division, every section, every paragraph exists because the creators of COBOL believed that programs should be as...
In This Chapter
- 2.1 Introduction: The Architecture of a COBOL Program
- 2.2 The Reference Format: Columns and Areas
- 2.3 Fixed-Format vs. Free-Format COBOL
- 2.4 The IDENTIFICATION DIVISION
- 2.5 The ENVIRONMENT DIVISION
- 2.6 The DATA DIVISION
- 2.7 The PROCEDURE DIVISION
- 2.8 The Period: Statement Terminator and Scope Delimiter
- 2.9 Naming Rules for User-Defined Words
- 2.10 COBOL Program Compilation and Execution Flow
- 2.11 Building a Program from Scratch: A Complete Walkthrough
- 2.15 Summary
Chapter 2: COBOL Program Structure -- Divisions, Sections, and Paragraphs
"The structure of a COBOL program is not merely organizational convenience -- it is the language's philosophy made manifest. Every division, every section, every paragraph exists because the creators of COBOL believed that programs should be as readable and well-organized as business documents."
2.1 Introduction: The Architecture of a COBOL Program
If you were to design a programming language for business, how would you organize a program? The designers of COBOL answered this question in 1959 with an architectural decision that has endured for over six decades: the four-division structure.
Every COBOL program -- whether it is ten lines or ten thousand -- follows the same fundamental blueprint. This blueprint divides a program into four distinct sections, each with a clearly defined purpose:
- IDENTIFICATION DIVISION -- Who is this program?
- ENVIRONMENT DIVISION -- Where does it run?
- DATA DIVISION -- What data does it use?
- PROCEDURE DIVISION -- What does it do?
This structure is not optional. It is not a convention or a best practice. It is a language requirement. The divisions must appear in this exact order, and together they define every aspect of a COBOL program's identity, environment, data, and logic.
Before we explore each division in depth, let us first understand the physical layout of COBOL source code, because the structure of a COBOL program begins at the level of individual columns on a line.
2.2 The Reference Format: Columns and Areas
COBOL was born in an era when programs were written on 80-column punched cards. Each card held one line of code, and specific columns had specific meanings. This fixed reference format has survived into the modern era, and understanding it is essential for reading and writing COBOL.
2.2.1 The Six Areas of a COBOL Line
Every line in a fixed-format COBOL program is divided into six areas:
| Area | Columns | Purpose |
|---|---|---|
| Sequence Number Area | 1-6 | Line numbering (ignored by compiler) |
| Indicator Area | 7 | Comment, continuation, or debug marker |
| Area A | 8-11 | Division headers, section headers, paragraph names, level indicators (01, 77, FD, SD) |
| Area B | 12-72 | Statements, clauses, sentences, continuation text |
| Identification Area | 73-80 | Program identification (ignored by compiler) |
Here is a visual representation:
Column: 1234567890123456789012345678901234567890...7273747576777879 80
| || | | |
Seq# |A B ........(program text)....... Identification
Ind Area A starts here (col 8) Area (ignored)
2.2.2 The Sequence Number Area (Columns 1-6)
In the punched-card era, these six columns held numeric sequence numbers so that if a deck of cards was dropped, they could be reassembled in the correct order. Modern compilers ignore these columns entirely, but they remain part of the format specification.
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. EXAMPLE.
000300 PROCEDURE DIVISION.
000400 DISPLAY "HELLO, WORLD"
000500 STOP RUN.
You may leave columns 1-6 blank (and most modern programmers do), or fill them with any characters. The compiler will not process them.
2.2.3 The Indicator Area (Column 7)
Column 7 is the indicator area -- a single column with significant power. The character placed here determines how the compiler treats the rest of the line:
| Character | Meaning |
|---|---|
| (space) | Normal source line |
* |
Comment line (entire line is ignored) |
/ |
Comment line with page eject in listing |
D or d |
Debugging line (compiled only when DEBUGGING MODE is active) |
- |
Continuation of previous line |
Comment Lines:
* This entire line is a comment.
* The compiler ignores everything on this line.
/ This is also a comment, but forces a new page in the listing.
Comments are your primary documentation tool in COBOL. Use them liberally to explain the purpose of sections, paragraphs, and complex logic.
Debugging Lines:
D DISPLAY "DEBUG: WS-COUNTER = " WS-COUNTER
D DISPLAY "DEBUG: ENTERING 2000-PROCESS"
Debugging lines are compiled only when WITH DEBUGGING MODE is specified in the SOURCE-COMPUTER paragraph. Without it, the compiler treats these lines as comments. This provides a built-in mechanism for conditional compilation of debug code.
Continuation Lines:
When a literal or word is too long to fit on a single line, you use a continuation line:
01 WS-LONG-MESSAGE PIC X(80) VALUE "THIS IS A VER
- "Y LONG STRING THAT CONTINUES ON THE NEXT LINE".
The rules for continuation are:
1. Place a hyphen (-) in column 7 of the continuation line
2. For non-literal continuation, the text continues in Area B (column 12 or later)
3. For literal continuation, close the quote on the first line at or before column 72, then on the continuation line place the hyphen in column 7 and reopen the quote before continuing the text
2.2.4 Area A (Columns 8-11) and Area B (Columns 12-72)
The distinction between Area A and Area B is one of the most important formatting rules in COBOL. Certain elements must begin in Area A, while others must begin in Area B.
Must begin in Area A (columns 8-11):
- Division headers (IDENTIFICATION DIVISION.)
- Section headers (WORKING-STORAGE SECTION.)
- Paragraph names (0000-MAIN.)
- Level indicators: FD, SD, 01, 77
- END PROGRAM header
Must begin in Area B (columns 12-72):
- Statements and sentences (DISPLAY "HELLO", MOVE X TO Y)
- Clauses and entries within a statement
- Level numbers 02 through 49, 66, 88
- Continuation text
Here is a properly formatted example showing Area A and Area B usage:
IDENTIFICATION DIVISION. <- Area A
PROGRAM-ID. AREADEMO. <- Area A
DATA DIVISION. <- Area A
WORKING-STORAGE SECTION. <- Area A
01 WS-NAME PIC X(20). <- Area A (01)
05 WS-FIRST PIC X(10). <- Area B (05)
05 WS-LAST PIC X(10). <- Area B (05)
77 WS-COUNT PIC 9(5). <- Area A (77)
PROCEDURE DIVISION. <- Area A
0000-MAIN. <- Area A
DISPLAY "HELLO" <- Area B
STOP RUN. <- Area B
2.2.5 The Identification Area (Columns 73-80)
Columns 73-80 were historically used to identify the program or punch card deck. The compiler ignores these columns entirely. In practice, modern programmers rarely use them.
2.3 Fixed-Format vs. Free-Format COBOL
The column-based layout described above is called fixed reference format (or simply fixed format). It is the traditional format and remains dominant in production mainframe environments. However, COBOL-2002 introduced free reference format (free format), which removes column restrictions entirely.
2.3.1 Free-Format Rules
In free format:
- Code can start in any column
- There is no sequence number area, indicator area, or identification area
- Lines can be up to 255 characters (compiler-dependent; some allow more)
- There is no Area A / Area B distinction
- Comments begin with *> and can appear anywhere on a line (including inline)
- Debugging lines use >>D at the start of the line
- Continuation uses ampersand (&) for literal concatenation instead of the column-7 hyphen
2.3.2 Side-by-Side Comparison
Fixed Format:
* This is a comment
IDENTIFICATION DIVISION.
PROGRAM-ID. EXAMPLE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-MSG PIC X(50) VALUE
- "HELLO FROM FIXED FORMAT".
PROCEDURE DIVISION.
0000-MAIN.
D DISPLAY "DEBUG MODE ON"
DISPLAY WS-MSG
STOP RUN.
Free Format:
*> This is a comment
identification division.
program-id. Example.
data division.
working-storage section.
01 ws-msg pic x(50) value
"HELLO FROM FREE FORMAT".
procedure division.
0000-main.
>>D display "DEBUG MODE ON"
display ws-msg
stop run.
2.3.3 Enabling Free Format
The method for enabling free format depends on your compiler:
| Compiler | Method |
|---|---|
| GnuCOBOL | -free command-line flag, or >>SOURCE FORMAT IS FREE directive |
| Micro Focus | $SET SOURCEFORMAT"FREE" directive |
| IBM Enterprise COBOL | PROCESS FREE or CBL FREE statement |
| Fujitsu NetCOBOL | Compiler option setting |
2.3.4 Which Format Should You Use?
For new projects, free format offers clear advantages: more readable code, longer lines, inline comments, and a more familiar feel for programmers coming from other languages. However, the vast majority of existing COBOL code -- billions of lines -- is in fixed format. If you will be maintaining legacy systems, you must be fluent in fixed format. This book uses fixed format as the primary format with free-format equivalents shown for comparison, because fixed format remains the industry standard for production COBOL.
2.4 The IDENTIFICATION DIVISION
The IDENTIFICATION DIVISION is the only required division in a COBOL program. Its primary purpose is to name the program and provide documentation metadata.
2.4.1 Syntax
IDENTIFICATION DIVISION.
PROGRAM-ID. program-name [IS INITIAL | COMMON | RECURSIVE].
AUTHOR. author-name.
INSTALLATION. installation-description.
DATE-WRITTEN. date-text.
DATE-COMPILED. date-text.
SECURITY. security-description.
In COBOL-2002 and later, you can abbreviate the header:
ID DIVISION.
PROGRAM-ID. program-name.
2.4.2 PROGRAM-ID: The Only Required Paragraph
The PROGRAM-ID paragraph assigns a name to the program. This name is used by the operating system, the linker, and by other programs that CALL this program.
Rules for program names: - 1 to 30 characters (8 in older standards) - Must begin with a letter - Can contain letters, digits, and hyphens - Cannot end with a hyphen - Cannot be a COBOL reserved word - Case sensitivity depends on the compiler
PROGRAM-ID. PAYROLL-PROCESS.
Optional clauses for PROGRAM-ID:
| Clause | Purpose |
|---|---|
IS INITIAL |
Program is returned to its initial state each time it is called |
IS COMMON |
Program can be called by sibling programs in a nested structure |
IS RECURSIVE |
Program can call itself (COBOL-2002+) |
PROGRAM-ID. CALCULATE-TAX IS INITIAL.
The IS INITIAL clause is particularly important for subprograms. Without it, WORKING-STORAGE variables retain their values between calls. With it, all variables are re-initialized to their VALUE clauses each time the program is called.
2.4.3 Optional Paragraphs
All other paragraphs in the IDENTIFICATION DIVISION are optional. In COBOL-2002 and later, they are classified as obsolete but remain supported by virtually all compilers. They serve a purely documentary purpose -- the compiler does not validate or enforce their content (with the exception of DATE-COMPILED, which some compilers replace with the actual compilation date).
| Paragraph | Purpose | Typical Content |
|---|---|---|
AUTHOR |
Who wrote the program | Developer name, team name |
INSTALLATION |
Where the program runs | Data center, server name, department |
DATE-WRITTEN |
When the program was created | Date in any text format |
DATE-COMPILED |
When the program was last compiled | Automatically filled by some compilers |
SECURITY |
Access or classification notes | Confidentiality level, restrictions |
Example with all paragraphs:
IDENTIFICATION DIVISION.
PROGRAM-ID. ACCT-RECV.
AUTHOR. MARY CHEN, ACCOUNTS TEAM.
INSTALLATION. CHICAGO DATA CENTER - SERVER FARM 3.
DATE-WRITTEN. 2026-01-15.
DATE-COMPILED.
SECURITY. CONFIDENTIAL - SOX COMPLIANCE REQUIRED.
2.4.4 Best Practices
While the optional paragraphs are obsolete in the standard, many organizations still require them as part of their coding standards. The rationale is straightforward: in a production environment with thousands of COBOL programs, this built-in metadata is invaluable for maintenance. When you open a 5,000-line program at 2 AM during an outage, knowing who wrote it and when can save precious time.
If your shop uses version control (and it should), much of this information is available through the version control system. In that case, a prominent comment block may serve the same purpose:
*================================================================*
* Program: ACCT-RECV
* Description: Accounts receivable batch processing
* Author: Mary Chen (mary.chen@acme.com)
* Created: 2026-01-15
* Modified: 2026-02-10 - Added aging report (J. Smith)
* Repository: git://mainframe/accounting/acct-recv.git
*================================================================*
IDENTIFICATION DIVISION.
PROGRAM-ID. ACCT-RECV.
2.5 The ENVIRONMENT DIVISION
The ENVIRONMENT DIVISION describes the computing environment in which the program will be compiled and executed. It is the most platform-dependent part of a COBOL program. When porting a program from one system to another, the ENVIRONMENT DIVISION typically requires the most changes.
The ENVIRONMENT DIVISION contains two sections: 1. CONFIGURATION SECTION -- Computer and special-name definitions 2. INPUT-OUTPUT SECTION -- File assignments and I/O control
Both sections and the division itself are optional. A minimal program may omit the ENVIRONMENT DIVISION entirely.
2.5.1 CONFIGURATION SECTION
The CONFIGURATION SECTION contains up to three paragraphs.
SOURCE-COMPUTER
Identifies the computer where the program will be compiled.
SOURCE-COMPUTER. IBM-MAINFRAME WITH DEBUGGING MODE.
The computer name is treated as a comment. The key clause here is WITH DEBUGGING MODE, which activates debugging lines (those with D in column 7).
OBJECT-COMPUTER
Identifies the computer where the compiled program will run.
OBJECT-COMPUTER. IBM-MAINFRAME
PROGRAM COLLATING SEQUENCE IS SPECIAL-SEQUENCE.
The most useful clause is PROGRAM COLLATING SEQUENCE, which specifies the character ordering used for comparisons and sorting. This is important for international applications where the default (EBCDIC or ASCII) ordering may not match local conventions.
SPECIAL-NAMES
The SPECIAL-NAMES paragraph is the most powerful paragraph in the CONFIGURATION SECTION. It allows you to customize the program's behavior in several ways:
Decimal point notation:
SPECIAL-NAMES.
DECIMAL-POINT IS COMMA.
This causes COBOL to swap the roles of the period and comma in numeric formatting. The number 1,234.56 would be displayed as 1.234,56 -- the European convention. This is purely a source-code and display convention; it does not affect internal storage.
Currency sign:
SPECIAL-NAMES.
CURRENCY SIGN IS "EUR" WITH PICTURE SYMBOL "E".
This allows you to use a custom currency symbol in PICTURE clauses. With the definition above, PIC EEE,EE9.99 would format values with the EUR prefix.
Class conditions:
SPECIAL-NAMES.
CLASS VALID-LETTER IS "A" THRU "Z" "a" THRU "z"
CLASS VALID-DIGIT IS "0" THRU "9".
Class conditions create custom data validation tests. After defining these, you can write:
IF WS-INPUT IS VALID-LETTER
DISPLAY "INPUT IS ALPHABETIC"
END-IF
Mnemonic names:
SPECIAL-NAMES.
CONSOLE IS OPERATOR-TERMINAL
PRINTER IS LINE-PRINTER.
Mnemonic names map implementor-defined device names to user-defined names, providing an abstraction layer.
Symbolic characters:
SPECIAL-NAMES.
SYMBOLIC CHARACTERS TAB-CHAR IS 10
LF-CHAR IS 11.
This assigns user-defined names to specific characters in the character set by their ordinal position (the actual position depends on whether the system uses ASCII or EBCDIC).
2.5.2 INPUT-OUTPUT SECTION
The INPUT-OUTPUT SECTION maps logical file names used in the program to physical files on the system. It contains two paragraphs.
FILE-CONTROL
The FILE-CONTROL paragraph contains a SELECT statement for each file the program uses. This is where COBOL achieves its powerful file-handling abstraction: the program logic works with logical file names, and the physical file assignments can be changed without modifying the PROCEDURE DIVISION.
FILE-CONTROL.
SELECT logical-file-name
ASSIGN TO physical-file-name
ORGANIZATION IS organization-type
ACCESS MODE IS access-mode
RECORD KEY IS key-field
FILE STATUS IS status-field.
File organizations:
| Organization | Description | Use Case |
|---|---|---|
SEQUENTIAL |
Records accessed in order | Batch processing, tape files |
LINE SEQUENTIAL |
Text files with line delimiters | Reports, CSV files |
RELATIVE |
Records accessed by record number | Direct access by position |
INDEXED |
Records accessed by key value | Master files, databases |
Access modes:
| Mode | Description |
|---|---|
SEQUENTIAL |
Records read/written in order |
RANDOM |
Records read/written by key or record number |
DYNAMIC |
Both sequential and random access |
Here is a comprehensive example:
FILE-CONTROL.
* Sequential text file
SELECT EMPLOYEE-FILE
ASSIGN TO "EMPFILE.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-EMP-STATUS.
* Indexed file with primary and alternate keys
SELECT CUSTOMER-FILE
ASSIGN TO "CUSTMAST.DAT"
ORGANIZATION IS INDEXED
ACCESS MODE IS DYNAMIC
RECORD KEY IS CUST-ID
ALTERNATE RECORD KEY IS CUST-NAME
WITH DUPLICATES
FILE STATUS IS WS-CUST-STATUS.
* Relative file
SELECT TRANSACTION-LOG
ASSIGN TO "TRANSLOG.DAT"
ORGANIZATION IS RELATIVE
ACCESS MODE IS RANDOM
RELATIVE KEY IS WS-RELATIVE-KEY
FILE STATUS IS WS-TRANS-STATUS.
The FILE STATUS clause is a critical best practice. It directs the system to store a two-character status code after each file operation, allowing your program to detect and handle errors gracefully. Common status codes include:
| Status | Meaning |
|---|---|
00 |
Successful completion |
10 |
End of file reached |
22 |
Duplicate key (indexed file) |
23 |
Record not found |
30 |
Permanent I/O error |
35 |
File not found |
41 |
File already open |
Always check the file status after every file operation. This is one of the most important defensive programming practices in COBOL.
I-O-CONTROL
The I-O-CONTROL paragraph specifies special I/O techniques. It is less commonly used in modern programs but can be important for batch processing:
I-O-CONTROL.
SAME RECORD AREA FOR FILE-A FILE-B.
The SAME RECORD AREA clause tells the compiler that two files share the same record buffer, which can save memory in resource-constrained environments. The RERUN clause (for checkpoint/restart) and the MULTIPLE FILE TAPE clause are other options, though they are rarely used in modern development.
2.6 The DATA DIVISION
The DATA DIVISION defines every piece of data the program will use. In a typical COBOL program, the DATA DIVISION is often the largest division, sometimes accounting for more than half the total lines of code. This may surprise programmers from other languages, but it reflects COBOL's philosophy: data structures should be explicitly and completely defined, not inferred by the compiler.
2.6.1 FILE SECTION
The FILE SECTION defines the record layout for each file declared in the FILE-CONTROL paragraph. Each file requires an FD (File Description) entry followed by one or more record descriptions.
FILE SECTION.
FD EMPLOYEE-FILE
LABEL RECORDS ARE STANDARD
RECORD CONTAINS 80 CHARACTERS
BLOCK CONTAINS 10 RECORDS
DATA RECORD IS EMPLOYEE-RECORD.
01 EMPLOYEE-RECORD.
05 EMP-ID PIC 9(6).
05 EMP-NAME PIC X(30).
05 EMP-DEPARTMENT PIC X(20).
05 EMP-SALARY PIC 9(7)V99.
05 FILLER PIC X(15).
Key points about the FILE SECTION:
FDmust begin in Area A- The
01level record description defines the layout of each record - Multiple
01level entries under the sameFDshare the same physical buffer (they provide different views of the same storage) FILLERis used for unused portions of the record- For sort files, use
SD(Sort Description) instead ofFD
2.6.2 WORKING-STORAGE SECTION
The WORKING-STORAGE SECTION defines variables that persist for the entire life of the program. Values set with VALUE clauses are initialized once when the program is first loaded. These values are retained across PERFORM calls and, importantly, across multiple calls to the program from a calling program (unless IS INITIAL is specified in the PROGRAM-ID).
WORKING-STORAGE SECTION.
* Independent elementary items (77-level)
77 WS-RETURN-CODE PIC S9(4) VALUE ZERO.
* Group items with subordinate fields
01 WS-FLAGS.
05 WS-EOF-FLAG PIC X VALUE 'N'.
88 END-OF-FILE VALUE 'Y'.
88 NOT-EOF VALUE 'N'.
* Counters
01 WS-COUNTERS.
05 WS-RECORD-COUNT PIC 9(7) VALUE ZEROS.
05 WS-ERROR-COUNT PIC 9(5) VALUE ZEROS.
Level numbers and their meanings:
| Level | Purpose |
|---|---|
| 01 | Record level (group item or independent elementary item) |
| 02-49 | Subordinate items within a group |
| 66 | RENAMES (alternative grouping of items) |
| 77 | Independent elementary item (not part of any group) |
| 88 | Condition name (used for boolean-like tests) |
Level 88: Condition Names
Condition names are one of COBOL's most elegant features. They associate meaningful names with specific values:
01 WS-ACCOUNT-TYPE PIC X.
88 CHECKING VALUE 'C'.
88 SAVINGS VALUE 'S'.
88 MONEY-MARKET VALUE 'M'.
88 INVALID-TYPE VALUE 'X' THRU 'Z'.
You can then write readable conditions:
IF CHECKING
PERFORM PROCESS-CHECKING
END-IF
SET SAVINGS TO TRUE
REDEFINES: Alternative Views of the Same Storage
01 WS-DATE-NUMERIC PIC 9(8).
01 WS-DATE-PARTS REDEFINES WS-DATE-NUMERIC.
05 WS-YEAR PIC 9(4).
05 WS-MONTH PIC 9(2).
05 WS-DAY PIC 9(2).
Both WS-DATE-NUMERIC and WS-DATE-PARTS occupy the same storage. Moving 20260210 to WS-DATE-NUMERIC makes WS-YEAR equal to 2026, WS-MONTH equal to 02, and WS-DAY equal to 10.
OCCURS: Tables and Arrays
01 WS-MONTHLY-TOTALS.
05 WS-MONTH-TOTAL PIC 9(9)V99
OCCURS 12 TIMES.
This creates an array of 12 numeric items, accessed as WS-MONTH-TOTAL(1) through WS-MONTH-TOTAL(12).
2.6.3 LOCAL-STORAGE SECTION
Introduced in COBOL-2002, LOCAL-STORAGE is similar to WORKING-STORAGE with one critical difference: LOCAL-STORAGE items are re-initialized to their VALUE clauses each time the program is invoked via a CALL statement.
WORKING-STORAGE SECTION.
01 WS-CALL-COUNT PIC 9(3) VALUE ZEROS.
LOCAL-STORAGE SECTION.
01 LS-TEMP-RESULT PIC 9(9)V99 VALUE ZEROS.
If this program is called three times, WS-CALL-COUNT retains its accumulated value (1, 2, 3), while LS-TEMP-RESULT is reset to zero at the start of each call. This distinction is crucial for writing reliable subprograms.
2.6.4 LINKAGE SECTION
The LINKAGE SECTION defines data items that are passed to the program by a calling program via the CALL ... USING statement. Items in the LINKAGE SECTION do not occupy storage in the called program; they describe the layout of data whose storage is owned by the calling program.
LINKAGE SECTION.
01 LS-EMPLOYEE-ID PIC 9(6).
01 LS-ACTION-CODE PIC X.
01 LS-RETURN-CODE PIC S9(4).
PROCEDURE DIVISION USING LS-EMPLOYEE-ID
LS-ACTION-CODE
LS-RETURN-CODE.
Important rules: - VALUE clauses are not allowed in the LINKAGE SECTION (except for 88-level items) - The USING clause in the PROCEDURE DIVISION header maps parameters in order - The number and sizes of parameters must match between the calling and called programs
2.6.5 Other Sections
COBOL defines several additional DATA DIVISION sections for specialized purposes:
REPORT SECTION: Used with the Report Writer feature to define complex report layouts declaratively. The Report Writer automates page breaks, headers, footers, and control breaks. While powerful, it is not supported by all compilers.
REPORT SECTION.
RD SALES-REPORT
CONTROL IS FINAL REGION-CODE
PAGE LIMIT IS 60 LINES
HEADING 1
FIRST DETAIL 5
LAST DETAIL 55
FOOTING 58.
SCREEN SECTION: Used for interactive terminal programs to define screen layouts with field positioning, colors, and input/output attributes.
SCREEN SECTION.
01 MAIN-SCREEN.
05 BLANK SCREEN.
05 LINE 1 COLUMN 30 VALUE "EMPLOYEE INQUIRY"
HIGHLIGHT.
05 LINE 3 COLUMN 5 VALUE "EMPLOYEE ID: ".
05 LINE 3 COLUMN 18 PIC 9(6)
USING WS-EMPLOYEE-ID
HIGHLIGHT AUTO.
2.7 The PROCEDURE DIVISION
The PROCEDURE DIVISION contains the executable logic of the program -- this is where the program actually does something. While the other three divisions are declarative (they describe things), the PROCEDURE DIVISION is imperative (it commands actions).
2.7.1 Hierarchical Structure
The PROCEDURE DIVISION has a four-level hierarchy:
PROCEDURE DIVISION
|
+-- SECTION (optional grouping)
| |
| +-- PARAGRAPH (named block of code)
| |
| +-- SENTENCE (one or more statements, ending with a period)
| |
| +-- STATEMENT (a single COBOL verb and its operands)
Statements
A statement is a single COBOL verb and its operands. It is the smallest unit of executable code:
MOVE 42 TO WS-RESULT
DISPLAY "HELLO, WORLD"
ADD 1 TO WS-COUNTER
READ EMPLOYEE-FILE AT END SET END-OF-FILE TO TRUE END-READ
Sentences
A sentence is one or more statements terminated by a period. The period is significant in COBOL -- it acts as a scope terminator for the entire sentence:
* One statement, one sentence:
DISPLAY "HELLO".
* Multiple statements in one sentence:
MOVE 0 TO WS-COUNTER
MOVE SPACES TO WS-NAME
MOVE "N" TO WS-EOF-FLAG.
Paragraphs
A paragraph is a named block of code consisting of one or more sentences. The paragraph name must begin in Area A and is followed by a period:
1000-INITIALIZE.
OPEN INPUT EMPLOYEE-FILE
OPEN OUTPUT REPORT-FILE
SET NOT-END-OF-FILE TO TRUE
PERFORM 8000-READ-EMPLOYEE
.
Paragraphs are the basic units of program organization in the PROCEDURE DIVISION. They can be PERFORMed (called) from other paragraphs:
PERFORM 1000-INITIALIZE
Sections
A section is a named group of one or more paragraphs. The section name must begin in Area A and is followed by the word SECTION and a period:
1000-INITIALIZATION SECTION.
1000-INIT-START.
OPEN INPUT EMPLOYEE-FILE
.
1100-OPEN-REPORT.
OPEN OUTPUT REPORT-FILE
.
1000-INIT-EXIT.
EXIT.
When you PERFORM a section, COBOL executes all paragraphs within that section from beginning to end. Sections provide a higher level of organization and are particularly useful in large programs.
2.7.2 Sections vs. Paragraphs: When to Use Which
This is a perennial debate in the COBOL community. Here are the two main approaches:
Paragraphs Only (no sections):
PROCEDURE DIVISION.
0000-MAIN.
PERFORM 1000-INITIALIZE
PERFORM 2000-PROCESS UNTIL END-OF-FILE
PERFORM 3000-FINALIZE
STOP RUN.
1000-INITIALIZE.
OPEN INPUT EMP-FILE
PERFORM 8000-READ-EMPLOYEE.
2000-PROCESS.
ADD 1 TO WS-COUNT
PERFORM 8000-READ-EMPLOYEE.
3000-FINALIZE.
CLOSE EMP-FILE
DISPLAY "DONE: " WS-COUNT " RECORDS".
8000-READ-EMPLOYEE.
READ EMP-FILE AT END SET END-OF-FILE TO TRUE END-READ.
Sections with Paragraphs:
PROCEDURE DIVISION.
0000-MAIN-CONTROL SECTION.
0000-MAIN.
PERFORM 1000-INITIALIZATION
PERFORM 2000-PROCESS UNTIL END-OF-FILE
PERFORM 3000-FINALIZATION
STOP RUN.
0000-MAIN-EXIT.
EXIT.
1000-INITIALIZATION SECTION.
1000-INIT-START.
OPEN INPUT EMP-FILE
PERFORM 8000-READ-EMPLOYEE.
1000-INIT-EXIT.
EXIT.
Each approach has advocates. Sections provide better organization in large programs and interact differently with the PERFORM THRU statement. Paragraphs are simpler and sufficient for smaller programs. Many mainframe shops have coding standards that mandate one style or the other.
2.7.3 Naming Conventions
There is no universal standard for paragraph and section naming, but the most widely adopted convention uses a numeric prefix to indicate the logical grouping:
| Range | Purpose |
|---|---|
| 0000-0999 | Main control / top-level logic |
| 1000-1999 | Initialization |
| 2000-2999 | Main processing |
| 3000-3999 | Output / report generation |
| 4000-4999 | Finalization / cleanup |
| 5000-7999 | Application-specific processing |
| 8000-8999 | Utility / common routines |
| 9000-9999 | Error handling |
Combined with descriptive names:
0000-MAIN-CONTROL.
1000-INITIALIZE.
2000-PROCESS-TRANSACTIONS.
2100-VALIDATE-TRANSACTION.
2200-APPLY-TRANSACTION.
3000-PRINT-REPORT.
3100-PRINT-HEADERS.
3200-PRINT-DETAIL.
3300-PRINT-TOTALS.
4000-FINALIZE.
8000-READ-TRANSACTION.
8100-READ-MASTER.
9000-HANDLE-FILE-ERROR.
9100-HANDLE-DATA-ERROR.
This convention has two enormous benefits: 1. Reading the code, you can instantly identify what category of processing a paragraph performs just by its number. 2. Searching the listing, paragraphs naturally sort into logical groups.
2.7.4 The PROCEDURE DIVISION USING Clause
When a program receives parameters from a calling program, the USING clause on the PROCEDURE DIVISION header connects the LINKAGE SECTION items to the incoming parameters:
PROCEDURE DIVISION USING LS-EMPLOYEE-ID
LS-ACTION-CODE
LS-RETURN-CODE.
The parameters are matched by position, not by name. The first item in the CALL matches the first item in the USING, and so on.
2.8 The Period: Statement Terminator and Scope Delimiter
The period (.) in COBOL is one of the most consequential punctuation marks in any programming language. It terminates sentences and implicitly closes all open scope delimiters. This dual role has been the source of countless bugs.
2.8.1 The Problem with Periods
Consider this code:
IF WS-BALANCE > 0
DISPLAY "POSITIVE BALANCE"
PERFORM 2000-PROCESS-CREDIT.
DISPLAY "CREDIT PROCESSED".
The period after PERFORM 2000-PROCESS-CREDIT terminates the IF statement. The second DISPLAY executes unconditionally, regardless of whether WS-BALANCE > 0. This is a classic and insidious bug because the indentation suggests both statements are inside the IF, but the period says otherwise.
2.8.2 Scope Terminators: The Modern Solution
COBOL-85 introduced explicit scope terminators to solve this problem. These are END- keywords that explicitly close a statement:
IF WS-BALANCE > 0
DISPLAY "POSITIVE BALANCE"
PERFORM 2000-PROCESS-CREDIT
DISPLAY "CREDIT PROCESSED"
END-IF
Now the intent is unambiguous. The END-IF explicitly terminates the IF statement, and all three subordinate statements are clearly inside the IF block.
Common scope terminators include:
| Scope Terminator | Closes |
|---|---|
END-IF |
IF statement |
END-EVALUATE |
EVALUATE statement |
END-PERFORM |
Inline PERFORM |
END-READ |
READ statement |
END-WRITE |
WRITE statement |
END-COMPUTE |
COMPUTE statement |
END-STRING |
STRING statement |
END-UNSTRING |
UNSTRING statement |
END-SEARCH |
SEARCH statement |
END-CALL |
CALL statement |
END-ADD |
ADD statement |
END-SUBTRACT |
SUBTRACT statement |
END-MULTIPLY |
MULTIPLY statement |
END-DIVIDE |
DIVIDE statement |
2.8.3 Best Practice: Minimize Periods
The modern best practice is to use exactly one period per paragraph -- at the very end of the paragraph. Use explicit scope terminators for all conditional and I/O statements within the paragraph.
2000-PROCESS-RECORD.
IF WS-RECORD-TYPE = "A"
PERFORM 2100-PROCESS-TYPE-A
ELSE
IF WS-RECORD-TYPE = "B"
PERFORM 2200-PROCESS-TYPE-B
ELSE
PERFORM 9000-HANDLE-ERROR
END-IF
END-IF
ADD 1 TO WS-RECORD-COUNT
.
Note the lone period on its own line at the end of the paragraph. This style makes the paragraph boundary visible and eliminates the risk of accidental scope termination.
2.9 Naming Rules for User-Defined Words
COBOL has specific rules for the names you create for data items, paragraphs, sections, and files.
2.9.1 General Rules
- Length: 1 to 30 characters
- Characters allowed: Letters (A-Z, a-z), digits (0-9), and hyphens (-)
- Must contain at least one letter (except paragraph names, which can be all digits)
- Cannot begin or end with a hyphen
- Cannot be a COBOL reserved word
- Not case-sensitive (in most compilers):
WS-COUNT,ws-count, andWs-Countare the same name
2.9.2 Data Name Prefixing Convention
A widely adopted convention is to prefix data names based on their section:
| Prefix | Section / Usage |
|---|---|
WS- |
WORKING-STORAGE SECTION |
LS- |
LOCAL-STORAGE SECTION or LINKAGE SECTION |
EMP- |
Fields in EMPLOYEE record |
CUST- |
Fields in CUSTOMER record |
WS-DET- |
Detail line fields |
WS-HDR- |
Header line fields |
WS-TOT- |
Total/summary fields |
This convention is not enforced by the compiler, but it dramatically improves readability. When you see WS-RECORD-COUNT in the PROCEDURE DIVISION, you immediately know it is defined in WORKING-STORAGE. When you see EMP-SALARY, you know it is part of the employee record.
2.9.3 Reserved Words
COBOL has a large set of reserved words -- over 400 in some standards. You cannot use any reserved word as a data name, paragraph name, or section name. Common pitfalls include:
DATEis reserved -- useWS-DATEinsteadTIMEis reserved -- useWS-TIMEinsteadCOUNTis reserved in some compilers -- useWS-COUNTSTATUSis reserved -- useWS-STATUSLENGTHis reserved in COBOL-2002+ -- useWS-LENGTH
When in doubt, prefix your names. The WS- convention virtually eliminates reserved word conflicts.
2.10 COBOL Program Compilation and Execution Flow
Understanding how a COBOL program goes from source code to running program helps clarify why the division structure matters.
2.10.1 The Compilation Process
Source Code (.cob/.cbl)
|
v
[COMPILER] <-- Uses ENVIRONMENT DIVISION for configuration
|
v
Object Module (.o/.obj)
|
v
[LINKER] <-- Resolves CALL references, links libraries
|
v
Executable Program (.exe/load module)
|
v
[RUNTIME] <-- Uses ENVIRONMENT DIVISION for file mapping
|
v
Program Output (files, reports, screens)
2.10.2 What Each Division Contributes
- IDENTIFICATION DIVISION: The program name becomes the module name in the object file and the entry point name for CALL resolution.
- ENVIRONMENT DIVISION: File assignments are resolved at compile time (for validation) and at run time (for actual file access). The CONFIGURATION SECTION may affect code generation (e.g., collating sequences, debugging mode).
- DATA DIVISION: The compiler allocates memory for all data items and generates the code to initialize VALUE clauses. The FILE SECTION determines buffer sizes and record layouts.
- PROCEDURE DIVISION: The compiler translates COBOL verbs into machine instructions or intermediate code.
2.10.3 Compiling with GnuCOBOL
For readers using GnuCOBOL (the most accessible open-source COBOL compiler), here is the basic compilation workflow:
cobc -x -o myprog myprog.cob (compile and link to executable)
cobc -x -free -o myprog myprog.cob (free-format source)
cobc -c myprog.cob (compile only, produce .o file)
cobc -x main.o sub1.o sub2.o (link multiple object files)
Common compiler flags:
| Flag | Purpose |
|---|---|
-x |
Produce an executable |
-m |
Produce a dynamically loadable module |
-free |
Treat source as free format |
-std=cobol85 |
Enforce COBOL-85 standard |
-std=cobol2014 |
Enforce COBOL-2014 standard |
-W |
Enable warnings |
-debug |
Enable runtime debugging features |
2.11 Building a Program from Scratch: A Complete Walkthrough
Let us build a complete COBOL program step by step, explaining each decision along the way. Our program will read an employee file and display a count and total salary.
Step 1: Start with the IDENTIFICATION DIVISION
Every program starts here. We need at minimum the division header and PROGRAM-ID:
IDENTIFICATION DIVISION.
PROGRAM-ID. EMPCOUNT.
AUTHOR. CLAUDE TEXTBOOKS.
DATE-WRITTEN. 2026-02-10.
Step 2: Define the ENVIRONMENT DIVISION
Our program reads one file, so we need a FILE-CONTROL entry:
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT EMPLOYEE-FILE
ASSIGN TO "EMPLOYEES.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-FILE-STATUS.
We omitted the CONFIGURATION SECTION because we do not need special names or debugging mode for this simple program.
Step 3: Define the DATA DIVISION
First, the FILE SECTION for our input file, then WORKING-STORAGE for our variables:
DATA DIVISION.
FILE SECTION.
FD EMPLOYEE-FILE
RECORD CONTAINS 50 CHARACTERS.
01 EMPLOYEE-RECORD.
05 EMP-ID PIC 9(5).
05 EMP-NAME PIC X(30).
05 EMP-SALARY PIC 9(7)V99.
05 FILLER PIC X(6).
WORKING-STORAGE SECTION.
01 WS-FILE-STATUS PIC XX VALUE SPACES.
01 WS-EOF-FLAG PIC X VALUE 'N'.
88 END-OF-FILE VALUE 'Y'.
01 WS-COUNT PIC 9(5) VALUE ZEROS.
01 WS-TOTAL-SALARY PIC 9(9)V99 VALUE ZEROS.
01 WS-DISPLAY-SALARY PIC $$$,$$$, MATH1 $,$$$,$$9.99.
procedure division.
0000-main.
perform 1000-initialize
perform 2000-process until end-of-file
perform 3000-finalize
stop run
.
1000-initialize.
open input employee-file
if ws-file-status not = "00"
display "ERROR OPENING FILE: " ws-file-status
stop run
end-if
perform 8000-read-employee
.
2000-process.
add 1 to ws-count
add emp-salary to ws-total-salary
perform 8000-read-employee
.
3000-finalize.
move ws-total-salary to ws-display-salary
display "EMPLOYEES: " ws-count
display "TOTAL SALARY: " ws-display-salary
close employee-file
.
8000-read-employee.
read employee-file
at end
set end-of-file to true
not at end
continue
end-read
.
Note that the logic and structure are identical. The only differences are cosmetic: no column restrictions, *> for comments, lowercase keywords (by convention, not requirement), and more flexible indentation.
2.15 Summary
The four-division structure is COBOL's defining architectural feature. It enforces a clean separation between program identity, environment configuration, data definitions, and executable logic. This separation is not just organizational tidiness -- it is a design philosophy that has kept COBOL programs maintainable for decades.
Key concepts to remember:
- IDENTIFICATION DIVISION is the only required division.
PROGRAM-IDis its only required paragraph. - ENVIRONMENT DIVISION bridges the program and the operating system, particularly through FILE-CONTROL.
- DATA DIVISION declares all data explicitly. WORKING-STORAGE persists; LOCAL-STORAGE reinitializes; LINKAGE SECTION describes shared data.
- PROCEDURE DIVISION contains the logic, organized into sections, paragraphs, sentences, and statements.
- Fixed format uses specific column ranges for specific purposes. Area A (8-11) is for headers and high-level items; Area B (12-72) is for code.
- Free format removes column restrictions but preserves the division structure.
- Periods terminate sentences and implicitly close all scope. Prefer explicit scope terminators (
END-IF,END-PERFORM, etc.) and minimize periods. - Naming conventions with numeric prefixes and descriptive names make programs dramatically more readable.
In the next chapter, we will dive deep into the DATA DIVISION and explore COBOL's rich data description capabilities -- the PICTURE clause, level numbers, and the full range of data types and structures that make COBOL uniquely suited for business data processing.
Chapter 2 code examples are available in the code/ subdirectory. Compile them with GnuCOBOL using cobc -x filename.cob for fixed format or cobc -x -free filename.cob for free format.