feat: add benchmark-programs — 58 telecom COBOL test programs
作为子目录纳入系统,与核心测试管道协同 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,696 @@
|
||||
*> ============================================================
|
||||
*> 10-divide-50 : 请求书50分割 (Invoice 50-Split)
|
||||
*> Input : FILE-IN.DAT (请求书记录: 50件毎分割)
|
||||
*> Output: FILE-OUT-NN (50件毎の分割出力文件: FILE-OUT-01, 02...)
|
||||
*> Coverage: S-N001~N003, S-N006, S-N007, S-R001, S-R002
|
||||
*> EXTENDED: Added file recovery, hash totals, boundary checks,
|
||||
*> split statistics, audit trail, inventory records,
|
||||
*> file status checking, error severity levels,
|
||||
*> header/trailer records, file-naming validation
|
||||
*> ============================================================
|
||||
IDENTIFICATION DIVISION.
|
||||
PROGRAM-ID. Divide50.
|
||||
|
||||
ENVIRONMENT DIVISION.
|
||||
INPUT-OUTPUT SECTION.
|
||||
FILE-CONTROL.
|
||||
SELECT FILE-IN
|
||||
ASSIGN TO WS-FILE-IN-NAME
|
||||
ORGANIZATION IS LINE SEQUENTIAL
|
||||
FILE STATUS IS WS-FILE-IN-STATUS.
|
||||
|
||||
SELECT FILE-OUT
|
||||
ASSIGN TO WS-OUT-FILE
|
||||
ORGANIZATION IS LINE SEQUENTIAL
|
||||
FILE STATUS IS WS-FILE-OUT-STATUS.
|
||||
|
||||
SELECT FILE-AUDIT
|
||||
ASSIGN TO "AUDIT-OUT.DAT"
|
||||
ORGANIZATION IS LINE SEQUENTIAL
|
||||
FILE STATUS IS WS-FILE-AUDIT-STATUS.
|
||||
|
||||
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'.
|
||||
|
||||
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 50.
|
||||
05 WS-QUOTIENT PIC 9(5).
|
||||
05 WS-REMAINDER PIC 9(5).
|
||||
|
||||
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".
|
||||
|
||||
*> ===== EXPANDED: Dynamic input file name =====
|
||||
01 WS-FILE-IN-NAME PIC X(30) VALUE "FILE-IN.DAT".
|
||||
|
||||
*> ===== EXPANDED: File status fields =====
|
||||
01 WS-FILE-STATUS-VARS.
|
||||
05 WS-FILE-IN-STATUS PIC X(2).
|
||||
05 WS-FILE-OUT-STATUS PIC X(2).
|
||||
05 WS-FILE-AUDIT-STATUS PIC X(2).
|
||||
|
||||
*> ===== EXPANDED: Error handling with severity levels =====
|
||||
01 WS-ERROR-HANDLING.
|
||||
05 WS-OPEN-RETRY-COUNT PIC 9(2) VALUE 0.
|
||||
05 WS-OPEN-RETRY-MAX PIC 9(2) VALUE 3.
|
||||
05 WS-ALT-SUFFIX PIC X(3) VALUE "ALT".
|
||||
05 WS-ALT-OUT-FILE PIC X(30).
|
||||
05 WS-SEVERITY PIC X(7).
|
||||
88 WS-SEVERITY-WARNING VALUE 'WARNING'.
|
||||
88 WS-SEVERITY-ERROR VALUE 'ERROR'.
|
||||
88 WS-SEVERITY-FATAL VALUE 'FATAL'.
|
||||
|
||||
*> ===== EXPANDED: File name validation flag =====
|
||||
01 WS-FILE-NAME-FLAGS.
|
||||
05 WS-FILE-NAME-VALID PIC X VALUE 'Y'.
|
||||
88 WS-FILE-NAME-OK VALUE 'Y' FALSE 'N'.
|
||||
88 WS-FILE-NAME-BAD VALUE 'N'.
|
||||
05 WS-NAME-CHAR-IDX PIC 9(2).
|
||||
05 WS-NAME-CHAR-VAL PIC X(1).
|
||||
|
||||
*> ===== EXPANDED: Hash totals for data integrity =====
|
||||
01 WS-HASH-TOTALS.
|
||||
05 WS-HASH-TOTAL-IN PIC 9(12) VALUE 0.
|
||||
05 WS-HASH-TOTAL-OUT PIC 9(12) VALUE 0.
|
||||
05 WS-HASH-VERIFIED PIC X VALUE 'N'.
|
||||
88 WS-HASH-MATCH VALUE 'Y' FALSE 'N'.
|
||||
|
||||
*> ===== EXPANDED: Split statistics per output file =====
|
||||
01 WS-SPLIT-STATS.
|
||||
05 WS-SPLIT-REC-COUNT PIC 9(5) VALUE 0.
|
||||
05 WS-SPLIT-HASH-TOTAL PIC 9(12) VALUE 0.
|
||||
05 WS-SPLIT-REC-MIN PIC X(30).
|
||||
05 WS-SPLIT-REC-MAX PIC X(30).
|
||||
05 WS-SPLIT-FIRST-REC PIC X(30).
|
||||
05 WS-SPLIT-LAST-REC PIC X(30).
|
||||
|
||||
*> ===== EXPANDED: Boundary condition flags =====
|
||||
01 WS-BOUNDARY-FLAG PIC X VALUE 'N'.
|
||||
88 WS-BOUNDARY-EMPTY VALUE 'E'.
|
||||
88 WS-BOUNDARY-SINGLE VALUE 'S'.
|
||||
88 WS-BOUNDARY-EXACT VALUE 'X'.
|
||||
88 WS-BOUNDARY-TRAILING VALUE 'T'.
|
||||
01 WS-TRAILER-COUNT PIC 9(5) VALUE 0.
|
||||
|
||||
*> ===== EXPANDED: Inventory table for output files =====
|
||||
01 WS-INVENTORY-TABLE.
|
||||
05 WS-INVENTORY-ENTRIES PIC 9(2) VALUE 0.
|
||||
05 WS-INVENTORY-ENTRY OCCURS 99 TIMES
|
||||
INDEXED BY WS-INV-IDX.
|
||||
10 WS-INV-FILE-NUM PIC 9(2).
|
||||
10 WS-INV-REC-COUNT PIC 9(5).
|
||||
10 WS-INV-HASH-TOTAL PIC 9(12).
|
||||
|
||||
*> ===== EXPANDED: Timestamp for display tracing =====
|
||||
01 WS-TIMESTAMP PIC X(14).
|
||||
|
||||
*> ===== EXPANDED: Batch control totals =====
|
||||
01 WS-BATCH-CONTROLS.
|
||||
05 WS-BATCH-TOTAL-RECS PIC 9(5) VALUE 0.
|
||||
|
||||
*> ===== EXPANDED: Display edited fields =====
|
||||
01 WS-DISPLAY-EDITED.
|
||||
05 WS-DISP-HASH-IN PIC Z(11)9.
|
||||
05 WS-DISP-HASH-OUT PIC Z(11)9.
|
||||
05 WS-DISP-SPLIT-COUNT PIC Z(9)9.
|
||||
05 WS-DISP-SPLIT-HASH PIC Z(11)9.
|
||||
05 WS-DISP-RETRY PIC Z9.
|
||||
05 WS-DISP-TRAILER PIC Z(9)9.
|
||||
05 WS-DISP-INV-RECS PIC Z(9)9.
|
||||
05 WS-DISP-INV-HASH PIC Z(11)9.
|
||||
|
||||
*> ===== EXPANDED: Hash computation work fields =====
|
||||
01 WS-HASH-WORK.
|
||||
05 WS-HASH-VAL PIC 9(3).
|
||||
05 WS-HASH-IDX PIC 9(2).
|
||||
05 WS-HASH-ALLOC PIC 9(12).
|
||||
|
||||
*> ===== EXPANDED: Inventory sum work fields =====
|
||||
01 WS-INVENTORY-SUM.
|
||||
05 WS-INV-SUM-COUNT PIC 9(5) VALUE 0.
|
||||
05 WS-INV-SUM-HASH PIC 9(12) VALUE 0.
|
||||
|
||||
*> ===== EXPANDED: Audit report fields =====
|
||||
01 WS-AUDIT-LINE.
|
||||
05 WS-AUDIT-TYPE PIC X(15).
|
||||
05 WS-AUDIT-DATA PIC X(65).
|
||||
|
||||
*> ===== EXPANDED: File name check constants =====
|
||||
01 WS-INVALID-CHARS.
|
||||
05 WS-INVALID-CHAR PIC X(18) VALUE
|
||||
"!@#$%^&*()+=[]{}|;':<>?,/".
|
||||
|
||||
PROCEDURE DIVISION.
|
||||
MAIN SECTION.
|
||||
MAIN-PROCEDURE.
|
||||
PERFORM 1000-INIT-SECTION
|
||||
PERFORM 2000-OPEN-FILES-SECTION
|
||||
PERFORM 3000-PROCESS-SECTION
|
||||
PERFORM 4000-REPORT-SECTION
|
||||
PERFORM 5000-AUDIT-SECTION
|
||||
PERFORM 9000-EXIT-SECTION
|
||||
STOP RUN.
|
||||
*
|
||||
1000-INIT-SECTION.
|
||||
*
|
||||
1000-INIT-PROC.
|
||||
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
||||
|
||||
DISPLAY "=== 50-DIVISION PROCESSING ==="
|
||||
DISPLAY "Records per file: " WS-DIVISOR
|
||||
DISPLAY "Init: " WS-TIMESTAMP
|
||||
DISPLAY " "
|
||||
|
||||
INITIALIZE WS-FILE-STATUS-VARS WS-ERROR-HANDLING
|
||||
INITIALIZE WS-HASH-TOTALS WS-SPLIT-STATS
|
||||
INITIALIZE WS-BOUNDARY-FLAG WS-TRAILER-COUNT
|
||||
INITIALIZE WS-INVENTORY-TABLE WS-BATCH-CONTROLS
|
||||
INITIALIZE WS-INVENTORY-SUM WS-HASH-WORK
|
||||
|
||||
MOVE "FILE-IN.DAT" TO WS-FILE-IN-NAME
|
||||
.
|
||||
*
|
||||
2000-OPEN-FILES-SECTION.
|
||||
*
|
||||
2000-OPEN-FILES-PROC.
|
||||
*> Open input file with status check
|
||||
OPEN INPUT FILE-IN
|
||||
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
||||
|
||||
IF WS-FILE-IN-STATUS = "00"
|
||||
DISPLAY "[" WS-TIMESTAMP "] OPEN: FILE-IN.DAT OK"
|
||||
ELSE
|
||||
MOVE 'ERROR' TO WS-SEVERITY
|
||||
DISPLAY "[" WS-TIMESTAMP "] ERROR: FILE-IN open "
|
||||
"failed status=" WS-FILE-IN-STATUS
|
||||
MOVE "FILE-IN.ALT" TO WS-FILE-IN-NAME
|
||||
ADD 1 TO WS-OPEN-RETRY-COUNT
|
||||
OPEN INPUT FILE-IN
|
||||
IF WS-FILE-IN-STATUS = "00"
|
||||
DISPLAY "[" WS-TIMESTAMP "] OPEN: FILE-IN.ALT OK "
|
||||
"(retry=" WS-OPEN-RETRY-COUNT ")"
|
||||
ELSE
|
||||
MOVE 'FATAL' TO WS-SEVERITY
|
||||
DISPLAY "[" WS-TIMESTAMP "] FATAL: Cannot open "
|
||||
"FILE-IN after retry"
|
||||
PERFORM 6000-ERROR-HANDLE-SECTION
|
||||
END-IF
|
||||
END-IF
|
||||
|
||||
OPEN OUTPUT FILE-AUDIT
|
||||
IF WS-FILE-AUDIT-STATUS = "00"
|
||||
DISPLAY "[" WS-TIMESTAMP "] OPEN: AUDIT-OUT.DAT OK"
|
||||
ELSE
|
||||
DISPLAY "[" WS-TIMESTAMP "] WARNING: AUDIT open "
|
||||
"failed status=" WS-FILE-AUDIT-STATUS
|
||||
END-IF
|
||||
|
||||
MOVE "AUDIT-START" TO WS-AUDIT-TYPE
|
||||
STRING "Session started " WS-TIMESTAMP
|
||||
" divisor=" WS-DIVISOR
|
||||
" input=" WS-FILE-IN-NAME
|
||||
INTO WS-AUDIT-DATA
|
||||
END-STRING
|
||||
MOVE WS-AUDIT-LINE TO FILE-AUDIT-REC
|
||||
WRITE FILE-AUDIT-REC
|
||||
.
|
||||
*
|
||||
3000-PROCESS-SECTION.
|
||||
*
|
||||
3000-PROCESS-PROC.
|
||||
MOVE "AUDIT-PROCESS" TO WS-AUDIT-TYPE
|
||||
STRING "Processing started, input="
|
||||
WS-FILE-IN-NAME
|
||||
INTO WS-AUDIT-DATA
|
||||
END-STRING
|
||||
MOVE WS-AUDIT-LINE TO FILE-AUDIT-REC
|
||||
WRITE FILE-AUDIT-REC
|
||||
|
||||
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
|
||||
|
||||
*> Close and finalize the last output file
|
||||
IF WS-FILE-NUM > 0
|
||||
PERFORM 3500-FINALIZE-FILE-SECTION
|
||||
CLOSE FILE-OUT
|
||||
IF WS-FILE-OUT-STATUS NOT = "00"
|
||||
DISPLAY "WARNING: FILE-OUT close status="
|
||||
WS-FILE-OUT-STATUS
|
||||
END-IF
|
||||
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
||||
DISPLAY "[" WS-TIMESTAMP "] Closed final file: "
|
||||
WS-OUT-FILE
|
||||
END-IF
|
||||
.
|
||||
*
|
||||
3100-READ-INPUT-SECTION.
|
||||
*
|
||||
3100-READ-INPUT-PROC.
|
||||
READ FILE-IN INTO FILE-IN-REC
|
||||
AT END SET WS-EOF TO TRUE
|
||||
NOT AT END
|
||||
ADD 1 TO WS-BATCH-TOTAL-RECS
|
||||
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
||||
DISPLAY "[" WS-TIMESTAMP "] Read record "
|
||||
WS-REC-COUNT
|
||||
END-READ
|
||||
|
||||
IF WS-FILE-IN-STATUS NOT = "00"
|
||||
AND WS-FILE-IN-STATUS NOT = "10"
|
||||
MOVE 'ERROR' TO WS-SEVERITY
|
||||
DISPLAY "ERROR: FILE-IN read failed, status="
|
||||
WS-FILE-IN-STATUS " at record "
|
||||
WS-REC-COUNT
|
||||
PERFORM 6000-ERROR-HANDLE-SECTION
|
||||
END-IF
|
||||
.
|
||||
*
|
||||
3200-VALIDATE-SECTION.
|
||||
*
|
||||
3200-VALIDATE-PROC.
|
||||
*> Check for empty record
|
||||
IF IN-RECORD = SPACES
|
||||
MOVE 'WARNING' TO WS-SEVERITY
|
||||
DISPLAY "WARNING: Record " WS-REC-COUNT
|
||||
" is empty"
|
||||
PERFORM 6000-ERROR-HANDLE-SECTION
|
||||
END-IF
|
||||
|
||||
*> Compute input hash total contribution
|
||||
PERFORM VARYING WS-HASH-IDX FROM 1 BY 1
|
||||
UNTIL WS-HASH-IDX > 30
|
||||
COMPUTE WS-HASH-VAL = FUNCTION ORD(
|
||||
IN-RECORD(WS-HASH-IDX:1))
|
||||
ADD WS-HASH-VAL TO WS-HASH-TOTAL-IN
|
||||
END-PERFORM
|
||||
.
|
||||
*
|
||||
3300-APPLY-RULES-SECTION.
|
||||
*
|
||||
*> === ORIGINAL DIVIDE LOGIC — preserved intact ===
|
||||
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
|
||||
PERFORM 3500-FINALIZE-FILE-SECTION
|
||||
CLOSE FILE-OUT
|
||||
IF WS-FILE-OUT-STATUS NOT = "00"
|
||||
DISPLAY "WARNING: Close status="
|
||||
WS-FILE-OUT-STATUS
|
||||
END-IF
|
||||
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
||||
DISPLAY "[" WS-TIMESTAMP "] 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
|
||||
PERFORM 3310-VALIDATE-FILE-NAME
|
||||
PERFORM 3320-OPEN-OUTPUT-WITH-RETRY
|
||||
PERFORM 3330-WRITE-SPLIT-HEADER
|
||||
END-IF
|
||||
.
|
||||
*
|
||||
3310-VALIDATE-FILE-NAME.
|
||||
*
|
||||
3310-VALIDATE-NAME-PROC.
|
||||
MOVE 'Y' TO WS-FILE-NAME-VALID
|
||||
|
||||
*> Check for empty name
|
||||
IF WS-OUT-FILE = SPACES
|
||||
MOVE 'N' TO WS-FILE-NAME-VALID
|
||||
MOVE 'ERROR' TO WS-SEVERITY
|
||||
DISPLAY "ERROR: Empty output file name"
|
||||
PERFORM 6000-ERROR-HANDLE-SECTION
|
||||
EXIT PARAGRAPH
|
||||
END-IF
|
||||
|
||||
*> Check for invalid characters in file name
|
||||
PERFORM VARYING WS-NAME-CHAR-IDX FROM 1 BY 1
|
||||
UNTIL WS-NAME-CHAR-IDX > 30
|
||||
OR WS-FILE-NAME-VALID = 'N'
|
||||
IF WS-OUT-FILE(WS-NAME-CHAR-IDX:1) = SPACE
|
||||
EXIT PERFORM
|
||||
END-IF
|
||||
MOVE WS-OUT-FILE(WS-NAME-CHAR-IDX:1)
|
||||
TO WS-NAME-CHAR-VAL
|
||||
MOVE 0 TO WS-HASH-ALLOC
|
||||
INSPECT WS-INVALID-CHARS TALLYING WS-HASH-ALLOC
|
||||
FOR ALL WS-NAME-CHAR-VAL
|
||||
IF WS-HASH-ALLOC > 0
|
||||
MOVE 'N' TO WS-FILE-NAME-VALID
|
||||
MOVE 'ERROR' TO WS-SEVERITY
|
||||
DISPLAY "ERROR: Invalid char in file name '"
|
||||
WS-OUT-FILE "'"
|
||||
PERFORM 6000-ERROR-HANDLE-SECTION
|
||||
EXIT PARAGRAPH
|
||||
END-IF
|
||||
END-PERFORM
|
||||
.
|
||||
*
|
||||
3320-OPEN-OUTPUT-WITH-RETRY.
|
||||
*
|
||||
3320-RETRY-PROC.
|
||||
MOVE 0 TO WS-OPEN-RETRY-COUNT
|
||||
MOVE WS-OUT-FILE TO WS-ALT-OUT-FILE
|
||||
.
|
||||
|
||||
3320-RETRY-LOOP.
|
||||
OPEN OUTPUT FILE-OUT
|
||||
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
||||
|
||||
IF WS-FILE-OUT-STATUS = "00"
|
||||
DISPLAY "[" WS-TIMESTAMP "] Opened: "
|
||||
WS-OUT-FILE
|
||||
ELSE
|
||||
ADD 1 TO WS-OPEN-RETRY-COUNT
|
||||
IF WS-OPEN-RETRY-COUNT <= WS-OPEN-RETRY-MAX
|
||||
DISPLAY "[" WS-TIMESTAMP "] RETRY "
|
||||
WS-OPEN-RETRY-COUNT ": "
|
||||
WS-OUT-FILE " status="
|
||||
WS-FILE-OUT-STATUS
|
||||
STRING "FILE-OUT-" WS-FILE-NUM-ED
|
||||
"-" WS-ALT-SUFFIX ".DAT"
|
||||
DELIMITED BY SIZE
|
||||
INTO WS-OUT-FILE
|
||||
END-STRING
|
||||
GO TO 3320-RETRY-LOOP
|
||||
ELSE
|
||||
MOVE 'FATAL' TO WS-SEVERITY
|
||||
DISPLAY "[" WS-TIMESTAMP "] FATAL: "
|
||||
"Open failed after "
|
||||
WS-OPEN-RETRY-MAX " retries"
|
||||
PERFORM 6000-ERROR-HANDLE-SECTION
|
||||
END-IF
|
||||
END-IF
|
||||
.
|
||||
*
|
||||
3330-WRITE-SPLIT-HEADER.
|
||||
*
|
||||
3330-HEADER-PROC.
|
||||
*> Initialize split statistics for new output file
|
||||
MOVE 0 TO WS-SPLIT-REC-COUNT
|
||||
MOVE 0 TO WS-SPLIT-HASH-TOTAL
|
||||
MOVE SPACES TO WS-SPLIT-REC-MIN
|
||||
MOVE SPACES TO WS-SPLIT-REC-MAX
|
||||
MOVE SPACES TO WS-SPLIT-FIRST-REC
|
||||
MOVE SPACES TO WS-SPLIT-LAST-REC
|
||||
|
||||
*> Write header record to output file
|
||||
MOVE SPACES TO FILE-OUT-REC
|
||||
STRING "HDR" WS-FILE-NUM-ED
|
||||
" SPLIT START"
|
||||
INTO OUT-RECORD
|
||||
END-STRING
|
||||
WRITE FILE-OUT-REC
|
||||
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
||||
DISPLAY "[" WS-TIMESTAMP "] Header: HDR"
|
||||
WS-FILE-NUM-ED " written to "
|
||||
WS-OUT-FILE
|
||||
.
|
||||
*
|
||||
3400-WRITE-OUTPUT-SECTION.
|
||||
*
|
||||
*> === ORIGINAL WRITE LOGIC — preserved intact ===
|
||||
3400-WRITE-OUTPUT-PROC.
|
||||
MOVE IN-RECORD TO OUT-RECORD
|
||||
WRITE FILE-OUT-REC
|
||||
|
||||
PERFORM 3410-UPDATE-SPLIT-STATS
|
||||
.
|
||||
*
|
||||
3410-UPDATE-SPLIT-STATS.
|
||||
*
|
||||
3410-STATS-PROC.
|
||||
ADD 1 TO WS-SPLIT-REC-COUNT
|
||||
|
||||
*> Accumulate hash total for this split file
|
||||
PERFORM VARYING WS-HASH-IDX FROM 1 BY 1
|
||||
UNTIL WS-HASH-IDX > 30
|
||||
COMPUTE WS-HASH-VAL = FUNCTION ORD(
|
||||
OUT-RECORD(WS-HASH-IDX:1))
|
||||
ADD WS-HASH-VAL TO WS-SPLIT-HASH-TOTAL
|
||||
ADD WS-HASH-VAL TO WS-HASH-TOTAL-OUT
|
||||
END-PERFORM
|
||||
|
||||
*> Track min, max, first, last records per split
|
||||
IF WS-SPLIT-REC-COUNT = 1
|
||||
MOVE IN-RECORD TO WS-SPLIT-REC-MIN
|
||||
MOVE IN-RECORD TO WS-SPLIT-REC-MAX
|
||||
MOVE IN-RECORD TO WS-SPLIT-FIRST-REC
|
||||
ELSE
|
||||
IF IN-RECORD < WS-SPLIT-REC-MIN
|
||||
MOVE IN-RECORD TO WS-SPLIT-REC-MIN
|
||||
END-IF
|
||||
IF IN-RECORD > WS-SPLIT-REC-MAX
|
||||
MOVE IN-RECORD TO WS-SPLIT-REC-MAX
|
||||
END-IF
|
||||
END-IF
|
||||
MOVE IN-RECORD TO WS-SPLIT-LAST-REC
|
||||
.
|
||||
*
|
||||
3500-FINALIZE-FILE-SECTION.
|
||||
*
|
||||
*> Write trailer record and update inventory for closing file
|
||||
3500-FINALIZE-PROC.
|
||||
MOVE SPACES TO FILE-OUT-REC
|
||||
MOVE WS-SPLIT-REC-COUNT TO WS-DISP-SPLIT-COUNT
|
||||
MOVE WS-SPLIT-HASH-TOTAL TO WS-DISP-SPLIT-HASH
|
||||
STRING "TRL" WS-FILE-NUM-ED
|
||||
" R=" WS-DISP-SPLIT-COUNT
|
||||
" H=" WS-DISP-SPLIT-HASH
|
||||
INTO OUT-RECORD
|
||||
END-STRING
|
||||
WRITE FILE-OUT-REC
|
||||
|
||||
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
||||
DISPLAY "[" WS-TIMESTAMP "] Trailer: TRL"
|
||||
WS-FILE-NUM-ED " R=" WS-DISP-SPLIT-COUNT
|
||||
" H=" WS-DISP-SPLIT-HASH
|
||||
|
||||
*> Update inventory table for this output file
|
||||
ADD 1 TO WS-INVENTORY-ENTRIES
|
||||
MOVE WS-FILE-NUM
|
||||
TO WS-INV-FILE-NUM(WS-INVENTORY-ENTRIES)
|
||||
MOVE WS-SPLIT-REC-COUNT
|
||||
TO WS-INV-REC-COUNT(WS-INVENTORY-ENTRIES)
|
||||
MOVE WS-SPLIT-HASH-TOTAL
|
||||
TO WS-INV-HASH-TOTAL(WS-INVENTORY-ENTRIES)
|
||||
|
||||
*> Write inventory record to audit file
|
||||
MOVE "INVENTORY" TO WS-AUDIT-TYPE
|
||||
STRING "File=F" WS-FILE-NUM-ED
|
||||
" Recs=" WS-DISP-SPLIT-COUNT
|
||||
" Hash=" WS-DISP-SPLIT-HASH
|
||||
INTO WS-AUDIT-DATA
|
||||
END-STRING
|
||||
MOVE WS-AUDIT-LINE TO FILE-AUDIT-REC
|
||||
WRITE FILE-AUDIT-REC
|
||||
.
|
||||
*
|
||||
4000-REPORT-SECTION.
|
||||
*
|
||||
4000-REPORT-PROC.
|
||||
MOVE WS-REC-COUNT TO WS-DISPLAY-COUNT
|
||||
DISPLAY " "
|
||||
DISPLAY "=== SPLIT REPORT ==="
|
||||
DISPLAY "Total records: " WS-DISPLAY-COUNT
|
||||
DISPLAY "Output files: " WS-FILE-NUM
|
||||
DISPLAY " "
|
||||
|
||||
*> Boundary condition detection
|
||||
IF WS-BATCH-TOTAL-RECS = 0
|
||||
SET WS-BOUNDARY-EMPTY TO TRUE
|
||||
DISPLAY "BOUNDARY: Empty input file"
|
||||
END-IF
|
||||
IF WS-BATCH-TOTAL-RECS = 1
|
||||
SET WS-BOUNDARY-SINGLE TO TRUE
|
||||
DISPLAY "BOUNDARY: Single-record file"
|
||||
END-IF
|
||||
DIVIDE WS-BATCH-TOTAL-RECS BY WS-DIVISOR
|
||||
GIVING WS-QUOTIENT REMAINDER WS-REMAINDER
|
||||
IF WS-REMAINDER = 0
|
||||
SET WS-BOUNDARY-EXACT TO TRUE
|
||||
DISPLAY "BOUNDARY: Exact multiple of " WS-DIVISOR
|
||||
ELSE
|
||||
SET WS-BOUNDARY-TRAILING TO TRUE
|
||||
MOVE WS-REMAINDER TO WS-TRAILER-COUNT
|
||||
MOVE WS-TRAILER-COUNT TO WS-DISP-TRAILER
|
||||
DISPLAY "BOUNDARY: Trailing records=" WS-DISP-TRAILER
|
||||
END-IF
|
||||
DISPLAY " "
|
||||
|
||||
*> Hash total verification
|
||||
MOVE WS-HASH-TOTAL-IN TO WS-DISP-HASH-IN
|
||||
MOVE WS-HASH-TOTAL-OUT TO WS-DISP-HASH-OUT
|
||||
DISPLAY "Hash IN: " WS-DISP-HASH-IN
|
||||
DISPLAY "Hash OUT: " WS-DISP-HASH-OUT
|
||||
MOVE 0 TO WS-INV-SUM-HASH
|
||||
PERFORM VARYING WS-INV-SUM-COUNT FROM 1 BY 1
|
||||
UNTIL WS-INV-SUM-COUNT > WS-INVENTORY-ENTRIES
|
||||
ADD WS-INV-HASH-TOTAL(WS-INV-SUM-COUNT)
|
||||
TO WS-INV-SUM-HASH
|
||||
END-PERFORM
|
||||
MOVE WS-INV-SUM-HASH TO WS-DISP-INV-HASH
|
||||
DISPLAY "Hash INV: " WS-DISP-INV-HASH
|
||||
IF WS-HASH-TOTAL-IN = WS-HASH-TOTAL-OUT
|
||||
AND WS-HASH-TOTAL-IN = WS-INV-SUM-HASH
|
||||
MOVE 'Y' TO WS-HASH-VERIFIED
|
||||
DISPLAY "HASH: VERIFIED"
|
||||
ELSE
|
||||
DISPLAY "HASH: MISMATCH!"
|
||||
END-IF
|
||||
DISPLAY " "
|
||||
|
||||
*> Per-file inventory summary
|
||||
DISPLAY "-- Split File Inventory --"
|
||||
PERFORM VARYING WS-INV-SUM-COUNT FROM 1 BY 1
|
||||
UNTIL WS-INV-SUM-COUNT > WS-INVENTORY-ENTRIES
|
||||
MOVE WS-INV-REC-COUNT(WS-INV-SUM-COUNT)
|
||||
TO WS-DISP-INV-RECS
|
||||
MOVE WS-INV-HASH-TOTAL(WS-INV-SUM-COUNT)
|
||||
TO WS-DISP-INV-HASH
|
||||
DISPLAY " F" WS-INV-FILE-NUM(WS-INV-SUM-COUNT)
|
||||
" recs=" WS-DISP-INV-RECS
|
||||
" hash=" WS-DISP-INV-HASH
|
||||
END-PERFORM
|
||||
.
|
||||
*
|
||||
5000-AUDIT-SECTION.
|
||||
*
|
||||
5000-AUDIT-PROC.
|
||||
MOVE "AUDIT-END" TO WS-AUDIT-TYPE
|
||||
STRING "Records=" WS-DISPLAY-COUNT
|
||||
" Files=" WS-FILE-NUM
|
||||
INTO WS-AUDIT-DATA
|
||||
END-STRING
|
||||
MOVE WS-AUDIT-LINE TO FILE-AUDIT-REC
|
||||
WRITE FILE-AUDIT-REC
|
||||
|
||||
IF WS-HASH-MATCH
|
||||
MOVE "HASH-VERIFIED" TO WS-AUDIT-TYPE
|
||||
ELSE
|
||||
MOVE "HASH-MISMATCH" TO WS-AUDIT-TYPE
|
||||
END-IF
|
||||
STRING "IN=" WS-DISP-HASH-IN " OUT=" WS-DISP-HASH-OUT
|
||||
INTO WS-AUDIT-DATA
|
||||
END-STRING
|
||||
MOVE WS-AUDIT-LINE TO FILE-AUDIT-REC
|
||||
WRITE FILE-AUDIT-REC
|
||||
|
||||
EVALUATE TRUE
|
||||
WHEN WS-BOUNDARY-EMPTY
|
||||
MOVE "BOUNDARY-EMPTY" TO WS-AUDIT-TYPE
|
||||
WHEN WS-BOUNDARY-SINGLE
|
||||
MOVE "BOUNDARY-SINGLE" TO WS-AUDIT-TYPE
|
||||
WHEN WS-BOUNDARY-EXACT
|
||||
MOVE "BOUNDARY-EXACT" TO WS-AUDIT-TYPE
|
||||
WHEN WS-BOUNDARY-TRAILING
|
||||
MOVE "BOUNDARY-TRAILING" TO WS-AUDIT-TYPE
|
||||
WHEN OTHER
|
||||
MOVE "BOUNDARY-NORMAL" TO WS-AUDIT-TYPE
|
||||
END-EVALUATE
|
||||
STRING "Records=" WS-DISPLAY-COUNT
|
||||
" Divisor=" WS-DIVISOR
|
||||
INTO WS-AUDIT-DATA
|
||||
END-STRING
|
||||
MOVE WS-AUDIT-LINE TO FILE-AUDIT-REC
|
||||
WRITE FILE-AUDIT-REC
|
||||
|
||||
PERFORM VARYING WS-INV-SUM-COUNT FROM 1 BY 1
|
||||
UNTIL WS-INV-SUM-COUNT > WS-INVENTORY-ENTRIES
|
||||
MOVE WS-INV-FILE-NUM(WS-INV-SUM-COUNT)
|
||||
TO WS-FILE-NUM-ED
|
||||
MOVE WS-INV-REC-COUNT(WS-INV-SUM-COUNT)
|
||||
TO WS-DISP-INV-RECS
|
||||
MOVE WS-INV-HASH-TOTAL(WS-INV-SUM-COUNT)
|
||||
TO WS-DISP-INV-HASH
|
||||
STRING "FILE=FILE-OUT-" WS-FILE-NUM-ED
|
||||
".DAT RECS=" WS-DISP-INV-RECS
|
||||
" HASH=" WS-DISP-INV-HASH
|
||||
INTO WS-AUDIT-DATA
|
||||
END-STRING
|
||||
MOVE "SPLIT-FILE" TO WS-AUDIT-TYPE
|
||||
MOVE WS-AUDIT-LINE TO FILE-AUDIT-REC
|
||||
WRITE FILE-AUDIT-REC
|
||||
END-PERFORM
|
||||
|
||||
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
||||
DISPLAY "[" WS-TIMESTAMP "] AUDIT: written"
|
||||
.
|
||||
*
|
||||
6000-ERROR-HANDLE-SECTION.
|
||||
*
|
||||
6000-ERROR-PROC.
|
||||
IF WS-SEVERITY = SPACES
|
||||
MOVE 'ERROR' TO WS-SEVERITY
|
||||
END-IF
|
||||
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
||||
DISPLAY "[" WS-TIMESTAMP "] " WS-SEVERITY
|
||||
|
||||
IF WS-SEVERITY-FATAL
|
||||
DISPLAY "FATAL: Terminating at record " WS-REC-COUNT
|
||||
MOVE "FATAL-ERROR" TO WS-AUDIT-TYPE
|
||||
STRING "Fatal at record=" WS-REC-COUNT
|
||||
INTO WS-AUDIT-DATA
|
||||
END-STRING
|
||||
MOVE WS-AUDIT-LINE TO FILE-AUDIT-REC
|
||||
WRITE FILE-AUDIT-REC
|
||||
PERFORM 9000-EXIT-SECTION
|
||||
STOP RUN
|
||||
END-IF
|
||||
.
|
||||
*
|
||||
9000-EXIT-SECTION.
|
||||
*
|
||||
9000-EXIT-PROC.
|
||||
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
||||
CLOSE FILE-IN
|
||||
IF WS-FILE-IN-STATUS NOT = "00"
|
||||
DISPLAY "WARNING: FILE-IN close status="
|
||||
WS-FILE-IN-STATUS
|
||||
END-IF
|
||||
CLOSE FILE-AUDIT
|
||||
IF WS-FILE-AUDIT-STATUS NOT = "00"
|
||||
AND WS-FILE-AUDIT-STATUS NOT = "42"
|
||||
DISPLAY "WARNING: AUDIT close status="
|
||||
WS-FILE-AUDIT-STATUS
|
||||
END-IF
|
||||
DISPLAY "[" WS-TIMESTAMP "] Divide50 session ended"
|
||||
EXIT PROGRAM.
|
||||
.
|
||||
Reference in New Issue
Block a user