COBOL Procedure Division

The PROCEDURE DIVISION is where a COBOL program does its work. It is the fourth division (after IDENTIFICATION, ENVIRONMENT, and DATA) and holds all executable logic: reading files, making decisions, performing calculations, and calling other programs. This page explains how the Procedure Division is structured, how to declare parameters with USING and RETURNING, and how sections and paragraphs organize the code.

Explain Like I'm Five: What Is the Procedure Division?

Imagine a recipe. The first parts of the program are like the title and the list of ingredients. The Procedure Division is the actual steps: "Open the file," "Read a line," "If it's empty, stop; otherwise do this." The computer runs those steps one after another (unless you tell it to jump to another step or call another recipe). So the Procedure Division is simply the list of instructions the program follows when it runs.

Procedure Division Header and Parameters

The PROCEDURE DIVISION starts with a header. The simplest form is just PROCEDURE DIVISION. with a period. If the program is called by another program and needs to receive or return data, you add USING and optionally RETURNING. Every parameter in USING must be defined in the LINKAGE SECTION so the compiler knows the size and type of the data the caller is passing.

Common PROCEDURE DIVISION header forms
Header formMeaningWhen to use
PROCEDURE DIVISION.No parameters. Main program or subprogram that does not receive or return arguments.Main programs, simple subprograms with no interface.
PROCEDURE DIVISION USING param-1 param-2.Receives one or more parameters from the caller. Each param must be in LINKAGE SECTION.Subprograms called with CALL ... USING.
PROCEDURE DIVISION RETURNING result.Returns a single value to the caller. Caller uses CALL ... RETURNING identifier.Functions or subprograms that compute one return value.
PROCEDURE DIVISION USING a, b RETURNING r.Both input parameters and one return value. Order is USING list first, then RETURNING.Subprograms that take inputs and return one result.

USING and RETURNING are optional. A main program (the one run directly by the system) often has no parameters. Subprograms that are called with CALL ... USING ... must declare the same number and order of parameters in PROCEDURE DIVISION USING, and each corresponding data item must appear in the LINKAGE SECTION.

PROCEDURE DIVISION USING in Detail

When a calling program executes CALL 'SUBPROG' USING WS-NUM, WS-NAME, the subprogram receives those two arguments. The subprogram must declare PROCEDURE DIVISION USING LNK-NUM, LNK-NAME (or similar names) and define LNK-NUM and LNK-NAME in the LINKAGE SECTION with the same characteristics (picture, length) as the caller's data, or at least compatible ones. By default, parameters are passed by reference: the subprogram gets the address of the caller's data, so any change it makes (e.g. MOVE something TO LNK-NUM) is visible in the caller. You can override this with BY VALUE or BY CONTENT in the CALL or in the procedure division header on some compilers.

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
*> Calling program CALL 'CALC-TOTAL' USING WS-AMOUNT, WS-RATE, WS-RESULT. *> Called program (CALC-TOTAL) LINKAGE SECTION. 01 LNK-AMOUNT PIC 9(7)V99. 01 LNK-RATE PIC 9(2)V99. 01 LNK-RESULT PIC 9(7)V99. PROCEDURE DIVISION USING LNK-AMOUNT, LNK-RATE, LNK-RESULT. MAIN-PARA. COMPUTE LNK-RESULT = LNK-AMOUNT * LNK-RATE GOBACK.

The order of parameters in USING must match the CALL. The first argument in the CALL corresponds to the first parameter in USING, and so on. If you swap two parameters in one place but not the other, you will pass the wrong data. Type and length should match to avoid undefined behavior or truncation.

PROCEDURE DIVISION RETURNING

RETURNING lets a subprogram return one value to the caller. The caller writes CALL 'SUB' RETURNING WS-OUTPUT. The subprogram declares PROCEDURE DIVISION RETURNING result-item. The result item can be defined in LINKAGE SECTION or, on some compilers, in WORKING-STORAGE. When the subprogram exits with GOBACK or EXIT PROGRAM, the current value of the return item is copied back to the caller's identifier. So the subprogram behaves like a function that returns a single value. You can combine USING and RETURNING: PROCEDURE DIVISION USING A, B RETURNING R.

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
*> Caller CALL 'GET-NEXT-ID' RETURNING WS-NEXT-ID. *> Called program GET-NEXT-ID DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NEXT PIC 9(8) VALUE 1. LINKAGE SECTION. 01 LNK-RETURN PIC 9(8). PROCEDURE DIVISION RETURNING LNK-RETURN. MAIN-PARA. MOVE WS-NEXT TO LNK-RETURN ADD 1 TO WS-NEXT GOBACK.

Sections and Paragraphs

