IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

Count No of Delimiters appearing in header


IBM Mainframe Forums -> DFSORT/ICETOOL
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
puneetvirmani143

New User


Joined: 24 Jul 2007
Posts: 55
Location: noida

PostPosted: Thu Mar 22, 2012 3:29 pm
Reply with quote

Hi,

I have a requirement to read 5 (# delimited) Variable length files as input and create one single output file containing 5 records, each record corresponding to one input file with following information in Output record:

<<filename 10 bytes>> <<Count (excluding Header record) 8 bytes>> <No of delimiters '#' appearing in header record of each file 5 bytes>>

ex.

//IN1 DD DSN=A.B.C,DISP=SHR
//IN2 DD DSN=C.D.E,DISP=SHR
//IN3 DD DSN=F.G.H,DISP=SHR
//IN4 DD DSN=I.J.K,DISP=SHR
//IN5 DD DSN=L.M.N,DISP=SHR

OUtput file should have 5 records as :

IN1 0000058 000078
IN2 0000020 000057
IN3 0000010 000052
IN4 0000070 000035
IN5 0000030 000040


Please let me know if you need some more information.


Regards
Puneet
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Mar 22, 2012 3:50 pm
Reply with quote

I'm not sure that counting the delimiters is "easy", particularly if more than 100 (if more than 100 PARSE will not come to your aid). You have a five-byte count, but what is your maximum number?
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Mar 22, 2012 3:52 pm
Reply with quote

Puneet,
after 9 topics in DFSORT/ICETOOL started by you,
what info do you think we need?

i would say it is incumbent upon you
to at least search the forum
and determine what info we may need
to do your work for you so that you can keep your job.
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Mar 22, 2012 4:12 pm
Reply with quote

Puneet,
your attention is requested here:
ibmmainframes.com/viewtopic.php?t=57515&highlight=count
Back to top
View user's profile Send private message
puneetvirmani143

New User


Joined: 24 Jul 2007
Posts: 55
Location: noida

PostPosted: Thu Mar 22, 2012 4:20 pm
Reply with quote

Hi Bill,

We need to Count the No of Delimiters "#" appearing in header record of each file and not from all the records in file.

Moreover, the No of delimiters will be less than 100.

The same exercise has to be done for all the 5 input files in one step (if possible)

Thanks
Puneet
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Mar 22, 2012 4:30 pm
Reply with quote

OK, that part of the requirement was reasonably clear anyway :-)

If less than or equal to 100 delimiters, then dbz has a useful requirement for you above.

You presumably know yourself how to identify and isolate the headers (you haven't told us).

Counting the records should be "easy" with ICETOOL.

Which-file-is-which you "hard code".

Bring all the stuff together. Five input files, two different processes for each file, one output file. One step if you can.
Back to top
View user's profile Send private message
puneetvirmani143

New User


Joined: 24 Jul 2007
Posts: 55
Location: noida

PostPosted: Thu Mar 22, 2012 4:44 pm
Reply with quote

Hi Bill,

The output file will have 5 records where each record contains information about each file.

OUtput file should have 5 records as :
<<Filename>> <<Record count >> <<No of # appearing in header>>
IN1 0000058 000078
IN2 0000020 000057
IN3 0000010 000052
IN4 0000070 000035
IN5 0000030 000040

Here Filenames IN1, IN2 etc .. I will deliberately hardcode to represent each file. We do not have to capture ddnames of input files here.

Thanks
Puneet
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Mar 22, 2012 4:49 pm
Reply with quote

Puneet,
thx for repeating what you have already posted.

what are the lengths of the header records for each file?
Back to top
View user's profile Send private message
puneetvirmani143

New User


Joined: 24 Jul 2007
Posts: 55
Location: noida

PostPosted: Thu Mar 22, 2012 4:52 pm
Reply with quote

1. Each input file is # delimited and of variable length VB= 560 bytes
2. There is no indicator text to identify the Header record. It would be the first record in each file.
3. Output file length required = 80 Bytes FB.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Mar 22, 2012 4:54 pm
Reply with quote

:-)

I understood all that a while ago. I was trying to give you some pointers for how you go about it.

From the link dbz required you to read, you can count the hash signs (for your headers).

Counting records on the files is easy with ICETOOL's COUNT operator.

The "hard coded" names are the easiest part.

Then you have to bring all that together to create your output file with five records on it.

