Instructions

Contents

Introductory text

Comments are supported, and may appear anywhere that a space can, with
the exception that comments are not allowed within a multi-character
operator (e.g. ** or ==).  They can occupy any number of lines and may
be nested. 
/* This is a comment.  It is started by /* and ended by */.  */

The star and slash characters of the comment delimiters must not be
separated by whitespace.

Each command must usually appear all on one line. The exception to this
rule is when a line ends with a comma. In this instance, the comma is
deleted and the next line appended with a space. Multiple lines may be
appended in this way. Thus
   say,          /* spaces and/or comments may follow the comma */
   "this is",
   "a test"
will actually be interpreted as
   say "this is" "a test"
and will result in
   this is a test

Note that quotation marks must always be closed before the end of a line.
For example, the following will cause an error:
   say "this is,
   a test"

Instructions may be separated by semicolons or by the ends of lines.

The following REXX commands are currently implemented. They are displayed
in upper case, but may be typed in mixed case.

Square brackets indicate optional parts of constructions.

NOP

This does nothing. It is provided for situations such as
IF xxxx THEN NOP ELSE yyyy.

SAY [expression]

The expression is evaluated and displayed on the standard output,
followed by a newline character. If no expression is supplied then just
the newline character is output.

LOCAL: The command:  SAYN expression
       evaluates the expression and displays it without a newline
       character.  Note that a similar effect can be obtained with
       the function call charout, though the output may have to be
       flushed by calling charout a second time with no parameters.

symbol=value

If `symbol' is a simple or compound symbol then it is assigned the value
`value', so that assignment in REXX has the usual meaning. A compound
symbol is subject to the usual substitution of qualifiers.

If `symbol' is a stem, then all possible compound symbols which start
with the given stem are assigned the value `value'.

Variables are allowed to have the same names as REXX keywords, with the
exception of some keywords within particular commands (e.g. "until" in a
DO construction). The following rule is applied, in order to distinguish
between an assignment and any other command: if the first word in the
line is followed by an `=' (after optional spaces), then it is an
assignment. This does not apply, however, to constant symbols, which can
not be assigned to.

DROP symbol [symbol,...]

The DROP command un-assigns each symbol named after the DROP keyword.
Simple or compound symbols or stems may be dropped. If the symbol is a
stem, then all compound symbols starting with that stem are dropped.

If a variable has been passed to a procedure with the PROCEDURE EXPOSE
construction, then the variable in the calling procedure will be dropped
also. If a dropped symbol is subsequently assigned a value, then the
variable will also be assigned that value in the calling procedure.

It is not an error to DROP a non-existent symbol, or to DROP a symbol
twice.

NOTE: Even if a compound variable is dropped, its value will always be
      undefined immediately after the drop.  For example,
         stem.="Some value"
         drop stem.6
         say stem.5 stem.6 stem.7
      makes stem.6 undefined and says "Some value STEM.6 Some value".

EXIT [expression]

The EXIT instruction returns control from a program to its most recent
external caller. This will either be a rexx external call (that is,
`CALL name' or `name()' where name is the name of the REXX program rather
than an internal or builtin function name) or a UNIX command, if the
program was not called by another REXX program. All the current DO,
SELECT, INTERPRET and internal call structures are terminated, and
control resumes at the point of the most recent external call. An
expression may follow the EXIT statement; this is passed back to the
caller in the same way as in the RETURN statement. If control is returned
back to UNIX, then the expression must be an integer if it is supplied,
and it is used as the exit value of the interpreter. If no value is
supplied then the exit code will be zero.

Note that reching the end of a program is the same as executing "EXIT".
In other words, reaching the end of a program terminates all internal
function calls.

NUMERIC parameter value

NUMERIC DIGITS n
NUMERIC FUZZ n
NUMERIC FORM   SCIENTIFIC
             | ENGINEERING
             | "string constant"
             | [VALUE] expression

The expression evaluator uses arbitrary length arithmetic for numeric
operations. The precision to which operations are carried out by the
evaluator may be altered using the NUMERIC DIGITS command, and is
initially 9. The number supplied will be the number of digits kept after
each operation, not including the decimal point, or leading zeros, which
are dropped by all arithmetic operations. The upper limit for NUMERIC
DIGITS is about 10000 (defined in const.h).  Note that a single
multiplication or division can take many minutes at this precision.

NUMERIC FUZZ is initially zero and is set to zero by each NUMERIC DIGITS
command. It specifies a temporary reduction in the precision of
arithmetic when doing comparisons (remember, for all numeric comparisons,
the two operands are subtracted and the result is compared with zero. It
is the precision of the subtraction which is affected by NUMERIC FUZZ).
The upper limit for NUMERIC FUZZ is clearly one less than the current
value of NUMERIC DIGITS.

NUMERIC FORM is used to set the form of exponents to either `scientific'
mode or `engineering' mode. When an exponent is used, in the scientific
mode there is always precisely one digit, which is non-zero, before the
decimal point. In engineering mode, there are up to three digits before
the decimal point, and the exponent is always a multiple of three.
   If an expression is used, it must evaluate to "SCIENTIFIC" or
"ENGINEERING" in upper case. If the expression does not start with a
symbol or string constant, then the keyword VALUE may be omitted.

The NUMERIC settings are saved across function calls, and restored on
return from a function, so a function may set the precision, etc. that
it needs without affecting the caller.  Moreover, the settings will be
restored to their default settings just after entering any external
REXX procedure.

DO

There are two uses of DO:

1.  DO
    ...commands...
    END

  This is a compound statement, i.e. the DO and END are wrapped around
  the block of commands so that they appear like one statement and may
  be used in IF constructs.

