For Programmers: Free Programming Magazines  


Home > Archive > Cobol > July 2006 > Program to validate delimiter count in VB file









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Program to validate delimiter count in VB file
sasquatch53@gmail.com

2006-07-12, 6:55 pm

I've written a program (with a lot of help) to validate the delimiter
counts in a Variable Blocked (VB) file on an os/390 MVS mainframe.

My problem is that I currently have to hard code in the maximum record
length of the input file(less 4 bytes) shown below as 32752. If I try
this program with a VB file that doesn't have an LRECL of 32756 then it
fails.

Do I have to do something to load the RDW from the input record into
the RDW in the working storage section? I want this program to work
with any VB file with different LRECLs without having to change the
program.

I'm very much a beginner with COBOL so any constructive feedback you
can give me would be appreciated. Thanks in advance.

IDENTIFICATION DIVISION.
PROGRAM-ID. VARSRCH.
INSTALLATION. IBM 370.
DATE-WRITTEN. JULY 11,2006.
DATE-COMPILED.
SECURITY. RACF.
****************************************
***********************
* Author: Timothy D. Lindsey
* Description: This program validates the number of delimiters
* in a variable blocked file on the mainframe. Records that
* pass the test are output to FILE-OUT and records that
* do not pass are output to FIL-ERR.
* Inputs: Parameters are passed in via SYSIN in the following
* format. The SYSIN record is 80 characters long. I'm
* showing it with HEX turned on so you can see the
* delimiter value in HEX.
* ----+----1----+----2----+----3----+----4----+----5
* DELIMITERCODE=.,DELIMITERCOUNT=005
* CCDCDCECDCDCC726CCDCDCECDCDEDE7FFF444444
4444444444
* 4539493593645EFB45394935936453E005000000
0000000000
****************************************
***********************
EJECT

ENVIRONMENT DIVISION.
CONFIGURATION SECTION.

INPUT-OUTPUT SECTION.
FILE-CONTROL.

*-------------- INPUT FILE ------------------------------------
SELECT FILE-IN ASSIGN TO UT-S-FILEIN.

*-------------- OUTPUT FILE -----------------------------------
SELECT FILE-OUT ASSIGN TO UT-S-FILEOUT.
SELECT FILE-ERR ASSIGN TO UT-S-FILEERR.


DATA DIVISION.
FILE SECTION.

FD FILE-IN
LABEL RECORDS ARE STANDARD
BLOCK CONTAINS 0 RECORDS
RECORD IS VARYING FROM 1 TO 32752 CHARACTERS
DEPENDING ON RDW
RECORDING MODE IS V
DATA RECORD IS FILE-IN-RECORD.

01 FILE-IN-RECORD.
05 FILLER OCCURS 1 TO 32752
DEPENDING ON RDW PIC X(01).


FD FILE-OUT
LABEL RECORDS ARE STANDARD
BLOCK CONTAINS 0 RECORDS
RECORD IS VARYING FROM 1 TO 32752 CHARACTERS
DEPENDING ON RDW
RECORDING MODE IS V
DATA RECORD IS FILE-OUT-RECORD.

01 FILE-OUT-RECORD.
05 FILLER OCCURS 1 TO 32752
DEPENDING ON RDW PIC X(01).

FD FILE-ERR
LABEL RECORDS ARE STANDARD
BLOCK CONTAINS 0 RECORDS
RECORD IS VARYING FROM 1 TO 32752 CHARACTERS
DEPENDING ON RDW
RECORDING MODE IS V
DATA RECORD IS FILE-ERR-RECORD.

01 FILE-ERR-RECORD.
05 FILLER OCCURS 1 TO 32752
DEPENDING ON RDW PIC X(01).

EJECT
****************************************
*******************
WORKING-STORAGE SECTION.

01 FILLER PIC X(33) VALUE
'** WORKING STORAGE BEGINS HERE **'.

****************************************
*******************

EJECT
****************************************
*******************
01 RDW PIC 9(4) COMP.
****************************************
*******************
01 SWITCHES.
05 INPUT-EOF-SW PIC X(01) VALUE 'N'.
88 INPUT-EOF VALUE 'Y'.
****************************************
*******************

01 WS-PARM-DATA.
05 FILLER PIC X(14).
05 WS-DELIMITER PIC X(01).
05 FILLER PIC X(16).
05 WS-DELIMITER-CNT PIC 9(03).
05 FILLER PIC X(46).

****************************************
*******************
01 FILLER PIC X(33) VALUE
'** MISCELLANEOUS BEGINS HERE =>'.

01 MISCELLAEOUS-AREA.
05 NUM-OF-DELIM PIC 9(04).

EJECT
****************************************
*******************
* HOLD INPUT AREA.
****************************************
*******************
****************************************
*******************
* COUNTERS ARE KEPT FOR STATISTICS, AUDIT, AND TRENDING
* PURPOSES.
****************************************
*******************

01 PROCESS-COUNTERS.
05 RECS-IN PIC S9(9) COMP VALUE ZERO.
05 OUT-RECS PIC S9(9) COMP VALUE ZERO.
05 ERR-RECS PIC S9(9) COMP VALUE ZERO.

EJECT
PROCEDURE DIVISION.
****************************************
*******************
*
****************************************
*******************

0000-MAINLINE.
****************************************
*******************
* MAIN PROCESSING SEQUENCE.
****************************************
*******************
DISPLAY '=========== VARSRCH STARTING ============'.

PERFORM 1000-INITIALIZE.

PERFORM 2000-PROCESS-INPUT
UNTIL INPUT-EOF.

PERFORM 9900-DONE.


