Not a lot of folks know about REXX. REXX is a pretty important little tool in the OS/400 and i5/OS arsenal, because it's sort of like an interpreted CL with lots of extra goodies thrown in. While there are a few things you can't do (for example, you can't directly call a procedure in a service program), the things that you can do are simply amazing. For example, you can execute OS/400 and i5/OS commands using program variables. You simply substitute the REXX variable name in the command, much like you do with PDM options.
Another feature I find especially useful is the ability to embed SQL in my REXX procedures. This ability is more powerful than the RUNSQLSTM command, because you can use it in conjunction with program variables in your REXX program, much as you would in SQLRPG programs. This makes REXX very powerful for system management functions. I can use an OS/400 command to create an output file, then read that file using SQL statements. Based on the contents of each record, I can then execute additional commands.
In this tip, I'm including a simple mass compile program that will compile all RPG and RPGLE members in a source file. The parameters (source file name and library) are read in from the command line. The procedure uses an OS/400 command call to display all the members of the selected source file to a file called MBRS in QTEMP. It then uses SQL statements to read through the file. For each record in the file, it calls a subroutine that processes that member.
To execute this, create a source file and then type the code from listing 1 into a new source member. Let's say you created a member called COMPILEALL in a file called QREXSRC in MYLIB. This would be the syntax:
Figure 1: This is the listing for the REXX procedure COMPILEALL. (Click image to enlarge.)
(A) First, you can pass as many parameters on the command line as you want; REXX has built-in opcodes to parse the input stream. C and Java programmers should recognize the term "input stream"; the REXX program reads STDIN to get its data (output goes to STDOUT).
(B) The next comparison has to do with calling OS/400 commands. The two are almost identical, except that you must put the command in quotes in REXX. This tells REXX to run the command through an external command processor. The default is to execute the command as an OS/400 command. But the next capability shows how powerful REXX is.
(C) The ADDRESS opcode tells REXX that you want to execute a command, but not an OS/400 command. Instead, you can tell it which environment to target. Environments include the standard OS/400 command processor, the SQL processor, or the CPI communications subsystem. You can even target your own program, which leads to a whole host of other possibilities.
(D) Here is where you can use SQL statement to populate local variables. One cool thing about REXX is that you don't have to define the variables ahead of time. Lazy programmers unite!
(E) This looks pretty simple: calling a subroutine, right? REXX is far more powerful than that, though. Not only can you pass parameters, but if the subroutine doesn't exist in your procedure, REXX will go look outside in the source file for a member with the appropriate name.
(F) Finally, this is the very impressive SELECT statement, which is much like the SELECT statement in RPG and far more impressive than the corresponding "switch" opcode in Java or C. This statement checks the source type and executes the appropriate compile command. Note that you can easily add more types right here or even add special processing for specific programs.