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:
/* REXX PROCEDURE FOR LIBRARY 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. 🙂
Thank you!
REXX is used in IBM Z mainframe very often. Advantage of learning REXX: 1/ Very easy to master, 2/Useful and powerful, 3/portability (IBM i and IBM Z)
Nice!! I was looking for something a user (None programmer) could manipulate his/her own entry criteria (via RPGLE) which doesn’t have to be compiled. This fits perfectly. Thanks