2.  DO [ symbol=start  [TO  finish]  ]     [WHILE expression_w]
       [               [BY  step  ]  ]
       [               [FOR count ]  ]     [UNTIL expression_u]

       [ expression_c                ]
       [FOREVER                      ]

    ...commands...
    
    END [symbol]

    where start, finish, step, count and the expressions are numerical
    expressions. Expression_c and count are required to be non-negative
    integers.

  This is a repetitive command. If `symbol' is present in the DO
  statement, then:

    a. `symbol' may be any simple or compound symbol
    b. the symbol name may appear after the END statement; if it does,
       then it must be the same one as after the DO.  The DO symbol and
       the END symbol are compared literally, without substituting any
       components in the tail of a compound symbol, but the comparison
       is case insensitive.
    c. the value of start is assigned to the symbol before the loop is
       entered.
    d. if [TO finish] is present, then the loop is not executed after the
       control variable (named by the symbol) passes the finish value.
       If it is not present, then the loop may potentially be executed
       for ever (unless a FOR clause is present).
    e. if [BY step] is present, then the variable is incremented by step
       after each pass. Otherwise the variable is incremented by 1.
    f. If [FOR count] is present, then the loop is executed at most
       count times.
    g. The TO, FOR and BY clauses may be specified in any order. (Note:
       each should be specified at most once, but specifying one or more
       of these twice will not cause an error. The last one encountered
       is the one which is used).
  If `symbol' is not present, then nothing must follow the END.

  If the expression_c is specified, then the loop is executed this number
  of times (unless terminated by some other condition).  Note that
  expression_c must not start with a symbol followed by '=', because it
  would then be taken to be a `symbol' as above.  This may be prevented
  by enclosing the expression in parentheses.

  If a WHILE clause is present, then expression_w is evaluated before
  each pass and the loop is terminated if the result is false.
  
  If an UNTIL clause is present, then expression_u is evaluated after
  each pass and the loop is terminated if the result is true.
  
  A `DO FOREVER' instruction creates a loop which never terminates
  (unless a LEAVE instruction is encountered).
  
  Note that if expression_w is false or if the variable clause needs no
  repetition, or if count or expression_c is zero, then the body of the
  loop will not be executed at all.

An END must appear for each DO construct, and if labelled with a symbol,
must have the correct symbol.

NOTE: The name of any variable specified at the DO statement is
      evaluated again each time it is incremented at the end of a
      pass through the loop.  This means, for example, that in
      "DO a.i=1 TO 10", the name of the variable which is incremented
      depends on the current value of i.  (Altering the value of i is,
      of course, not highly recommended).

Example: The code

        do name=expri to exprt by exprb for exprf while exprw (or until expru)
           ... instructions ...
        end

will be executed as if it were written thus:

        $tempi = expri       /* variables staring with $ are */
        $tempt = exprt       /* invisible to the rest of the */
        $tempb = exprb       /* program. */
        $tempf = exprf
        name = $tempi + 0

 $loop: if name > $tempt then goto $end    /* "goto" is a pseudo-op */
        if $tempf = 0 then goto $end       /* meaning the obvious   */
        if \exprw then goto $end

        ... instructions ...

 $iter: if expru then goto $end            /* "iterate" will come here */
        name = name + $tempb
        $tempf = $tempf - 1
        goto $loop
 $end:                                     /* "leave" will come here */

(If any of the constructs in the original code are left out, the
coresponding lines will be left out of this example).

LEAVE [symbol]

If a symbol name is not specified, then LEAVE leaves the innermost
repetitive DO statement by jumping to the statement after the END
statement for that loop. If a symbol name is specified, then LEAVE
leaves the innermost loop with that symbol as control (i.e. where the
DO statement specified that symbol) - this may involve leaving several
inner loops.  The specified symbol must match that in the DO
instruction literally, except that case is ignored.
  The LEAVE statement will not return from procedures or functions.
  If there is no suitable loop to leave within the current function or
procedure call, then an error results.

NOTE: LEAVE will not exit from a string being interpreted: it is an
      error to use LEAVE within INTERPRET unless the corresponding DO
      occurs there as well.

ITERATE [symbol]

This instruction is similar to LEAVE, but instead of leaving the loop
it jumps to execute the END statement and possibly continue with another
iteration around the loop.  The same NOTE applies.

IF expression [;] THEN [;] instruction [ ; ELSE [;] instruction]

This construction has the obvious meaning. Note that the THEN and ELSE
must be followed by single instructions, but the DO-END or SELECT-END
(qv) and even IF-THEN-ELSE constructions count as single instructions
for this purpose.

A semicolon or line-end may optionally appear between the expression and
the THEN, but one must appear before ELSE, as above.

IF statements may be nested, but note that each ELSE statement
corresponds to the most recent IF statement without an ELSE. If a null
THEN or ELSE clause is needed, the NOP instruction must be used (as a
null statement is just ignored by REXX).

BUG: There is at present no way to detect incorrectly positioned ELSE
     statements. If an ELSE is detected during program interpretation,
     this will just cause the interpreter to skip the following statement
     and will not be an error. This bug also prevents the interpreter
     from flagging a construction such as "if expr then else ..." since
     in that case the "else" will be considered to be the statement to
     execute when expr is true.

SELECT [expression]

   WHEN expression THEN instruction
   WHEN expression THEN instruction
   ...
   [OTHERWISE instructions]
END [SELECT]

If an expression is supplied after SELECT, then this construction is like
a Pascal or Modula `CASE' construction. The expression is compared with
each of the other expressions in turn, until one is found that matches
(using the `=' form of equality). If a match is found, then the
corresponding instruction is executed. If a match is not found, then an
OTHERWISE clause must be specified, or else an error is reported. The
instructions after OTHERWISE will be executed.
  If an expression is not specified after SELECT, then the construction
is a list of guarded commands - that is, each expression is evaluated
until a true one is found, and the corresponding action is taken. Again,
if no expression is true and there is no OTHERWISE then an error is
reported.
  The word SELECT may be placed after the closing END but is optional.
Adding the word SELECT allows easier detection of missing ENDs.
  It is an error for the word WHEN or OTHERWISE to appear anywhere except
immediately inside a SELECT construction.
  Precisely one instruction is required after each WHEN, so NOP should be
used if no action is required. NOP need not be used after OTHERWISE.
  If multiple instructions are required to follow each WHEN condition,
then they should be contained in a DO ... END block.  Multiple
instructions may follow the OTHERWISE keyword.

LOCAL: The optional expression following the SELECT keyword, and the
       optional SELECT following the END keyword are features of PL/1
       and not of standard REXX.

PARSE [UPPER] string [template] (also: ARG [template], PULL [template])

[PARSE [UPPER]] ARG template
[PARSE [UPPER]] PULL [template]
PARSE [UPPER] LINEIN [template]
PARSE [UPPER] SOURCE template
PARSE [UPPER] VERSION template
PARSE [UPPER] NUMERIC template
PARSE [UPPER] VAR symbol template
PARSE [UPPER] VALUE expression WITH template

This command is a powerful parser which divides the operand up as
specified by the `template'. If the UPPER keyword is specified, then the
operand is uppercased before parsing.

The "ARG template" and "PULL template" commands are short forms of
"PARSE UPPER ARG template" and "PARSE UPPER PULL template" respectively.

The possible operands are as follows:

ARG   - the command-line arguments, or the arguments passed by a function
        or procedure call, are parsed.
PULL  - the top value on the stack, if one exists, is parsed; otherwise
        a line of input is read from the standard input and parsed as
        described for LINEIN below.  See QUEUE/PUSH for details about
        the stack.
LINEIN- A line is read directly from stdin.  The stack is not affected
        by this instruction.  In general, PULL is recommended in
        preference to LINEIN.

        If a line cannot be read because of an I/O error or EOF
        condition, then the NOTREADY condition will be raised and an
        empty string will be parsed.  The NOTREADY condition is ignored
        unless trapped by SIGNAL ON or CALL ON, in which case it is
        difficult to tell the difference between an empty input line
        and an I/O error.  However, the STREAM() function may be
        used to examine the most recent I/O error on stream "stdin".

        NOTE: If the program is interrupted (via ^C) while input is being
              read, then the characters which have been read in may be
              lost, but the remainder of a partially-input line will
              remain to be read again.

SOURCE- An implementation-dependent string representing the `source' of
        the program is parsed.
        In this implementation, the string contains five words:
         1. the system under which the interpreter runs (always UNIX)
         2. the way in which the program was called (one of COMMAND,
            FUNCTION or SUBROUTINE, depending whether the program was
            invoked by a command shell or as a function or subroutine)
         3. the name of the file containing the program, with the full
            path name (unless no directory was specified and getwd could
            not name the current directory)
         4. the name by which the program was called (always without a
            path name).
         5. the environment name which was current when the program
            started up
VERSION-A string representing the version of the REXX interpreter is
        parsed. This contains five words:
         1. A word describing the language, of which the first four
            letters are always REXX. In this implementation the word is
            REXX/imc.
         2. A string representing the version number (e.g. 1.0)
         3,4,5. The date on which the interpreter was compiled, in the
            same format as the DATE() function (e.g. 18 May 1990).
NUMERIC-The current NUMERIC settings are parsed.  There are three words
        in the string to be parsed: NUMERIC DIGITS, NUMERIC FUZZ and
        NUMERIC FORM respectively.
VAR   - The symbol specified is evaluated, and if it represents
        a currently defined variable, its value is substituted. The
        result is then parsed.
VALUE - The expression between "VALUE" and "WITH" is evaluated and then
        parsed (note that WITH is a reserved keyword in this instruction)

If no template is supplied, the information to be parsed is collected and
then thrown away.

The "ARG" and "VALUE" forms may parse more than one string at once. This
comes about with "ARG" when a function or procedure call (note - not a
command line call) passes more than one argument, or with "VALUE" when
the expression contains comma separators. In this case, the parse
template may contain commas. The part of the template before the first
comma applies to the first operand string, that part between the first
and second commas applies to the second string, and so on. E.g.

 PARSE VALUE 43 56,5*9,hello,there WITH template1,template2,
 
Here template1 applies to "43 56"; template2 applies to "5*9" and no
other parsing takes place. Note that there does not have to be a template
for each operand string, and also that there does not have to be an
operand string for each template (in this case the extra templates will
be applied to the empty string).

LOCAL: Parsing multiple strings with the PARSE VALUE construction is a
       local extension.

A parse template obeys the following grammar. A symbol in brackets
indicates that that symbol may be optionally present. A character in
single quotes indicates that that character should be typed literally.
A symbol in double quotes is a terminal symbol, indicating the
appropriate REXX entity should be present.

 template        -> [firstPosition] assignments [assignments]
 assignments     -> [nextPosition] varlist [stopPosition]
 varlist         -> varname [varlist]
 varname         ->   "non-constant symbol"
                    | '.'
 firstPosition   -> position
 nextPosition    -> position [nextPosition]
 stopPosition    -> position
 position        ->   searchPosition
                    | absPosition
                    | relPosition
                    | '(' "expression" ')'
 searchPosition  -> "string constant"
 absPosition     ->   "integer"
                    | '=' numexpr
 relPosition     ->   '+' numexpr
                    | '-' numexpr
 numexpr         ->   "integer"
                    | '(' "integer expression" ')'

Each position symbol in this grammar indicates a column number to the
parser. Positions are translated to column numbers (numbered from 1 up to
l+1, where l is the length of the string being parsed) in the following
way. Note that the absPosition indicator "1" is implicitly present
before and after any parse template.

absPosition:    gives the column number directly, except that numbers not
                between 1 and l+1 are translated into 1 or l+1 as
                appropriate.
searchPosition: searches for the given string constant in the string
                being parsed, starting from the most recent column number
                Usually, two column numbers result: the column number of
                the first character which matched, and that of the first
                character after the matching string. The latter number is
                suppressed if the next position indicator (if any) is a
                `relPosition'. If the string is not found, then the
                single column number l+1 results.
"expression":   evaluates the expression and then treats it as the string
                constant of a searchPosition
relPosition:    The given positive or negative number is added to the
                previous column number to give the result. As for an
                absolute position, numbers which are out of range are
                translated into 1 or l+1 as appropriate.

For example, given the string "hello, world, hello!" and the position
indicators 1 "ello" +4 ! 5 -3 'x' -2 1, the resulting column numbers
would be:
  1  (the given number)
  2  (the first character of "ello" - the second number is suppressed)
  6  (+4 characters from the previous position)
 20}{(the first character of "!")
 21}{(the first character after "!")
  5  (the given number)
  2  (-3 characters from 5)
 21  (the end of the string, since "x" is not found)
 19  (-2 characters from 21)
  1  (the given number)

The position indicators are translated into column numbers independent
of the varlist, except in one case described below. Thus the parse
template may be reduced by the above rules into a sequence of column
numbers and varlists. Taking into account the rule that each template is
implicitly prefixed and suffixed by the column number "1", each varlist
thus occurs between two column numbers. Each varlist is treated
separately, as follows:

Denote the varlist, together with the column numbers immediately before
and after the varlist, as m v1 v2 ... vk n. If m<n, or if m=n and
n resulted from a search, then there exists a well-defined substring s of
the string being parsed, which starts at column m and is of length n-m.
(this string ends at, but does not include, column n). Otherwise, let s
be that substring which starts at column m and continues to the end of
the string being parsed. Then the string s is divided between the
variables of the varlist by assigning the blank-delimited tokens to v1,
v2, ... in order. If there are more varnames in the varlist than there
are blank-delimited tokens, then the extra varnames are assigned with the
empty string. The tokens assigned to varnames v1, v2, ... , v(k-1) will
contain no leading or trailing blanks, but the token assigned to vk will
contain all blanks which occur after v(k-1), except for the one blank
immediately after v(k-1).

Each varname is either a symbol name or a dot. If the varname is a dot,
then the token which would be assigned to it is thrown away. Otherwise
the token is assigned to it in the usual way, just as if there had been
an instruction: symbol = token

NOTE: Most versions of REXX allow only a symbol name between parentheses
      where this version allows an arbitrary expression.

The one case in which the presence of a varlist may affect the
translation from position indicators to column numbers is when one or
more of the symbols mentioned in an "expression" is also stated in a
varlist. Hence:

PARSE VALUE "s/this/that" WITH 2 delim +1 first (delim) second

will assign "/" to delim, "this" to first and "that" to second. This is
because the variable delim is assigned as soon as the "+1" is reached.
This provides a way to provide commands (such as locate commands) which
take any string parameter and also some options. It allows any delimiter
to separate the parameter from the options.
However,

PARSE VALUE "s / this/that" WITH . delim first (delim) second

will not have the same effect, since delim and first are not assigned
until after the expression (delim) has been searched for.

Note that the symbols are assigned in order from left to right, so

PARSE VALUE "1 2 3" WITH a x.a y.a

will assign 1 to a, then 2 to x.1, then 3 to y.1

Other Examples:

PARSE VALUE "Hello there ! etc.." WITH a b ! . "c" c

will assign "Hello" to a and "there " to b, then throw away " et" and
assign ".." to c.

PARSE VALUE "123456789" WITH a +4 b 6 c

will assign "1234" to a, "5" to b, and "6789" to c.

PARSE VALUE "   multiple   spaces   between   words" WITH a b c

will assign "multiple" to a, "spaces" to b and "  between   words" to c.

PARSE VALUE "a  b  c  d  e  f" WITH "b" a b "e"

will assign "c" to a and " d  " to b.

PARSE VALUE "hello-there" WITH a "-" b -1 c +1

This assigns "hello" to a, "-there" to b and "o" to c. 

QUEUE [expression] ; PUSH [expression]

These instructions place the specified single expression on to the stack.
If the expression is omitted, then the null string will be used.
If QUEUE is used, the expression will be added in FIFO order (it will be
retrieved after all currently existing stack items). If PUSH is used, the
expression will be added in LIFO order (it will be retrieved before all
currently existing stack items).

Other programs may communicate with the REXX stack to provide data for
or retrieve data from a REXX program. See the separate section on the
REXX stack for details.

CALL name [arg][,[arg],...]]