EJECT
1000-INITIALIZE.
****************************************
*******************
* INITIALIZE WS AND READ FIRST RECORD
****************************************
*******************


MOVE 'N' TO INPUT-EOF-SW.

OPEN INPUT FILE-IN.
OPEN OUTPUT FILE-OUT
FILE-ERR.

ACCEPT WS-PARM-DATA.

PERFORM 8000-READ-INPUT.

IF INPUT-EOF
DISPLAY 'INPUT FILE EMPTY'
END-IF.



EJECT
2000-PROCESS-INPUT.
****************************************
*******************
* PROCESS RECORDS.
****************************************
*******************

MOVE 0 TO NUM-OF-DELIM.

INSPECT FILE-IN-RECORD
TALLYING NUM-OF-DELIM
FOR ALL WS-DELIMITER.


IF NUM-OF-DELIM = WS-DELIMITER-CNT
PERFORM 8100-WRITE-OK-RECORD
ELSE
PERFORM 8200-WRITE-ERR-RECORD
END-IF.

PERFORM 8000-READ-INPUT.

8000-READ-INPUT.
****************************************
*******************
* READ INPUT RECORDS
****************************************
*******************

MOVE SPACES TO FILE-IN-RECORD.

READ FILE-IN
AT END
MOVE 'Y' TO INPUT-EOF-SW
NOT AT END
ADD +1 TO RECS-IN
END-READ.


8100-WRITE-OK-RECORD.
****************************************
*******************
* WRITE OUT THE GOOD RECORDS
****************************************
*******************

MOVE FILE-IN-RECORD TO FILE-OUT-RECORD.

WRITE FILE-OUT-RECORD.
ADD +1 TO OUT-RECS.


8200-WRITE-ERR-RECORD.
****************************************
*******************
* WRITE OUT THE BAD RECORDS
****************************************
*******************

MOVE FILE-IN-RECORD TO FILE-ERR-RECORD.

WRITE FILE-ERR-RECORD.
ADD +1 TO ERR-RECS.


9900-DONE.
****************************************
*******************
* PROGRAM WRAP UP.
****************************************
*******************

CLOSE FILE-IN
FILE-OUT.

DISPLAY 'INPUT RECORDS: ' RECS-IN.
DISPLAY 'GOOD RECORDS: ' OUT-RECS.
DISPLAY 'ERRORS FOUND: ' ERR-RECS.


GOBACK.

Richard

2006-07-12, 6:55 pm


sasquatch53@gmail.com wrote:

> RECORD IS VARYING FROM 1 TO 32752 CHARACTERS
> DEPENDING ON RDW


> 01 RDW PIC 9(4) COMP.


32752 is a 5 digit number. RDW is a 4 digit variable. This may work,
or it may not depending on compiler options and how you use the
variable.

> MOVE 0 TO NUM-OF-DELIM.
>
> INSPECT FILE-IN-RECORD
> TALLYING NUM-OF-DELIM
> FOR ALL WS-DELIMITER.


I find with delimited files that I have to deal with that there is
often some mechanism for 'escape'. For example in comma delimited the
text fields are quoted and a comma within the field is not a delimiter.
So:

12345,"42, Commerce St.,","Main City,","Somewhere.",245.00

has 4 delimiters and 3 commas within the fields.

William M. Klein

2006-07-12, 6:55 pm

COBOL checks for "fixed file attribute conflicts" (FS=39) at OPEN. Although
each vendor may determine what to check, IBM *does* check that the "max" in the
program matches the DCB in the program. You *might* get around this using
FORMAT U - but I don't recommend it and it probably won't work.

Bottom-Line:
(IBM mainframe) COBOL is NOT intended to function well for files whose
attributes are not known at compile time.

