Joined: 06 Nov 2008 Posts: 46 Location: Manila, Philippines
Hi all,
I am not sure if the NEAT command is our system specific macro, but i'll just explain it anyway..
If I issue the NEAT command in EDIT mode in a PROC, what it will do is substitute all the symbolics in the proc.
My question is, how do I invoke NEAT in REXX (if there is a way to do that)?
My ultimate goal is this:
Create a REXX program to get a JCLCARD member and use this values to override the symbolics in the proc. The output is like what NEAT command does, with the overrides in the JCLCARD applied.
NEAT is probably a local macro written in Rexx so you can start the editor calling a macro that then calls NEAT. For example, a macro called CALLNEAT might be
To see if it is a local macro type TSO ISRDDN M(NEAT) and see if it is in a site or vendor library then browse it. Vendor code will usually have a copyright statement in it, local tools usually do not. (General rule, there are many exceptions!)
Joined: 06 Nov 2008 Posts: 46 Location: Manila, Philippines
i have search through the librarues and found out that NEAT is a macro that calls another macro...
Thanks for your reply.
It gave me new idea how to write my program in a simpler way.
1. Get JCLCARD name from user
2. read the JCLCARD and locate the PROCNAME
3. continue reading while putting all overrides in a datastack
4. read the procname and insert the datastack into the procedure
5. remove the symbolics in the proc (by matching? sort then remove dups?)
6. exec NEAT macro.
I am now wondering how will I do #5..
Any ideas?
Thanks again, I really appreciate the reply, as this is just my 2nd REXX program to write.
Joined: 01 Sep 2006 Posts: 2593 Location: Silicon Valley
I suggest:
1. parsing the PROC statement to find the variables and their values.
2. execute as variable assignments in rexx
3. remove the PEND statement
4. pass the rest of the proc through ISPF file tailoring to resolve the variables
Joined: 06 Nov 2008 Posts: 46 Location: Manila, Philippines
Hi all,
So far, I have managed to put the JCL card overrides and the proc contents in one file.
Do you have any sugegstions how I can overwrite the proc defaults with the jcl card overrides?
Joined: 01 Sep 2006 Posts: 2593 Location: Silicon Valley
repeating:
I suggest:
1. parsing the PROC statement to find the variables and their values.
2. execute as variable assignments in rexx
3. remove the PEND statement
4. pass the rest of the proc through ISPF file tailoring to resolve the variables
The problem is that since VSAMCRD3 is the last override in the jclcard and i am using the entire line of the jclcard to replace a line in the proc if the symbolics are equal, i end up not having a comma on VSAMCRD3...
I don't know if it's a good idea to think meticulously and come up with additional code to put a comma at the end of each symbolic, except on the last one..
any ideas?
Thanks..
Joined: 06 Nov 2008 Posts: 46 Location: Manila, Philippines
Thanks prino.
I have used STRIP to remove the comma on the last symbolic.
I added a logic to insert a comma at the end of all jclcard lines.
Thanks for all your help.
I am posting the program here.
Sorry if there's a lot of finetuning here...
This is my 2nd program, and I am happy to be learning more.
Code:
/* REXX */ /* created 2009-07-28 */
/*--------------------------------------------------------------*/
/* This program creates a test job from input JCLCARD */
/* Output file is : <userid>.<jobname>.SUBSTJOB */
/*--------------------------------------------------------------*/
/* To invoke this program, issue : TSO CRJOB <jobname> */
/*--------------------------------------------------------------*/
ARG jclcard
Messg_Enable_Sw = MSG(OFF)
/**----------------------**/
/** Start of the program **/
/**----------------------**/
say_on = 0
/* if no argument has been passed, retry */
IF jclcard = '' THEN say_on = 1
/* retries getting jclcard from user */
CALL ACCEPT_JCLCARD
/* verify output file if ok to create */
CALL ALLOC_OUTFLE
/* main process */
CALL PROCESS_JCLCARD
/* write output file */
CALL WRITE_SUBSTJOB
EXIT
/**----------------------------------------------------------------*/
ACCEPT_JCLCARD:
DO FOREVER
IF say_on = 1 THEN
DO
SAY 'Please enter JCLCARD member...'
PULL jclcard
END
IF jclcard = 'EXIT' ³ jclcard = 'CANCEL' ³ ,
jclcard = 'exit' ³ jclcard = 'cancel' THEN LEAVE
sysdsn_msg = SYSDSN(cardmem)
IF sysdsn_msg = 'OK' THEN LEAVE
ELSE DO
SAY sysdsn_msg
say_on = 1
END
END
RETURN
/**----------------------------------------------------------------*/
ALLOC_OUTFLE:
outproc = "'" ³³ USERID() ³³ "." ³³ jclcard ³³ "." ³³ ,
"SUBSTJOB" ³³ "'"
/* verifies if file already exists */
DS_Exist = SYSDSN(outproc)
IF DS_Exist = "OK" THEN DO
SAY 'Dataset ' outproc 'has been allocated '³³,
'and will now be deleted...'
"DELETE "outproc" PURGE"
IF RC = 0 THEN DO
SAY 'Dataset ' outproc 'deleted'
END
ELSE DO
SAY 'Error deleting' outproc ', cannot continue. '
SAY "Pls. check if it's currently open or being used.."
LEAVE
END
END
/* allocates output file */
"ALLOCATE DATASET("outproc") SHR NEW
SPACE(30,10) TRACKS RELEASE
DSORG(PS) LRECL(80) RECFM(F B)"
IF RC ª= 0 THEN DO
SAY 'Error allocating output file ' outproc '. RC=20'
EXIT
END
RETURN
/**----------------------------------------------------------------*/
PROCESS_JCLCARD:
/**----------------------------------------------------------------*/
/* allocates input JCLCARD for reading */
CALL ALLOC_INCARD
/* logic that reads jclcard member */
sysdsn_msg1 = SYSDSN(cardmem)
IF sysdsn_msg1 = 'OK' THEN
DO
SAY 'Reading ' cardmem ' for procname...'
/* this read will start on the 4th line to get the proc name */
/* it will finish reading at the 4th line as well */
CALL GET_PROC_NME
/* it now read the procname found from jclcard */
CALL READ_PROC
END
SAY 'Overrides of ' cardmem ' has been copied to ' outproc
RETURN
/**----------------------------------------------------------------*/
GET_PROC_NME:
proc_found = 'NO'
"EXECIO 1 DISKR INJCL 4 "
PARSE PULL exec_ln
excol = INDEX(exec_ln,'EXEC')
IF SUBSTR(exec_ln,excol,4) = 'EXEC' THEN
DO
proc_found = 'YES'
procnme = SUBSTR(exec_ln,excol + 5,8)
SAY 'Procedure ' procnme ' found in JCLCARD.'
END
RETURN
/**----------------------------------------------------------------*/
READ_PROC:
IF proc_found = 'YES' THEN
DO
procdsn = "'" ³³ 'XXXX.XXX.PROCLIB(' ³³ procnme ³³ ")'"
/* checks if proc member exists */
sysdsn_msg = SYSDSN(procdsn)
IF sysdsn_msg = 'OK' THEN
DO
search_ovr = 'YES'
CALL ALLOC_INPROC
/* this will read proc overrides and stores them */
CALL READ_JCLCARD
SAY 'Reading ' procdsn
/* writes the first line of the procedure using jclcard */
Write_line.1 = '//' ³³ jclcard ³³ ' PROC PR1=, '
/* starts reading at line #2 */
proc_lctr = 2
end_of_symb = 'NO'
/* initial read of procedure */
"EXECIO 1 DISKR INPROC 2"
PULL procline
/* this loop if for processing symbolics */
CALL PROCESS_SYMBS
/* this will remove the comma on the last symbolic */
CALL REMOVE_COMMA
/* this loop if for copying the procedure body */
CALL COPY_PROC
/* this will close the proc file */
"EXECIO 0 DISKR INPROC (FINIS"
END
END
RETURN
/**----------------------------------------------------------------*/
ALLOC_INCARD:
/* allocates input proc for reading */
"ALLOCATE FILE(INJCL) DATASET("cardmem") SHR REUSE"
IF RC ª= 0 THEN
DO
SAY 'Error opening ' cardmem ' for reading. RC=30'
EXIT
END
RETURN
/**----------------------------------------------------------------*/
ALLOC_INPROC:
/* allocates input proc for reading */
"ALLOCATE FILE(INPROC) DATASET("procdsn") SHR REUSE"
IF RC ª= 0 THEN
DO
SAY 'Error opening ' procdsn ' for reading. RC=30'
EXIT
END
RETURN
/**----------------------------------------------------------------*/
READ_JCLCARD:
jcl_lctr = 0
/* reads and stores overrides until end of jclcard file */
"EXECIO 1 DISKR INJCL"
DO WHILE RC = 0
PARSE PULL jcl_line
jcl_lctr = jcl_lctr + 1
jclsym_val.jcl_lctr = jcl_line
/* // symbolic = override */
PARSE VAR jcl_line . jclsym.jcl_lctr '=' jclval.jcl_lctr
/* we get the column of the last byte of the override */
comma_col = LENGTH(SPACE(jclval.jcl_lctr))
/* if last column is not comma, insert a comma */
IF SUBSTR(jclval.jcl_lctr,comma_col,1) ª= ',' THEN
jclval.jcl_lctr = INSERT(",",jclval.jcl_lctr,comma_col)
/* read another line of the jclcard */
"EXECIO 1 DISKR INJCL"
END
SAY 'There are ' jcl_lctr ' overrides in ' jclcard
RETURN
/**----------------------------------------------------------------*/
PROCESS_SYMBS:
DO UNTIL end_of_symb = 'YES'
/* this will retrieve stored overrides and substitute */
/* overrides if values match a proc symbolics */
CALL SUBST_OVRRD
/* read another line */
"EXECIO 1 DISKR INPROC"
PULL procline
proc_lctr = proc_lctr + 1
IF SUBSTR(procline,3,10) = '**********'
THEN end_of_symb = 'YES'
END
RETURN
/**----------------------------------------------------------------*/
REMOVE_COMMA:
last_sym_ctr = proc_lctr - 1
Write_Last_Sym = STRIP(Write_Line.last_sym_ctr,'T',",")
Write_Line.last_sym_ctr = Write_Last_Sym
RETURN
/**----------------------------------------------------------------*/
COPY_PROC:
DO WHILE RC = 0
Write_Line.proc_lctr = procline
"EXECIO 1 DISKR INPROC"
PULL procline
proc_lctr = proc_lctr + 1
END
RETURN
/**----------------------------------------------------------------*/
SUBST_OVRRD:
loop_ctr = 1
ovrrd_found = 'NO'
/* this will search the overrides array for values */
PARSE VAR procline . procsym.proc_lctr '=' .
PARSE VAR procline procsubln '='
DO UNTIL loop_ctr > jcl_lctr
IF procsym.proc_lctr = jclsym.loop_ctr THEN
DO
ovrrd_found = 'YES'
Write_Line.proc_lctr = procsubln ³³ '=' ³³ jclval.loop_ctr
END
loop_ctr = loop_ctr + 1
END
IF ovrrd_found = 'NO' THEN
Write_Line.proc_lctr = procline
RETURN
/**----------------------------------------------------------------*/
WRITE_SUBSTJOB:
/* frees input jclcard */
/* frees input proc */
"FREE FILE(INJCL INPROC)"
/* frees output file */
"ALLOC DS("outproc") DD(OUTFLE) SHR"
"EXECIO * DISKW OUTFLE (STEM Write_Line. FINIS"
"FREE F(OUTFLE)"
"FREE DATASET("outproc")"
SAY 'Output dataset ' outproc 'created'
ADDRESS ISPEXEC "EDIT DATASET("outproc")"
RETURN
/**----------------------------------------------------------------*/
Joined: 06 Nov 2008 Posts: 46 Location: Manila, Philippines
Note that:
Code:
/*----------------------------------------------------------------*/
/* This will work only if the following assumptions are satisfied */
/* (1) The JCLCARD is in XXXX.XXX.JCLCARD */
/* (2) The PROC NAME found in the JCLCARD satisfies the ff: */
/* (a) The PROC is in XXXX.XXX.PROCLIB */
/* (b) The PROC uses PR1 symbolic in the first line */
/* (c) The PROC's first comment line is AT THE END of */
/* ALL SYMBOLICS */
/*----------------------------------------------------------------*/
If you'll use it, adjust the codes to allow processing if any of the above is not satisfied