94400d50d4
作为子目录纳入系统,与核心测试管道协同 Co-Authored-By: Claude <noreply@anthropic.com>
994 lines
36 KiB
COBOL
994 lines
36 KiB
COBOL
*> ============================================================
|
|
*> 15-csv-fb-nolf : 外部CDR CSV取込(无LF) (CDR Import)
|
|
*> Input : FILE-IN (file-in.csv) Output: FILE-OUT (file-out.dat)
|
|
*> ERROR-REPORT (csv-errors.dat) AUDIT-FILE (csv-audit.dat)
|
|
*> Enhanced: SECTIONs, field validation, truncation detection,
|
|
*> quote check, count reconciliation, hash totals,
|
|
*> severity levels, FILE STATUS after every I/O.
|
|
*> Coverage: CF-N001, CF-N003~N006, CF-A002
|
|
*> ============================================================
|
|
IDENTIFICATION DIVISION.
|
|
PROGRAM-ID. CsvFbNoLf.
|
|
|
|
ENVIRONMENT DIVISION.
|
|
INPUT-OUTPUT SECTION.
|
|
FILE-CONTROL.
|
|
SELECT FILE-IN ASSIGN TO 'file-in.csv'
|
|
ORGANIZATION IS LINE 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.
|
|
SELECT ERROR-REPORT ASSIGN TO 'csv-errors.dat'
|
|
ORGANIZATION IS LINE SEQUENTIAL
|
|
FILE STATUS IS WS-ERR-STATUS.
|
|
SELECT AUDIT-FILE ASSIGN TO 'csv-audit.dat'
|
|
ORGANIZATION IS LINE SEQUENTIAL
|
|
FILE STATUS IS WS-AUDIT-STATUS.
|
|
|
|
DATA DIVISION.
|
|
FILE SECTION.
|
|
FD FILE-IN.
|
|
01 IN-LINE PIC X(200).
|
|
|
|
FD FILE-OUT.
|
|
01 OUT-REC PIC X(100).
|
|
|
|
FD ERROR-REPORT.
|
|
01 ERR-REC PIC X(80).
|
|
|
|
FD AUDIT-FILE.
|
|
01 AUD-REC PIC X(80).
|
|
|
|
WORKING-STORAGE SECTION.
|
|
01 WS-TELECOM-REC.
|
|
COPY "telecom/TEL-CDR.cpy".
|
|
|
|
*> File status keys for all files
|
|
01 WS-FILE-IN-STATUS PIC X(02).
|
|
01 WS-FILE-OUT-STATUS PIC X(02).
|
|
01 WS-ERR-STATUS PIC X(02).
|
|
01 WS-AUDIT-STATUS PIC X(02).
|
|
|
|
*> EOF flag
|
|
01 WS-EOF PIC X(01) VALUE 'N'.
|
|
88 WS-EOF-YES VALUE 'Y' FALSE 'N'.
|
|
|
|
*> Record counters (original + expanded)
|
|
01 WS-REC-COUNT PIC 9(05) VALUE ZERO.
|
|
01 WS-LINE-COUNT PIC 9(05) VALUE ZERO.
|
|
01 WS-COUNTERS.
|
|
05 WS-TOT-READ PIC 9(09) VALUE ZERO.
|
|
05 WS-TOT-WRITTEN PIC 9(09) VALUE ZERO.
|
|
05 WS-TOT-MALFORMED PIC 9(09) VALUE ZERO.
|
|
05 WS-TOT-TRUNCATED PIC 9(09) VALUE ZERO.
|
|
05 WS-TOT-QUOTE-ERR PIC 9(09) VALUE ZERO.
|
|
05 WS-TOT-FIELD-ERR PIC 9(09) VALUE ZERO.
|
|
05 WS-TOT-WARNINGS PIC 9(09) VALUE ZERO.
|
|
05 WS-TOT-ERRORS PIC 9(09) VALUE ZERO.
|
|
05 WS-TOT-CRITICAL PIC 9(09) VALUE ZERO.
|
|
|
|
*> CSV parsing fields (original)
|
|
01 WS-FIELDS.
|
|
05 WS-FIELD1 PIC X(30).
|
|
05 WS-FIELD2 PIC X(30).
|
|
05 WS-FIELD3 PIC X(30).
|
|
01 WS-POS PIC 9(03).
|
|
01 WS-CHAR PIC X(01).
|
|
01 WS-FIELD-NUM PIC 9(01).
|
|
01 WS-CHAR-OFFSET PIC 9(02).
|
|
01 WS-IN-QUOTE PIC X(01) VALUE 'N'.
|
|
88 WS-IN-QUOTE-YES VALUE 'Y' FALSE 'N'.
|
|
01 WS-OUT-LINE PIC X(100).
|
|
|
|
*> Validation fields
|
|
01 WS-QUOTE-COUNT PIC 9(03) VALUE ZERO.
|
|
01 WS-MALFORMED-CNT PIC 9(05) VALUE ZERO.
|
|
01 WS-TRUNC-CNT PIC 9(05) VALUE ZERO.
|
|
01 WS-FIELD-COUNT-ERR PIC 9(05) VALUE ZERO.
|
|
01 WS-FIELD3-LEN PIC 9(02).
|
|
01 WS-IDX PIC 9(02).
|
|
01 WS-CHAR-CHK PIC X(01).
|
|
01 WS-ALL-NUMERIC PIC X(01) VALUE 'Y'.
|
|
01 WS-RECONCILE-OK PIC X(01) VALUE 'Y'.
|
|
01 WS-VALID-FLAG PIC X(01) VALUE 'Y'.
|
|
88 WS-VALID-REC-YES VALUE 'Y' FALSE 'N'.
|
|
88 WS-VALID-REC-NO VALUE 'N'.
|
|
|
|
*> Field-level validation status per field
|
|
01 WS-FIELD-STATUS.
|
|
05 WS-FIELD1-OK PIC X(01) VALUE 'Y'.
|
|
05 WS-FIELD2-OK PIC X(01) VALUE 'Y'.
|
|
05 WS-FIELD3-OK PIC X(01) VALUE 'Y'.
|
|
01 WS-FIELD-ERR-MSG PIC X(60).
|
|
01 WS-FIELD-TRUNC-FLAG PIC X(01) VALUE 'N'.
|
|
88 WS-FIELD-TRUNC-YES VALUE 'Y' FALSE 'N'.
|
|
|
|
*> Input record buffer for error reporting
|
|
01 WS-INPUT-BUF PIC X(200).
|
|
|
|
*> Hash totals (per field + overall)
|
|
01 WS-HASH-TOTAL PIC 9(10) VALUE ZERO.
|
|
01 WS-HASH-FIELD-LEN PIC 9(05) VALUE ZERO.
|
|
01 WS-HASH-FIELD1 PIC 9(10) VALUE ZERO.
|
|
01 WS-HASH-FIELD2 PIC 9(10) VALUE ZERO.
|
|
01 WS-HASH-FIELD3 PIC 9(10) VALUE ZERO.
|
|
|
|
*> Timestamp
|
|
01 WS-TIMESTAMP PIC X(20).
|
|
01 WS-CUR-DATE-DISP PIC X(08).
|
|
01 WS-CUR-TIME-DISP PIC X(06).
|
|
01 WS-TS-DISPLAY PIC X(26).
|
|
|
|
*> Error severity levels
|
|
01 WS-SEVERITY PIC X(01).
|
|
88 WS-SEV-INFO VALUE 'I'.
|
|
88 WS-SEV-WARNING VALUE 'W'.
|
|
88 WS-SEV-ERROR VALUE 'E'.
|
|
88 WS-SEV-CRITICAL VALUE 'C'.
|
|
|
|
*> Report and display formatting fields
|
|
01 WS-RPT-COUNT PIC Z(9)9.
|
|
01 WS-RPT-COUNT9 PIC Z(9)9.
|
|
01 WS-RPT-LINE PIC X(80).
|
|
01 WS-RPT-PCT PIC Z(9)9.9.
|
|
01 WS-LINE-DISP PIC Z(9)9.
|
|
01 WS-DISP-BUFFER PIC X(80).
|
|
|
|
PROCEDURE DIVISION.
|
|
|
|
*> ===== MAIN SECTION =====
|
|
MAIN SECTION.
|
|
MB-PROCESS.
|
|
PERFORM 1000-INIT
|
|
PERFORM 2000-OPEN-FILES
|
|
PERFORM 3000-READ-INPUT
|
|
PERFORM 4000-REPORT
|
|
PERFORM 5000-AUDIT
|
|
PERFORM 6000-ERROR-HANDLE
|
|
PERFORM 9000-EXIT
|
|
.
|
|
|
|
*> ===== 1000-INIT =====
|
|
1000-INIT SECTION.
|
|
1000-START.
|
|
MOVE FUNCTION CURRENT-DATE (1:8) TO WS-CUR-DATE-DISP.
|
|
MOVE FUNCTION CURRENT-DATE (9:6) TO WS-CUR-TIME-DISP.
|
|
STRING WS-CUR-DATE-DISP '-'
|
|
WS-CUR-TIME-DISP
|
|
DELIMITED BY SIZE INTO WS-TIMESTAMP.
|
|
STRING WS-CUR-DATE-DISP(1:4) '-'
|
|
WS-CUR-DATE-DISP(5:2) '-'
|
|
WS-CUR-DATE-DISP(7:2) ' '
|
|
WS-CUR-TIME-DISP(1:2) ':'
|
|
WS-CUR-TIME-DISP(3:2) ':'
|
|
WS-CUR-TIME-DISP(5:2)
|
|
DELIMITED BY SIZE INTO WS-TS-DISPLAY.
|
|
DISPLAY WS-TS-DISPLAY ' 1000-INIT: CsvFbNoLf START'.
|
|
|
|
*> Initialize all counters to zero
|
|
MOVE ZERO TO WS-REC-COUNT
|
|
WS-LINE-COUNT
|
|
WS-TOT-READ
|
|
WS-TOT-WRITTEN
|
|
WS-TOT-MALFORMED
|
|
WS-TOT-TRUNCATED
|
|
WS-TOT-QUOTE-ERR
|
|
WS-TOT-FIELD-ERR
|
|
WS-TOT-WARNINGS
|
|
WS-TOT-ERRORS
|
|
WS-TOT-CRITICAL
|
|
WS-MALFORMED-CNT
|
|
WS-TRUNC-CNT
|
|
WS-FIELD-COUNT-ERR
|
|
WS-HASH-TOTAL
|
|
WS-HASH-FIELD1
|
|
WS-HASH-FIELD2
|
|
WS-HASH-FIELD3
|
|
WS-HASH-FIELD-LEN.
|
|
|
|
*> Initialize flags
|
|
MOVE 'Y' TO WS-RECONCILE-OK.
|
|
MOVE 'N' TO WS-EOF.
|
|
|
|
*> ===== 2000-OPEN-FILES =====
|
|
2000-OPEN-FILES SECTION.
|
|
2000-START.
|
|
DISPLAY WS-TS-DISPLAY ' 2000-OPEN-FILES: Opening files'.
|
|
OPEN INPUT FILE-IN.
|
|
IF WS-FILE-IN-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY ' ERROR: Cannot open FILE-IN,'
|
|
' status: ' WS-FILE-IN-STATUS
|
|
MOVE 1 TO RETURN-CODE
|
|
STOP RUN
|
|
END-IF.
|
|
DISPLAY WS-TS-DISPLAY ' FILE-IN opened, status='
|
|
WS-FILE-IN-STATUS.
|
|
OPEN OUTPUT FILE-OUT.
|
|
IF WS-FILE-OUT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY ' ERROR: Cannot open FILE-OUT,'
|
|
' status: ' WS-FILE-OUT-STATUS
|
|
MOVE 1 TO RETURN-CODE
|
|
STOP RUN
|
|
END-IF.
|
|
DISPLAY WS-TS-DISPLAY ' FILE-OUT opened, status='
|
|
WS-FILE-OUT-STATUS.
|
|
OPEN OUTPUT ERROR-REPORT.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY ' ERROR: Cannot open ERROR-REPORT,'
|
|
' status: ' WS-ERR-STATUS
|
|
MOVE 1 TO RETURN-CODE
|
|
STOP RUN
|
|
END-IF.
|
|
DISPLAY WS-TS-DISPLAY ' ERROR-REPORT opened, status='
|
|
WS-ERR-STATUS.
|
|
OPEN OUTPUT AUDIT-FILE.
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY ' ERROR: Cannot open AUDIT-FILE,'
|
|
' status: ' WS-AUDIT-STATUS
|
|
MOVE 1 TO RETURN-CODE
|
|
STOP RUN
|
|
END-IF.
|
|
DISPLAY WS-TS-DISPLAY ' AUDIT-FILE opened, status='
|
|
WS-AUDIT-STATUS.
|
|
|
|
*> Write error report header lines
|
|
MOVE 'CSV Error Detail Report - CsvFbNoLf' TO ERR-REC.
|
|
WRITE ERR-REC.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY 'WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
|
|
STRING 'Run: ' WS-TIMESTAMP INTO ERR-REC.
|
|
WRITE ERR-REC.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY 'WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
|
|
MOVE SPACES TO ERR-REC.
|
|
MOVE 'Line Severity Field Description' TO ERR-REC.
|
|
WRITE ERR-REC.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY 'WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
|
|
MOVE SPACES TO ERR-REC.
|
|
WRITE ERR-REC.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY 'WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
|
|
*> Write audit file header lines
|
|
MOVE 'CSV Audit Report - CsvFbNoLf' TO AUD-REC.
|
|
WRITE AUD-REC.
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY ' WRITE ERROR: AUDIT-FILE status='
|
|
WS-AUDIT-STATUS
|
|
END-IF.
|
|
|
|
STRING 'Run: ' WS-TIMESTAMP INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY ' WRITE ERROR: AUDIT-FILE status='
|
|
WS-AUDIT-STATUS
|
|
END-IF.
|
|
|
|
MOVE SPACES TO AUD-REC.
|
|
WRITE AUD-REC.
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY ' WRITE ERROR: AUDIT-FILE status='
|
|
WS-AUDIT-STATUS
|
|
END-IF.
|
|
|
|
DISPLAY WS-TS-DISPLAY '2000-OPEN-FILES: All files opened OK'.
|
|
|
|
*> ===== 3000-READ-INPUT =====
|
|
3000-READ-INPUT SECTION.
|
|
3000-START.
|
|
DISPLAY WS-TS-DISPLAY ' 3000-READ-INPUT: Processing CSV'.
|
|
|
|
PERFORM UNTIL WS-EOF-YES
|
|
READ FILE-IN
|
|
AT END
|
|
SET WS-EOF-YES TO TRUE
|
|
DISPLAY WS-TS-DISPLAY ' EOF reached,'
|
|
' lines=' WS-LINE-COUNT
|
|
NOT AT END
|
|
ADD 1 TO WS-LINE-COUNT
|
|
ADD 1 TO WS-TOT-READ
|
|
MOVE IN-LINE TO WS-INPUT-BUF
|
|
PERFORM 3100-VALIDATE-RECORD
|
|
END-READ
|
|
IF WS-FILE-IN-STATUS NOT = '00'
|
|
AND NOT = '10'
|
|
DISPLAY WS-TS-DISPLAY ' READ ERROR: FILE-IN status='
|
|
WS-FILE-IN-STATUS
|
|
MOVE 'E' TO WS-SEVERITY
|
|
ADD 1 TO WS-TOT-ERRORS
|
|
END-IF
|
|
END-PERFORM.
|
|
|
|
*> Close input file with STATUS check
|
|
CLOSE FILE-IN.
|
|
IF WS-FILE-IN-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY ' CLOSE ERROR: FILE-IN status='
|
|
WS-FILE-IN-STATUS
|
|
ADD 1 TO WS-TOT-ERRORS
|
|
END-IF.
|
|
DISPLAY WS-TS-DISPLAY ' 3000-READ-INPUT: Input closed,'
|
|
' total=' WS-LINE-COUNT.
|
|
|
|
*> ===== 3100-VALIDATE-RECORD =====
|
|
3100-VALIDATE-RECORD SECTION.
|
|
3100-START.
|
|
MOVE 'Y' TO WS-VALID-FLAG.
|
|
MOVE 'Y' TO WS-FIELD1-OK.
|
|
MOVE 'Y' TO WS-FIELD2-OK.
|
|
MOVE 'Y' TO WS-FIELD3-OK.
|
|
MOVE 'N' TO WS-FIELD-TRUNC-FLAG.
|
|
MOVE SPACES TO WS-FIELD-ERR-MSG.
|
|
|
|
*> Quote pairing: odd quote count = malformed
|
|
MOVE 0 TO WS-QUOTE-COUNT.
|
|
INSPECT IN-LINE TALLYING WS-QUOTE-COUNT
|
|
FOR ALL '"'.
|
|
|
|
IF FUNCTION MOD(WS-QUOTE-COUNT, 2) NOT = 0
|
|
ADD 1 TO WS-MALFORMED-CNT
|
|
ADD 1 TO WS-TOT-QUOTE-ERR
|
|
ADD 1 TO WS-TOT-ERRORS
|
|
MOVE 'E' TO WS-SEVERITY
|
|
MOVE 'Unpaired quote in CSV line' TO WS-FIELD-ERR-MSG
|
|
MOVE 'N' TO WS-VALID-FLAG
|
|
STRING WS-LINE-COUNT ' ERROR Quote '
|
|
WS-FIELD-ERR-MSG
|
|
DELIMITED BY SIZE INTO ERR-REC
|
|
WRITE ERR-REC
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF
|
|
DISPLAY WS-TS-DISPLAY ' Quote error at line '
|
|
WS-LINE-COUNT ': ' WS-FIELD-ERR-MSG
|
|
END-IF.
|
|
|
|
*> Parse using original logic -> WS-FIELD1..3
|
|
PERFORM PARSE-CSV-LINE.
|
|
|
|
*> Field count: expect 3 fields
|
|
IF WS-FIELD-NUM < 3
|
|
ADD 1 TO WS-FIELD-COUNT-ERR
|
|
ADD 1 TO WS-TOT-FIELD-ERR
|
|
ADD 1 TO WS-TOT-ERRORS
|
|
MOVE 'E' TO WS-SEVERITY
|
|
MOVE 'N' TO WS-VALID-FLAG
|
|
STRING 'Expected 3 fields, got ' WS-FIELD-NUM
|
|
INTO WS-FIELD-ERR-MSG
|
|
STRING WS-LINE-COUNT ' ERROR Field '
|
|
WS-FIELD-ERR-MSG
|
|
DELIMITED BY SIZE INTO ERR-REC
|
|
WRITE ERR-REC
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF
|
|
DISPLAY WS-TS-DISPLAY ' Field count error at line '
|
|
WS-LINE-COUNT ': ' WS-FIELD-ERR-MSG
|
|
END-IF.
|
|
|
|
*> Field 1: presence check
|
|
IF WS-FIELD1 = SPACES
|
|
MOVE 'N' TO WS-FIELD1-OK
|
|
MOVE 'W' TO WS-SEVERITY
|
|
ADD 1 TO WS-TOT-WARNINGS
|
|
MOVE 'Field1 is empty' TO WS-FIELD-ERR-MSG
|
|
STRING WS-LINE-COUNT ' WARNING Field1 '
|
|
'Empty field content'
|
|
DELIMITED BY SIZE INTO ERR-REC
|
|
WRITE ERR-REC
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF
|
|
END-IF.
|
|
|
|
*> Truncation check: Field1 > 30 chars
|
|
IF FUNCTION LENGTH(FUNCTION TRIM(WS-FIELD1)) > 30
|
|
ADD 1 TO WS-TRUNC-CNT
|
|
ADD 1 TO WS-TOT-TRUNCATED
|
|
MOVE 'Y' TO WS-FIELD-TRUNC-FLAG
|
|
MOVE 'W' TO WS-SEVERITY
|
|
ADD 1 TO WS-TOT-WARNINGS
|
|
STRING WS-LINE-COUNT ' WARNING Field1 '
|
|
'Truncated to 30 chars'
|
|
DELIMITED BY SIZE INTO ERR-REC
|
|
WRITE ERR-REC
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF
|
|
END-IF.
|
|
|
|
*> Truncation check: Field2 > 30 chars
|
|
IF FUNCTION LENGTH(FUNCTION TRIM(WS-FIELD2)) > 30
|
|
ADD 1 TO WS-TRUNC-CNT
|
|
ADD 1 TO WS-TOT-TRUNCATED
|
|
MOVE 'Y' TO WS-FIELD-TRUNC-FLAG
|
|
MOVE 'W' TO WS-SEVERITY
|
|
ADD 1 TO WS-TOT-WARNINGS
|
|
STRING WS-LINE-COUNT ' WARNING Field2 '
|
|
'Truncated to 30 chars'
|
|
DELIMITED BY SIZE INTO ERR-REC
|
|
WRITE ERR-REC
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF
|
|
END-IF.
|
|
|
|
*> Numeric check: Field2
|
|
IF WS-FIELD2 NOT = SPACES
|
|
MOVE 'Y' TO WS-ALL-NUMERIC
|
|
MOVE WS-FIELD2 TO WS-DISP-BUFFER
|
|
INSPECT WS-DISP-BUFFER REPLACING ALL SPACES BY '0'
|
|
PERFORM VARYING WS-IDX FROM 1 BY 1
|
|
UNTIL WS-IDX > 30 OR WS-ALL-NUMERIC = 'N'
|
|
MOVE WS-DISP-BUFFER(WS-IDX:1) TO WS-CHAR-CHK
|
|
IF WS-CHAR-CHK < '0' OR > '9'
|
|
MOVE 'N' TO WS-ALL-NUMERIC
|
|
END-IF
|
|
END-PERFORM
|
|
IF WS-ALL-NUMERIC = 'N'
|
|
MOVE 'N' TO WS-FIELD2-OK
|
|
MOVE 'W' TO WS-SEVERITY
|
|
ADD 1 TO WS-TOT-WARNINGS
|
|
STRING WS-LINE-COUNT ' WARNING Field2 '
|
|
'Non-numeric content'
|
|
DELIMITED BY SIZE INTO ERR-REC
|
|
WRITE ERR-REC
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF
|
|
END-IF
|
|
END-IF.
|
|
|
|
*> Truncation check: Field3 > 30 chars
|
|
IF FUNCTION LENGTH(FUNCTION TRIM(WS-FIELD3)) > 30
|
|
ADD 1 TO WS-TRUNC-CNT
|
|
ADD 1 TO WS-TOT-TRUNCATED
|
|
MOVE 'Y' TO WS-FIELD-TRUNC-FLAG
|
|
MOVE 'W' TO WS-SEVERITY
|
|
ADD 1 TO WS-TOT-WARNINGS
|
|
STRING WS-LINE-COUNT ' WARNING Field3 '
|
|
'Truncated to 30 chars'
|
|
DELIMITED BY SIZE INTO ERR-REC
|
|
WRITE ERR-REC
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF
|
|
END-IF.
|
|
|
|
*> Numeric check: Field3
|
|
IF WS-FIELD3 > SPACES
|
|
MOVE 'Y' TO WS-ALL-NUMERIC
|
|
MOVE WS-FIELD3 TO WS-DISP-BUFFER
|
|
INSPECT WS-DISP-BUFFER REPLACING ALL SPACES BY '0'
|
|
PERFORM VARYING WS-IDX FROM 1 BY 1
|
|
UNTIL WS-IDX > 30 OR WS-ALL-NUMERIC = 'N'
|
|
MOVE WS-DISP-BUFFER(WS-IDX:1) TO WS-CHAR-CHK
|
|
IF WS-CHAR-CHK < '0' OR > '9'
|
|
MOVE 'N' TO WS-ALL-NUMERIC
|
|
END-IF
|
|
END-PERFORM
|
|
IF WS-ALL-NUMERIC = 'N'
|
|
MOVE 'N' TO WS-FIELD3-OK
|
|
MOVE 'W' TO WS-SEVERITY
|
|
ADD 1 TO WS-TOT-WARNINGS
|
|
STRING WS-LINE-COUNT ' WARNING Field3 '
|
|
'Non-numeric content'
|
|
DELIMITED BY SIZE INTO ERR-REC
|
|
WRITE ERR-REC
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF
|
|
END-IF
|
|
END-IF.
|
|
|
|
*> If record is valid (no ERROR severity), process it
|
|
IF WS-VALID-FLAG = 'Y'
|
|
PERFORM 3200-PROCESS-RECORD
|
|
ELSE
|
|
DISPLAY WS-TS-DISPLAY ' Record ' WS-LINE-COUNT
|
|
' skipped due to validation errors'
|
|
END-IF.
|
|
|
|
*> ===== 3200-PROCESS-RECORD =====
|
|
3200-PROCESS-RECORD SECTION.
|
|
3200-START.
|
|
PERFORM 3300-WRITE-OUTPUT.
|
|
|
|
*> Update per-field hash totals for batch control
|
|
COMPUTE WS-HASH-FIELD1 = WS-HASH-FIELD1 +
|
|
FUNCTION LENGTH(FUNCTION TRIM(WS-FIELD1))
|
|
COMPUTE WS-HASH-FIELD2 = WS-HASH-FIELD2 +
|
|
FUNCTION LENGTH(FUNCTION TRIM(WS-FIELD2))
|
|
COMPUTE WS-HASH-FIELD3 = WS-HASH-FIELD3 +
|
|
FUNCTION LENGTH(FUNCTION TRIM(WS-FIELD3)).
|
|
|
|
*> ===== 3300-WRITE-OUTPUT =====
|
|
3300-WRITE-OUTPUT SECTION.
|
|
3300-START.
|
|
*> Build output record from parsed fields (original logic preserved)
|
|
MOVE SPACES TO WS-OUT-LINE.
|
|
STRING WS-FIELD1 DELIMITED BY SPACES
|
|
'|'
|
|
WS-FIELD2 DELIMITED BY SPACES
|
|
'|'
|
|
WS-FIELD3 DELIMITED BY SPACES
|
|
INTO WS-OUT-LINE
|
|
END-STRING.
|
|
MOVE WS-OUT-LINE TO OUT-REC.
|
|
WRITE OUT-REC.
|
|
|
|
*> FILE STATUS check after EVERY write
|
|
IF WS-FILE-OUT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: FILE-OUT status='
|
|
WS-FILE-OUT-STATUS
|
|
MOVE 'E' TO WS-SEVERITY
|
|
ADD 1 TO WS-TOT-ERRORS
|
|
END-IF.
|
|
|
|
ADD 1 TO WS-REC-COUNT.
|
|
ADD 1 TO WS-TOT-WRITTEN.
|
|
|
|
*> Combined hash total: sum of all field lengths
|
|
COMPUTE WS-HASH-FIELD-LEN =
|
|
FUNCTION LENGTH(FUNCTION TRIM(WS-FIELD1)) +
|
|
FUNCTION LENGTH(FUNCTION TRIM(WS-FIELD2)) +
|
|
FUNCTION LENGTH(FUNCTION TRIM(WS-FIELD3)).
|
|
ADD WS-HASH-FIELD-LEN TO WS-HASH-TOTAL.
|
|
|
|
|
|
*> ===== 4000-REPORT =====
|
|
4000-REPORT SECTION.
|
|
4000-START.
|
|
DISPLAY WS-TS-DISPLAY '4000-REPORT: Finalizing error report'.
|
|
|
|
*> Write error report trailer
|
|
MOVE SPACES TO ERR-REC.
|
|
MOVE '--- End of CSV Error Detail Report ---' TO ERR-REC.
|
|
WRITE ERR-REC.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
|
|
*> Write error summary to error report
|
|
MOVE SPACES TO ERR-REC.
|
|
WRITE ERR-REC.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
|
|
MOVE WS-LINE-COUNT TO WS-RPT-COUNT.
|
|
STRING 'Total input lines: ' WS-RPT-COUNT
|
|
INTO ERR-REC.
|
|
WRITE ERR-REC.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
|
|
MOVE WS-MALFORMED-CNT TO WS-RPT-COUNT.
|
|
STRING 'Malformed records: ' WS-RPT-COUNT
|
|
INTO ERR-REC.
|
|
WRITE ERR-REC.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
|
|
MOVE WS-TRUNC-CNT TO WS-RPT-COUNT.
|
|
STRING 'Truncation warns: ' WS-RPT-COUNT
|
|
INTO ERR-REC.
|
|
WRITE ERR-REC.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
|
|
MOVE WS-FIELD-COUNT-ERR TO WS-RPT-COUNT.
|
|
STRING 'Field count errors: ' WS-RPT-COUNT
|
|
INTO ERR-REC.
|
|
WRITE ERR-REC.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
|
|
*> Record count reconciliation summary
|
|
IF WS-LINE-COUNT = WS-REC-COUNT
|
|
MOVE 'PASS' TO WS-RPT-LINE
|
|
ELSE
|
|
MOVE 'MISMATCH (see audit)' TO WS-RPT-LINE
|
|
MOVE 'N' TO WS-RECONCILE-OK
|
|
END-IF.
|
|
STRING 'Count reconcile: ' WS-RPT-LINE
|
|
INTO ERR-REC.
|
|
WRITE ERR-REC.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
|
|
*> Close error report with STATUS check
|
|
CLOSE ERROR-REPORT.
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' CLOSE ERROR: ERROR-REPORT status='
|
|
WS-ERR-STATUS
|
|
END-IF.
|
|
DISPLAY WS-TS-DISPLAY ' 4000-REPORT: Error report closed'.
|
|
|
|
*> ===== 5000-AUDIT =====
|
|
5000-AUDIT SECTION.
|
|
5000-START.
|
|
DISPLAY WS-TS-DISPLAY
|
|
'5000-AUDIT: audit report and control totals'.
|
|
|
|
*> Audit header
|
|
MOVE '=== CSV Import Summary ===' TO AUD-REC.
|
|
WRITE AUD-REC.
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: AUDIT-FILE status='
|
|
WS-AUDIT-STATUS
|
|
END-IF.
|
|
|
|
MOVE SPACES TO AUD-REC.
|
|
WRITE AUD-REC.
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: AUDIT-FILE status='
|
|
WS-AUDIT-STATUS
|
|
END-IF.
|
|
|
|
*> Batch run identification
|
|
STRING 'Program: CsvFbNoLf' INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: AUDIT-FILE status='
|
|
WS-AUDIT-STATUS
|
|
END-IF.
|
|
|
|
STRING 'Run date: ' WS-CUR-DATE-DISP
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: AUDIT-FILE status='
|
|
WS-AUDIT-STATUS
|
|
END-IF.
|
|
|
|
STRING 'Run time: ' WS-CUR-TIME-DISP
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: AUDIT-FILE status='
|
|
WS-AUDIT-STATUS
|
|
END-IF.
|
|
|
|
MOVE SPACES TO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
*> Record counts
|
|
MOVE WS-LINE-COUNT TO WS-RPT-COUNT.
|
|
STRING 'Input lines read: ' WS-RPT-COUNT
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
MOVE WS-REC-COUNT TO WS-RPT-COUNT.
|
|
STRING 'Output records written: ' WS-RPT-COUNT
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
*> Record count reconciliation
|
|
IF WS-LINE-COUNT = WS-REC-COUNT
|
|
MOVE 'PASS' TO WS-RPT-LINE
|
|
ELSE
|
|
MOVE 'MISMATCH (see details)' TO WS-RPT-LINE
|
|
MOVE 'N' TO WS-RECONCILE-OK
|
|
END-IF.
|
|
STRING 'Line vs record reconcile: ' WS-RPT-LINE
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
*> Error counts
|
|
MOVE WS-MALFORMED-CNT TO WS-RPT-COUNT.
|
|
STRING 'Malformed records: ' WS-RPT-COUNT
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
MOVE WS-TRUNC-CNT TO WS-RPT-COUNT.
|
|
STRING 'Truncation warnings: ' WS-RPT-COUNT
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
MOVE WS-FIELD-COUNT-ERR TO WS-RPT-COUNT.
|
|
STRING 'Field count errors: ' WS-RPT-COUNT
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
MOVE WS-TOT-QUOTE-ERR TO WS-RPT-COUNT.
|
|
STRING 'Quote errors: ' WS-RPT-COUNT
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
MOVE SPACES TO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
*> ------------------------
|
|
*> Batch Control Totals
|
|
*> ------------------------
|
|
MOVE '=== Batch Control Totals ===' TO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
MOVE WS-REC-COUNT TO WS-RPT-COUNT.
|
|
STRING 'Record count total: ' WS-RPT-COUNT
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
MOVE WS-HASH-FIELD1 TO WS-RPT-COUNT9.
|
|
STRING 'Hash total Field1: ' WS-RPT-COUNT9
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
MOVE WS-HASH-FIELD2 TO WS-RPT-COUNT9.
|
|
STRING 'Hash total Field2: ' WS-RPT-COUNT9
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
MOVE WS-HASH-FIELD3 TO WS-RPT-COUNT9.
|
|
STRING 'Hash total Field3: ' WS-RPT-COUNT9
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
MOVE WS-HASH-TOTAL TO WS-RPT-COUNT9.
|
|
STRING 'Combined hash total: ' WS-RPT-COUNT9
|
|
INTO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
MOVE SPACES TO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
*> Processing success rate
|
|
IF WS-LINE-COUNT > 0
|
|
COMPUTE WS-RPT-PCT ROUNDED =
|
|
(WS-REC-COUNT / WS-LINE-COUNT) * 100
|
|
STRING 'Processing success rate: '
|
|
WS-RPT-PCT '%'
|
|
INTO AUD-REC
|
|
WRITE AUD-REC
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: AUDIT-FILE status='
|
|
WS-AUDIT-STATUS
|
|
END-IF
|
|
END-IF.
|
|
|
|
MOVE SPACES TO AUD-REC.
|
|
WRITE AUD-REC.
|
|
|
|
*> Audit trailer
|
|
MOVE '=== End of CSV Audit Report ===' TO AUD-REC.
|
|
WRITE AUD-REC.
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WRITE ERROR: AUDIT-FILE status='
|
|
WS-AUDIT-STATUS
|
|
END-IF.
|
|
|
|
*> Close audit file with STATUS check
|
|
CLOSE AUDIT-FILE.
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' CLOSE ERROR: AUDIT-FILE status='
|
|
WS-AUDIT-STATUS
|
|
END-IF.
|
|
DISPLAY WS-TS-DISPLAY ' 5000-AUDIT: Audit file closed'.
|
|
|
|
*> ===== 6000-ERROR-HANDLE =====
|
|
6000-ERROR-HANDLE SECTION.
|
|
6000-START.
|
|
DISPLAY WS-TS-DISPLAY
|
|
' 6000-ERROR-HANDLE: Error summary'.
|
|
|
|
*> FILE-IN status summary
|
|
IF WS-FILE-IN-STATUS NOT = '00'
|
|
AND NOT = '10'
|
|
DISPLAY WS-TS-DISPLAY ' FILE-IN status: '
|
|
WS-FILE-IN-STATUS
|
|
ADD 1 TO WS-TOT-ERRORS
|
|
ELSE
|
|
DISPLAY WS-TS-DISPLAY ' FILE-IN status OK ('
|
|
WS-FILE-IN-STATUS ')'
|
|
END-IF.
|
|
|
|
*> FILE-OUT status summary
|
|
IF WS-FILE-OUT-STATUS NOT = '00'
|
|
AND NOT = '10'
|
|
DISPLAY WS-TS-DISPLAY ' FILE-OUT status: '
|
|
WS-FILE-OUT-STATUS
|
|
ADD 1 TO WS-TOT-ERRORS
|
|
ELSE
|
|
DISPLAY WS-TS-DISPLAY ' FILE-OUT status OK ('
|
|
WS-FILE-OUT-STATUS ')'
|
|
END-IF.
|
|
|
|
*> ERROR-REPORT status summary
|
|
IF WS-ERR-STATUS NOT = '00'
|
|
AND NOT = '10'
|
|
DISPLAY WS-TS-DISPLAY ' ERROR-REPORT status: '
|
|
WS-ERR-STATUS
|
|
ADD 1 TO WS-TOT-ERRORS
|
|
ELSE
|
|
DISPLAY WS-TS-DISPLAY ' ERROR-REPORT status OK ('
|
|
WS-ERR-STATUS ')'
|
|
END-IF.
|
|
|
|
*> AUDIT-FILE status summary
|
|
IF WS-AUDIT-STATUS NOT = '00'
|
|
AND NOT = '10'
|
|
DISPLAY WS-TS-DISPLAY ' AUDIT-FILE status: '
|
|
WS-AUDIT-STATUS
|
|
ADD 1 TO WS-TOT-ERRORS
|
|
ELSE
|
|
DISPLAY WS-TS-DISPLAY ' AUDIT-FILE status OK ('
|
|
WS-AUDIT-STATUS ')'
|
|
END-IF.
|
|
|
|
*> Error count summary with severity breakdown
|
|
DISPLAY WS-TS-DISPLAY ' Severity totals:'
|
|
MOVE WS-TOT-WARNINGS TO WS-RPT-COUNT9
|
|
DISPLAY ' Warnings: ' WS-RPT-COUNT9
|
|
MOVE WS-TOT-ERRORS TO WS-RPT-COUNT9
|
|
DISPLAY ' Errors: ' WS-RPT-COUNT9
|
|
MOVE WS-TOT-CRITICAL TO WS-RPT-COUNT9
|
|
DISPLAY ' Critical: ' WS-RPT-COUNT9.
|
|
|
|
*> Record count reconciliation check
|
|
IF WS-LINE-COUNT NOT = WS-REC-COUNT
|
|
DISPLAY WS-TS-DISPLAY
|
|
' WARNING: Line/output count mismatch'
|
|
MOVE 'N' TO WS-RECONCILE-OK
|
|
END-IF.
|
|
|
|
*> ===== 9000-EXIT =====
|
|
9000-EXIT SECTION.
|
|
9000-START.
|
|
DISPLAY WS-TS-DISPLAY
|
|
' 9000-EXIT: Program CsvFbNoLf completed'.
|
|
|
|
*> Final record counts display
|
|
MOVE WS-LINE-COUNT TO WS-RPT-COUNT.
|
|
MOVE WS-REC-COUNT TO WS-LINE-DISP.
|
|
DISPLAY ' Input lines: ' WS-RPT-COUNT.
|
|
MOVE WS-REC-COUNT TO WS-RPT-COUNT.
|
|
DISPLAY ' Output recs: ' WS-RPT-COUNT.
|
|
DISPLAY ' Reconcile: ' WS-RECONCILE-OK.
|
|
|
|
*> Error counts display
|
|
MOVE WS-MALFORMED-CNT TO WS-RPT-COUNT.
|
|
DISPLAY ' Malformed: ' WS-RPT-COUNT.
|
|
MOVE WS-TRUNC-CNT TO WS-RPT-COUNT.
|
|
DISPLAY ' Truncated: ' WS-RPT-COUNT.
|
|
MOVE WS-FIELD-COUNT-ERR TO WS-RPT-COUNT.
|
|
DISPLAY ' Field err: ' WS-RPT-COUNT.
|
|
|
|
*> Hash total display
|
|
MOVE WS-HASH-TOTAL TO WS-RPT-COUNT9.
|
|
DISPLAY ' Hash total: ' WS-RPT-COUNT9.
|
|
|
|
*> Output file listing
|
|
DISPLAY ' Output file: file-out.dat'.
|
|
DISPLAY ' Error report: csv-errors.dat'.
|
|
DISPLAY ' Audit report: csv-audit.dat'.
|
|
|
|
*> Close FILE-OUT with STATUS check
|
|
CLOSE FILE-OUT.
|
|
IF WS-FILE-OUT-STATUS NOT = '00'
|
|
DISPLAY WS-TS-DISPLAY
|
|
' CLOSE ERROR: FILE-OUT status='
|
|
WS-FILE-OUT-STATUS
|
|
END-IF.
|
|
DISPLAY WS-TS-DISPLAY ' FILE-OUT closed, status='
|
|
WS-FILE-OUT-STATUS.
|
|
|
|
*> Set return code based on reconciliation status
|
|
IF WS-RECONCILE-OK = 'N'
|
|
MOVE 4 TO RETURN-CODE
|
|
DISPLAY WS-TS-DISPLAY
|
|
' RETURN-CODE=4 (reconciliation mismatch)'
|
|
ELSE
|
|
MOVE 0 TO RETURN-CODE
|
|
DISPLAY WS-TS-DISPLAY
|
|
' RETURN-CODE=0 (normal completion)'
|
|
END-IF.
|
|
|
|
*> Terminate program
|
|
STOP RUN.
|
|
|
|
*> ===== PARSE-CSV-LINE (original logic, UNCHANGED) =====
|
|
PARSE-CSV-LINE.
|
|
MOVE SPACES TO WS-FIELDS.
|
|
MOVE 1 TO WS-POS.
|
|
MOVE 1 TO WS-FIELD-NUM.
|
|
MOVE 1 TO WS-CHAR-OFFSET.
|
|
MOVE 'N' TO WS-IN-QUOTE.
|
|
|
|
PERFORM VARYING WS-POS FROM 1 BY 1
|
|
UNTIL WS-POS > 200
|
|
OR WS-FIELD-NUM > 3
|
|
MOVE IN-LINE(WS-POS:1) TO WS-CHAR
|
|
IF WS-CHAR = '"'
|
|
IF WS-IN-QUOTE-YES
|
|
MOVE 'N' TO WS-IN-QUOTE
|
|
ELSE
|
|
MOVE 'Y' TO WS-IN-QUOTE
|
|
END-IF
|
|
ELSE
|
|
IF WS-CHAR = ',' AND NOT WS-IN-QUOTE-YES
|
|
ADD 1 TO WS-FIELD-NUM
|
|
MOVE 1 TO WS-CHAR-OFFSET
|
|
ELSE
|
|
IF WS-CHAR NOT = SPACE
|
|
OR WS-CHAR-OFFSET > 1
|
|
THEN
|
|
PERFORM SAVE-CHAR-TO-FIELD
|
|
END-IF
|
|
IF WS-CHAR-OFFSET < 30
|
|
ADD 1 TO WS-CHAR-OFFSET
|
|
END-IF
|
|
END-IF
|
|
END-IF
|
|
END-PERFORM.
|
|
|
|
*> ===== SAVE-CHAR-TO-FIELD (original, UNCHANGED) =====
|
|
SAVE-CHAR-TO-FIELD.
|
|
EVALUATE WS-FIELD-NUM
|
|
WHEN 1
|
|
MOVE WS-CHAR TO WS-FIELD1(WS-CHAR-OFFSET:1)
|
|
WHEN 2
|
|
MOVE WS-CHAR TO WS-FIELD2(WS-CHAR-OFFSET:1)
|
|
WHEN 3
|
|
MOVE WS-CHAR TO WS-FIELD3(WS-CHAR-OFFSET:1)
|
|
END-EVALUATE.
|
|
|
|
END PROGRAM CsvFbNoLf.
|