--
Bill Klein
wmklein <at> ix.netcom.com
<sasquatch53@gmail.com> wrote in message
news:1152717242.754256.101030@75g2000cwc.googlegroups.com...
> I've written a program (with a lot of help) to validate the delimiter
> counts in a Variable Blocked (VB) file on an os/390 MVS mainframe.
>
> My problem is that I currently have to hard code in the maximum record
> length of the input file(less 4 bytes) shown below as 32752. If I try
> this program with a VB file that doesn't have an LRECL of 32756 then it
> fails.
>
> Do I have to do something to load the RDW from the input record into
> the RDW in the working storage section? I want this program to work
> with any VB file with different LRECLs without having to change the
> program.
>
> I'm very much a beginner with COBOL so any constructive feedback you
> can give me would be appreciated. Thanks in advance.
>
> IDENTIFICATION DIVISION.
> PROGRAM-ID. VARSRCH.
> INSTALLATION. IBM 370.
> DATE-WRITTEN. JULY 11,2006.
> DATE-COMPILED.
> SECURITY. RACF.
> ****************************************
***********************
> * Author: Timothy D. Lindsey
> * Description: This program validates the number of delimiters
> * in a variable blocked file on the mainframe. Records that
> * pass the test are output to FILE-OUT and records that
> * do not pass are output to FIL-ERR.
> * Inputs: Parameters are passed in via SYSIN in the following
> * format. The SYSIN record is 80 characters long. I'm
> * showing it with HEX turned on so you can see the
> * delimiter value in HEX.
> * ----+----1----+----2----+----3----+----4----+----5
> * DELIMITERCODE=.,DELIMITERCOUNT=005
> * CCDCDCECDCDCC726CCDCDCECDCDEDE7FFF444444
4444444444
> * 4539493593645EFB45394935936453E005000000
0000000000
> ****************************************
***********************
> EJECT
>
> ENVIRONMENT DIVISION.
> CONFIGURATION SECTION.
>
> INPUT-OUTPUT SECTION.
> FILE-CONTROL.
>
> *-------------- INPUT FILE ------------------------------------
> SELECT FILE-IN ASSIGN TO UT-S-FILEIN.
>
> *-------------- OUTPUT FILE -----------------------------------
> SELECT FILE-OUT ASSIGN TO UT-S-FILEOUT.
> SELECT FILE-ERR ASSIGN TO UT-S-FILEERR.
>
>
> DATA DIVISION.
> FILE SECTION.
>
> FD FILE-IN
> LABEL RECORDS ARE STANDARD
> BLOCK CONTAINS 0 RECORDS
> RECORD IS VARYING FROM 1 TO 32752 CHARACTERS
> DEPENDING ON RDW
> RECORDING MODE IS V
> DATA RECORD IS FILE-IN-RECORD.
>
> 01 FILE-IN-RECORD.
> 05 FILLER OCCURS 1 TO 32752
> DEPENDING ON RDW PIC X(01).
>
>
> FD FILE-OUT
> LABEL RECORDS ARE STANDARD
> BLOCK CONTAINS 0 RECORDS
> RECORD IS VARYING FROM 1 TO 32752 CHARACTERS
> DEPENDING ON RDW
> RECORDING MODE IS V
> DATA RECORD IS FILE-OUT-RECORD.
>
> 01 FILE-OUT-RECORD.
> 05 FILLER OCCURS 1 TO 32752
> DEPENDING ON RDW PIC X(01).
>
> FD FILE-ERR
> LABEL RECORDS ARE STANDARD
> BLOCK CONTAINS 0 RECORDS
> RECORD IS VARYING FROM 1 TO 32752 CHARACTERS
> DEPENDING ON RDW
> RECORDING MODE IS V
> DATA RECORD IS FILE-ERR-RECORD.
>
> 01 FILE-ERR-RECORD.
> 05 FILLER OCCURS 1 TO 32752
> DEPENDING ON RDW PIC X(01).
>
> EJECT
> ****************************************
*******************
> WORKING-STORAGE SECTION.
>
> 01 FILLER PIC X(33) VALUE
> '** WORKING STORAGE BEGINS HERE **'.
>
> ****************************************
*******************
>
> EJECT
> ****************************************
*******************
> 01 RDW PIC 9(4) COMP.
> ****************************************
*******************
> 01 SWITCHES.
> 05 INPUT-EOF-SW PIC X(01) VALUE 'N'.
> 88 INPUT-EOF VALUE 'Y'.
> ****************************************
*******************
>
> 01 WS-PARM-DATA.
> 05 FILLER PIC X(14).
> 05 WS-DELIMITER PIC X(01).
> 05 FILLER PIC X(16).
> 05 WS-DELIMITER-CNT PIC 9(03).
> 05 FILLER PIC X(46).
>
> ****************************************
*******************
> 01 FILLER PIC X(33) VALUE
> '** MISCELLANEOUS BEGINS HERE =>'.
>
> 01 MISCELLAEOUS-AREA.
> 05 NUM-OF-DELIM PIC 9(04).
>
> EJECT
> ****************************************
*******************
> * HOLD INPUT AREA.
> ****************************************
*******************
> ****************************************
*******************
> * COUNTERS ARE KEPT FOR STATISTICS, AUDIT, AND TRENDING
> * PURPOSES.
> ****************************************
*******************
>
> 01 PROCESS-COUNTERS.
> 05 RECS-IN PIC S9(9) COMP VALUE ZERO.
> 05 OUT-RECS PIC S9(9) COMP VALUE ZERO.
> 05 ERR-RECS PIC S9(9) COMP VALUE ZERO.
>
> EJECT
> PROCEDURE DIVISION.
> ****************************************
*******************
> *
> ****************************************
*******************
>
> 0000-MAINLINE.
> ****************************************
*******************
> * MAIN PROCESSING SEQUENCE.
> ****************************************
*******************
> DISPLAY '=========== VARSRCH STARTING ============'.
>
> PERFORM 1000-INITIALIZE.
>
> PERFORM 2000-PROCESS-INPUT
> UNTIL INPUT-EOF.
>
> PERFORM 9900-DONE.
>
>
> EJECT
> 1000-INITIALIZE.
> ****************************************
*******************
> * INITIALIZE WS AND READ FIRST RECORD
> ****************************************
*******************
>
>
> MOVE 'N' TO INPUT-EOF-SW.
>
> OPEN INPUT FILE-IN.
> OPEN OUTPUT FILE-OUT
> FILE-ERR.
>
> ACCEPT WS-PARM-DATA.
>
> PERFORM 8000-READ-INPUT.
>
> IF INPUT-EOF
> DISPLAY 'INPUT FILE EMPTY'
> END-IF.
>
>
>
> EJECT
> 2000-PROCESS-INPUT.
> ****************************************
*******************
> * PROCESS RECORDS.
> ****************************************
*******************
>
> MOVE 0 TO NUM-OF-DELIM.
>
> INSPECT FILE-IN-RECORD
> TALLYING NUM-OF-DELIM
> FOR ALL WS-DELIMITER.
>
>
> IF NUM-OF-DELIM = WS-DELIMITER-CNT
> PERFORM 8100-WRITE-OK-RECORD
> ELSE
> PERFORM 8200-WRITE-ERR-RECORD
> END-IF.
>
> PERFORM 8000-READ-INPUT.
>
> 8000-READ-INPUT.
> ****************************************
*******************
> * READ INPUT RECORDS
> ****************************************
*******************
>
> MOVE SPACES TO FILE-IN-RECORD.
>
> READ FILE-IN
> AT END
> MOVE 'Y' TO INPUT-EOF-SW
> NOT AT END
> ADD +1 TO RECS-IN
> END-READ.
>
>
> 8100-WRITE-OK-RECORD.
> ****************************************
*******************
> * WRITE OUT THE GOOD RECORDS
> ****************************************
*******************
>
> MOVE FILE-IN-RECORD TO FILE-OUT-RECORD.
>
> WRITE FILE-OUT-RECORD.
> ADD +1 TO OUT-RECS.
>
>
> 8200-WRITE-ERR-RECORD.
> ****************************************
*******************
> * WRITE OUT THE BAD RECORDS
> ****************************************
*******************
>
> MOVE FILE-IN-RECORD TO FILE-ERR-RECORD.
>
> WRITE FILE-ERR-RECORD.
> ADD +1 TO ERR-RECS.
>
>
> 9900-DONE.
> ****************************************
*******************
> * PROGRAM WRAP UP.
> ****************************************
*******************
>
> CLOSE FILE-IN
> FILE-OUT.
>
> DISPLAY 'INPUT RECORDS: ' RECS-IN.
> DISPLAY 'GOOD RECORDS: ' OUT-RECS.
> DISPLAY 'ERRORS FOUND: ' ERR-RECS.
>
>
> GOBACK.
>



