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

REXX code to expand all submodules inside calling program


IBM Mainframe Forums -> CLIST & REXX
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
Chhandak Chakraborty

New User


Joined: 22 Jul 2015
Posts: 6
Location: India

PostPosted: Thu Jul 23, 2015 10:22 am
Reply with quote

Hi Everyone,

I am working on a REXX code which would expand all submodules inside the calling program. Previously, for a similar kind of work I referred the code snippet to expand copybooks. However, I am not able to expand the submodules. Any help on this would be much appreciated. Thanks!
Back to top
View user's profile Send private message
Nic Clouston

Global Moderator


Joined: 10 May 2007
Posts: 2455
Location: Hampshire, UK

PostPosted: Thu Jul 23, 2015 2:35 pm
Reply with quote

First: do it manually, writing down each step you undertake
Second: take that information and create a program design
Third: create your pseudo code
Fourth: write your code
Fifth: test

Look out for CALL variable_name type calls as you will have to back-track through your code to find where the program name is assigned to that variable.
Back to top
View user's profile Send private message
Chhandak Chakraborty

New User


Joined: 22 Jul 2015
Posts: 6
Location: India

PostPosted: Thu Jul 23, 2015 3:03 pm
Reply with quote

This is the code I have written. Can you please let me know where I am doing the incorrect -

Code:
ADDRESS ISREDIT
"MACRO PROCESS"
/* ============================================================ */
SUBLIB = "PROD.STANDARD.COB.SOURCE" /* name of cobol submodule  lib*/
C_CNT = 0
/* ------------------------------------------------------------ */
/* LOOP THROUGH PROGRAM SOURCE */
"(CURRLN) = LINENUM .ZCSR"            /* CURRENT LINE           */
"(LASTLN) = LINENUM .ZLAST"           /* LAST LINE NUMBER       */
I = 1
DO UNTIL I > 5
I = I + 1
END
I = 1
  DO UNTIL I > LASTLN
   "(LINE)  = LINE " I
   LINE = SUBSTR(LINE,7,64)
   X = POS('CALL',LINE)
   Y = X+6
   IF X = 0 THEN
   NOP
   ELSE DO
   SBM = SUBSTR(LINE,Y,8)
   END
  I = I + 1
   CALL EXPAND_SUBMODULES
END

"UP MAX"
"DOWN " CURRLN


EXIT 0

/* ------------------------------------------------------------ */
EXPAND_SUBMODULES:
   SAY 'ENTERING FOR EXPANSION'
   /* CHECK IF SUBMODUL EXISTS */
   DSN = SUBLIB || "("SBM")"
   RC = SYSDSN("'"DSN"'")
   IF (RC \= 'OK') THEN DO
      MSG = "'SUBMODULE NOT FOUND:" SBM "'"
      "ISREDIT LINE_AFTER " I "= NOTELINE" MSG
      RETURN
   END
   C_CNT = C_CNT + 1

   /* READ SUBMODULE */
   ADDRESS TSO
   "ALLOC FI(IFILE) DA('" || DSN || "') SHR"
   'EXECIO * DISKR IFILE (STEM BOOK.'
   'EXECIO 0 DISKR IFILE (FINIS'
   'FREE F(IFILE)'
   ADDRESS ISREDIT

   /* PASTE EXPANDED SUBMODULE INTO PROGRAM SOURCE */
   IF I < CURRLN THEN CURRLN = CURRLN + BOOK.0   /* COUNT NEW LINES */
   LN = I
   P  = 1
   D  = +1
   DO J = 1 TO BOOK.0
      MARK = '|====|'
      TXT = SUBSTR(BOOK.J,7,66)
      TXT = TRANSLATE(TXT,"'",'"')   /* DOUBLE TO SINGLE QUOTE */
      MSG = '"' || MARK || TXT || SBM || '"'
      "ISREDIT LINE_AFTER " LN "= DATALINE" MSG
      LN = LN + 1
   END
  LASTLN = LASTLN + BOOK.0    /* ADD SUBMODULE LINES */
RETURN
  /* ------------------------------------------------------------ */
  /* ============================================================ */


Code'd
Back to top
View user's profile Send private message
Garry Carroll

Senior Member


