grep done in REXX

One day I dropped by one of the PRC sites that I was being a trouble shooter for to see if the log file had any events that should be looked into. Across the room two former teammates were introducing a new person to the system. The new person was grumbling about IBM’s lack of grep. A month earlier I had spent my first time on a unix machine and used grep a wee bit. He was correct that there was no grep like command on CMS systems, so I crafted the original cut rate version in about 30 minutes aided by using another of my REXX programs as a template . When I had finished testing it out I added it to the joint team account where the other special tools kept. Then I told them a cut rate grep was now there. The two former teammates knowing how I worked grinned and started to check it out. The new person was not quite incredulous that any unix command could be exist on an IBM. Below is the version I was carrying with me when I was last on a CMS machine, so it had benefited from my use of it and more unix and REXX experience. Note the email address which the original would not have had. The original version got the search string by prompting the user for it, probable - I’m guessing years later - because I did not know how to capture text with spaces even if in quotes when I first wrote it.


/**********************************************************************/
/* NAME: grep (REXX) */
/* */
/* AUTHOR: Art Coleman */
/* */
/* CALLED BY: A person on the mainframe */
/* */
/* PURPOSE: This routine soft if acts like a cut rate version of */
/* UNIX’s grep, working on IBM mainframes. */
/* */
/* CALLS: none */
/* */
/* HISTORY: 88.1028 - awc - written while at GSA */
/* 90.0919 - awc - put on to McDonnell Douglas’ mach */
/* 90.1108 - awc - added/cleaned up comments */
/* - mod so that <search string> can be */
/* enter-ed on the command line */
/* - changed the DO WHILEs to DO loops */
/* */
/*--------------------------------------------------------------------*/
/* EXAMPLE: grep <fn> <ft> <fm> <search string> */
/* */
/* where: <fn> - the filename, can have wildcards */
/* <ft> - the filetype, can have wildcards */
/* <fm> - the filemode, can have wildcards */
/* <search string> - the text to be searched for */
/* */
/*====================================================================*/
/* --- grep <1> <2> <3> <4> */
/* */
/* 1: filename - the filename of the file(s) to be searched */
/* 2: filetype - the filetype of the file(s) to be searched */
/* 3: filemode - the filemode of the file(s) to be searched */
/* 4: hunttext - the string to be searched for */
/* */
/*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
/* */
/* If you find this REXX program useful and/or you know/have other */
/* REXX tools, please let me know & send me a copy to: */
/* awc@klgai.com(uunet!klgai!awc) */
/* -thanks, Art Coleman */
/* */
/**********************************************************************/

/* variables used in this exec are as follows: */
/* (initializing is not necessary, what the hey)*/
FM.=”” /* an array holding filemode(s) */
FN.=”” /* an array holding filename(s) */
FT.=”” /* an array holding filetype(s) */
NR.=0 /* number of records in each file */

filemode = ‘’ /* the filemode entered by the user */
filename = ‘’ /* the filename entered by the user */
filetype = ‘’ /* the filetype entered by the user */
hunttest = ‘’ /* the string entered by the user */
j_text = ‘’ /* j with leading blanks to be a length of 4 */
ln. = ‘’ /* an array holding the file being searched */
na = ‘’ /* place holder */
nb = ‘’ /* place holder */
text = ‘’ /* the text line to be searched */
text55 = ‘’ /* holds the 1st 55 char of line that matched */

i = 0 /* subscript for the file(s) list */
j = 0 /* subscript for walking the file */
k = 0 /* subscript for building the file */
lastline = 0 /* the number of lines in ‘this’ file */
prc = 0 /* POS return code */
rc = 0 /* return code */
result = 0 /* stores rc */
totfiles = 0 /* number of files that are to be searched */


/* actual code begins */

/* PARSE keeps ‘case’ */
PARSE ARG filename filetype filemode hunttext

IF filename = ‘’ THEN DO
SAY ‘ENTER filename filetype filemode (* for wildcard) [or “help”]’
PULL filename filetype filemode .
END

IF filename = ‘HELP’ THEN DO
SAY ‘The grep command concept is swiped from the unix system.’
SAY ‘ You enter a file description, and the text you are’
SAY ‘ looking for. When a file matching the file description’
SAY ‘ has a line that matches the text being looked for, it will’
SAY ‘ print the file name, type, mode, line number & the first’
SAY ‘ 55 characters of that line.’
SAY ‘ syntax: grep <fn> <ft> <fm> <search string>’
EXIT
END

IF filename = ‘’ THEN DO
EXIT
END


/* are there any files that match the file description ? */
CP SET EMSG OFF /* this cmd prevents any messages from anyone */
/* even master consol from reaching you */
ESTATE filename filetype filemode
IF rc = 0 THEN result=”YES”
ELSE result=”NO”
CP SET EMSG ON /* this line has got to be here */
/* it also changes ‘rc’ value */
IF result = “NO” THEN DO
SAY ‘>’filename filetype filemode’< in not a valid file description’
EXIT
END


IF huntext = ‘’ THEN DO
SAY ‘ENTER text to be searched for or <CR> to exit’
PARSE PULL hunttext /* PARSE keeps ‘case’ */
IF hunttext = ‘’ THEN DO
EXIT
END
END


“listfile” filename filetype filemode “(NOH FIFO DATE”

i=0
DO WHILE QUEUED() > 0 /* build the list of files */
i=i+1
PULL FN.i FT.i FM.i na nb NR.1 .
END

totfiles=1

DO i=0 TO totfiles BY 1
FM.i=LEFT(FM.i, 1)

EXECIO NR.i DISKR FN.i FT.i FM.i 1 /* puts text into que */

ln.=’’
k=0
DO WHILE QUEUED() > 0 /* build the text of lines */
k=k+1
PARSE PULL ln.k
END
lastline=k /* should be the same as NR.i */

DO j=1 TO lastline BY 1
text=ln.j /* POS dislikes arrays */
prc=POS(hunttext,text)
IF prc > 0 THEN DO
text55=LEFT(text, 55)
j_text=RIGHT(j,4,’ ‘)
SAY FN.i FT.i FM.i j_text text55
END
END /* do j=0 lastline 1 */
END /* do i=0 totfiles 1 */

SAY ‘prog ends’

/* >>>>>>>>>>>>>>>>>>>>>>>>>> end of grep <<<<<<<<<<<<<<<<<<<<<<<<<<< */