Howard Brazee

2006-07-12, 6:55 pm

On Wed, 12 Jul 2006 20:22:46 GMT, "William M. Klein"
<wmklein@nospam.netcom.com> wrote:

>COBOL checks for "fixed file attribute conflicts" (FS=39) at OPEN. Although
>each vendor may determine what to check, IBM *does* check that the "max" in the
>program matches the DCB in the program. You *might* get around this using
>FORMAT U - but I don't recommend it and it probably won't work.
>
>Bottom-Line:
> (IBM mainframe) COBOL is NOT intended to function well for files whose
>attributes are not known at compile time.


However, there are utilities that can copy data into files whose
attributes are known.
James J. Gavan

2006-07-12, 6:55 pm

sasquatch53@gmail.com wrote:
> I've written a program (with a lot of help) to validate the delimiter
> counts in a Variable Blocked (VB) file on an os/390 MVS mainframe.
>
> My problem is that I currently have to hard code in the maximum record
> length of the input file(less 4 bytes) shown below as 32752. If I try
> this program with a VB file that doesn't have an LRECL of 32756 then it
> fails.
>
> Do I have to do something to load the RDW from the input record into
> the RDW in the working storage section? I want this program to work
> with any VB file with different LRECLs without having to change the
> program.
>
> I'm very much a beginner with COBOL so any constructive feedback you
> can give me would be appreciated. Thanks in advance.


OK so it's mainframe and presumably via JCL (?) you are picking up
filenames with your UT-S-FILEIN, etc. (???).

Problem #1 that file sizing. Perhaps Howard has offered best solution -
look for utilities that will read in byte-stream files.

(Just as background, M/F Net Express has it's own byte-stream routines
using their own CBL_READ_FILE routines etc... which allows you to read
in the file as individual chunks, or one huge chunk, subject to memory
availability).

So can you search out a utility which will let you read in an 'alien'
file. That then poses some questions :-

A- The INPUT FILE

1 - Fixed records and what length - here I'm referring to the data
records contained in your BLOCK (32752). Is each separate data record
preceded by its own individual record length, or can you establish
individual record lengths from the known input file before you start.

2. Variation on # 1 which is what you were after - Variable length
records (not the BLOCK). Can you recognize those from a preceding record
length or a 'Record Type' contained in a field of each input record.

B - RECORD VALIDATION

Reading through the program, unless I've misunderstood, It seems that
all you are doing is counting Delimiters PER BLOCK and not per
individual record. Then you are writing out 'Good Blocks" and 'Error
Blocks'. So even if you read in and validate you aren't much further
ahead - you still have to read again your 'Good Records' and re-format.
As your Delimiter input-count appears to be per BLOCK, no doubt you will
come up with an error on the final BLOCK.

C - SEARCHING YOUR BLOCK

It seems to me you have to do the following, which is parallel to what I
would have to do do with the M/F CBL_FILE routines. For the sake of
discussion assume the following input for a BLOCK with comma delimiters :-

AAA,BBBB,CCC,DDDDDD,EEEE,FFFF, Length = 30 Delimiters = 6
GGG,BBBB,DDD,HHHHHH,KKKK,LLLL,

From your input parameters you know the filename and record format, and
you can specify the field-count :-

01 MyInput-Record.
05 Field-1 pic x(03).
05 filler pic x(01).
05 Field-2 pic x(04).
05 filler pic x(01).
05 Field-3 pic x(03).
05 filler pic x(01).
05 Field-4 pic x(06).
05 filler pic x(01).
05 Field-5 pic x(04).
05 filler pic x(01).
05 Field-6 pic x(04).
05 filler pic x(01).

a) If you have a preceding record length indicator then you could check
for correct length - the final comma after Field-6. The very first
record will be positioned as follows :-

with included recLength - 0030,AAA,BBBB,CCC,DDDDDD,EEEE,FFFF,
1 6 34

without reclength - AAA,BBBB,CCC,DDDDDD,EEEE,FFFF,
1 30

Whichever choice, you have to keep 'pointers' (position markers) for the
start and end of your individual records. Then you increment these
pointers as you move forward within your block to get the next data record.

