View previous topic :: View next topic
|
Author |
Message |
Chhandak Chakraborty
New User
Joined: 22 Jul 2015 Posts: 6 Location: India
|
|
|
|
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 |
|
|
Nic Clouston
Global Moderator
Joined: 10 May 2007 Posts: 2455 Location: Hampshire, UK
|
|
|
|
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 |
|
|
Chhandak Chakraborty
New User
Joined: 22 Jul 2015 Posts: 6 Location: India
|
|
|
|
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 |
|
|
Garry Carroll
Senior Member
Joined: 08 May 2006 Posts: 1193 Location: Dublin, Ireland
|
|
|
|
First, using DO UNTIL is generally not recommended. It would be simpler to replace both DO UNTILs with
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
Garry. |
|
Back to top |
|
|
Chhandak Chakraborty
New User
Joined: 22 Jul 2015 Posts: 6 Location: India
|
|
|
|
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
/* ------------------------------------------------------------ */
/* ============================================================ */
|
|
Back to top |
|
|
Garry Carroll
Senior Member
Joined: 08 May 2006 Posts: 1193 Location: Dublin, Ireland
|
|
|
|
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 |
|
|
enrico-sorichetti
Superior Member
Joined: 14 Mar 2007 Posts: 10873 Location: italy
|
|
|
|
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 (*)
(*) IOW ... we really do not care ... |
|
Back to top |
|
|
don.leahy
Active Member
Joined: 06 Jul 2010 Posts: 765 Location: Whitby, ON, Canada
|
|
|
|
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 |
|
|
enrico-sorichetti
Superior Member
Joined: 14 Mar 2007 Posts: 10873 Location: italy
|
|
|
|
IMNSHO
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 |
|
|
Chhandak Chakraborty
New User
Joined: 22 Jul 2015 Posts: 6 Location: India
|
|
|
|
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 |
|
|
Nic Clouston
Global Moderator
Joined: 10 May 2007 Posts: 2455 Location: Hampshire, UK
|
|
|
|
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 |
|
|
prino
Senior Member
Joined: 07 Feb 2009 Posts: 1306 Location: Vilnius, Lithuania
|
|
|
|
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 |
|
|
Pedro
Global Moderator
Joined: 01 Sep 2006 Posts: 2547 Location: Silicon Valley
|
|
|
|
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 |
|
|
Pedro
Global Moderator
Joined: 01 Sep 2006 Posts: 2547 Location: Silicon Valley
|
|
|
|
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 |
|
|
Mickeydusaor
Active User
Joined: 24 May 2006 Posts: 258 Location: Salem, Oregon
|
|
|
|
Exactly Pedro, I have never heard of such a waste of time and resources |
|
Back to top |
|
|
don.leahy
Active Member
Joined: 06 Jul 2010 Posts: 765 Location: Whitby, ON, Canada
|
|
|
|
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 |
|
|
RahulG31
Active User
Joined: 20 Dec 2014 Posts: 446 Location: USA
|
|
|
|
@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 |
|
|
Chhandak Chakraborty
New User
Joined: 22 Jul 2015 Posts: 6 Location: India
|
|
|
|
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 |
|
|
Chhandak Chakraborty
New User
Joined: 22 Jul 2015 Posts: 6 Location: India
|
|
|
|
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 |
|
|
enrico-sorichetti
Superior Member
Joined: 14 Mar 2007 Posts: 10873 Location: italy
|
|
|
|
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 |
|
|
Nic Clouston
Global Moderator
Joined: 10 May 2007 Posts: 2455 Location: Hampshire, UK
|
|
|
|
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 |
|
|
Pedro
Global Moderator
Joined: 01 Sep 2006 Posts: 2547 Location: Silicon Valley
|
|
|
|
Quote: |
I came here expecting some solution to my problem |
I gave you useful feedback on your code.
You are welcome. |
|
Back to top |
|
|
Rohit Umarjikar
Global Moderator
Joined: 21 Sep 2010 Posts: 3053 Location: NYC,USA
|
|
|
|
Can you make a use of ISRLEMX ? |
|
Back to top |
|
|
Marso
REXX Moderator
Joined: 13 Mar 2006 Posts: 1353 Location: Israel
|
|
|
|
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 |
|
|
RahulG31
Active User
Joined: 20 Dec 2014 Posts: 446 Location: USA
|
|
|
|
@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 |
|
|
|