The PERFORM statement is COBOL's primary mechanism for program control flow. It executes paragraphs, sections, or inline code blocks, and provides various looping constructs for iteration control.
Executes a paragraph or section once:
12PERFORM paragraph-name PERFORM section-name
Example:
12345678910PROCEDURE DIVISION. MAIN-PARA. PERFORM INITIALIZE-DATA PERFORM PROCESS-RECORDS PERFORM CLEANUP STOP RUN. INITIALIZE-DATA. MOVE ZEROS TO WS-COUNTER MOVE SPACES TO WS-BUFFER.
Executes a paragraph or section a specific number of times:
12PERFORM paragraph-name n TIMES PERFORM paragraph-name identifier TIMES
Example:
123456789PROCEDURE DIVISION. MAIN-PARA. PERFORM PROCESS-MONTH 12 TIMES PERFORM GENERATE-REPORT 3 TIMES STOP RUN. PROCESS-MONTH. ADD 1 TO MONTH-COUNT DISPLAY "Processing month: " MONTH-COUNT.
Executes until a condition becomes true:
123PERFORM paragraph-name UNTIL condition PERFORM paragraph-name WITH TEST BEFORE UNTIL condition PERFORM paragraph-name WITH TEST AFTER UNTIL condition
Example:
1234567891011121314PROCEDURE DIVISION. MAIN-PARA. PERFORM READ-RECORD PERFORM PROCESS-RECORD UNTIL END-OF-FILE STOP RUN. READ-RECORD. READ INPUT-FILE AT END MOVE 'Y' TO EOF-FLAG END-READ. PROCESS-RECORD. ADD 1 TO RECORD-COUNT PERFORM READ-RECORD.
Executes with a varying index or variable:
1234567PERFORM paragraph-name VARYING identifier-1 FROM identifier-2 BY identifier-3 UNTIL condition PERFORM paragraph-name VARYING identifier-1 FROM literal-1 BY literal-2 UNTIL condition
Example:
12345678910PROCEDURE DIVISION. MAIN-PARA. PERFORM PROCESS-ARRAY VARYING ARRAY-INDEX FROM 1 BY 1 UNTIL ARRAY-INDEX > 100 STOP RUN. PROCESS-ARRAY. ADD ARRAY-VALUE(ARRAY-INDEX) TO TOTAL-SUM DISPLAY "Element " ARRAY-INDEX ": " ARRAY-VALUE(ARRAY-INDEX).
Executes while a condition is true:
1PERFORM paragraph-name WHILE condition
Example:
1234567891011PROCEDURE DIVISION. MAIN-PARA. PERFORM PROCESS-RECORD WHILE VALID-RECORD STOP RUN. PROCESS-RECORD. READ INPUT-FILE AT END SET INVALID-RECORD TO TRUE NOT AT END ADD 1 TO RECORD-COUNT END-READ.
Executes statements directly without a separate paragraph:
1234567891011121314151617PERFORM statement-1 statement-2 ... END-PERFORM PERFORM UNTIL condition statement-1 statement-2 ... END-PERFORM PERFORM VARYING identifier FROM start BY increment UNTIL condition statement-1 statement-2 ... END-PERFORM
Example:
1234567891011121314PROCEDURE DIVISION. MAIN-PARA. PERFORM UNTIL COUNTER >= 10 ADD 1 TO COUNTER COMPUTE TOTAL = TOTAL + COUNTER DISPLAY "Counter: " COUNTER " Total: " TOTAL END-PERFORM PERFORM VARYING I FROM 1 BY 1 UNTIL I > 5 DISPLAY "Iteration: " I ADD I TO SUM END-PERFORM STOP RUN.
| PERFORM Form | Syntax | Purpose |
|---|---|---|
| Simple | PERFORM paragraph-name | Execute once |
| TIMES | PERFORM paragraph-name n TIMES | Execute fixed number of times |
| UNTIL | PERFORM paragraph-name UNTIL condition | Execute until condition is true |
| VARYING | PERFORM paragraph-name VARYING var FROM start BY incr UNTIL condition | Execute with varying index |
| WHILE | PERFORM paragraph-name WHILE condition | Execute while condition is true |
| Inline | PERFORM ... statements ... END-PERFORM | Execute statements directly |
| THRU | PERFORM para-1 THRU para-2 | Execute range of paragraphs |
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647IDENTIFICATION DIVISION. PROGRAM-ID. FILE-PROCESS. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT INPUT-FILE ASSIGN TO "INPUT.DAT" ORGANIZATION IS SEQUENTIAL FILE STATUS IS FILE-STATUS-CODE. DATA DIVISION. FILE SECTION. FD INPUT-FILE. 01 INPUT-RECORD PIC X(80). WORKING-STORAGE SECTION. 01 FILE-STATUS-CODE PIC XX. 88 END-OF-FILE VALUE "10". 01 RECORD-COUNT PIC 9(5) VALUE ZEROS. PROCEDURE DIVISION. MAIN-PROCESS. OPEN INPUT INPUT-FILE IF FILE-STATUS-CODE NOT = "00" DISPLAY "Error opening file" STOP RUN END-IF PERFORM READ-RECORD PERFORM PROCESS-RECORD UNTIL END-OF-FILE CLOSE INPUT-FILE DISPLAY "Records processed: " RECORD-COUNT STOP RUN. READ-RECORD. READ INPUT-FILE AT END CONTINUE NOT AT END ADD 1 TO RECORD-COUNT END-READ. PROCESS-RECORD. *> Process the record DISPLAY "Processing: " INPUT-RECORD PERFORM READ-RECORD.
12345678910111213141516171819202122232425262728293031IDENTIFICATION DIVISION. PROGRAM-ID. ARRAY-PROCESS. DATA DIVISION. WORKING-STORAGE SECTION. 01 ARRAY-INDEX PIC 9(3). 01 NUMBER-ARRAY. 05 NUMBERS OCCURS 10 TIMES PIC 9(5). 01 TOTAL-SUM PIC 9(7) VALUE ZEROS. 01 AVERAGE-VALUE PIC 9(5)V99. PROCEDURE DIVISION. MAIN-PROCESS. *> Initialize array PERFORM VARYING ARRAY-INDEX FROM 1 BY 1 UNTIL ARRAY-INDEX > 10 COMPUTE NUMBERS(ARRAY-INDEX) = ARRAY-INDEX * 10 END-PERFORM *> Calculate sum PERFORM VARYING ARRAY-INDEX FROM 1 BY 1 UNTIL ARRAY-INDEX > 10 ADD NUMBERS(ARRAY-INDEX) TO TOTAL-SUM END-PERFORM *> Calculate average COMPUTE AVERAGE-VALUE = TOTAL-SUM / 10 DISPLAY "Total: " TOTAL-SUM DISPLAY "Average: " AVERAGE-VALUE STOP RUN.
12345678910111213141516171819202122232425262728293031323334IDENTIFICATION DIVISION. PROGRAM-ID. NESTED-PERFORM. DATA DIVISION. WORKING-STORAGE SECTION. 01 ROW-INDEX PIC 9(2). 01 COL-INDEX PIC 9(2). 01 MATRIX. 05 ROW OCCURS 5 TIMES. 10 COL OCCURS 5 TIMES PIC 9(3). PROCEDURE DIVISION. MAIN-PROCESS. *> Initialize matrix PERFORM VARYING ROW-INDEX FROM 1 BY 1 UNTIL ROW-INDEX > 5 PERFORM VARYING COL-INDEX FROM 1 BY 1 UNTIL COL-INDEX > 5 COMPUTE COL(ROW-INDEX, COL-INDEX) = ROW-INDEX * 10 + COL-INDEX END-PERFORM END-PERFORM *> Display matrix PERFORM VARYING ROW-INDEX FROM 1 BY 1 UNTIL ROW-INDEX > 5 PERFORM VARYING COL-INDEX FROM 1 BY 1 UNTIL COL-INDEX > 5 DISPLAY "Matrix[" ROW-INDEX "," COL-INDEX "] = " COL(ROW-INDEX, COL-INDEX) END-PERFORM END-PERFORM STOP RUN.
The TEST BEFORE and TEST AFTER options control when the condition is evaluated in PERFORM UNTIL:
123PERFORM paragraph-name UNTIL condition *> Condition checked before each iteration *> Loop may not execute if condition is initially true
123PERFORM paragraph-name WITH TEST AFTER UNTIL condition *> Condition checked after each iteration *> Loop executes at least once
Example:
12345678910111213141516171819202122DATA DIVISION. WORKING-STORAGE SECTION. 01 COUNTER PIC 9(2) VALUE 10. PROCEDURE DIVISION. MAIN-PARA. *> TEST BEFORE - may not execute PERFORM PROCESS-ITEM UNTIL COUNTER >= 5 *> Since COUNTER starts at 10, condition is already true *> Loop does not execute MOVE 10 TO COUNTER *> TEST AFTER - executes at least once PERFORM PROCESS-ITEM WITH TEST AFTER UNTIL COUNTER >= 5 *> Loop executes once, then checks condition STOP RUN. PROCESS-ITEM. SUBTRACT 1 FROM COUNTER DISPLAY "Counter: " COUNTER.
PERFORM THRU executes a range of paragraphs in sequence:
1234PERFORM paragraph-1 THRU paragraph-2 *> Executes paragraph-1, then all paragraphs between, *> then paragraph-2, then returns
Note: PERFORM THRU is less commonly used in modern COBOL and can make code harder to maintain. Consider using explicit PERFORM statements or restructuring code to avoid THRU.
The PERFORM statement is COBOL's primary control flow mechanism. Key points:
Choose the appropriate PERFORM form based on your iteration needs. PERFORM VARYING is particularly useful for array processing, while PERFORM UNTIL is ideal for condition-based loops like file processing.
1. What is the simplest form of the PERFORM statement?
2. How do you execute a paragraph exactly 5 times?
3. What does PERFORM UNTIL do?
4. Which PERFORM variation is best for processing an array?
5. What is the syntax for an inline PERFORM?
Learn about control flow structures including PERFORM, IF, EVALUATE, and other program control mechanisms in COBOL.
Comprehensive guide to the PERFORM statement including all variations, examples, and best practices.
Learn techniques for processing arrays and tables including OCCURS clause and table iteration patterns.