Taking that sample I did then you can move Data-Block(6:34) or (1:30) to
ws-Record and do your Delimiter check.

Now that you have Record 1 in ws-Record you could now use MOVE
CORR(esponding) into the output record you want, dropping the delimiters :

01 Good-Output-Record. (either ISAM or Sequential)
05 Field-1 pic x(03).
05 Field-2 pic x(04).
05 Field-3 pic x(03).
05 Field-4 pic x(06).
05 Field-5 pic x(04).
05 Field-6 pic x(04).

MOVE CORR MyInput-Record to Good-Output-Record
write Good-Output-Record

Note I've dropped the fillers (delimiters) and using the common
field-names the output fields could even be in a REVERSE or MIXED
sequence - the MOVE puts each of your input fields into its
corresponding output-field. There are some problems with MOVE CORR
relating to the OCCURS clause, so check out your Language Reference
Manual for caveats.

BAD Records -

I'd be inclined to get rid of non-displayable delimiters, by replacing
them with a Tilde (~) - not likely the input file uses that character.

INSPECT ws-Record replacing all (MyDelimier) by "~".

Now you should be able to display Bad Records in something like Notepad
etc. (Don't know if you have LINE SEQUENTIAL with IBM - but that would
be your best bet).

Above is obviously not the whole story and depends in great part on your
inputs, how many different formats, frequencies etc - and how much time
you want to put into generalizing the routines.

Sing out if you are half-interested and want further clarification.
(That's assuming somebody doesn't blow my suggestions out of the water
:-) ). Somebody may well say there is an advantage using UNSTRING - but
without additional detail from you, I tend to favour MOVE CORR on this one.

Jimmy


