MVSFORUMS.com Forum Index MVSFORUMS.com
A Community of and for MVS Professionals
 
 FAQFAQ   SearchSearch   Quick Manuals   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Compiling Rexx scripts

 
Post new topic   Reply to topic   printer-friendly view    MVSFORUMS.com Forum Index -> TSO and ISPF
View previous topic :: View next topic  
Author Message
misi01
Advanced


Joined: 02 Dec 2002
Posts: 629
Topics: 176
Location: Stockholm, Sweden

PostPosted: Wed Jan 10, 2024 10:51 am    Post subject: Compiling Rexx scripts Reply with quote

I searched the forum, but couldn't find anything that seemed relevant.
I am playing with compiling some Rexx code and have a few questions.

- when compiling, the compiled code ends up in a PDS. I'm assuming that every script has to/should be compiled into the same PDS? From what I've read, I understood it to be that if I have, say, 3 scripts, A, B and C and A & B are compiled into PDS1 (first in the chain of libraries) and C is uncompiled in PDS2, then Rexx will automatically "switch over" to PDS2 to run C from A or B?
- is it possible to/should one "link" all the scripts into one MASSIVE script. If it's possible, are there any particular advantages?
- I read somewhere a discussion about compiling panels as well (I assume they meant ISPF ones). Is this necessary, and is there any real point to it?

Thank you.
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
kolusu
Site Admin
Site Admin


Joined: 26 Nov 2002
Posts: 12376
Topics: 75
Location: San Jose

PostPosted: Wed Jan 17, 2024 5:36 pm    Post subject: Re: Compiling Rexx scripts Reply with quote

misi01 wrote:

- when compiling, the compiled code ends up in a PDS.


what do you mean by ends up in a PDS ? How are you compiling? PGM=REXXCOMP

Check the REXXCL (FANCMCL) or REXXCLG (FANCMCLG) procedure as to how the compile is done.

https://www.ibm.com/docs/en/zos/3.1.0?topic=reference-zos-cataloged-procedures-supplied-by

misi01 wrote:

I'm assuming that every script has to/should be compiled into the same PDS? From what I've read, I understood it to be that if I have, say, 3 scripts, A, B and C and A & B are compiled into PDS1 (first in the chain of libraries) and C is uncompiled in PDS2, then Rexx will automatically "switch over" to PDS2 to run C from A or B?


When you compile you create an object deck and when you link edit it it will become executable load module. So a compiled rexx is NO longer an interpreted code at run time.

misi01 wrote:


- I read somewhere a discussion about compiling panels as well (I assume they meant ISPF ones). Is this necessary, and is there any real point to it?


well the panels will do the same thing as executing the catalogued procedures under the covers. Check this link

https://www.ibm.com/docs/en/zos/3.1.0?topic=zos-invoking-compiler-ispf-panels
_________________
Kolusu
www.linkedin.com/in/kolusu
Back to top
View user's profile Send private message Send e-mail Visit poster's website
misi01
Advanced


Joined: 02 Dec 2002
Posts: 629
Topics: 176
Location: Stockholm, Sweden

PostPosted: Tue Feb 06, 2024 8:46 am    Post subject: Reply with quote

Thank you.
Lot to read and, I imagine, many pitfalls along the way Smile

Still, simply a matter of reading up, experimenting and taking notes of what to do to get it all working.
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
misi01
Advanced


Joined: 02 Dec 2002
Posts: 629
Topics: 176
Location: Stockholm, Sweden

PostPosted: Thu Feb 08, 2024 7:06 am    Post subject: Cannot preview append Reply with quote

I was going to append a long description of how my attempts went compiling Rexx scripts, but the preview button is still failing.
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
kolusu
Site Admin
Site Admin


Joined: 26 Nov 2002
Posts: 12376
Topics: 75
Location: San Jose

PostPosted: Thu Feb 08, 2024 3:21 pm    Post subject: Re: Cannot preview append Reply with quote

misi01 wrote:
I was going to append a long description of how my attempts went compiling Rexx scripts, but the preview button is still failing.


The preview is working fine for me using Firefox. What browser are you using? can you clear cookies and cache and see if it works?
_________________
Kolusu
www.linkedin.com/in/kolusu
Back to top
View user's profile Send private message Send e-mail Visit poster's website
misi01
Advanced


Joined: 02 Dec 2002
Posts: 629
Topics: 176
Location: Stockholm, Sweden