The CALL command evaluates its arguments, if any, and passes them to the
named procedure.  The name may be either a symbol or a string constant.
If it is a symbol, then it will be translated to upper case before
use.

The procedure may or may not return a result.  If it does return a
result, then this is assigned to the variable RESULT, otherwise this
variable is dropped - that is, it will no longer have a value.

See the section on function or subroutine invocation for more details.

CALL ON  condition [NAME symbol]
CALL OFF condition

These call instructions provide error trapping.  The possible
conditions which may be trapped are as follows:

 FAILURE:  A command to the environment returned a "failure" code.
           Usually this means a negative return code, but see the
           section on commands to the environment.
 ERROR:    A command to the environment returned an "error" code.
           This usually means a non-zero return code.  Note that if
           "failures" are not being trapped, then "error" will catch
           failures also.
 NOTREADY: A function from the REXX I/O model (see the separate section)
           was unsuccessful because, for example, an input function
           encountered an end-of-file condition.
 HALT:     The user has attempted to halt the program, for example by
           typing Control-C.  Signals SIGHUP and SIGTERM also raise the
           HALT condition.

(These are the same conditions as for SIGNAL ON, except that the two
conditions SYNTAX and NOVALUE may not be trapped by CALL ON).

The CALL ON instruction turns on condition handling.  Whenever the
specified condition occurs, a CALL is made to a handling routine.  If
the NAME keyword is specified, then the following symbol is taken as
the name of the handling routine.  Otherwise the handling routine has
the same name as the condition.  On return from the call, execution
proceeds normally.  The RESULT variable will not be affected by the
call.  During the handling routine, the condition handling will be
set to "DELAY".  For the FAILURE, ERROR and NOTREADY conditions, this
means that further conditions will be ignored until the handling routine
returns or until handling is explicitly turned on or off.  For the HALT
condition, the program will continue executing but the halt signal will
be remembered until the handling routine returns or until handling is
explicitly turned on or off.  At that time the signal will be handled
in an appropriate way.