Joined: 08 May 2006
Posts: 1193
Location: Dublin, Ireland

PostPosted: Thu Jul 23, 2015 4:18 pm
Reply with quote

First, using DO UNTIL is generally not recommended. It would be simpler to replace both DO UNTILs with

Code:
 DO I = 6 to LASTLN


Next, will the name of the called sub-module always start after exactly two spaces following the CALL keyword? If the called sub-module name is shorter that eight characters, will the trailing bytes always be blank?

Have you traced execution to see the submodule being read ?

In the EXPAND_SUBMODULES: routine, you can combine the two EXECIO statements into one

Code:
"EXECIO * DISKR IFILE (FINIS STEM BOOK. "



Every time you enter EXPAND_SUBMODULES, CURRLN is pointing to the start of the source module - I don't see you increment or reset it. The line
Code:

IF I < CURRLN THEN CURRLN = CURRLN + BOOK.0   /* COUNT NEW LINES */

is redundant as "I" will always be > CURRLN.

What is the purpose of

Code:
   P  = 1
   D  = +1


Garry.
Back to top
View user's profile Send private message
Chhandak Chakraborty

New User


Joined: 22 Jul 2015
Posts: 6
Location: India

PostPosted: Thu Jul 23, 2015 5:32 pm
Reply with quote

Hey Garry,

Thanks for your response. I am very new to REXX so don't have that much of knowledge. However, let me try to answer your questions -
1. More or less in all cases the submodule name is started after 2 spaces after CALL
2. There are cases where submodule length is less than 8 bytes - not sure how to handle that, I tried using LENGTH function but that didn't work
3. combine the two EXECIO statements into one - I have included it now
4. CURRLN is pointing to the start of the source module - I don't see you increment or reset it - I understand this point, but not able to implement the logic with proper syntax - would be great if you could please help
5. Purpose of p=1 and D=+1 - It was for my previous copybook expansion code, can be ignored.

My current code looks like this -

ADDRESS ISREDIT
"MACRO PROCESS"
/* ============================================================ */
SUBLIB = "PROD.STANDARD.BATCH.SOURCE"
C_CNT = 0
/* ------------------------------------------------------------ */
/* LOOP THROUGH PROGRAM SOURCE */
"(CURRLN) = LINENUM .ZCSR" /* CURRENT LINE */
"(LASTLN) = LINENUM .ZLAST" /* LAST LINE NUMBER */
I = 1
DO I = 6 TO LASTLN
I = I + 1
END
I = 1
DO I = 6 TO LASTLN
"(LINE) = LINE " I
LINE = SUBSTR(LINE,7,64)
X = POS('CALL',LINE)
Y = X+6
IF X = 0 THEN
NOP
ELSE DO
SBM = SUBSTR(LINE,Y,8)
END
I = I + 1
CALL EXPAND_SUBMODULES
END

"UP MAX"
"DOWN " CURRLN
ZEDLMSG = 'The tool has removed ' C_CNT 'EXPANDED SUBMODULE'
ADDRESS ISPEXEC "SETMSG MSG(ISRZ000)"

EXIT 0
/* ------------------------------------------------------------ */
EXPAND_SUBMODULES:
/* CHECK IF SUBMODUL EXISTS */
DSN = SUBLIB || "("SBM")"
RC = SYSDSN("'"DSN"'")
IF (RC \= 'OK') THEN DO
MSG = "'SUBMODULE NOT FOUND:" SBM "'"
"ISREDIT LINE_AFTER " I "= NOTELINE" MSG
RETURN
END
C_CNT = C_CNT + 1

/* READ SUBMODULE */
ADDRESS TSO
"ALLOC FI(IFILE) DA('" || DSN || "') SHR"
'EXECIO * DISKR IFILE (FINIS STEM BOOK.'
/*'EXECIO 0 DISKR IFILE (FINIS' */
'FREE F(IFILE)'
SAY 'ENTERING FOR EXPANSION'
ADDRESS ISREDIT