The Procedure Division is organized into sections and paragraphs. A section is a name followed by the word SECTION and a period (e.g. FILE-HANDLING SECTION.). A paragraph is a name followed by a period (e.g. READ-INPUT.). Sections are optional; many programs use only paragraphs. Paragraphs can stand alone or sit inside a section. Sections group related paragraphs (e.g. all file handling in one section, all calculations in another). Both sections and paragraphs can be the target of PERFORM: PERFORM PARAGRAPH-NAME or PERFORM SECTION-NAME will run that block of code.

Hierarchy: section, paragraph, sentence, statement
LevelDescriptionExample
SectionOptional. Name SECTION followed by a period. Groups one or more paragraphs. Can have a priority number (0–99) for segmentation.FILE-HANDLING SECTION.
ParagraphName followed by a period. Contains one or more sentences. The usual target of PERFORM.READ-INPUT-FILE.
SentenceOne or more statements ending with a period. A period terminates the sentence and the paragraph if no more sentences follow.READ INFILE AT END SET EOF TO TRUE.
StatementA single COBOL verb or command (MOVE, ADD, READ, IF, etc.).MOVE 0 TO WS-COUNT.

A section ends at the next section header or at the end of the Procedure Division. A paragraph ends at the next paragraph name, the next section header, or the end of the division. So the period that ends a sentence also ends the paragraph if there are no more sentences before the next paragraph name. Because of that, early COBOL style often avoided periods in the middle of paragraphs to prevent accidentally ending the paragraph; modern style uses explicit scope terminators (END-IF, END-PERFORM, etc.) so periods are less of a trap.

Sentences and Statements

A sentence is one or more statements terminated by a period. A statement is a single COBOL verb or construct (MOVE, ADD, READ, IF, PERFORM, etc.). So "MOVE 0 TO WS-COUNT." is one statement and one sentence. "READ INFILE AT END SET EOF TO TRUE." is one sentence with one statement. Multiple statements in one sentence are separated by spaces or line breaks and share the same period at the end. Execution is sequential unless a verb transfers control (PERFORM to another paragraph, CALL to another program, or conditional branching with IF/EVALUATE).

Where Execution Begins and Ends

Execution starts at the first statement in the PROCEDURE DIVISION, ignoring declaratives. Declaratives are optional blocks (e.g. USE BEFORE REPORTING) that run only when their condition is true. So the "main" flow is from the top of the division downward. The program ends when it runs STOP RUN (in a main program), GOBACK, or EXIT PROGRAM (in a subprogram), or when the last statement has been executed and control would fall off the end of the program. In a called program, GOBACK or EXIT PROGRAM returns control to the caller and, if RETURNING was used, copies the return value back.

Step-by-Step: Writing a Simple Procedure Division

  1. After the DATA DIVISION, write PROCEDURE DIVISION. (or PROCEDURE DIVISION USING ... / RETURNING ... if the program is a subprogram).
  2. Choose a first paragraph name (e.g. MAIN-LOGIC. or 100-MAIN.). This is where execution will start.
  3. Write the first instruction (e.g. OPEN the file, INITIALIZE a counter, or PERFORM a paragraph that does the real work).
  4. Add more paragraphs for each logical task (read loop, validate, calculate, write). Use PERFORM paragraph-name to call them.
  5. End the main flow with STOP RUN (main program) or GOBACK/EXIT PROGRAM (subprogram).

Step-by-Step: Adding Parameters for a Called Program

  1. In the called program, add a LINKAGE SECTION and define one 01 (or 77) for each parameter, with the same picture and length the caller will use.
  2. Write PROCEDURE DIVISION USING name1, name2, ... using those linkage names. Order must match the CALL.
  3. In the procedure code, use the linkage names to read input and, if the caller expects updated values, move results into them before GOBACK.
  4. If the program returns a single value, add RETURNING result-name to the header and define result-name in LINKAGE SECTION (or as allowed). Set result-name before GOBACK/EXIT PROGRAM.

Declaratives and Priority Numbers

Declaratives are a special part of the Procedure Division. They begin with DECLARATIVES. and end with END DECLARATIVES. Each declarative procedure runs only when a specific condition occurs (e.g. a file error or a report group). They are not part of the normal top-to-bottom flow. Sections in declaratives typically include a priority number (0–49). Outside declaratives, sections can optionally have a priority number (0–99) for segmentation: the system can swap segments in and out of memory. This is an advanced topic; many programs omit priority numbers and use only paragraphs.

Best Practices

Test Your Knowledge

Test Your Knowledge

1. Execution in the PROCEDURE DIVISION starts at:

  • The first paragraph
  • The first section
  • The first statement (excluding declaratives)
  • The paragraph named MAIN

2. Parameters in PROCEDURE DIVISION USING must be defined in:

  • WORKING-STORAGE
  • FILE SECTION
  • LINKAGE SECTION
  • Any of the above

3. A paragraph ends when:

  • You code END-PARAGRAPH
  • The next paragraph-name or section header appears
  • You code EXIT PARAGRAPH
  • After 10 statements