Since you are keeping other relevant information close to you, I'm assuming that you're going to pick up the task and run with it to completion.

If not, think about the information anyone else would need to do the task. Like how are the headers identified? Is there anything unique to the file on the header? Are the files all the same RECFM? Same LRECL? Does your site allow use of ICETOOL for the task? What is the "one step" thing about? Anything else you can think of, without just repeating what you've already said?

EDIT: OK, got some. What about the rest, please?
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Mar 22, 2012 4:55 pm
Reply with quote

so each header is 560 bytes long?

by the way, sounds like a class room project with the 1 step requirement
Back to top
View user's profile Send private message
puneetvirmani143

New User


Joined: 24 Jul 2007
Posts: 55
Location: noida

PostPosted: Thu Mar 22, 2012 5:05 pm
Reply with quote

No, since file is of variable length (max LRECL=556 + 4 Bytes) total = 560 bytes. it does not mean that header continue till 556 position.


1. All input file are of different LRECL and are variable length files.
2. want this task to be done in only ONE STEP of Jcl.(if possible)
3. Header is to be identified as the first record appearing in the file. There are no specific Indicators in the HEADER part of each file.
4. No trailers in Input files.
5
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Mar 22, 2012 7:32 pm
Reply with quote

well, maybe this logic could be used to count the delimiters.
unfortunately i don't have access to mainframe, so i can not dev and test:

header record, max 556
so you need a 'if it is a short record, deal with it parm' in you control card

Quote:

2 ICETOOL Processing Steps per file
ctl1 TO pull a header, parse out each '#', creating 1 record for each
ctl2 only include records with '#', and generate a trailer with the count

1. read file 1 record to temp-n file using ctl1

ctl1

