/* REXX */ /* */ /* AUTHOR: Mark Zelden */ /* */ /* Label checking code */ /* contribution from: */ /* Sean M. Smith */ /* */ /* Last Updated 08/21/2016 */ /* (added showdups option) */ /* */ help_start = HELP_INCL() /********************************************************************/ /* This edit macro will sort a file and delete the duplicate lines */ /* from it. */ /* */ /* The duplicate search can optionally be limited to specific */ /* columns and/or lines by using labels. */ /* */ /* An optional parameter of "Showdups" may be specified and all */ /* the duplicate lines will be shown instead of being deleted. You */ /* may wish to use the "hide excluded" command after using the */ /* Showdups option so you don't see the "n Line(s) not Displayed" */ /* messages after execution. To see the lines again you would use */ /* the "reset hide" command. If you would like to see what would */ /* be the remaining lines from an actual DELDUPS execution without */ /* "Showdups" specified, use the "FLIP" command after execution */ /* with the Showdups option. The "Showdups" option may be */ /* appreviated by using one or more of its characters. */ /* */ /* The file must be sorted first in order to delete the duplicate */ /* lines and is sorted using the "begcol" and "endcol" for all */ /* lines or only the lines that are within the label range used. */ /* This sorting is still required when using the "Showdups" */ /* option even though no lines are actually deleted. */ /* */ /* NOTE: The Showdups option requires z/OS 1.6 (ISPF 5.6) or above. */ /* */ /********************************************************************/ /* Command syntax: */ /* */ /* DELDUPS (begcol) (endcol) (.label1) .label2) (Showdups) */ /* */ /* - OR - */ /* */ /* DELDUPS (.label1) .label2) (begcol) (endcol) (Showdups) */ /* */ /* ** The Showdups option requires z/OS 1.6 (ISPF 5.6) or above. */ /* */ /* */ /* ** NOTE: If you execute DELDUPS with a parm of '?' the */ /* the comment secion of this code with syntax and usage */ /* examples will be displayed as "HELP" note lines. Use */ /* the "RESET" command to remove them. */ /* */ /* */ /********************************************************************/ /* Execution examples: */ /* */ /* DELDUPS */ /* DELDUPS show */ /* DELDUPS s */ /* DELDUPS 10 15 */ /* DELDUPS 10 15 Showdups */ /* DELDUPS .from .to */ /* DELDUPS .from .to s */ /* DELDUPS 43 57 .here .there */ /* DELDUPS 43 57 .here .there Show */ /* DELDUPS .to .from 43 57 */ /* DELDUPS .to .from 43 57 show */ /* */ /********************************************************************/ help_end = HELP_INCL() /*****************************************************/ /* To help performance, this macro uses the exclude */ /* command and a "DELETE ALL X" command, which is */ /* much quicker than individual line deletes. */ /*****************************************************/ /* Trace ?R */ Address ISREDIT "MACRO (var1 var2 var3 var4 var5)" If var1 = '?' then do Call HELP_NOTELINES Exit 1 /* return cursor to command line */ End /******************************************************/ /* Check for Showdups option - if found set the usage */ /* flag and remove the parm before processing the */ /* column and label options. */ /******************************************************/ showopt='no' allparms = Translate(var1 var2 var3 var4 var5) showchk = Pos('S',allparms) If showchk <> 0 then do /* showdups option ? */ show_word = Substr(allparms,showchk) /* opt actually specified */ show_wpos = Wordpos(show_word,allparms) /* which parm was it? */ If Abbrev('SHOWDUPS',Strip(show_word)) = 0 then do /* bad abbr. */ zedsmsg = 'Invalid parameter' zedlmsg = 'Invalid parameter or option specified. Please', 'check your execution parameters.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Call HELP_NOTELINES Exit 12 End Else showopt = 'yes' /* set usage flag to 'yes' */ If show_wpos = 1 then do /* show was 1st parm */ If var2 <> '' then do /* any other parms invalid */ zedsmsg = 'Invalid parameter' zedlmsg = 'Invalid parameter or option specified. Please', 'check your execution parameters.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Call HELP_NOTELINES Exit 12 End Else var1 = '' /* remove show parm before */ End /* doing col/lbl checks */ If show_wpos = 3 then do /* show was 3rd parm */ If var4 <> '' then do /* any other parms invalid */ zedsmsg = 'Invalid parameter' zedlmsg = 'Invalid parameter or option specified. Please', 'check your execution parameters.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Call HELP_NOTELINES Exit 12 End Else var3 = '' /* remove show parm before */ End /* doing col/lbl checks */ End If showopt = 'yes' then do /* show option was used */ Address ISPEXEC "VGET ZENVIR" /* get ispf version */ If Substr(ZENVIR,6,3) < 5.5 then do /* below 5.5 has no "FLIP" */ zedsmsg = 'Showdups not allowed' zedlmsg = 'You need z/OS 1.6 (ISPF 5.6)', 'or above to use the Showdups option.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End End /*****************************************/ /* Code below allows either columns */ /* and/or labels to be specified in */ /* either order. */ /*****************************************/ col1 = '' col2 = '' lbl1 = '' lbl2 = '' If var1 <> '' then do If pos('.',var1) > 0 then lbl1 = var1 Else col1 = var1 End If var2 <> '' then do If pos('.',var2) > 0 then lbl2= var2 Else col2 = var2 End If var3 <> '' then do If pos('.',var3) > 0 then lbl1= var3 Else col1 = var3 End If var4 <> '' then do If pos('.',var4) > 0 then lbl2= var4 Else col2 = var4 End /*****************************************/ Address ISPEXEC "CONTROL ERRORS RETURN" /****************************/ /* Validate parms */ /****************************/ If col1 <> '' then do If Datatype(col1,Number) <> 1 then do zedsmsg = 'Invalid parameter' zedlmsg = 'Invalid parameter or option specified. Please', 'check your execution parameters.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Call HELP_NOTELINES Exit 12 End "(chkwidth) = DATA_WIDTH" If col1 > chkwidth | col1 < 1 then do zedsmsg = 'Invalid start column' zedlmsg = 'The start column must be between 1 and the', 'data width (1-'Format(chkwidth)').' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If col2 = '' then do zedsmsg = 'No ending column' zedlmsg = 'An ending column for the', 'duplicate search must be specified.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End End Else col1 = 1 /* default starting column for duplicate search */ If col2 <> '' then do If Datatype(col2,Number) <> 1 then do zedsmsg = 'End column not numeric' zedlmsg = 'The ending column for the', 'duplicate search must be numeric.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If col2 < col1 | col2 > chkwidth then do zedsmsg = 'Invalid end column' zedlmsg = 'The end column must be between the start column', 'and the data width ('col1'-'Format(chkwidth)').' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End End Else "(col2) = DATA_WIDTH" /* default end col for dup search */ /****************************************************/ /* Additional parm validation and some housekeeping */ /****************************************************/ If lbl1 <> '' & lbl2 = '' then do zedsmsg = 'No ending label' zedlmsg = 'An ending label fro the', 'duplicate search must be specified.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If lbl1 = '' then lbl1 = '.ZFIRST' If lbl2 = '' then lbl2 = '.ZLAST' "(status) = USER_STATE" /* save current bounds */ "(firstln) = LINENUM" lbl1 /* first data line */ "(lastln) = LINENUM" lbl2 /* last data line */ If firstln = 0 then do zedsmsg = 'Invalid label:' lbl1 zedlmsg = 'The starting label must be defined.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If lastln = 0 then do zedsmsg = 'Invalid label:' lbl2 zedlmsg = 'The ending label must be defined.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If lastln < firstln then do /* 2nd label specified */ firstln_sv = firstln /* before 1st label */ firstln = lastln /* so line numbers */ lastln = firstln_sv /* need to be swapped */ End If lastln - firstln < 1 then do zedsmsg = 'Need at least 2 lines' zedlmsg = 'There must be at least 2 lines in the file', 'or label range to use DELDUPS.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ EXIT 12 End delcount = 0 /* count of deleted lines */ currln = firstln /* current line number */ "BOUNDS" /* reset bounds */ "RESET EXCLUDED" /* reset exclude status */ "SORT " col1 col2 lbl1 lbl2 /* sort on key columns */ /***********************************/ /* Begin search for duplicates. */ /***********************************/ Do while currln < lastln "(data1) = LINE "currln /* data1 = current line */ data1 = Substr(data1,col1,col2-col1+1) nextln = currln + 1 "(data2) = LINE "nextln /* data2 = next line */ data2 = Substr(data2,col1,col2-col1+1) If data1 == data2 then do "ISREDIT XSTATUS "nextln" = X" /* match, excl line */ delcount = delcount + 1 currln = currln + 1 End Else currln = currln + 1 /* no dup found - loop */ End /* do while */ /***********************************/ /* End search for duplicates. */ /***********************************/ If showopt = 'no' then , "DELETE ALL EXCLUDED" /* search done - delete all excluded lines */ Else "FLIP" /* don't delete, just SHOWdups */ "(lastln) = LINENUM .ZLAST" /* last data line */ /*******************************************************************/ "UP MAX" /* move display to 1st line */ "USER_STATE = (status)" /* restore saved bounds */ Address ISPEXEC If delcount = 0 then do zedsmsg = 'No duplicate lines!' zedlmsg = 'No duplicate lines were found in the file!' "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 4 End Else do lastln = Format(lastln) /* remove leading zeros */ If showopt = 'no' then do zedsmsg = delcount 'lines deleted' zedlmsg = delcount 'duplicate line(s) were deleted and', lastln' line(s) were kept in the file.' End Else do zedsmsg = delcount 'dup line(s) shown' zedlmsg = delcount 'duplicate line(s) shown and', lastln-delcount' non-dup line(s) were' , 'excluded in the file.' End "SETMSG MSG(ISRZ000)" /* msg - no alarm */ Exit 1 /* return cursor to command line */ End /*********************************/ /* HELP SUB-ROUTINES */ /*********************************/ HELP_INCL: Return SIGL HELP_NOTELINES: Do hlp = help_end-1 to help_start+1 by -1 hline = Sourceline(hlp) "ISREDIT LINE_AFTER 0 = NOTELINE (hline)" End hline2 = '===================' hline3 = '=== H E L P ===' "ISREDIT LINE_AFTER 0 = NOTELINE (hline2)" "ISREDIT LINE_AFTER 0 = NOTELINE (hline3)" "ISREDIT LINE_AFTER 0 = NOTELINE (hline2)" Return