Condition handling with the CALL ON instruction always occurs at clause
boundaries.  When a condition occurs, it is delayed until the currently
executing clause has completed, and then the condition handler is
called.

At any time after the handling routine is called and before it returns,
the CONDITION() builtin function may be used to retrieve information
about the condition which was trapped.  The information provided by
this function is saved across function calls.  If a further condition
is handled while the handler is still active, this will not affect the
information which may be provided to the current handler.

When a condition handler is activated, the special variable SIGL is set
to the line number of the instruction in which the condition was
raised.  Also, for conditions ERROR and FAILURE, the special variable
RC will hold the return code of the command which caused the condition
to be raised.

Condition handling will always remain on until turned off with either
"CALL OFF condition" or "SIGNAL OFF condition".  If an external routine
is called, condition handling will be turned off temporarily until the
external routine finishes or turns condition handling on.

The status of condition handling is saved across function calls.  If a
subroutine uses a "CALL ON/OFF" or "SIGNAL ON/OFF" instruction, the
condition handling within the current routine will be unaffected.

A CALL OFF instructions cancels condition handling for a particular
condition.  If handling is turned off for ERROR, FAILURE or NOTREADY,
then the condition will be ignored whenever it occurs.  If handling is
turned off for HALT then the program will halt when the condition
occurs.

