REXX - IBM Mainframe

REXX (Restructured extended executor)is a modern, structured, high-level programming language that was consciously designed for ease of both reading and writing. It was designed and first implemented between 1979 and 1982 by Mike Cowlishaw of IBM. Though it was primarily developed by one individual, it was widely disseminated within IBM during that time, and improved by the feedback of hundreds of users. REXX was first made commercially available as the system procedure language for IBM's VM/CMS operating system in 1983.

When IBM's Systems Application Architecture was announced in 1987, REXX was included as the standard system procedure language. By that fact, IBM indicated that REXX would eventually be implemented in a standard way on all of their strategic computing systems. An implementation for the MVS system appeared in 1988. In 1990, an implementation of REXX from IBM appeared on personal workstations in version 1.2 of OS/2.

Long before then, others had implemented REXX on various computers and operating systems. The first such implementation, known as Personal REXX, was developed for MS-DOS by Charles Daney and Mansfield Software Group in 1985. They followed this with a version of REXX for OS/2 in 1989. ARexx for the Commodore Amiga made its debut in 1987.

At the present time, IBM has widened the availability of REXX in its systems to include OS/400. Other vendors have developed versions of REXX for Unix and for Tandem computers. Thanks largely to the relative clarity and completeness of Mike Cowlishaw's original definition of REXX, there is a high degree of compatibility among existing versions of the language.

Ease of use in end-user personal programming Was the predominant objective in the design of REXX. Several key characteristics contribute to this ease of use. They include:

  • Character-string orientation
  • Dynamic data typing (no declarations)
  • Reliable, machine-independent arithmetic
  • Automatic storage management
  • Protection from "crashing"
  • Content-addressable data structures
  • Straightforward access to system commands and facilities
  • Few artificial limitations

It should be mentioned, also, that REXX's ease of use does not limit its appeal to end-users only. The same characteristics make it useful to professional programmers as a utility programming language for "quick and dirty" jobs, because REXX programs can be developed and debugged much faster than programs in most conventional languages, even if the user is an experienced programmer.

In overall appearance, REXX is a fairly conventional language, not too much unlike Pascal, C, or other languages which trace their ancestry to Algol. This is in contrast to languages like Snobol, LISP, or Smalltalk, which explore very different approaches to programming. Thus, REXX has much in common with other Algol-like procedural languages-variables, expressions, control structures, subroutines, and I/O facilities.

The following is a complete REXX program that prompts for a file name, and then asks the user to make a selection from a menu, and executes a command corresponding to the selection. The fact that the program should require no further explanation to be understood illustrates the naturalness and readability of the language.

REXX

One important point about this program arises from the fact that REXX originated as a system procedure language. Specifically, the capability of executing system or application commands is an integral, part of the language, rather than a function, which is available (if at all) only through library routines. In other words, like a Unix shell language or the MS-DOS and OS/2 batch language, REXX automatically passes commands to the surrounding "environment" for execution. Consider another example:

REXX

The above example is a REXX procedure that contains the commands necessary to allocate a VS COBOL II program, invoke the debugger and free the allocated file. If you are in the process of testing and debugging a COBOL program, you can save the time of repeatedly issuing the commands for invoking the VS COBOL II debugger by storing the commands in a REXX procedure as shown above.

You can create a REXX procedure by using a text editor such as ISPF edit option or TSO EDIT command. Every line of a REXX exec should be either a REXX instruction or a TSO command. Any line that is not a valid REXX instruction is assumed to be a TSO command. The TSO commands in a REXX exec should be enclosed within quotes.

The first line of a REXX procedure or program is /* REXX */. This is a comment that identifies the procedure as a REXX exec. Comments begin with the characters '/*' and end with the characters '*/'. The first line of every REXX exec should be a comment that includes the word REXX. That is how TSO distinguishes REXX execs from CLISTs. The word REXX can appear anywhere in the comment, in upper or lower case.

REXX execs are usually stored as members of a partitioned data set whose type qualifier is EXEC. When you create the EXEC library, you should pattern it after the existing system-wide CLIST procedure library, which should have a name like SYSl.CLIST. To find out the name of the CLIST procedure library, use the TSO LISTCAT STATUS command and note the name of the data set assigned to SYSPROC. Then to create a private exec library, use the LIKE operand on an ALLOCATE command as follows:

ALLOCATE DSNAME (EXEC) LIKE ('SYSl.CLIST)

Here a library named ALEXIS.EXEC is created (assuming ALEXIS is the user-id) with the same characteristics as SYSl.CLIST. Most EXEC libraries have either fixed-length records of 80 bytes each or variable-length records of up to 255 bytes. If you need to include a line that is longer than the maximum, you can continue it to the next line by using a comma as a continuation character. For example consider the ALLOCATE COMMAND:

ALLOCATE COMMAND

In the above example, the comma tells REXX that the command is continued on to the next line.

To execute REXX procedure, you use the EXEC command. The two formats of the EXEC command is given below:

  • EXEC library-name (member-name) 'parameters' EXEC - Explicit form of EXEC command
  • [%] member-name parameters - Implicit form of EXEC command

Here 'library-name' is the name of the library containing the REXX procedure (a type qualifier of EXEC is assumed). This can be omitted if the library is named user-id.EXEC, 'member-name' is the member name of the procedure to be invoked, 'parameters' is a parameter string to be passed to the procedure. The procedure may use an ARC instruction to parse this string into variables. 'EXEC tells TSO that member-name is a REXX procedure rather than a CLIST. '%' tells TSO to bypass the search of its command libraries and instead search SYSEXEC and SYSPROC directly.

Assuming that PKOO1 the name of the exec that we have coded for debugging and assuming that it is in ALEXIS.TEST.EXEC, you can invoke it with the following command:

EXEC TEST (PK001) EXEC

You can omit the library name (as it has the format user-id.EXEC) and issue the command as follows: EXEC (PK001) EXEC

In the implicit form you just specify the name of the procedure. If you include a % sign in front of the procedure name TSO does not search for the procedure name in its command libraries.

When you use the implicit form of the EXEC command, TSO looks in the library allocated to the ddname SYSEXEC to find your procedure. As a result before you issue an implicit EXEC command, you must allocate your command procedure library to SYSEXEC with an allocate command as follows:

ALLOCATE DDNAME (SYSEXEC) DSNAME (TEST.EXEC) SHR REUSE

You can allocate REXX procedure libraries to SYSPROC also, but that is usually used for CLIST procedure libraries. When SYSEXEC and SYSPROC are allocated TSO searches SYSEXEC first. Thus if a REXX procedure and a CLIST have the same name, TSO executes the REXX procedure.

To invoke a REXX procedure from ISPF, you have to make sure that ISPF knows you are issuing a TSO command rather than an ISPF command. You can do that from any ISPF panel by prefixing the command with the word TSO. Thus to allocate a user exec library the following two commands can be used:

TSO ALLOCATE DDNAME (SYSEXEC) DSN.(TEST.EXEC) SHR REUSE TSO ALTLIB ACTIVATE USER (EXEC)

The to invoke a procedure from the user library, you can enter the following command:

TSO %PK001

Perhaps the most noteworthy departure of REXX from other Algol-like languages is its "natural" data typing. All data is treated as character strings. Numbers, including both integers and reals, are just special cases of strings. Numbers need to be recognized as such for computational purposes only, but no explicit conversion, no "formatting," is required for communications with humans. This alone is a major aid to usability, as any novice who was ever baffled by a "format" statement can testify.

Another consequence of this approach is that data declarations are never required (or even possible). Data declarations in other languages are really provided for the convenience of the computer, not the user. They are an accommodation of the fact that computers use a variety of internal data representations for different purposes and must be told which representation to use for a given data item. REXX isolates the user from all concern with these internal representations.

A further side effect of treating all data as character strings is that there need to be no inconvenient limits on the magnitudes of numeric data items. Although seldom required, hundreds of digits can be handled in REXX as easily (for the user) as five or six. Errors both gross and subtle that result from the inability to represent a number in a particular word size simply are not possible. This also makes REXX programs much more portable between widely different computer architectures.

In particular, REXX does not cause a program failure when a computation exceeds a user-definable maximum precision. It does not even generate wildly incorrect results, as other languages usually do, when an "overflow" occurs. Instead, it discards the least significant digits of a result in order to stay within the specified degree of precision.

In conventional languages, data declarations not only specify internal representations to use, but also define storage allocation. Since there are no declarations in REXX, it is not necessary to worry about allocation issues (at least as long as enough storage is available). This is another great simplification. All data items, even elements of arrays, are allocated storage automatically when, and only when, they are required. They are also deallocated automatically as soon as possible. Another pleasant benefit of REXX's dynamic memory management is that REXX is almost crash proof, even on a CPU without memory protection. One of the most unpleasant experiences in programming for end users (or professionals) is the tendency for undebugged programs to crash themselves, or even the operating system, because they have overwritten their own code, or code belonging to other applications or the system. This is essentially impossible in REXX. (The exception is such things as functions provided explicitly to give access to external memory.)

Another unusual feature of REXX is the way arrays are handled. In REXX, data variables have names that are either simple or compound. A simple name is just a sequence of alphanumeric characters that contains no periods. A compound name is composed of two or more simple names connected by periods, for example, age.alex. The portion of a compound name before the first period is called the stem; it is taken literally. The remaining portions of the name are themselves variables that can be substituted. In effect, these are subscripts.

In order to work with arrays of any number of dimensions, one uses a stem followed by the appropriate number of subscripts. For instance, temperature.x.y.z is an element of a three-dimensional array called temperature. If the variables x, y, z have values 1, 2, 3, respectively, this element is temperature.1.2.3.

There are several important points here. The first is that no storage is allocated except for array elements that have actually been assigned values. The subscripts may be as large as necessary, but as long as there are only three elements having values, only three are stored, so the array can be very sparse.

But more importantly than that, the array subscripts need not be numeric—they can have any data value at all. This permits associative indexing, in which the subscripts are general nonnumeric data. For instance, one can have an age array whose elements include, in particular, age.alex, age.ashwin, etc. A computation can deal with a data reference like age.person, where person is a variable that ranges over values alex, ashwin, etc.

It should be apparent by now that the uniform representation of data as character strings is very important in REXX. This is connected with another design objective of the language, which is to place a great emphasis on symbolic manipulation. Since most system commands and application programs interact with users—or with REXX—much more with arbitrary strings of symbols than just with numbers, this is very appropriate for a system command language.

The most basic operation possible with character strings is concatenation, so REXX makes it as easy as possible to express. There are several flavors of this. The following example illustrates two of them:

The date is: 1 month' / 'day' / 'year'.'

Here, strings enclosed in quotes are literals, while month, day, and year are variable names. In this expression, all of these parts are simply concatenated together, just as written. The extra blank before month is even retained, because it is actually the operator for "concatenate with a blank in between." No explicit operator is required to express direct concatenation. (An explicit operator, "11", is provided for cases where juxtaposition alone would be ambiguous.)

A large number of other character-string manipulation primitives are provided in REXX by means of built-in functions. Indeed, this is one of the most agreeable features of REXX. Included are such operations as substring, replacement, translation, verification, insertion, searching, and the like. There are even operations to reverse the characters of a string or to center a string in a given field. Since it is frequently useful to treat a string as a sequence of "words" delimited by blanks, there are a number of functions to count and extract such words.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

IBM Mainframe Topics