PostPosted: Fri Feb 09, 2024 4:39 am    Post subject: Experiences of compiling Rexx code. Reply with quote

After reading the documentation, it was actually easier than I thought.
The stripped down PROC I created was the same as that defined at

https://www.ibm.com/docs/en/zos/3.1.0?topic=by-rexxc-fancmc

My JCL to compile a script looked like this
Code:

//JCLLIB   JCLLIB ORDER=(S6843F.TEST.PROCLIB)               
//*                                                         
//*                                                         
//* Compile a Rexx script                                   
//*                                                         
// EXPORT SYMLIST=(MEMBER)                                   
// SET MEMBER=DL1DB232                                       
//*                                                         
//S1 EXEC REXXC                                             
//REXX.SYSCEXEC DD DSN=S6843F.TEST.CEXEC(&MEMBER),DISP=SHR   
//REXX.SYSPUNCH DD DSN=S6843F.TEST.OBJ(&MEMBER),DISP=SHR     
//REXX.SYSIN    DD DSN=S6843F.TEST.CLIST(&MEMBER),DISP=SHR   
//*


Now the interesting part started.
First of all, which member do you use, CEXEC or OBJ?
I'm sure it's in the docs SOMEWHERE, but I couldn't see it.
I tested using OBJ and received the following message

Quote:
STMT 1 OTHER THAN DBCS CHARACTER FOUND IN A DBCS STRING


Turns out that it's the CEXEC library.

Next part is that at OUR installation, you can define a special PDS and
member called userid.TEST.EXEC(xLDDNAME) which contains lines along these

Quote:

ISPMLIB S6843F.TEST.MSGS
ISPPLIB S6843F.TEST.PANELS
ISPSLIB S6843F.TEST.SKELS
SYSPROC S6843F.TEST.CEXEC <--- the compiled scripts
SYSPROC S6843F.TEST.CLIST <--- my Rexx scripts


Now, originally, my TEST.CLIST had DCB's of VB, 255, 3600.

I compiled a script (called MSGESQL) that uses panels and other scripts and compiled it (so it ended up in the CEXEC library).
I then renamed it to MSGESQLB in TEST.CLIST.
That way, I knew that if TSO MSGESQL worked correctly, it was because it was coming from the CEXEC library and not the TEST.CLIST one.

That's where I hit my first "problem". Starting TSO MSGESQL immediately gave the message

Quote:

An invalid record was found during exec load. This is an internal error.
42 +++ rc = dl1db232()
15 +++ rc = init()
Error 43 running compiled MSGESQL, line 42: Routine not found


DL1DB32 was NOT compiled into CEXEC, so I did that, and tried again.
This time I got the same message for a script called ISPFADD.
This is where I started to guess/realize that I either had to compile all the called scripts into the CEXEC library
..... OR .....
try copying TEST.CLIST to a library with the same DCB's as the CEXEC one. This time my xLDDNAME looked like this

Quote:
ISPMLIB S6843F.TEST.MSGS
ISPPLIB S6843F.TEST.PANELS
ISPSLIB S6843F.TEST.SKELS
SYSPROC S6843F.TEST.CEXEC <--- the compiled scripts
SYSPROC S6843F.TEST.CLIST.FB80 <--- same DCB's as TEST.CEXEC


I then deleted DL1DB232 from TEST.CEXEC, logged off and on and tried again. SUCCESS !!!!

Now it seems to turn out that Rexx scripts are run from CEXEC first and if not found there, then from TEST.CLIST.
Why was my original TEST.CLIST VB 255 ? Because all the other standard company EXEC/CLIST PDS's are.
My only "problem" now is that every time I log on to ISPF, I get the error message
Quote:

INVALID COMMAND NAME SYNTAX