NOTE: Because calling the handling routine affects the special variable
      SIGL, this variable can no longer be trusted to remain constant
      when CALL ON HALT is in effect, since this condition can occur at
      any time without notice.

BUG:  The routine named in a CALL ON instruction must be an internal
      routine.  Built-in or external routines are not allowed.

RETURN [value]

This statement returns control to the most recent caller, optionally
returning a value to the caller. All current DO and SELECT structures
are exited and, if appropriate, the current variables are deleted and
the caller's variables are reinstated.

If the caller was a function call or a CALL statement, the value may be
any string which is passed to the caller in the manner described above.
If the caller was a function call, the return value must be given or an
error results.  On return from a condition handler, the result is
ignored.

If the caller was a shell (that is, no CALL statement or function call
is currently active), then the RETURN statement exits from the REXX
interpreter. The return value need not be given, but if it is specified
it must be an integer, which is returned to the shell as an exit status.

PROCEDURE

PROCEDURE EXPOSE var1 [var2 ...]
PROCEDURE HIDE var1 [var2 ...]    (LOCAL)

The PROCEDURE command is used in an internal function or procedure to
hide the caller's variables.

The PROCEDURE command on its own hides all the caller's variables and
makes sure that on return all the current function's variables are
erased. On return from a function containing this instruction, the
caller's old variables are reinstated when the current function's have
been deleted.

The PROCEDURE EXPOSE varlist command is like the form with no arguments
except that all the named variables are left visible. These variables
will all remain when the RETURN statement deletes all the other variables
from the current function. If any of the named variables are not defined,
then they will remain undefined until they are assigned a value. This
value will then be carried back to the calling procedure.

It is not an error to specify a symbol more than once; this will have
the same effect as specifying it just once.

Simple symbols, stems or compound symbols may be exposed.  If a stem is
named, then all possible compound symbols starting with that stem will
be exposed.

BUG: It is not possible to expose a stem and one of its compound
     symbols at the same time.  If a stem is named and one of its
     compound symbols appears later, then the compound symbol has in
     effect already been exposed and so the expected results will
     occur.  However, if a stem appears after one of its compound
     variables, the stem will be ignored without a warning.

Any symbol(s) in the list following PROCEDURE EXPOSE may be enclosed in
parentheses.  In such cases the value of the symbol is used as a list
of extra symbols to expose.  For example, if the assignment:
     list = "var1 var2 stem. misc.3"
occurred in the calling program, then the instruction:
     procedure expose test1 (list) test2
will expose the following symbols (in this order):
     test1 list var1 var2 stem. misc.3 test2
Notice that the symbol inside the parentheses is itself exposed before
its value is obtained.

LOCAL: The PROCEDURE HIDE varlist command hides only the named variables,
      leaving the rest visible. On return the hidden variables are
      deleted, leaving all the others. The action of PROCEDURE HIDE list
      is identical to that of
      PROCEDURE EXPOSE <every existing variable except those named>.
      (in fact what happens is that all existing symbols are exposed and
      then the named symbols are deleted from the new variable table.
      This command is therefore quite inefficient and should be used
      sparingly).
      The PROCEDURE HIDE statement may not hide individual compound
      variables. Only stems and simple symbols should be specified,
      otherwise a syntax error will result.
NOTE: This means that variables which are undefined when the
      PROCEDURE HIDE statement is executed will be deleted on return from
      the current function. However, if new compound variables are 
      defined having a stem in common with some compound variables which
      already exist, then the new compound variables will not be deleted
      on return.

NOTE: As in standard REXX, the order in which the symbols are named can
      have an effect. For example, if i=5 then
         procedure expose i a.i
      will expose i and the compound symbol a.5, but
         procedure expose a.i i
      will expose the compound symbol a.I and i. This is because the
      names are processed from left to right, and in the latter case the
      symbol i is not visible when the name a.i is encountered.

The PROCEDURE command will almost invariably be at the beginning of a
function or procedure. It may be used in the middle rather than at the
beginning, but this is not recommended. In fact the ANSI standard
states that PROCEDURE must be the first instruction of a subroutine, if
it is present. In any case, an error will result if it is used within
an INTERPRET, or a DO, or some other control structure.

LOCAL: If OPTIONS 'EXPOSE' (qv) is in effect then the PROCEDURE
       instruction will be allowed at the start of a program which is
       called as an external subroutine or function.  This allows
       variables from the caller (which would normally be hidden) to be
       exposed.  The instruction does not have to be the first in the
       program but it must not be placed inside any control structure (so
       it could, for example, be preceded by an OPTIONS 'EXPOSE'
       instruction).

Example: an improved version of the above factorial program
        parse arg x
        say x"!="fact(x)
        exit
 fact:  procedure           /* now we get a different p each time */
        parse arg p
        if p<3 then return p
        return fact(p-1) * p

NOTE: The special variable SIGL must be explicitly exposed if its current
      value is needed within the procedure.  It is set by the CALL
      instruction or the function call before any PROCEDURE instruction
      is encountered.

INTERPRET string

This command evaluates the given string and interprets it as if it were
part of a real rexx program. The string may contain any commands that
the program line containing the INTERPRET command might have executed
except that any DO or SELECT control blocks within the string must be
complete.  That is, the string may not start any new DO or SELECT
control blocks to be continued by the main program, and nor can it
contain an END, LEAVE, WHEN, etc. corresponding to a control block of
the main program.  An interpreted command can, however, cause a return
from a function.

NOTE: Interpreted strings must not contain labels.

Example: This program evaluates an expression given on the command line:

#!/mclab/imc/sun4/rexx  
parse arg x
interpret "y="||x
say x"="y

SIGNAL [VALUE] name | SIGNAL ON|OFF condition [NAME label]

1. SIGNAL [VALUE] name

