Files
cobol-java-v3/benchmark-programs/11-divide-25/main-11-divide-25.cbl
T
NB-076 94400d50d4 feat: add benchmark-programs — 58 telecom COBOL test programs
作为子目录纳入系统,与核心测试管道协同

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-25 09:53:21 +08:00

643 lines
25 KiB
COBOL

*> Input: FILE-IN.DAT Output: FILE-OUT-NN.DAT, AUDIT-11.RPT
*> Original DIVIDE + expansions: I/O recovery, hash totals,
*> header/trailer recs, split stats, audit trail, boundary
*> checks, trailing recs, naming validation, file inventory,
*> error severity levels (WARNING/ERROR/FATAL)
IDENTIFICATION DIVISION.
PROGRAM-ID. Divide25.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT FILE-IN
ASSIGN TO "FILE-IN.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-FILE-STATUS-IN.
SELECT FILE-OUT
ASSIGN TO WS-OUT-FILE
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-FILE-STATUS-OUT.
SELECT FILE-AUDIT
ASSIGN TO "AUDIT-11.RPT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-FILE-STATUS-AUD.
DATA DIVISION.
FILE SECTION.
FD FILE-IN.
01 FILE-IN-REC.
05 IN-RECORD PIC X(30).
FD FILE-OUT.
01 FILE-OUT-REC.
05 OUT-RECORD PIC X(30).
FD FILE-AUDIT.
01 FILE-AUDIT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 WS-TELECOM-REC.
COPY "telecom/TEL-INVOICE.cpy".
01 WS-STATUS.
05 WS-EOF-FLAG PIC X VALUE 'N'.
88 WS-EOF VALUE 'Y' FALSE 'N'.
05 WS-FILE-STATUS-IN PIC X(2).
05 WS-FILE-STATUS-OUT PIC X(2).
05 WS-FILE-STATUS-AUD PIC X(2).
01 WS-COUNTERS.
05 WS-REC-COUNT PIC 9(5) VALUE 0.
05 WS-FILE-NUM PIC 9(2) VALUE 0.
05 WS-DIVISOR PIC 9(2) VALUE 25.
05 WS-QUOTIENT PIC 9(5).
05 WS-REMAINDER PIC 9(5).
05 WS-REC-IN-FILE PIC 9(5) VALUE 0.
05 WS-TOTAL-RECS-WRITTEN PIC 9(5) VALUE 0.
01 WS-OUT-FILE PIC X(30).
01 WS-FILE-NUM-ED PIC 99.
01 WS-DISPLAY-COUNT PIC Z(9)9.
01 WS-INVOICE-REC.
COPY "telecom/TEL-INVOICE.cpy".
01 WS-TIMESTAMP.
05 WS-TS-DATE PIC 9(8).
05 WS-TS-TIME PIC 9(8).
05 WS-TS-EDITED PIC X(19).
01 WS-OPEN-RETRY-COUNT PIC 9(2) VALUE 0.
01 WS-ALT-SUFFIX PIC X(4) VALUE ".ALT".
01 WS-OPEN-OK PIC X VALUE 'N'.
88 WS-OPEN-SUCCESS VALUE 'Y' FALSE 'N'.
88 WS-OPEN-FAILED VALUE 'N'.
01 WS-FILE-NAME-VALID PIC X VALUE 'Y'.
88 WS-FILE-NAME-OK VALUE 'Y' FALSE 'N'.
01 WS-HASH-TOTAL-IN PIC 9(9) VALUE 0.
01 WS-HASH-OUT-TABLE.
05 WS-HASH-OUT PIC 9(9) OCCURS 99.
01 WS-HASH-SUM-OUT PIC 9(9) VALUE 0.
01 WS-HASH-VERIFIED PIC X VALUE 'N'.
88 WS-HASH-VERIFIED-YES VALUE 'Y' FALSE 'N'.
01 WS-SPLIT-STATS.
05 WS-SPLIT-MIN-RECS PIC 9(5) VALUE 99999.
05 WS-SPLIT-MAX-RECS PIC 9(5) VALUE 0.
05 WS-SPLIT-TOTAL-FILES PIC 9(5) VALUE 0.
05 WS-SPLIT-TOTAL-RECS PIC 9(9) VALUE 0.
05 WS-SPLIT-AVG-RECS PIC 9(5) VALUE 0.
01 WS-BOUNDARY-FLAG PIC X.
88 WS-BOUNDARY-EMPTY VALUE 'E'.
88 WS-BOUNDARY-SINGLE VALUE 'S'.
88 WS-BOUNDARY-EXACT VALUE 'M'.
88 WS-BOUNDARY-NORMAL VALUE 'N'.
01 WS-TRAILER-COUNT PIC 9(5) VALUE 0.
01 WS-TRAILER-FLAG PIC X VALUE 'N'.
88 WS-TRAILER-WRITTEN VALUE 'Y' FALSE 'N'.
01 WS-TRAIL-RECS-LAST PIC 9(5) VALUE 0.
01 WS-SEVERITY PIC X(7).
88 WS-SEVERITY-WARN VALUE 'WARNING'.
88 WS-SEVERITY-ERR VALUE 'ERROR'.
88 WS-SEVERITY-FATAL VALUE 'FATAL'.
01 WS-ERROR-MSG PIC X(60).
01 WS-SPLIT-HEADER.
05 FILLER PIC X(6) VALUE 'HEADER'.
05 FILLER PIC X VALUE SPACE.
05 WS-HDR-FILE PIC 9(2).
05 FILLER PIC X VALUE SPACE.
05 WS-HDR-DATE PIC 9(8).
05 FILLER PIC X VALUE SPACE.
05 WS-HDR-TIME PIC 9(8).
05 FILLER PIC X VALUE SPACE.
05 WS-HDR-EXPREC PIC 9(5).
01 WS-SPLIT-TRAILER.
05 FILLER PIC X(7) VALUE 'TRAILER'.
05 FILLER PIC X VALUE SPACE.
05 WS-TRL-FILE PIC 9(2).
05 FILLER PIC X VALUE SPACE.
05 WS-TRL-COUNT PIC 9(5).
05 FILLER PIC X VALUE SPACE.
05 WS-TRL-HASH PIC 9(9).
01 WS-HASH-WORK.
05 WS-H-CHAR-IDX PIC 99.
05 WS-H-CHAR PIC X.
05 WS-H-SUM PIC 9(9).
05 WS-H-ORD PIC 9(3).
01 WS-INVENTORY-REC.
05 WS-INV-FILE PIC 9(2).
05 FILLER PIC X(3) VALUE SPACES.
05 WS-INV-RECS PIC 9(5).
05 FILLER PIC X(3) VALUE SPACES.
05 WS-INV-HASH PIC 9(9).
01 WS-REPORT-LINE PIC X(80).
01 WS-I PIC 99.
01 WS-NEXT-REM PIC 9(5).
01 WS-HASH-DISP PIC Z(9)9.
PROCEDURE DIVISION.
MAIN SECTION.
MAIN-PROCEDURE.
PERFORM 1000-INIT-SECTION
PERFORM 2000-OPEN-FILES-SECTION
*> === Original code: banner ===
DISPLAY "=== 25-DIVISION PROCESSING ==="
DISPLAY "Records per file: " WS-DIVISOR
*> === Original code: processing loop ===
PERFORM 3000-PROCESS-SECTION
PERFORM 3500-TRAILING-HANDLE-SECTION
PERFORM 4000-REPORT-SECTION
PERFORM 5000-AUDIT-SECTION
PERFORM 9000-EXIT-SECTION
STOP RUN.
*> ============================================================
*> 1000-INIT-SECTION
*> ============================================================
1000-INIT-SECTION.
1000-INIT-PROC.
ACCEPT WS-TS-DATE FROM DATE YYYYMMDD
ACCEPT WS-TS-TIME FROM TIME
STRING WS-TS-DATE(1:4) '-' WS-TS-DATE(5:2) '-'
WS-TS-DATE(7:2) ' '
WS-TS-TIME(1:2) ':' WS-TS-TIME(3:2) ':'
WS-TS-TIME(5:2)
INTO WS-TS-EDITED
END-STRING
DISPLAY "=== Divide25 v2 Started " WS-TS-EDITED " ==="
MOVE 'N' TO WS-BOUNDARY-FLAG
MOVE 0 TO WS-SPLIT-TOTAL-FILES WS-SPLIT-TOTAL-RECS
MOVE 99999 TO WS-SPLIT-MIN-RECS
MOVE 0 TO WS-SPLIT-MAX-RECS WS-TRAILER-COUNT
MOVE 'N' TO WS-TRAILER-FLAG WS-HASH-VERIFIED
MOVE 0 TO WS-TRAIL-RECS-LAST WS-HASH-TOTAL-IN
MOVE 'Y' TO WS-FILE-NAME-VALID
DISPLAY "1000-INIT: All counters zeroed"
.
*> ============================================================
*> 2000-OPEN-FILES-SECTION — Retry + alt fallback for input
*> ============================================================
2000-OPEN-FILES-SECTION.
2000-OPEN-FILES-PROC.
MOVE 0 TO WS-OPEN-RETRY-COUNT
MOVE 'N' TO WS-OPEN-OK
PERFORM UNTIL WS-OPEN-SUCCESS
OR WS-OPEN-RETRY-COUNT > 3
OPEN INPUT FILE-IN
IF WS-FILE-STATUS-IN = '00'
MOVE 'Y' TO WS-OPEN-OK
DISPLAY "2000-OPEN: FILE-IN.DAT OK"
ELSE
ADD 1 TO WS-OPEN-RETRY-COUNT
MOVE 'WARNING' TO WS-SEVERITY
STRING "2000: FILE-IN retry "
WS-OPEN-RETRY-COUNT
" sts=" WS-FILE-STATUS-IN
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
END-PERFORM
IF WS-OPEN-FAILED
STRING "FILE-IN" WS-ALT-SUFFIX
INTO WS-OUT-FILE
END-STRING
OPEN INPUT FILE-IN
IF WS-FILE-STATUS-IN = '00'
MOVE 'Y' TO WS-OPEN-OK
DISPLAY "2000-OPEN: ALT file opened"
ELSE
MOVE 'FATAL' TO WS-SEVERITY
STRING "2000: FILE-IN open failed all retry"
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
PERFORM 9000-EXIT-SECTION
END-IF
END-IF
OPEN OUTPUT FILE-AUDIT
IF WS-FILE-STATUS-AUD NOT = '00'
MOVE 'FATAL' TO WS-SEVERITY
STRING "2000: AUDIT open fail sts="
WS-FILE-STATUS-AUD
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
PERFORM 9000-EXIT-SECTION
ELSE
DISPLAY "2000-OPEN: AUDIT-11.RPT OK"
STRING "*** Divide25 v2 START *** " WS-TS-EDITED
INTO WS-REPORT-LINE
WRITE FILE-AUDIT-REC FROM WS-REPORT-LINE
END-IF
.
*> ============================================================
*> 3000-PROCESS-SECTION — Read/validate/apply/write loop
*> ============================================================
3000-PROCESS-SECTION.
3000-PROCESS-PROC.
PERFORM VARYING WS-REC-COUNT FROM 1 BY 1
UNTIL WS-EOF
PERFORM 3100-READ-INPUT-SECTION
IF NOT WS-EOF
PERFORM 3200-VALIDATE-SECTION
PERFORM 3300-APPLY-RULES-SECTION
PERFORM 3400-WRITE-OUTPUT-SECTION
END-IF
END-PERFORM
.
*> ============================================================
*> 3100-READ-INPUT-SECTION — Read + FILE STATUS check
*> ============================================================
3100-READ-INPUT-SECTION.
3100-READ-INPUT-PROC.
READ FILE-IN INTO FILE-IN-REC
AT END
SET WS-EOF TO TRUE
DISPLAY "3100-READ: EOF at " WS-REC-COUNT
NOT AT END
IF WS-FILE-STATUS-IN NOT = '00'
MOVE 'ERROR' TO WS-SEVERITY
STRING "3100: FILE-IN read err sts="
WS-FILE-STATUS-IN
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
END-READ
.
*> ============================================================
*> 3200-VALIDATE-SECTION — Hash sum + boundary detect
*> ============================================================
3200-VALIDATE-SECTION.
3200-VALIDATE-PROC.
MOVE 0 TO WS-H-SUM
PERFORM VARYING WS-H-CHAR-IDX FROM 1 BY 1
UNTIL WS-H-CHAR-IDX > 30
MOVE IN-RECORD(WS-H-CHAR-IDX:1) TO WS-H-CHAR
IF WS-H-CHAR NOT = SPACE
COMPUTE WS-H-ORD = FUNCTION ORD(WS-H-CHAR)
ADD WS-H-ORD TO WS-H-SUM
END-IF
END-PERFORM
ADD WS-H-SUM TO WS-HASH-TOTAL-IN
IF WS-REC-COUNT = 1
MOVE 'S' TO WS-BOUNDARY-FLAG
END-IF
.
*> ============================================================
*> 3300-APPLY-RULES-SECTION
*> *** ORIGINAL DIVIDE LOGIC — PRESERVED VERBATIM ***
*> ============================================================
3300-APPLY-RULES-SECTION.
3300-APPLY-RULES-PROC.
DIVIDE WS-REC-COUNT BY WS-DIVISOR
GIVING WS-QUOTIENT REMAINDER WS-REMAINDER
IF WS-REMAINDER = 1
IF WS-FILE-NUM > 0
CLOSE FILE-OUT
DISPLAY " Closed: " WS-OUT-FILE
END-IF
ADD 1 TO WS-FILE-NUM
MOVE WS-FILE-NUM TO WS-FILE-NUM-ED
STRING "FILE-OUT-" DELIMITED BY SIZE
WS-FILE-NUM-ED DELIMITED BY SIZE
".DAT" DELIMITED BY SIZE
INTO WS-OUT-FILE
OPEN OUTPUT FILE-OUT
DISPLAY " Opened: " WS-OUT-FILE
END-IF
.
*> ============================================================
*> 3400-WRITE-OUTPUT-SECTION — Header/data/trailer + hash
*> ============================================================
3400-WRITE-OUTPUT-SECTION.
3400-WRITE-OUTPUT-PROC.
IF WS-REMAINDER = 1
MOVE WS-FILE-NUM TO WS-HDR-FILE
MOVE WS-TS-DATE TO WS-HDR-DATE
MOVE WS-TS-TIME TO WS-HDR-TIME
MOVE WS-DIVISOR TO WS-HDR-EXPREC
MOVE WS-SPLIT-HEADER TO FILE-OUT-REC
WRITE FILE-OUT-REC
IF WS-FILE-STATUS-OUT NOT = '00'
MOVE 'ERROR' TO WS-SEVERITY
STRING "3400: HDR write fail file="
WS-FILE-NUM " sts=" WS-FILE-STATUS-OUT
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
MOVE 0 TO WS-REC-IN-FILE
MOVE 0 TO WS-HASH-OUT(WS-FILE-NUM)
MOVE 'N' TO WS-TRAILER-FLAG
END-IF
*> Write data record (original MOVE/WRITE preserved)
MOVE IN-RECORD TO OUT-RECORD
WRITE FILE-OUT-REC
IF WS-FILE-STATUS-OUT NOT = '00'
MOVE 'ERROR' TO WS-SEVERITY
STRING "3400: Write fail file=" WS-FILE-NUM
" rec=" WS-REC-COUNT
" sts=" WS-FILE-STATUS-OUT
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
ELSE
ADD 1 TO WS-REC-IN-FILE
ADD 1 TO WS-TOTAL-RECS-WRITTEN
ADD WS-H-SUM TO WS-HASH-OUT(WS-FILE-NUM)
END-IF
*> Write trailer when next record starts new file
COMPUTE WS-NEXT-REM =
FUNCTION MOD(WS-REC-COUNT + 1, WS-DIVISOR)
IF WS-NEXT-REM = 1
MOVE WS-FILE-NUM TO WS-TRL-FILE
MOVE WS-REC-IN-FILE TO WS-TRL-COUNT
MOVE WS-HASH-OUT(WS-FILE-NUM) TO WS-TRL-HASH
MOVE WS-SPLIT-TRAILER TO FILE-OUT-REC
WRITE FILE-OUT-REC
IF WS-FILE-STATUS-OUT NOT = '00'
MOVE 'ERROR' TO WS-SEVERITY
STRING "3400: TRL write fail file="
WS-FILE-NUM " sts=" WS-FILE-STATUS-OUT
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
ADD 1 TO WS-TRAILER-COUNT
MOVE 'Y' TO WS-TRAILER-FLAG
ADD 1 TO WS-SPLIT-TOTAL-FILES
ADD WS-REC-IN-FILE TO WS-SPLIT-TOTAL-RECS
IF WS-REC-IN-FILE < WS-SPLIT-MIN-RECS
MOVE WS-REC-IN-FILE TO WS-SPLIT-MIN-RECS
END-IF
IF WS-REC-IN-FILE > WS-SPLIT-MAX-RECS
MOVE WS-REC-IN-FILE TO WS-SPLIT-MAX-RECS
END-IF
END-IF
.
*> ============================================================
*> 3500-TRAILING-HANDLE-SECTION — Last file trailer,
*> boundary classification
*> ============================================================
3500-TRAILING-HANDLE-SECTION.
3500-TRAILING-HANDLE-PROC.
IF WS-FILE-NUM > 0
IF WS-TRAILER-FLAG = 'N'
MOVE WS-FILE-NUM TO WS-TRL-FILE
MOVE WS-REC-IN-FILE TO WS-TRL-COUNT
MOVE WS-HASH-OUT(WS-FILE-NUM) TO WS-TRL-HASH
MOVE WS-SPLIT-TRAILER TO FILE-OUT-REC
WRITE FILE-OUT-REC
IF WS-FILE-STATUS-OUT NOT = '00'
MOVE 'ERROR' TO WS-SEVERITY
STRING "3500: TRL write fail last file"
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
ADD 1 TO WS-TRAILER-COUNT
MOVE 'Y' TO WS-TRAILER-FLAG
MOVE WS-REC-IN-FILE TO WS-TRAIL-RECS-LAST
ADD 1 TO WS-SPLIT-TOTAL-FILES
ADD WS-REC-IN-FILE TO WS-SPLIT-TOTAL-RECS
IF WS-REC-IN-FILE < WS-SPLIT-MIN-RECS
MOVE WS-REC-IN-FILE TO WS-SPLIT-MIN-RECS
END-IF
IF WS-REC-IN-FILE > WS-SPLIT-MAX-RECS
MOVE WS-REC-IN-FILE TO WS-SPLIT-MAX-RECS
END-IF
DISPLAY "3500-TRAIL: Last trailer written"
END-IF
ELSE
MOVE 'E' TO WS-BOUNDARY-FLAG
DISPLAY "3500-TRAIL: Empty input file"
END-IF
IF WS-TOTAL-RECS-WRITTEN = 0
MOVE 'E' TO WS-BOUNDARY-FLAG
END-IF
IF WS-TOTAL-RECS-WRITTEN = 1
MOVE 'S' TO WS-BOUNDARY-FLAG
DISPLAY "3500-TRAIL: Single-record file"
END-IF
IF WS-SPLIT-TOTAL-FILES > 1
IF WS-SPLIT-MIN-RECS = WS-SPLIT-MAX-RECS
MOVE 'M' TO WS-BOUNDARY-FLAG
DISPLAY "3500-TRAIL: Exact multiple split"
END-IF
END-IF
.
*> ============================================================
*> 4000-REPORT-SECTION — Display + audit file stats/inventory
*> ============================================================
4000-REPORT-SECTION.
4000-REPORT-PROC.
DISPLAY " "
DISPLAY "=== SPLIT STATISTICS REPORT ==="
MOVE WS-REC-COUNT TO WS-DISPLAY-COUNT
DISPLAY "Total records read: " WS-DISPLAY-COUNT
DISPLAY "Total records written: " WS-TOTAL-RECS-WRITTEN
DISPLAY "Output files created: " WS-FILE-NUM
DISPLAY "Divisor: " WS-DIVISOR
IF WS-SPLIT-TOTAL-FILES > 0
COMPUTE WS-SPLIT-AVG-RECS =
WS-SPLIT-TOTAL-RECS / WS-SPLIT-TOTAL-FILES
ELSE
MOVE 0 TO WS-SPLIT-AVG-RECS
END-IF
DISPLAY "Split files counted: " WS-SPLIT-TOTAL-FILES
DISPLAY "Min recs per file: " WS-SPLIT-MIN-RECS
DISPLAY "Max recs per file: " WS-SPLIT-MAX-RECS
DISPLAY "Avg recs per file: " WS-SPLIT-AVG-RECS
DISPLAY "Trailer recs written: " WS-TRAILER-COUNT
DISPLAY "Trailing recs last file: " WS-TRAIL-RECS-LAST
DISPLAY "Boundary condition: " WS-BOUNDARY-FLAG
STRING "*** SPLIT STATS *** Total=" WS-SPLIT-TOTAL-RECS
" Files=" WS-SPLIT-TOTAL-FILES
" Min=" WS-SPLIT-MIN-RECS
" Max=" WS-SPLIT-MAX-RECS
INTO WS-REPORT-LINE
WRITE FILE-AUDIT-REC FROM WS-REPORT-LINE
IF WS-FILE-STATUS-AUD NOT = '00'
MOVE 'WARNING' TO WS-SEVERITY
STRING "4000: Audit write sts=" WS-FILE-STATUS-AUD
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
STRING "*** OUTPUT FILE INVENTORY ***"
INTO WS-REPORT-LINE
WRITE FILE-AUDIT-REC FROM WS-REPORT-LINE
PERFORM VARYING WS-I FROM 1 BY 1
UNTIL WS-I > WS-FILE-NUM
MOVE WS-I TO WS-INV-FILE
IF WS-I < WS-FILE-NUM
MOVE WS-DIVISOR TO WS-INV-RECS
ELSE
MOVE WS-REC-IN-FILE TO WS-INV-RECS
END-IF
MOVE WS-HASH-OUT(WS-I) TO WS-INV-HASH
STRING "FILE " WS-INV-FILE " RECS=" WS-INV-RECS
" HASH=" WS-INV-HASH
INTO WS-REPORT-LINE
WRITE FILE-AUDIT-REC FROM WS-REPORT-LINE
END-PERFORM
.
*> ============================================================
*> 5000-AUDIT-SECTION — Hash total verification
*> ============================================================
5000-AUDIT-SECTION.
5000-AUDIT-PROC.
DISPLAY "=== HASH TOTAL VERIFICATION ==="
MOVE 0 TO WS-HASH-SUM-OUT
PERFORM VARYING WS-I FROM 1 BY 1
UNTIL WS-I > WS-FILE-NUM
ADD WS-HASH-OUT(WS-I) TO WS-HASH-SUM-OUT
END-PERFORM
MOVE WS-HASH-TOTAL-IN TO WS-HASH-DISP
DISPLAY "Input hash: " WS-HASH-DISP
MOVE WS-HASH-SUM-OUT TO WS-HASH-DISP
DISPLAY "Output hash: " WS-HASH-DISP
DISPLAY "Files hashed: " WS-FILE-NUM
IF WS-HASH-TOTAL-IN = WS-HASH-SUM-OUT
MOVE 'Y' TO WS-HASH-VERIFIED
DISPLAY "Hash verification: PASSED"
STRING "*** HASH VERIFICATION PASSED ***"
INTO WS-REPORT-LINE
ELSE
MOVE 'N' TO WS-HASH-VERIFIED
DISPLAY "Hash verification: FAILED"
MOVE 'ERROR' TO WS-SEVERITY
STRING "5000: Hash mismatch IN=" WS-HASH-TOTAL-IN
" OUT=" WS-HASH-SUM-OUT
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
STRING "*** HASH VERIFICATION FAILED ***"
INTO WS-REPORT-LINE
END-IF
WRITE FILE-AUDIT-REC FROM WS-REPORT-LINE
.
*> ============================================================
*> 6000-ERROR-HANDLE-SECTION — Log with severity level
*> ============================================================
6000-ERROR-HANDLE-SECTION.
6000-ERROR-HANDLE-PROC.
DISPLAY "*** " WS-SEVERITY " *** " WS-ERROR-MSG
STRING "*** " WS-SEVERITY " *** " WS-ERROR-MSG
INTO WS-REPORT-LINE
WRITE FILE-AUDIT-REC FROM WS-REPORT-LINE
IF WS-FILE-STATUS-AUD NOT = '00'
DISPLAY "6000: Audit write also failed"
END-IF
IF WS-SEVERITY-FATAL
DISPLAY "6000: FATAL — terminating"
PERFORM 9000-EXIT-SECTION
END-IF
.
*> ============================================================
*> 9000-EXIT-SECTION — Close files, original summary
*> *** ORIGINAL CLOSE / DISPLAY LOGIC PRESERVED ***
*> ============================================================
9000-EXIT-SECTION.
9000-EXIT-PROC.
ACCEPT WS-TS-TIME FROM TIME
STRING WS-TS-TIME(1:2) ':' WS-TS-TIME(3:2) ':'
WS-TS-TIME(5:2) INTO WS-TS-EDITED
END-STRING
IF WS-FILE-NUM > 0
CLOSE FILE-OUT
IF WS-FILE-STATUS-OUT NOT = '00'
MOVE 'WARNING' TO WS-SEVERITY
STRING "9000: FILE-OUT close sts="
WS-FILE-STATUS-OUT
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
DISPLAY "Closed final file: " WS-OUT-FILE
END-IF
MOVE WS-REC-COUNT TO WS-DISPLAY-COUNT
DISPLAY " "
DISPLAY "Total records read: " WS-DISPLAY-COUNT
DISPLAY "Output files created: " WS-FILE-NUM
CLOSE FILE-IN
IF WS-FILE-STATUS-IN NOT = '00'
MOVE 'WARNING' TO WS-SEVERITY
STRING "9000: FILE-IN close sts="
WS-FILE-STATUS-IN
INTO WS-ERROR-MSG
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
STRING "*** Divide25 v2 END *** " WS-TS-EDITED
INTO WS-REPORT-LINE
WRITE FILE-AUDIT-REC FROM WS-REPORT-LINE
CLOSE FILE-AUDIT
DISPLAY " "
DISPLAY "--- Boundary condition ---"
EVALUATE TRUE
WHEN WS-BOUNDARY-EMPTY
DISPLAY " EMPTY FILE (0 records)"
WHEN WS-BOUNDARY-SINGLE
DISPLAY " SINGLE-RECORD FILE"
WHEN WS-BOUNDARY-EXACT
DISPLAY " EXACT MULTIPLE of " WS-DIVISOR
WHEN WS-BOUNDARY-NORMAL
DISPLAY " NORMAL (trailing partial batch)"
WHEN OTHER
DISPLAY " NOT DETERMINED"
END-EVALUATE
DISPLAY "--- Data Integrity ---"
MOVE WS-HASH-TOTAL-IN TO WS-HASH-DISP
DISPLAY " Input hash: " WS-HASH-DISP
MOVE WS-HASH-SUM-OUT TO WS-HASH-DISP
DISPLAY " Output hash: " WS-HASH-DISP
IF WS-HASH-VERIFIED-YES
DISPLAY " Integrity: PASSED"
ELSE
DISPLAY " Integrity: FAILED"
END-IF
DISPLAY " "
DISPLAY "=== Divide25 v2 Ended at "
WS-TS-EDITED " ==="
STOP RUN.