feat: add benchmark-programs — 58 telecom COBOL test programs
作为子目录纳入系统,与核心测试管道协同 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# 11-divide-25 — 25-Division File Splitter
|
||||
|
||||
## 电信业务场景
|
||||
|
||||
明细25分割。将请求书明细行按25件一个文件进行分割。
|
||||
|
||||
Demonstrates dividing input records into groups of 25:
|
||||
|
||||
- **PERFORM VARYING counter**: Track record numbers across the loop
|
||||
- **DIVIDE ... GIVING REMAINDER**: Calculate file number from record count
|
||||
- **Close-write cycle**: Close old file, open new file at each boundary
|
||||
- Tested at boundary conditions: 25 (exact), 26 (one extra), 24 (one short)
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `main-11-divide-25.cbl` | COBOL program (fixed format) |
|
||||
| `data-gen.sh` | Generate N test records (default 26) |
|
||||
| `run.sh` | Compile + run 3 test cases |
|
||||
|
||||
## Algorithm
|
||||
|
||||
```
|
||||
DIVIDE record-count BY 25 GIVING Q REMAINDER R
|
||||
IF R = 1 → open new FILE-OUT-NN
|
||||
Write record to current file
|
||||
```
|
||||
|
||||
## Output Files
|
||||
|
||||
- FILE-OUT-01.DAT: records 1-25
|
||||
- FILE-OUT-02.DAT: records 26-50
|
||||
- etc.
|
||||
@@ -0,0 +1,642 @@
|
||||
*> 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.
|
||||
@@ -0,0 +1,91 @@
|
||||
*> ============================================================
|
||||
*> main-divide-25 : 明细25分割 (Detail 25-Split)
|
||||
*> Input : FILE-IN (INPUT.DAT: 明细记录)
|
||||
*> Output: FILE-OUT (SPLIT-OUT: 25件毎分割)
|
||||
*> Coverage: S-N004, S-N006, S-N007, S-R001, S-R002
|
||||
*> ============================================================
|
||||
IDENTIFICATION DIVISION.
|
||||
PROGRAM-ID. DIVIDE-25.
|
||||
|
||||
ENVIRONMENT DIVISION.
|
||||
INPUT-OUTPUT SECTION.
|
||||
FILE-CONTROL.
|
||||
SELECT FILE-IN ASSIGN TO "INPUT.DAT"
|
||||
ORGANIZATION IS SEQUENTIAL
|
||||
FILE STATUS IS WS-FS.
|
||||
|
||||
SELECT FILE-OUT ASSIGN TO "SPLIT-OUT"
|
||||
ORGANIZATION IS SEQUENTIAL.
|
||||
|
||||
DATA DIVISION.
|
||||
FILE SECTION.
|
||||
FD FILE-IN RECORD CONTAINS 40 CHARACTERS.
|
||||
01 IN-REC.
|
||||
05 IN-KEY PIC X(10).
|
||||
05 IN-DATA PIC X(20).
|
||||
05 IN-AMT PIC 9(10).
|
||||
|
||||
FD FILE-OUT RECORD CONTAINS 40 CHARACTERS.
|
||||
01 OUT-REC PIC X(40).
|
||||
|
||||
WORKING-STORAGE SECTION.
|
||||
01 WS-FS PIC X(2).
|
||||
01 WS-EOF PIC X(1) VALUE 'N'.
|
||||
88 WS-EOF-Y VALUE 'Y' FALSE 'N'.
|
||||
01 WS-COUNT PIC 9(10).
|
||||
01 WS-FILE-NUM PIC 9(2).
|
||||
01 WS-FILE-NAME PIC X(20).
|
||||
01 WS-TOTAL-IN PIC 9(10).
|
||||
01 WS-TOTAL-OUT PIC 9(10).
|
||||
01 WS-SPLIT-LIMIT PIC 9(5) VALUE 25.
|
||||
01 WS-INVOICE-REC.
|
||||
COPY "telecom/TEL-INVOICE.cpy".
|
||||
|
||||
PROCEDURE DIVISION.
|
||||
MAIN.
|
||||
DISPLAY "DIVIDE-25: Starting 25-split"
|
||||
OPEN INPUT FILE-IN.
|
||||
MOVE 1 TO WS-FILE-NUM.
|
||||
MOVE 0 TO WS-COUNT.
|
||||
MOVE 0 TO WS-TOTAL-IN.
|
||||
PERFORM OPEN-NEXT-FILE.
|
||||
|
||||
PERFORM UNTIL WS-EOF-Y
|
||||
READ FILE-IN INTO IN-REC
|
||||
AT END SET WS-EOF-Y TO TRUE
|
||||
NOT AT END
|
||||
ADD 1 TO WS-TOTAL-IN WS-COUNT
|
||||
MOVE IN-REC TO OUT-REC
|
||||
WRITE OUT-REC
|
||||
ADD 1 TO WS-TOTAL-OUT
|
||||
IF WS-COUNT >= WS-SPLIT-LIMIT
|
||||
CLOSE FILE-OUT
|
||||
ADD 1 TO WS-FILE-NUM
|
||||
MOVE 0 TO WS-COUNT
|
||||
PERFORM OPEN-NEXT-FILE
|
||||
END-IF
|
||||
END-READ
|
||||
END-PERFORM.
|
||||
|
||||
CLOSE FILE-IN FILE-OUT.
|
||||
DISPLAY "DIVIDE-25: IN=" WS-TOTAL-IN
|
||||
" OUT=" WS-TOTAL-OUT " FILES=" WS-FILE-NUM
|
||||
IF WS-TOTAL-IN = WS-TOTAL-OUT
|
||||
DISPLAY "DIVIDE-25: PASS"
|
||||
STOP RUN RETURNING 0
|
||||
ELSE
|
||||
DISPLAY "DIVIDE-25: FAIL"
|
||||
STOP RUN RETURNING 1
|
||||
END-IF
|
||||
.
|
||||
|
||||
OPEN-NEXT-FILE.
|
||||
STRING "SPLIT25-" WS-FILE-NUM ".DAT"
|
||||
DELIMITED BY SIZE INTO WS-FILE-NAME
|
||||
END-STRING
|
||||
CLOSE FILE-OUT
|
||||
OPEN OUTPUT FILE-OUT
|
||||
DISPLAY "OPEN: " WS-FILE-NAME
|
||||
.
|
||||
|
||||
END PROGRAM DIVIDE-25.
|
||||
Reference in New Issue
Block a user