In this form, the SIGNAL instruction is a primitive form of `goto'.
Using it to control program flow in this manner is strongly discouraged.

When this command is encountered interpretation jumps to the named label
(SIGNAL labels work just like procedure labels - but SIGNAL never invokes
another rexx program).

If the VALUE keyword is present, or if the name does not start with a
symbol or a string constant, then the name is treated as an expression
which must evaluate to the name of a label (irrespective of case).

All current DO and SELECT structures within the current procedure are
terminated by the SIGNAL instruction before the jump is taken.

When the SIGNAL instruction is executed, the variable SIGL is set to hold
the number of the line at the time of the jump. This can be used in
error analysis - as in:

  if something_is_wrong then signal error
  ...
  error: say "Something is wrong at line" sigl

or it can be used to type out long texts or help - as in:

   <lots of argument checking>
   if something_is_wrong then signal help /*
   This is a paragraph of help. It is enclosed in comments, so
   the interpreter ignores it. However the help routine will
   use the sourceline function to type it out on to the screen.
   */
   ...
   help: do i=sigl+1 while sourceline(i)~="*/"
   say sourceline(i)
   end

The SIGNAL VALUE construction is useful for calling procedures with
variable names. This can be done as follows:

   /* procname is set to the name of a procedure */
   call jumpto procname,arguments
   ...
   jumpto: parse arg jumpname
   signal value jumpname
   ...
When the named procedure is called, its first argument will be its name,
and the subsequent arguments will be those supplied by the caller.
The DO and SELECT structures in the calling program are protected from
the SIGNAL instruction, since the latter is encountered within procedure
`jumpto'.

2. SIGNAL ON  condition [NAME symbol]
   SIGNAL OFF condition

These instructions maintain exception handlers for the following
contitions:

 SYNTAX:   Any syntax error (for example "Bad arithmetic conversion" or
           "Unexpected ',' or ')'") which occurs during interpretation.
 NOVALUE:  A variable name is used which has no value.
           NOTE: This condition is not raised during interpretation of
                 sub-names in compound variables. Hence, if `foo' has no
                 value, then "a=foo+1" will cause a novalue error but
                 "a=abc.foo" will not cause an error unless ABC.'FOO' has
                 no value.  Also, the builtin function VALUE() will never
                 raise the NOVALUE condition.
 HALT:     The user has attempted to halt the program, for example by
           typing Control-C.  Signals SIGHUP and SIGTERM also raise the
           HALT condition.
 FAILURE:  A command to the environment returned a "failure" code.
           Usually this means a negative return code, but see the
           section on commands to the environment.
 ERROR:    A command to the environment returned an "error" code.
           This usually means a non-zero return code.  Note that if
           "failures" are not being trapped, then "error" will catch
           failures also.
 NOTREADY: A function from the REXX I/O model (see the separate section)
           was unsuccessful because, for example, an input function
           encountered an end-of-file condition.
           
(These are the same conditions as for CALL ON, with the two extra
conditions SYNTAX and NOVALUE).

The SIGNAL ON instruction turns on condition handling.  Whenever the
specified condition occurs, a SIGNAL is made to a handler.  If the NAME
keyword is specified, then the following symbol is taken as the name of
the handler.  Otherwise the handler has the same name as the condition.
At this point, RC holds the number of the error which caused the jump
(except in the case of NOTREADY) and SIGL holds the line number in
which the error occurred.  The routine in which the SIGNAL ON
instruction was encountered becomes the current routine; all internal
routines which became active since then are terminated.  All
DO/SELECT/IF control structures within the current routine are also
terminated.  The SIGNAL ON instruction is then cancelled, and another
SIGNAL ON instruction will be necessary to reinstate handling of this
particular condition.

At any time after control is passed to the handler, and before the
handler causes a return from the current subroutine, the CONDITION()
builtin function may be used to retrieve information about the
condition which was trapped.

A SIGNAL OFF instructions cancels condition handling for a particular
condition.  If handling is turned off for ERROR, FAILURE, NOTREADY or
NOVALUE, then the condition will be ignored whenever it occurs.  If
handling is turned off for HALT or SYNTAX, then the program will halt
when the condition occurs.

Condition handling persists from the point of the SIGNAL ON instruction
until the current function returns, or until a SIGNAL OFF instruction
is executed.  If an external routine is called, condition handling will
be turned off temporarily until the external routine finishes or turns
condition handling on.

The status of condition handling is saved across function calls.  If a
subroutine uses a "SIGNAL ON/OFF" or "CALL ON/OFF" instruction, the
condition handling within the current routine will be unaffected.

NOTE: The SIGNAL ON SYNTAX command does not trap fatal system errors or
      the error which is caused when EXIT or RETURN returns a non-integer
      to the UNIX environment (this is because the latter is, in effect,
      raised by the environment rather than by the interpreter itself).

TRACE [symbol]

TRACE "string"
TRACE VALUE expression

The symbol, string constant or expression is evaluated (the VALUE keyword
may be omitted if the expression does not start with a symbol or a string
constant).  It must evaluate to a word consisting of zero or more
question marks, followed by an optional letter, followed by an optional
string of characters. Each question mark at the start of the string
toggles the `interactive tracing' mode (see below), and the following
letter, if any, is translated to upper case and must be one of the
following:

   A (All):      all clauses are traced before execution
   C (Commands): all commands to the environment are traced before
                 execution, together with the actual string passed to
                 the environment. If the command results in a non-zero
                 return code, then the return code is traced after
                 execution.
   E (Error):    Any command to the environment resulting in an error
                 (i.e. non-zero return code) is traced after execution,
                 together with the return code
   F (Failure):  Any command to the environment resulting in failure
                 (i.e. negative return code) is traced after execution,
                 together with the return code
   I (Intermediates): All clauses are traced before execution, and all
                 calculations are traced, including intermediate values
                 evaluated during the calculation. Assignments made by
                 PARSE instructions are also traced.
   L (Labels):   All labels passed during execution are traced
   N (Normal):   the default setting - same as F.
   O (Off):      Nothing is traced, and interactive tracing is also
                 switched off.
   R (Results):  All clauses are traced before execution, and the results
                 from all calculations are traced. Assignments made by
                 PARSE instructions are also traced.

If no setting is specified or if the setting is an empty string, then
interactive tracing is turned off and tracing is set to "N".

