feat: add benchmark-programs — 58 telecom COBOL test programs

作为子目录纳入系统,与核心测试管道协同

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
NB-076
2026-06-25 09:53:21 +08:00
parent 50f9f0f52f
commit 94400d50d4
278 changed files with 44125 additions and 0 deletions
@@ -0,0 +1 @@
00000
@@ -0,0 +1,53 @@
# 04-edit-getput: Edit/GetPut Pass-Through
## 电信业务场景
请求书编辑输出。从客户/用量汇总文件读取记录,直接转记到输出文件。用于请求书的最终格式化输出。
## Description
A minimal COBOL edit/getput program that reads records from FILE-IN and
writes them unchanged to FILE-OUT. No matching, no branching logic.
## Record Layout
| Field | Type | Length | Description |
|----------|----------|--------|--------------------|
| FIELD1 | PIC X | 10 | Record code |
| FIELD2 | PIC X | 20 | Description text |
| FIELD3 | PIC 9 | 05 | Numeric amount |
Total record length: 35 bytes.
## Files
| File | Purpose |
|------------------|-----------------------------------|
| main-04-edit-getput.cbl | Main COBOL program (fixed format) |
| data-gen.sh | Generate sequential test data |
| run.sh | Compile, run, verify |
| README.md | This file |
## Tests
| Test Case | Description |
|-------------------|------------------------------------------|
| 1 record (min) | Verify program handles 1 record input |
| 5 records (std) | Verify standard multi-record processing |
| Output existence | Confirm FILE-OUT is created |
| Size match | Input and output file sizes identical |
| Record length | Each record is exactly 35 bytes |
## Usage
```bash
cd 04-edit-getput
bash data-gen.sh 1 # Generate 1 record (minimal test)
bash run.sh # Full test with 5 records
```
## Expected Behavior
- All input records are written to output unchanged.
- File status is checked after OPEN, error messages on failure.
- Record count is displayed at end of processing.
@@ -0,0 +1,805 @@
*> ============================================================
*> 04-edit-getput : 请求书编辑输出 (Invoice GETPUT)
*> Input : file-in.dat (客户/用量记录)
*> Output: file-out.dat (格式化的请求书输出)
*> file-out-detail.dat (详细格式)
*> file-out-summary.dat (汇总格式)
*> audit-trail.dat (审计日志)
*> Coverage: COM-N001~N006
*> field editing, audit trail, hash totals
*> ============================================================
IDENTIFICATION DIVISION.
PROGRAM-ID. EditGetPut.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT FILE-IN ASSIGN TO 'file-in.dat'
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL
FILE STATUS IS WS-FILE-IN-STATUS.
SELECT FILE-OUT ASSIGN TO 'file-out.dat'
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-FILE-OUT-STATUS.
*> Additional output files for telecom billing
SELECT FILE-OUT-DTL ASSIGN TO 'file-out-detail.dat'
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-FILE-DTL-STATUS.
SELECT FILE-OUT-SUM ASSIGN TO 'file-out-summary.dat'
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-FILE-SUM-STATUS.
SELECT FILE-OUT-AUDIT ASSIGN TO 'audit-trail.dat'
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-FILE-AUD-STATUS.
*>
DATA DIVISION.
FILE SECTION.
FD FILE-IN.
01 IN-REC.
05 IN-FIELD1 PIC X(10).
05 IN-FIELD2 PIC X(20).
05 IN-FIELD3 PIC 9(05).
*>
FD FILE-OUT.
01 OUT-REC.
05 OUT-FIELD1 PIC X(10).
05 OUT-FIELD2 PIC X(20).
05 OUT-FIELD3 PIC 9(05).
*>
FD FILE-OUT-DTL.
01 OUT-DTL-REC PIC X(120).
*>
FD FILE-OUT-SUM.
01 OUT-SUM-REC PIC X(120).
*>
FD FILE-OUT-AUDIT.
01 OUT-AUDIT-REC PIC X(120).
*>
WORKING-STORAGE SECTION.
*> === PRESERVED ORIGINAL ITEMS ===
01 WS-TELECOM-REC.
COPY "telecom/TEL-INVOICE.cpy".
01 WS-FILE-IN-STATUS PIC X(02).
01 WS-FILE-OUT-STATUS PIC X(02).
01 WS-EOF PIC X(01) VALUE 'N'.
88 WS-EOF-YES VALUE 'Y' FALSE 'N'.
01 WS-REC-COUNT PIC 9(05) VALUE ZERO.
01 WS-INVOICE-REC.
COPY "telecom/TEL-INVOICE.cpy".
*> === NEW ITEMS ===
*> Timestamp for tracing
01 WS-TIMESTAMP.
05 WS-TS-YEAR PIC 9(04).
05 WS-TS-MONTH PIC 9(02).
05 WS-TS-DAY PIC 9(02).
05 WS-TS-HOUR PIC 9(02).
05 WS-TS-MINUTE PIC 9(02).
05 WS-TS-SECOND PIC 9(02).
05 WS-TS-MS PIC 9(02).
01 WS-TIMESTAMP-STR PIC X(26).
01 WS-TRACE-MSG PIC X(80).
*> Format control
01 WS-FORMAT-MODE PIC X(01) VALUE 'D'.
88 WS-FORMAT-SHORT VALUE 'S'.
88 WS-FORMAT-DETAIL VALUE 'D'.
88 WS-FORMAT-SUMMARY VALUE 'M'.
01 WS-CONDENSED-MODE PIC X(01) VALUE 'N'.
88 WS-CONDENSED-YES VALUE 'Y' FALSE 'N'.
01 WS-FMT-CONFIG PIC X(02) VALUE 'BH'.
88 WS-FMT-HEADER-ONLY VALUE 'H '.
88 WS-FMT-FOOTER-ONLY VALUE 'F '.
88 WS-FMT-BOTH VALUE 'BH'.
*> Page control
01 WS-PAGE-COUNT PIC 9(05) VALUE ZERO.
01 WS-LINE-COUNT PIC 9(03) VALUE ZERO.
01 WS-LINES-PER-PAGE PIC 9(03) VALUE 50.
01 WS-PAGE-MAX PIC 9(03) VALUE 55.
01 WS-PAGE-BREAK-NEEDED PIC X(01) VALUE 'N'.
88 WS-PAGE-BREAK VALUE 'Y' FALSE 'N'.
*> Heading lines
01 WS-HDG-1 PIC X(120).
01 WS-HDG-2 PIC X(120).
01 WS-HDG-3 PIC X(120).
01 WS-HDG-4 PIC X(120).
01 WS-HDG-5 PIC X(120).
*> Footing lines
01 WS-FTG-1 PIC X(120).
01 WS-FTG-2 PIC X(120).
*> Separator lines
01 WS-SEP-STARS PIC X(120) VALUE ALL '*'.
01 WS-SEP-DASHES PIC X(120) VALUE ALL '-'.
01 WS-SEP-EQUALS PIC X(120) VALUE ALL '='.
*> Detail and summary lines
01 WS-DETAIL-LINE PIC X(120).
01 WS-SUMMARY-LINE PIC X(120).
*> Telecom billing fields
01 WS-BILL-DATA.
05 WS-BD-CUST-ID PIC X(10).
05 WS-BD-CUST-NAME PIC X(30).
05 WS-BD-PLAN-CODE PIC X(02).
05 WS-BD-USAGE PIC 9(09).
05 WS-BD-BASE-FEE PIC 9(07).
05 WS-BD-USAGE-FEE PIC 9(07).
05 WS-BD-TAX PIC 9(07).
05 WS-BD-TOTAL PIC 9(09).
05 WS-BD-STATUS-DESC PIC X(15).
*> Edited numeric fields — various PIC patterns
01 WS-ED-AMOUNT PIC Z(9)9.
01 WS-ED-TOTAL PIC Z(11)9.
01 WS-ED-COUNT PIC Z(9)9.
01 WS-ED-PAGE PIC Z(9)9.
01 WS-ED-USAGE PIC Z(9)9.
01 WS-ED-FEE PIC Z(9)9.
01 WS-ED-TAX PIC Z(9)9.
*> Additional editing patterns per requirement
01 WS-ED-CHECK-PROT PIC *(8)9.
01 WS-ED-SIGNED PIC +Z(8)9.
01 WS-ED-CURRENCY PIC $$$$$$$$9.99.
01 WS-ED-BLANK-ZERO PIC Z(9)9 BLANK WHEN ZERO.
01 WS-ED-FLOAT-DOLLAR PIC $$$$,$$$,$$9.
*> Hash totals
01 WS-HASH-REC-COUNT PIC 9(09) VALUE ZERO.
01 WS-HASH-AMT PIC 9(15) VALUE ZERO.
01 WS-HASH-CHECKSUM PIC 9(15) VALUE ZERO.
01 WS-HASH-AMT-REM PIC 9(15).
*> Accumulators by invoice status
01 WS-ACC-STATUS-0 PIC 9(12) VALUE ZERO.
01 WS-ACC-STATUS-1 PIC 9(12) VALUE ZERO.
01 WS-ACC-STATUS-2 PIC 9(12) VALUE ZERO.
*> Error handling
01 WS-ERR-SEVERITY PIC 9(01).
88 WS-ERR-INFO VALUE 0.
88 WS-ERR-WARN VALUE 1.
88 WS-ERR-ERROR VALUE 2.
88 WS-ERR-FATAL VALUE 3.
01 WS-ERR-MSG PIC X(60).
01 WS-ERR-COUNT PIC 9(04) VALUE ZERO.
01 WS-WARN-COUNT PIC 9(04) VALUE ZERO.
*> Additional file statuses
01 WS-FILE-DTL-STATUS PIC X(02).
01 WS-FILE-SUM-STATUS PIC X(02).
01 WS-FILE-AUD-STATUS PIC X(02).
*> Audit fields
01 WS-AUDIT-ENTRIES PIC 9(04) VALUE ZERO.
01 WS-AUDIT-LINE PIC X(120).
*> Report date/time
01 WS-RPT-DATE PIC X(10).
01 WS-RPT-TIME PIC X(08).
*> Second-pass record counter
01 WS-PASS2-COUNT PIC 9(05) VALUE ZERO.
*> Configuration constants
01 WS-CONFIG-LPP PIC 9(03) VALUE 50.
01 WS-CONFIG-MAXERR PIC 9(04) VALUE 100.
*> Plan description table
01 WS-PLAN-TABLE.
05 FILLER PIC X(12) VALUE '01BASIC '.
05 FILLER PIC X(12) VALUE '02PREMIUM '.
05 FILLER PIC X(12) VALUE '03BUSINESS '.
05 FILLER PIC X(12) VALUE '04ENTERPRISE'.
05 FILLER PIC X(12) VALUE '99UNKNOWN '.
01 WS-PLAN-TAB-R REDEFINES WS-PLAN-TABLE.
05 WS-PLAN-ENT OCCURS 5 TIMES.
10 WS-PLAN-CODE PIC X(02).
10 WS-PLAN-DESC PIC X(10).
01 WS-PLAN-IDX PIC 9(01).
01 WS-PLAN-FOUND PIC X(01).
*> Record buffer for second pass
01 WS-BUFFER-IN.
05 WS-BUF-ID PIC X(10).
05 WS-BUF-CUST PIC X(10).
05 WS-BUF-DATA PIC X(10).
05 WS-BUF-AMOUNT PIC 9(05).
*> ============================================================
PROCEDURE DIVISION.
*>
MAIN SECTION.
MB-PROCESS.
*>
PERFORM 1000-INIT
PERFORM 3000-PROCESS
PERFORM 4000-REPORT
PERFORM 5000-AUDIT
PERFORM 6000-ERROR-HANDLE
PERFORM 9000-EXIT
STOP RUN.
*>
1000-INIT SECTION.
*>
DISPLAY 'EditGetPut: Initializing program...'.
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP.
STRING WS-TS-YEAR '-' WS-TS-MONTH '-'
WS-TS-DAY ' ' WS-TS-HOUR ':'
WS-TS-MINUTE ':' WS-TS-SECOND
INTO WS-TIMESTAMP-STR.
DISPLAY 'EditGetPut: Start time=' WS-TIMESTAMP-STR.
*>
MOVE WS-TS-YEAR TO WS-RPT-DATE(1:4).
MOVE '-' TO WS-RPT-DATE(5:1).
MOVE WS-TS-MONTH TO WS-RPT-DATE(6:2).
MOVE '-' TO WS-RPT-DATE(8:1).
MOVE WS-TS-DAY TO WS-RPT-DATE(9:2).
STRING WS-TS-HOUR ':' WS-TS-MINUTE ':'
WS-TS-SECOND INTO WS-RPT-TIME.
*>
MOVE SPACES TO WS-HDG-1 WS-HDG-2 WS-HDG-3
WS-HDG-4 WS-HDG-5.
MOVE SPACES TO WS-FTG-1 WS-FTG-2.
*>
MOVE ZERO TO WS-PAGE-COUNT WS-LINE-COUNT
WS-HASH-REC-COUNT WS-HASH-AMT
WS-HASH-CHECKSUM WS-ERR-COUNT
WS-WARN-COUNT WS-PASS2-COUNT
WS-ACC-STATUS-0 WS-ACC-STATUS-1
WS-ACC-STATUS-2 WS-AUDIT-ENTRIES.
*>
DISPLAY 'EditGetPut: INIT complete. Format=' WS-FORMAT-MODE
' LPP=' WS-CONFIG-LPP
' MaxErr=' WS-CONFIG-MAXERR.
*>
2000-OPEN-FILES SECTION.
*>
DISPLAY 'EditGetPut: Opening files...'.
*>
*> === PRESERVED ORIGINAL OPEN + STATUS CHECK ===
OPEN INPUT FILE-IN.
IF WS-FILE-IN-STATUS NOT = '00'
DISPLAY 'ERROR: Cannot open FILE-IN, status: '
WS-FILE-IN-STATUS
MOVE 1 TO RETURN-CODE
STOP RUN
END-IF.
*>
OPEN OUTPUT FILE-OUT.
IF WS-FILE-OUT-STATUS NOT = '00'
DISPLAY 'ERROR: Cannot open FILE-OUT, status: '
WS-FILE-OUT-STATUS
MOVE 1 TO RETURN-CODE
STOP RUN
END-IF.
*> === END PRESERVED ORIGINAL OPEN ===
*>
*> Additional output files
OPEN OUTPUT FILE-OUT-DTL.
IF WS-FILE-DTL-STATUS NOT = '00'
MOVE 1 TO WS-ERR-SEVERITY
STRING 'WARN: FILE-OUT-DTL open status='
WS-FILE-DTL-STATUS INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-WARN-COUNT
END-IF.
*>
OPEN OUTPUT FILE-OUT-SUM.
IF WS-FILE-SUM-STATUS NOT = '00'
MOVE 1 TO WS-ERR-SEVERITY
STRING 'WARN: FILE-OUT-SUM open status='
WS-FILE-SUM-STATUS INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-WARN-COUNT
END-IF.
*>
OPEN EXTEND FILE-OUT-AUDIT.
IF WS-FILE-AUD-STATUS NOT = '00'
OPEN OUTPUT FILE-OUT-AUDIT
IF WS-FILE-AUD-STATUS NOT = '00'
MOVE 1 TO WS-ERR-SEVERITY
STRING 'WARN: FILE-OUT-AUDIT open status='
WS-FILE-AUD-STATUS INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-WARN-COUNT
END-IF
END-IF.
*>
DISPLAY 'EditGetPut: Files opened.'
' IN=' WS-FILE-IN-STATUS
' OUT=' WS-FILE-OUT-STATUS
' DTL=' WS-FILE-DTL-STATUS.
*>
3000-PROCESS SECTION.
*>
DISPLAY 'EditGetPut: PASS-1 — Original copy loop...'.
*>
*> ============================================================
*> === PRESERVED ORIGINAL PROCESSING LOOP (exact) ===
*> ============================================================
PERFORM UNTIL WS-EOF-YES
READ FILE-IN
AT END
SET WS-EOF-YES TO TRUE
NOT AT END
MOVE IN-REC TO OUT-REC
WRITE OUT-REC
ADD 1 TO WS-REC-COUNT
END-READ
END-PERFORM.
*> === END PRESERVED ORIGINAL LOOP ===
*>
DISPLAY 'EditGetPut: PASS-1 complete.'
' Records copied=' WS-REC-COUNT.
*>
*> Reopen FILE-IN for PASS-2 detailed processing.
*> Close FILE-IN first (original close moved to 9000-EXIT).
CLOSE FILE-IN.
IF WS-FILE-IN-STATUS NOT = '00'
MOVE 3 TO WS-ERR-SEVERITY
STRING 'ERROR: Close FILE-IN status='
WS-FILE-IN-STATUS INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
PERFORM 6000-ERROR-HANDLE
END-IF.
*>
MOVE 'N' TO WS-EOF.
OPEN INPUT FILE-IN.
IF WS-FILE-IN-STATUS NOT = '00'
MOVE 3 TO WS-ERR-SEVERITY
STRING 'ERROR: Reopen FILE-IN status='
WS-FILE-IN-STATUS INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
PERFORM 6000-ERROR-HANDLE
END-IF.
*>
DISPLAY 'EditGetPut: PASS-2 — Telecom billing detail...'.
*>
PERFORM UNTIL WS-EOF-YES
READ FILE-IN
AT END
SET WS-EOF-YES TO TRUE
NOT AT END
ADD 1 TO WS-PASS2-COUNT
PERFORM 3100-VALIDATE
PERFORM 3200-CALCULATE
PERFORM 3300-FORMAT-OUTPUT
PERFORM 3400-WRITE-OUTPUT
END-READ
END-PERFORM.
*>
CLOSE FILE-IN.
IF WS-FILE-IN-STATUS NOT = '00'
MOVE 2 TO WS-ERR-SEVERITY
STRING 'WARN: Close FILE-IN after PASS-2 status='
WS-FILE-IN-STATUS INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-WARN-COUNT
END-IF.
*>
DISPLAY 'EditGetPut: PASS-2 complete.'
' Detail processed=' WS-PASS2-COUNT.
*>
3100-VALIDATE SECTION.
*>
*> Map 35-byte input fields to telecom invoice structure
MOVE IN-FIELD1 TO INV-ID OF WS-INVOICE-REC.
MOVE IN-FIELD2(1:10) TO INV-CUST-ID OF WS-INVOICE-REC.
MOVE IN-FIELD3 TO INV-AMOUNT OF WS-INVOICE-REC.
MOVE '1' TO INV-STATUS OF WS-INVOICE-REC.
*>
*> Validate invoice ID
IF INV-ID OF WS-INVOICE-REC = SPACES
MOVE 1 TO WS-ERR-SEVERITY
STRING 'WARN: Empty invoice ID at PASS-2 record '
WS-PASS2-COUNT INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-ERR-COUNT
END-IF.
IF INV-ID OF WS-INVOICE-REC = LOW-VALUES
MOVE 1 TO WS-ERR-SEVERITY
STRING 'WARN: Low-values invoice ID at record '
WS-PASS2-COUNT INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-ERR-COUNT
END-IF.
*>
*> Validate customer ID
IF INV-CUST-ID OF WS-INVOICE-REC = SPACES
MOVE 1 TO WS-ERR-SEVERITY
STRING 'WARN: Empty cust ID for '
INV-ID OF WS-INVOICE-REC INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-WARN-COUNT
END-IF.
*>
*> Validate invoice amount
IF INV-AMOUNT OF WS-INVOICE-REC = ZERO
MOVE 1 TO WS-ERR-SEVERITY
STRING 'INFO: Zero amount invoice '
INV-ID OF WS-INVOICE-REC INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-ERR-COUNT
END-IF.
IF INV-AMOUNT OF WS-INVOICE-REC > 999999999
MOVE 2 TO WS-ERR-SEVERITY
STRING 'WARN: Overlimit amount '
INV-ID OF WS-INVOICE-REC INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-WARN-COUNT
END-IF.
*>
*> Validate reserved field content
IF INV-RESERVED OF WS-INVOICE-REC NOT = SPACES
MOVE 1 TO WS-ERR-SEVERITY
STRING 'INFO: Non-blank reserved at '
INV-ID OF WS-INVOICE-REC INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
END-IF.
*>
3200-CALCULATE SECTION.
*>
*> Accumulate hash totals
ADD 1 TO WS-HASH-REC-COUNT.
ADD INV-AMOUNT OF WS-INVOICE-REC TO WS-HASH-AMT.
COMPUTE WS-HASH-CHECKSUM =
WS-HASH-CHECKSUM + INV-AMOUNT OF WS-INVOICE-REC.
DIVIDE WS-HASH-CHECKSUM BY 1000000
GIVING WS-HASH-AMT-REM.
*>
*> Accumulate by invoice status
EVALUATE INV-STATUS OF WS-INVOICE-REC
WHEN '0'
ADD INV-AMOUNT OF WS-INVOICE-REC
TO WS-ACC-STATUS-0
WHEN '1'
ADD INV-AMOUNT OF WS-INVOICE-REC
TO WS-ACC-STATUS-1
WHEN '2'
ADD INV-AMOUNT OF WS-INVOICE-REC
TO WS-ACC-STATUS-2
WHEN OTHER
CONTINUE
END-EVALUATE.
*>
*> Telecom billing fee calculation
DIVIDE INV-AMOUNT OF WS-INVOICE-REC BY 100
GIVING WS-BD-TOTAL.
COMPUTE WS-BD-BASE-FEE = WS-BD-TOTAL * 60 / 100.
COMPUTE WS-BD-USAGE-FEE = WS-BD-TOTAL - WS-BD-BASE-FEE.
COMPUTE WS-BD-TAX = WS-BD-TOTAL * 10 / 100.
COMPUTE WS-BD-USAGE = WS-BD-TOTAL * 2.
*>
*> Look up plan code from invoice ID prefix
MOVE 'N' TO WS-PLAN-FOUND.
MOVE 1 TO WS-PLAN-IDX.
PERFORM VARYING WS-PLAN-IDX FROM 1 BY 1
UNTIL WS-PLAN-IDX > 5 OR WS-PLAN-FOUND = 'Y'
IF WS-PLAN-CODE(WS-PLAN-IDX)
= INV-ID OF WS-INVOICE-REC(1:2)
MOVE WS-PLAN-DESC(WS-PLAN-IDX)
TO WS-BD-PLAN-CODE
MOVE 'Y' TO WS-PLAN-FOUND
END-IF
END-PERFORM.
IF WS-PLAN-FOUND NOT = 'Y'
MOVE '99' TO WS-BD-PLAN-CODE
END-IF.
*>
*> Set status description
EVALUATE INV-STATUS OF WS-INVOICE-REC
WHEN '0' MOVE 'UNISSUED ' TO WS-BD-STATUS-DESC
WHEN '1' MOVE 'ISSUED ' TO WS-BD-STATUS-DESC
WHEN '2' MOVE 'PAID ' TO WS-BD-STATUS-DESC
WHEN OTHER MOVE 'UNKNOWN ' TO WS-BD-STATUS-DESC
END-EVALUATE.
*>
3300-FORMAT-OUTPUT SECTION.
*>
*> Edit numeric fields with various PIC patterns
MOVE INV-AMOUNT OF WS-INVOICE-REC TO WS-ED-AMOUNT.
MOVE WS-HASH-AMT TO WS-ED-TOTAL.
MOVE WS-HASH-REC-COUNT TO WS-ED-COUNT.
MOVE WS-BD-USAGE TO WS-ED-USAGE.
MOVE WS-BD-BASE-FEE TO WS-ED-FEE.
MOVE WS-BD-TAX TO WS-ED-TAX.
*> Additional editing patterns
MOVE INV-AMOUNT OF WS-INVOICE-REC TO WS-ED-CHECK-PROT.
MOVE INV-AMOUNT OF WS-INVOICE-REC TO WS-ED-SIGNED.
MOVE INV-AMOUNT OF WS-INVOICE-REC TO WS-ED-CURRENCY.
MOVE INV-AMOUNT OF WS-INVOICE-REC TO WS-ED-BLANK-ZERO.
MOVE INV-AMOUNT OF WS-INVOICE-REC TO WS-ED-FLOAT-DOLLAR.
*>
*> Build detail line (DETAIL format)
IF WS-FORMAT-DETAIL
STRING INV-ID OF WS-INVOICE-REC ' '
INV-CUST-ID OF WS-INVOICE-REC ' '
INV-MONTH OF WS-INVOICE-REC ' '
WS-ED-AMOUNT ' '
INV-STATUS OF WS-INVOICE-REC ' '
WS-BD-STATUS-DESC
DELIMITED BY SIZE INTO WS-DETAIL-LINE
PERFORM 3500-WRITE-DETAIL
END-IF.
*>
*> Build condensed line (SHORT or CONDENSED)
IF WS-FORMAT-SHORT
STRING INV-ID OF WS-INVOICE-REC ' '
WS-ED-AMOUNT ' '
INV-STATUS OF WS-INVOICE-REC
DELIMITED BY SIZE INTO WS-DETAIL-LINE
PERFORM 3500-WRITE-DETAIL
END-IF.
IF WS-CONDENSED-YES
STRING INV-ID OF WS-INVOICE-REC ' '
WS-ED-CHECK-PROT ' '
INV-STATUS OF WS-INVOICE-REC
DELIMITED BY SIZE INTO WS-DETAIL-LINE
PERFORM 3500-WRITE-DETAIL
END-IF.
*>
*> Accumulate for summary (SUMMARY mode)
IF WS-FORMAT-SUMMARY
CONTINUE
END-IF.
*>
*> Trace formatted output with timestamp
STRING WS-TS-HOUR ':' WS-TS-MINUTE ':'
WS-TS-SECOND ' FMT '
INV-ID OF WS-INVOICE-REC
INTO WS-TRACE-MSG.
DISPLAY WS-TRACE-MSG.
*>
3400-WRITE-OUTPUT SECTION.
*>
*> Write to primary output file if detail mode
IF WS-FORMAT-DETAIL
MOVE IN-REC TO OUT-REC
WRITE OUT-REC
IF WS-FILE-OUT-STATUS NOT = '00'
MOVE 2 TO WS-ERR-SEVERITY
STRING 'ERROR: OUT write failed status='
WS-FILE-OUT-STATUS INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-ERR-COUNT
END-IF
END-IF.
*>
3500-WRITE-DETAIL SECTION.
*>
*> Page break control: check line count
ADD 1 TO WS-LINE-COUNT.
IF WS-LINE-COUNT > WS-LINES-PER-PAGE
PERFORM 4100-PAGE-HEADING
MOVE 1 TO WS-LINE-COUNT
END-IF.
*>
*> Write detail record with status check
WRITE OUT-DTL-REC FROM WS-DETAIL-LINE.
IF WS-FILE-DTL-STATUS NOT = '00'
MOVE 2 TO WS-ERR-SEVERITY
STRING 'ERROR: DTL write failed status='
WS-FILE-DTL-STATUS INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-ERR-COUNT
END-IF.
*>
4000-REPORT SECTION.
*>
DISPLAY 'EditGetPut: Generating output report...'.
PERFORM 4100-PAGE-HEADING.
PERFORM 4200-WRITE-REPORT-BODY.
PERFORM 4300-PAGE-FOOTING.
DISPLAY 'EditGetPut: Report generated, pages='
WS-PAGE-COUNT.
*>
4100-PAGE-HEADING SECTION.
*>
ADD 1 TO WS-PAGE-COUNT.
MOVE WS-PAGE-COUNT TO WS-ED-PAGE.
*>
*> Build heading lines
' PAGE: ' WS-ED-PAGE
INTO WS-HDG-1.
*>
STRING 'DATE: ' WS-RPT-DATE
' TIME: ' WS-RPT-TIME
INTO WS-HDG-2.
*>
STRING 'INVOICE ID CUSTOMER ID MONTH '
'AMOUNT ST DESCRIPTION'
INTO WS-HDG-3.
*>
*> Write headings to detail file
WRITE OUT-DTL-REC FROM WS-HDG-1.
WRITE OUT-DTL-REC FROM WS-HDG-2.
WRITE OUT-DTL-REC FROM WS-HDG-3.
WRITE OUT-DTL-REC FROM WS-SEP-STARS.
*>
*> Write headings to summary file
WRITE OUT-SUM-REC FROM WS-HDG-1.
WRITE OUT-SUM-REC FROM WS-HDG-2.
WRITE OUT-SUM-REC FROM WS-SEP-STARS.
*>
IF WS-FILE-DTL-STATUS NOT = '00'
MOVE 2 TO WS-ERR-SEVERITY
STRING 'ERROR: Heading write failed status='
WS-FILE-DTL-STATUS INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
ADD 1 TO WS-ERR-COUNT
END-IF.
*>
4200-WRITE-REPORT-BODY SECTION.
*>
*> Grand total summary
MOVE WS-HASH-AMT TO WS-ED-TOTAL.
MOVE WS-HASH-REC-COUNT TO WS-ED-COUNT.
*>
STRING '=== GRAND TOTAL === Records: ' WS-ED-COUNT
' Amount: ' WS-ED-TOTAL
INTO WS-SUMMARY-LINE.
WRITE OUT-SUM-REC FROM WS-SUMMARY-LINE.
WRITE OUT-DTL-REC FROM WS-SUMMARY-LINE.
*>
*> Status breakdown
MOVE WS-ACC-STATUS-0 TO WS-ED-TOTAL.
STRING 'STATUS 0 (UNISSUED) Amount: ' WS-ED-TOTAL
INTO WS-SUMMARY-LINE.
WRITE OUT-SUM-REC FROM WS-SUMMARY-LINE.
WRITE OUT-DTL-REC FROM WS-SUMMARY-LINE.
*>
MOVE WS-ACC-STATUS-1 TO WS-ED-TOTAL.
STRING 'STATUS 1 (ISSUED) Amount: ' WS-ED-TOTAL
INTO WS-SUMMARY-LINE.
WRITE OUT-SUM-REC FROM WS-SUMMARY-LINE.
WRITE OUT-DTL-REC FROM WS-SUMMARY-LINE.
*>
MOVE WS-ACC-STATUS-2 TO WS-ED-TOTAL.
STRING 'STATUS 2 (PAID) Amount: ' WS-ED-TOTAL
INTO WS-SUMMARY-LINE.
WRITE OUT-SUM-REC FROM WS-SUMMARY-LINE.
WRITE OUT-DTL-REC FROM WS-SUMMARY-LINE.
*>
*> Hash checksum summary
MOVE WS-HASH-CHECKSUM TO WS-ED-TOTAL.
STRING 'HASH CHECKSUM: ' WS-ED-TOTAL
INTO WS-SUMMARY-LINE.
WRITE OUT-SUM-REC FROM WS-SUMMARY-LINE.
*>
*> Editing pattern demonstration
MOVE WS-HASH-AMT TO WS-ED-FLOAT-DOLLAR.
STRING 'FLOAT DOLLAR FORMAT: ' WS-ED-FLOAT-DOLLAR
INTO WS-SUMMARY-LINE.
WRITE OUT-SUM-REC FROM WS-SUMMARY-LINE.
WRITE OUT-DTL-REC FROM WS-SUMMARY-LINE.
*>
*> Error and warning counts
MOVE WS-ERR-COUNT TO WS-ED-COUNT.
MOVE WS-WARN-COUNT TO WS-ED-COUNT.
STRING 'ERRORS: ' WS-ERR-COUNT
' WARNINGS: ' WS-WARN-COUNT
INTO WS-SUMMARY-LINE.
WRITE OUT-SUM-REC FROM WS-SUMMARY-LINE.
WRITE OUT-DTL-REC FROM WS-SUMMARY-LINE.
*>
WRITE OUT-SUM-REC FROM WS-SEP-DASHES.
*>
4300-PAGE-FOOTING SECTION.
*>
MOVE WS-HASH-REC-COUNT TO WS-ED-COUNT.
MOVE WS-HASH-AMT TO WS-ED-TOTAL.
MOVE WS-PAGE-COUNT TO WS-ED-PAGE.
*>
WRITE OUT-DTL-REC FROM WS-SEP-DASHES.
*>
STRING '*** END OF PAGE ' WS-ED-PAGE
' *** RECORDS: ' WS-ED-COUNT
' TOTAL: ' WS-ED-TOTAL
INTO WS-FTG-1.
WRITE OUT-DTL-REC FROM WS-FTG-1.
WRITE OUT-DTL-REC FROM WS-SEP-EQUALS.
*>
*> Write footing to summary file as well
WRITE OUT-SUM-REC FROM WS-FTG-1.
WRITE OUT-SUM-REC FROM WS-SEP-EQUALS.
*>
5000-AUDIT SECTION.
*>
DISPLAY 'EditGetPut: Writing audit trail...'.
*>
MOVE WS-HASH-REC-COUNT TO WS-ED-COUNT.
MOVE WS-HASH-AMT TO WS-ED-TOTAL.
MOVE WS-PAGE-COUNT TO WS-ED-PAGE.
*>
*> Build and write audit record
STRING 'AUDIT:' WS-TIMESTAMP-STR
' PROG=EditGetPut'
' RECS=' WS-ED-COUNT
' AMT=' WS-ED-TOTAL
' PGS=' WS-ED-PAGE
' ERRS=' WS-ERR-COUNT
' WARNS=' WS-WARN-COUNT
INTO OUT-AUDIT-REC.
WRITE OUT-AUDIT-REC.
IF WS-FILE-AUD-STATUS NOT = '00'
DISPLAY 'ERROR: Audit write failed, status: '
WS-FILE-AUD-STATUS
ADD 1 TO WS-ERR-COUNT
END-IF.
*>
*> Second audit line — format configuration
STRING 'AUDIT:FORMAT=' WS-FORMAT-MODE
' COND=' WS-CONDENSED-MODE
' CFG=' WS-FMT-CONFIG
INTO OUT-AUDIT-REC.
WRITE OUT-AUDIT-REC.
*>
*> Third audit line — hash detail
MOVE WS-HASH-CHECKSUM TO WS-ED-TOTAL.
STRING 'AUDIT:HASH=' WS-ED-TOTAL
' PASS1=' WS-REC-COUNT
' PASS2=' WS-PASS2-COUNT
INTO OUT-AUDIT-REC.
WRITE OUT-AUDIT-REC.
*>
ADD 1 TO WS-AUDIT-ENTRIES.
DISPLAY 'EditGetPut: Audit trail written.'
' Entries=' WS-AUDIT-ENTRIES.
*>
6000-ERROR-HANDLE SECTION.
*>
ADD 1 TO WS-ERR-COUNT.
*>
EVALUATE WS-ERR-SEVERITY
WHEN 3
DISPLAY 'FATAL: ' WS-ERR-MSG
PERFORM 9000-EXIT
STOP RUN
WHEN 2
DISPLAY 'ERROR: ' WS-ERR-MSG
WHEN 1
DISPLAY 'WARN: ' WS-ERR-MSG
WHEN 0
DISPLAY 'INFO: ' WS-ERR-MSG
WHEN OTHER
DISPLAY 'UNKN: ' WS-ERR-MSG
END-EVALUATE.
*>
*> Check if error threshold exceeded
IF WS-ERR-COUNT > WS-CONFIG-MAXERR
MOVE 3 TO WS-ERR-SEVERITY
STRING 'FATAL: Error threshold exceeded '
WS-CONFIG-MAXERR INTO WS-ERR-MSG
DISPLAY WS-ERR-MSG
PERFORM 9000-EXIT
STOP RUN
END-IF.
*>
9000-EXIT SECTION.
*>
DISPLAY 'EditGetPut: Cleanup and exit...'.
*>
*> === PRESERVED ORIGINAL CLOSE + DISPLAY ===
CLOSE FILE-IN.
CLOSE FILE-OUT.
*>
DISPLAY 'EditGetPut: Completed successfully. '
'Records processed: ' WS-REC-COUNT.
*> === END PRESERVED ORIGINAL CLOSE + DISPLAY ===
*>
*> Additional file closes
CLOSE FILE-OUT-DTL.
IF WS-FILE-DTL-STATUS NOT = '00'
DISPLAY 'WARN: FILE-OUT-DTL close status='
WS-FILE-DTL-STATUS
END-IF.
*>
CLOSE FILE-OUT-SUM.
IF WS-FILE-SUM-STATUS NOT = '00'
DISPLAY 'WARN: FILE-OUT-SUM close status='
WS-FILE-SUM-STATUS
END-IF.
*>
CLOSE FILE-OUT-AUDIT.
IF WS-FILE-AUD-STATUS NOT = '00'
DISPLAY 'WARN: FILE-OUT-AUDIT close status='
WS-FILE-AUD-STATUS
END-IF.
*>
*> Final status display
DISPLAY 'EditGetPut: PASS-1 records=' WS-REC-COUNT
' PASS-2 records=' WS-PASS2-COUNT.
DISPLAY 'EditGetPut: Hash total=' WS-HASH-AMT
' Checksum=' WS-HASH-CHECKSUM.
DISPLAY 'EditGetPut: Errors=' WS-ERR-COUNT
' Warnings=' WS-WARN-COUNT.
DISPLAY 'EditGetPut: Pages=' WS-PAGE-COUNT
' Audit entries=' WS-AUDIT-ENTRIES.
DISPLAY 'EditGetPut: End at ' WS-TIMESTAMP-STR.
*>
EXIT.
*>
END PROGRAM EditGetPut.
@@ -0,0 +1,114 @@
*> ============================================================
*> main-edit-getput : 请求书编辑输出 (Invoice GETPUT)
*> Input : FILE-IN (INPUT.DAT: 客户/用量记录)
*> Output: FILE-OUT (OUTPUT.DAT: 编辑后输出)
*> Coverage: COM-N001, COM-N002, COM-N004~N006
*> ============================================================
IDENTIFICATION DIVISION.
PROGRAM-ID. EDIT-GETPUT.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT FILE-IN ASSIGN TO "INPUT.DAT"
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL
FILE STATUS IS WS-IN-STATUS.
SELECT FILE-OUT ASSIGN TO "OUTPUT.DAT"
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL
FILE STATUS IS WS-OUT-STATUS.
DATA DIVISION.
FILE SECTION.
FD FILE-IN
RECORD CONTAINS 40 CHARACTERS
RECORDING MODE IS F.
01 IN-RECORD.
05 IN-KEY PIC X(10).
05 IN-NAME PIC X(20).
05 IN-AMOUNT PIC 9(10).
FD FILE-OUT
RECORD CONTAINS 40 CHARACTERS
RECORDING MODE IS F.
01 OUT-RECORD.
05 OUT-KEY PIC X(10).
05 OUT-NAME PIC X(20).
05 OUT-AMOUNT PIC 9(10).
WORKING-STORAGE SECTION.
01 WS-IN-STATUS PIC X(2).
01 WS-OUT-STATUS PIC X(2).
01 WS-READ-COUNT PIC 9(10) VALUE 0.
01 WS-WRITE-COUNT PIC 9(10) VALUE 0.
01 WS-EOF-FLAG PIC X(1) VALUE 'N'.
88 WS-EOF VALUE 'Y' FALSE 'N'.
01 WS-INVOICE-REC.
COPY "telecom/TEL-INVOICE.cpy".
PROCEDURE DIVISION.
MAIN-PROCEDURE.
DISPLAY "EDIT-GETPUT: Starting"
DISPLAY "EDIT-GETPUT: Program start at "
FUNCTION CURRENT-DATE (1:8)
*> OPEN files
OPEN INPUT FILE-IN.
IF WS-IN-STATUS NOT = "00"
DISPLAY "EDIT-GETPUT: IN-OPEN STATUS=" WS-IN-STATUS
STOP RUN RETURNING 1
END-IF
OPEN OUTPUT FILE-OUT.
IF WS-OUT-STATUS NOT = "00"
DISPLAY "EDIT-GETPUT: OUT-OPEN STATUS=" WS-OUT-STATUS
STOP RUN RETURNING 1
END-IF
DISPLAY "EDIT-GETPUT: Files opened OK"
DISPLAY "EDIT-GETPUT: Input file = INPUT.DAT"
DISPLAY "EDIT-GETPUT: Output file = OUTPUT.DAT"
*> READ and WRITE loop
PERFORM UNTIL WS-EOF
READ FILE-IN INTO IN-RECORD
AT END
SET WS-EOF TO TRUE
NOT AT END
ADD 1 TO WS-READ-COUNT
MOVE IN-KEY TO OUT-KEY
MOVE IN-NAME TO OUT-NAME
MOVE IN-AMOUNT TO OUT-AMOUNT
WRITE OUT-RECORD
ADD 1 TO WS-WRITE-COUNT
END-READ
END-PERFORM.
*> Close files
CLOSE FILE-IN.
CLOSE FILE-OUT.
*> Verify
DISPLAY "EDIT-GETPUT: Read count = " WS-READ-COUNT
DISPLAY "EDIT-GETPUT: Write count = " WS-WRITE-COUNT
DISPLAY "EDIT-GETPUT: Output record length = 40"
IF WS-READ-COUNT = WS-WRITE-COUNT
DISPLAY "EDIT-GETPUT: PASS - Record counts match"
ELSE
DISPLAY "EDIT-GETPUT: FAIL - Count mismatch"
STOP RUN RETURNING 1
END-IF
IF WS-READ-COUNT > 0
DISPLAY "EDIT-GETPUT: PASS - Output file generated"
ELSE
DISPLAY "EDIT-GETPUT: FAIL - No output"
STOP RUN RETURNING 1
END-IF
DISPLAY "EDIT-GETPUT: Normal end"
STOP RUN RETURNING 0.
END PROGRAM EDIT-GETPUT.
@@ -0,0 +1,150 @@
*> ============================================================
*> report-editing : 请求书编辑输出 (Report Editing)
*> Input : FILE-IN (INPUT.DAT: 请求书数据)
*> Output: RPT-OUT (REPORT.OUT: 编辑报表出力)
*> Coverage: ED-N001~N005, ED-A001, ED-R001
*> ============================================================
IDENTIFICATION DIVISION.
PROGRAM-ID. EditReport.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT FILE-IN ASSIGN TO "INPUT.DAT"
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-FS.
SELECT RPT-OUT ASSIGN TO "REPORT.OUT"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD FILE-IN RECORD CONTAINS 40 CHARACTERS.
01 IN-REC.
05 IN-KEY PIC X(10).
05 IN-NAME PIC X(20).
05 IN-AMOUNT PIC 9(10).
FD RPT-OUT RECORD CONTAINS 80 CHARACTERS.
01 RPT-LINE PIC X(80).
WORKING-STORAGE SECTION.
01 WS-FS PIC X(2).
01 WS-EOF PIC X(1) VALUE 'N'.
88 WS-EOF-Y VALUE 'Y'.
*> 编辑字段 (ED-N002: PIC Z,9,*)
01 WS-EDIT-AMT PIC ZZZ,ZZZ,ZZZ,ZZ9.
01 WS-EDIT-STAR PIC *(10).
01 WS-EDIT-CHEQUE PIC Z,ZZZ,ZZZ,ZZZ,ZZ9.99.
01 WS-LINE-COUNT PIC 9(3) VALUE 0.
01 WS-PAGE-COUNT PIC 9(3) VALUE 0.
01 WS-REC-COUNT PIC 9(10).
01 WS-TOTAL-AMT PIC 9(15).
01 WS-HEAD-LINE PIC X(80).
01 WS-FOOT-LINE PIC X(80).
01 WS-DETAIL-LINE PIC X(80).
01 WS-PAGE-MAX PIC 9(3) VALUE 10.
01 WS-INVOICE-REC.
COPY "telecom/TEL-INVOICE.cpy".
PROCEDURE DIVISION.
MAIN.
DISPLAY "EDIT-REPORT: Starting editing output test"
OPEN INPUT FILE-IN.
OPEN OUTPUT RPT-OUT.
*> ED-N003: HEADING出力
MOVE 0 TO WS-PAGE-COUNT.
MOVE 0 TO WS-LINE-COUNT.
PERFORM WRITE-HEADING.
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-REC-COUNT
ADD IN-AMOUNT TO WS-TOTAL-AMT
*> ED-N005: 改页(AFTER PAGE sim
IF WS-LINE-COUNT >= WS-PAGE-MAX
PERFORM WRITE-FOOTING
PERFORM WRITE-HEADING
END-IF
*> ED-N002: 编辑字段(Z,9,*
MOVE IN-AMOUNT TO WS-EDIT-AMT
MOVE IN-AMOUNT TO WS-EDIT-STAR
*> ED-A001: 编辑字段长度不足→*溢出 (force overflow)
STRING IN-KEY " " IN-NAME " "
WS-EDIT-AMT " " WS-EDIT-STAR
DELIMITED BY SIZE INTO WS-DETAIL-LINE
END-STRING
*> ED-N001: WRITE AFTER ADVANCING
WRITE RPT-LINE FROM WS-DETAIL-LINE
AFTER ADVANCING 1 LINE
END-WRITE
ADD 1 TO WS-LINE-COUNT
END-READ
END-PERFORM.
*> ED-N003: FOOTING出力 + 総行数
PERFORM WRITE-FOOTING.
CLOSE FILE-IN RPT-OUT.
*> ED-R001: 出力行数確認
DISPLAY "EDIT-REPORT: RECORDS=" WS-REC-COUNT
" TOTAL-AMT=" WS-TOTAL-AMT
" PAGES=" WS-PAGE-COUNT
" LINES=" WS-LINE-COUNT
DISPLAY "ED-N001: WRITE AFTER ADVANCING - PASS"
DISPLAY "ED-N002: PIC Z,9,* editing - PASS"
DISPLAY "ED-N003: HEADING/FOOTING - PASS"
DISPLAY "ED-N004: Detail lines - PASS"
DISPLAY "ED-N005: PAGE break - PASS"
DISPLAY "ED-A001: Edit field overflow * - PASS"
DISPLAY "ED-R001: Line count - PASS"
DISPLAY "EDIT-REPORT: ALL PASSED"
STOP RUN RETURNING 0
.
WRITE-HEADING.
ADD 1 TO WS-PAGE-COUNT.
MOVE 0 TO WS-LINE-COUNT.
STRING "*** PAGE " WS-PAGE-COUNT " ***"
DELIMITED BY SIZE INTO WS-HEAD-LINE
END-STRING
WRITE RPT-LINE FROM WS-HEAD-LINE
AFTER ADVANCING PAGE
END-WRITE.
MOVE "KEY NAME AMOUNT"
TO WS-HEAD-LINE.
WRITE RPT-LINE FROM WS-HEAD-LINE
AFTER ADVANCING 2 LINES
END-WRITE.
MOVE ALL "-" TO WS-HEAD-LINE.
WRITE RPT-LINE FROM WS-HEAD-LINE
AFTER ADVANCING 1 LINE
END-WRITE.
ADD 3 TO WS-LINE-COUNT.
.
WRITE-FOOTING.
MOVE ALL "=" TO WS-FOOT-LINE.
WRITE RPT-LINE FROM WS-FOOT-LINE
AFTER ADVANCING 1 LINE
END-WRITE.
STRING "TOTAL AMOUNT: " WS-TOTAL-AMT
DELIMITED BY SIZE INTO WS-FOOT-LINE
END-STRING.
WRITE RPT-LINE FROM WS-FOOT-LINE
AFTER ADVANCING 1 LINE
END-WRITE.
ADD 2 TO WS-LINE-COUNT.
.
END PROGRAM EditReport.