Playing with REXX on IBM i

Wondering what REXX is? First off, it has nothing to do with those big green lizards that ran around angrily eating other lizards (presumably because their pathetically small arms gave them some kind of appendage envy) REXX is a kinda cool interpretive language — a bit like Control language (CLP).

The neat thing about it is that you just enter the commands in a source member and then use STRREXPRC to run them. No need to compile.

I haven’t used REXX for years. Not since my early days working on the old System38. But, last week I was writing a little upload script to make emailing/upload/installing a *SAVF a little easier and I had this thought of “Wouldnt it be nice if I could just write an install script to run automatically? Then I could send it to another IBM I system in text form to let them run it with a simple copy/paste“. Rexx lets us do exactly that!

Caveat Emptor – I ended up discarding this idea and doing things a completely different way but… but… I did write and test these very simple scripts and thought maybe it’s worth stuffing a blog in case it helps someone else out?

So here is a very basic REXX scrptin that you could copy/paste into a source member and then run using STREXPRC from the IBM i Command line:

/* -------------------------------------------------------- */ 
/* REXX PROCEDURE FOR HOTFIX INSTALL */ 
/* -------------------------------------------------------- */

say 'starting HOTFIX install'
 
cmd = 'dltf TSTFIXNEW/MYSAVF' 
cmd 
select 
 when rc = 0 then 
 say 'previous version of *SAVF(TSTFIXNEW/MYSAVF) deleted' 
 otherwise 
 say '*** debug: TSTFIXNEW/MYSAVF did not delete'
end


cmd = 'crtsavf file(TSTFIXNEW/MYSAVF) text(hotfix_installer_from_NickLitten)' 
cmd 
select 
 when rc = 0 then 
 say 'savefile created OK' 
 otherwise 
 say '*** debug: *SAVF did not create' 
end

So, logic is really basic here and the code is self-explanatory right?

But, I started thinking about – would it be nice if I could prompt for library and save file name as a parameter? Perhaps I could add subroutines to do multiple logic chunks in the same script?

The answer is YES and during a few hours tinkering I discovered that REX is a lot more powerful than I remembered. Here is a bit more evolved version of the same code:

RPG Code Snippet/* ------------------------------------------------------------ */
/* REXX PROCEDURE FOR HOTFIX INSTALL */
/* ------------------------------------------------------------ */
/* Parameters passed: */
/* (1) function - 3Char - values("CRT"/"RST"/"RUN") */
/* (2) library - 10Char - library name ie: "HOTFIXNEW" */
/* (3) savefile - 10Char - Name of *SAVF being installed */
/* Returns: '0' SUCCESS */
/* '1' FAIL */
/* ------------------------------------------------------------ */
/* Author: nick@nicklitten.com */
/* Date: Sep 18 2017 */
/* Reason: created. */
/* ------------------------------------------------------------ */

/* Setup ERROR,FAILURE & SYNTAX condition traps.*/
 SIGNAL on NOVALUE
 SIGNAL ON SYNTAX

PARSE ARG 'FUNCTION(' function ')'
 PARSE ARG 'LIBRARY(' library ')'
 PARSE ARG 'SAVEFILE(' savefile ')'

say "+-------------------------------+"
 say "| HOTFIX INSTALL PROCESS |"
 say "+-------------------------------+"

if function = " " then
 do
 say "Enter function CRT/RST/RUN?"
 pull function
 end
 say 'INSTALLING using Function 'function

if library = " " then
 do
 say "Library Name?"
 pull library
 end
 say 'Using Library 'library

if savefile = " " then
 do
 say "Save File Name?"
 pull savefile
 end
 say 'Save File 'savefile

/* Does the library exist ? */
 'CHKOBJ OBJ(QSYS/'library') OBJTYPE(*LIB)'
 if POS('CPF98',rc) ¬= 0 then do
 msg = '** Library 'library' not found.'
 'SNDPGMMSG MSG(&msg)'
 exit(rc)
 end

select
 when function = "CRT" then CALL proc_create
 when function = "RST" then CALL proc_restore
 when function = "RUN" then CALL proc_run
 end

EXIT(0)



/* ------------------------------------------------------------ */
/* subprocedures for CRT - CREATE */
/* ------------------------------------------------------------ */
proc_create:
 say 'HOTFIX REXX - starting CREATE process'
 'DLTF 'library'/'savefile
 if rc = 0 then
 say 'previous version of *SAVF('library'/'savefile') deleted'

'crtsavf file('library'/'savefile') text(hotfix_installer)'
 if rc = 0 then say 'Savefile created OK'
return

/* ------------------------------------------------------------ */
/* subprocedures for RST - RESTORE */
/* ------------------------------------------------------------ */
proc_restore:
 'RSTLIB SAVLIB('library') RSTLIB('library') DEV(SAVF) SAVF('library'/'savefile')'
 if rc = 0 then say library ' has been restored'
 else say '*** debug: RSTLIB did not work'
return

/* ------------------------------------------------------------ */
/* subprocedures for RUN - POSTRUN OPTIONS */
/* ------------------------------------------------------------ */
proc_run:
 say 'placeholder for some POST RUN logic to add later. Add some logic here'
return
return

Self explanatory code really; Nowt much else I am going to say about this…

So lets run this version. Simply copy/paste it into a source member (in this case I pasted it into a member called REXXTEST in LITTENN/QRPGLESRC) and then run it like this:

STRREXPRC SRCMBR(REXXTEST) SRCFILE(LITTENN/QRPGLESRC) CMDENV(*COMMAND)

enter the prompts:

So, I actually think REXX is a little used, but very powerful tool to have in every IBM i or RPG programmers brainbox.

Hope its maybe useful.

If it’s not useful then just smile a the nice picture of the T-Rexx.  🙂