When clauses are being traced (i.e. A, R or I), when an INTERPRET command
is traced, the actual string being interpreted is also traced. When an
END command is traced, the source statement to which the END corresponds
is also traced.

A program may be made to trace itself during execution by signalling
it with SIGQUIT (on the Suns this can be done by pressing "control \").
When this signal is received, the tracing mode switches to "?i". If
a SIGQUIT is received whilst in interactive tracing mode and if an
interruption has already been received but not handled, the program
exits immediately (as is the case when SIGQUIT is not handled).  This
feature exists mainly to stop the interpreter in case of a bug.

A program may be made to trace itself when execution starts by using the
"-t" commandline flag (see the invocation section for details).

Interactive tracing

In interactive trace mode, all TRACE instructions passed in the program
are ignored and the interpreter will pause after tracing each clause,
label, command or return code (as appropriate for the trace setting).
The interpreter prompts for input with the string ">trace>".
   If an empty line is entered (without spaces), execution of the
program continues normally until the next event which is traced.
   If a line of REXX is entered, then that line is interpreted with
tracing set to "E".  If the line calls a program, then TRACE
instructions in that program are ignored. If the line itself uses the
TRACE instruction, then the trace setting is altered accordingly and
execution of the program will continue after the input line has been
interpreted.
   If the input line does not contain a TRACE instruction, then when it
has been interpreted the prompt will reappear for more input.
   If an error occurs during interpretation of the input line, a message
is displayed and the prompt reappears (unless the command executed a
TRACE instruction). The error does not cause the program to exit, and
no signalling takes place (unless the error occurred in a program which
was called by the input line and which contains its own SIGNAL ON xxx
command).
   Commands to the environment within the string will not set the
variable RC, but will have non-zero return codes traced.
   All condition traps are turned off during interpretation of the
string.

It is possible to make the interpreter change tracing and also prompt
for more input by using the built-in TRACE function rather than the
TRACE instruction, for example:
   call trace r
sets the `results' tracing mode (whilst keeping interactive mode) without
continuing execution of the program.

The interactive tracing mode is useful for the following purposes (and
others):
   - single-stepping through a program (use trace ?a)
   - setting breakpoints (use trace ?l and put a label at the breakpoint)
   - examining or changing variables during execution.

The input line is interpreted in exactly the same way as with the
INTERPRET command, and so the same restrictions apply (e.g. DO and END
instructions etc must be matched properly).

BUG:The following also applies, however:
  - some of the source information is lost, so any PARSE SOURCE
    instruction in the line will have the calling method and the calling
    name replaced by "TRACE" (this does not apply to PARSE SOURCE
    instructions within programs that may be called by the input line).

If the input line transfers control by a SIGNAL instruction, then control
is immediately transferred to the target instruction and it is executed
before tracing resumes. If the input line contains a RETURN or EXIT
instruction, then execution returns to the caller and continues to the
end of the current statement. The return may cause a change in the
tracing mode, since this is saved across function calls. However, if
interactive tracing is still in effect, then tracing will resume at the
next instruction.

NOTE:If the interpreter has a controlling terminal (that is, "/dev/tty"
     can be opened when the interpreter initialises), then the trace
     prompt will be written to the terminal, and input will be read from
     the terminal. Otherwise, stderr and stdin are used respectively.
     If an error occurs during a command which was typed in interactive
     trace mode, then the error message will be written to the terminal.
     However, all normal input and output use stdin and stdout, while
     trace output is written to the requested file (see OPTIONS).  In
     particular, if tracing has been redirected, then no trace output
     will appear on the terminal. Therefore it is not a good idea to
     redirect tracing when interactive tracing will be used.

BUG: Interactive tracing is not recursive, i.e. if, during interactive
     tracing, a line is entered such as:
        trace i;say a+b
     then the tracing of "say a+b" (and other statements following the
     TRACE instruction) will not be interactive, even though the
     interactive tracing mode is (in theory) still in operation.

TRACE output

Each line of trace output is preceded by three characters which identify
the type of trace output. Any clause or command traced will be indented
according to its logical depth of nesting. Results (or intermediate
values) will be indented a further two spaces, and have leading and
trailing quotes added. The line numbers of source statements and labels
are displayed before the three-character prefix.  An interpreted
instruction or a command about to be executed will be displayed without
a line number.

The three-character prefixes are:

+++ A trace message (an error message, or the return code from a command)

*-* A source statement or label (exactly as it appears in the source).
*,* A source statement which is continued from the previous line.
*~* The result of evaluating an expression which is either a command to
    be passed to the environment or the parameter of an INTERPRET
    instruction.

>>> The result of an expression displayed in "trace r", or the value
    assigned to a variable during parsing or during update of the
    control variable of a repetitive DO loop.
>.> The value `assigned' to a placeholder (dot) during parsing.

The following prefixes are used during TRACE I:

>V> The contents of a variable
>L> a literal (that is, a constant symbol or number, an uninitialised
    variable, or a string/hex/binary constant)
>F> The result of applying a function
>P> The result of applying a prefix operator
>O> The result of applying a (binary) operator
>C> The name of a compound variable (after substitution and before use).

The trace setting is saved across function calls, so that if tracing is
switched on or off during a function, the previous setting is restored
when the function returns. This means that:
  - if a function is known to work, then "trace off" may be placed at
    the start. When a program is being traced, tracing is switched off
    when the function is entered, and back on when the function returns.
  - if a function is known not to work, then a trace instruction placed
    at the start of the function will switch tracing on only for the
    duration of the function call.

OPTIONS expression

The expression is evaluated and broken into blank-delimited words.
Each word is examined to see if it is recognised as a valid interpreter
option for this implementation.  Any word which is not recognised is
skipped over, since it probably applies to some other implementation.

In REXX/imc, the case of the options is not significant, and options
may be abbreviated.  The minimum abbreviation for each option is shown
in uppercase.  Options which require an '=' are only recognised if the
'=' sign is present and followed by a valid string. 

REXX/imc currently recognises the following options (options starting
"no" are listed under their opposites):

 EXPose              This option makes the PROCEDURE EXPOSE instruction
 NOEXPose            legal at the beginning of a program which is called
                     as an external subroutine or function, so that it
                     can gain access to the variables of the caller.  The
                     NOEXPose option restores the standard behaviour in
                     which PROCEDURE will cause an error when written at
                     the beginning of a program.  See also the PROCEDURE
                     instruction.

 SETRC               This option causes the I/O operations linein,
 NOSETRC             charin, lineout, charout, parse pull and parse
                     linein to set the RC special variable as they did in
                     earlier versions of REXX/imc.  If the NOTREADY
                     condition is not being trapped then an I/O operation
                     which sets RC to a nonzero value will instead
                     cause an ERROR condition to be raised, if that
                     is being trapped.  Option NOSETRC restores the
                     behaviour of I/O operations to the documented
                     behaviour.

 SIGPipe             Usually the interpreter terminates silently when it
 NOSIGPipe           receives a SIGPIPE signal.  This occurs when a
                     program tries to write data down a pipe with no
                     process to read it: for example, the command

                       rexx -s "do forever; say hello; end" | head -1

                     will echo one line of output before the "head"
                     process terminates, and the Rexx program will then
                     receive a SIGPIPE and terminate.

                     Using the SIGPipe option will make the interpreter
                     trap this signal and continue running.  In this
                     case the program should take care to detect error
                     conditions from LINEOUT, CHAROUT and other I/O
                     functions to avoid wasting resources.

                     Using the NOSIGPipe option will restore the
                     behaviour of terminating when a SIGPIPE signal is
                     received.

 TRACEfile=filespec  If "filespec" represents a filename which can be
                     opened for writing, then an information message is
                     written to the standard output and all trace output
                     is redirected to the named file.  Otherwise an error
                     message is written to the standard error and tracing
                     remains unchanged.  Instead of a regular file the
                     filespec can be "stdout" to send trace output to
                     the standard output or "stderr" to send it to the
                     standard error.

ADDRESS [VALUE] [environment] | ADDRESS environment command

When  the REXX interpreter finds a program statement which is not an
instruction (as listed above), then it evaluates the whole statement as
an expression (if it can), and issues the resulting string to the
current environment as a command.

The first form of the ADDRESS instruction stated above changes the
environment (until the next ADDRESS instruction).  If the environment
name is given, it may be a symbol (which is translated to upper case,
but not substituted by its value) or a string constant, or a string
expression preceded by the keyword VALUE.  The VALUE may be omitted if
the expression does not start with a symbol or a string constant.  The
current environment is changed to the given string.

If no environment name follows the ADDRESS instruction, then the previous
environment is made current.  For example:

   address unix       /* "UNIX" is current   */
   address "MY_ENV"   /* "MY_ENV" is current */
   address            /* "UNIX" is current   */
   address            /* "MY_ENV" is current */

The second form of the ADDRESS instruction given above executes a command
in a given environment without changing the current environment.  The
environment name must be a symbol or string constant, and the command may
be any string expression.  So, if the following line is appended to the
previous example:

   address command "ls -al"

the command "ls -al" is executed in environment "COMMAND", while the
current environment is still "MY_ENV".

Whenever a command is executed, the special variable RC is set to the
return code given by the command.  If this return code is non-zero,
then the command will also cause a FAILURE or ERROR condition to be
raised.  These conditions are ignored unless trapped by CALL ON or
SIGNAL ON.

Two environments are built in to REXX/imc:

ADDRESS UNIX

Each command sent to the "UNIX" environment is executed in a separate
Bourne shell.  Note that this involves considerable overhead, and
moreover no command can make a permanent change to the environment (e.g.
"set" and "export" will have no effect).  However, it does allow the
flexible syntax of the Bourne shell to be used, including piping, I/O
redirection, and filename expansion.

In this environment, any command which returns a code of 1 will raise
the FAILURE condition, as well as any command which returns a negative
return code.  This is because the Bourne shell always returns 1 when
it fails to find the requested command.

ADDRESS COMMAND

Each command sent to the "COMMAND" environment is tokenised and executed
by a primitive shell which is built into the interpreter (in shell.c).
This makes for quicker execution of each command, but note that at
present the only "meta-characters" which are supported are quotes.  That
is, enclosing a string in quotes passes it verbatim (i.e. untokenised)
as a parameter to a command.  In particular, piping, file redirection
and filename expansion are not supported.  Nor does this shell have any
builtin commands (such as cd, set), with the exception of "hash" (see
later).  For speed of execution, each time a command is executed its
path is remembered in a hash table.  The hash table statistics may be
obtained with the "hash" builtin command, which is similar to that of
the Bourne shell (and bash).  The command "hash name1 [name2 ...]" will
search for each of the given names and add the results to the hash
table, but if any of the names is "-r" then the hash table will be
cleared.  The names are examined from left to right, so "hash cat -r
ls" will result in just "/bin/ls" in the hash table.  The hash table is
also cleared whenever putenv() or value(,,"ENVIRONMENT") is used to
change PATH.  The command "hash" will print out the list of hash table
entries.  "hits" represents the number of times a command has been
looked up in the table, and "cost" represents the amount of work which
was initially carried out in searching along the path for the command.
A plus-sign in column 1 indicates that the entry was placed in the same
hash bucket as the previous entry; the commands within hash buckets are
arranged in alphabetical order.  The hash buckets are listed in no
particular order.

In this environment, an unrecognised command produces return code -3.
Any command which produces a negative return code will raise the
FAILURE condition.

Other environments may be added by application programs.

If a command is sent to an unrecognised environment, then return code
-3 and a FAILURE condition results.

The environment when a program starts up is usually UNIX.  The current
environment may be found by calling address(), and the environment at
startup may be found using "parse source".

Here is a simple shell program to demonstrate the use of commands:

do i
   sayn i'>'
   parse pull command
   parse upper var command word .
   if word='EXIT' then exit
   command
   if rc!=0 then say "The return code was" rc
end i

Each command is read from standard input. If the command 'Exit' is
received, the shell quits. Otherwise, the command is issued to a Bourne
Shell and the return code is checked.

Both the ADDRESS settings (that is, the current environment and the most
recent one) are saved across function calls.

NOTE: The program rxstack (in Oxford /mclab/imc/sun4/rxstack) may be
      used to access the stack while executing a shell command.  See
      the stack section below for details.