OUTFILE parse %00=(STARTAT='#', FIXLEN=1),
...
PARSE %99=(STARTAT='#', FIXLEN=1)
BUILD=(%00,' ',/,%01,' ',/,...%99

2. COPY TEMP-n TO TEMP-n+1 USING CTL2
CTL2

INCLUDE=1,CH,EQ,'#'

OUTFILE/OUTREC
COUNT

1 icetool processing step per file
create trailer with count of all records - 1 (don't count header)


then be clever and join them together, keeping track of which is which
separate temp files.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Mar 22, 2012 8:30 pm
Reply with quote

Please use the standard Code tags, not the Elixir ones...

:-)

EDIT: I was wondering about RESIZE to chop the headers into one-byte records, then the include...

2nd EDIT: To add the word EDIT.
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Mar 22, 2012 8:38 pm
Reply with quote

as it was pseudo code and not code (per se)
and it was easier to read with elixir tags (though i did refrain from color codes)
than with code tags, i decided to go with quote tags.

sorry........ icon_fU.gif
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Mar 22, 2012 9:32 pm
Reply with quote

Since it is a variable-length record...

Code:
//COUNTEM EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SORTIN DD DSN=&&OUT,DISP=(OLD,PASS)
//SORTOUT DD SYSOUT=*
//SYSIN DD *
 OPTION COPY
 INREC IFTHEN=(WHEN=INIT,FINDREP=(IN=(C'A',
                    C'B',
                    C' '),OUT=C'')),
       IFTHEN=(WHEN=INIT,BUILD=(1,4,1,2,BI,SUB,+4,TO=ZD,LENGTH=5))


I give on the SORTIN
Code:

#################################
# # #B# # # # # # # # # #A# # ## #


And on the SORTOUT get
Code:

00033
00018


Now, the idea is, if this is a "hash-seperated-variables" file that probably means it is a text file. So, just needs lots of repeats of the "C'B'," line, then replaced by remaining letters of the alphabet, numbers and keyboard characters.

I was also thinking that if the "header" is actually some sort of header, the only thing headery about it will be column-titles. Meaning that the last record on the file will be equally useful for knowing how many "columns" are in the data. May or may not be of use to any further solution elements. Should be San Jose time soon anyway...
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Mar 22, 2012 10:30 pm
Reply with quote

OK, with the second step being a shameless copy from the Smart DFSORT Tricks, this

Code:
//GENEM EXEC PGM=SORT
//SORTOUT DD DSN=&&OUT,UNIT=SYSDA,SPACE=(CYL,1),DISP=(,PASS)
//SORTIN DD *
CONTENT NOT RELEVANT
//SYSOUT DD SYSOUT=*
//SYSIN DD *
 SORT FIELDS=COPY
 OUTFIL REPEAT=256,
 IFTHEN=(WHEN=INIT,BUILD=(SEQNUM,1,BI,START=0),
                                HIT=NEXT),
 IFTHEN=(WHEN=INIT,BUILD=(C'X''',1,1,
                                TRAN=HEX,C''','))
//COMB1 EXEC PGM=ICETOOL
//TOOLMSG DD SYSOUT=*
//DFSMSG DD SYSOUT=*
//IN1 DD DSN=&&OUT,DISP=(OLD,PASS)
//OUT1 DD SYSOUT=*
//TOOLIN DD *
 RESIZE FROM(IN1) TO(OUT1) TOLEN(60)

//OUT1 DD SYSOUT=*
//TOOLIN DD *
 RESIZE FROM(IN1) TO(OUT1) TOLEN(60)


Produces this:
Code:

X'00',X'01',X'02',X'03',X'04',X'05',X'06',X'07',X'08',X'09',
X'0A',X'0B',X'0C',X'0D',X'0E',X'0F',X'10',X'11',X'12',X'13',
X'14',X'15',X'16',X'17',X'18',X'19',X'1A',X'1B',X'1C',X'1D',
X'1E',X'1F',X'20',X'21',X'22',X'23',X'24',X'25',X'26',X'27',
X'28',X'29',X'2A',X'2B',X'2C',X'2D',X'2E',X'2F',X'30',X'31',
X'32',X'33',X'34',X'35',X'36',X'37',X'38',X'39',X'3A',X'3B',
X'3C',X'3D',X'3E',X'3F',X'40',X'41',X'42',X'43',X'44',X'45',
X'46',X'47',X'48',X'49',X'4A',X'4B',X'4C',X'4D',X'4E',X'4F',
X'50',X'51',X'52',X'53',X'54',X'55',X'56',X'57',X'58',X'59',
X'5A',X'5B',X'5C',X'5D',X'5E',X'5F',X'60',X'61',X'62',X'63',
X'64',X'65',X'66',X'67',X'68',X'69',X'6A',X'6B',X'6C',X'6D',
X'6E',X'6F',X'70',X'71',X'72',X'73',X'74',X'75',X'76',X'77',
X'78',X'79',X'7A',X'7B',X'7C',X'7D',X'7E',X'7F',X'80',X'81',
X'82',X'83',X'84',X'85',X'86',X'87',X'88',X'89',X'8A',X'8B',
X'8C',X'8D',X'8E',X'8F',X'90',X'91',X'92',X'93',X'94',X'95',
X'96',X'97',X'98',X'99',X'9A',X'9B',X'9C',X'9D',X'9E',X'9F',
X'A0',X'A1',X'A2',X'A3',X'A4',X'A5',X'A6',X'A7',X'A8',X'A9',
X'AA',X'AB',X'AC',X'AD',X'AE',X'AF',X'B0',X'B1',X'B2',X'B3',
X'B4',X'B5',X'B6',X'B7',X'B8',X'B9',X'BA',X'BB',X'BC',X'BD',
X'BE',X'BF',X'C0',X'C1',X'C2',X'C3',X'C4',X'C5',X'C6',X'C7',
X'C8',X'C9',X'CA',X'CB',X'CC',X'CD',X'CE',X'CF',X'D0',X'D1',
X'D2',X'D3',X'D4',X'D5',X'D6',X'D7',X'D8',X'D9',X'DA',X'DB',
X'DC',X'DD',X'DE',X'DF',X'E0',X'E1',X'E2',X'E3',X'E4',X'E5',
X'E6',X'E7',X'E8',X'E9',X'EA',X'EB',X'EC',X'ED',X'EE',X'EF',
X'F0',X'F1',X'F2',X'F3',X'F4',X'F5',X'F6',X'F7',X'F8',X'F9',
X'FA',X'FB',X'FC',X'FD',X'FE',X'FF',               


With a little pasting and editing, produces this:
Code:

//COUNTEM EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SORTIN DD DSN=&&OUT,DISP=(OLD,PASS)
//SORTOUT DD SYSOUT=*
//SYSIN DD *
 OPTION COPY
 INREC IFTHEN=(WHEN=INIT,FINDREP=(IN=(X'00',
        X'01',X'02',X'03',X'04',X'05',X'06',X'07',X'08',X'09',
  X'0A',X'0B',X'0C',X'0D',X'0E',X'0F',X'10',X'11',X'12',X'13',
  X'14',X'15',X'16',X'17',X'18',X'19',X'1A',X'1B',X'1C',X'1D',
  X'1E',X'1F',X'20',X'21',X'22',X'23',X'24',X'25',X'26',X'27',
  X'28',X'29',X'2A',X'2B',X'2C',X'2D',X'2E',X'2F',X'30',X'31',
  X'32',X'33',X'34',X'35',X'36',X'37',X'38',X'39',X'3A',X'3B',
  X'3C',X'3D',X'3E',X'3F',X'40',X'41',X'42',X'43',X'44',X'45',
  X'46',X'47',X'48',X'49',X'4A',X'4B',X'4C',X'4D',X'4E',X'4F',
  X'50',X'51',X'52',X'53',X'54',X'55',X'56',X'57',X'58',X'59',
  X'5A',X'5B',X'5C',X'5D',X'5E',X'5F',X'60',X'61',X'62',X'63',
  X'64',X'65',X'66',X'67',X'68',X'69',X'6A',X'6B',X'6C',X'6D',
  X'6E',X'6F',X'70',X'71',X'72',X'73',X'74',X'75',X'76',X'77',
  X'78',X'79',X'7A',X'7C',X'7D',X'7E',X'7F',X'80',X'81',
  X'82',X'83',X'84',X'85',X'86',X'87',X'88',X'89',X'8A',X'8B',
  X'8C',X'8D',X'8E',X'8F',X'90',X'91',X'92',X'93',X'94',X'95',
  X'96',X'97',X'98',X'99',X'9A',X'9B',X'9C',X'9D',X'9E',X'9F',
  X'A0',X'A1',X'A2',X'A3',X'A4',X'A5',X'A6',X'A7',X'A8',X'A9',
  X'AA',X'AB',X'AC',X'AD',X'AE',X'AF',X'B0',X'B1',X'B2',X'B3',
  X'B4',X'B5',X'B6',X'B7',X'B8',X'B9',X'BA',X'BB',X'BC',X'BD',
  X'BE',X'BF',X'C0',X'C1',X'C2',X'C3',X'C4',X'C5',X'C6',X'C7',
  X'C8',X'C9',X'CA',X'CB',X'CC',X'CD',X'CE',X'CF',X'D0',X'D1',
  X'D2',X'D3',X'D4',X'D5',X'D6',X'D7',X'D8',X'D9',X'DA',X'DB',
  X'DC',X'DD',X'DE',X'DF',X'E0',X'E1',X'E2',X'E3',X'E4',X'E5',
  X'E6',X'E7',X'E8',X'E9',X'EA',X'EB',X'EC',X'ED',X'EE',X'EF',
  X'F0',X'F1',X'F2',X'F3',X'F4',X'F5',X'F6',X'F7',X'F8',X'F9',
  X'FA',X'FB',X'FC',X'FD',X'FE',X'FF',
                    X'FF'),OUT=C'')),
       IFTHEN=(WHEN=INIT,BUILD=(1,4,1,2,BI,SUB,+4,TO=ZD,LENGTH=5))


Which has the hex-literal for the HASH sign (#) removed, so counts all the hashes on a variable-length record.

Can be easily applied to other values, and uses...
Back to top
View user's profile Send private message
Skolusu

Senior Member


Joined: 07 Dec 2007
Posts: 2205
Location: San Jose

PostPosted: Fri Mar 23, 2012 4:51 am
Reply with quote

Ideally I would use an exit to count the delimiters and DFSORT to count the records in each file. Since the input files are VB , you can simply concatenate them and find the counts. There is nothing unique to distinguish the headers , so we create a dummy file to generate the headers.

Code:

//STEP0100 EXEC PGM=SORT                                   
//SYSOUT   DD SYSOUT=*                                     
//SORTIN   DD *                                             
//SORTOUT  DD DSN=&&HDR,DISP=(,PASS),SPACE=(TRK,(1,0),RLSE)
//SYSIN    DD *                                             
  SORT FIELDS=COPY                                         
  OUTFIL FTOV,REMOVECC,HEADER1=(3'$')                       
//*                                                         
//STEP0200 EXEC PGM=SORT                                             
//SYSOUT   DD SYSOUT=*                                               
//SORTIN   DD DSN=&&HDR,DISP=SHR,VOL=REF=*.STEP0100.SORTOUT           
//         DD DSN=Your input VB file1,DISP=SHR
//         DD DSN=&&HDR,DISP=SHR,VOL=REF=*.STEP0100.SORTOUT           
//         DD DSN=Your input VB file2,DISP=SHR
//         DD DSN=&&HDR,DISP=SHR,VOL=REF=*.STEP0100.SORTOUT           
//         DD DSN=Your input VB file3,DISP=SHR
//         DD DSN=&&HDR,DISP=SHR,VOL=REF=*.STEP0100.SORTOUT           
//         DD DSN=Your input VB file4,DISP=SHR
//         DD DSN=&&HDR,DISP=SHR,VOL=REF=*.STEP0100.SORTOUT           
//         DD DSN=Your input VB file5,DISP=SHR         
//*
//SORTOUT  DD DSN=&&TMP,DISP=(,PASS),SPACE=(CYL,(2,2),RLSE)           
//SYSIN    DD *                                                       
  SORT FIELDS=COPY                                                   
  INREC IFTHEN=(WHEN=INIT,BUILD=(1,4,X,5)),                           
  IFTHEN=(WHEN=GROUP,BEGIN=(6,3,CH,EQ,C'$$$'),PUSH=(5:ID=1))         
                                                                     
  OUTFIL REMOVECC,NODETAIL,VTOF,BUILD=(557X),OMIT=(6,3,CH,EQ,C'$$$'),
  SECTIONS=(5,1,                                                     
  HEADER3=('H',6,556),                                               
  TRAILER3=('TFILE: ',5,1,12:COUNT-1=(M11,LENGTH=8)))                 
//*                                                                   
//STEP0300 EXEC PGM=SORT,PARM='MSGDDN=DFSOUT'
//SYSOUT   DD SYSOUT=*                       
//DFSOUT   DD SYSOUT=*                       
//EXITC    DD DSN=Your Cobol exit loadlib,DISP=SHR
//SORTIN   DD DSN=&&TMP,DISP=SHR             
//SORTOUT  DD SYSOUT=*                       
//SYSIN    DD *                               
  SORT FIELDS=COPY                           
  MODS E15=(DLMCOUNT,557,EXITC,C)             
  OUTREC BUILD=(1,80)                         
//*



and your cobol exit would be

Code:

IDENTIFICATION DIVISION.                                       
PROGRAM-ID.    DLMCOUNT.                                       
ENVIRONMENT DIVISION.                                           
DATA DIVISION.                                                 
WORKING-STORAGE SECTION.                                       
01 WS-DLM-COUNT                PIC 99999.                       
LINKAGE SECTION.                                               
01  RECORD-FLAGS               PIC 9(8) BINARY.                 
    88  FIRST-REC              VALUE 00.                       
    88  MIDDLE-REC             VALUE 04.                       
    88  END-REC                VALUE 08.                       
                                                               
01 IP-RECORD                   PIC X(557).                     
01 OP-RECORD                   PIC X(557).                     
                                                               
PROCEDURE DIVISION USING RECORD-FLAGS                           
                       , IP-RECORD                             
                       , OP-RECORD.                             
                                                               
   IF END-REC                                                   
      MOVE 8                   TO RETURN-CODE                   
   ELSE                                                         
      IF IP-RECORD (1 : 1) = 'H'                               
         MOVE 0                TO WS-DLM-COUNT                 
         INSPECT IP-RECORD TALLYING WS-DLM-COUNT FOR ALL '#'   
         MOVE 4                TO RETURN-CODE                   
      ELSE                                                     
         MOVE IP-RECORD(2:80)  TO OP-RECORD(1:80)               
         MOVE WS-DLM-COUNT     TO OP-RECORD(20:5)               
         MOVE 20               TO RETURN-CODE                   
      END-IF                                                   
   END-IF                                                       
                                                               
   GOBACK.                                                     


The output would be something like this
Code:

FILE: 1   00000079 00005
FILE: 2   00000029 00004
FILE: 3   00000059 00003
FILE: 4   00000074 00002
FILE: 5   00000104 00556
Back to top
View user's profile Send private message
Frank Yaeger

DFSORT Developer


Joined: 15 Feb 2005
Posts: 7129
Location: San Jose, CA

PostPosted: Fri Mar 23, 2012 5:54 am
Reply with quote

Here's a way to do it without the exit or the added $$$ separators. I incorporated Bill's character counting code, which is quite clever. I decided to use an extra pass to handle IN1, IN2, etc rather than repeating all of the control statements each time to use 'IN1', 'IN2', etc.

Code:

//S1    EXEC  PGM=ICETOOL
//TOOLMSG DD SYSOUT=*
//DFSMSG  DD SYSOUT=*
//IN1 DD DSN=...  input file1 (VB)
//IN2 DD DSN=...  input file2 (VB)
//IN3 DD DSN=...  input file3 (VB)
//IN4 DD DSN=...  input file4 (VB)
//IN5 DD DSN=...  input file5 (VB)
//T1 DD DSN=&&T1,UNIT=SYSDA,SPACE=(TRK,(5,5)),DISP=(MOD,PASS)
//OUT DD DSN=...  output file (FB/80)
//TOOLIN DD *
COPY FROM(IN1) USING(CTL1)
COPY FROM(IN2) USING(CTL1)
COPY FROM(IN3) USING(CTL1)
COPY FROM(IN4) USING(CTL1)
COPY FROM(IN5) USING(CTL1)
COPY FROM(T1) TO(OUT) USING(CTL2)
//CTL1CNTL DD *
 OPTION COPY
 INREC IFTHEN=(WHEN=INIT,BUILD=(1,4,SEQNUM,6,ZD,START=0,5)),
  IFTHEN=(WHEN=(5,6,ZD,EQ,0),HIT=NEXT,
  IFTHEN=(WHEN=(5,6,ZD,EQ,0),HIT=NEXT,
    FINDREP=(STARTPOS=11,IN=(X'00',
        X'01',X'02',X'03',X'04',X'05',X'06',X'07',X'08',X'09',
  X'0A',X'0B',X'0C',X'0D',X'0E',X'0F',X'10',X'11',X'12',X'13',
  X'14',X'15',X'16',X'17',X'18',X'19',X'1A',X'1B',X'1C',X'1D',
  X'1E',X'1F',X'20',X'21',X'22',X'23',X'24',X'25',X'26',X'27',
  X'28',X'29',X'2A',X'2B',X'2C',X'2D',X'2E',X'2F',X'30',X'31',
  X'32',X'33',X'34',X'35',X'36',X'37',X'38',X'39',X'3A',X'3B',
  X'3C',X'3D',X'3E',X'3F',X'40',X'41',X'42',X'43',X'44',X'45',
  X'46',X'47',X'48',X'49',X'4A',X'4B',X'4C',X'4D',X'4E',X'4F',
  X'50',X'51',X'52',X'53',X'54',X'55',X'56',X'57',X'58',X'59',
  X'5A',X'5B',X'5C',X'5D',X'5E',X'5F',X'60',X'61',X'62',X'63',
  X'64',X'65',X'66',X'67',X'68',X'69',X'6A',X'6B',X'6C',X'6D',
  X'6E',X'6F',X'70',X'71',X'72',X'73',X'74',X'75',X'76',X'77',
  X'78',X'79',X'7A',X'7C',X'7D',X'7E',X'7F',X'80',X'81',
  X'82',X'83',X'84',X'85',X'86',X'87',X'88',X'89',X'8A',X'8B',
  X'8C',X'8D',X'8E',X'8F',X'90',X'91',X'92',X'93',X'94',X'95',
  X'96',X'97',X'98',X'99',X'9A',X'9B',X'9C',X'9D',X'9E',X'9F',
  X'A0',X'A1',X'A2',X'A3',X'A4',X'A5',X'A6',X'A7',X'A8',X'A9',
  X'AA',X'AB',X'AC',X'AD',X'AE',X'AF',X'B0',X'B1',X'B2',X'B3',
  X'B4',X'B5',X'B6',X'B7',X'B8',X'B9',X'BA',X'BB',X'BC',X'BD',
  X'BE',X'BF',X'C0',X'C1',X'C2',X'C3',X'C4',X'C5',X'C6',X'C7',
  X'C8',X'C9',X'CA',X'CB',X'CC',X'CD',X'CE',X'CF',X'D0',X'D1',
  X'D2',X'D3',X'D4',X'D5',X'D6',X'D7',X'D8',X'D9',X'DA',X'DB',
  X'DC',X'DD',X'DE',X'DF',X'E0',X'E1',X'E2',X'E3',X'E4',X'E5',
  X'E6',X'E7',X'E8',X'E9',X'EA',X'EB',X'EC',X'ED',X'EE',X'EF',
  X'F0',X'F1',X'F2',X'F3',X'F4',X'F5',X'F6',X'F7',X'F8',X'F9',
 X'FA',X'FB',X'FC',X'FD',X'FE',
                    X'FF'),OUT=C'')),
  IFTHEN=(WHEN=(5,6,ZD,EQ,0),
     BUILD=(1,10,11:1,2,BI,SUB,+10,TO=ZD,LENGTH=6))
  OUTREC IFTHEN=(WHEN=GROUP,BEGIN=(5,6,ZD,EQ,0),PUSH=(11:11,6))
 OUTFIL FNAMES=T1,REMOVECC,NODETAIL,VTOF,
   BUILD=(80X),
   TRAILER1=(C'IN1',X,5,6,X,11,6)
//CTL2CNTL DD *
  INREC OVERLAY=(3:SEQNUM,1,ZD)
/*
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Fri Mar 23, 2012 6:23 am
Reply with quote

the 1 step solution

and 6000 posts!
Back to top
View user's profile Send private message
Frank Yaeger

DFSORT Developer


Joined: 15 Feb 2005
Posts: 7129
Location: San Jose, CA

PostPosted: Fri Mar 23, 2012 11:25 pm
Reply with quote

Bill sent me a better version of his trick offline (thanks, Bill). He realized we could just remove the target characters and then get the number of those characters from

original length of record - new length of record

Hopefully, he'll post the general version of his trick here.

I've incorporated his trick into my solution and it makes it much simpler. Here's the revised version:

Code:

//S2    EXEC  PGM=ICETOOL
//TOOLMSG DD SYSOUT=*
//DFSMSG  DD SYSOUT=*
//IN1 DD DSN=...  input file1 (VB)
//IN2 DD DSN=...  input file2 (VB)
//IN3 DD DSN=...  input file3 (VB)
//IN4 DD DSN=...  input file4 (VB)
//IN5 DD DSN=...  input file5 (VB)
//T1 DD DSN=&&T1,UNIT=SYSDA,SPACE=(TRK,(5,5)),DISP=(MOD,PASS)
//OUT DD DSN=...  output file (FB/80)
//TOOLIN DD *
COPY FROM(IN1) USING(CTL1)
COPY FROM(IN2) USING(CTL1)
COPY FROM(IN3) USING(CTL1)
COPY FROM(IN4) USING(CTL1)
COPY FROM(IN5) USING(CTL1)
COPY FROM(T1) TO(OUT) USING(CTL2)
//CTL1CNTL DD *
  OPTION COPY
  INREC IFTHEN=(WHEN=INIT,BUILD=(1,4,5:SEQNUM,6,ZD,START=0,
      11:1,2,BI,ADD,+8,TO=BI,LENGTH=2,13:5)),
    IFTHEN=(WHEN=(5,6,ZD,EQ,0),HIT=NEXT,
      FINDREP=(STARTPOS=13,IN=X'7B',OUT=C'')),
    IFTHEN=(WHEN=(5,6,ZD,EQ,0),
      BUILD=(1,10,11:11,2,BI,SUB,1,2,BI,TO=ZD,LENGTH=6))
  OUTREC IFTHEN=(WHEN=GROUP,BEGIN=(5,6,ZD,EQ,0),PUSH=(11:11,6))
  OUTFIL FNAMES=T1,REMOVECC,NODETAIL,VTOF,
     BUILD=(80X),
     TRAILER1=(C'IN1',X,5,6,X,11,6)
//CTL2CNTL DD *
  INREC OVERLAY=(3:SEQNUM,1,ZD)
/*
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Sat Mar 24, 2012 12:38 am
Reply with quote

Thanks Frank.

When I can, I'll make it look a bit neater, with SYMNAMES, but my connection is "up the wall" at the moment...

Two things to bear in mind:

  • It is "destructive", in that the data being counted no longer exists.
  • Only works with variable-length records, as it relies on the RDW being present

First, build a record, RDW, original record-length from the RDW, the rest of the record
Second, do the FINDREP for the character (multiple are possible if needed) being counted - the located character is made to disappear by DFSORT (the C'' bit) and the record-length in the RDW is automatically adjusted.
Third, calculate the difference between the original saved record-length and the current record-length. The adjustment for +2 is to take account of the two-byte extension of the record to include the original record-length.

The STARTPOS=7 on the FINDREP is to make sure nothing from the RDW or the original record-length is touched, it is the first byte of the actual data.

Since the FINDREP IN are no longer generated, no need to have a hex literal, just whatever is needed in plain text is fine.

Since the record has been destroyed, there is no problem with just putting the final count over the start of the remaining data.

If this needs a name, it is called Humphrey, my son's cat, in memoriam

Code:
//COUNTEM EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SORTIN DD DSN=must be variable-length records
//SORTOUT DD SYSOUT=*
//SYSIN DD *
 OPTION COPY
 INREC IFTHEN=(WHEN=INIT,BUILD=(1,4,1,2,5)),
       IFTHEN=(WHEN=INIT,FINDREP=(IN=X'7B',
                    OUT=C'',STARTPOS=7)),
       IFTHEN=(WHEN=INIT,BUILD=(1,4,5,2,BI,SUB,1,2,BI,ADD,+2,
                                 TO=ZD,LENGTH=5))
Back to top
View user's profile Send private message
Frank Yaeger

DFSORT Developer


Joined: 15 Feb 2005
Posts: 7129
Location: San Jose, CA

PostPosted: Sat Mar 24, 2012 1:23 am
Reply with quote

Bill,

I'm sorry to hear that Humphrey passed away. icon_cry.gif Condolences to your son and family.

Quote:
Only works with variable-length records, as it relies on the RDW being present


This can, of course, be taken care of by first having an FTOV step to convert the FB file to a VB file.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Sat Mar 24, 2012 9:05 am
Reply with quote

Frank,

Thank you very much. Appreciated.

The "destructiveness" can be overcome as well, of course, if the count needs to be embedded.

Here's Humph
Code:

//HUMPHREY EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SORTIN DD DSN=&&OUT,DISP=(OLD,PASS)
//SORTOUT DD SYSOUT=*
//SYMNAMES DD *
RECORD-RDW,1,4,CH
 RDW-RECORD-LENGTH,=,2,BI
 RDW-RESERVED,*,2,CH
RECORD-START-OF-DATA,*,1,CH
 RECORD-START-OF-DATA-COL,=
BUILD-ORIGINAL-RECORD-LENGTH,=,2,BI
LENGTH-ADJUST-FOR-NEW-RECORD-LENGTH,+2
//SYMNOUT DD SYSOUT=*
//SYSIN DD *
                                                           
 OPTION COPY
                                                           
 INREC IFTHEN=(WHEN=INIT,
                BUILD=(RECORD-RDW,
                       RDW-RECORD-LENGTH,
                       RECORD-START-OF-DATA-COL)),
                                                           
       IFTHEN=(WHEN=INIT,
                FINDREP=(IN=C'#',
                         OUT=C'',
                         STARTPOS=7)),
                                                           
       IFTHEN=(WHEN=INIT,
                BUILD=(RECORD-RDW,
                       BUILD-ORIGINAL-RECORD-LENGTH,
                      SUB,
                       RDW-RECORD-LENGTH,
                      ADD,
                       LENGTH-ADJUST-FOR-NEW-RECORD-LENGTH,
                      TO=ZD,
                      LENGTH=5))


And here after substitution (and manual formatting)

Code:
OPTION COPY                                                           
INREC IFTHEN=(WHEN=INIT,BUILD=(1,4,1,2,5)),
      IFTHEN=(WHEN=INIT,FINDREP=(IN=C'#',OUT=C'',STARTPOS=7)),
      IFTHEN=(WHEN=INIT,
               BUILD=(1,4,5,2,BI,SUB,1,2,BI,ADD,+2,TO=ZD,LENGTH=5))             
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> DFSORT/ICETOOL

 


Similar Topics
Topic Forum Replies
No new posts To get the count of rows for every 1 ... DB2 3
No new posts To find whether record count are true... DFSORT/ICETOOL 6
No new posts Validating record count of a file is ... DFSORT/ICETOOL 13
No new posts Insert header record with record coun... DFSORT/ICETOOL 14
No new posts Count the number of characters in a f... CA Products 1
Search our Forums:

Back to Top