This is a collection of hints, tips, and code samples that may be useful to people who are thinking of developing in Rexx.

The usual disclaimers apply to all code samples (including the MACROs').

We have now made available a full working copy of some of our Rexx execs. it is available here.

We would definitely recommend the use of Rexx over clist and we thoroughly recommend Michael Cowlishaw's book "The Rexx Language: A Practical Approach To Programming"  enough. It is a wonderful reference book, in it's own right and an invaluable learning tool when it comes to Rexx 'how to' type questions.

Some of the code on this page may seem a little obvious to some people but we have included it here as a reference as much for ourselves so that we don't have to look though reams of code in order to find out how we did something.

Here is a really useful Rexx link (The Rexx Language) that we would recommend.


  Fuss Free Dataset Name Format Checking  
  upper dsname    /* Make it upper case */
dsname = STRIP(dsname,,'''')   /* Remove quotes */
x = MSG('OFF')
TrapON=OutTrap('ON')
Dsnstat = SYSDSN("'"dsname"'")   /* Check dataset name */
TrapON=OutTrap('OFF')
x = MSG('ON')
if word(dsnstat,1) = 'INVALID' then do
   Say 'Dataset name invalid 'dsname
   Signal dosomething
end
The technique shown in this example will quickly let you know if the dataset name passed in the variable is in a valid format or not.

You could use Case logic to trap so many more things but if you are just looking to see if the format of the dataset is valid, then this technique will do nicely.
 
 
 
  Zeller's Congruence  
  day.0 = Saturday
day.1 = Sunday
day.2 = Monday
day.3 = Tuesday
day.4 = Wednesday
day.5 = Thursday
day.6 = Friday
temp1 = ((mm+1)*26)%10
temp2 = yy%4
temp3 = 6*(yy%100)
temp4 = yy%400
temp1 = dd+temp1+temp2+temp3+temp4+yy
if yy < 1751 then do
   temp1 = temp1 + 11
end
if yy = 1752 then do
  if mm <= 3 then do
    if mm = 3 then do
      if dd <= 24 then do
        temp1 = temp1 - 11
      end
    end
    temp1 = temp1 + 11
  end
end
temp4 = temp1%7
temp2 = temp4*7
temp3 = temp1-temp2
say day.temp3 dd mm yy
Zeller's Congruence (explained here) will calculate the day of the week for a given date.

This sample code shows how to calculate Zeller's congruence in a way such that it is easier to follow the steps. The code alongside is stripped down for example purposes but a working copy is available here
 
 
 
  Discovering What LPAR You Are Running On  
  CVTECVT=D2X(C2D(STORAGE(10,4))+140)
lparname=STRIP(STORAGE(D2X(C2D(STORAGE(CVTECVT,4))+344),8))
permitted_on = "SYS2SYS3" /* only allow it on these systems */
If POS(lparname,permitted_on) = 0 then do
     say "Not allowed on "lparname
end
else do
     say "OK to run on "lparname
end




Example of how to use CPUCHECK

cpucheck
if rc = 0 then
   say ‘allowed’
else
   say ‘denied’
Sometimes you may want to restrict which LPAR a Rexx exec can execute on.

This code will allow to you find out which LPAR the exec is running on. The first two lines return the LPAR name and the next few lines show how to prevent/allow the exec to run.

In this example we set a list of LPAR names that the exec is allowed to execute on (SYS2 & SYS3) so that we don't have to code lots of SELECTS just one simple POS. However you may have to reconsider the POS technique if you have an LPAR named anything that may get inadvertently matched e.g. YS2S

Of course you could also flip the logic a little and make the name specified the name of the LPAR that this exec is not allowed to execute on.

We have a Rexx EXEC named CPUCHECK (available here) that can be called by any Rexx EXEC and it will set a return code that indicates if the Rexx EXEC is running on an allowed system or not. An example of how to use this is shown here. It will save you having to repeat the checking code. Again you can always flip the logic if desired.

It is important to note that CPUCHECK uses a system variable (sysname) that is set on our system. If you prefer you could navigate the control blocks in the example above.
 
 
 
  Discovering What Jobname Is Running The Rexx Exec In Batch.  
  CVT = STORAGE(10,4)

TCBP = STORAGE(D2X(C2D(CVT)),4)           /* CVTTCBP */

TCB = STORAGE(D2X(C2D(TCBP)+4),4)

TIOT = STORAGE(D2X(C2D(TCB)+12),4)        /* TCBTIO */

job = STRIP(STORAGE(D2X(C2D(TIOT)),8))    /* TIOCNJOB */
This code can be used to discover the job name that is running the Rexx exec in batch.

If you do it under TSO it will return your own TSO name.

Once you have the jobname you can make lots of choices based on the jobname...like use it for a dataset level or, if you have good naming standards you can take a different logic flow based on whether it is a production or development job.

 
 
 
  Discovering The Job Number of The Job Running The Exec.  
  CVT = STORAGE(10,4)
TCBP = STORAGE(D2X(C2D(CVT)),4)           /* CVTTCBP */
TCB = STORAGE(D2X(C2D(TCBP)+4),4)
JSCB = STORAGE(D2X(C2D(TCB)+180),4)        /* JSCB */
SSIB = STORAGE(D2X(C2D(JSCB)+316),4)        /* SSIB */
jobnum = STRIP(STORAGE(D2X(C2D(SSIB)+12),8))    /* Get jobnum */
This code can be used to discover the job number that is running the Rexx exec in batch.

If you do it under TSO it will return your own TSO number.
 
 
 
  Replacing a String In a Rexx Exec  
  /* Rexx */
input = 'my favorite color is red'
input = strrepl(input,'red','green')
say input
exit

StrRepl:
Orig = ARG(1)
Oldtxt = ARG(2)
Newtxt = ARG(3)
Newstr = ''
Work = Orig
Do while POS(Oldtxt,Work) > 0
Newstr = Newstr||SUBSTR(Work,1,pos(Oldtxt,Work)-1)||Newtxt
Work= SUBSTR(Work,pos(Oldtxt,Work)+LENGTH(Oldtxt))
end
Newstr = Newstr||SUBSTR(Work,1)
return Newstr
We use this routine in many of our Rexx execs.

It will replace the second value with the third value in the field specified by the first value. The string lengths don't matter so it makes this code pretty slick.

In the example here we replace the sting 'red' with the string 'green' in the field 'input' which contains the string 'my favorite color is red'.

Note: The StrRepl routine here is a subroutine and so it can be copied and pasted in its entirety into any exec and be ready to be used.

A text version of StrRepl subroutine is available from here.
 
 
 
  Finding The Name of The Current Exec  
  /* Rexx */
dialogid = sysvar(sysicmd)
parse source Exec_String
excnme = word(Exec_String,3)       /* Get EXEC's name */
say excnme ' Starting.' date() time()
final = TIME('Reset ')

say excnme 'Finished :' date() time() 'Elapsed time 'time(e) 'seconds'
exit
This snippet of code will return the name of the executing Rexx exec.

In this sample code we also demonstrate how to display the time that the Rexx exec took to execute.

 
 
 
  Convert A Month Number To Month Name  
  /* Rexx */
Mon.01="January"
Mon.02="February"
Mon.03="March"
Mon.04="April"
Mon.05="May"
Mon.06="June"
Mon.07="July"
Mon.08="August"
Mon.09="September"
Mon.10="October"
Mon.11="November"
Mon.12="December"
myDate= "1999/12/25" /* This is a sample date in yyyy/mm/dd format */
year = substr(myDate,1,4) /* Year portion (change as appropriate) */
day = substr(myDate,9,2) /* Day portion (change as appropriate) */
mon = substr(myDate,6,2) /* Month portion (change as appropriate) */
monname=MON.mon
/* translate to name */
say day monname year /* show the date */
exit
Sometimes a date is in all numeric format and you may want the full month name in this case this sample code will do the trick.

Any value can be placed in the 'table'. In other words if you only want the first three characters, then simply enter them instead of the full month name.

You will need to tweak the code to accommodate the date format if it isn't yyyy/mm/dd.

A text version of this code can be found here.
 
 
 
  Building a Delay Into a Rexx Exec (Sleep)  
  /* Rexx */
parse upper arg time value
If value <> "" then do
   value = substr(value,1,1)
   /* If you don't pass a value seconds are assumed otherwise:*/
   /* use M for minutes or H for hours */
   if value = "M" then time = time * 60
   if value = "H" then time = time * 60 * 60
end
if time = "" then time = '1'
hit = 0
Do while hit < time
   hit = TIME('Elapsed ')
   end = lastpos('.',hit)
   hit = substr(hit,1,end)
end
exit
Occasionally you may want to delay an Exec for a couple of seconds or more. There is currently no inbuilt Rexx function for this. This Exec will delay the execution of the calling Exec for the number of seconds, minute or hours that are passed to it.

*** WARNING *** This Exec takes no prisoners! If you say sleep for an extended duration it will do just that and will lock out the TSO id or job for that long.

A text version of this code can be found here.
 
 
 
  Converting a String to Proper Name Format  
  /* Rexx */
input = 'ABBYDALE'
input = Proper(input)
say input
exit

Proper:
Orig = ARG(1)
if length(orig) > 1 then do /* Ensure there is more than one char */
  UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  LOWER = "abcdefghijklmnopqrstuvwxyz"
  tempName = TRANSLATE(Orig,LOWER,UPPER)
  build = substr(tempName,2,Length(tempName)-1)
  initial = substr(tempName,1,1)
  initial = TRANSLATE(initial,UPPER,LOWER)
  newname = initial||build
end
else do
  newname = Orig
end
return newname
When you are dealing with proper names (People's name, place names etc.) the correct format is to start them with a capital letter. Unlike some languages there is no built in Rexx function for doing this therefore we use this subroutine for achieving this.

In the example shown the name ABBYDALE will be converted to Abbydale by the subroutine. It should be noted that even if the name is already in lower case this routine will work. Note: The Proper routine here is a subroutine and so it can be copied and pasted in its entirety into any exec and be ready to be used.

A text version of Proper subroutine is available from here.

A brief demonstration is available here.
 
 
 
  Dropping the Last Level From a Dataset Name  
  dsname = SUBSTR(dsname,1,(LASTPOS('.',dsname)-1)) If you ever want to drop the last level from a dataset name, you can do it by using this code.

You can use this for generic LISTCATs etc.

Looping through this process will drop you down more levels.
 
 
 
  Obtaining the Current TSO PROFILE PREFIX  
  /* rexx */
prof = getprof(prof)         /* Get current prefix */
say "Value of prof="Prof     /* Show answer        */
"Profile noprefix"           /* Profile NOPREFIX   */
prof = getprof(prof)         /* Get current prefix */
say "Value of prof="Prof     /* Show answer        */
"Profile PREFIX("userid()")" /* Set to our userid  */
prof = getprof(prof)         /* Get current prefix */
say "Current profile "prof   /* Show answer        */
"Profile noprefix"           /* Set NOPREFIX       */
"Profile"                    /* Show our profile   */
say
say "Value of prof="Prof     /* Show answer        */
say
if Prof/='N' then do         /* Prof = our userid  */
"Profile PREFIX("Prof")"     /* Reset prefix       */
end
"Profile"                    /* Show our profile   */
exit
It is sometimes useful to store the TSO PREFIX in use when a Rexx is executing. It is extremely useful when you want to set the PROFILE to NOPREFIX but want to reset it back to what it was when the exec was called.

GETPROF can provide this function.

The GETPROF routine is available from here.

The code alongside is NOT GETPROF but a demonstration of how to use GETPROF.

A copy of the code alongside is available from here.
 
 
 
  Counting Occurances of a String  
 

Usage x=CountStr(find,where)

Sample of use:

     x = CountStr('.','ABBYDALE.ALLFREE.REXX')
This would return 2 as the value of x.

If you need to know if this is an odd or even number you can use:


x = CountStr('.','ABBYDALE.ALLFREE.REXX')//2
if x > 0 say 'Odd'


This function will count the number of times a passed string occurs in another passed string.

This is useful if you want to count the number of levels in a dataset name.

The COUNTSTR routine is available from here.
 
 
 


If you need any support or assistance with any of the code on this site
or
if you would like to contact us, please click here

follow us on facebook
Follow us on Facebook

 

Number of unique visitors 759

Copyright © Abbydale Systems LLC 2015-2024

Abbydale Systems LLC Lic. 802696149. All rights reserved.

Last modified : Wednesday 16th of November 2022