every time before entering ISPF (I'm guessing it's something to do with our logon procedures, but
and I have no idea where it's coming from).
I've reported it, but it's a slight irritant rather than a serious error

All the standard libraries allocated to SYSPROC are defined as VB 255, so I thought I could copy TEST.CEXEC to
TEST.CEXEC.VB27998 (same DCB's as the other SYSPROC libraries).
For my troubles (TSO MSGESQL) I receive the following error

Quote:

System abend code 0C4, reason code 00000016.
IDI0001I Fault Analyzer V15R1M03 (UI94574 2023/11/22) invoked by IDIXDCAP using
SYS1.PARMLIB.IDI(IDICNF34)

ISPV028

IKJCT441 interface error
The caller is not in a CLIST or REXX environment. Return code = 40. This
could be a result of not having the function pool flag set in the ISPTCM
table for the command being executed.


so I'm guessing that the CEXEC library has to be FB 80 and the idea died.
(I'm assuming that the requisite DCB's are defined somewhere in the link you sent me, but again, it's not obvious)
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
kolusu
Site Admin
Site Admin


Joined: 26 Nov 2002
Posts: 12376
Topics: 75
Location: San Jose

PostPosted: Mon Feb 12, 2024 2:42 pm    Post subject: Reply with quote

misi01,

Here is the example that I use
Code:

//***************************************************************
//* COMPILE THE REXX EXEC                                       *
//***************************************************************
//REXX     EXEC PGM=REXXCOMP,                                   
//             PARM='CEXEC OBJECT NOCOMPILE(W) XREF'             
//SYSCEXEC DD DSN=&&EXEC(your.pgm.name),DISP=(NEW,PASS),               
//            UNIT=SYSDA,SPACE=(TRK,(10,5,1)),                   
//            DCB=(LRECL=80,RECFM=FB)                           
//SYSPRINT DD SYSOUT=*                                           
//SYSPUNCH DD DSN=&&OBJECT,DISP=(MOD,PASS),UNIT=SYSDA,           
//            SPACE=(800,(800,100)) 
//SYSIN    DD *
  Your rexx exec
/*
//*                                                               
//***************************************************************
//* Prepare SYSLIN data set for subsequent link step.           *
//***************************************************************
//PLKED    EXEC PGM=IRXJCL,PARM='REXXL MVS',COND=(0,LT,REXX)                       
//SYSEXEC  DD DISP=SHR,DSN=REXX.SEAGCMD                           
//SYSIN    DD DSN=&&OBJECT,DISP=(OLD,PASS)                       
//SYSTSPRT DD SYSOUT=*                                           
//SYSPRINT DD SYSOUT=*                                           
//SYSOUT   DD DSN=&&SYSOUT,DISP=(MOD,PASS),UNIT=SYSDA,           
//            DCB=(RECFM=FB,LRECL=80,BLKSIZE=800),               
//            SPACE=(800,(800,100))                               
//*
//***************************************************************
//* LINK TOGETHER STUB AND PROGRAM.                             *
//***************************************************************
//LKED     EXEC PGM=HEWL,PARM='LIST,AMODE=31,RMODE=ANY,RENT,MAP',
//             COND=((0,LT,REXX),(0,NE,PLKED))                                 
//SYSPRINT DD SYSOUT=*                                           
//SYSLIB   DD DISP=SHR,DSN=REXX.SEAGLMD                           
//SYSLIN   DD DSN=&&SYSOUT,DISP=(OLD,DELETE)                     
//SYSUT1   DD UNIT=SYSDA,SPACE=(1024,(200,20))                   
//SYSLMOD  DD DISP=OLD,DSN=your.loadlib.pds(pgmname)   << PDS/PDSE (RECFM=U, LRECL=0, BLKSIZE=27920 (pds) or 32760(pdse)         
//*


once you have it in the loadlib then you just need to execute like any other program
Code:

//STEP0100 EXEC PGM=your.pgm.name
//STEPLIB  DD DISP=SHR,DSN=Your.loadlib.name       
//SYSPRINT DD SYSOUT=*                               
//SYSOUT   DD SYSOUT=*                       

_________________
Kolusu
www.linkedin.com/in/kolusu
Back to top
View user's profile Send private message Send e-mail Visit poster's website
misi01
Advanced


Joined: 02 Dec 2002
Posts: 629
Topics: 176
Location: Stockholm, Sweden

PostPosted: Thu Feb 15, 2024 5:02 am    Post subject: Reply with quote

Thought I'd update this thread a bit more.
One of the "quirks" of the Rexx compiler (CREXX) is the fact that it is less "forgiving" than the interpretative variation (IREXX) (which is both good and bad, depending on ...)
For example, IREXX allows duplicate procedure names, whereas CREXX gives a compiler error. IREXX doesn't care if you have code such as
Code:

fred = left(bert)

(as long as you don't try to actually use it). CREXX gives a compiler error.

So, basically, unless there's some option I haven't noticed/don't know about, you have to review the JCL results of any Rexx compilation to check if your code is "invalid".
Not only that, but the results of the compilation (valid or not) ALWAYS result in a member in your CEXEC PDS.
This is obviously a hassle. The result of this, is I changed my proclib and skeleton JCL to the following.
(I set SYSPUNCH to DUMMY since I never envisage linking my compiled Rexx scripts into a load library)

Code:
//REXX    EXEC PGM=REXXCOMP,PARM='&OPTIONS'               
//STEPLIB   DD DSN=&COMPDSN,DISP=SHR                       
//SYSPRINT  DD SYSOUT=*                                   
//SYSTERM   DD SYSOUT=*                                   
//SYSCEXEC  DD DSN=&&CEXEC(GO),DISP=(MOD,PASS),UNIT=SYSDA,
//             SPACE=(800,(800,100,1))                     
//SYSPUNCH  DD DUMMY                                       
//*                                                       
//         IF (REXX.RC NE 0) THEN 
//*       Compilation threw errors for whatever reason
//*                                                       
//S010     EXEC PGM=IDCAMS                                 
//SYSPRINT DD SYSOUT=*                                     
//SYSOUT   DD SYSOUT=*                                     
//SYSIN DD *                                               
  SET MAXCC = 12                                           
/*                                                         
//         ELSE                                           
(more code here to do this and that)
           ENDIF
 


and my SKEL JCL to

Code:
//&ZUSER.A JOB (CCC0,),'&ZUSER.',CLASS=IMSB,                   
//            MSGCLASS=X,MSGLEVEL=(1,1),                       
//            REGION=20M,NOTIFY=&SYSUID                       
//*                                                           
//JCLLIB   JCLLIB ORDER=(&ZUSER..TEST.PROCLIB)                 
//*                                                           
//*                                                           
//* Compile a Rexx script                                     
//*                                                           
// EXPORT SYMLIST=(MEMBER)                                     
// SET MEMBER=&MEMBER                                         
//*                                                           
//REXXDEL  EXEC PGM=IDCAMS
//*
//*  Ensure the output CEXEC member is always deleted first                                     
//*                                                           
//SYSPRINT DD SYSOUT=*                                         
//*                                                           
//SYSIN    DD *,SYMBOLS=JCLONLY                               
  DELETE   &SYSUID..TEST.CEXEC(&MEMBER)                       
  SET MAXCC = 0                                               
//*                                                           
//*                                                           
//REXXC    EXEC REXXC                                         
//REXX.SYSCEXEC DD DSN=&ZUSER..TEST.CEXEC(&MEMBER),DISP=SHR       
//REXX.SYSIN    DD DSN=&ZUSER..TEST.CLIST(&MEMBER),DISP=SHR   
//*                                                           
//         IF (REXXC.REXX.RC GT 1) THEN 
//*    Problems with compilation. Delete the CEXEC member   
//*                                         
//S010REXX EXEC PGM=IDCAMS                   
//SYSPRINT DD SYSOUT=*                       
//SYSOUT   DD SYSOUT=*                       
//SYSIN DD *                                 
  DELETE &SYSUID..TEST.CEXEC(&MEMBER)       
/*                                           
//         ENDIF   


What this does is to ensure any existing member in TEST.CEXEC is deleted before the compiler is calledand
if the compiler returns a non-zero return code, then delete the TEST.CEXEC member afterwards as well.
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
misi01
Advanced


Joined: 02 Dec 2002
Posts: 629
Topics: 176
Location: Stockholm, Sweden

PostPosted: Thu Feb 15, 2024 5:20 am    Post subject: Keeping your Rexx source/CEXEC libraries in synch Reply with quote

The idea (?) behind compiled Rexx is to be able to distribute your code as object code only while "protecting" your source code from prying eyes.
One of the problems you're going to run into inevitably is knowing whether you need to recompile your source code, i.e., is the CEXEC member back-leveled?
To this end, I've written a Rexx panel script that allows you to compare the source script changed date/time against that for the CEXEC member.


Code:
MS            Check source Rexx against compiled code                 
COMMAND ===>                                                           
                                                                       
CLIST  userid.TEST.CLIST(DL1DB2*)      CEXEC  userid.TEST.CEXEC       
                                                                       
Results                                                               
-----------------------------------------------------------------------
_      DL1DB201 2024/02/08 08:47 <            2024/02/08 15:03         
_      DL1DB202 2024/02/08 09:32              Missing                 
_      DL1DB205 2023/10/09 07:50              Missing                 
_      DL1DB207 2024/02/08 07:20              Missing                 
_      DL1DB212 2023/12/27 10:03              Missing                 
_      DL1DB214 2024/02/08 08:46              Missing                 
_      DL1DB215 2024/02/07 10:05              Missing                 


As can be seen from the screen scrape above, you specify your source code library and your CEXEC one. You can specify a pattern for the source code.
From above, the DL1DB01 line will be shown in green, since the last changed date for the member is
less than that for the CEXEC member, so that member is in synch.
In this example, the remaining source members have not been compiled yet.
You can select any rows via the select column, press PF12 and each entry will be submitted as a job to be compiled.
.... and this is where the changed PROCLIB/SKEL entries shown in the previous append come into play.
For any "invalid" source script, the JCL will now return a return code of 12.
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
kolusu
Site Admin
Site Admin


Joined: 26 Nov 2002
Posts: 12376
Topics: 75
Location: San Jose

PostPosted: Thu Feb 15, 2024 11:36 am    Post subject: Re: Keeping your Rexx source/CEXEC libraries in synch Reply with quote

misi01 wrote:
The idea (?) behind compiled Rexx is to be able to distribute your code as object code only while "protecting" your source code from prying eyes.


Misi01,

My sample JCL uses the option NOCOMPILE(W) on the compile step which suppresses the generation of compiled code if a warning, error, severe error, or terminating error is detected.

The next steps (PLKED and LKED) check the return code the compile Step REXX and skip running them.

I hope you also realize that SYSPRINT in REXX step actually is the Compiler LISTING of the rexx code.

The output of SYSCEXEC is kinda of Object code which cannot be deciphered that easily.

misi01 wrote:

For example, IREXX allows duplicate procedure names, whereas CREXX gives a compiler error. [b]IREXX doesn't care if you have code such as
Code:
   

fred = left(bert)

(as long as you don't try to actually use it). CREXX gives a compiler error. [/


For duplicate procedure names, the compiled exec gives you a warning
Code:

+++FANPAR0071W Duplicate label: Only first occurrence on line 39 used


https://www.ibm.com/docs/en/zos/3.1.0?topic=listing-messages#EAGU0MST-gen41__msglst

For the 2nd question about interpreting vs compiling, Not sure why you say IREXX ignores it I get
Code:

     2 +++ fred = left(bert)                                     
IRX0040I Error running TST, line 2: Incorrect call to routine   


when running
Code:

/* REXX */         
fred = left(bert) 

_________________
Kolusu
www.linkedin.com/in/kolusu
Back to top
View user's profile Send private message Send e-mail Visit poster's website
misi01
Advanced


Joined: 02 Dec 2002
Posts: 629
Topics: 176
Location: Stockholm, Sweden

PostPosted: Sat Mar 02, 2024 3:02 am    Post subject: Reply with quote

I think you missed the bit where I wrote
Quote:
as long as you don't try to actually use it


Not sure if want to compile the code using the NOCOMPILE option you mentioned.
I'm quite happy to see duplicate procedure names pointed out as well as other similar errors.
Duplicate names can be a bummer inasmuch as Rexx always uses thelast entry.
You then try and understand why things aren't working as expected. Edit the script and do a find on the name and find the first one rather than the failing one and are left wondering what the hell is going on. My bad coding, but if the computer catches that, I'm good.

Are there any specific advantages in creating object (?) Rexx rather than the simple compiled Rexx?

Is object rexx more "encrypted" (the compiled code seemed pretty unreadable, though, theoretically, one might want to "hide" simple strings a bit better)

It seems to me that any change in the Rexx source code only needs to be compiled and distributed on its own, whereas, using object code everything has to be "linked".

BTW
I think I forgot to mention how my scripts are used. Basically they are all such that

a) the user starts a panel to drive the script
b) they are edit macros.

I read/saw the bit about object scripts (from your link), but then lost it when it started talking about stubs. My (very) simple text indicated the following.
I have 2 scripts, A and B (A calls B)
My login procedure allocates the compiled Rexx library first, then the uncompiled one.
If I compile A and run it, uncompiled B is called happily and run.
If I then compile B, compiled A will call and run compiled B automatically.

In what sort of situation would the object code be needed?
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic   printer-friendly view    MVSFORUMS.com Forum Index -> TSO and ISPF All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


MVSFORUMS
Powered by phpBB © 2001, 2005 phpBB Group