A Review of Personal REXX for OS/2
Written by Jonathan Story
OS/2 is like a chest full of treasures. It runs OS/2, DOS and Windows programs, and you don't need to buy DOS or Windows because both are already included. And when you dig a little deeper you discover REXX, a jewel brought over from the mainframe world.
OS/2 includes REXX for no extra charge. Quercus Systems, makers of Personal REXX, would be very happy to sell you a copy of their version. Why should anyone pay good money for something they already have? Well, consider OS/2's REXX compared to Personal REXX as the difference between a good pair of sensible street shoes and top-of-the-line rollerblades.
The documentation that comes with Personal REXX can help almost anyone to get started learning and using REXX. It includes: a User's Guide, an OS/2 Addendum, a REXXLIB User's Guide, a Reference Summary booklet, and the book The REXX Language: A Practical Approach to Programming, Second Edition by M.F. Cowlishaw (the 'bible' for the REXX language.)
For the novice, the User's Guide introduces the elements of the language in an easy step-by-step fashion illustrated by brief example programs. The Guide takes care to distinguish between what is a part of the language itself and the extensions from Quercus. For someone who wants to make his programs work on as many environments as possible, this is very important to know.
This is one of the few areas I would like to see improved. Personal REXX for OS/2 has an install program, but it does not modify your CONFIG.SYS. It could be that the installation process avoids changing anything that might cause problems, although for me installing manually caused problems anyway: I completed what was left of the install by hand according to the instructions, but it took me two tries (rebooting each time) before successfully making the changeover from the REXX included with OS/2 to Quercus's Personal REXX. Why should the ordinary REXX user have to know about PATH and LIBPATH? Adding a few more smarts so that everything will install automatically (an uninstall would be another pleasant bonus) can remove this unwelcome technical encounter.
A minor nit: a program called INSTEST checks that all components of the package have been installed. This is useful (and, for me, was necessary), but when nothing is correctly installed the report can be misinterpreted to suggest that all is okay. A more informative message ("Personal REXX is NOT installed") and some corrective suggestions would make INSTEST more useful.
Almost every program that runs under OS/2's REXX will also run under Personal REXX. The exceptions are few and are documented. (One very rare condition is not documented: If a REXX program is reading characters from the standard input and then invokes another program that also is reading from the standard input, the second program might not receive the first part of the remaining data. This has to do with how Personal REXX reads buffers and here compatibility is sacrificed for speed.)
In addition, Personal REXX has loosened some of the constraints in OS/2's REXX. It has increased the maximum number of arguments for a procedure from 20 to 250, and the number of I/O streams from 15 to 50. But mere compatibility is not sufficient reason to use Personal REXX.
It is, of course, important that programs running OS/2's REXX continue to work with Personal REXX. But the real seasoning for this product comes from greater speed and abilities.
The first thing you notice when using Personal REXX is that programs run faster. In most cases the difference is not only noticeable, it is striking. Like moving from a 386 to a 486, or from a 486 to a Pentium, performance typically doubles or better. Some people use REXX for easy prototyping and then recode in C for speed. Personal REXX surprisingly often can be an acceptable alternative to a compiled program. In addition to programs running faster, Personal REXX includes functions for things that either cannot be done in standard REXX or that would otherwise need clever workarounds.
The utilities enhancements to standard REXX can be grouped into three areas: PC hardware; the Operating System; and miscellaneous functions. With the hardware functions you can discover the PC type, the type of drives on the system, the type of keyboard, the number of serial and parallel ports, and so on. You can change the cursor position, make sounds from the PC's speaker, change the shift state of the NumLock and CapsLock keys, and more. (There is some difference in the kinds of things that can be done by the OS/2 version and the DOS version of Personal REXX. This is related to the degree the operating system isolates a program from the physical environment and the meaningfulness of the information. For example, in OS/2 you don't have PEEK() and POKE(), and there is no such thing as EMS memory.)
Operating system functions can sometimes be handled in REXX simply by passing the command on to the OS environment. Personal REXX provides functions that do these too, and more. In addition to DOSCD() to change the current directory, there is also DOSISDEV() and DOSISDIR() to detect whether something is a file or a device.
Miscellaneous functions provided with Personal REXX include some that it would be easy to imagine had been left out of standard REXX by mistake. In particular, UPPER() to convert characters to upper case and LOWER(), plus DATECONV() to convert a date from one type to another.
For the old guard REXX programmer who learned the language when it first appeared on IBM's mainframes, Personal REXX gives some consideration. The three commands LISTFILE, EXECIO, and GLOBALV were a staple of such old REXX programs. In this package these three commands are included as utilities, making it easier to convert code to run on PCs.
REXXLIB is a package included with Personal REXX for OS/2, but one can purchase it separately to use with OS/2's REXX. It contains a wide range of functions to make programming easier.
One group of functions repairs a major deficiency in the language itself. Compound variables serve the same purpose as arrays do in other languages. These variables can have arbitrary indexes - a valuable tool. But REXX cannot simply find all indexes that have been defined, which reduces the power of arbitrary indexes. REXXLIB addresses this flaw with CVTAILS() and related functions: CVTAILS() makes an array of all the tails of a compound variable. CVWRITE() writes all values of a variable to a file and CVREAD() reads values from this file. CVCOPY() copies the values of a compound variable.
Another type of compound variable is known as an array. Here, the stem indexes begin at 1 and increase sequentially. The total number of array elements is kept in the element 0. Functions developed for this are: ARRAYCOPY(), ARRAYDELETE(), ARRAYINSERT(), and ARRAYSORT().
VARDUMP(), VARREAD(), and VARWRITE() read and write the values of variables from and to a file. This makes it easy for a program to recall what it was doing the last time it ran.
There are also functions that deal with OS/2 sessions, processes, and other services. These let you, for example, change the priority of a process or kill it. In addition, to make working with concurrently running processes easier, REXXLIB includes the ability to use semaphores and named pipes.
Finally, the package includes some very useful mathematical functions: logarithms (LOG(), LOG10()); exponentiation (EXP(), POW(), SQRT()); trigonometric (SIN(), COS(), TAN(), etc.); hyperbolic (COSH(), SINH(), TANH()); plus ERF(), ERFC(), and GAMMA().
Personal REXX for OS/2 with REXXLIB adds speed and power to REXX in the OS/2 environment. True, it doesn't match the glitter of the GUI REXXes, but in raw performance it shines.