/* PASTE EXPANDED SUBMODULE INTO PROGRAM SOURCE */
IF I < CURRLN THEN CURRLN = CURRLN + BOOK.0 /* COUNT NEW LINES */
LN = I
/*P = 1
D = +1 */
DO J = 1 TO BOOK.0
MARK = '|====|'
TXT = SUBSTR(BOOK.J,7,66)
TXT = TRANSLATE(TXT,"'",'"') /* DOUBLE TO SINGLE QUOTE */
MSG = '"' || MARK || TXT || SBM || '"'
"ISREDIT LINE_AFTER " LN "= DATALINE" MSG
LN = LN + 1
END
LASTLN = LASTLN + BOOK.0 /* ADD SUBMODULE LINES */
RETURN
/* ------------------------------------------------------------ */
/* ============================================================ */
Code:
Back to top
View user's profile Send private message
Garry Carroll

Senior Member


Joined: 08 May 2006
Posts: 1193
Location: Dublin, Ireland

PostPosted: Thu Jul 23, 2015 5:50 pm
Reply with quote

Hi Chhandak,

To extract the sub-module name, you could use two loops

Code:
X = POS('CALL',LINE)
/* skip past blanks after the CALL */
do n = (x+4) to LENGTH(LINE) ,
    while(substr(LINE,n,1) = " "
end
/* n = start of sub-module name */
/* find the end of the sub-module name */
do p = n to LENGTH(LINE),
    while(substr(LINE,p,1) ¬= " "
end
/* you might want to check that it didn't exceed 8 ?*/
subm_len = p - n
SBM = substr(LINE,n,subn_len)


For item 4 in your list, you could move this to AFTER you've appended the lines and change the < to > ?

However, when you insert and add the sub-modules lines, won't you also need to update LASTLN since, when you go back from EXPAND_SUBMODULES, the "I" counter will now point to the first line of the sub-module expansion? You should probably update "I" to allow for the lines just added, too.

Garry.
Back to top
View user's profile Send private message
enrico-sorichetti

Superior Member


Joined: 14 Mar 2007
Posts: 10872
Location: italy

PostPosted: Thu Jul 23, 2015 11:17 pm
Reply with quote

so, if You call a sub_whatever_you_call_it 20 times You are going to inline the code 20 times ???

does not look like a too smart approach,
but if You and Your organisation are happy we are happy (*)
icon_cool.gif

(*) IOW ... we really do not care ...
Back to top
View user's profile Send private message
don.leahy

Active Member


Joined: 06 Jul 2010
Posts: 765
Location: Whitby, ON, Canada

PostPosted: Fri Jul 24, 2015 12:08 am
Reply with quote

Another approach is to examine the Cross-reference in the compile listing.
Code:
 Defined   Cross-reference of programs     References       
                                                             
EXTERNAL   AIBTDLI. . . . . . . . . . . .  14115             
EXTERNAL   DSNHADDR . . . . . . . . . . .  11168 11174 11178
EXTERNAL   DSNHADD2 . . . . . . . . . . .  11170 11176       
EXTERNAL   DSNHLI . . . . . . . . . . . .  14016             
EXTERNAL   xxxxBRN. . . . . . . . . . . .  13765             
     570   xxxxABO4                                         
EXTERNAL   xxxxACCE . . . . . . . . . . .  13824             
EXTERNAL   xxxxAORV . . . . . . . . . . .  13640             
This of course will not catch 'call variable' cases like CALL WS-PROGRAM-NAME. That is a difficult one to crack; WS-PROGRAM-NAME might be set by a value in a copycode or perhaps even an external file or data base. But it should catch weird cases like
Code:
CALL

     'MYPROG' USING WS-WHATEVER
where the program name is not on the same line as the CALL
Back to top
View user's profile Send private message
enrico-sorichetti

Superior Member


Joined: 14 Mar 2007
Posts: 10872
Location: italy

PostPosted: Fri Jul 24, 2015 2:05 am
Reply with quote

IMNSHO icon_cool.gif

a better option would be to use the ISPF provided member parts list...
it will cross reference calls and includes

You can ask for a raw output and process it with rexx


naturally it will not track dynamic calls,
but neither will any approach looking only at the source code.
Back to top
View user's profile Send private message
Chhandak Chakraborty

New User


Joined: 22 Jul 2015
Posts: 6
Location: India

PostPosted: Fri Jul 24, 2015 2:42 pm
Reply with quote

Thanks for the response everyone. But I am still not able to make this out. Can some one explicitly mention what are the changes need to be done?

Following is the code, I have currently written -

Code:
ADDRESS ISREDIT
"MACRO PROCESS"
/* ============================================================ */
SUBLIB = "PROD.STANDARD.BATCH.SOURCE"
C_CNT = 0
/* ------------------------------------------------------------ */
/* LOOP THROUGH PROGRAM SOURCE */
"(CURRLN) = LINENUM .ZCSR" /* CURRENT LINE */
"(LASTLN) = LINENUM .ZLAST" /* LAST LINE NUMBER */
I = 1
DO I = 6 TO LASTLN
   I = I + 1
END
I = 1
DO I = 6 TO LASTLN
   "(LINE) = LINE " I
   LINE = SUBSTR(LINE,7,64)
   X = POS('CALL',LINE)
   Y = X+6
   IF X = 0 THEN
       NOP
   ELSE DO
      SBM = SUBSTR(LINE,Y,8)
   END
   I = I + 1
   CALL EXPAND_SUBMODULES
END

"UP MAX"
"DOWN " CURRLN
ZEDLMSG = 'The tool has removed ' C_CNT 'EXPANDED SUBMODULE'
ADDRESS ISPEXEC "SETMSG MSG(ISRZ000)"

EXIT 0
/* ------------------------------------------------------------ */
EXPAND_SUBMODULES:
/* CHECK IF SUBMODUL EXISTS */
DSN = SUBLIB || "("SBM")"
RC = SYSDSN("'"DSN"'")
IF (RC \= 'OK') THEN DO
   MSG = "'SUBMODULE NOT FOUND:" SBM "'"
   "ISREDIT LINE_AFTER " I "= NOTELINE" MSG
   RETURN
END
C_CNT = C_CNT + 1

/* READ SUBMODULE */
ADDRESS TSO
"ALLOC FI(IFILE) DA('" || DSN || "') SHR"
'EXECIO * DISKR IFILE (FINIS STEM BOOK.'
/*'EXECIO 0 DISKR IFILE (FINIS' */
'FREE F(IFILE)'
SAY 'ENTERING FOR EXPANSION'
ADDRESS ISREDIT

/* PASTE EXPANDED SUBMODULE INTO PROGRAM SOURCE */
IF I < CURRLN THEN CURRLN = CURRLN + BOOK.0 /* COUNT NEW LINES */
LN = I
/*P = 1
D = +1 */
DO J = 1 TO BOOK.0
   MARK = '|====|'
   TXT = SUBSTR(BOOK.J,7,66)
   TXT = TRANSLATE(TXT,"'",'"') /* DOUBLE TO SINGLE QUOTE */
   MSG = '"' || MARK || TXT || SBM || '"'
   "ISREDIT LINE_AFTER " LN "= DATALINE" MSG
   LN = LN + 1
END
LASTLN = LASTLN + BOOK.0 /* ADD SUBMODULE LINES */
RETURN
/* ------------------------------------------------------------ */
/* ============================================================ */
Back to top
View user's profile Send private message
Nic Clouston

Global Moderator


Joined: 10 May 2007
Posts: 2455
Location: Hampshire, UK

PostPosted: Fri Jul 24, 2015 5:44 pm
Reply with quote

It would help if you indented your code. Peolpe would be able to read it more esily and realise the structure of your program. I have indented it for you. Whilst doing this I noticed this bit of code:
Code:
IF X = 0 THEN
   NOP
ELSE DO
   SBM = SUBSTR(LINE,Y,8)
END

Why not
Code:
If x <> 0
Then SBM = Substr(line, y, 8)

?
Back to top
View user's profile Send private message
prino

Senior Member


Joined: 07 Feb 2009
Posts: 1306
Location: Vilnius, Lithuania

PostPosted: Fri Jul 24, 2015 9:07 pm
Reply with quote

And this is also very useful:
Code:
I = 1
DO I = 6 TO LASTLN
   I = I + 1
END
I = 1

?????

Why the flipping 'ell are you actually writing this "a REXX code".

Oh, sorry I forgot, you've got to create client-billable time...
Back to top
View user's profile Send private message
Pedro

Global Moderator


Joined: 01 Sep 2006
Posts: 2546
Location: Silicon Valley

PostPosted: Fri Jul 24, 2015 9:44 pm
Reply with quote

With Nic's correction, you have this:
Code:

 000001 DO I = 6 TO LASTLN                 
 000002    "(LINE) = LINE " I               
 000003    LINE = SUBSTR(LINE,7,64)         
 000004    X = POS('CALL',LINE)             
 000005    Y = X+6                         
 000006    IF X <> 0                       
 000007       THEN SBM = SUBSTR(LINE, Y, 8)
 000008    I = I + 1                       
 000009    CALL EXPAND_SUBMODULES           
 000010 END                                 

1. If the file has 97 records, Line 1 of this code example will initialize 'I' to 6 and then automatically increment for each iteration of the loop until it reaches 97. You do not need to manually increment I in line number 8. When you manually increment it, you are skipping every second line. Remove line 8 to process each line.

2. You call your subroutine in line 9 for each record. I think the call should be in a DO group along with line 7, so that the call to the subroutine is done only when 'CALL' is found.

3. This: POS('CALL',LINE), is prone to false positives. For example, CALL being a suffix to another string, or CALL being within a comment block. Likely, mixed case situations would fail.

4. You are using an editor macro, so my suggestion is to use the power of the editor to find your text.
Code:
Findrc = 0                     
Do While (Findrc = 0)           
   "FIND 'CALL' WORD"           
   Findrc = RC                 
   If (Findrc = 0) Then         
     Do                         
       /* process this line */ 
     End                       
End                             


Yeah, I realize #4 makes #1 thru #3 somewhat irrelevant. But perhaps someone can learn from those mistakes.
Back to top
View user's profile Send private message
Pedro

Global Moderator


Joined: 01 Sep 2006
Posts: 2546
Location: Silicon Valley

PostPosted: Fri Jul 24, 2015 9:58 pm
Reply with quote

You seem to insert the source of the called routine into the main routine. I agree with Enrico about this being a poor design choice. I think this would also be confusing to the reader and perhaps might corrupt the main file.
Back to top
View user's profile Send private message
Mickeydusaor

Active User


Joined: 24 May 2006
Posts: 258
Location: Salem, Oregon

PostPosted: Fri Jul 24, 2015 10:51 pm
Reply with quote

Exactly Pedro, I have never heard of such a waste of time and resources
Back to top
View user's profile Send private message
don.leahy

Active Member


Joined: 06 Jul 2010
Posts: 765
Location: Whitby, ON, Canada

PostPosted: Sat Jul 25, 2015 12:34 am
Reply with quote

I misunderstood the TS's original question; I thought the goal was to identify external references to subroutines. (IMO that topic has been beaten to death on this forum).

Anyway, I agree that inserting the source from a called module is a bad idea.

However, I do have a tool that I use to bring in copybook definitions for easy reference. The lines are brought in as INFOLINEs, so unless you make a special effort using the MD line command, the lines are not saved with the member.

In practice, the longer the copycode, the less useful this tool is. The main reason is that the FIND command ignores INFOLINES, so finding a particular field in the copybook is a tedious exercise.
Back to top
View user's profile Send private message
RahulG31

Active User


Joined: 20 Dec 2014
Posts: 446
Location: USA

PostPosted: Sat Jul 25, 2015 1:16 am
Reply with quote

@Chhandak: If I may ask, Why are you doing it?

In my opinion, It is a good idea to expand a copybook but to expand a submodule is a different thing.

If you really want to see the submodule code without changing the screen then you can write a simple macro that searches the module name on which the cursor is present in a library of your choice. Map this macro with any function key (say PF2).

I am not sure if I am deviating from the topic, but I would just like to know the need for doing this. It may be helpful for me and others if you can share that.
Back to top
View user's profile Send private message
Chhandak Chakraborty

New User


Joined: 22 Jul 2015
Posts: 6
Location: India

PostPosted: Mon Jul 27, 2015 11:36 am
Reply with quote

Hello All,

Well that might seem IRRELEVANT for you that pasting the expanded submodules inside the main code but that's what my requirement actually is.

I didn't drop in here to check if the task I am working on is relevant or not, I came here expecting some solution to my problem at the position I got stuck.

Nevermind!!
Back to top
View user's profile Send private message
Chhandak Chakraborty

New User


Joined: 22 Jul 2015
Posts: 6
Location: India

PostPosted: Mon Jul 27, 2015 11:40 am
Reply with quote

Hey Rahul,

Thanks for writing. Yeah, even if that can be done that you place the cursor just beneath the the submodule name and press any certain key and the submodule opens - I would be more than happy. If you have something handy like this, would you please share? Thanks a ton in advance!
Back to top
View user's profile Send private message
enrico-sorichetti

Superior Member


Joined: 14 Mar 2007
Posts: 10872
Location: italy

PostPosted: Mon Jul 27, 2015 3:29 pm
Reply with quote

Quote:
I didn't drop in here to check if the task I am working on is relevant or not, I came here expecting some solution to my problem at the position I got stuck.

pretty inconsiderate remark,

people replying here are professionals,
so when they see a VERY poor requirement they point it out
with the result that the chances of getting help for it will be small

and with Your attitude the chances of getting help will be even less
Back to top
View user's profile Send private message
Nic Clouston

Global Moderator


Joined: 10 May 2007
Posts: 2455
Location: Hampshire, UK

PostPosted: Mon Jul 27, 2015 3:55 pm
Reply with quote

If all you need to see is your main program code and the code of the sub-program that is cuerrently the focus of your main program then why not use the basic facilities of an ISPF session - multiple screens, split or full screen?

In your initial requirement, how were you going to handle recursive programs? Did you even think about that?
Back to top
View user's profile Send private message
Pedro

Global Moderator


Joined: 01 Sep 2006
Posts: 2546
Location: Silicon Valley

PostPosted: Mon Jul 27, 2015 9:10 pm
Reply with quote

Quote:
I came here expecting some solution to my problem

I gave you useful feedback on your code.

You are welcome.
Back to top
View user's profile Send private message
Rohit Umarjikar

Global Moderator


Joined: 21 Sep 2010
Posts: 3048
Location: NYC,USA

PostPosted: Mon Jul 27, 2015 10:29 pm
Reply with quote

Can you make a use of ISRLEMX ?
Back to top
View user's profile Send private message
Marso

REXX Moderator


Joined: 13 Mar 2006
Posts: 1353
Location: Israel

PostPosted: Tue Jul 28, 2015 12:27 pm
Reply with quote

I did that, and much more...
When running the macro I show at the top of the program:
Code:
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
-IPT- EDIT HLQ.DEV.COBOL(MYMNPROG) - 01.22                 Columns 00001 00072
Command ===>                                                  Scroll ===> CSR 
****** ***************************** Top of Data ******************************
==MSG>    Found the following routines:
=NOTE=    +----------------+----------------+----------------+----------------+
=NOTE=    | CALL  WRTTOLOG | CALL  SOMEPROG | XCTL  CICSPROG |                |
=NOTE=    +----------------+----------------+----------------+----------------+
MSG lines are hilighted (white), NOTE lines are normal (blue)
It is then easy to copy/paste the subprogram name, FIND it in the program or bringing it in edit (every site has its own macro for this).
Back to top
View user's profile Send private message
RahulG31

Active User


Joined: 20 Dec 2014
Posts: 446
Location: USA

PostPosted: Tue Jul 28, 2015 8:06 pm
Reply with quote

@Chhandak: I don't have that handy but what you need to do is:

1. get the line data
2. parse line data to get the module name
3. view dataset by hardcoding the library name (where module resides) concatenated by member name you get from parse
4. map this macro with any function key

It's all available on the internet. If you face any problem in doing that, you may post on the forum. But first, you have to try.
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 -> CLIST & REXX Goto page 1, 2  Next

 


Similar Topics
Topic Forum Replies
No new posts Using API Gateway from CICS program CICS 0
No new posts Running REXX through JOB CLIST & REXX 13
No new posts Error to read log with rexx CLIST & REXX 11
No new posts isfline didnt work in rexx at z/OS ve... CLIST & REXX 7
No new posts run rexx code with jcl CLIST & REXX 15
Search our Forums:

Back to Top