>
> IDENTIFICATION DIVISION.
> PROGRAM-ID. VARSRCH.
> INSTALLATION. IBM 370.
> DATE-WRITTEN. JULY 11,2006.
> DATE-COMPILED.
> SECURITY. RACF.
> ****************************************
***********************
> * Author: Timothy D. Lindsey
> * Description: This program validates the number of delimiters
> * in a variable blocked file on the mainframe. Records that
> * pass the test are output to FILE-OUT and records that
> * do not pass are output to FIL-ERR.
> * Inputs: Parameters are passed in via SYSIN in the following
> * format. The SYSIN record is 80 characters long. I'm
> * showing it with HEX turned on so you can see the
> * delimiter value in HEX.
> * ----+----1----+----2----+----3----+----4----+----5
> * DELIMITERCODE=.,DELIMITERCOUNT=005
> * CCDCDCECDCDCC726CCDCDCECDCDEDE7FFF444444
4444444444
> * 4539493593645EFB45394935936453E005000000
0000000000
> ****************************************
***********************
> EJECT
>
> ENVIRONMENT DIVISION.
> CONFIGURATION SECTION.
>
> INPUT-OUTPUT SECTION.
> FILE-CONTROL.
>
> *-------------- INPUT FILE ------------------------------------
> SELECT FILE-IN ASSIGN TO UT-S-FILEIN.
>
> *-------------- OUTPUT FILE -----------------------------------
> SELECT FILE-OUT ASSIGN TO UT-S-FILEOUT.
> SELECT FILE-ERR ASSIGN TO UT-S-FILEERR.
>
>
> DATA DIVISION.
> FILE SECTION.
>
> FD FILE-IN
> LABEL RECORDS ARE STANDARD
> BLOCK CONTAINS 0 RECORDS
> RECORD IS VARYING FROM 1 TO 32752 CHARACTERS
> DEPENDING ON RDW
> RECORDING MODE IS V
> DATA RECORD IS FILE-IN-RECORD.
>
> 01 FILE-IN-RECORD.
> 05 FILLER OCCURS 1 TO 32752
> DEPENDING ON RDW PIC X(01).
>
>
> FD FILE-OUT
> LABEL RECORDS ARE STANDARD
> BLOCK CONTAINS 0 RECORDS
> RECORD IS VARYING FROM 1 TO 32752 CHARACTERS
> DEPENDING ON RDW
> RECORDING MODE IS V
> DATA RECORD IS FILE-OUT-RECORD.
>
> 01 FILE-OUT-RECORD.
> 05 FILLER OCCURS 1 TO 32752
> DEPENDING ON RDW PIC X(01).
>
> FD FILE-ERR
> LABEL RECORDS ARE STANDARD
> BLOCK CONTAINS 0 RECORDS
> RECORD IS VARYING FROM 1 TO 32752 CHARACTERS
> DEPENDING ON RDW
> RECORDING MODE IS V
> DATA RECORD IS FILE-ERR-RECORD.
>
> 01 FILE-ERR-RECORD.
> 05 FILLER OCCURS 1 TO 32752
> DEPENDING ON RDW PIC X(01).
>
> EJECT
> ****************************************
*******************
> WORKING-STORAGE SECTION.
>
> 01 FILLER PIC X(33) VALUE
> '** WORKING STORAGE BEGINS HERE **'.
>
> ****************************************
*******************
>
> EJECT
> ****************************************
*******************
> 01 RDW PIC 9(4) COMP.
> ****************************************
*******************
> 01 SWITCHES.
> 05 INPUT-EOF-SW PIC X(01) VALUE 'N'.
> 88 INPUT-EOF VALUE 'Y'.
> ****************************************
*******************
>
> 01 WS-PARM-DATA.
> 05 FILLER PIC X(14).
> 05 WS-DELIMITER PIC X(01).
> 05 FILLER PIC X(16).
> 05 WS-DELIMITER-CNT PIC 9(03).
> 05 FILLER PIC X(46).
>
> ****************************************
*******************
> 01 FILLER PIC X(33) VALUE
> '** MISCELLANEOUS BEGINS HERE =>'.
>
> 01 MISCELLAEOUS-AREA.
> 05 NUM-OF-DELIM PIC 9(04).
>
> EJECT
> ****************************************
*******************
> * HOLD INPUT AREA.
> ****************************************
*******************
> ****************************************
*******************
> * COUNTERS ARE KEPT FOR STATISTICS, AUDIT, AND TRENDING
> * PURPOSES.
> ****************************************
*******************
>
> 01 PROCESS-COUNTERS.
> 05 RECS-IN PIC S9(9) COMP VALUE ZERO.
> 05 OUT-RECS PIC S9(9) COMP VALUE ZERO.
> 05 ERR-RECS PIC S9(9) COMP VALUE ZERO.
>
> EJECT
> PROCEDURE DIVISION.
> ****************************************
*******************
> *
> ****************************************
*******************
>
> 0000-MAINLINE.
> ****************************************
*******************
> * MAIN PROCESSING SEQUENCE.
> ****************************************
*******************
> DISPLAY '=========== VARSRCH STARTING ============'.
>
> PERFORM 1000-INITIALIZE.
>
> PERFORM 2000-PROCESS-INPUT
> UNTIL INPUT-EOF.
>
> PERFORM 9900-DONE.
>
>
> EJECT
> 1000-INITIALIZE.
> ****************************************
*******************
> * INITIALIZE WS AND READ FIRST RECORD
> ****************************************
*******************
>
>
> MOVE 'N' TO INPUT-EOF-SW.
>
> OPEN INPUT FILE-IN.
> OPEN OUTPUT FILE-OUT
> FILE-ERR.
>
> ACCEPT WS-PARM-DATA.
>
> PERFORM 8000-READ-INPUT.
>
> IF INPUT-EOF
> DISPLAY 'INPUT FILE EMPTY'
> END-IF.
>
>
>
> EJECT
> 2000-PROCESS-INPUT.
> ****************************************
*******************
> * PROCESS RECORDS.
> ****************************************
*******************
>
> MOVE 0 TO NUM-OF-DELIM.
>
> INSPECT FILE-IN-RECORD
> TALLYING NUM-OF-DELIM
> FOR ALL WS-DELIMITER.
>
>
> IF NUM-OF-DELIM = WS-DELIMITER-CNT
> PERFORM 8100-WRITE-OK-RECORD
> ELSE
> PERFORM 8200-WRITE-ERR-RECORD
> END-IF.
>
> PERFORM 8000-READ-INPUT.
>
> 8000-READ-INPUT.
> ****************************************
*******************
> * READ INPUT RECORDS
> ****************************************
*******************
>
> MOVE SPACES TO FILE-IN-RECORD.
>
> READ FILE-IN
> AT END
> MOVE 'Y' TO INPUT-EOF-SW
> NOT AT END
> ADD +1 TO RECS-IN
> END-READ.
>
>
> 8100-WRITE-OK-RECORD.
> ****************************************
*******************
> * WRITE OUT THE GOOD RECORDS
> ****************************************
*******************
>
> MOVE FILE-IN-RECORD TO FILE-OUT-RECORD.
>
> WRITE FILE-OUT-RECORD.
> ADD +1 TO OUT-RECS.
>
>
> 8200-WRITE-ERR-RECORD.
> ****************************************
*******************
> * WRITE OUT THE BAD RECORDS
> ****************************************
*******************
>
> MOVE FILE-IN-RECORD TO FILE-ERR-RECORD.
>
> WRITE FILE-ERR-RECORD.
> ADD +1 TO ERR-RECS.
>
>
> 9900-DONE.
> ****************************************
*******************
> * PROGRAM WRAP UP.
> ****************************************
*******************
>
> CLOSE FILE-IN
> FILE-OUT.
>
> DISPLAY 'INPUT RECORDS: ' RECS-IN.
> DISPLAY 'GOOD RECORDS: ' OUT-RECS.
> DISPLAY 'ERRORS FOUND: ' ERR-RECS.
>
>
> GOBACK.
>

Robert Jones

2006-07-13, 6:55 pm

message snipped

My memory is a bit porous, but I think that you can cheat a bit by just
specifying the maximum allowable LRECL in the JCL and program (that in
the JCL is 4 bytes more to allow for the RDW - record descriptor word).
You should then be able to read any variable length file, even if that
wasn't it's original maximum length. Similarly for writing, when so
long as you only write records of the desired length, the maximum size
is just academic.

Another other option is to write a set of small assembler subprograms
just to read and write QSAM records that can be of any record format or
length within the system limits. You might be able to persuade you
friendly systems programmer to assist you with this or buy an assember
book to point you in the desired direction. You might find that the IBM
manuals and redbooks for HLASM (High Level Assember), which are free
downloads, would provide sufficient information..

Robert

sasquatch53@gmail.com

2006-07-14, 6:55 pm

Ok, here is the solution.
My co-worker that provided me with most of the code, Joe Leeds,
suggested I concatinate a dummy dataset containing no records before
the input file in the JCL. This dummy dataset is allocated at the
maximum LRECL defined in the COBOL program plus 4 bytes.
I tested it and it works great. The regular input files in the JCL can
be any length as long as it is less than the LRECL defined in the COBOL
program.
This essentially "fools" the program into thinking that the LRECL is
the same for all files even though it is not. The output file would
have the same LRECL as the dummy input file.
This answers Bill Klein's concern that "IBM mainframe COBOL is NOT
intended to function well for files whose attributes are not known at
compile time".
Thanks to James J. Gaven for his idea to convert the incoming delimiter
to a tilde "~" for readability in the rejected records.
Thanks to all of you who replied to my post.


