IDENTIFICATION DIVISION. PROGRAM-ID. CEPIS-CSV-NEXT. *> --------------------------------------------------------------------- *> Read one field of an RFC 4180 record. *> *> CALL "CEPIS-CSV-NEXT" USING CSV-TEXT CEPIS-CSV-SCAN *> *> Values from the batch endpoint contain commas -- "Rua Um, Dois" is an *> ordinary street name -- and are then double-quoted with "" for an *> embedded quote. Splitting on commas would shear those rows in two and *> shift every column after them, so this walks the quoting properly, *> newlines inside a quoted value included. *> --------------------------------------------------------------------- DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-C PIC X. 01 WS-DOUBLED PIC X. 01 CONST-QUOTE PIC X VALUE '"'. LINKAGE SECTION. 01 CSV-TEXT PIC X(262144). COPY "cepis-csv.cpy". PROCEDURE DIVISION USING CSV-TEXT CEPIS-CSV-SCAN. MAIN-START. MOVE SPACES TO CSV-FIELD MOVE 0 TO CSV-FIELD-LEN MOVE "N" TO CSV-ROW-END MOVE "N" TO CSV-EXHAUSTED IF CSV-POS > CSV-LEN MOVE "Y" TO CSV-EXHAUSTED MOVE "Y" TO CSV-ROW-END GOBACK END-IF IF CSV-TEXT(CSV-POS:1) = CONST-QUOTE PERFORM READ-QUOTED ELSE PERFORM READ-BARE END-IF PERFORM CLOSE-FIELD GOBACK. *> ------------------------------------------------------------------- READ-QUOTED. ADD 1 TO CSV-POS PERFORM UNTIL CSV-POS > CSV-LEN MOVE CSV-TEXT(CSV-POS:1) TO WS-C IF WS-C = CONST-QUOTE MOVE "N" TO WS-DOUBLED IF CSV-POS < CSV-LEN IF CSV-TEXT(CSV-POS + 1:1) = CONST-QUOTE MOVE "Y" TO WS-DOUBLED END-IF END-IF IF WS-DOUBLED = "Y" PERFORM APPEND-CHAR ADD 2 TO CSV-POS ELSE ADD 1 TO CSV-POS EXIT PERFORM END-IF ELSE PERFORM APPEND-CHAR ADD 1 TO CSV-POS END-IF END-PERFORM PERFORM UNTIL CSV-POS > CSV-LEN MOVE CSV-TEXT(CSV-POS:1) TO WS-C IF WS-C = "," OR WS-C = X"0D" OR WS-C = X"0A" EXIT PERFORM END-IF ADD 1 TO CSV-POS END-PERFORM. *> ------------------------------------------------------------------- READ-BARE. PERFORM UNTIL CSV-POS > CSV-LEN MOVE CSV-TEXT(CSV-POS:1) TO WS-C IF WS-C = "," OR WS-C = X"0D" OR WS-C = X"0A" EXIT PERFORM END-IF PERFORM APPEND-CHAR ADD 1 TO CSV-POS END-PERFORM. *> ------------------------------------------------------------------- CLOSE-FIELD. IF CSV-POS > CSV-LEN MOVE "Y" TO CSV-ROW-END EXIT PARAGRAPH END-IF MOVE CSV-TEXT(CSV-POS:1) TO WS-C EVALUATE TRUE WHEN WS-C = "," ADD 1 TO CSV-POS WHEN WS-C = X"0D" ADD 1 TO CSV-POS IF CSV-POS <= CSV-LEN IF CSV-TEXT(CSV-POS:1) = X"0A" ADD 1 TO CSV-POS END-IF END-IF MOVE "Y" TO CSV-ROW-END WHEN WS-C = X"0A" ADD 1 TO CSV-POS MOVE "Y" TO CSV-ROW-END WHEN OTHER ADD 1 TO CSV-POS END-EVALUATE. *> ------------------------------------------------------------------- APPEND-CHAR. IF CSV-FIELD-LEN < 512 ADD 1 TO CSV-FIELD-LEN MOVE WS-C TO CSV-FIELD(CSV-FIELD-LEN:1) END-IF. END PROGRAM CEPIS-CSV-NEXT.