//X JOB (XXXXXX),'VALIDATE DELIMITERS', PRTY=9,CLASS=A
//*
//JOBLIB DD DSN=ACRO.COBOL.OBJECT.CNTL,DISP=SHR
//*
//* ========================================
==========================
//* THIS PROGRAM VALIATES THE DELIMITER COUNT IN A VARIABLE LENGTH
//* FILE AND OUTPUTS MATCHING AND NON-MATCHING RECORDS TO DIFFERENT
//* OUTPUTS.
//* THE DELIMITER VALUE AND TARGET DELIMITER COUNT ARE PASSED IN VIA
//* THE SYSIN DATASET.
//* THE INPUT FILES CAN BE ANY LRECL AS LONG AS THEY ARE LESS THAN
//* OR EQUAL TO THE LRECL OF THE DUMMY FILE.
//* THE DUMMY FILE LRECL MUST EQUAL THE LRECL OF THE INPUT FILE
//* DEFINED IN THE COBOL PROGRAM PLUS FOUR BYTES.
//* DELIMITER VALUES IN THE RECORDS OUTPUT TO FILEERR ARE CONVERTED
//* TO A TILDE VALUE "~" FOR READABILTY.
//* ========================================
==========================
//* -----------------------------------------------------------------
//* DELETE DATASETS IF THEY EXIST AND DO NOTHING IF THEY DO NOT
//* -----------------------------------------------------------------
//P010 EXEC PGM=IEFBR14
//DD1 DD DSN=MYUSERID.DELIM.GOOD.DATA,
// SPACE=(TRK,(250,25),RLSE),
// DCB=(RECFM=FB,LRECL=80),
// DISP=(MOD,DELETE),UNIT=SYSDA
//DD2 DD DSN=MYUSERID.DELIM.BAD.DATA,
// SPACE=(TRK,(250,25),RLSE),
// DCB=(RECFM=FB,LRECL=80),
// DISP=(MOD,DELETE),UNIT=SYSDA
//*
//* ------------------------------------------------------------------
//* VALIDATE THE DELIMITER COUNT IN THE INCOMING RECORD.
//* OUTPUT RECORDS THAT MATCH THE TARGET COUNT TO FILEOUT AND RECORDS
//* THAT DO NOT MATCH THE TARGET COUNT TO FILEERR.
//* THE DELIMITER VALUE IN THE SYSIN IS A HEX 2F AND APPEARS BLANK.
//* ------------------------------------------------------------------
//P020 EXEC PGM=VALDLMVB,REGION=4M,TIME=20,ACCT=EXCP

//* FILEIN DCB PARAMETERS OF DUMMY FILE = RECFM=VB,LRECL=9004
//FILEIN DD DSN=MYUSERID.INPUT.DATA.DUMMY,DISP=SHR
// DD DSN=MYUSERID.INPUT.DATA,DISP=SHR
//FILEOUT DD DSN=MYUSERID.DELIM.GOOD.DATA,
// DISP=(,CATLG,DELETE),
// SPACE=(TRK,(750,75),RLSE),UNIT=SYSWK
//FILEERR DD DSN=MYUSERID.DELIM.BAD.DATA,
// DISP=(,CATLG,DELETE),
// SPACE=(TRK,(750,75),RLSE),UNIT=SYSWK
//SYSIN DD *
DELIMITERCODE= ,DELIMITERCOUNT=005
//SYSOUT DD SYSOUT=A
//SYSPRINT DD SYSOUT=A
//SYSABOUT DD SYSOUT=A
//SYSDBOUT DD SYSOUT=A
//SYSUDUMP DD SYSOUT=A


Here is the COBOL program.

IDENTIFICATION DIVISION.
PROGRAM-ID. VALDLMVB.
INSTALLATION. IBM 390.
DATE-WRITTEN. JULY 11,2006.
DATE-COMPILED.
SECURITY. RACF.
****************************************
***********************
* Author: Joe Leeds and Timothy D. Lindsey
* Description: This program validates the delimiter count
* in a variable length file on the IBM mainframe. Records
* that match the target count are output to FILE-OUT and
* records that do not match are output to FIL-ERR.
* The input files can be any LRECL as long as they are less
* than or equal to the LRECL of the dummy file.
* The dummy file LRECL must equal the LRECL of the input
* file defined in this program plus four bytes.
* Delimiter values in the FIL-ERR file are converted to a
* tilde "~" for readablity.
* Inputs: Parameters are passed in via SYSIN in the following
* format. The SYSIN record is 80 characters long. I'm
* showing it with HEX turned on so you can see the
* delimiter value in HEX.
* ----+----1----+----2----+----3----+----4----+----5
* DELIMITERCODE=.,DELIMITERCOUNT=005
* CCDCDCECDCDCC726CCDCDCECDCDEDE7FFF444444
4444444444
* 4539493593645EFB45394935936453E005000000
0000000000
****************************************
***********************
EJECT

ENVIRONMENT DIVISION.
CONFIGURATION SECTION.

INPUT-OUTPUT SECTION.
FILE-CONTROL.

*-------------- INPUT FILE ------------------------------------
SELECT FILE-IN ASSIGN TO UT-S-FILEIN.

*-------------- OUTPUT FILE -----------------------------------
SELECT FILE-OUT ASSIGN TO UT-S-FILEOUT.
SELECT FILE-ERR ASSIGN TO UT-S-FILEERR.


DATA DIVISION.
FILE SECTION.

FD FILE-IN
LABEL RECORDS ARE STANDARD
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS V
DATA RECORD IS FILE-IN-RECORD.

01 FILE-IN-RECORD.
05 FILLER PIC X(9000).


FD FILE-OUT
LABEL RECORDS ARE STANDARD
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS V
DATA RECORD IS FILE-OUT-RECORD.

01 FILE-OUT-RECORD.
05 FILLER PIC X(9000).


FD FILE-ERR
LABEL RECORDS ARE STANDARD
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS V
DATA RECORD IS FILE-ERR-RECORD.

01 FILE-ERR-RECORD.
05 FILLER PIC X(9000).


EJECT
****************************************
*******************
WORKING-STORAGE SECTION.

01 FILLER PIC X(33) VALUE
'** WORKING STORAGE BEGINS HERE **'.

****************************************
*******************

EJECT
****************************************
*******************
01 RDW PIC 9(4) COMP.
****************************************
*******************
01 SWITCHES.
05 INPUT-EOF-SW PIC X(01) VALUE 'N'.
88 INPUT-EOF VALUE 'Y'.
****************************************
*******************

01 WS-PARM-DATA.
05 FILLER PIC X(14).
05 WS-DELIMITER PIC X(01).
05 FILLER PIC X(16).
05 WS-DELIMITER-CNT PIC 9(03).
05 FILLER PIC X(46).

****************************************
*******************
01 FILLER PIC X(33) VALUE
'** MISCELLANEOUS BEGINS HERE =>'.

01 MISCELLAEOUS-AREA.
05 NUM-OF-DELIM PIC 9(04).

EJECT
****************************************
*******************
* HOLD INPUT AREA.
****************************************
*******************
****************************************
*******************
* COUNTERS ARE KEPT FOR STATISTICS, AUDIT, AND TRENDING
* PURPOSES.
****************************************
*******************

01 PROCESS-COUNTERS.
05 RECS-IN PIC S9(9) COMP VALUE ZERO.
05 OUT-RECS PIC S9(9) COMP VALUE ZERO.
05 ERR-RECS PIC S9(9) COMP VALUE ZERO.

EJECT
PROCEDURE DIVISION.
****************************************
*******************
*
****************************************
*******************

0000-MAINLINE.
****************************************
*******************
* MAIN PROCESSING SEQUENCE.
****************************************
*******************
DISPLAY '=========== VARSRCH STARTING ============'.

PERFORM 1000-INITIALIZE.

PERFORM 2000-PROCESS-INPUT
UNTIL INPUT-EOF.

PERFORM 9900-DONE.


EJECT
1000-INITIALIZE.
****************************************
*******************
* INITIALIZE WS AND READ FIRST RECORD
****************************************
*******************


MOVE 'N' TO INPUT-EOF-SW.

OPEN INPUT FILE-IN.
OPEN OUTPUT FILE-OUT
FILE-ERR.

ACCEPT WS-PARM-DATA.

PERFORM 8000-READ-INPUT.

IF INPUT-EOF
DISPLAY 'INPUT FILE EMPTY'
END-IF.



EJECT
2000-PROCESS-INPUT.
****************************************
*******************
* PROCESS RECORDS.
****************************************
*******************

MOVE 0 TO NUM-OF-DELIM.

INSPECT FILE-IN-RECORD
TALLYING NUM-OF-DELIM
FOR ALL WS-DELIMITER.


IF NUM-OF-DELIM = WS-DELIMITER-CNT
PERFORM 8100-WRITE-OK-RECORD
ELSE
PERFORM 8200-WRITE-ERR-RECORD
END-IF.

PERFORM 8000-READ-INPUT.

8000-READ-INPUT.
****************************************
*******************
* READ INPUT RECORDS
****************************************
*******************

MOVE SPACES TO FILE-IN-RECORD.

READ FILE-IN
AT END
MOVE 'Y' TO INPUT-EOF-SW
NOT AT END
ADD +1 TO RECS-IN
END-READ.


8100-WRITE-OK-RECORD.
****************************************
*******************
* WRITE OUT THE GOOD RECORDS
****************************************
*******************

MOVE FILE-IN-RECORD TO FILE-OUT-RECORD.

WRITE FILE-OUT-RECORD.
ADD +1 TO OUT-RECS.


8200-WRITE-ERR-RECORD.
****************************************
*******************
* WRITE OUT THE BAD RECORDS.
* REPLACE EXISTING DELIMITER WITH A TILDE FOR READABILITY.
****************************************
*******************
INSPECT FILE-IN-RECORD
REPLACING ALL WS-DELIMITER BY '~'.

MOVE FILE-IN-RECORD TO FILE-ERR-RECORD.

WRITE FILE-ERR-RECORD.
ADD +1 TO ERR-RECS.


9900-DONE.
****************************************
*******************
* PROGRAM WRAP UP.
****************************************
*******************

CLOSE FILE-IN
FILE-OUT.

DISPLAY 'INPUT RECORDS: ' RECS-IN.
DISPLAY 'GOOD RECORDS: ' OUT-RECS.
DISPLAY 'ERRORS FOUND: ' ERR-RECS.


GOBACK.

sasquatch53@gmail.com wrote:
> I've written a program (with a lot of help) to validate the delimiter
> counts in a Variable Blocked (VB) file on an os/390 MVS mainframe.
>
> My problem is that I currently have to hard code in the maximum record
> length of the input file(less 4 bytes) shown below as 32752. If I try
> this program with a VB file that doesn't have an LRECL of 32756 then it
> fails.
>

<snip>

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com