en:docs:os2:rexx

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
en:docs:os2:rexx [2024/09/04 06:49] – [Purpose of this document] prokusheven:docs:os2:rexx [2024/09/04 06:58] (current) prokushev
Line 24: Line 24:
 ===== Purpose of this document ===== ===== Purpose of this document =====
  
-The purpose of this document is to provide an overview of the Rexx Language and the osFree Classic REXX implementation of the REXX Language. It is not intended as a definitive reference to REXX; you should really have a copy of the REXX "bible"; The REXX Language, by Mike Cowlishaw [TRL2].+The purpose of this document is to provide an overview of the REXX Language and the osFree Classic REXX implementation of the REXX Language. It is not intended as a definitive reference to REXX; you should really have a copy of the REXX "bible"; The REXX Language, by Mike Cowlishaw [TRL2].
  
 ===== Implementation ===== ===== Implementation =====
Line 51: Line 51:
   * rexx is the name of the osFree Classic REXX executable   * rexx is the name of the osFree Classic REXX executable
   * switches are optional switches. See the section below for an explanation of the switches currently supported by osFree Classic REXX   * switches are optional switches. See the section below for an explanation of the switches currently supported by osFree Classic REXX
-  * program the name of the Rexx program to be executed. See the section External REXX Programs, below, for details on how osFree Classic REXX interprets this argument. If no program name is specified, osFree Classic REXX waits for REXX commands to be typed in and will execute those commands when the appropriate end-of-file character is typed.+  * program the name of the REXX program to be executed. See the section External REXX Programs, below, for details on how osFree Classic REXX interprets this argument. If no program name is specified, osFree Classic REXX waits for REXX commands to be typed in and will execute those commands when the appropriate end-of-file character is typed.
   * program parameters any optional parameters to be passed to the REXX program.   * program parameters any optional parameters to be passed to the REXX program.
  
Line 60: Line 60:
  
  
-The following switches allow the user to control how osFree Classic REXX executes the supplied Rexx program. Switches are recognised by either a leading hyphen character; '-', followed immediately by a single alphabetic character, or the full switch name preceded by two hyphen characters. Some switches allow for optional parameters. These, too must follow the switch without any intervening spaces. All switches and their optional parameters are case-sensitive. Single character switches that take no option can be combined. e.g. “-arp”+The following switches allow the user to control how osFree Classic REXX executes the supplied REXX program. Switches are recognised by either a leading hyphen character; '-', followed immediately by a single alphabetic character, or the full switch name preceded by two hyphen characters. Some switches allow for optional parameters. These, too must follow the switch without any intervening spaces. All switches and their optional parameters are case-sensitive. Single character switches that take no option can be combined. e.g. “-arp”
  
 <code> <code>
Line 81: Line 81:
 </code> </code>
  
-Without this switch, all command line parameters are passed to osFree Classic REXX as a single argument. Specifying -a, ensures that the Rexx program invoked has access to the command line parameters as separate arguments, as passed from the command line interpreter. i.e. The BIF ARG() can return a value of other than 1 or 0. Also PARSE SOURCE will return SUBROUTINE instead of the normal COMMAND value.+Without this switch, all command line parameters are passed to osFree Classic REXX as a single argument. Specifying -a, ensures that the REXX program invoked has access to the command line parameters as separate arguments, as passed from the command line interpreter. i.e. The BIF ARG() can return a value of other than 1 or 0. Also PARSE SOURCE will return SUBROUTINE instead of the normal COMMAND value.
  
 <code> <code>
Line 124: Line 124:
 </code> </code>
  
-This switch causes osFree Classic REXX to pause on exit. This switch is useful if you run Rexx programs from a GUI file manager and want to see the output from that program before the console window closes.+This switch causes osFree Classic REXX to pause on exit. This switch is useful if you run REXX programs from a GUI file manager and want to see the output from that program before the console window closes.
  
 <code> <code>
Line 193: Line 193:
 ====== REXX Language Constructs ====== ====== REXX Language Constructs ======
  
-In this chapter, the concept and syntax of Rexx clauses are explained. At the end of the chapter there is a section describing how osFree Classic REXX differs from standard Rexx as described in the first part of the chapter.+In this chapter, the concept and syntax of REXX clauses are explained. At the end of the chapter there is a section describing how osFree Classic REXX differs from standard REXX as described in the first part of the chapter.
  
  
 ===== Definitions ===== ===== Definitions =====
  
-A program in the Rexx language consists of clauses, which are divided into four groups: null clauses, commands, assignments, and instructions. The three latter groups (commands, assignments, and instructions) are collectively referred to as statements. This does not match the terminology in [TRL2], where "instruction" is equivalent to what is known here as "statement", and "keyword instruction" is equivalent to what is known here as "instruction". However, I find the terminology used here simpler and less confusing.+A program in the REXX language consists of clauses, which are divided into four groups: null clauses, commands, assignments, and instructions. The three latter groups (commands, assignments, and instructions) are collectively referred to as statements. This does not match the terminology in [TRL2], where "instruction" is equivalent to what is known here as "statement", and "keyword instruction" is equivalent to what is known here as "instruction". However, I find the terminology used here simpler and less confusing.
  
 Incidentally, the terminology used here matches [DANEY]. Incidentally, the terminology used here matches [DANEY].
Line 214: Line 214:
 Example: Binary transferring files Example: Binary transferring files
  
-Suppose a Rexx program is stored on an MS-DOS machine. Then, an end-of-line sequence is marked in the file as the two characters carriage return and newline. If this file is transferred to a Unix system, then only newline marks the end-of-line. For this to work, the file must be transferred as a text file. If it is (incorrectly) transferred as a binary file, the result is that on the Unix system, each line seems to contain a trailing carriage return character. In an editor, it might look like this:+Suppose a REXX program is stored on an MS-DOS machine. Then, an end-of-line sequence is marked in the file as the two characters carriage return and newline. If this file is transferred to a Unix system, then only newline marks the end-of-line. For this to work, the file must be transferred as a text file. If it is (incorrectly) transferred as a binary file, the result is that on the Unix system, each line seems to contain a trailing carriage return character. In an editor, it might look like this:
  
 <code rexx> <code rexx>
Line 226: Line 226:
 ==== Tokens ==== ==== Tokens ====
  
-The fundamental building block of a Rexx clause is a token. Tokens can be split into a number of different types; Literal Strings, Hexadecimal Strings, Binary Strings, Symbols, Operators and Special Characters.+The fundamental building block of a REXX clause is a token. Tokens can be split into a number of different types; Literal Strings, Hexadecimal Strings, Binary Strings, Symbols, Operators and Special Characters.
  
 === Literal String === === Literal String ===
Line 283: Line 283:
  
  
-The characters in the table below have special significance in Rexx's syntax. They also delimit tokens.+The characters in the table below have special significance in REXX's syntax. They also delimit tokens.
  
  
Line 395: Line 395:
 Example: Multiple assignment Example: Multiple assignment
  
-The difference between Rexx's multiple assignment and a default value can be seen from the following code:+The difference between REXX's multiple assignment and a default value can be seen from the following code:
  
 <code rexx> <code rexx>
Line 436: Line 436:
  
  
-In this section, all instructions in standard Rexx are described. Extensions are listed later in this chapter.+In this section, all instructions in standard REXX are described. Extensions are listed later in this chapter.
  
 First some notes on the terminology. What is called an instruction in this document is equivalent to a "unit" of clauses. That is, each instruction can consist of one or more clauses. For instance, the SAY instruction is always a single instruction, but the IF instruction is a multi-clause instruction. Consider the following script, where each clause has been boxed: First some notes on the terminology. What is called an instruction in this document is equivalent to a "unit" of clauses. That is, each instruction can consist of one or more clauses. For instance, the SAY instruction is always a single instruction, but the IF instruction is a multi-clause instruction. Consider the following script, where each clause has been boxed:
Line 450: Line 450:
 Then, some notes on the syntax diagrams used in the following descriptions of the instructions. The rules applying to these diagrams can be listed as: Then, some notes on the syntax diagrams used in the following descriptions of the instructions. The rules applying to these diagrams can be listed as:
  
-Anything written in courier font in the syntax diagrams indicates that it should occur as-is in the Rexx program. Whenever something is written in italic font, it means that the term should be substituted for another value, expression, or terms.+Anything written in courier font in the syntax diagrams indicates that it should occur as-is in the REXX program. Whenever something is written in italic font, it means that the term should be substituted for another value, expression, or terms.
  
 Anything contained within matching pairs of square brackets ([...]) are optional, and may be left out. Anything contained within matching pairs of square brackets ([...]) are optional, and may be left out.
Line 483: Line 483:
 You can generally identify these situations by the fact that they comes a bit below the real syntax diagram, and that they contains a colon character after the name of the term to be expanded. You can generally identify these situations by the fact that they comes a bit below the real syntax diagram, and that they contains a colon character after the name of the term to be expanded.
  
-In the syntax diagrams, some generic names have been used for the various parts, in order to indicate common attributes for the term. For instance, whenever a term in the syntax diagrams is called expr, it means that any valid Rexx expression may occur instead of that term. The most common such names are:+In the syntax diagrams, some generic names have been used for the various parts, in order to indicate common attributes for the term. For instance, whenever a term in the syntax diagrams is called expr, it means that any valid REXX expression may occur instead of that term. The most common such names are:
  
   condition   condition
Line 491: Line 491:
   expr   expr
  
-Indicates that the subclause can be any valid Rexx expression, and will in general be evaluated as normal during execution.+Indicates that the subclause can be any valid REXX expression, and will in general be evaluated as normal during execution.
  
   statement   statement
Line 531: Line 531:
 In other words: All normal commands are ADDRESS statements with a suppressed keyword and environment. In other words: All normal commands are ADDRESS statements with a suppressed keyword and environment.
  
-The environment term must be a symbol or a literal string. If it is a symbol, its "name" is used, i.e. it is not tail substituted or swapped for a variable value. The command and expression terms can be any Rexx expression. eg.+The environment term must be a symbol or a literal string. If it is a symbol, its "name" is used, i.e. it is not tail substituted or swapped for a variable value. The command and expression terms can be any REXX expression. eg.
  
 <code rexx> <code rexx>
Line 555: Line 555:
  
  
-Rexx maintains a list of environments, the size of this list is at least two. If you select a new environment, it will be put in the front of this list. Note that if command is specified, the contents of the environment stack is not changed. If you omit command, environment will always be put in the front of the list of environments. Regina has an infinite list and never pushes out any entry.+REXX maintains a list of environments, the size of this list is at least two. If you select a new environment, it will be put in the front of this list. Note that if command is specified, the contents of the environment stack is not changed. If you omit command, environment will always be put in the front of the list of environments. Regina has an infinite list and never pushes out any entry.
  
 Possible values are listed below. If you supply a command with the ADDRESS statement, the environment is interpreted as a temporary change for just this command. Possible values are listed below. If you supply a command with the ADDRESS statement, the environment is interpreted as a temporary change for just this command.
Line 630: Line 630:
 </code> </code>
  
-This environment uses a new instance of the Regina interpreter program to execute a program. The program has to be a Rexx script. This environment has several advantages. The output of a script can be redirected, the process is independent and a risk of a crash is minimized when playing with external libraries, finally, Regina itself tries to find the correct Rexx interpreter by itself and does everything to create a new incarnation of Regina.+This environment uses a new instance of the Regina interpreter program to execute a program. The program has to be a REXX script. This environment has several advantages. The output of a script can be redirected, the process is independent and a risk of a crash is minimized when playing with external libraries, finally, Regina itself tries to find the correct REXX interpreter by itself and does everything to create a new incarnation of Regina.
  
-The definition of Rexx says nothing about which environment is preselected when you invoke the interpreter, although TRL defines that one environment is automatically preselected when starting up a Rexx script. Note that there is no NONE environment in standard Rexx, i.e. an environment that ignores commands, but some interpreters implement the TRACE setting ??? to accomplish this. Regina uses the environment SYSTEM as the preselected environment as mentioned above. More implementation specific details can be found in the section implementation specific documentation for Regina.+The definition of REXX says nothing about which environment is preselected when you invoke the interpreter, although TRL defines that one environment is automatically preselected when starting up a REXX script. Note that there is no NONE environment in standard REXX, i.e. an environment that ignores commands, but some interpreters implement the TRACE setting ??? to accomplish this. Regina uses the environment SYSTEM as the preselected environment as mentioned above. More implementation specific details can be found in the section implementation specific documentation for Regina.
  
 The list of environments will be saved across subroutine calls; so the effect of any ADDRESS clauses in a subroutine will cease upon return from the subroutine. The list of environments will be saved across subroutine calls; so the effect of any ADDRESS clauses in a subroutine will cease upon return from the subroutine.
Line 671: Line 671:
   * Every environment has its own default redirection set.   * Every environment has its own default redirection set.
   * Every redirection set consists of three independent redirection elements; standard input (INPUT), standard output (OUTPUT) and standard error (ERROR). Users with some experiences with Unix, DOS & Windows or OS/2 may remember the redirection commands of the command line interpreter which can redirect each of the streams, too. This is nearly the same.   * Every redirection set consists of three independent redirection elements; standard input (INPUT), standard output (OUTPUT) and standard error (ERROR). Users with some experiences with Unix, DOS & Windows or OS/2 may remember the redirection commands of the command line interpreter which can redirect each of the streams, too. This is nearly the same.
-  * Each redirection element starts with the program-startup streams given to Rexx when invoking the interpreter. These can be reset to the startup default by specifying the argument NORMAL for each redirection element.+  * Each redirection element starts with the program-startup streams given to REXX when invoking the interpreter. These can be reset to the startup default by specifying the argument NORMAL for each redirection element.
   * The sequence of the redirection elements is irrelevant.   * The sequence of the redirection elements is irrelevant.
   * You can specify each redirection element only once per statement.   * You can specify each redirection element only once per statement.
Line 685: Line 685:
 The processor STEM uses the content of the symbol destination.0 to access the count of the currently accessible lines. destination is the given destination name, of course. destination.0 must be filled with a whole, non-negative number in terms of the DATATYPE built-in function. Each of n lines can be addressed by appending the whole numbers one to n to the stem. Example: STEM foo. is given, FOO.0 contains 3. This indicates three content lines. They are the contents of the symbols FOO.1 and FOO.2 and FOO.3 . The processor STEM uses the content of the symbol destination.0 to access the count of the currently accessible lines. destination is the given destination name, of course. destination.0 must be filled with a whole, non-negative number in terms of the DATATYPE built-in function. Each of n lines can be addressed by appending the whole numbers one to n to the stem. Example: STEM foo. is given, FOO.0 contains 3. This indicates three content lines. They are the contents of the symbols FOO.1 and FOO.2 and FOO.3 .
  
-The processor STREAM uses the content of the symbol destination to use a stream as known in the STREAM built-in function. The usage is nearly equivalent to the commands LINEIN destination or LINEOUT destination for accessing the contents of the file. An empty variable (content set to the empty string) as the content of the destination is allowed and indicates the default input, output or error streams given to the Rexx program. This is equivalent to the NORMAL keyword.+The processor STREAM uses the content of the symbol destination to use a stream as known in the STREAM built-in function. The usage is nearly equivalent to the commands LINEIN destination or LINEOUT destination for accessing the contents of the file. An empty variable (content set to the empty string) as the content of the destination is allowed and indicates the default input, output or error streams given to the REXX program. This is equivalent to the NORMAL keyword.
  
 The processor LIFO uses the content of the symbol destination as a queue name. New lines are pushed in last-in, first-out order to the queue. An empty destination string is allowed and describes the default queue. Lines are fetched from the queue if this processor is used for the INPUT stream. The processor LIFO uses the content of the symbol destination as a queue name. New lines are pushed in last-in, first-out order to the queue. An empty destination string is allowed and describes the default queue. Lines are fetched from the queue if this processor is used for the INPUT stream.
Line 695: Line 695:
 One line DELIMITER One line DELIMITER
  
-Second line and furthermore two processes p1 and p2 called WITH INPUT STREAM f with f containing the three lines above. p1 reads lines up until a line containing DELIMITER and p2 processes the rest. It is very likely that the second process won't fetch any line because the stream may be processed by Rexx, and Rexx may has put one or more lines ahead into the feeder pipe to the process. This might or might not happen. It is implementation dependent and Regina shows this behavior. The input object is checked for existence and if it is properly set up before the command is started.+Second line and furthermore two processes p1 and p2 called WITH INPUT STREAM f with f containing the three lines above. p1 reads lines up until a line containing DELIMITER and p2 processes the rest. It is very likely that the second process won't fetch any line because the stream may be processed by REXX, and REXX may has put one or more lines ahead into the feeder pipe to the process. This might or might not happen. It is implementation dependent and Regina shows this behavior. The input object is checked for existence and if it is properly set up before the command is started.
  
 In short: INPUT may or may not use the entire input. In short: INPUT may or may not use the entire input.
Line 819: Line 819:
 The called subroutines may or may not return data to the caller. In the calling routine, the special variable RESULT will be set to the return value or dropped, depending on whether any data was returned or not. Thus, the CALL instruction is equivalent to calling the routine as a function, and assigning the return value to RESULT, except when the routine does not return data. The called subroutines may or may not return data to the caller. In the calling routine, the special variable RESULT will be set to the return value or dropped, depending on whether any data was returned or not. Thus, the CALL instruction is equivalent to calling the routine as a function, and assigning the return value to RESULT, except when the routine does not return data.
  
-In Rexx, recursive routines are allowed. A minimum number of 100 nested internal and external subroutine invocations, and support for a minimum of 10 parameters for each call are required by Rexx. See chapter Limits for more information concerning implementation limits.+In REXX, recursive routines are allowed. A minimum number of 100 nested internal and external subroutine invocations, and support for a minimum of 10 parameters for each call are required by REXX. See chapter Limits for more information concerning implementation limits.
  
 When the token following CALL is either ON or OFF, the CALL instruction is not used for calling a subroutine, but for setting up condition traps. In this case, the third token of the clause must be the name of a condition, which setup is to be changed. When the token following CALL is either ON or OFF, the CALL instruction is not used for calling a subroutine, but for setting up condition traps. In this case, the third token of the clause must be the name of a condition, which setup is to be changed.
Line 845: Line 845:
 The DO/END instruction is the instruction used for looping and grouping several statements into one block. This is a multi-clause instruction. The DO/END instruction is the instruction used for looping and grouping several statements into one block. This is a multi-clause instruction.
  
-The most simple case is when there is no repetitor or conditional it groups zero or more Rexx clauses into one conceptual statement. This is most often used to execute multiple clauses in an IF instruction.+The most simple case is when there is no repetitor or conditional it groups zero or more REXX clauses into one conceptual statement. This is most often used to execute multiple clauses in an IF instruction.
  
 e.g. e.g.
Line 910: Line 910:
 will start with CTRL being 1, and then iterate through 2, 3, 4, ..., and never terminate except by LEAVE, RETURN, SIGNAL, or EXIT. will start with CTRL being 1, and then iterate through 2, 3, 4, ..., and never terminate except by LEAVE, RETURN, SIGNAL, or EXIT.
  
-Although similar constructs in other languages typically provokes an overflow at some point, something "strange" happens in Rexx. Whenever the value of ctrl becomes too large, the incrementation of that variable produces a result that is identical to the old value of ctrl. For NUMERIC DIGITS set to 9, this happens when ctrl becomes 1.00000000E+9. When adding 1 to this number, the result is still 1.00000000E+9. Thus, the loop "converges" at that value.+Although similar constructs in other languages typically provokes an overflow at some point, something "strange" happens in REXX. Whenever the value of ctrl becomes too large, the incrementation of that variable produces a result that is identical to the old value of ctrl. For NUMERIC DIGITS set to 9, this happens when ctrl becomes 1.00000000E+9. When adding 1 to this number, the result is still 1.00000000E+9. Thus, the loop "converges" at that value.
  
 If the value of NUMERIC DIGITS is 1, then it will "converge" at 10, or 1E+1 which is the "correct" way of writing that number under NUMERIC DIGITS 1. You can in general disregard loop "convergence", because it will only occur in very rare situations. If the value of NUMERIC DIGITS is 1, then it will "converge" at 10, or 1E+1 which is the "correct" way of writing that number under NUMERIC DIGITS 1. You can in general disregard loop "convergence", because it will only occur in very rare situations.
Line 918: Line 918:
 One frequent misunderstanding is that the WHILE and UNTIL subclauses of the DO/END instruction are equivalent, except that WHILE is checked before the first iteration, while UNTIL is first checked before the second iteration. One frequent misunderstanding is that the WHILE and UNTIL subclauses of the DO/END instruction are equivalent, except that WHILE is checked before the first iteration, while UNTIL is first checked before the second iteration.
  
-This may be so in other languages, but in Rexx. Because of the order in which the parts of the loop are performed, there are other differences. Consider the following code:+This may be so in other languages, but in REXX. Because of the order in which the parts of the loop are performed, there are other differences. Consider the following code:
  
 <code rexx> <code rexx>
Line 942: Line 942:
 Note that on exit from a loop, the value of the control variable has been incremented once after the last iteration of the loop, if the loop was terminated by the WHILE expression, by exceeding the number of max iterations, or if the control variable exceeded the stop value. However, the control variable has the value of the last iteration if the loop was terminated by the UNTIL expression, or by an instruction inside the loop (e.g. LEAVE, SIGNAL, etc.). Note that on exit from a loop, the value of the control variable has been incremented once after the last iteration of the loop, if the loop was terminated by the WHILE expression, by exceeding the number of max iterations, or if the control variable exceeded the stop value. However, the control variable has the value of the last iteration if the loop was terminated by the UNTIL expression, or by an instruction inside the loop (e.g. LEAVE, SIGNAL, etc.).
  
-The following algorithm in Rexx code shows the execution of a DO instruction, assuming that expri, exprt, exprb, exprf, exprw, expru, and symbol have been taken from the syntax diagram of DO.+The following algorithm in REXX code shows the execution of a DO instruction, assuming that expri, exprt, exprb, exprf, exprw, expru, and symbol have been taken from the syntax diagram of DO.
  
 <code rexx> <code rexx>
Line 990: Line 990:
 However, this process is not recursive, so that the list of names referred to indirectly can not itself contain parentheses. Note that the second form was introduced in TRL2, mainly in order to make INTERPRET unnecessary. However, this process is not recursive, so that the list of names referred to indirectly can not itself contain parentheses. Note that the second form was introduced in TRL2, mainly in order to make INTERPRET unnecessary.
  
-In general, things contained in parentheses can be any valid Rexx expression, but this does not apply to the DROP, PARSE, and PROCEDURE instructions.+In general, things contained in parentheses can be any valid REXX expression, but this does not apply to the DROP, PARSE, and PROCEDURE instructions.
  
 Example: Dropping compound variables Example: Dropping compound variables
Line 1025: Line 1025:
 </code> </code>
  
-Terminates the Rexx program, and optionally returns the expression expr to the caller. If specified, expr can be any string. In some systems, there are restrictions on the range of valid values for the expr. Often the return expression must be an integer, or even a non-negative integer. This is not really a restriction on the Rexx language itself, but a restriction in the environment in which the interpreter operates, check the system dependent documentation for more information.+Terminates the REXX program, and optionally returns the expression expr to the caller. If specified, expr can be any string. In some systems, there are restrictions on the range of valid values for the expr. Often the return expression must be an integer, or even a non-negative integer. This is not really a restriction on the REXX language itself, but a restriction in the environment in which the interpreter operates, check the system dependent documentation for more information.
  
-If expr is omitted, nothing will be returned to the caller. Under some circumstances that is not legal, and might be handled as an error or a default value might be used. The EXIT instruction behaves differently in a "program" than in an external subroutine. In a "program", it returns control to the caller e.g. the operating system command interpreter. While for an external routine, it returns control to the calling Rexx script, independent of the level of nesting inside the external routine being terminated.+If expr is omitted, nothing will be returned to the caller. Under some circumstances that is not legal, and might be handled as an error or a default value might be used. The EXIT instruction behaves differently in a "program" than in an external subroutine. In a "program", it returns control to the caller e.g. the operating system command interpreter. While for an external routine, it returns control to the calling REXX script, independent of the level of nesting inside the external routine being terminated.
  
 |                                                     | RETURN                                  | EXIT                          | |                                                     | RETURN                                  | EXIT                          |
Line 1037: Line 1037:
 Actions of RETURN and EXIT Instructions Actions of RETURN and EXIT Instructions
  
-If terminating an external routine (i.e. returning to the calling Rexx script) any legal Rexx string value is allowed as a return value. Also, no return value can be returned, and in both cases, this information is successfully transmitted back to the calling routine. In the case of a function call (as opposed to a subroutine call), returning no value will raise SYNTAX condition {44}. The table above describes the actions taken by the EXIT and RETURN instruction in various situations.+If terminating an external routine (i.e. returning to the calling REXX script) any legal REXX string value is allowed as a return value. Also, no return value can be returned, and in both cases, this information is successfully transmitted back to the calling routine. In the case of a function call (as opposed to a subroutine call), returning no value will raise SYNTAX condition {44}. The table above describes the actions taken by the EXIT and RETURN instruction in various situations.
  
 ==== The IF/THEN/ELSE Instruction ==== ==== The IF/THEN/ELSE Instruction ====
Line 1075: Line 1075:
 </code> </code>
  
-The INTERPRET instruction is used to dynamically build and execute Rexx instructions during run-time. First, it evaluates the expression expr, and then parses and interprets the result as a (possibly empty) list of Rexx instructions to be executed. For instance:+The INTERPRET instruction is used to dynamically build and execute REXX instructions during run-time. First, it evaluates the expression expr, and then parses and interprets the result as a (possibly empty) list of REXX instructions to be executed. For instance:
  
 <code rexx> <code rexx>
Line 1085: Line 1085:
 executes the statement SAY "hello, world!" after having evaluated the expression following INTERPRET. This example shows several important aspects of INTERPRET. Firstly, it's very easy to get confused by the levels of quotes, and a bit of caution should be taken to nest the quotes correctly. Secondly, the use of INTERPRET does not exactly improve readability. executes the statement SAY "hello, world!" after having evaluated the expression following INTERPRET. This example shows several important aspects of INTERPRET. Firstly, it's very easy to get confused by the levels of quotes, and a bit of caution should be taken to nest the quotes correctly. Secondly, the use of INTERPRET does not exactly improve readability.
  
-Also, INTERPRET will probably increase execution time considerably if put inside loops, since the interpreter may be forced to reparse the source code for each iteration. Many optimizing Rexx interpreters (and in particular Rexx compilers) has little or no support for INTERPRET. Since virtually anything can happen inside it, it is hard to optimize, and it often invalidates assumptions in other parts of the script, forcing it to ignore other possible optimizations. Thus, you should avoid INTERPRET when speed is at a premium.+Also, INTERPRET will probably increase execution time considerably if put inside loops, since the interpreter may be forced to reparse the source code for each iteration. Many optimizing REXX interpreters (and in particular REXX compilers) has little or no support for INTERPRET. Since virtually anything can happen inside it, it is hard to optimize, and it often invalidates assumptions in other parts of the script, forcing it to ignore other possible optimizations. Thus, you should avoid INTERPRET when speed is at a premium.
  
 There are some restrictions on which statements can be inside an INTERPRET statement. Firstly, labels cannot occur there. TRL states that they are not allowed, but you may find that in some implementations labels occurring there will not affect the label symbol table of the program being run. Consider the statement: There are some restrictions on which statements can be inside an INTERPRET statement. Firstly, labels cannot occur there. TRL states that they are not allowed, but you may find that in some implementations labels occurring there will not affect the label symbol table of the program being run. Consider the statement:
Line 1100: Line 1100:
 Example: Self-modifying Program Example: Self-modifying Program
  
-There is an idea for a self-modifying program in Rexx which is basically like this:+There is an idea for a self-modifying program in REXX which is basically like this:
  
 <code rexx> <code rexx>
Line 1118: Line 1118:
 </code> </code>
  
-Unfortunately, there are several reasons why this program will not work in Rexx, and it may be instructive to investigate why. Firstly, it uses the label TRANSFORM, which is not allowed in the argument to INTERPRET. The interpret will thus refer to the TRANSFORM routine of the "outermost" invocation, not the one "in" the INTERPRET string.+Unfortunately, there are several reasons why this program will not work in REXX, and it may be instructive to investigate why. Firstly, it uses the label TRANSFORM, which is not allowed in the argument to INTERPRET. The interpret will thus refer to the TRANSFORM routine of the "outermost" invocation, not the one "in" the INTERPRET string.
  
 Secondly, the program does not take line continuations into mind. Worse, the SOURCELINE() built-in function refers to the data of the main program, even inside the code executed by the INTERPRET instruction. Thirdly, the program will never end, as it will nest itself up till an implementation-dependent limit for the maximum number of nested INTERPRET instructions. Secondly, the program does not take line continuations into mind. Worse, the SOURCELINE() built-in function refers to the data of the main program, even inside the code executed by the INTERPRET instruction. Thirdly, the program will never end, as it will nest itself up till an implementation-dependent limit for the maximum number of nested INTERPRET instructions.
Line 1189: Line 1189:
 </code> </code>
  
-Rexx has an unusual form of arithmetic. Most programming languages use integer and floating point arithmetic, where numbers are coded as bits in the computers native memory words. However, Rexx uses floating point arithmetic of arbitrary precision, that operates on strings representing the numbers. Although much slower, this approach gives lots of interesting functionality. Unless number-crunching is your task, the extra time spent by the interpreter is generally quite acceptable and often almost unnoticeable.+REXX has an unusual form of arithmetic. Most programming languages use integer and floating point arithmetic, where numbers are coded as bits in the computers native memory words. However, REXX uses floating point arithmetic of arbitrary precision, that operates on strings representing the numbers. Although much slower, this approach gives lots of interesting functionality. Unless number-crunching is your task, the extra time spent by the interpreter is generally quite acceptable and often almost unnoticeable.
  
 The NUMERIC statement is used to control most aspects of arithmetic operations. It has three distinct forms: DIGITS, FORM and FUZZ; which to choose is given by the second token in the instruction: The NUMERIC statement is used to control most aspects of arithmetic operations. It has three distinct forms: DIGITS, FORM and FUZZ; which to choose is given by the second token in the instruction:
Line 1209: Line 1209:
 The setting of FORM never affects the decision about whether to choose exponential form or normal floating point form; it only affects the appearance of the exponential form once that form has been selected. The setting of FORM never affects the decision about whether to choose exponential form or normal floating point form; it only affects the appearance of the exponential form once that form has been selected.
  
-Many things can be said about the usefulness of FUZZ. My impression is that it is seldom used in Rexx programs. One problem is that it only addresses relative inaccuracy: i.e. that the smaller value must be within a certain range, that is determined by a percentage of the larger value. Often one needs absolute inaccuracy, e.g. two measurements are equal if their difference are less than a certain absolute threshold.+Many things can be said about the usefulness of FUZZ. My impression is that it is seldom used in REXX programs. One problem is that it only addresses relative inaccuracy: i.e. that the smaller value must be within a certain range, that is determined by a percentage of the larger value. Often one needs absolute inaccuracy, e.g. two measurements are equal if their difference are less than a certain absolute threshold.
  
 Example: Simulating relative accuracy with absolute accuracy Example: Simulating relative accuracy with absolute accuracy
  
-As explained above, Rexx arithmetic has only relative accuracy, in order to obtain absolute accuracy, one can use the following trick:+As explained above, REXX arithmetic has only relative accuracy, in order to obtain absolute accuracy, one can use the following trick:
  
 <code rexx> <code rexx>
Line 1239: Line 1239:
 </code> </code>
  
-The OPTIONS instruction is used to set various interpreter-specific options. Its typical uses are to select certain Rexx dialects, enable optimizations (e.g. time versus memory considerations), etc. No standard dictates what may follow the OPTIONS keyword, except that it should be a valid Rexx expression, which is evaluated. Currently, no specific options are required by any standard.+The OPTIONS instruction is used to set various interpreter-specific options. Its typical uses are to select certain REXX dialects, enable optimizations (e.g. time versus memory considerations), etc. No standard dictates what may follow the OPTIONS keyword, except that it should be a valid REXX expression, which is evaluated. Currently, no specific options are required by any standard.
  
-The contents of expr is supposed to be word based, and it is the intention that more than one option can be specified in one OPTIONS instruction. Rexx interpreters are specifically instructed to ignore OPTIONS words which they do not recognize. That way, a program can use run-time options for one interpreter, without making other interpreters trip when they see those options. An example of OPTION may be:+The contents of expr is supposed to be word based, and it is the intention that more than one option can be specified in one OPTIONS instruction. REXX interpreters are specifically instructed to ignore OPTIONS words which they do not recognize. That way, a program can use run-time options for one interpreter, without making other interpreters trip when they see those options. An example of OPTION may be:
  
 <code rexx> <code rexx>
Line 1247: Line 1247:
 </code> </code>
  
-The instruction might instruct the interpreter to start enforcing language level 4.00, and to use native floating point numbers in stead of the Rexx arbitrary precision arithmetic. On the other hand, it might also be completely ignored by the interpreter.+The instruction might instruct the interpreter to start enforcing language level 4.00, and to use native floating point numbers in stead of the REXX arbitrary precision arithmetic. On the other hand, it might also be completely ignored by the interpreter.
  
 It is uncertain whether modes selected by OPTIONS will be saved across subroutine calls. Refer to implementation-specific documentation for information about this. It is uncertain whether modes selected by OPTIONS will be saved across subroutine calls. Refer to implementation-specific documentation for information about this.
Line 1294: Line 1294:
 SOURCE. SOURCE.
  
-The source string for the parsing is a string containing information about how this invocation of the Rexx interpreter was started. This information will not change during the execution of a Rexx script. The format of the string is:+The source string for the parsing is a string containing information about how this invocation of the REXX interpreter was started. This information will not change during the execution of a REXX script. The format of the string is:
  
 <code> <code>
Line 1302: Line 1302:
 Here, the first space-separated word (system) is a single word describing the platform on which the system is running. Often, this is the name of the operating system. The second word describes how the script was invoked. TRL2 suggests that invocation could be COMMAND, FUNCTION, or SUBROUTINE, but notes that this may be specific to VM/CMS. Here, the first space-separated word (system) is a single word describing the platform on which the system is running. Often, this is the name of the operating system. The second word describes how the script was invoked. TRL2 suggests that invocation could be COMMAND, FUNCTION, or SUBROUTINE, but notes that this may be specific to VM/CMS.
  
-Everything after the second word is implementation-dependent. It is indicated that it should refer to the name of the Rexx script, but the format is not specified. In practice, the format will differ because the format of file names differs between various operating systems. Also, the part after the second word might contain other types of information. Refer to the implementation-specific notes for exact information.+Everything after the second word is implementation-dependent. It is indicated that it should refer to the name of the REXX script, but the format is not specified. In practice, the format will differ because the format of file names differs between various operating systems. Also, the part after the second word might contain other types of information. Refer to the implementation-specific notes for exact information.
  
 VALUE expr WITH. VALUE expr WITH.
Line 1314: Line 1314:
 VERSION. VERSION.
  
-This format resembles SOURCE, but it contains information about the version of Rexx that the interpreter supports. The string contains five words, and has the following format:+This format resembles SOURCE, but it contains information about the version of REXX that the interpreter supports. The string contains five words, and has the following format:
  
 <code> <code>
Line 1320: Line 1320:
 </code> </code>
  
-Where language is the name of the language supported by the Rexx interpreter. This may seem like overkill, since the language is Rexx, but there may be various different dialects of Rexx. The word can be just about anything, except for two restrictions, the first four letters should be REXX (in upper case), and the word should not contain any periods. [TRL2] indicates that the remainder of the word (after the fourth character) can be used to identify the implementation.+Where language is the name of the language supported by the REXX interpreter. This may seem like overkill, since the language is REXX, but there may be various different dialects of REXX. The word can be just about anything, except for two restrictions, the first four letters should be REXX (in upper case), and the word should not contain any periods. [TRL2] indicates that the remainder of the word (after the fourth character) can be used to identify the implementation.
  
-The second word is the Rexx language level supported by the interpreter. Note that this is not the same as the version of the interpreter, although several implementations makes this mistake. Strictly speaking, neither [TRL1] nor [TRL2] define the format of this word, but a numeric format is strongly suggested.+The second word is the REXX language level supported by the interpreter. Note that this is not the same as the version of the interpreter, although several implementations makes this mistake. Strictly speaking, neither [TRL1] nor [TRL2] define the format of this word, but a numeric format is strongly suggested.
  
 The last three words (date, month, and year) makes up the date part of the string. This is the release date of the interpreter, in the default format of the DATE() built-in function. The last three words (date, month, and year) makes up the date part of the string. This is the release date of the interpreter, in the default format of the DATE() built-in function.
  
-Much confusion seems to be related to the second word of PARSE VERSION. It describes the language level, which is not the same as the version number of the interpreter. In fact, most interpreters have a version numbering which is independent of the Rexx language level.+Much confusion seems to be related to the second word of PARSE VERSION. It describes the language level, which is not the same as the version number of the interpreter. In fact, most interpreters have a version numbering which is independent of the REXX language level.
  
-Unfortunately, several interpreters makes the mistake of using this field as for their own version number. This is very unfortunate for two reasons; first, it is incorrect, and second, it makes it difficult to determine which Rexx language level the interpreter is supposed to support.+Unfortunately, several interpreters makes the mistake of using this field as for their own version number. This is very unfortunate for two reasons; first, it is incorrect, and second, it makes it difficult to determine which REXX language level the interpreter is supposed to support.
  
 Chances are that you can find the interpreter version number in PARSE SOURCE or the first word of PARSE VERSION. Chances are that you can find the interpreter version number in PARSE SOURCE or the first word of PARSE VERSION.
  
-The format of the Rexx language level is not rigidly defined, but TRL1 corresponds to the language level 3.50, while TRL2 corresponds to the language level 4.00. Both implicitly indicate the that language level description is a number, and states that an implementation less than a certain number "may be assumed to indicate a subset" of that language level. However, this must not be taken to literally, since language level 3.50 has at least two features which are missing in language level 4.00 (the Scan trace setting, and the PROCEDURE instruction that is not forced to be the first instruction in a subroutine). [TRH:PRICE] gives a very good overview over the varying functionality of different language levels of Rexx up to level 4.00.+The format of the REXX language level is not rigidly defined, but TRL1 corresponds to the language level 3.50, while TRL2 corresponds to the language level 4.00. Both implicitly indicate the that language level description is a number, and states that an implementation less than a certain number "may be assumed to indicate a subset" of that language level. However, this must not be taken to literally, since language level 3.50 has at least two features which are missing in language level 4.00 (the Scan trace setting, and the PROCEDURE instruction that is not forced to be the first instruction in a subroutine). [TRH:PRICE] gives a very good overview over the varying functionality of different language levels of REXX up to level 4.00.
  
-With the release of the ANSI Rexx Standard [ANSI] in 1996, the Rexx language IS now rigidly defined. The language level of ANSI Rexx is 5.00. Regina is now compliant to the ANSI Standard. Thus PARSE VERSION will return 5.00.+With the release of the ANSI REXX Standard [ANSI] in 1996, the REXX language IS now rigidly defined. The language level of ANSI REXX is 5.00. Regina is now compliant to the ANSI Standard. Thus PARSE VERSION will return 5.00.
  
-Note that even though the information of the PARSE SOURCE is constant throughout the execution of a Rexx script, this is not necessarily correct for the PARSE VERSION. If your interpreter supports multiple language levels (e.g. through the OPTIONS instruction), then it will have to change the contents of the PARSE VERSION string in order to comply with different language levels. To some extent, this may also apply to PARSE SOURCE, since it may have to comply with several implementation-specific standards.+Note that even though the information of the PARSE SOURCE is constant throughout the execution of a REXX script, this is not necessarily correct for the PARSE VERSION. If your interpreter supports multiple language levels (e.g. through the OPTIONS instruction), then it will have to change the contents of the PARSE VERSION string in order to comply with different language levels. To some extent, this may also apply to PARSE SOURCE, since it may have to comply with several implementation-specific standards.
  
 After the source string has been selected by the type subclause in the PARSE instruction, this string is parsed into the template. The functionality of templates is common for the PARSE, ARG and PULL instructions, and is further explained in chapter [not yet written]. After the source string has been selected by the type subclause in the PARSE instruction, this string is parsed into the template. The functionality of templates is common for the PARSE, ARG and PULL instructions, and is further explained in chapter [not yet written].
Line 1347: Line 1347:
 </code> </code>
  
-The PROCEDURE instruction is used by Rexx subroutines in order to control how variables are shared among routines. The simplest use is without any parameters; then all future references to variables in that subroutine refer to local variables. If there is no PROCEDURE instruction in a subroutine, then all variable references in that subroutine refer to variables in the calling routine's name space.+The PROCEDURE instruction is used by REXX subroutines in order to control how variables are shared among routines. The simplest use is without any parameters; then all future references to variables in that subroutine refer to local variables. If there is no PROCEDURE instruction in a subroutine, then all variable references in that subroutine refer to variables in the calling routine's name space.
  
 If the EXPOSE subkeyword is specified too, then any references to the variables in the list following EXPOSE refer to local variables, but to variables in the name space of the calling routine. If the EXPOSE subkeyword is specified too, then any references to the variables in the list following EXPOSE refer to local variables, but to variables in the name space of the calling routine.
Line 1368: Line 1368:
 Several restrictions have been imposed on PROCEDURE in [TRL2] in order to simplify the execution of PROCEDURE (and in particular, to ease the implementation of optimizing interpreters and compilers). Several restrictions have been imposed on PROCEDURE in [TRL2] in order to simplify the execution of PROCEDURE (and in particular, to ease the implementation of optimizing interpreters and compilers).
  
-The first restriction, to which all Rexx interpreters adhere as far as I know, is that each invocation of a subroutine (i.e. not the main program) may execute PROCEDURE at most once. Both TRL1 and TRL2 contain this restriction. However, more than one PROCEDURE instruction may exist "in" each routine, as long as at most one is executed at each invocation of the subroutine.+The first restriction, to which all REXX interpreters adhere as far as I know, is that each invocation of a subroutine (i.e. not the main program) may execute PROCEDURE at most once. Both TRL1 and TRL2 contain this restriction. However, more than one PROCEDURE instruction may exist "in" each routine, as long as at most one is executed at each invocation of the subroutine.
  
-The second restriction is that the PROCEDURE instruction must be the first statement in the subroutine. This restriction was introduced between Rexx language level 3.50 and 4.00, but several level 4.00 interpreters may not enforce it, since there is no breakage when allowing it.+The second restriction is that the PROCEDURE instruction must be the first statement in the subroutine. This restriction was introduced between REXX language level 3.50 and 4.00, but several level 4.00 interpreters may not enforce it, since there is no breakage when allowing it.
  
 There are several important consequences of this second restriction: There are several important consequences of this second restriction:
Line 1411: Line 1411:
 Example: Global variables Example: Global variables
  
-A problem lurking on new Rexx users, is the fact that exposing a variable only exposes it to the calling routine. Therefore, it is incorrect to speak of global variables, since the variable might be local to the calling routine. To illustrate, consider the following code:+A problem lurking on new REXX users, is the fact that exposing a variable only exposes it to the calling routine. Therefore, it is incorrect to speak of global variables, since the variable might be local to the calling routine. To illustrate, consider the following code:
  
 <code rexx> <code rexx>
Line 1433: Line 1433:
 However, SUB2 calls SUB1, which exposes FOO, but that subroutine also writes out FOO. The reason for this is that EXPOSE works on the run-time nesting of routines, not on the typographical structure of the code. So the PROCEDURE in SUB1 (on its second invocation) exposes FOO to SUB2, not to the main program as typography might falsely indicate. However, SUB2 calls SUB1, which exposes FOO, but that subroutine also writes out FOO. The reason for this is that EXPOSE works on the run-time nesting of routines, not on the typographical structure of the code. So the PROCEDURE in SUB1 (on its second invocation) exposes FOO to SUB2, not to the main program as typography might falsely indicate.
  
-The often confusing consequence of the run-time binding of variable names is that an exposed variable of SUB1 can be bound to different global variables, depending on from where it was called. This differs from most compiled languages, which bind their variables independently of from where a subroutine is called. In turn, the consequence of this is that Rexx has severe problems storing a persistent, static variable which is needed by one subroutine only. A subroutine needing such a variable (e.g. a count variable which is incremented each time the subroutine is called), must either use an operating system command, or all subroutines calling that subroutine (and their calling routines, etc.) must expose the variable. The first of these solution is very inelegant and non-standard, while the second is at best troublesome and at worst seriously limits the maximum practical size of a Rexx program. There are hopes that the VALUE() built-in function will fix this in future standards of Rexx.+The often confusing consequence of the run-time binding of variable names is that an exposed variable of SUB1 can be bound to different global variables, depending on from where it was called. This differs from most compiled languages, which bind their variables independently of from where a subroutine is called. In turn, the consequence of this is that REXX has severe problems storing a persistent, static variable which is needed by one subroutine only. A subroutine needing such a variable (e.g. a count variable which is incremented each time the subroutine is called), must either use an operating system command, or all subroutines calling that subroutine (and their calling routines, etc.) must expose the variable. The first of these solution is very inelegant and non-standard, while the second is at best troublesome and at worst seriously limits the maximum practical size of a REXX program. There are hopes that the VALUE() built-in function will fix this in future standards of REXX.
  
 Another important drawback with PROCEDURE is that it only works for internal subroutines; for external subroutines it either do not work, or PROCEDURE may not even be allowed on the main level of the external subroutine. However, in internal subroutines inside the external subroutines, PROCEDURE is allowed, and works like usual. Another important drawback with PROCEDURE is that it only works for internal subroutines; for external subroutines it either do not work, or PROCEDURE may not even be allowed on the main level of the external subroutine. However, in internal subroutines inside the external subroutines, PROCEDURE is allowed, and works like usual.
Line 1512: Line 1512:
 When a routine is located at the very end of a source file, there is an implicit RETURN instruction after the last explicit clause. However, according to good programming practice, you should avoid taking advantage of this feature, because it can create problems later if you append new routines to the source file and forget to change the implied RETURN to an explicit one. When a routine is located at the very end of a source file, there is an implicit RETURN instruction after the last explicit clause. However, according to good programming practice, you should avoid taking advantage of this feature, because it can create problems later if you append new routines to the source file and forget to change the implied RETURN to an explicit one.
  
-If the current procedure level is the main level of either the program or an external subroutine, then a RETURN instruction is equivalent to an EXIT instruction, i.e. it will terminate the Rexx program or the external routine. The table in the Exit section shows the actions of both the RETURN and+If the current procedure level is the main level of either the program or an external subroutine, then a RETURN instruction is equivalent to an EXIT instruction, i.e. it will terminate the REXX program or the external routine. The table in the Exit section shows the actions of both the RETURN and
  
 EXIT instructions depending on the context in which they occur. EXIT instructions depending on the context in which they occur.
Line 1568: Line 1568:
  
  
-SELECT in Rexx is just a shorthand notation for nested IF instructions. Thus a SELECT instruction can always be written as set of nested IF statements; but for very large SELECT statements, the corresponding nested IF structure may be too deeply nested for the interpreter to handle.+SELECT in REXX is just a shorthand notation for nested IF instructions. Thus a SELECT instruction can always be written as set of nested IF statements; but for very large SELECT statements, the corresponding nested IF structure may be too deeply nested for the interpreter to handle.
  
 The following code shows how the SELECT statement shown above can be written as a nested IF structure: The following code shows how the SELECT statement shown above can be written as a nested IF structure:
Line 1596: Line 1596:
 The first form in the syntax definition transfers control to the named label, which must exist somewhere in the program; if it does not exist, a SYNTAX condition {16} is raised. If the label is multiple defined, the first definition is used. The parameter can be either a symbol (which is taken literally) or a string. If it is a string, then be sure that the case of the string matches the case of the label where it is defined. In practice, labels are in upper case, so the string should contain only uppercase letters too, and no space characters. The first form in the syntax definition transfers control to the named label, which must exist somewhere in the program; if it does not exist, a SYNTAX condition {16} is raised. If the label is multiple defined, the first definition is used. The parameter can be either a symbol (which is taken literally) or a string. If it is a string, then be sure that the case of the string matches the case of the label where it is defined. In practice, labels are in upper case, so the string should contain only uppercase letters too, and no space characters.
  
-The second form of the syntax is used if the second token of the instruction is VALUE. Then, the rest of the instruction is taken as a general Rexx expression, which result after evaluation is taken to be the name of the label to transfer control to. This form is really just a special case of the first form, where the programmer is allowed to specify the label as an expression. Note that if the start of expr is such that it can not be misinterpreted as the first form (i.e. the first token of expr is neither a string nor a symbol), then the VALUE subkeyword can be omitted.+The second form of the syntax is used if the second token of the instruction is VALUE. Then, the rest of the instruction is taken as a general REXX expression, which result after evaluation is taken to be the name of the label to transfer control to. This form is really just a special case of the first form, where the programmer is allowed to specify the label as an expression. Note that if the start of expr is such that it can not be misinterpreted as the first form (i.e. the first token of expr is neither a string nor a symbol), then the VALUE subkeyword can be omitted.
  
 Example: Transferring control to inside a loop Example: Transferring control to inside a loop
Line 1646: Line 1646:
 Example: Named condition traps in TRL1 Example: Named condition traps in TRL1
  
-A common problem when trying to port Rexx code from a TRL2 interpreter to a TRL1 interpreter, is that explicitly named condition traps are not supported. There exist ways to circumvent this, like:+A common problem when trying to port REXX code from a TRL2 interpreter to a TRL1 interpreter, is that explicitly named condition traps are not supported. There exist ways to circumvent this, like:
  
 <code rexx> <code rexx>
Line 1675: Line 1675:
 </code> </code>
  
-The TRACE instruction is used to set a tracing mode. Depending on the current mode, various levels of debugging information is displayed for the programmer. Also interactive tracing is allowed, where the user can re-execute clauses, change values of variables, or in general, execute Rexx code interactively between the statements of the Rexx script.+The TRACE instruction is used to set a tracing mode. Depending on the current mode, various levels of debugging information is displayed for the programmer. Also interactive tracing is allowed, where the user can re-execute clauses, change values of variables, or in general, execute REXX code interactively between the statements of the REXX script.
  
 If no parameters are specified, then the default value N is assumed. If no parameters are specified, then the default value N is assumed.
Line 1739: Line 1739:
 According to this figure, Intermediate is a superset of Result, which is a superset of All. Further, All is a superset of both Commands and Labels. Commands is a superset of Errors, which is a superset of Failures. Both Failure and Labels are supersets of Off. Actually, Command is strictly speaking not a superset of Errors, since Errors traces after the command, while Command traces before the command. According to this figure, Intermediate is a superset of Result, which is a superset of All. Further, All is a superset of both Commands and Labels. Commands is a superset of Errors, which is a superset of Failures. Both Failure and Labels are supersets of Off. Actually, Command is strictly speaking not a superset of Errors, since Errors traces after the command, while Command traces before the command.
  
-Scan is not part of this diagram, since it provides a completely different tracing functionality. Note that Scan is part of TRL1, but was removed in TRL2. It is not likely to be part of newer Rexx interpreters.+Scan is not part of this diagram, since it provides a completely different tracing functionality. Note that Scan is part of TRL1, but was removed in TRL2. It is not likely to be part of newer REXX interpreters.
  
 ==== The UPPER Instruction ==== ==== The UPPER Instruction ====
Line 1758: Line 1758:
 ===== Operators ‌ ===== ===== Operators ‌ =====
  
-An operator represents an operation to be carried out between two terms, such as division. There are 5 groups of operators in the Rexx Language: Arithmetic, Assignment, Comparative, Concatenation, and Logical Operators. The groups are shown below in descending order of precedence with further details for group. The defined precedence of operators can be overridden by the use of matching pairs of parentheses: ().+An operator represents an operation to be carried out between two terms, such as division. There are 5 groups of operators in the REXX Language: Arithmetic, Assignment, Comparative, Concatenation, and Logical Operators. The groups are shown below in descending order of precedence with further details for group. The defined precedence of operators can be overridden by the use of matching pairs of parentheses: ().
  
 ==== Arithmetic Operators ==== ==== Arithmetic Operators ====
  
  
-Arithmetic operators can be applied to numeric constants and Rexx variables that evaluate to valid Rexx numbers. The following operators are grouped in decreasing order of precedence:+Arithmetic operators can be applied to numeric constants and REXX variables that evaluate to valid REXX numbers. The following operators are grouped in decreasing order of precedence:
  
 %%-%% Unary prefix. Same as 0 – number. %%-%% Unary prefix. Same as 0 – number.
Line 1840: Line 1840:
 ==== Concatenation Operators ==== ==== Concatenation Operators ====
  
-The concatenation operators combine two strings to form one, by appending the second string to the right side of the first. The Rexx concatenation operators are:+The concatenation operators combine two strings to form one, by appending the second string to the right side of the first. The REXX concatenation operators are:
  
  
Line 1861: Line 1861:
 ==== Comparative Operators ==== ==== Comparative Operators ====
  
-The Rexx comparative operators compare two terms and return the logical value 1 if the result of the comparison is true, or 0 if the result of the comparison is false. The non-strict comparative operators will ignore leading or trailing blanks for string comparisons, and leading zeros for numeric comparisons. Numeric comparisons are made if both terms to be compared are valid Rexx numbers, otherwise string comparison is done. String comparisons are case sensitive, and the shorter of the two strings is padded with blanks.+The REXX comparative operators compare two terms and return the logical value 1 if the result of the comparison is true, or 0 if the result of the comparison is false. The non-strict comparative operators will ignore leading or trailing blanks for string comparisons, and leading zeros for numeric comparisons. Numeric comparisons are made if both terms to be compared are valid REXX numbers, otherwise string comparison is done. String comparisons are case sensitive, and the shorter of the two strings is padded with blanks.
  
 The following lists the non-strict comparative operators. The following lists the non-strict comparative operators.
Line 1918: Line 1918:
  
  
-Logical operators work with the Rexx strings 1 and 0, usually as a result of a comparative operator. These operators also only result in logical TRUE; 1 or logical FALSE; 0. The logical operators are shown in decreasing order of precedence.+Logical operators work with the REXX strings 1 and 0, usually as a result of a comparative operator. These operators also only result in logical TRUE; 1 or logical FALSE; 0. The logical operators are shown in decreasing order of precedence.
  
  
Line 1934: Line 1934:
 ===== Special Variables ===== ===== Special Variables =====
  
-The Rexx Language defines a number of special variables which are set by the interpreter during the execution of a program. There are two types of special variables. The first are special variables that are local in scope and can be changed by the programmer. The second are global in scope and cannot be changed by the programmer.+The REXX Language defines a number of special variables which are set by the interpreter during the execution of a program. There are two types of special variables. The first are special variables that are local in scope and can be changed by the programmer. The second are global in scope and cannot be changed by the programmer.
  
 ==== Local Scope – User Writeable ==== ==== Local Scope – User Writeable ====
Line 1981: Line 1981:
 === .LINE - (Regina) === === .LINE - (Regina) ===
  
-This special variable contains the line number of the Rexx program.+This special variable contains the line number of the REXX program.
  
 === .FILE - (Regina) === === .FILE - (Regina) ===
  
-This special variable contains the fully qualified file name of the Rexx program.+This special variable contains the fully qualified file name of the REXX program.
  
 === .ENDOFLINE - (Regina) === === .ENDOFLINE - (Regina) ===
Line 2012: Line 2012:
 Default return value Default return value
  
-From a Rexx program is 0 under most systems, specifically Unix, OS/2, MS-DOS. Here, VMS deviates, since it uses 1 as the default return value. Using 0 under VMS tends to make VMS issue a warning saying that no error occurred.+From a REXX program is 0 under most systems, specifically Unix, OS/2, MS-DOS. Here, VMS deviates, since it uses 1 as the default return value. Using 0 under VMS tends to make VMS issue a warning saying that no error occurred.
  
 Transferring control into a loop Transferring control into a loop
Line 2024: Line 2024:
 Last line of source code Last line of source code
  
-Is implicitly taken to be terminated by an end-of-line sequence in Regina, even if such a sequence is not present in the source code of the Rexx script. This applies only to source code. Also, the end-of-string in INTERPRET strings is taken to be implicitly terminated by an end-of-line character sequence.+Is implicitly taken to be terminated by an end-of-line sequence in Regina, even if such a sequence is not present in the source code of the REXX script. This applies only to source code. Also, the end-of-string in INTERPRET strings is taken to be implicitly terminated by an end-of-line character sequence.
  
 Moving code MS-DOS to Unix Moving code MS-DOS to Unix
Line 2037: Line 2037:
  
  
-Most people have problems invoking external programs. This section shows the basic rules, and some tricks to let you use Regina and other Rexx interpreters successfully.+Most people have problems invoking external programs. This section shows the basic rules, and some tricks to let you use Regina and other REXX interpreters successfully.
  
 Every call to an external program is executed by an implicit ADDRESS statement. Every call to an external program is executed by an implicit ADDRESS statement.
Line 2051: Line 2051:
 </code> </code>
  
-The default environment is SYSTEM in Regina and many other Rexx interpreters.+The default environment is SYSTEM in Regina and many other REXX interpreters.
  
 Every ADDRESS environment has its own purpose and advantages. It is a good idea to use ADDRESS in front of each command. Everybody knows what happens in this case. And you can choose the best environment for the command. Every ADDRESS environment has its own purpose and advantages. It is a good idea to use ADDRESS in front of each command. Everybody knows what happens in this case. And you can choose the best environment for the command.
Line 2079: Line 2079:
 REXX or REGINA REXX or REGINA
  
-Use this if you want to execute a Rexx program in a separate instance of the interpreter. Whereas a normal CALL on an external program will run the external Rexx program in the current instance of Regina, this allows the external Rexx program to run in a new, independent instance of Regina.+Use this if you want to execute a REXX program in a separate instance of the interpreter. Whereas a normal CALL on an external program will run the external REXX program in the current instance of Regina, this allows the external REXX program to run in a new, independent instance of Regina.
  
 Use this environment if: Use this environment if:
Line 2107: Line 2107:
 Those Systems with a 32 bit startup kernel known as Windows NT, Windows 2000, Windows XP will hide the console windows when starting a text mode program from a GUI program. Those Systems with a 32 bit startup kernel known as Windows NT, Windows 2000, Windows XP will hide the console windows when starting a text mode program from a GUI program.
  
-ATTENTION: Your programs might crash or you may loose control either of the called program or of Regina if you change the interpreter inside your Rexx program. Never use+ATTENTION: Your programs might crash or you may loose control either of the called program or of Regina if you change the interpreter inside your REXX program. Never use
  
 <code rexx> <code rexx>
Line 2116: Line 2116:
  
  
-====== Rexx Built-in Functions ======+====== REXX Built-in Functions ======
  
  
-This chapter describes the Rexx library of built-in functions. It is divided into three parts:+This chapter describes the REXX library of built-in functions. It is divided into three parts:
  
  
Line 2128: Line 2128:
  
  
-At the end, there is documentation that describes where and how Regina differs from standard Rexx, as described in the two other sections. It also lists Regina's extensions to the built-in library.+At the end, there is documentation that describes where and how Regina differs from standard REXX, as described in the two other sections. It also lists Regina's extensions to the built-in library.
  
  
Line 2143: Line 2143:
 In the description of the built-in functions, the syntax of each one is listed. For each of the syntax diagrams, the parts written in italic font names the parameters. Terms enclosed in [square brackets] denote optional elements. And the courier font is used to denote that something should be written as is, and it is also used to mark output from the computer. At the right of each function syntax is an indication of where the function is defined. In the description of the built-in functions, the syntax of each one is listed. For each of the syntax diagrams, the parts written in italic font names the parameters. Terms enclosed in [square brackets] denote optional elements. And the courier font is used to denote that something should be written as is, and it is also used to mark output from the computer. At the right of each function syntax is an indication of where the function is defined.
  
-  * (ANSI) ANSI Standard for Rexx 1996 +  * (ANSI) ANSI Standard for REXX 1996 
-  * (EXT-ANSI) Extended Rexx+  * (EXT-ANSI) Extended REXX
   * (SAA) System Application Architecture - IBM   * (SAA) System Application Architecture - IBM
-  * (OS/2) IBM OS/2 Rexx +  * (OS/2) IBM OS/2 REXX 
-  * (CMS) Rexx on CMS+  * (CMS) REXX on CMS
   * (AREXX) AREXX on Amiga   * (AREXX) AREXX on Amiga
   * (REGINA) Additional function provided by Regina   * (REGINA) Additional function provided by Regina
Line 2153: Line 2153:
 Definitions of the AREXX built-in functions were taken verbatim in 2003 from http://dfduck.homeip.net/dfd/ados/arexx/main.shtml Definitions of the AREXX built-in functions were taken verbatim in 2003 from http://dfduck.homeip.net/dfd/ados/arexx/main.shtml
  
-Note that in standard Rexx it is not really allowed to let the last possible parameter be empty if all commas are included, although some implementations allow it. In the following calls:+Note that in standard REXX it is not really allowed to let the last possible parameter be empty if all commas are included, although some implementations allow it. In the following calls:
  
 <code rexx> <code rexx>
Line 2173: Line 2173:
 In the descriptions of the built-in functions, several generic names are used for parameters, to indicate something about the type and use of that parameter, e.g. valid range. To avoid repeating the same information for the majority of the functions, some common "rules" for the standard parameter names are stated here. These rules implicitly apply for the rest of this chapter. In the descriptions of the built-in functions, several generic names are used for parameters, to indicate something about the type and use of that parameter, e.g. valid range. To avoid repeating the same information for the majority of the functions, some common "rules" for the standard parameter names are stated here. These rules implicitly apply for the rest of this chapter.
  
-Note that the following list does not try to classify any general Rexx "datatypes", but provides a binding between the sub-datatypes of strings and the methodology used when naming parameters.+Note that the following list does not try to classify any general REXX "datatypes", but provides a binding between the sub-datatypes of strings and the methodology used when naming parameters.
  
 Length is a non-negative whole number within the internal precision of the built-in functions. Whether it denotes a length in characters or in words, depends on the context. Length is a non-negative whole number within the internal precision of the built-in functions. Whether it denotes a length in characters or in words, depends on the context.
Line 2185: Line 2185:
 Padchar must be a string, exactly one character long. That character is used for padding. Padchar must be a string, exactly one character long. That character is used for padding.
  
-Streamid is a string that identifies a Rexx stream. The actual contents and format of such a string is implementation dependent.+Streamid is a string that identifies a REXX stream. The actual contents and format of such a string is implementation dependent.
  
-Number is any valid Rexx number, and will be normalized according to NUMERIC settings before it is used by the function.+Number is any valid REXX number, and will be normalized according to NUMERIC settings before it is used by the function.
  
 If you see one of these names having a number appended, that is only to separate several parameters of the same type, e.g. string1, string2 etc. They still follow the rules listed above. There are several parameters in the built-in functions that do not easily fall into the categories above. These are given other names, and their type and functionality will be described together with the functions in which they occur. If you see one of these names having a number appended, that is only to separate several parameters of the same type, e.g. string1, string2 etc. They still follow the rules listed above. There are several parameters in the built-in functions that do not easily fall into the categories above. These are given other names, and their type and functionality will be described together with the functions in which they occur.
Line 2193: Line 2193:
 ==== Error Messages ==== ==== Error Messages ====
  
-There are several errors that might occur in the built-in functions. Just one error message is only relevant for all the built-in functions, that is number 40 (Incorrect call to routine). In fact, an implementation of Rexx can choose to use that for any problem it encounters in the built-in functions. Regina also provides further information in errors in built-in functions, as defined by the ANSI standard. This additional information is provided as sub-error messages and usually provide a more detailed explanation of the error.+There are several errors that might occur in the built-in functions. Just one error message is only relevant for all the built-in functions, that is number 40 (Incorrect call to routine). In fact, an implementation of REXX can choose to use that for any problem it encounters in the built-in functions. Regina also provides further information in errors in built-in functions, as defined by the ANSI standard. This additional information is provided as sub-error messages and usually provide a more detailed explanation of the error.
  
 Depending on the implementation, other error messages might be used as well. Error message number 26 (Invalid whole number) might be used for any case where a parameter should have been a whole number, or where a whole number is out of range. It is implied that this error message can be used in these situations, and it is not explicitly mentioned in the description of the functions. Depending on the implementation, other error messages might be used as well. Error message number 26 (Invalid whole number) might be used for any case where a parameter should have been a whole number, or where a whole number is out of range. It is implied that this error message can be used in these situations, and it is not explicitly mentioned in the description of the functions.
  
-Other general error messages that might be used in the built-in functions are error number 41 (Bad arithmetic conversion) for any parameter that should have been a valid Rexx number. The error message 15 (Invalid binary or hexadecimal string) might occur in any of the conversion routines that converts from binary or hexadecimal format (B2X(), X2B(), X2C(), X2D()). And of course the more general error messages like error message 5 (Machine resources exhausted) can occur.+Other general error messages that might be used in the built-in functions are error number 41 (Bad arithmetic conversion) for any parameter that should have been a valid REXX number. The error message 15 (Invalid binary or hexadecimal string) might occur in any of the conversion routines that converts from binary or hexadecimal format (B2X(), X2B(), X2C(), X2D()). And of course the more general error messages like error message 5 (Machine resources exhausted) can occur.
  
 Generally, it is taken as granted that these error messages might occur for any relevant built-in function, and this will not be restated for each function. When other error messages than these are relevant, it will be mentioned in the text. Generally, it is taken as granted that these error messages might occur for any relevant built-in function, and this will not be restated for each function. When other error messages than these are relevant, it will be mentioned in the text.
  
-In Rexx, it is in general not an error to specify a start position that is larger than the length of the string, or a length that refers to parts of a string that is beyond the end of that string. The meaning of such instances will depend on the context, and are described for each function.+In REXX, it is in general not an error to specify a start position that is larger than the length of the string, or a length that refers to parts of a string that is beyond the end of that string. The meaning of such instances will depend on the context, and are described for each function.
  
 ==== Possible System Dependencies ==== ==== Possible System Dependencies ====
Line 2207: Line 2207:
 Some of the functions in the built-in library are more or less system or implementation dependent. The functionality of these may vary, so you should use defensive programming and be prepared for any side-effects that they might have. These functions include: Some of the functions in the built-in library are more or less system or implementation dependent. The functionality of these may vary, so you should use defensive programming and be prepared for any side-effects that they might have. These functions include:
  
-ADDRESS() is dependent on your operating system and the implementation of Rexx, since there is no standard for naming environments.+ADDRESS() is dependent on your operating system and the implementation of REXX, since there is no standard for naming environments.
  
 ARG() at the main level (not in subroutines and functions) is dependent on how your implementation handles and parses the parameters it got from the operating system. It is also dependent on whether the user specifies the -a command line switch. ARG() at the main level (not in subroutines and functions) is dependent on how your implementation handles and parses the parameters it got from the operating system. It is also dependent on whether the user specifies the -a command line switch.
Line 2219: Line 2219:
 CONDITION() is dependent on the condition system, which in turn depends on such implementation dependent things as file I/O and execution of commands. Although the general operation of this function will be fairly equal among systems, the details may differ. CONDITION() is dependent on the condition system, which in turn depends on such implementation dependent things as file I/O and execution of commands. Although the general operation of this function will be fairly equal among systems, the details may differ.
  
-DATATYPE() and TRANSLATE() know how to recognize upper and lower case letters, and how to transform letters to upper case. If your Rexx implementation supports national character sets, the operation of these two functions will depend on the language chosen.+DATATYPE() and TRANSLATE() know how to recognize upper and lower case letters, and how to transform letters to upper case. If your REXX implementation supports national character sets, the operation of these two functions will depend on the language chosen.
  
 DATE() has the options Month, Weekday and Normal, which produce the name of the day or month in text. Depending on how your implementation handles national character sets, the result from these functions might use the correct spelling of the currently chosen language. DATE() has the options Month, Weekday and Normal, which produce the name of the day or month in text. Depending on how your implementation handles national character sets, the result from these functions might use the correct spelling of the currently chosen language.
Line 2231: Line 2231:
 RANDOM() will differ from machine to machine, since the algorithm is implementation dependent. If you set the seed, you can safely assume that the same interpreter under the same operating system and on the same hardware platform will return a reproducible sequence. But if you change to another interpreter, another machine or even just another version of the operating system, the same seed might not give the same pseudo-random sequence. RANDOM() will differ from machine to machine, since the algorithm is implementation dependent. If you set the seed, you can safely assume that the same interpreter under the same operating system and on the same hardware platform will return a reproducible sequence. But if you change to another interpreter, another machine or even just another version of the operating system, the same seed might not give the same pseudo-random sequence.
  
-SOURCELINE() has been changed between Rexx language level 3.50 and 4.00. In 4.00 it can return 0 if the Rexx implementation finds it necessary, and any request for a particular line may get a nullstring as result. Before assuming that this function will return anything useful, consult the documentation.+SOURCELINE() has been changed between REXX language level 3.50 and 4.00. In 4.00 it can return 0 if the REXX implementation finds it necessary, and any request for a particular line may get a nullstring as result. Before assuming that this function will return anything useful, consult the documentation.
  
 TIME() will differ somewhat on different machines, since it is dependent on the underlying operating system to produce the timing information. In particular, the granularity and accuracy of this information may vary. TIME() will differ somewhat on different machines, since it is dependent on the underlying operating system to produce the timing information. In particular, the granularity and accuracy of this information may vary.
Line 2241: Line 2241:
 The built-in functions marked as AREXX are available by default on Amiga and AROS systems, but the AREXX_BIFS OPTION is required on other system to make these functions available. The built-in functions marked as AREXX are available by default on Amiga and AROS systems, but the AREXX_BIFS OPTION is required on other system to make these functions available.
  
-As you can see, even Rexx interpreters that are within the standard can differ quite a lot in the builtin functions. Although the points listed above seldom are any problem, you should never assume anything about them before you have read the implementation specific documentation. Failure to do so will give you surprises sooner or later.+As you can see, even REXX interpreters that are within the standard can differ quite a lot in the builtin functions. Although the points listed above seldom are any problem, you should never assume anything about them before you have read the implementation specific documentation. Failure to do so will give you surprises sooner or later.
  
 And, by the way, many implementations (probably the majority) do not follow the standard completely. So, in fact, you should never assume anything at all. Sorry ... And, by the way, many implementations (probably the majority) do not follow the standard completely. So, in fact, you should never assume anything at all. Sorry ...
Line 2271: Line 2271:
  
 ==== ABS(number) - (ANSI) ==== ==== ABS(number) - (ANSI) ====
- Returns the absolute value of the number , which can be any valid Rexx number. Note that the result will be normalized according to the current NUMERIC settings.+ Returns the absolute value of the number , which can be any valid REXX number. Note that the result will be normalized according to the current NUMERIC settings.
  
 | ABS(-42) | 42 | | ABS(-42) | 42 |
Line 2320: Line 2320:
 ==== ARG([argno [,option]]) - (ANSI) ==== ==== ARG([argno [,option]]) - (ANSI) ====
  
-Returns information about the arguments of the current procedure level. For subroutines and functions it will refer to the arguments with which they were called. For the "main" program it will refer to the arguments used when the Rexx interpreter was called.+Returns information about the arguments of the current procedure level. For subroutines and functions it will refer to the arguments with which they were called. For the "main" program it will refer to the arguments used when the REXX interpreter was called.
  
-Note that under some operating systems, Rexx scripts are run by starting the Rexx interpreter as a program, giving it the name of the script to be executed as parameter. Then the Rexx interpreter might process the command line and "eat" some or all of the arguments and options. Therefore, the result of this function at the main level is implementation dependent. The parts of the command line which are not available to the Rexx script might for instance be the options and arguments meaningful only to the interpreter itself.+Note that under some operating systems, REXX scripts are run by starting the REXX interpreter as a program, giving it the name of the script to be executed as parameter. Then the REXX interpreter might process the command line and "eat" some or all of the arguments and options. Therefore, the result of this function at the main level is implementation dependent. The parts of the command line which are not available to the REXX script might for instance be the options and arguments meaningful only to the interpreter itself.
  
 Also note that how the interpreter on the main level divides the parameter line into individual arguments, is implementation dependent. The standard seems to define that the main procedure level can only get one parameter string, but don't count on it. On all platforms, Regina will receive one parameter string at the main procedural level, unless Regina is started with the -a switch, when multiple parameter strings are passed in. Also note that how the interpreter on the main level divides the parameter line into individual arguments, is implementation dependent. The standard seems to define that the main procedure level can only get one parameter string, but don't count on it. On all platforms, Regina will receive one parameter string at the main procedural level, unless Regina is started with the -a switch, when multiple parameter strings are passed in.
  
-For more information on how the interpreter processes arguments when called from the operating system, see the documentation on how to run a Rexx script.+For more information on how the interpreter processes arguments when called from the operating system, see the documentation on how to run a REXX script.
  
-When called without any parameters, ARG() will return the number of comma-delimited arguments. Unspecified (omitted) arguments at the end of the call are not counted. Note the difference between using comma and using space to separate strings. Only comma-separated arguments will be interpreted by Rexx as different arguments. Space-separated strings are interpreted as different parts of the same argument.+When called without any parameters, ARG() will return the number of comma-delimited arguments. Unspecified (omitted) arguments at the end of the call are not counted. Note the difference between using comma and using space to separate strings. Only comma-separated arguments will be interpreted by REXX as different arguments. Space-separated strings are interpreted as different parts of the same argument.
  
 Argno must be a positive whole number. If only argno is specified, the argument specified will be returned. The first argument is numbered 1. If argno refers to an unspecified argument (either omitted or argno is greater than the number of arguments), a nullstring is returned. Argno must be a positive whole number. If only argno is specified, the argument specified will be returned. The first argument is numbered 1. If argno refers to an unspecified argument (either omitted or argno is greater than the number of arguments), a nullstring is returned.
Line 2581: Line 2581:
 Note that this function reads the stream raw. Some operating systems use special characters to differentiate between separate lines in text files. On these systems these special characters will be returned as well. Therefore, never assume that this function will behave identically for text streams on different systems. Note that this function reads the stream raw. Some operating systems use special characters to differentiate between separate lines in text files. On these systems these special characters will be returned as well. Therefore, never assume that this function will behave identically for text streams on different systems.
  
-What happens when an error occurs or the End-Of-File (EOF) is seen during reading, is implementation dependent. The implementation may choose to set the NOTREADY condition (does not exist in Rexx language level 3.50). For more information, see chapter on Stream Input and Output.+What happens when an error occurs or the End-Of-File (EOF) is seen during reading, is implementation dependent. The implementation may choose to set the NOTREADY condition (does not exist in REXX language level 3.50). For more information, see chapter on Stream Input and Output.
  
 (Assuming that the file "/tmp/file" contains the first line: "This is the first line"): (Assuming that the file "/tmp/file" contains the first line: "This is the first line"):
Line 2600: Line 2600:
 If string is omitted, nothing is written, and the effect is to set the current write position if start is specified. If neither string nor start is specified, the implementation can really do whatever it likes, and many implementations use this operation to close the file, or flush any changes. Check implementation specific documentation for more information. If string is omitted, nothing is written, and the effect is to set the current write position if start is specified. If neither string nor start is specified, the implementation can really do whatever it likes, and many implementations use this operation to close the file, or flush any changes. Check implementation specific documentation for more information.
  
-The return value is the number of characters in string that was not successfully written, so 0 denotes a successful write. Note that in many Rexx implementations there is no need to open a stream; it will be implicitly opened when it is first used in a read or write operation.+The return value is the number of characters in string that was not successfully written, so 0 denotes a successful write. Note that in many REXX implementations there is no need to open a stream; it will be implicitly opened when it is first used in a read or write operation.
  
 (Assuming the file referred to by outdata was empty, it will contain the string FoobWow afterwards. Note that there might will not be an End-Of-Line marker after this string, it depends on the implementation.) (Assuming the file referred to by outdata was empty, it will contain the string FoobWow afterwards. Note that there might will not be an End-Of-Line marker after this string, it depends on the implementation.)
Line 2709: Line 2709:
 ==== DATATYPE(string [,option]) - (ANSI) ==== ==== DATATYPE(string [,option]) - (ANSI) ====
  
-With only one parameter, this function identifies the "datatype" of string . The value returned will be " NUM " if string is a valid Rexx number. Otherwise, " CHAR " is returned. Note that the interpretation of whether string is a valid number will depend on the current NUMERIC settings.+With only one parameter, this function identifies the "datatype" of string . The value returned will be " NUM " if string is a valid REXX number. Otherwise, " CHAR " is returned. Note that the interpretation of whether string is a valid number will depend on the current NUMERIC settings.
  
 If option is specified too, it will check if string is of a particular datatype, and return either "1" or "0" depending on whether string is or is not, respectively, of the specified datatype. The possible values of option are: If option is specified too, it will check if string is of a particular datatype, and return either "1" or "0" depending on whether string is or is not, respectively, of the specified datatype. The possible values of option are:
Line 2731: Line 2731:
 [N] [N]
  
-(Numeric) If string is a valid Rexx number, i.e. DATATYPE( string ) would return NUM.+(Numeric) If string is a valid REXX number, i.e. DATATYPE( string ) would return NUM.
  
 [S] [S]
  
-(Symbolic) Consists of characters that are legal in Rexx symbols. Note that this test will pass several strings that are not legal symbols. The characters includes plus, minus and the decimal point.+(Symbolic) Consists of characters that are legal in REXX symbols. Note that this test will pass several strings that are not legal symbols. The characters includes plus, minus and the decimal point.
  
 [U] [U]
Line 2743: Line 2743:
 [W] [W]
  
-(Whole) If string is a valid Rexx whole number under the current NUMERIC setting. Note that 13.0 is a whole number since the decimal part is zero.+(Whole) If string is a valid REXX whole number under the current NUMERIC setting. Note that 13.0 is a whole number since the decimal part is zero.
  
 [X] [X]
Line 2826: Line 2826:
 (time_t) Returns the current UTC date/time in UNIX time_t format. time_t is the number of seconds since January 1st 1970. It always represents the UTC date/time, so any conversion from another date format (which is always assumed to be local time) will result in a time_t value offset by time zone. (Regina Extension) (time_t) Returns the current UTC date/time in UNIX time_t format. time_t is the number of seconds since January 1st 1970. It always represents the UTC date/time, so any conversion from another date format (which is always assumed to be local time) will result in a time_t value offset by time zone. (Regina Extension)
  
-Note that the "C" option is present in Rexx language level 3.50, but was removed in level 4.00. The new "B" option should be used instead. When porting code that use the "C" option to an interpreter that only have the "B" option, you will can use the conversion that January 1st 1900 is day 693595 in the Gregorian calendar.+Note that the "C" option is present in REXX language level 3.50, but was removed in level 4.00. The new "B" option should be used instead. When porting code that use the "C" option to an interpreter that only have the "B" option, you will can use the conversion that January 1st 1900 is day 693595 in the Gregorian calendar.
  
-Note that none of the formats in which DATE() returns its result are affected by the NUMERIC settings. Also note that if there is more than one call to DATE() (or TIME()) in a single clause of Rexx code, all of them will use the same basis data for calculating the date (or time).+Note that none of the formats in which DATE() returns its result are affected by the NUMERIC settings. Also note that if there is more than one call to DATE() (or TIME()) in a single clause of REXX code, all of them will use the same basis data for calculating the date (or time).
  
-If the Rexx interpreter contains national support, some of these options may return different output for the names of months and weekdays.+If the REXX interpreter contains national support, some of these options may return different output for the names of months and weekdays.
  
 Assuming that today is January 6th 1992: Assuming that today is January 6th 1992:
Line 2878: Line 2878:
 | DATE('S','13-02-96',E','-','-') | 1996-02-13 | | DATE('S','13-02-96',E','-','-') | 1996-02-13 |
  
-The sep_out and sep_in options are extensions to the ANSI standard originally provided by Object Rexx.+The sep_out and sep_in options are extensions to the ANSI standard originally provided by Object REXX.
  
  
Line 2980: Line 2980:
 ==== ERRORTEXT(errorno [, lang]) - (ANSI) ==== ==== ERRORTEXT(errorno [, lang]) - (ANSI) ====
  
-Returns the Rexx error message associated with error number errorno . If the lang character is specified, it will determine the native language in which the error message is returned. The default value for lang is " N ".+Returns the REXX error message associated with error number errorno . If the lang character is specified, it will determine the native language in which the error message is returned. The default value for lang is " N ".
  
 Possible options are: Possible options are:
Line 3011: Line 3011:
 | ERRORTEXT(40.24,'S') | <bif> argument 1 must be a binary string; found "<value>" | | ERRORTEXT(40.24,'S') | <bif> argument 1 must be a binary string; found "<value>" |
  
-The error messages in Rexx might be slightly different between the various implementations. The ANSI standard says that errno must be in the range 0-90, but in some implementations it might be within a less restricted range which gives room for system specific messages. You should in general not assume that the wordings and ordering of the error messages are constant between implementations and systems.+The error messages in REXX might be slightly different between the various implementations. The ANSI standard says that errno must be in the range 0-90, but in some implementations it might be within a less restricted range which gives room for system specific messages. You should in general not assume that the wordings and ordering of the error messages are constant between implementations and systems.
  
 With OPTIONS STRICT_ANSI, Regina will return an error if errorno is larger than 90: With OPTIONS STRICT_ANSI, Regina will return an error if errorno is larger than 90:
Line 3094: Line 3094:
 ==== FORMAT(number [,[before] [,[after] [,[expp] [,[expt]]]]]) - (ANSI) ==== ==== FORMAT(number [,[before] [,[after] [,[expp] [,[expt]]]]]) - (ANSI) ====
  
-This function is used to control the format of numbers, and you may request the size and format in which the number is written. The parameter number is the number to be formatted, and it must be a valid Rexx number. note that before any conversion or formatting is done, this number will be normalized according to the current NUMERIC settings.+This function is used to control the format of numbers, and you may request the size and format in which the number is written. The parameter number is the number to be formatted, and it must be a valid REXX number. note that before any conversion or formatting is done, this number will be normalized according to the current NUMERIC settings.
  
 The before and after parameters determines how many characters that are used before and after the decimal point, respectively. Note that before does not specify the number of digits in the integer part, it specifies the size of the field in which the integer part of the number is written. Remember to allocate space in this field for a minus too, if that is relevant. If the field is not long enough to hold the integer part (including a minus if relevant), an error is reported. The before and after parameters determines how many characters that are used before and after the decimal point, respectively. Note that before does not specify the number of digits in the integer part, it specifies the size of the field in which the integer part of the number is written. Remember to allocate space in this field for a minus too, if that is relevant. If the field is not long enough to hold the integer part (including a minus if relevant), an error is reported.
Line 3141: Line 3141:
  
  
-Returns the fully qualified file name of the Rexx program that called the current program. The optional argument level specifies the level in Regina's call stack you wish to query. The immediate level is 1, the level above that is 2, etc. If not specified level is 1. Where level exceeds Regina's call stack this function returns the empty string.+Returns the fully qualified file name of the REXX program that called the current program. The optional argument level specifies the level in Regina's call stack you wish to query. The immediate level is 1, the level above that is 2, etc. If not specified level is 1. Where level exceeds Regina's call stack this function returns the empty string.
  
 | GETCALLER() | 'C:\regina\fred1.rexx' /* (Maybe) */ | | GETCALLER() | 'C:\regina\fred1.rexx' /* (Maybe) */ |
Line 3179: Line 3179:
 ==== GETSPACE(length) - (AREXX) ==== ==== GETSPACE(length) - (AREXX) ====
  
-Allocates a block of memory of the specified length from the interpreter's internal pool. The returned value is the 4-byte address of the allocated block, which is not cleared or otherwise initialized. Internal memory is automatically returned to the system when the Rexx program terminates,so this function should not be used to allocate memory for use by external programs. See also FREESPACE()+Allocates a block of memory of the specified length from the interpreter's internal pool. The returned value is the 4-byte address of the allocated block, which is not cleared or otherwise initialized. Internal memory is automatically returned to the system when the REXX program terminates,so this function should not be used to allocate memory for use by external programs. See also FREESPACE()
  
 | GETSPACE(32) | '0003BF40' /* maybe */ | | GETSPACE(32) | '0003BF40' /* maybe */ |
Line 3288: Line 3288:
 Count specifies the number of lines to read. However, it can only take the values 0 and 1. When it is 1 (which is the default), it will read one line. When it is 0 it will not read any lines, and a nullstring is returned. This has the effect of setting the current read position of the file if line was specified. Count specifies the number of lines to read. However, it can only take the values 0 and 1. When it is 1 (which is the default), it will read one line. When it is 0 it will not read any lines, and a nullstring is returned. This has the effect of setting the current read position of the file if line was specified.
  
-What happens when the functions finds a End-Of-File (EOF) condition is to some extent implementation dependent. The implementation may interpret the EOF as an implicit End-Of-Line (EOL) mark is none such was explicitly present. The implementation may also choose to raise the NOTREADY condition flag (this condition is new from Rexx language level 4.00).+What happens when the functions finds a End-Of-File (EOF) condition is to some extent implementation dependent. The implementation may interpret the EOF as an implicit End-Of-Line (EOL) mark is none such was explicitly present. The implementation may also choose to raise the NOTREADY condition flag (this condition is new from REXX language level 4.00).
  
 Whether or not stream must be explicitly opened before a read operation can be performed, is implementation dependent. In many implementations, a read or write operation will implicitly open the stream if not already open. Whether or not stream must be explicitly opened before a read operation can be performed, is implementation dependent. In many implementations, a read or write operation will implicitly open the stream if not already open.
Line 3379: Line 3379:
 ==== MAX(number1 [,number2] ...) - (ANSI) ==== ==== MAX(number1 [,number2] ...) - (ANSI) ====
  
-Takes any positive number of parameters, and will return the parameter that had the highest numerical value. The parameters may be any valid Rexx number. The number that is returned, is normalized according to the current NUMERIC settings, so the result need not be strictly equal to any of the parameters.+Takes any positive number of parameters, and will return the parameter that had the highest numerical value. The parameters may be any valid REXX number. The number that is returned, is normalized according to the current NUMERIC settings, so the result need not be strictly equal to any of the parameters.
  
 Actually, the standard says that the value returned is the first number in the parameter list which is equal to the result of adding a positive number or zero to any of the other parameters. Note that this definition opens for "strange" results if you are brave enough to play around with the settings of NUMERIC FUZZ. Actually, the standard says that the value returned is the first number in the parameter list which is equal to the result of adding a positive number or zero to any of the other parameters. Note that this definition opens for "strange" results if you are brave enough to play around with the settings of NUMERIC FUZZ.
Line 3439: Line 3439:
 ==== POPEN(command [,stem.]) - (REGINA) ==== ==== POPEN(command [,stem.]) - (REGINA) ====
  
-Runs the operating system command. If the optional stem. is supplied all output from the command is placed in the specified stem variable as a Rexx array. Note that only the command's stdout can be captured.+Runs the operating system command. If the optional stem. is supplied all output from the command is placed in the specified stem variable as a REXX array. Note that only the command's stdout can be captured.
  
 This command is now deprecated. ADDRESS WITH can do the same thing, and can also capture the command's stderr. This command is now deprecated. ADDRESS WITH can do the same thing, and can also capture the command's stderr.
Line 3479: Line 3479:
 ==== QUEUED() - (ANSI) ‌ ==== ==== QUEUED() - (ANSI) ‌ ====
  
-Returns the number of lines currently in the external data queue (the "stack"). Note that the stack is a concept external to Rexx, this function may depend on the implementation and system Consult the system specific documentation for more information.+Returns the number of lines currently in the external data queue (the "stack"). Note that the stack is a concept external to REXX, this function may depend on the implementation and system Consult the system specific documentation for more information.
  
 | QUEUED() | '0' /* Maybe */ | | QUEUED() | '0' /* Maybe */ |
Line 3498: Line 3498:
 The standard does not require that a specific method is to be used for generating the pseudo-random numbers, so the reproducibility can only be guaranteed as long as you use the same implementation on the same machine, using the same operating system. If any of these change, a given seed may produce a different sequence of pseudo-random numbers. The standard does not require that a specific method is to be used for generating the pseudo-random numbers, so the reproducibility can only be guaranteed as long as you use the same implementation on the same machine, using the same operating system. If any of these change, a given seed may produce a different sequence of pseudo-random numbers.
  
-Note that depending on the implementation, some numbers might have a slightly increased chance of turning up than other. If the Rexx implementation uses a 32 bit pseudo-random generator provided by the operating system and returns the remainder after integer dividing it by the difference of min and max, low numbers are favored if the 2^32 is not a multiple of that difference. Supposing that the call is RANDOM(100000) and the pseudo-random generator generates any 32 bit number with equal chance, the change of getting a number in the range 0-67296 is about 0.000010000076, while the changes of getting a number in the range 67297-100000 is about 0.000009999843.+Note that depending on the implementation, some numbers might have a slightly increased chance of turning up than other. If the REXX implementation uses a 32 bit pseudo-random generator provided by the operating system and returns the remainder after integer dividing it by the difference of min and max, low numbers are favored if the 2^32 is not a multiple of that difference. Supposing that the call is RANDOM(100000) and the pseudo-random generator generates any 32 bit number with equal chance, the change of getting a number in the range 0-67296 is about 0.000010000076, while the changes of getting a number in the range 67297-100000 is about 0.000009999843.
  
 A much worse problem with pseudo-random numbers are that they sometimes do not tend to be random at all. Under one operating system (name withheld to protect the guilty), the system's pseudo-random routine returned numbers where the last binary digit alternated between 0 and 1. On that machine, RANDOM(1) would return the series 0, 1, 0, 1, 0, 1, 0, 1 etc., which is hardly random at all. You should therefore never trust the pseudo-random routine to give you random numbers. A much worse problem with pseudo-random numbers are that they sometimes do not tend to be random at all. Under one operating system (name withheld to protect the guilty), the system's pseudo-random routine returned numbers where the last binary digit alternated between 0 and 1. On that machine, RANDOM(1) would return the series 0, 1, 0, 1, 0, 1, 0, 1 etc., which is hardly random at all. You should therefore never trust the pseudo-random routine to give you random numbers.
Line 3562: Line 3562:
 ==== RXFUNCADD(externalname, library, internalname) - (SAA) ==== ==== RXFUNCADD(externalname, library, internalname) - (SAA) ====
  
-Registers the internalname in library as an external function callable from with the current program by referencing externalname. library is a Rexx external function package in the format of shared library or dynamic link library (DLL). library and internalname are case-sensitive. library is the base name of the shared library or dynamic link library. On platforms that support DLLs, the full name of the external function package is library.dll. On Unix environments, the full name of the shared library is lib library.a (AIX), lib library.sl (HPUX) or lib library.so (most other Unixes).+Registers the internalname in library as an external function callable from with the current program by referencing externalname. library is a REXX external function package in the format of shared library or dynamic link library (DLL). library and internalname are case-sensitive. library is the base name of the shared library or dynamic link library. On platforms that support DLLs, the full name of the external function package is library.dll. On Unix environments, the full name of the shared library is lib library.a (AIX), lib library.sl (HPUX) or lib library.so (most other Unixes).
  
 External function packages are searched for in the location where shared libraries or DLLs are normally found by the operating system. DLLs are normally located in directories specified in the PATH or LIBPATH environment variables. Shared libraries are normally searched for in LD_LIBRARY_PATH or LIBPATH environment variables. External function packages are searched for in the location where shared libraries or DLLs are normally found by the operating system. DLLs are normally located in directories specified in the PATH or LIBPATH environment variables. Shared libraries are normally searched for in LD_LIBRARY_PATH or LIBPATH environment variables.
Line 3658: Line 3658:
 ==== SIGN(number) - (ANSI) ==== ==== SIGN(number) - (ANSI) ====
  
-Returns either -1 , 0 or 1 , depending on whether number is negative, zero, or positive, respectively. Number must be a valid Rexx number, and are normalized according to the current settings of NUMERIC before comparison.+Returns either -1 , 0 or 1 , depending on whether number is negative, zero, or positive, respectively. Number must be a valid REXX number, and are normalized according to the current settings of NUMERIC before comparison.
  
 | SIGN(-12) | '-1' | | SIGN(-12) | '-1' |
Line 3676: Line 3676:
 ==== SOURCELINE([lineno]) - (ANSI) ==== ==== SOURCELINE([lineno]) - (ANSI) ====
  
-If lineno (which must be a positive whole number) is specified, this function will return a string containing a copy of the Rexx script source code on that line. If lineno is greater than the number of lines in the Rexx script source code, an error is reported.+If lineno (which must be a positive whole number) is specified, this function will return a string containing a copy of the REXX script source code on that line. If lineno is greater than the number of lines in the REXX script source code, an error is reported.
  
-If lineno is unspecified, the number of lines in the Rexx script source code is returned.+If lineno is unspecified, the number of lines in the REXX script source code is returned.
  
-Note that from Rexx language level 3.50 to 4.00, the requirements of this function were relaxed to simplify execution when the source code is not available (compiled or pre-parsed Rexx). An implementation might make two simplifications: to return 0 if called without a parameter. If so, any call to SOURCELINE() with a parameter will generate an error. The other simplification is to return a nullstring for any call to SOURCELINE() with a legal parameter.+Note that from REXX language level 3.50 to 4.00, the requirements of this function were relaxed to simplify execution when the source code is not available (compiled or pre-parsed REXX). An implementation might make two simplifications: to return 0 if called without a parameter. If so, any call to SOURCELINE() with a parameter will generate an error. The other simplification is to return a nullstring for any call to SOURCELINE() with a legal parameter.
  
 Note that the code executed by the INTERPRET clause can not be retrieved by SOURCELINE(). Note that the code executed by the INTERPRET clause can not be retrieved by SOURCELINE().
  
 | SOURCELINE() | '42' /*Maybe */ | | SOURCELINE() | '42' /*Maybe */ |
-| SOURCELINE(1) | '/* This Rexx script will ... */' |+| SOURCELINE(1) | '/* This REXX script will ... */' |
 | SOURCELINE(23) | 'var = 12' /*Maybe */' | | SOURCELINE(23) | 'var = 12' /*Maybe */' |
  
Line 3720: Line 3720:
 ==== STREAM(streamid[,option[,command]]) (ANSI) ==== ==== STREAM(streamid[,option[,command]]) (ANSI) ====
  
-This function was added to Rexx in language level 4.00. It provides a general mechanism for doing operations on streams. However, very little is specified about how the internal of this function should work, so you should consult the implementation specific documentation for more information.+This function was added to REXX in language level 4.00. It provides a general mechanism for doing operations on streams. However, very little is specified about how the internal of this function should work, so you should consult the implementation specific documentation for more information.
  
 The streamid identifies a stream. The actual contents and format of this string is implementation dependent. The streamid identifies a stream. The actual contents and format of this string is implementation dependent.
Line 3826: Line 3826:
 DATETIME returns the date and time of last modification of the stream in DATETIME returns the date and time of last modification of the stream in
  
-Rexx US Date format; MM-DD-YY HH:MM:SS.+REXX US Date format; MM-DD-YY HH:MM:SS.
  
 EXISTS returns the fully-qualified file name of the specified stream. EXISTS returns the fully-qualified file name of the specified stream.
Line 4194: Line 4194:
 ==== VALUE(symbol [,[value], [pool]]) - (ANSI) ==== ==== VALUE(symbol [,[value], [pool]]) - (ANSI) ====
  
-This function expects as first parameter string symbol , which names an existing variable. The result returned from the function is the value of that variable. If symbol does not name an existing variable, the default value is returned, and the NOVALUE condition is not raised. If symbol is not a valid symbol name, and this function is used to access an normal Rexx variable, an error occurs. Be aware of the "double-expansion" effect, and quote the first parameter if necessary.+This function expects as first parameter string symbol , which names an existing variable. The result returned from the function is the value of that variable. If symbol does not name an existing variable, the default value is returned, and the NOVALUE condition is not raised. If symbol is not a valid symbol name, and this function is used to access an normal REXX variable, an error occurs. Be aware of the "double-expansion" effect, and quote the first parameter if necessary.
  
 If the optional second parameter is specified, the variable will be set to that value, after the old value has been extracted. If the optional second parameter is specified, the variable will be set to that value, after the old value has been extracted.
  
-The optional parameter pool might be specified to select a particular pool of variables to search for symbol. The contents and format of pool is implementation dependent. The default is to search in the variables at the current procedural level in Rexx. Which pools that are available is implementation dependent, but typically one can set variables in application programs or in the operating system.+The optional parameter pool might be specified to select a particular pool of variables to search for symbol. The contents and format of pool is implementation dependent. The default is to search in the variables at the current procedural level in REXX. Which pools that are available is implementation dependent, but typically one can set variables in application programs or in the operating system.
  
-Note that if VALUE() is used to access variables in pools outside the Rexx interpreter, the requirements to format (a valid symbol) will not in general hold. There may be other requirements instead, depending on the implementation and the system. Depending on the validity of the name, the value, or whether the variable can be set or read, the VALUE() function can give error messages when accessing variables in pools other than the normal. Consult the implementation and system specific documentation for more information.+Note that if VALUE() is used to access variables in pools outside the REXX interpreter, the requirements to format (a valid symbol) will not in general hold. There may be other requirements instead, depending on the implementation and the system. Depending on the validity of the name, the value, or whether the variable can be set or read, the VALUE() function can give error messages when accessing variables in pools other than the normal. Consult the implementation and system specific documentation for more information.
  
-If it is used to access compound variables inside the interpreter the tail part of this function can take any expression, even expression that are not normally legal in Rexx scripts source code.+If it is used to access compound variables inside the interpreter the tail part of this function can take any expression, even expression that are not normally legal in REXX scripts source code.
  
 The valid value of pool in Regina is one of ENVIRONMENT, SYSTEM, OS2ENVIRONMENT, or CALLER; the latter refering to the most immediate, higher level poo, and the 3 former referring to the external environment. pool can also be a number representing the call level to search, with the first level being 1. It is therefore possible to get and set the value of a variable in a higher call level procedure from the current one without the need to EXPOSE the variable. This and the POOLID() BIF which returns the current call level are Regina extensions. The valid value of pool in Regina is one of ENVIRONMENT, SYSTEM, OS2ENVIRONMENT, or CALLER; the latter refering to the most immediate, higher level poo, and the 3 former referring to the external environment. pool can also be a number representing the call level to search, with the first level being 1. It is therefore possible to get and set the value of a variable in a higher call level procedure from the current one without the need to EXPOSE the variable. This and the POOLID() BIF which returns the current call level are Regina extensions.
Line 4409: Line 4409:
 ==== DUMPTREE() ==== ==== DUMPTREE() ====
  
-Prints out the internal parse tree for the Rexx program currently being executed. This output is not very interesting unless you have good knowledge of the interpreter's internal structures.+Prints out the internal parse tree for the REXX program currently being executed. This output is not very interesting unless you have good knowledge of the interpreter's internal structures.
  
  
Line 4436: Line 4436:
 Prints out a traceback. This is the same routine which is called when the interpreter encounters an error. Nice for debugging, but not really useful for any other purposes. Prints out a traceback. This is the same routine which is called when the interpreter encounters an error. Nice for debugging, but not really useful for any other purposes.
  
-===== Rexx VMS Interface Functions =====+===== REXX VMS Interface Functions =====
  
 F$CVSI F$CVTIME F$CVUI F$DIRECTORY F$ELEMENT F$EXTRACT F$FAO F$FILE_ATTRIBUTES F$GETDVI F$GETJPI F$GETQUI F$GETSYI F$IDENTIFIER F$INTEGER F$LENGTH F$LOCATE F$LOGICAL F$MESSAGE F$MODE F$PARSE F$PID F$PRIVILEGE F$PROCESS F$SEARCH F$SETPRV F$STRING F$TIME F$TRNLNM F$TYPE F$USER F$CVSI F$CVTIME F$CVUI F$DIRECTORY F$ELEMENT F$EXTRACT F$FAO F$FILE_ATTRIBUTES F$GETDVI F$GETJPI F$GETQUI F$GETSYI F$IDENTIFIER F$INTEGER F$LENGTH F$LOCATE F$LOGICAL F$MESSAGE F$MODE F$PARSE F$PID F$PRIVILEGE F$PROCESS F$SEARCH F$SETPRV F$STRING F$TIME F$TRNLNM F$TYPE F$USER
Line 4446: Line 4446:
 ====== Conditions ====== ====== Conditions ======
  
-In this chapter, the Rexx concept of "conditions" is described. Conditions allow the programmer to handle abnormal control flow, and enable him to assign special pieces of Rexx code to be executed in case of certain incidences.+In this chapter, the REXX concept of "conditions" is described. Conditions allow the programmer to handle abnormal control flow, and enable him to assign special pieces of REXX code to be executed in case of certain incidences.
  
 In the first section the concept of conditions is explained. In the first section the concept of conditions is explained.
  
-Then, there is a description of how a standard condition in Rexx would work, if it existed.+Then, there is a description of how a standard condition in REXX would work, if it existed.
  
-In the third section, all the existing conditions in Rexx are presented, and the differences compared to the standard condition described in the previous section are listed.+In the third section, all the existing conditions in REXX are presented, and the differences compared to the standard condition described in the previous section are listed.
  
-The fourth sections contains a collections of random notes on the conditions in Rexx.+The fourth sections contains a collections of random notes on the conditions in REXX.
  
  
Line 4480: Line 4480:
 [Condition:] [Condition:]
  
-Names the Rexx concept that is equivalent to the incident.+Names the REXX concept that is equivalent to the incident.
  
 [Raise a Condition:] [Raise a Condition:]
Line 4500: Line 4500:
 [(Condition) Handler:] [(Condition) Handler:]
  
-Part of the condition trap, which points to a piece of Rexx code which is to be used to handle the condition.+Part of the condition trap, which points to a piece of REXX code which is to be used to handle the condition.
  
 [(Trap) Method:] [(Trap) Method:]
Line 4531: Line 4531:
 ===== The Mythical Standard Condition ===== ===== The Mythical Standard Condition =====
  
-Rexx Language Level 4.00 has six different conditions, and Rexx Language Level 5.00 has seven. However, each of these is a special case of a mythical, non-existing, standard condition. In order to better understand the real conditions, we start by explaining how a standard condition work.+REXX Language Level 4.00 has six different conditions, and REXX Language Level 5.00 has seven. However, each of these is a special case of a mythical, non-existing, standard condition. In order to better understand the real conditions, we start by explaining how a standard condition work.
  
-In the examples below, we will call our non-existing standard condition MYTH. Note that these examples will not be executable on any Rexx implementation.+In the examples below, we will call our non-existing standard condition MYTH. Note that these examples will not be executable on any REXX implementation.
  
 ==== Information Regarding Conditions (data structures) ==== ==== Information Regarding Conditions (data structures) ====
Line 4543: Line 4543:
 There is one interpreter-wide queue of pending conditions. Raising a condition is identical to adding information about the condition to this queue (FIFO). The order of the queue is the same order in which the conditions are to be handled. There is one interpreter-wide queue of pending conditions. Raising a condition is identical to adding information about the condition to this queue (FIFO). The order of the queue is the same order in which the conditions are to be handled.
  
-Every entry in the queue of pending conditions contains some information about the event: the line number of the Rexx script when the condition was raised, a descriptive text and the condition type.+Every entry in the queue of pending conditions contains some information about the event: the line number of the REXX script when the condition was raised, a descriptive text and the condition type.
  
 [Default-Action.] [Default-Action.]
Line 4557: Line 4557:
 For each condition there is a trap which contains three pieces of status information: the state; the handler; and the method. The state can be ON, OFF or DELAY. For each condition there is a trap which contains three pieces of status information: the state; the handler; and the method. The state can be ON, OFF or DELAY.
  
-The handler names the Rexx label in the start of the Rexx code to handle the event. The method can be either SIGNAL or CALL, and denotes the method in which the condition is to be handled. If the state is OFF, then neither handler nor method is defined.+The handler names the REXX label in the start of the REXX code to handle the event. The method can be either SIGNAL or CALL, and denotes the method in which the condition is to be handled. If the state is OFF, then neither handler nor method is defined.
  
 [Current Trapped Condition.] [Current Trapped Condition.]
Line 4574: Line 4574:
  
   * To set the trap method, use either SIGNAL or CALL as keyword.   * To set the trap method, use either SIGNAL or CALL as keyword.
-  * To set state to ON or OFF, use the appropriate subkeyword in the clause. Note that there is no clause or function in Rexx, capable of setting the state of a trap to DELAY.+  * To set state to ON or OFF, use the appropriate subkeyword in the clause. Note that there is no clause or function in REXX, capable of setting the state of a trap to DELAY.
   * To set the condition handler, append the term "NAME handler" to the command. Note that this term is only legal if you are setting the state to ON; you can not specify a handler when setting the state to OFF.   * To set the condition handler, append the term "NAME handler" to the command. Note that this term is only legal if you are setting the state to ON; you can not specify a handler when setting the state to OFF.
  
-The trap is said to be "enabled" when the state is either ON or DELAY, and "disabled" when the state is OFF. Note that neither the event queue, nor the current trapped condition can be set explicitly by Rexx clauses. They can only be set as a result of incidents, when raising and trapping conditions. It sounds very theoretical, doesn't it? Look at the following examples, which sets the trap MYTH:+The trap is said to be "enabled" when the state is either ON or DELAY, and "disabled" when the state is OFF. Note that neither the event queue, nor the current trapped condition can be set explicitly by REXX clauses. They can only be set as a result of incidents, when raising and trapping conditions. It sounds very theoretical, doesn't it? Look at the following examples, which sets the trap MYTH:
  
 <code rexx> <code rexx>
Line 4595: Line 4595:
 ==== How to Raise a Condition ==== ==== How to Raise a Condition ====
  
-How do you raise a condition? Well, there are really no explicit way in Rexx to do that. The conditions are raised when an incident occurs. What sort of situations that is, depends on the context. There are in general three types of incidents, classified by the origin of the event:+How do you raise a condition? Well, there are really no explicit way in REXX to do that. The conditions are raised when an incident occurs. What sort of situations that is, depends on the context. There are in general three types of incidents, classified by the origin of the event:
  
-Internal origin. The incident is only dependent on the behaviour of the Rexx script. The SYNTAX condition is of this type.+Internal origin. The incident is only dependent on the behaviour of the REXX script. The SYNTAX condition is of this type.
  
-External origin. The Rexx script and the interpreter has really no control over when this incident. It happens completely independent of the control of the Rexx script or interpreter. The HALT condition is of this type.+External origin. The REXX script and the interpreter has really no control over when this incident. It happens completely independent of the control of the REXX script or interpreter. The HALT condition is of this type.
  
-Mixed origin. The incident is of external origin, but the situation that created the incident, was an action by the Rexx script or the interpreter. The ERROR condition is of this type: the incident is a command returning error, but it can only occur when the interpreter is executing commands.+Mixed origin. The incident is of external origin, but the situation that created the incident, was an action by the REXX script or the interpreter. The ERROR condition is of this type: the incident is a command returning error, but it can only occur when the interpreter is executing commands.
  
-For conditions trapped by method CALL, standard Rexx requires an implementation to at least check for incidents and raise condition at clause boundaries. (But it is allowed to do so elsewhere too; although the actual triggering must only be performed at clause boundaries.) Consequently, you must be prepared that in some implementations, conditions trappable by method CALL might only be raised (and the trap triggered) at clause boundaries, even if they are currently trapped by method SIGNAL.+For conditions trapped by method CALL, standard REXX requires an implementation to at least check for incidents and raise condition at clause boundaries. (But it is allowed to do so elsewhere too; although the actual triggering must only be performed at clause boundaries.) Consequently, you must be prepared that in some implementations, conditions trappable by method CALL might only be raised (and the trap triggered) at clause boundaries, even if they are currently trapped by method SIGNAL.
  
 The seven standard conditions will be raised as result of various situations, read the section describing each one of them for more information. The seven standard conditions will be raised as result of various situations, read the section describing each one of them for more information.
Line 4664: Line 4664:
 In addition, the interpreter will at each clause boundary check for any pending events in the event queue. If the queue is non-empty, the interpreter will not immediately execute the next normal statement, but it will handle the condition(s) first. This procedure is repeated until there are no more events queued. Only then will the interpreter advance to execute the next normal statement. In addition, the interpreter will at each clause boundary check for any pending events in the event queue. If the queue is non-empty, the interpreter will not immediately execute the next normal statement, but it will handle the condition(s) first. This procedure is repeated until there are no more events queued. Only then will the interpreter advance to execute the next normal statement.
  
-Note that the Rexx standard does not require the pending events to be handled in any particular order, although the model shown in this documentation it will be in the order in which the conditions were raised. Consequently, if one clause generates several events that raise conditions before or at the next clause boundary, and these conditions are trapped by method CALL. Then, the order on which the various traps are triggered is implementations-dependent. But the order in which the different instances of the same condition is handled, is the same as the order of the condition indicator queue.+Note that the REXX standard does not require the pending events to be handled in any particular order, although the model shown in this documentation it will be in the order in which the conditions were raised. Consequently, if one clause generates several events that raise conditions before or at the next clause boundary, and these conditions are trapped by method CALL. Then, the order on which the various traps are triggered is implementations-dependent. But the order in which the different instances of the same condition is handled, is the same as the order of the condition indicator queue.
  
 ==== Trapping by Method SIGNAL ==== ==== Trapping by Method SIGNAL ====
  
-Assume that a condition is being trapped by method SIGNAL, that the state is ON and the handler is MYTH_TRAP. The following Rexx clause will setup the trap correctly:+Assume that a condition is being trapped by method SIGNAL, that the state is ON and the handler is MYTH_TRAP. The following REXX clause will setup the trap correctly:
  
 <code rexx> <code rexx>
Line 4693: Line 4693:
 Assume that the condition MYTH is being trapped by method CALL, that the state is ON and the handler is MYTH_HANDLER. Assume that the condition MYTH is being trapped by method CALL, that the state is ON and the handler is MYTH_HANDLER.
  
-The following Rexx clause will setup the trap correctly:+The following REXX clause will setup the trap correctly:
  
 <code rexx> <code rexx>
Line 4711: Line 4711:
 At the return from the condition handler, the current trapped condition and the setup of all traps are restored, as with a normal return from subroutine. As a special case, the state of the trap just triggered, will not be put back into DELAY state, but is set to state ON. At the return from the condition handler, the current trapped condition and the setup of all traps are restored, as with a normal return from subroutine. As a special case, the state of the trap just triggered, will not be put back into DELAY state, but is set to state ON.
  
-Afterward (and before the next normal clause), the interpreter will again check for more events in the event queue, and it will not continue on the Rexx script before the queue is empty.+Afterward (and before the next normal clause), the interpreter will again check for more events in the event queue, and it will not continue on the REXX script before the queue is empty.
  
 During the triggering of a trap by method CALL at a clause boundary, the state of the trap is not normally changed, it will continue to be DELAY, as was set when the condition was raised. It will continue to be in state DELAY until return from the condition handler, at which the state of the trap in the caller will be changed to ON. If, during the execution of the condition trap, the state of the condition being trapped is set, that change will only last until the return from the condition handler. During the triggering of a trap by method CALL at a clause boundary, the state of the trap is not normally changed, it will continue to be DELAY, as was set when the condition was raised. It will continue to be in state DELAY until return from the condition handler, at which the state of the trap in the caller will be changed to ON. If, during the execution of the condition trap, the state of the condition being trapped is set, that change will only last until the return from the condition handler.
Line 4739: Line 4739:
 ===== The Real Conditions ===== ===== The Real Conditions =====
  
-We have now described how the standard condition and condition trap works in Rexx. Let's look at the seven conditions defined which do exist. Note that none of these behaves exactly as the standard condition.+We have now described how the standard condition and condition trap works in REXX. Let's look at the seven conditions defined which do exist. Note that none of these behaves exactly as the standard condition.
  
 ==== The SYNTAX condition ==== ==== The SYNTAX condition ====
  
-The SYNTAX condition is of internal origin, and is raised when any syntax or runtime error is discovered by the Rexx interpreter. It might be any of the situations that would normally lead to the abortion of the program and the report of a Rexx error message, except error message number 4 (Program interrupted), which is handled by the HALT condition.+The SYNTAX condition is of internal origin, and is raised when any syntax or runtime error is discovered by the REXX interpreter. It might be any of the situations that would normally lead to the abortion of the program and the report of a REXX error message, except error message number 4 (Program interrupted), which is handled by the HALT condition.
  
 There are several differences between this condition and the standard condition: There are several differences between this condition and the standard condition:
Line 4749: Line 4749:
 It is not possible to trap this condition with the method CALL, only method SIGNAL. The reason for this is partly that method CALL tries to continue execution until next boundary before triggering the trap. That might not be possible with syntax or runtime errors. It is not possible to trap this condition with the method CALL, only method SIGNAL. The reason for this is partly that method CALL tries to continue execution until next boundary before triggering the trap. That might not be possible with syntax or runtime errors.
  
-When this condition is trapped, the special variable RC is set to the Rexx error number of the syntax or runtime error that caused the condition. This is done just before the setting of the special variable SIGL.+When this condition is trapped, the special variable RC is set to the REXX error number of the syntax or runtime error that caused the condition. This is done just before the setting of the special variable SIGL.
  
 The default action of this condition if the trap state is OFF, is to abort the program with a traceback and error message. The default action of this condition if the trap state is OFF, is to abort the program with a traceback and error message.
Line 4762: Line 4762:
 The HALT condition of external origin, which is raised as a result of an action from the user, normally a combination of keys which tries to abort the program. Which combination of keys will vary between operating systems. Some systems might also simulate this event by other means than key combinations. In general ^C and ^-Break key combinations will generate this condition. The differences between HALT and the standard condition are: The HALT condition of external origin, which is raised as a result of an action from the user, normally a combination of keys which tries to abort the program. Which combination of keys will vary between operating systems. Some systems might also simulate this event by other means than key combinations. In general ^C and ^-Break key combinations will generate this condition. The differences between HALT and the standard condition are:
  
-The default-action for the HALT condition is to abort execution, as though a Rexx runtime error number 4 (Program interrupted) had been reported. But note that SYNTAX will never be raised if HALT is not trapped.+The default-action for the HALT condition is to abort execution, as though a REXX runtime error number 4 (Program interrupted) had been reported. But note that SYNTAX will never be raised if HALT is not trapped.
  
 The delay-action of this condition is to ignore, not queue. The delay-action of this condition is to ignore, not queue.
Line 4782: Line 4782:
 Unfortunately, there is no universal standard on return values. As stated, they are often numeric, but some operating system use non-numeric return values. For those which do use numeric values, there are no standard telling which values and ranges are considered errors and which are considered success. In fact, the interpretation of the value might differ between commands within the same operating system. Unfortunately, there is no universal standard on return values. As stated, they are often numeric, but some operating system use non-numeric return values. For those which do use numeric values, there are no standard telling which values and ranges are considered errors and which are considered success. In fact, the interpretation of the value might differ between commands within the same operating system.
  
-Therefore, it is up to the Rexx implementation to define which values and ranges that are considered errors. You must expect that this information can differ between implementations as well as between different environments within one implementation.+Therefore, it is up to the REXX implementation to define which values and ranges that are considered errors. You must expect that this information can differ between implementations as well as between different environments within one implementation.
  
-The descriptive text returned by CONDITION() when called with the Description option for condition ERROR, is the command which caused the error. Note that this is the command as the environment saw it, not as it was entered in the Rexx script source code.+The descriptive text returned by CONDITION() when called with the Description option for condition ERROR, is the command which caused the error. Note that this is the command as the environment saw it, not as it was entered in the REXX script source code.
  
 ==== The FAILURE condition ==== ==== The FAILURE condition ====
Line 4798: Line 4798:
 As for ERROR, there is no standard the defines which return values are failures and which are errors. Consult the system and implementation independent documentation for more information. As for ERROR, there is no standard the defines which return values are failures and which are errors. Consult the system and implementation independent documentation for more information.
  
-The descriptive text returned by CONDITION() when called with the Description option for condition FAILURE, is the command which caused the error. Note that this is the command as the environment saw it, not as it was entered in the Rexx script source code.+The descriptive text returned by CONDITION() when called with the Description option for condition FAILURE, is the command which caused the error. Note that this is the command as the environment saw it, not as it was entered in the REXX script source code.
  
 ==== The NOVALUE condition ==== ==== The NOVALUE condition ====
Line 4847: Line 4847:
 ==== Conditions under Language Level 3.50 ==== ==== Conditions under Language Level 3.50 ====
  
-The concept of conditions was very much expanded from Rexx language level 3.50 to level 4.00. Many of the central features in conditions are new in level 4.00, these include:+The concept of conditions was very much expanded from REXX language level 3.50 to level 4.00. Many of the central features in conditions are new in level 4.00, these include:
  
 The CALL method is new, previously only the SIGNAL method was available, which made it rather difficult to resume execution after a problem. As a part of this, the DELAY state has been added too. The CALL method is new, previously only the SIGNAL method was available, which made it rather difficult to resume execution after a problem. As a part of this, the DELAY state has been added too.
Line 4867: Line 4867:
 ==== The Correctness of this Description ==== ==== The Correctness of this Description ====
  
-In this description of conditions in Rexx, I have gone further in the description of how conditions work, their internal data structures, the order in which things are executed etc., than the standard does. I have tried to interpret the set of distinct statements that is the documentation on condition, and design a complete and consistent system describing how such conditions work. I have done this to try to clarify an area of Rexx which at first glance is very difficult and sometimes non-intuitive.+In this description of conditions in REXX, I have gone further in the description of how conditions work, their internal data structures, the order in which things are executed etc., than the standard does. I have tried to interpret the set of distinct statements that is the documentation on condition, and design a complete and consistent system describing how such conditions work. I have done this to try to clarify an area of REXX which at first glance is very difficult and sometimes non-intuitive.
  
-I hope that the liberties I have taken have helped describe conditions in Rexx. I do not feel that the adding of details that I have done in any way change how conditions work, but at least I owe the reader to list which concepts that are genuine Rexx, and which have been filled in by me to make the picture more complete. These are not a part of the standard Rexx.+I hope that the liberties I have taken have helped describe conditions in REXX. I do not feel that the adding of details that I have done in any way change how conditions work, but at least I owe the reader to list which concepts that are genuine REXX, and which have been filled in by me to make the picture more complete. These are not a part of the standard REXX.
  
-Rexx does not have anything called a standard condition. There just "are" a set of conditions having different attributes and values. Sometimes there are default values to some of the attributes, but still the are no default condition.+REXX does not have anything called a standard condition. There just "are" a set of conditions having different attributes and values. Sometimes there are default values to some of the attributes, but still the are no default condition.
  
 The terms "event" and "incident" are not used. Instead the term "condition" is somewhat overloaded to mean several things, depending on the situation. I have found it advantageous to use different terms for each of these concepts. The terms "event" and "incident" are not used. Instead the term "condition" is somewhat overloaded to mean several things, depending on the situation. I have found it advantageous to use different terms for each of these concepts.
  
-Standard Rexx does not have condition queue, although a structure of such a kind is needed to handled the queuing of pending conditions when the trap state is DELAY.+Standard REXX does not have condition queue, although a structure of such a kind is needed to handled the queuing of pending conditions when the trap state is DELAY.
  
-The values default-action and delay-action are really non-existing in the Standard Rexx documentation. I made them up to make the system more easy to explain.+The values default-action and delay-action are really non-existing in the Standard REXX documentation. I made them up to make the system more easy to explain.
  
-The two-step process of first raising the flag, and then (possibly at a later stage) triggering the trap, is not really a Rexx concept. Originally, Rexx seems to allow implementations to select certain places of the interpreter where events are sought for. All standard conditions that can be called by method CALL, can be implemented by checking only at clause boundaries.+The two-step process of first raising the flag, and then (possibly at a later stage) triggering the trap, is not really a REXX concept. Originally, REXX seems to allow implementations to select certain places of the interpreter where events are sought for. All standard conditions that can be called by method CALL, can be implemented by checking only at clause boundaries.
  
-Consequently,Rexx implementation can choose to trigger the trap immediately after a condition are raised (since conditions are only raised immediately before the trap would trigger anyway). This is also the common way used in language level 3.50, when only method SIGNAL was implemented.+Consequently,REXX implementation can choose to trigger the trap immediately after a condition are raised (since conditions are only raised immediately before the trap would trigger anyway). This is also the common way used in language level 3.50, when only method SIGNAL was implemented.
  
 Unfortunately, the introduction of the state DELAY forces the interpreter to keep a queue of pending conditions, so there is nothing to gain on insisting that raising should happen immediately before triggering. And the picture is even more muddied when the NOTREADY condition is introduced. Since it explicitly allows raising of condition to be done during the clause, even though the triggering of the trap must happen (if method is CALL) at the end of the clause. Unfortunately, the introduction of the state DELAY forces the interpreter to keep a queue of pending conditions, so there is nothing to gain on insisting that raising should happen immediately before triggering. And the picture is even more muddied when the NOTREADY condition is introduced. Since it explicitly allows raising of condition to be done during the clause, even though the triggering of the trap must happen (if method is CALL) at the end of the clause.
  
-I really hope that these changes has made the concept of conditions easier to understand, not harder. Please feel free to flame me for any of these which you don't think is representative for Rexx.+I really hope that these changes has made the concept of conditions easier to understand, not harder. Please feel free to flame me for any of these which you don't think is representative for REXX.
  
  
 ===== Conditions in Regina ===== ===== Conditions in Regina =====
  
-Here comes documentation that are specific for the Regina implementation of Rexx.+Here comes documentation that are specific for the Regina implementation of REXX.
  
 ==== How to Raise the HALT condition ==== ==== How to Raise the HALT condition ====
Line 4905: Line 4905:
 ===== Possible Future extensions ===== ===== Possible Future extensions =====
  
-Here is a list of possible future extensions to Rexx which has not been implemented into Regina. Some of these exist in other implementations of Rexx, and some of them are just suggestions or ideas thrown around by various people.+Here is a list of possible future extensions to REXX which has not been implemented into Regina. Some of these exist in other implementations of REXX, and some of them are just suggestions or ideas thrown around by various people.
  
-Another extension could have been included, but have been left out so far. It is the delay-action, which in standard Rexx can be either to ignore or to queue. There is at least one other action that make sense: to replace. That is, when a trap is in state DELAY, and a new condition has been raised, the pending queue is emptied, before the new condition is queued. That way, the new condition will effectively replace any conditions already in the queue.+Another extension could have been included, but have been left out so far. It is the delay-action, which in standard REXX can be either to ignore or to queue. There is at least one other action that make sense: to replace. That is, when a trap is in state DELAY, and a new condition has been raised, the pending queue is emptied, before the new condition is queued. That way, the new condition will effectively replace any conditions already in the queue.
  
 If there are several new conditions raised while the condition handler is executing (and the trap state is DELAY), only the very last of them is remembered. If there are several new conditions raised while the condition handler is executing (and the trap state is DELAY), only the very last of them is remembered.
Line 4930: Line 4930:
 ===== Background and Historical Remarks ===== ===== Background and Historical Remarks =====
  
-Stream I/O is a problem area for languages like Rexx. They try to maintain compatibility for all platforms (i.e. to be non-system-specific), but the basic I/O capabilities differ between systems, so the simplest way to achieve compatibility is to include only a minimal, common subset of the functionality of all platforms. With respect to the functionality of the interface to their surrounding environment, non-system-specific script languages like Rexx are inherently inferior to system specific script languages which are hardwired to particular operating systems and can benefit from all their features.+Stream I/O is a problem area for languages like REXX. They try to maintain compatibility for all platforms (i.e. to be non-system-specific), but the basic I/O capabilities differ between systems, so the simplest way to achieve compatibility is to include only a minimal, common subset of the functionality of all platforms. With respect to the functionality of the interface to their surrounding environment, non-system-specific script languages like REXX are inherently inferior to system specific script languages which are hardwired to particular operating systems and can benefit from all their features.
  
-Although Rexx formally has its own I/O constructs, it is common for some platforms that most or all of the I/O is performed as operating system commands rather than in Rexx. This is how it was originally done under VM/CMS, which was one of the earliest implementations and which did not support Rexx's I/O constructs. There, the EXECIO program and the stack (among other methods) are used to transfer data to and from a Rexx program.+Although REXX formally has its own I/O constructs, it is common for some platforms that most or all of the I/O is performed as operating system commands rather than in REXX. This is how it was originally done under VM/CMS, which was one of the earliest implementations and which did not support REXX's I/O constructs. There, the EXECIO program and the stack (among other methods) are used to transfer data to and from a REXX program.
  
-Later, the built-in functions for stream I/O gained territory, but lots of implementations still rely on special purpose programs for doing I/O. The general recommendation to Rexx programmers is to use the built-in functions instead of special purpose programs whenever possible; that is the only way to make compatible programs.+Later, the built-in functions for stream I/O gained territory, but lots of implementations still rely on special purpose programs for doing I/O. The general recommendation to REXX programmers is to use the built-in functions instead of special purpose programs whenever possible; that is the only way to make compatible programs.
  
  
-===== Rexx's Notion of a Stream =====+===== REXX's Notion of a Stream =====
  
-Rexx regards a stream as a sequence of characters, conceptually equivalent to what a user might type at the keyboard. Note that a stream is not generally equivalent to a file. [MCGH:DICT] defines a file as "a collection of related records treated as a unit," while [OX:CDICT] defines it as "Information held on backing store [...] in order (a) to enable it to persist beyond the time of execution of a single job and/or (b) to overcome space limitations in main memory." A stream is defined by [OX:CDICT] as "a flow of data characterized by relative long duration and constant rate."+REXX regards a stream as a sequence of characters, conceptually equivalent to what a user might type at the keyboard. Note that a stream is not generally equivalent to a file. [MCGH:DICT] defines a file as "a collection of related records treated as a unit," while [OX:CDICT] defines it as "Information held on backing store [...] in order (a) to enable it to persist beyond the time of execution of a single job and/or (b) to overcome space limitations in main memory." A stream is defined by [OX:CDICT] as "a flow of data characterized by relative long duration and constant rate."
  
-Thus, a file has a flavor of persistency, while a stream has a flavor of sequence and momentarily. For a stream, data read earlier may already have been lost, and the data not yet read may not be currently defined; for instance the input typed at a keyboard or the output of a program. Even though much of the Rexx literature use these two terms interchangeably (and after all, there is some overlap), you should bear in mind that there is a difference between them.+Thus, a file has a flavor of persistency, while a stream has a flavor of sequence and momentarily. For a stream, data read earlier may already have been lost, and the data not yet read may not be currently defined; for instance the input typed at a keyboard or the output of a program. Even though much of the REXX literature use these two terms interchangeably (and after all, there is some overlap), you should bear in mind that there is a difference between them.
  
-In this documentation, the term "file" means "a collection of persistent data on secondary storage, to which random access and multiple retrieval are allowed." The term "stream" means a sequential flow of data from a file or from a sequential device like a terminal, tape, or the output of a program. The term stream is also used in its strict Rexx meaning: a handle to/from which a flow of data can be written/read.+In this documentation, the term "file" means "a collection of persistent data on secondary storage, to which random access and multiple retrieval are allowed." The term "stream" means a sequential flow of data from a file or from a sequential device like a terminal, tape, or the output of a program. The term stream is also used in its strict REXX meaning: a handle to/from which a flow of data can be written/read.
  
  
 ===== Short Crash-Course ===== ===== Short Crash-Course =====
  
-Rexx I/O is very simple, and this short crash course is probably all you need in a first-time reading of this chapter. But note that that, we need to jump a bit ahead in this section.+REXX I/O is very simple, and this short crash course is probably all you need in a first-time reading of this chapter. But note that that, we need to jump a bit ahead in this section.
  
 To read a line from a stream, use the LINEIN() built-in function, which returns the data read. To write a stream, use the LINEOUT() built-in function, and supply the data to be written as the second parameter. For both operations, give the name of the stream as the first parameter. Some small examples: To read a line from a stream, use the LINEIN() built-in function, which returns the data read. To write a stream, use the LINEOUT() built-in function, and supply the data to be written as the second parameter. For both operations, give the name of the stream as the first parameter. Some small examples:
Line 4959: Line 4959:
 The first of these reads a line from the stream myfile.txt, while the second writes a line to the stream yourfile.txt. Both these calls operate on lines and they use a system specific end-of-line marker as a delimiter between lines. The marker is tagged on at the end of any data written out, and stripped off any data read. The first of these reads a line from the stream myfile.txt, while the second writes a line to the stream yourfile.txt. Both these calls operate on lines and they use a system specific end-of-line marker as a delimiter between lines. The marker is tagged on at the end of any data written out, and stripped off any data read.
  
-Opening a stream in Rexx is generally done automatically, so you can generally ignore that in your programs. Another useful method is repositioning to a particular line:+Opening a stream in REXX is generally done automatically, so you can generally ignore that in your programs. Another useful method is repositioning to a particular line:
  
 <code rexx> <code rexx>
Line 4987: Line 4987:
 ===== Naming Streams ===== ===== Naming Streams =====
  
-Unlike most programming languages, Rexx does not use file handles; the name of the stream is also in general the handle (although some implementations add an extra level of indirection). You must supply the name to all I/O functions operating on a stream. However, internally, the Rexx interpreter is likely to use the native file pointers of the operating system, in order to improve speed. The name specified can generally be the name of an operating system file, a device name, or a special stream name supported by your implementation.+Unlike most programming languages, REXX does not use file handles; the name of the stream is also in general the handle (although some implementations add an extra level of indirection). You must supply the name to all I/O functions operating on a stream. However, internally, the REXX interpreter is likely to use the native file pointers of the operating system, in order to improve speed. The name specified can generally be the name of an operating system file, a device name, or a special stream name supported by your implementation.
  
 The format of the stream name is very dependent upon your operating system. For portability concerns, you should try not to specify it as a literal string in each I/O call, but set a variable to the stream name, and use that variable when calling I/O functions. This reduces the number of places you need to make changes if you need to port the program to another system. Unfortunately, this approach increases the need for PROCEDURE EXPOSE, since the variable containing the files name must be available to all routines using file I/O for that particular file, and all their non-common ancestors. The format of the stream name is very dependent upon your operating system. For portability concerns, you should try not to specify it as a literal string in each I/O call, but set a variable to the stream name, and use that variable when calling I/O functions. This reduces the number of places you need to make changes if you need to port the program to another system. Unfortunately, this approach increases the need for PROCEDURE EXPOSE, since the variable containing the files name must be available to all routines using file I/O for that particular file, and all their non-common ancestors.
Line 5006: Line 5006:
 However, most implementations allow you to access the default streams explicitly through a name, maybe the nullstring or something like stdin and stdout. However, you must refer to the implementation-specific documentation for information about this. However, most implementations allow you to access the default streams explicitly through a name, maybe the nullstring or something like stdin and stdout. However, you must refer to the implementation-specific documentation for information about this.
  
-Also note that standard Rexx does not support the concept of a default error stream. On operating systems supporting this, it can probably be accessed through a special name; see system-specific information. The same applies for other special streams.+Also note that standard REXX does not support the concept of a default error stream. On operating systems supporting this, it can probably be accessed through a special name; see system-specific information. The same applies for other special streams.
  
 Sometimes the term "default input stream" is called "standard input stream," "default input devices," "standard input," or just "stdin." Sometimes the term "default input stream" is called "standard input stream," "default input devices," "standard input," or just "stdin."
  
-The use of stream names instead of stream descriptors or handles is deeply rooted in the Rexx philosophy: Data structures are text strings carrying information, rather than opaque data blocks in internal, binary format. This opens for some intriguing possibilities. Under some operating systems, a file can be referred to by many names. For instance, under Unix, a file can be referred to as foobar, ./foobar and ././foobar. All which name the same file, although a Rexx interpreter may be likely to interpret them as three different streams, because the names themselves differ. On the other hand, nothing prevents an interpreter from discovering that these are names for the same stream, and treat them as equivalent (except concerns for processing time). Under Unix, the problem is not just confined to the use of ./ in file names, hard-links and soft-links can produce similar effects, too.+The use of stream names instead of stream descriptors or handles is deeply rooted in the REXX philosophy: Data structures are text strings carrying information, rather than opaque data blocks in internal, binary format. This opens for some intriguing possibilities. Under some operating systems, a file can be referred to by many names. For instance, under Unix, a file can be referred to as foobar, ./foobar and ././foobar. All which name the same file, although a REXX interpreter may be likely to interpret them as three different streams, because the names themselves differ. On the other hand, nothing prevents an interpreter from discovering that these are names for the same stream, and treat them as equivalent (except concerns for processing time). Under Unix, the problem is not just confined to the use of ./ in file names, hard-links and soft-links can produce similar effects, too.
  
 Example: Internal file handles Example: Internal file handles
  
-Suppose you start reading from a stream, which is connected to a file called foo. You read the first line of foo, then you issue a command, in order to rename foo to bar. Then, you try to read the next line from foo. The Rexx program for doing this under Unix looks something like:+Suppose you start reading from a stream, which is connected to a file called foo. You read the first line of foo, then you issue a command, in order to rename foo to bar. Then, you try to read the next line from foo. The REXX program for doing this under Unix looks something like:
  
 <code rexx> <code rexx>
Line 5021: Line 5021:
 </code> </code>
  
-Theoretically, the file foo does not exist during the second call, so the second read should raise the NOTREADY condition. However, a Rexx interpreter is likely to have opened the stream already, so it is performing the reading on the file descriptor of the open file. It is probably not going to check whether the file exists before each I/O operation (that would require a lot of extra checking). Under most operating systems, renaming a file will not invalidate existing file descriptors. Consequently, the interpreter is likely to continue to read from the original foo file, even though its has changed.+Theoretically, the file foo does not exist during the second call, so the second read should raise the NOTREADY condition. However, a REXX interpreter is likely to have opened the stream already, so it is performing the reading on the file descriptor of the open file. It is probably not going to check whether the file exists before each I/O operation (that would require a lot of extra checking). Under most operating systems, renaming a file will not invalidate existing file descriptors. Consequently, the interpreter is likely to continue to read from the original foo file, even though its has changed.
  
 Example: Unix temporary files Example: Unix temporary files
Line 5032: Line 5032:
 </code> </code>
  
-Under Unix, this technique is often used to create temporary files; you are guaranteed that the file will be deleted on closing, no matter how your program terminates. Unix deletes a file whenever there are no more references to it. Whether the reference is from the file system or from an open descriptor in a user process is irrelevant. After the rm command, the only reference to the file is from the Rexx interpreter. Whenever it terminates, the file is deleted--since there are no more references to it.+Under Unix, this technique is often used to create temporary files; you are guaranteed that the file will be deleted on closing, no matter how your program terminates. Unix deletes a file whenever there are no more references to it. Whether the reference is from the file system or from an open descriptor in a user process is irrelevant. After the rm command, the only reference to the file is from the REXX interpreter. Whenever it terminates, the file is deleted--since there are no more references to it.
  
 Example: Files in different directories Example: Files in different directories
Line 5044: Line 5044:
 </code> </code>
  
-Since the file is implicitly opened while you are in the directory dir1, the file foobar refers to a file located there. However, after changing the directory to dir2, it may seem logical that the second call to LINEOUT() operates on a file in dir2, but that may not be the case. Considering that these clauses may come a great number of lines apart, that Rexx has no standard way of closing files, and that Rexx only have one file table (i.e. open files are not local to subroutines); this may open for a significant astonishment in complex Rexx scripts.+Since the file is implicitly opened while you are in the directory dir1, the file foobar refers to a file located there. However, after changing the directory to dir2, it may seem logical that the second call to LINEOUT() operates on a file in dir2, but that may not be the case. Considering that these clauses may come a great number of lines apart, that REXX has no standard way of closing files, and that REXX only have one file table (i.e. open files are not local to subroutines); this may open for a significant astonishment in complex REXX scripts.
  
 Whether an implementation treats ././foo and ./foo as different streams is system-dependent; that applies to the effects of renaming or deleting the file while reading or writing, too. See your interpreter's system-specific documentation. Whether an implementation treats ././foo and ./foo as different streams is system-dependent; that applies to the effects of renaming or deleting the file while reading or writing, too. See your interpreter's system-specific documentation.
  
-Most of the effects shown in the examples above are due to insufficient isolation between the filename of the operating system and the file handle in the Rexx program. Whenever a file can be explicitly opened and bound to a file handle, you should do that in order to decrease the possibilities for strange side effects.+Most of the effects shown in the examples above are due to insufficient isolation between the filename of the operating system and the file handle in the REXX program. Whenever a file can be explicitly opened and bound to a file handle, you should do that in order to decrease the possibilities for strange side effects.
  
 Interpreters that allow this method generally have an OPEN() function that takes the name of the files to open as a parameter, and returns a string that uniquely identifies that open file within the current context; e.g. an index into a table of open files. Later, this index can be used instead of the filename. Interpreters that allow this method generally have an OPEN() function that takes the name of the files to open as a parameter, and returns a string that uniquely identifies that open file within the current context; e.g. an index into a table of open files. Later, this index can be used instead of the filename.
Line 5056: Line 5056:
 ===== Persistent and Transient Streams ===== ===== Persistent and Transient Streams =====
  
-Rexx knows two different types of streams: persistent and transient. They differ conceptually in the way they can be operated, which is dictated by the way they are stored. But there is no difference in the data you can read from or write to them (i.e. both can used for character- or line-wise data), and both are read and written using the same functions.+REXX knows two different types of streams: persistent and transient. They differ conceptually in the way they can be operated, which is dictated by the way they are stored. But there is no difference in the data you can read from or write to them (i.e. both can used for character- or line-wise data), and both are read and written using the same functions.
  
 [Persistent streams] [Persistent streams]
Line 5066: Line 5066:
 are typically not available for random access or repeated retrieval, either because it is not stored permanently, but read as a sequence of data that is generated on the fly; or because they are available from a sequential storage (e.g. magnetic tape) where random access is difficult or impossible. Typical examples of transient streams are devices like keyboards, printers, communication interfaces, pipelines, etc. are typically not available for random access or repeated retrieval, either because it is not stored permanently, but read as a sequence of data that is generated on the fly; or because they are available from a sequential storage (e.g. magnetic tape) where random access is difficult or impossible. Typical examples of transient streams are devices like keyboards, printers, communication interfaces, pipelines, etc.
  
-Rexx does not allow any repositioning on transient streams; such operations are not conceptually meaningful; a transient stream must be treated sequentially. It is possible to treat a persistent stream as a transient stream, but not vice versa. Thus, some implementations may allow you to open a persistent stream as transient. This may be useful for files to which you have only append access, i.e. writes can only be performed at the end of file. Whether you can open a stream in a particular mode, or change the mode of a stream already open depends on your implementation.+REXX does not allow any repositioning on transient streams; such operations are not conceptually meaningful; a transient stream must be treated sequentially. It is possible to treat a persistent stream as a transient stream, but not vice versa. Thus, some implementations may allow you to open a persistent stream as transient. This may be useful for files to which you have only append access, i.e. writes can only be performed at the end of file. Whether you can open a stream in a particular mode, or change the mode of a stream already open depends on your implementation.
  
 Example: Determining stream type Example: Determining stream type
Line 5088: Line 5088:
 ===== Opening a Stream ===== ===== Opening a Stream =====
  
-In most programming languages, opening a file is the process of binding a file (given by a file name) to an internal handle. Rexx is a bit special, since conceptually, it does not use stream handles, just stream names. Therefore, the stream name is itself also the stream handle, and the process of opening streams becomes apparently redundant. However, note that a number of implementations allow explicit opening, and some even require it.+In most programming languages, opening a file is the process of binding a file (given by a file name) to an internal handle. REXX is a bit special, since conceptually, it does not use stream handles, just stream names. Therefore, the stream name is itself also the stream handle, and the process of opening streams becomes apparently redundant. However, note that a number of implementations allow explicit opening, and some even require it.
  
-Rexx may open streams "on demand" when they are used for the first time. However, this behavior is not defined in TRL, which says the act of opening the stream is not a part of Rexx [TRL2]. This might be interpreted as open-on-demand or that some system-specific program must be executed to open a stream.+REXX may open streams "on demand" when they are used for the first time. However, this behavior is not defined in TRL, which says the act of opening the stream is not a part of REXX [TRL2]. This might be interpreted as open-on-demand or that some system-specific program must be executed to open a stream.
  
-Although an open-on-demand feature is very practical, there are situations where you need to open streams in particular modes. Thus, most systems have facilities for explicitly opening a file. Some Rexx interpreters may require you to perform some implementation-specific operation before accessing streams, but most are likely to just open them the first time they are referred to in an I/O operation.+Although an open-on-demand feature is very practical, there are situations where you need to open streams in particular modes. Thus, most systems have facilities for explicitly opening a file. Some REXX interpreters may require you to perform some implementation-specific operation before accessing streams, but most are likely to just open them the first time they are referred to in an I/O operation.
  
 There are two main approaches to explicit opening of streams. The first uses a non-standard built-in function normally called OPEN(), which generally takes the name of the file to open as the first parameter, and often the mode as the second parameter. The second approach is similar, but uses the standard built-in function STREAM() with a Command option. There are two main approaches to explicit opening of streams. The first uses a non-standard built-in function normally called OPEN(), which generally takes the name of the file to open as the first parameter, and often the mode as the second parameter. The second approach is similar, but uses the standard built-in function STREAM() with a Command option.
Line 5098: Line 5098:
 Example: Not closing files Example: Not closing files
  
-Since there are no open or close operation, a Rexx interpreter never knows when to close a stream, unless explicitly told so. It can never predict when a particular stream is to be used next, so it has to keep the current read and write positions in case the stream is to be used again. Therefore, you should always close the streams when you are finished using them. Failure to do so, will fill the interpreter with data about unneeded streams, and more serious, it may fill the file table of your process or system. As a rule, any Rexx script that uses more than a couple of streams, should close every stream after use, in order to minimize the number of simultaneously open streams. Thus, the following code might eventually crash for some Rexx interpreters:+Since there are no open or close operation, a REXX interpreter never knows when to close a stream, unless explicitly told so. It can never predict when a particular stream is to be used next, so it has to keep the current read and write positions in case the stream is to be used again. Therefore, you should always close the streams when you are finished using them. Failure to do so, will fill the interpreter with data about unneeded streams, and more serious, it may fill the file table of your process or system. As a rule, any REXX script that uses more than a couple of streams, should close every stream after use, in order to minimize the number of simultaneously open streams. Thus, the following code might eventually crash for some REXX interpreters:
  
 <code rexx> <code rexx>
Line 5106: Line 5106:
 </code> </code>
  
-Rexx interpreter might try to defend itself against this sort of open-many-close-none programming, using of various programming techniques; this may lead to other strange effects. However, the main responsibility for avoiding this is with you, the Rexx script programmer.+REXX interpreter might try to defend itself against this sort of open-many-close-none programming, using of various programming techniques; this may lead to other strange effects. However, the main responsibility for avoiding this is with you, the REXX script programmer.
  
 Note that if a stream is already open for reading, and you start writing to it, your implementation may have to reopen it in order to open for both reading and writing. There are mainly two strategies for handling this. Either the old file is closed, and then reopened in the new mode, which may leave you with read and write access to another file. Or a new file handle is opened for the new mode, which may leave you with read and write access to two different files. Note that if a stream is already open for reading, and you start writing to it, your implementation may have to reopen it in order to open for both reading and writing. There are mainly two strategies for handling this. Either the old file is closed, and then reopened in the new mode, which may leave you with read and write access to another file. Or a new file handle is opened for the new mode, which may leave you with read and write access to two different files.
Line 5114: Line 5114:
 ===== Closing a Stream ===== ===== Closing a Stream =====
  
-As already mentioned, Rexx does not have an explicit way of opening a stream. Nor does it have an explicit way of closing a stream. There is one semi-standard method: If you call LINEOUT(), but omit both the data to be written and the new current write position, then the implementation is defined to set the current write position to the end-of-file. Furthermore, it is allowed by TRL to do something "magic" in addition. It is not explicitly defined what this magic is, but TRL suggests that it may be closing the stream, flushing the stream, or committing changes done previously to the stream.+As already mentioned, REXX does not have an explicit way of opening a stream. Nor does it have an explicit way of closing a stream. There is one semi-standard method: If you call LINEOUT(), but omit both the data to be written and the new current write position, then the implementation is defined to set the current write position to the end-of-file. Furthermore, it is allowed by TRL to do something "magic" in addition. It is not explicitly defined what this magic is, but TRL suggests that it may be closing the stream, flushing the stream, or committing changes done previously to the stream.
  
 In SAA, the definition is strengthened to state that the "magic" is closing, provided that the environment supports that operation. In SAA, the definition is strengthened to state that the "magic" is closing, provided that the environment supports that operation.
Line 5134: Line 5134:
  
  
-Basically, the built-in Rexx library offers two strategies of reading and writing streams: line-wise and character-wise. When reading line-wise, the underlying storage method of the stream must contain information which describes where each line starts and ends.+Basically, the built-in REXX library offers two strategies of reading and writing streams: line-wise and character-wise. When reading line-wise, the underlying storage method of the stream must contain information which describes where each line starts and ends.
  
 Some file systems store this information as one or more special characters; while others structure the file in a number of records; each containing a single line. This introduces a slightly subtle point; even though a stream foo returns the same data when read by LINEIN()on two different machines; the data read from foo may differ between the same two machines when the stream is read by CHARIN(), and vice versa. This is so because the end-of-line markers can vary between the two operating systems. Some file systems store this information as one or more special characters; while others structure the file in a number of records; each containing a single line. This introduces a slightly subtle point; even though a stream foo returns the same data when read by LINEIN()on two different machines; the data read from foo may differ between the same two machines when the stream is read by CHARIN(), and vice versa. This is so because the end-of-line markers can vary between the two operating systems.
Line 5209: Line 5209:
 Example: Counting lines, words, and characters Example: Counting lines, words, and characters
  
-The following Rexx program emulates the core functionality of the wc program under Unix. It counts the number of lines, words, and characters in a file given as the first argument.+The following REXX program emulates the core functionality of the wc program under Unix. It counts the number of lines, words, and characters in a file given as the first argument.
  
 <code rexx> <code rexx>
Line 5228: Line 5228:
 ===== Determining the Current Position ===== ===== Determining the Current Position =====
  
-Standard Rexx does not have any seek call that returns the current position in a stream. Instead, it provides two calls that returns the amount of data remaining on a stream. These two built-in functions are LINES() and CHARS().+Standard REXX does not have any seek call that returns the current position in a stream. Instead, it provides two calls that returns the amount of data remaining on a stream. These two built-in functions are LINES() and CHARS().
  
 The LINES() built-in function returns the number of complete lines left on the stream given as its first parameter. The term "complete lines" does not really matter much, since an implementation can assume the end-of-file to implicitly mean an end-of-line. The LINES() built-in function returns the number of complete lines left on the stream given as its first parameter. The term "complete lines" does not really matter much, since an implementation can assume the end-of-file to implicitly mean an end-of-line.
Line 5234: Line 5234:
 The CHARS() built-in function returns the number of character left in the stream given as its first parameter. The CHARS() built-in function returns the number of character left in the stream given as its first parameter.
  
-This is one of the concepts where Rexx I/O does not map very well to C I/O and vice versa. While Rexx reports the amount of data from the current read position to the end of stream, C reports the amount of data from the start of the file to the current position. Further, the Rexx method only works for input streams, while the C method works for both input and output files. On the other hand, C has no basic constructs for counting remaining or reposition at lines of a file.+This is one of the concepts where REXX I/O does not map very well to C I/O and vice versa. While REXX reports the amount of data from the current read position to the end of stream, C reports the amount of data from the start of the file to the current position. Further, the REXX method only works for input streams, while the C method works for both input and output files. On the other hand, C has no basic constructs for counting remaining or reposition at lines of a file.
  
 Example: Retrieving current position Example: Retrieving current position
Line 5287: Line 5287:
 ===== Positioning Within a File ===== ===== Positioning Within a File =====
  
-Rexx supports two strategies for reading and writing streams: character-wise, and line-wise, this section describes how a program can reposition the current positions for each these strategies. Note that positioning is only allowed for persistent streams.+REXX supports two strategies for reading and writing streams: character-wise, and line-wise, this section describes how a program can reposition the current positions for each these strategies. Note that positioning is only allowed for persistent streams.
  
 For each open file, there is a current read position or a current write position, depending on whether the file is opened for reading or writing. If the file is opened for reading and writing simultaneously, it has both a current read position and a current write position, and the two are independent and in general different. A position within a file is the sequence number of the byte or line that will be read or written in the next such operation. For each open file, there is a current read position or a current write position, depending on whether the file is opened for reading or writing. If the file is opened for reading and writing simultaneously, it has both a current read position and a current write position, and the two are independent and in general different. A position within a file is the sequence number of the byte or line that will be read or written in the next such operation.
  
-Note that Rexx starts numbering at one, not zero. Therefore, the first character and the first line of a stream are both numbered one. This differs from several other programming languages, which starts numbering at zero.+Note that REXX starts numbering at one, not zero. Therefore, the first character and the first line of a stream are both numbered one. This differs from several other programming languages, which starts numbering at zero.
  
 Just after a stream has been opened, the initial values of the current read position is the first character in the stream, while the current write position is the end-of-file, i.e. the position just after the last character in the stream. Then, reading will return the first character (or line) in the stream, and writing will append a new character (or line) to the stream. Just after a stream has been opened, the initial values of the current read position is the first character in the stream, while the current write position is the end-of-file, i.e. the position just after the last character in the stream. Then, reading will return the first character (or line) in the stream, and writing will append a new character (or line) to the stream.
  
-These initial values for the current read and write positions are the default values. Depending on your Rexx implementation, other mechanisms for explicitly opening streams (e.g. through the STREAM() built-in function) may be provided, and may set other initial values for these positions. See the implementation-specific documentation for further information.+These initial values for the current read and write positions are the default values. Depending on your REXX implementation, other mechanisms for explicitly opening streams (e.g. through the STREAM() built-in function) may be provided, and may set other initial values for these positions. See the implementation-specific documentation for further information.
  
 When setting the current read position, it must be set to the position of an existing character in the stream; i.e. a positive value, not greater than the total number of characters in the stream. In particular, it is illegal to set the current read position to the position immediately after the last character in the stream; although this is legal in many other programming languages and operating systems, where it is known as "seeking to the end-of-file". When setting the current read position, it must be set to the position of an existing character in the stream; i.e. a positive value, not greater than the total number of characters in the stream. In particular, it is illegal to set the current read position to the position immediately after the last character in the stream; although this is legal in many other programming languages and operating systems, where it is known as "seeking to the end-of-file".
Line 5301: Line 5301:
 When setting the current write position, it too must be set to the position of an existing character in the stream. In addition, and unlike the current read position, the current write position may also be set to the position immediately following the last character in the stream. This is known as "positioning at the end-of-file", and it is the initial value for the current write position when a stream is opened. Note that you are not allowed to reposition the current write position further out beyond the end-of-file--which would create a "hole" in the stream--even though this is allowed in many other languages and operating systems. When setting the current write position, it too must be set to the position of an existing character in the stream. In addition, and unlike the current read position, the current write position may also be set to the position immediately following the last character in the stream. This is known as "positioning at the end-of-file", and it is the initial value for the current write position when a stream is opened. Note that you are not allowed to reposition the current write position further out beyond the end-of-file--which would create a "hole" in the stream--even though this is allowed in many other languages and operating systems.
  
-Depending on your operating system and Rexx interpreter, repositioning to after the end-of-file may be allowed as an extension, although it is illegal according to TRL2. You should avoid this technique if you wish to write portable programs.+Depending on your operating system and REXX interpreter, repositioning to after the end-of-file may be allowed as an extension, although it is illegal according to TRL2. You should avoid this technique if you wish to write portable programs.
  
-Rexx only keeps one current read position and one current write position for each stream. So both line-wise and character-wise reading as well as positioning of the current read position will operate on the same current read position, and similarly for the current write position.+REXX only keeps one current read position and one current write position for each stream. So both line-wise and character-wise reading as well as positioning of the current read position will operate on the same current read position, and similarly for the current write position.
  
 When repositioning line-wise, the current write position is set to the first character of the line positioned at. However, if positioning character-wise so that the current read position is in the middle of a line in the file, a subsequent call to LINEIN() will read from (and including) the current position until the next end-of-line marker. Thus, LINEIN() might under some circumstances return only the last part of a line. Similarly, if the current write position has been positioned in the middle of an existing line by character-wise positioning, and LINEOUT() is called, then the line written out becomes the last part of the line stored in the stream. When repositioning line-wise, the current write position is set to the first character of the line positioned at. However, if positioning character-wise so that the current read position is in the middle of a line in the file, a subsequent call to LINEIN() will read from (and including) the current position until the next end-of-line marker. Thus, LINEIN() might under some circumstances return only the last part of a line. Similarly, if the current write position has been positioned in the middle of an existing line by character-wise positioning, and LINEOUT() is called, then the line written out becomes the last part of the line stored in the stream.
Line 5409: Line 5409:
 ===== Common Differences and Problems with Stream I/O ===== ===== Common Differences and Problems with Stream I/O =====
  
-This section describes some of the common traps and pitfalls of Rexx I/O.+This section describes some of the common traps and pitfalls of REXX I/O.
  
 ==== Where Implementations are Allowed to Differ ==== ==== Where Implementations are Allowed to Differ ====
  
-TRL is rather relaxed in its specifications of what an interpreter must implement of the I/O system. It recognizes that operating systems differ, and that some details must be left to the implementor to decide, if Rexx is to be effectively implemented. The parts of the I/O subsystem of Rexx where implementations are allowed to differ, are:+TRL is rather relaxed in its specifications of what an interpreter must implement of the I/O system. It recognizes that operating systems differ, and that some details must be left to the implementor to decide, if REXX is to be effectively implemented. The parts of the I/O subsystem of REXX where implementations are allowed to differ, are:
  
 The functions LINES() and CHARS() are not required to return the number of lines or characters left in a stream. TRL says that if it is impossible or difficult to calculate the numbers, these functions may return 1 unless it is absolutely certain that there are no more data left. This leads to some rather kludgey programming techniques. The functions LINES() and CHARS() are not required to return the number of lines or characters left in a stream. TRL says that if it is impossible or difficult to calculate the numbers, these functions may return 1 unless it is absolutely certain that there are no more data left. This leads to some rather kludgey programming techniques.
Line 5422: Line 5422:
  
  
-The difference in the action of closing and flushing a file, can make a Rexx script that works under one implementation crash under another, so this feature is of very limited value if you are trying to write portable programs.+The difference in the action of closing and flushing a file, can make a REXX script that works under one implementation crash under another, so this feature is of very limited value if you are trying to write portable programs.
  
  
Line 5439: Line 5439:
 Some implementations will use the same position for both the current read position and the current write position to overcome these implementations. Whenever you are doing a read, and the previous operation was a write (or vice versa), it is may prove useful to reposition the current read (or write) position. Some implementations will use the same position for both the current read position and the current write position to overcome these implementations. Whenever you are doing a read, and the previous operation was a write (or vice versa), it is may prove useful to reposition the current read (or write) position.
  
-There might be a maximum linesize for your Rexx interpreter. At least the 50Kb limit on string length may apply.+There might be a maximum linesize for your REXX interpreter. At least the 50Kb limit on string length may apply.
  
-Handling the situation where another program writes data to a file which is used by the Rexx interpreter for reading.+Handling the situation where another program writes data to a file which is used by the REXX interpreter for reading.
  
 ==== LINES() and CHARS() are Inaccurate ==== ==== LINES() and CHARS() are Inaccurate ====
  
-Because of the large differences between various operating systems, Rexx allows some fuzz in the implementation of the LINES() and CHARS() built-in functions. Sometimes, it is difficult to calculate the number of lines or characters in a stream; generally because the storage format of the file often requires a linear search through the whole stream to determine that number. Thus, Rexx allows an implementation to return the value 1 for any situation where the real number is difficult or impossible to determine. Effectively, an implementation can restrict the domain of return values for these two functions only 1 and 0 from these two functions.+Because of the large differences between various operating systems, REXX allows some fuzz in the implementation of the LINES() and CHARS() built-in functions. Sometimes, it is difficult to calculate the number of lines or characters in a stream; generally because the storage format of the file often requires a linear search through the whole stream to determine that number. Thus, REXX allows an implementation to return the value 1 for any situation where the real number is difficult or impossible to determine. Effectively, an implementation can restrict the domain of return values for these two functions only 1 and 0 from these two functions.
  
 Many operating systems store lines using a special end-of-line character sequence. For these systems, it is very time-consuming to count the number of lines in a file, as the file must be scanned for such character sequences. Thus, it is very tempting for an implementor to return the value 1 for any situation where there are more than zero lines left. Many operating systems store lines using a special end-of-line character sequence. For these systems, it is very time-consuming to count the number of lines in a file, as the file must be scanned for such character sequences. Thus, it is very tempting for an implementor to return the value 1 for any situation where there are more than zero lines left.
Line 5455: Line 5455:
 Example: File reading idiom Example: File reading idiom
  
-This example shows a common idiom for reading all contents of a file into Rexx variables using the LINES() and LINEIN() built-in functions.+This example shows a common idiom for reading all contents of a file into REXX variables using the LINES() and LINEIN() built-in functions.
  
 <code rexx> <code rexx>
Line 5496: Line 5496:
 ==== Other Parts of the I/O System ==== ==== Other Parts of the I/O System ====
  
-This section lists some of the other parts of Rexx and the environments around Rexx that may be considered a part of the I/O system.+This section lists some of the other parts of REXX and the environments around REXX that may be considered a part of the I/O system.
  
 [Stack.] [Stack.]
  
-The stack be used to communicate with external environments. At the Rexx side, the interface to the stack is the instructions PUSH, PULL, PARSE PULL, and QUEUE; and the built-in function QUEUED(). These can be used to communicate with external programs by storing data to be transferred on the stack.+The stack be used to communicate with external environments. At the REXX side, the interface to the stack is the instructions PUSH, PULL, PARSE PULL, and QUEUE; and the built-in function QUEUED(). These can be used to communicate with external programs by storing data to be transferred on the stack.
  
 [The STREAM() built-in function.] [The STREAM() built-in function.]
Line 5520: Line 5520:
 [SAA API.] [SAA API.]
  
-The SAA API provides several operations that can be used to communicate between processes. In general, SAA API allows you to perform the operations listed above from a binary program written in a language other than Rexx.+The SAA API provides several operations that can be used to communicate between processes. In general, SAA API allows you to perform the operations listed above from a binary program written in a language other than REXX.
  
-And of course, I/O is performed whenever a Rexx program or external function is started.+And of course, I/O is performed whenever a REXX program or external function is started.
  
 ==== Implementation-Specific Information ==== ==== Implementation-Specific Information ====
  
-This section describes some implementations of stream I/O in Rexx. Unfortunately, this has become a very large section, reflecting the fact that stream I/O is an area of many system-specific solutions.+This section describes some implementations of stream I/O in REXX. Unfortunately, this has become a very large section, reflecting the fact that stream I/O is an area of many system-specific solutions.
  
 In addition, the variations within this topic are rather large. Regina implements a set of functions that are very close to that of TRL2. The other extreme are ARexx and BRexx, which contain a set of functions which is very close to the standard I/O library of the C programming language. In addition, the variations within this topic are rather large. Regina implements a set of functions that are very close to that of TRL2. The other extreme are ARexx and BRexx, which contain a set of functions which is very close to the standard I/O library of the C programming language.
Line 5639: Line 5639:
 [Files with holes.] [Files with holes.]
  
-Regina will be changed to allow it to generate files with holes for system where this is relevant. Although standard Rexx does not allow this, it is a very common programming idiom for certain systems, and should be allowed. It will, however, be controllable through a extension called SparseFiles.+Regina will be changed to allow it to generate files with holes for system where this is relevant. Although standard REXX does not allow this, it is a very common programming idiom for certain systems, and should be allowed. It will, however, be controllable through a extension called SparseFiles.
  
 ==== Stream I/O in ARexx 1.15 ==== ==== Stream I/O in ARexx 1.15 ====
  
-ARexx differs considerably from standard Rexx with respect to stream I/O. In fact, none of the standard stream functionality of Rexx is available in ARexx. Instead, a completely distinct set of functions are used. The differences are so big, that it is useless to describe ARexx stream I/O in terms of standard Rexx stream I/O, and everything said so far in this chapter is irrelevant for ARexx. Therefore, we explain the ARexx functionality from scratch.+ARexx differs considerably from standard REXX with respect to stream I/O. In fact, none of the standard stream functionality of REXX is available in ARexx. Instead, a completely distinct set of functions are used. The differences are so big, that it is useless to describe ARexx stream I/O in terms of standard REXX stream I/O, and everything said so far in this chapter is irrelevant for ARexx. Therefore, we explain the ARexx functionality from scratch.
  
 All in all, the ARexx file I/O interface resembles the functions of the Standard C I/O library, probably because ARexx is written in C, and the ARexx I/O functions are "just" interfaces to the underlying C functions. You may want to check up the documentation for the ANSI C I/O library as described in [ANSIC], [KR], and [PJPlauger]. All in all, the ARexx file I/O interface resembles the functions of the Standard C I/O library, probably because ARexx is written in C, and the ARexx I/O functions are "just" interfaces to the underlying C functions. You may want to check up the documentation for the ANSI C I/O library as described in [ANSIC], [KR], and [PJPlauger].
Line 5765: Line 5765:
  
  
-==== Main Differences from Standard Rexx ====+==== Main Differences from Standard REXX ====
  
-Now, as the functionality has been explained, let me point out the main conceptual differences from standard Rexx; they are:+Now, as the functionality has been explained, let me point out the main conceptual differences from standard REXX; they are:
  
 [Current position.] [Current position.]
Line 5775: Line 5775:
 [Indirect naming.] [Indirect naming.]
  
-The stream I/O operations in ARexx do not get a parameter which is the name of the file. Instead, ARexx uses an indirect naming scheme. The OPEN() built-in function binds a Rexx stream name for a file to a named file in the AmigaDOS operating system; and later, only the Rexx stream name is used in other stream I/O functions operating on that file.+The stream I/O operations in ARexx do not get a parameter which is the name of the file. Instead, ARexx uses an indirect naming scheme. The OPEN() built-in function binds a REXX stream name for a file to a named file in the AmigaDOS operating system; and later, only the REXX stream name is used in other stream I/O functions operating on that file.
  
 [Special stream names.] [Special stream names.]
Line 5789: Line 5789:
 In ARexx, all files must be explicitly opened. There is no way to reposition line-wise, except for reading lines and keeping a count yourself. In ARexx, all files must be explicitly opened. There is no way to reposition line-wise, except for reading lines and keeping a count yourself.
  
-Of course, ARexx also has a lot of functionality which is not part of standard Rexx, like relative repositioning, explicit opening, an end-of-file indicator, etc. But this functionality is descriptive above in the descriptions of extended built-in functions, and it is of less interest here.+Of course, ARexx also has a lot of functionality which is not part of standard REXX, like relative repositioning, explicit opening, an end-of-file indicator, etc. But this functionality is descriptive above in the descriptions of extended built-in functions, and it is of less interest here.
  
 When an ARexx script has opened a file in Write mode, other ARexx scripts are not allowed to access that file. However, if the file is opened in Read or Append mode, then other ARexx scripts can open the file too, and the same state of the contents of the file is seen by all scripts. When an ARexx script has opened a file in Write mode, other ARexx scripts are not allowed to access that file. However, if the file is opened in Read or Append mode, then other ARexx scripts can open the file too, and the same state of the contents of the file is seen by all scripts.
  
-Note that it is difficult to translate between using standard Rexx stream I/O and ARexx stream I/O. In particular, the main problem (other than missing functionality in one of the systems) is the processing of end-of-lines. In standard Rexx, the end-of-file is detected by checking whether there is more data left, while in ARexx one checks whether the end-of-file has been read. The following is a common standard Rexx idiom:+Note that it is difficult to translate between using standard REXX stream I/O and ARexx stream I/O. In particular, the main problem (other than missing functionality in one of the systems) is the processing of end-of-lines. In standard REXX, the end-of-file is detected by checking whether there is more data left, while in ARexx one checks whether the end-of-file has been read. The following is a common standard REXX idiom:
  
 <code rexx> <code rexx>
Line 5811: Line 5811:
 </code> </code>
  
-It is hard to mechanically translate between them, because of the lack of an EOF() built-in function in standard Rexx, and the lack of a LINES() built-in function in ARexx.+It is hard to mechanically translate between them, because of the lack of an EOF() built-in function in standard REXX, and the lack of a LINES() built-in function in ARexx.
  
 Note that in the ARexx example, an improperly terminated last line is not read as an independent line, since READLN() searches for an end-of-line character sequence. Thus, in the last invocation tmp is set to the last unterminated line, but EOF() returns true too. To make this different, make the UNTIL subterm of the DO loop check for the expression EOF('file') && TMP<>". Note that in the ARexx example, an improperly terminated last line is not read as an independent line, since READLN() searches for an end-of-line character sequence. Thus, in the last invocation tmp is set to the last unterminated line, but EOF() returns true too. To make this different, make the UNTIL subterm of the DO loop check for the expression EOF('file') && TMP<>".
Line 5833: Line 5833:
 BRexx contains a set of I/O which shows very close relations with the C programming language I/O library. In fact, you should consider consulting the C library documentation for in-depth documentation on this functionality. BRexx contains a set of I/O which shows very close relations with the C programming language I/O library. In fact, you should consider consulting the C library documentation for in-depth documentation on this functionality.
  
-BRexx contains a two-level naming scheme: in Rexx, streams are referred to by a stream handle, which is an integer; in the operating system files are referred to by a file name, which is a normal string. The function OPEN() is used to bind a file name to a stream handle. However, BRexx I/O functions generally have the ability to get a reference either as a file name and a stream handle, and open the file if appropriate. However, if the name of a file is an integer which can be interpreted as a file descriptor number, it is interpreted as a descriptor rather than a name. Whenever you use BRexx and want to program robust code, always use OPEN() and the descriptor.+BRexx contains a two-level naming scheme: in REXX, streams are referred to by a stream handle, which is an integer; in the operating system files are referred to by a file name, which is a normal string. The function OPEN() is used to bind a file name to a stream handle. However, BRexx I/O functions generally have the ability to get a reference either as a file name and a stream handle, and open the file if appropriate. However, if the name of a file is an integer which can be interpreted as a file descriptor number, it is interpreted as a descriptor rather than a name. Whenever you use BRexx and want to program robust code, always use OPEN() and the descriptor.
  
 If a file is opened by specifying the name in a I/O operation other than OPEN(), and the name is an integer and only one or two higher than the highest current file descriptor, strange things may happen. If a file is opened by specifying the name in a I/O operation other than OPEN(), and the name is an integer and only one or two higher than the highest current file descriptor, strange things may happen.
Line 6002: Line 6002:
  
  
-===== Extensions and Standard Rexx =====+===== Extensions and Standard REXX =====
  
-In standard Rexx, the OPTIONS instruction provides a "hook" for extensions. It takes any type of parameters, and interprets them in a system-dependent manner.+In standard REXX, the OPTIONS instruction provides a "hook" for extensions. It takes any type of parameters, and interprets them in a system-dependent manner.
  
 The format and legal values of the parameters for the OPTIONS instruction is clearly implementation dependent [TRL2, p62]. The format and legal values of the parameters for the OPTIONS instruction is clearly implementation dependent [TRL2, p62].
Line 6015: Line 6015:
 At the lowest level are these "atomic" extensions. Then there are some "meta-extensions". These are collections of other extensions which belong together in some manner. If you need the extension for creating "buffers" on the stack, it would be logical to use the extension to remove buffers from the stack too. Therefore, all the individual extensions for operations that handle buffers in the stack can be named by such a "meta-extensions". At the end of this chapter, there is a list of all the meta-extensions, and which extensions they include. At the lowest level are these "atomic" extensions. Then there are some "meta-extensions". These are collections of other extensions which belong together in some manner. If you need the extension for creating "buffers" on the stack, it would be logical to use the extension to remove buffers from the stack too. Therefore, all the individual extensions for operations that handle buffers in the stack can be named by such a "meta-extensions". At the end of this chapter, there is a list of all the meta-extensions, and which extensions they include.
  
-At the top is "standards". These are sets of extensions that makes the interpreter behave in a fashion compatible with some standard. Note that "standard" is used very liberally, since it may refer to other implementations of Rexx. However, this description of how the extensions are structured is only followed to some extent. Where practical, the structure has been deviated.+At the top is "standards". These are sets of extensions that makes the interpreter behave in a fashion compatible with some standard. Note that "standard" is used very liberally, since it may refer to other implementations of REXX. However, this description of how the extensions are structured is only followed to some extent. Where practical, the structure has been deviated.
  
  
Line 6022: Line 6022:
 There is one very big problem with extensions. If you want to be able to turn them on and off during execution, then your program has to be a bit careful. There is one very big problem with extensions. If you want to be able to turn them on and off during execution, then your program has to be a bit careful.
  
-More and more Rexx interpreters (including Regina parsing the program when the interpreter is started. The "old" way was to postpone the parsing of each clause until it was actually executed. This leads to the problem mentioned.+More and more REXX interpreters (including Regina parsing the program when the interpreter is started. The "old" way was to postpone the parsing of each clause until it was actually executed. This leads to the problem mentioned.
  
-Suppose you want to use an extension that allows a slightly different syntax, for the sake of the argument, let us assume that you allow an expression after the SELECT keyword. Also assume that this extension is only allowed in extended mode, not in "standard mode". However, since Regina parses the source code only once (typically at the starts of the program), the problem is a catch-22: the extension can only be turned on after parsing the program, but it is needed before parsing. This also applies to a lot of other Rexx interpreters, and all Rexx compilers and preprocessors.+Suppose you want to use an extension that allows a slightly different syntax, for the sake of the argument, let us assume that you allow an expression after the SELECT keyword. Also assume that this extension is only allowed in extended mode, not in "standard mode". However, since Regina parses the source code only once (typically at the starts of the program), the problem is a catch-22: the extension can only be turned on after parsing the program, but it is needed before parsing. This also applies to a lot of other REXX interpreters, and all REXX compilers and preprocessors.
  
 If the extension is not turned on during parsing, it will generate a syntax error, but the parsing is all done before the first clause is executed. Consequently, this extension can not be turned on during execution, it has to be set before the parsing starts. If the extension is not turned on during parsing, it will generate a syntax error, but the parsing is all done before the first clause is executed. Consequently, this extension can not be turned on during execution, it has to be set before the parsing starts.
  
-Therefore, there are two alternative ways to invoke a set of extensions before the Rexx program is parsed:+Therefore, there are two alternative ways to invoke a set of extensions before the REXX program is parsed:
  
 It can be invoked by setting an environment variable, which must be a string of the same format as the parameters to the OPTIONS clause. Regina supports this mechanism by the use of the REGINA_OPTIONS environment variable. It can be invoked by setting an environment variable, which must be a string of the same format as the parameters to the OPTIONS clause. Regina supports this mechanism by the use of the REGINA_OPTIONS environment variable.
Line 6036: Line 6036:
 ===== The Format of the OPTIONS clause ===== ===== The Format of the OPTIONS clause =====
  
-The format of the OPTIONS clause is very simple, it is followed by any Rexx string expression, which is interpreted as a set of space separated words. The words are treated strictly in order from left to right, and each word can change zero or more extension settings.+The format of the OPTIONS clause is very simple, it is followed by any REXX string expression, which is interpreted as a set of space separated words. The words are treated strictly in order from left to right, and each word can change zero or more extension settings.
  
 Each extension has a name. If the word being treated matches that name, that extension will be turned on. However, if the word being treated matches the name of an extension but has the prefix NO, then that extension is turned off. If the word does not match any extensions, then it is simply ignored, without creating any errors or raising any conditions. Each extension has a name. If the word being treated matches that name, that extension will be turned on. However, if the word being treated matches the name of an extension but has the prefix NO, then that extension is turned off. If the word does not match any extensions, then it is simply ignored, without creating any errors or raising any conditions.
Line 6157: Line 6157:
 [STRICT_ANSI] [STRICT_ANSI]
  
-This OPTION results in interpretation of a program to strict ANSI standards, and will reject any Regina extensions. NOSTRICT_ANSI is the default. As this OPTION affects the initial parsing of the Rexx program, it must be specified using the REGINA_OPTIONS environment variable or the '-o' command line switch.+This OPTION results in interpretation of a program to strict ANSI standards, and will reject any Regina extensions. NOSTRICT_ANSI is the default. As this OPTION affects the initial parsing of the REXX program, it must be specified using the REGINA_OPTIONS environment variable or the '-o' command line switch.
  
 [STRICT_WHITE_SPACE_COMPARISONS] [STRICT_WHITE_SPACE_COMPARISONS]
Line 6209: Line 6209:
 [CMS] [CMS]
  
-A set of extensions that stems from the VM/CMS operating system. Basically, this includes the most common extensions in the VM/CMS version of Rexx, in addition of some functions that perform tasks normally done with commands under VM/CMS.+A set of extensions that stems from the VM/CMS operating system. Basically, this includes the most common extensions in the VM/CMS version of REXX, in addition of some functions that perform tasks normally done with commands under VM/CMS.
  
 [VMS] [VMS]
  
-A set of interface functions to the VMS operating system. Basically, this makes the Rexx programming under VMS as powerful as programming directly in DCL.+A set of interface functions to the VMS operating system. Basically, this makes the REXX programming under VMS as powerful as programming directly in DCL.
  
 [UNIX] [UNIX]
Line 6224: Line 6224:
  
  
-The following table shows which options are available in different Rexx Language Levels, and the default settings applicable for Regina.+The following table shows which options are available in different REXX Language Levels, and the default settings applicable for Regina.
  
 [ANSI] [ANSI]
  
-Rexx Language level 5.0, as described in [ANSI].+REXX Language level 5.0, as described in [ANSI].
  
 [REGINA] [REGINA]
  
-Rexx Language level 5.0, plus extensions, as implemented by Regina 3.1 and above.+REXX Language level 5.0, plus extensions, as implemented by Regina 3.1 and above.
  
 [SAA] [SAA]
  
-Rexx Language level ??, as defined by IBM's System Application Architecture [SAA].+REXX Language level ??, as defined by IBM's System Application Architecture [SAA].
  
 [TRL1] [TRL1]
  
-Rexx Language level 3.50, as described in [TRL1].+REXX Language level 3.50, as described in [TRL1].
  
 [TRL2] [TRL2]
  
-Rexx Language level 4.00, as described in [TRL2].+REXX Language level 4.00, as described in [TRL2].
  
 ^ Option ^ ANSI ^ REGINA ^ SAA ^ TRL1 ^ TRL2 ^ ^ Option ^ ANSI ^ REGINA ^ SAA ^ TRL1 ^ TRL2 ^
Line 6272: Line 6272:
 ====== The Stack ====== ====== The Stack ======
  
-In this chapter, the stack and operations manipulating the stack are discussed. Since the stack is external to the Rexx language, there are large differences between implementations with respect to the stack. These differences are attempted described in the latter part of this chapter.+In this chapter, the stack and operations manipulating the stack are discussed. Since the stack is external to the REXX language, there are large differences between implementations with respect to the stack. These differences are attempted described in the latter part of this chapter.
  
 Another goal of this chapter is to try to describe both the "real" standards and some of the most commonly used de facto standards related to stack operation. Where something is not a part of any defined standard, this is clearly labelled. Also, some liberties have been taken in order to create a coherent vocabulary on a field where very little standardization has taken place. Another goal of this chapter is to try to describe both the "real" standards and some of the most commonly used de facto standards related to stack operation. Where something is not a part of any defined standard, this is clearly labelled. Also, some liberties have been taken in order to create a coherent vocabulary on a field where very little standardization has taken place.
Line 6279: Line 6279:
 ===== Background and history ===== ===== Background and history =====
  
-In the various definitions of Rexx, there are numerous references to the "stack" (often called the "external data queue", or just the "queue"). It is a structure capable of storing information, but it is not a part of the Rexx language itself. Rather, it is a part of the external environment supporting a Rexx implementation.+In the various definitions of REXX, there are numerous references to the "stack" (often called the "external data queue", or just the "queue"). It is a structure capable of storing information, but it is not a part of the REXX language itself. Rather, it is a part of the external environment supporting a REXX implementation.
  
-Originally, the references to the stack was introduced into Rexx because of the strong binding between Rexx and IBM mainframes in the early history of Rexx [BMARKS]. Most (all?) of the operating systems for these machines support a stack, and many of their script programming idioms involve the stack. Therefore, it was quite natural to introduce an interface to the stack into Rexx, and consequently today many of the programming paradigms of Rexx involve a stack.+Originally, the references to the stack was introduced into REXX because of the strong binding between REXX and IBM mainframes in the early history of REXX [BMARKS]. Most (all?) of the operating systems for these machines support a stack, and many of their script programming idioms involve the stack. Therefore, it was quite natural to introduce an interface to the stack into REXX, and consequently today many of the programming paradigms of REXX involve a stack.
  
-Unfortunately, this introduced an element of incompatibility into Rexx, as the stack is not in general supported for other operating systems. Consequently, Rexx implementers often must implement a stack as well of the core Rexx interpreter. Since no authoritative definition of the stack exists, considerable differences between various implementations. Ironically, although the stack was introduced to help communication between separate programs, the interpreter-specific implementations of stacks may actually be a hindrance against compatibility between different interpreters.+Unfortunately, this introduced an element of incompatibility into REXX, as the stack is not in general supported for other operating systems. Consequently, REXX implementers often must implement a stack as well of the core REXX interpreter. Since no authoritative definition of the stack exists, considerable differences between various implementations. Ironically, although the stack was introduced to help communication between separate programs, the interpreter-specific implementations of stacks may actually be a hindrance against compatibility between different interpreters.
  
-The stack may have "seemed like a good idea at the time", but in hindsight, it was probably a bad move, since it made Rexx more dependent on the host operating system and its interfaces.+The stack may have "seemed like a good idea at the time", but in hindsight, it was probably a bad move, since it made REXX more dependent on the host operating system and its interfaces.
  
  
Line 6302: Line 6302:
 There exists a way of counting the number of strings currently stored in the stack. There exists a way of counting the number of strings currently stored in the stack.
  
-A stack is often compared with the pile of plates you often find in cantinas. It allows you to either add new plates at the top of the pile or take old plates from the top. When a plate is taken from the pile, it will be the most recently plate (that is still present) added to the pile. Stack operating in Rexx works the same way, although it also allows "plates" to be added to the bottom of the pile.+A stack is often compared with the pile of plates you often find in cantinas. It allows you to either add new plates at the top of the pile or take old plates from the top. When a plate is taken from the pile, it will be the most recently plate (that is still present) added to the pile. Stack operating in REXX works the same way, although it also allows "plates" to be added to the bottom of the pile.
  
 There might be an implementation-specific limit on the length and number of strings stored in the stack. Ideally, the maximum length will be fairly large, at least 2%%**%%16, although some implementations are likely to enforce shorter limits. Similarly, there might be a limit on the number of strings that can be simultaneously stored in the stack. Ideally, there should be no such limit. There might be an implementation-specific limit on the length and number of strings stored in the stack. Ideally, the maximum length will be fairly large, at least 2%%**%%16, although some implementations are likely to enforce shorter limits. Similarly, there might be a limit on the number of strings that can be simultaneously stored in the stack. Ideally, there should be no such limit.
Line 6312: Line 6312:
 This documentation use the term "string", while "line" is in common use elsewhere. The term is used because the strings in the stack are not inherently interpreted as lines (having an implied end-of-line), only as a string. This documentation use the term "string", while "line" is in common use elsewhere. The term is used because the strings in the stack are not inherently interpreted as lines (having an implied end-of-line), only as a string.
  
-Note that the stack itself is not a part of Rexx, only the parts which interface to the stack.+Note that the stack itself is not a part of REXX, only the parts which interface to the stack.
  
 Example: Using the stack to transfer parameters Example: Using the stack to transfer parameters
  
-This is a common Rexx idiom used in several situations for special parameter passing. The following code illustrates its use:+This is a common REXX idiom used in several situations for special parameter passing. The following code illustrates its use:
  
 <code rexx> <code rexx>
Line 6359: Line 6359:
 ==== Using multiple buffers in the stack ==== ==== Using multiple buffers in the stack ====
  
-The concept of buffers and everything directly related to buffers lay without the domain of standard Rexx. Thus, this section describes a de facto standard.+The concept of buffers and everything directly related to buffers lay without the domain of standard REXX. Thus, this section describes a de facto standard.
  
 Note that Regina supports multiple buffers only in internal stacks. Note that Regina supports multiple buffers only in internal stacks.
Line 6397: Line 6397:
 Example: Process all strings in the stack Example: Process all strings in the stack
  
-This is a common Rexx idiom, where a loop iterates over all the strings currently in the stack, but otherwise leave the stack untouched. Supposing the routine PROCESS() exists, and do to processing with its parameter and return the processed string:+This is a common REXX idiom, where a loop iterates over all the strings currently in the stack, but otherwise leave the stack untouched. Supposing the routine PROCESS() exists, and do to processing with its parameter and return the processed string:
  
 <code rexx> <code rexx>
Line 6445: Line 6445:
 ==== Creating new stacks ==== ==== Creating new stacks ====
  
-The description of multiple stack operations in this section, is not part of standard Rexx, nor is it implemented in Regina. Thus, this section describes a de facto standard and you may find that few implementations support these operations.+The description of multiple stack operations in this section, is not part of standard REXX, nor is it implemented in Regina. Thus, this section describes a de facto standard and you may find that few implementations support these operations.
  
-Just as the operations described above let the Rexx programmer use multiple buffers within one stack, there exists another set of operations which let the programmer create multiple stacks. There is really nothing fancy about this, except that a command will swap the stack the interpreter correctly uses with another stack.+Just as the operations described above let the REXX programmer use multiple buffers within one stack, there exists another set of operations which let the programmer create multiple stacks. There is really nothing fancy about this, except that a command will swap the stack the interpreter correctly uses with another stack.
  
-To the interpreter this is really equivalent to a situation where a command empties the current stack, and sets up a new stack. When one stack is empty, and the Rexx program tries to read from the stack, the request will not "overflow" to the previous stack (as requests to an empty buffer "overflows" to the previous buffer). Thus, the use of multiple stacks has even less direct impact on Rexx interpreters than multiple buffers.+To the interpreter this is really equivalent to a situation where a command empties the current stack, and sets up a new stack. When one stack is empty, and the REXX program tries to read from the stack, the request will not "overflow" to the previous stack (as requests to an empty buffer "overflows" to the previous buffer). Thus, the use of multiple stacks has even less direct impact on REXX interpreters than multiple buffers.
  
 Here, it is instructive to list the commands operating multiple stacks that exists. This list has been taken from the MVS environment, according to [REXXSAA]. Here, it is instructive to list the commands operating multiple stacks that exists. This list has been taken from the MVS environment, according to [REXXSAA].
Line 6463: Line 6463:
 [QBUF] [QBUF]
  
-Counts the number of buffers in the current stack, and returns that number as the return value. A Rexx program starting this command can retrieve this value as the special variable RC.+Counts the number of buffers in the current stack, and returns that number as the return value. A REXX program starting this command can retrieve this value as the special variable RC.
  
 [QELEM] [QELEM]
  
-Counts the number of strings (i.e. elements) in the current stack, and returns that value as the return value of the command. This value can be retrieved in Rexx as the special variable RC. This operation is equivalent to the QUEUED() built-in function in Rexx; it has been probably included for the benefit of other script languages that have less functionality than Rexx.+Counts the number of strings (i.e. elements) in the current stack, and returns that value as the return value of the command. This value can be retrieved in REXX as the special variable RC. This operation is equivalent to the QUEUED() built-in function in REXX; it has been probably included for the benefit of other script languages that have less functionality than REXX.
  
 [QSTACK] [QSTACK]
  
-Counts the number of stacks (including the current stack) and returns the value as the return value from the command. This number can be retrieved in Rexx as the special variable RC.+Counts the number of stacks (including the current stack) and returns the value as the return value from the command. This number can be retrieved in REXX as the special variable RC.
  
 One can regard multiple buffers and stacks as two ways of insulating the stack; where multiple stacks are a deeper and more insulating method than buffers. Note that each stack can contain multiple buffers, while a buffer can not contain any stacks. The term "hard buffers" has been used about multiple stacks, as opposed to normal buffers, which are sometimes called "soft buffers". One can regard multiple buffers and stacks as two ways of insulating the stack; where multiple stacks are a deeper and more insulating method than buffers. Note that each stack can contain multiple buffers, while a buffer can not contain any stacks. The term "hard buffers" has been used about multiple stacks, as opposed to normal buffers, which are sometimes called "soft buffers".
  
-Also note that neither multiple stacks nor buffers are part of standard Rexx, so you might come across implementations that support only multiple stacks, only buffers, or even none of them.+Also note that neither multiple stacks nor buffers are part of standard REXX, so you might come across implementations that support only multiple stacks, only buffers, or even none of them.
  
 Example: Counting the number of buffers Example: Counting the number of buffers
Line 6489: Line 6489:
  
  
-===== The interface between Rexx and the stack =====+===== The interface between REXX and the stack =====
  
 As defined in TRL, the interface to the stack consists of the PARSE PULL, PULL, PUSH, and QUEUE instructions; and the QUEUED() built-in function. As defined in TRL, the interface to the stack consists of the PARSE PULL, PULL, PUSH, and QUEUE instructions; and the QUEUED() built-in function.
Line 6497: Line 6497:
 ===== Strategies for implementing stacks ===== ===== Strategies for implementing stacks =====
  
-As mentioned, stacks are rarely a part of the operating system. Therefore, under most operating systems, Rexx interpreters have to implement their own stacks. There are several strategies for doing this, some which are listed below.+As mentioned, stacks are rarely a part of the operating system. Therefore, under most operating systems, REXX interpreters have to implement their own stacks. There are several strategies for doing this, some which are listed below.
  
 [In the operating system.] [In the operating system.]
  
-This is of course "the right way" to do it. However, it requires that the definition of the operating system is such that stacks are supported. Currently, only IBM mainframe-based systems support stack, together with a few other systems that have included stacks as a consequence of making Rexx a main scripting language (Amiga and OS/2 come to mind).+This is of course "the right way" to do it. However, it requires that the definition of the operating system is such that stacks are supported. Currently, only IBM mainframe-based systems support stack, together with a few other systems that have included stacks as a consequence of making REXX a main scripting language (Amiga and OS/2 come to mind).
  
 [As a device driver.] [As a device driver.]
Line 6565: Line 6565:
 In Regina, the stack is implemented as both an integral, private part of the interpreter and as a cross-platform external stack able to be used by multiple clients on multiple machines. Internal stacks provide the obvious advantage of speed at the expense of data sharing. External stacks are considerably slower, but do enable data sharing between instances of Regina and/or other programs. In Regina, the stack is implemented as both an integral, private part of the interpreter and as a cross-platform external stack able to be used by multiple clients on multiple machines. Internal stacks provide the obvious advantage of speed at the expense of data sharing. External stacks are considerably slower, but do enable data sharing between instances of Regina and/or other programs.
  
-Regina supports the standard TRL (and ANSI) Rexx stack interface functionality, like PARSE PULL, PULL, QUEUE, PUSH, the QUEUED() built-in function, and in future versions, support the SAA API stack interface. These commands and functions operate on both the internal and external stacks.+Regina supports the standard TRL (and ANSI) REXX stack interface functionality, like PARSE PULL, PULL, QUEUE, PUSH, the QUEUED() built-in function, and in future versions, support the SAA API stack interface. These commands and functions operate on both the internal and external stacks.
  
 ==== Implementation of the internal stack in Regina 2.2 and above ==== ==== Implementation of the internal stack in Regina 2.2 and above ====
  
-Whenever the Rexx programmer wants to execute a command and let that command either flush the output to the internal stack, or read its input from the internal stack, this has to be arranged by the interpreter itself. In Regina this is normally done by pre pending or appending certain terms to the command to be executed.+Whenever the REXX programmer wants to execute a command and let that command either flush the output to the internal stack, or read its input from the internal stack, this has to be arranged by the interpreter itself. In Regina this is normally done by pre pending or appending certain terms to the command to be executed.
  
 Consider the following command clauses for Regina: Consider the following command clauses for Regina:
Line 6596: Line 6596:
 Note that this particular form of redirection of command input and output will most probably disappear in future versions of Regina, where it will probably be replaced by an extended ADDRESS instruction. Note that this particular form of redirection of command input and output will most probably disappear in future versions of Regina, where it will probably be replaced by an extended ADDRESS instruction.
  
-In addition to the ANSI standard, there are a few extra built-in functions, which are supposed to provide compatibility with other Rexx implementations, principally CMS Rexx. These are BUFTYPE, DESBUF, DROPBUF and MAKEBUF. See the descriptions of these function in the built-in functions section above.+In addition to the ANSI standard, there are a few extra built-in functions, which are supposed to provide compatibility with other REXX implementations, principally CMS REXX. These are BUFTYPE, DESBUF, DROPBUF and MAKEBUF. See the descriptions of these function in the built-in functions section above.
  
 ==== Implementation of the external stack in Regina 2.2 and above ==== ==== Implementation of the external stack in Regina 2.2 and above ====
  
-The implementation of the external stack follows the model used by OS/2 Rexx, but is implemented as an operating system daemon. This daemon is rxstack.+The implementation of the external stack follows the model used by OS/2 REXX, but is implemented as an operating system daemon. This daemon is rxstack.
  
 === rxstack === === rxstack ===
Line 6634: Line 6634:
 the following switches are applicable to Windows 2000 and above the following switches are applicable to Windows 2000 and above
  
--install installs the NT Service; Rexx Stack - Windows 2000 and above only+-install installs the NT Service; REXX Stack - Windows 2000 and above only
  
--start starts the NT Service; Rexx Stack - Windows 2000 and above only+-start starts the NT Service; REXX Stack - Windows 2000 and above only
  
--stop stops the NT Service; Rexx Stack - Windows 2000 and above only+-stop stops the NT Service; REXX Stack - Windows 2000 and above only
  
--remove stops and removes the NT Service; Rexx -Stack - Windows 2000 and above only+-remove stops and removes the NT Service; REXX -Stack - Windows 2000 and above only
  
 -d runs rxstack in a command prompt which then allows non-service related switches - Windows 2000 and above only -d runs rxstack in a command prompt which then allows non-service related switches - Windows 2000 and above only
Line 6648: Line 6648:
 === rxqueue === === rxqueue ===
  
-To allow non-Rexx program to interface to the rxstack daemon, a companion program; rxqueue, is provided. rxqueue communicates with non-Rexx programs via its stdin and stdout.+To allow non-REXX program to interface to the rxstack daemon, a companion program; rxqueue, is provided. rxqueue communicates with non-REXX programs via its stdin and stdout.
  
 Consider the following equivalents for Regina's internal and external stack Consider the following equivalents for Regina's internal and external stack
Line 6679: Line 6679:
 queue is a Regina external queue name – see Queue Names for structure. If no queue is specified, rxqueue uses the queue name; SESSION queue is a Regina external queue name – see Queue Names for structure. If no queue is specified, rxqueue uses the queue name; SESSION
  
-action is one of the following – as per OS/2 Rexx+action is one of the following – as per OS/2 REXX
  
 /fifo queue lines from stdin LIFO onto the queue /fifo queue lines from stdin LIFO onto the queue
Line 6697: Line 6697:
 === rxqueue Built-in Function === === rxqueue Built-in Function ===
  
-Rexx programs communicate with rxstack via the normal queueing mechanisms of QUEUE, PUSH, PULL and QUEUED(). These commands operate on the current queue and have no mechanism for changing the queue to use. This is whereRXQUEUE() is used. Its primary purpose is to control the queue that the remainder of the Rexx program operates on.+REXX programs communicate with rxstack via the normal queueing mechanisms of QUEUE, PUSH, PULL and QUEUED(). These commands operate on the current queue and have no mechanism for changing the queue to use. This is whereRXQUEUE() is used. Its primary purpose is to control the queue that the remainder of the REXX program operates on.
  
 === Queue Names ‌ === === Queue Names ‌ ===
  
-To enable the use of the Rexx stack as a cross-platform, multi-machine IPC, the naming conventions adopted by OS/2 Rexx has been modified. As OS/2 Rexx queues are local to a single machine, queue names have no structure. To enable identification of queues on different machines, some structure must be built into external queue names on Regina. An external queue name on Regina has the following format:+To enable the use of the REXX stack as a cross-platform, multi-machine IPC, the naming conventions adopted by OS/2 REXX has been modified. As OS/2 REXX queues are local to a single machine, queue names have no structure. To enable identification of queues on different machines, some structure must be built into external queue names on Regina. An external queue name on Regina has the following format:
  
 <code> <code>
Line 6715: Line 6715:
 port The port number that rxstack on machine is listening to. The default port number for rxstack is 5757. port The port number that rxstack on machine is listening to. The default port number for rxstack is 5757.
  
-When referring to queues on the local machine, the machine and port components need not be specified. The behaviour of the external stack is then the same as for OS/2 Rexx, with the exception that the queues on the local machine can still be manipulated by Regina on another machine.+When referring to queues on the local machine, the machine and port components need not be specified. The behaviour of the external stack is then the same as for OS/2 REXX, with the exception that the queues on the local machine can still be manipulated by Regina on another machine.
  
 Some examples may make this clearer. TBD Some examples may make this clearer. TBD
Line 6729: Line 6729:
 RXQUEUE RXSTACK RXQUEUE RXSTACK
  
-====== Interfacing Rexx to other programs ======+====== Interfacing REXX to other programs ======
  
-This chapter describes an interface between a Rexx interpreter and another program, typically written in C or another high level, compiled language. It is intended for application programmers who are implementing Rexx support in their programs. It describes the interface known as the Rexx SAA API.+This chapter describes an interface between a REXX interpreter and another program, typically written in C or another high level, compiled language. It is intended for application programmers who are implementing REXX support in their programs. It describes the interface known as the REXX SAA API.
  
  
Line 6744: Line 6744:
 External function handlers External function handlers
  
-extend the Rexx language with external functions+extend the REXX language with external functions
  
 Interpreting Interpreting
  
-Rexx scripts, either from a disk file, or from memory.+REXX scripts, either from a disk file, or from memory.
  
 Variable interface Variable interface
Line 6782: Line 6782:
 ==== Include Files and Libraries ==== ==== Include Files and Libraries ====
  
-All the C code that uses the Rexx application interface, must include a special header file that contains the necessary definitions. This file is called rexxsaa.h. Where you will find this file, will depend on you system and which compiler you use.+All the C code that uses the REXX application interface, must include a special header file that contains the necessary definitions. This file is called rexxsaa.h. Where you will find this file, will depend on you system and which compiler you use.
  
-Also, the interface part between the application and the Rexx interpreter may be implemented as a library, which you link with the application using the functions described in this chapter. The name of this library, and its location might differ from system to system. Under Unix, this library is implemented as a static (libregina.a) or dynamic library (libregina.[so|sl]). Under other platforms the Regina library is also implemented as a static or dynamic library.+Also, the interface part between the application and the REXX interpreter may be implemented as a library, which you link with the application using the functions described in this chapter. The name of this library, and its location might differ from system to system. Under Unix, this library is implemented as a static (libregina.a) or dynamic library (libregina.[so|sl]). Under other platforms the Regina library is also implemented as a static or dynamic library.
  
 ==== Preprocessor Symbols ==== ==== Preprocessor Symbols ====
Line 6810: Line 6810:
 INCL_RXSHV INCL_RXSHV
  
-Must be set in order to get the prototypes, symbols and datatype definitions necessary to use the Rexx variable pool.+Must be set in order to get the prototypes, symbols and datatype definitions necessary to use the REXX variable pool.
  
 INCL_RXQUEUE INCL_RXQUEUE
  
-Must be set in order to get the prototypes, symbols and datatype definitions necessary to use the Rexx external queues.+Must be set in order to get the prototypes, symbols and datatype definitions necessary to use the REXX external queues.
  
 INCL_RXMACRO INCL_RXMACRO
  
-Must be set in order to get the prototypes, symbols and datatype definitions necessary to use the Rexx macrospace interface of the API.+Must be set in order to get the prototypes, symbols and datatype definitions necessary to use the REXX macrospace interface of the API.
  
 ==== Data structures and data types ==== ==== Data structures and data types ====
  
-In this section, some data structures and datatypes relevant to the application interface to Rexx are defined and described. The datatypes defined are:+In this section, some data structures and datatypes relevant to the application interface to REXX are defined and described. The datatypes defined are:
  
 RXSTRING RXSTRING
  
-Holds a Rexx string.+Holds a REXX string.
  
 RXSYSEXIT RXSYSEXIT
  
-Holds a definition of a system exit handler. Used when starting a Rexx script with RexxStart(), and when defining the system exit handlers.+Holds a definition of a system exit handler. Used when starting a REXX script with RexxStart(), and when defining the system exit handlers.
  
 The datatypes used in the SAA API are defined in rexxsaa.h. They are:  The datatypes used in the SAA API are defined in rexxsaa.h. They are: 
Line 6858: Line 6858:
 === The RXSTRING structured === === The RXSTRING structured ===
  
-The SAA API interface uses Rexx string which are stored in the structure RXSTRING. There is also a datatype PRXSTRING, which is a pointer to RXSTRING. Their definitions are:+The SAA API interface uses REXX string which are stored in the structure RXSTRING. There is also a datatype PRXSTRING, which is a pointer to RXSTRING. Their definitions are:
  
 <code c> <code c>
Line 6868: Line 6868:
 </code> </code>
  
-The strptr field is a pointer to an array of characters making up the contents of the Rexx string', while strlength holds the number of characters in that array.+The strptr field is a pointer to an array of characters making up the contents of the REXX string', while strlength holds the number of characters in that array.
  
-Unfortunately, there are some inconsistencies in naming of various special kinds of strings. In Rexx (TRL), a ''null string'' is a string that has zero length. On the other hand, the SAA API operates with two kinds of special strings: null strings and zero length strings. The latter is a string with zero length (equals null strings in Rexx), while the former is a sort of undefined or empty string, which denotes a string without a value. The null strings of SAA API are used to denote unspecified values (e.g. a parameter left out in a subroutine call). In this chapter, when the terms null strings and zero length strings are italicized, they refer to the SAA API style meaning.+Unfortunately, there are some inconsistencies in naming of various special kinds of strings. In REXX (TRL), a ''null string'' is a string that has zero length. On the other hand, the SAA API operates with two kinds of special strings: null strings and zero length strings. The latter is a string with zero length (equals null strings in REXX), while the former is a sort of undefined or empty string, which denotes a string without a value. The null strings of SAA API are used to denote unspecified values (e.g. a parameter left out in a subroutine call). In this chapter, when the terms null strings and zero length strings are italicized, they refer to the SAA API style meaning.
  
 A number of macros are defined, which simplifies operations on RXSTRINGs for the programmer. In the list below, all parameters called x are of type RXSTRING. A number of macros are defined, which simplifies operations on RXSTRINGs for the programmer. In the list below, all parameters called x are of type RXSTRING.
Line 6942: Line 6942:
 ===== The Subcommand Handler Interface ===== ===== The Subcommand Handler Interface =====
  
-This sections describes the subcommand handler interface, which enables the application to trap commands in a Rexx script being executed and handle these commands itself.+This sections describes the subcommand handler interface, which enables the application to trap commands in a REXX script being executed and handle these commands itself.
  
 ==== What is a Subcommand Handler ==== ==== What is a Subcommand Handler ====
  
-A subcommand handler is a piece of code that is called to handle a command to an external environment in Rexx. It must be either a subroutine in the application that started the interpreter, or a subroutine in a dynamic link library. In any case, when the interpreter needs to execute a command to an external environment, it will call the subcommand handler, passing the command as a parameter.+A subcommand handler is a piece of code that is called to handle a command to an external environment in REXX. It must be either a subroutine in the application that started the interpreter, or a subroutine in a dynamic link library. In any case, when the interpreter needs to execute a command to an external environment, it will call the subcommand handler, passing the command as a parameter.
  
-Typically, an application will set up a subcommand handler before starting a Rexx script. That way, it can trap and handle any command being executed during the course of the script.+Typically, an application will set up a subcommand handler before starting a REXX script. That way, it can trap and handle any command being executed during the course of the script.
  
 Each subcommand handler handles one environment, which is referred to by a name. It seems to be undefined whether upper and lower case letters differ in the environment name, so you should assume they differ. Also, there might be an upper limit for the length of an environment name, and some letters may be illegal as part of an environment name. Each subcommand handler handles one environment, which is referred to by a name. It seems to be undefined whether upper and lower case letters differ in the environment name, so you should assume they differ. Also, there might be an upper limit for the length of an environment name, and some letters may be illegal as part of an environment name.
Line 6964: Line 6964:
 [command] [command]
  
-The command string that is to be executed. This is the resulting string after the command expression has been evaluated in the Rexx interpreter. It can not be empty, although it can be a zero-length-string.+The command string that is to be executed. This is the resulting string after the command expression has been evaluated in the REXX interpreter. It can not be empty, although it can be a zero-length-string.
  
 [flags] [flags]
Line 6980: Line 6980:
 ==== The RexxRegisterSubcomExe() function ==== ==== The RexxRegisterSubcomExe() function ====
  
-This function is used to register a subcommand handler with the interface. The subcommand handler must be a procedure located within the code of the application. After registration, the Rexx interpreter can execute subcommands by calling the subcommand handler with parameters describing the subcommand.+This function is used to register a subcommand handler with the interface. The subcommand handler must be a procedure located within the code of the application. After registration, the REXX interpreter can execute subcommands by calling the subcommand handler with parameters describing the subcommand.
  
 The prototype for RexxRegisterSubcomExe() is: The prototype for RexxRegisterSubcomExe() is:
Line 6992: Line 6992:
 [EnvName] [EnvName]
  
-Points to an ASCII NUL terminated character string which defines the name of the environment to be registered. This is the same name as the Rexx interpreter uses with the ADDRESS clause in order to select an external environment.+Points to an ASCII NUL terminated character string which defines the name of the environment to be registered. This is the same name as the REXX interpreter uses with the ADDRESS clause in order to select an external environment.
  
 [EntryPoint] [EntryPoint]
Line 7028: Line 7028:
 ==== The RexxRegisterSubcomDll() function ==== ==== The RexxRegisterSubcomDll() function ====
  
-This function is used to set up a routine that is located in a module in a dynamic link library, as a subcommand handler. After registration, the Rexx interpreter can execute subcommands by calling the subcommand handler with parameters describing the subcommand.+This function is used to set up a routine that is located in a module in a dynamic link library, as a subcommand handler. After registration, the REXX interpreter can execute subcommands by calling the subcommand handler with parameters describing the subcommand.
  
 Some operating systems don't have dynamic linking, and thus cannot make use of this facility. The prototype of this function is: Some operating systems don't have dynamic linking, and thus cannot make use of this facility. The prototype of this function is:
Line 7040: Line 7040:
 [EnvName] [EnvName]
  
-Points to an ASCII NUL terminated character string which defines the name of the environment to be registered. This is the same name as the Rexx interpreter uses with the ADDRESS clause in order to select an external environment.+Points to an ASCII NUL terminated character string which defines the name of the environment to be registered. This is the same name as the REXX interpreter uses with the ADDRESS clause in order to select an external environment.
  
 [ModuleName] [ModuleName]
Line 7168: Line 7168:
 ===== The External Function Handler Interface ===== ===== The External Function Handler Interface =====
  
-This sections describes the external function handler interface, which extends the language by enabling external functions to be written in a language other than Rexx.+This sections describes the external function handler interface, which extends the language by enabling external functions to be written in a language other than REXX.
  
 ==== What is an External Function Handler ==== ==== What is an External Function Handler ====
  
-An external function handler is a piece of code, that is called to handle external functions and subroutine calls in Rexx. It must be either a subroutine in the application that started the interpreter, or a subroutine in a dynamic link library. In any case, when the interpreter needs to execute a function registered as an external function, it will call the external function handler, passing the function name as a parameter.+An external function handler is a piece of code, that is called to handle external functions and subroutine calls in REXX. It must be either a subroutine in the application that started the interpreter, or a subroutine in a dynamic link library. In any case, when the interpreter needs to execute a function registered as an external function, it will call the external function handler, passing the function name as a parameter.
  
-All external functions written in a language other than Rexx must be registered with the interpreter before starting a Rexx script.+All external functions written in a language other than REXX must be registered with the interpreter before starting a REXX script.
  
 An external function handler can handle one or more functions. The handler can determine the function actually called by examining one of the parameters passed to the handler and act accordingly. An external function handler can handle one or more functions. The handler can determine the function actually called by examining one of the parameters passed to the handler and act accordingly.
Line 7210: Line 7210:
 ==== The RexxRegisterFunctionExe() function ==== ==== The RexxRegisterFunctionExe() function ====
  
-This function is used to register an external function handler with the interface. The external function handler must be a procedure located within the code of the application. After registration, the Rexx interpreter can execute external functions as if they were built-ins.+This function is used to register an external function handler with the interface. The external function handler must be a procedure located within the code of the application. After registration, the REXX interpreter can execute external functions as if they were built-ins.
  
 The prototype for RexxRegisterFunctionExe() is: The prototype for RexxRegisterFunctionExe() is:
Line 7222: Line 7222:
 [FuncName] [FuncName]
  
-Points to an ASCII NUL terminated character string which defines the name of the external function to be registered. This is the same name as the Rexx interpreter uses with a function call or via the CALL command.+Points to an ASCII NUL terminated character string which defines the name of the external function to be registered. This is the same name as the REXX interpreter uses with a function call or via the CALL command.
  
 [EntryPoint] [EntryPoint]
Line 7260: Line 7260:
 [ExternalName] [ExternalName]
  
-Points to an ASCII NUL terminated character string which defines the name of the external function to be registered. This is the same name as the Rexx interpreter uses with a function call or via the CALL command.+Points to an ASCII NUL terminated character string which defines the name of the external function to be registered. This is the same name as the REXX interpreter uses with a function call or via the CALL command.
  
 [LibraryName] [LibraryName]
Line 7306: Line 7306:
 [FuncName] [FuncName]
  
-Points to an ASCII NUL terminated character string which defines the name of the external function to be registered. This is the same name as the Rexx interpreter uses with a function call or via the CALL command.+Points to an ASCII NUL terminated character string which defines the name of the external function to be registered. This is the same name as the REXX interpreter uses with a function call or via the CALL command.
  
 The list of defined function handlers is searched, and if an environment matching the one named by the parameter are found, it is deleted. This call is used to de-register function handlers registered with either RexxRegisterFunctionExe() or RexxRegisterFunctionDll(). The list of defined function handlers is searched, and if an environment matching the one named by the parameter are found, it is deleted. This call is used to de-register function handlers registered with either RexxRegisterFunctionExe() or RexxRegisterFunctionDll().
Line 7334: Line 7334:
 [FuncName] [FuncName]
  
-Points to an ASCII NUL terminated character string which defines the name of the external function to be registered. This is the same name as the Rexx interpreter uses with a function call or via the CALL command.+Points to an ASCII NUL terminated character string which defines the name of the external function to be registered. This is the same name as the REXX interpreter uses with a function call or via the CALL command.
  
 The returned value from RexxQueryFunction() can be one of: The returned value from RexxQueryFunction() can be one of:
Line 7346: Line 7346:
 The handler was not found. The handler was not found.
  
-===== Executing Rexx Code =====+===== Executing REXX Code =====
  
  
-This sections describes the RexxStart() function, which allows the application to startup the interpreter and make it interpret pieces of Rexx code.+This sections describes the RexxStart() function, which allows the application to startup the interpreter and make it interpret pieces of REXX code.
  
 ==== The RexxStart() function ==== ==== The RexxStart() function ====
  
-This function is used to invoke the Rexx interpreter in order to execute a piece of Rexx code, which may be located on disk, as a pre-tokenized macro, or as ASCII source code in memory.+This function is used to invoke the REXX interpreter in order to execute a piece of REXX code, which may be located on disk, as a pre-tokenized macro, or as ASCII source code in memory.
  
 <code c> <code c>
Line 7363: Line 7363:
 [ArgCount] [ArgCount]
  
-The number of parameter strings given to the procedure. This is the number of defined Rexx-strings pointed to by the ArgList parameter. The default maximum number of arguments that can be passed is 32, but this can be changed by the MAX_ARGS_TO_REXXSTART macro in rexx.h.+The number of parameter strings given to the procedure. This is the number of defined REXX-strings pointed to by the ArgList parameter. The default maximum number of arguments that can be passed is 32, but this can be changed by the MAX_ARGS_TO_REXXSTART macro in rexx.h.
  
 [ArgList] [ArgList]
  
-Pointer to an array of Rexx-strings, constituting the parameters to this call to Rexx. The size of this array is given by the parameter ArgCount. If ArgCount is greater than one, the first and last parameters are ArgList[0] and ArgList[ArgCount-1]. If ArgCount is 0, the value of ArgList is irrelevant.+Pointer to an array of REXX-strings, constituting the parameters to this call to REXX. The size of this array is given by the parameter ArgCount. If ArgCount is greater than one, the first and last parameters are ArgList[0] and ArgList[ArgCount-1]. If ArgCount is 0, the value of ArgList is irrelevant.
  
 If the strptr of one of the elements in the array pointed to by ArgList is NULL, that means that this parameter is empty (i.e. unspecified, as opposed to a string of zero size). If the strptr of one of the elements in the array pointed to by ArgList is NULL, that means that this parameter is empty (i.e. unspecified, as opposed to a string of zero size).
Line 7373: Line 7373:
 [ProgramName] [ProgramName]
  
-An ASCII NUL terminated string, specifying the name of the Rexx script to be executed. The value of Instore will determine whether this value is interpreted as the name of a (on-disk) script, or a pre-tokenized macro. If it refers to a filename, the syntax of the contents of this parameter depends on the operating system.+An ASCII NUL terminated string, specifying the name of the REXX script to be executed. The value of Instore will determine whether this value is interpreted as the name of a (on-disk) script, or a pre-tokenized macro. If it refers to a filename, the syntax of the contents of this parameter depends on the operating system.
  
 [Instore] [Instore]
  
-Parameter used for storing tokenized Rexx scripts. This parameter might either be NULL, else it will be a pointer to two RXSTRING structures, the first holding the ASCII version of a Rexx program, the other holding the tokenized version of that program. See below for more information about how to use Instore.+Parameter used for storing tokenized REXX scripts. This parameter might either be NULL, else it will be a pointer to two RXSTRING structures, the first holding the ASCII version of a REXX program, the other holding the tokenized version of that program. See below for more information about how to use Instore.
  
 [EnvName] [EnvName]
Line 7385: Line 7385:
 [CallType] [CallType]
  
-A value describing whether the Rexx interpreter is to be invoked in command, function or subroutine mode. Actually, this has little significance. The main difference is that in command mode, only one parameter string can be passed, and in function mode, a value must be returned. In addition, the mode chosen will affect the output of the PARSE SOURCE instruction in Rexx.+A value describing whether the REXX interpreter is to be invoked in command, function or subroutine mode. Actually, this has little significance. The main difference is that in command mode, only one parameter string can be passed, and in function mode, a value must be returned. In addition, the mode chosen will affect the output of the PARSE SOURCE instruction in REXX.
  
 [Exits] [Exits]
Line 7401: Line 7401:
 [Result] [Result]
  
-Points to a Rexx string into which the result string is written. The caller may or may not let the strptr field be supplied. If supplied (i.e. it is non-NULL), that area will be used, else a new area will be allocated. If the supplied area is used, its size is supposed to be given by the strlength field. If the size if not sufficient, a new area will be allocated, by RexxAllocateMemory(), and the caller must see to that it is properly de-allocated using RexxFreeMemory().+Points to a REXX string into which the result string is written. The caller may or may not let the strptr field be supplied. If supplied (i.e. it is non-NULL), that area will be used, else a new area will be allocated. If the supplied area is used, its size is supposed to be given by the strlength field. If the size if not sufficient, a new area will be allocated, by RexxAllocateMemory(), and the caller must see to that it is properly de-allocated using RexxFreeMemory().
  
 Regina allows the value of this parameter to be NULL if the user is not interested in it. Regina allows the value of this parameter to be NULL if the user is not interested in it.
Line 7409: Line 7409:
 The Instore parameter needs some special attention. It is used to directly or indirectly specify where to fetch the code to execute. The following algorithm is used to determine what to execute: The Instore parameter needs some special attention. It is used to directly or indirectly specify where to fetch the code to execute. The following algorithm is used to determine what to execute:
  
-If Instore is NULL, then ProgramName names the filename of an on-disk Rexx script which it to be read and executed.+If Instore is NULL, then ProgramName names the filename of an on-disk REXX script which it to be read and executed.
  
 Else, if Instore is not NULL, the script is somewhere in memory, and no reading from disk is performed. If both Instore[0].strptr and Instore[1].strptr are NULL, then the script to execute is a pre-loaded macro which must have been loaded with a call to either RexxAddMacro() or RexxLoadMacroSpace(); and ProgName is the name of the macro to execute. Else, if Instore is not NULL, the script is somewhere in memory, and no reading from disk is performed. If both Instore[0].strptr and Instore[1].strptr are NULL, then the script to execute is a pre-loaded macro which must have been loaded with a call to either RexxAddMacro() or RexxLoadMacroSpace(); and ProgName is the name of the macro to execute.
  
-Else, if Instore[1].strptr is non-NULL, then Instore[1] contains the pre-tokenized image of a Rexx script, and it is used for the execution.+Else, if Instore[1].strptr is non-NULL, then Instore[1] contains the pre-tokenized image of a REXX script, and it is used for the execution.
  
-Else, if Instore[0].strptr is non-NULL, then Instore[0]} contains the ASCII image of a Rexx script, just as if the script had been read directly from the disk (i.e. including linefeeds and such). This image is passed to the interpreter, which tokenizes it, and stores the tokenized script in the Instore[1] string, and then proceeds to execute that script. Upon return, the Instore[1] will be set, and can later be used to re-execute the script within the same process, without the overhead of tokenizing.+Else, if Instore[0].strptr is non-NULL, then Instore[0]} contains the ASCII image of a REXX script, just as if the script had been read directly from the disk (i.e. including linefeeds and such). This image is passed to the interpreter, which tokenizes it, and stores the tokenized script in the Instore[1] string, and then proceeds to execute that script. Upon return, the Instore[1] will be set, and can later be used to re-execute the script within the same process, without the overhead of tokenizing.
  
 The user is responsible for de-allocating any storage used by Instore[1]. Note that after tokenizing, the source code in Instore[0] is strictly speaking not needed anymore. It will only be consulted if the user calls the SOURCELINE() built-in function. It is not an error to use SOURCELINE() if the source is not present, but nullstring and zero will be returned. The user is responsible for de-allocating any storage used by Instore[1]. Note that after tokenizing, the source code in Instore[0] is strictly speaking not needed anymore. It will only be consulted if the user calls the SOURCELINE() built-in function. It is not an error to use SOURCELINE() if the source is not present, but nullstring and zero will be returned.
  
-To tokenise a Rexx script and save it for execution by a later execution by RexxStart() either in the currently running process or outside the current process, you need to call RexxStart() with the following arguments:+To tokenise a REXX script and save it for execution by a later execution by RexxStart() either in the currently running process or outside the current process, you need to call RexxStart() with the following arguments:
  
 ^ Parameter ^ Value ^ Notes ^ ^ Parameter ^ Value ^ Notes ^
Line 7426: Line 7426:
 | ArgList.strptr | %%//T%% | | | ArgList.strptr | %%//T%% | |
 | ProgramName |  | Ignored | | ProgramName |  | Ignored |
-| Instore[0].strptr | ASCII image of Rexx script | |+| Instore[0].strptr | ASCII image of REXX script | |
 | Instrore[0].strlength | Length of Instore[0].strptr | | | Instrore[0].strlength | Length of Instore[0].strptr | |
 | Instrore[1].strptr | Ignored | This will be populated with the tokenised code. | | Instrore[1].strptr | Ignored | This will be populated with the tokenised code. |
Line 7441: Line 7441:
 [Negative] [Negative]
  
-indicates that a syntax error occurred during interpretation. In general, you can expect the error value to have the same absolute value as the Rexx syntax error (but opposite signs, of course).+indicates that a syntax error occurred during interpretation. In general, you can expect the error value to have the same absolute value as the REXX syntax error (but opposite signs, of course).
  
 [Zero] [Zero]
Line 7453: Line 7453:
 During the course of an execution of RexxStart(), subcommand handlers and exit handlers might be called. These may call any function in the application interface, including another invocation of RexxStart(). During the course of an execution of RexxStart(), subcommand handlers and exit handlers might be called. These may call any function in the application interface, including another invocation of RexxStart().
  
-Often, the application programmer is interested in providing support simplifying the specification of filenames, like an environment variable search path or a default file type. The Rexx interface does support a default file type: .CMD, but the user may not set this to anything else. Therefore, it is generally up to the application programmer to handle search paths, and also default file types (unless .CMD is OK).+Often, the application programmer is interested in providing support simplifying the specification of filenames, like an environment variable search path or a default file type. The REXX interface does support a default file type: .CMD, but the user may not set this to anything else. Therefore, it is generally up to the application programmer to handle search paths, and also default file types (unless .CMD is OK).
  
 If the initial environment name (EvnName) is NULL, then the initial environment during interpretation will be set equal to the file type of the script to execute. If the script does not have a file type, it is probably set to some interpreter specific value. If the initial environment name (EvnName) is NULL, then the initial environment during interpretation will be set equal to the file type of the script to execute. If the script does not have a file type, it is probably set to some interpreter specific value.
Line 7459: Line 7459:
 ===== Variable Pool Interface ===== ===== Variable Pool Interface =====
  
-This section describes the variable pool part of the application interface, which allows the application programmer to set, retrieve and drop variables in the Rexx interpreter from the application program. It also allows access to other information.+This section describes the variable pool part of the application interface, which allows the application programmer to set, retrieve and drop variables in the REXX interpreter from the application program. It also allows access to other information.
  
 The C preprocessor symbol INCL_RXSHV must be defined if the definitions for the variable pool interface are to be made available when rexxsaa.h is included. The C preprocessor symbol INCL_RXSHV must be defined if the definitions for the variable pool interface are to be made available when rexxsaa.h is included.
Line 7480: Line 7480:
  
  
-All requests to manipulate the Rexx variable pool are controlled by a structure which is called SHVBLOCK, having the definition:+All requests to manipulate the REXX variable pool are controlled by a structure which is called SHVBLOCK, having the definition:
  
 <code c> <code c>
Line 7550: Line 7550:
 Successive requests for RXSHV_NEXTV will traverse the interpreter's internal data structure for storing variables, and return a new pair of variable name and value for each request. Each variable that is visible in the current scope, is returned once and only once, but the order is non-deterministic. Successive requests for RXSHV_NEXTV will traverse the interpreter's internal data structure for storing variables, and return a new pair of variable name and value for each request. Each variable that is visible in the current scope, is returned once and only once, but the order is non-deterministic.
  
-When all available variables in the Rexx interpreter have already been retrieved, subsequent RXSHV_NEXTV requests will set the flag RXSHV_LVAR in the shvret field. There are a few restrictions. The traversal will be reset whenever the interpreter resumes execution, so an incomplete traversal can not be continued in a later external function, exit handler, or subcommand handler. Also, any set, fetch or drop operation will reset the traversal. These restrictions have been added to ensure that the variable pool is static throughout one traversal.+When all available variables in the REXX interpreter have already been retrieved, subsequent RXSHV_NEXTV requests will set the flag RXSHV_LVAR in the shvret field. There are a few restrictions. The traversal will be reset whenever the interpreter resumes execution, so an incomplete traversal can not be continued in a later external function, exit handler, or subcommand handler. Also, any set, fetch or drop operation will reset the traversal. These restrictions have been added to ensure that the variable pool is static throughout one traversal.
  
 [RXSHV_PRIV] [RXSHV_PRIV]
Line 7576: Line 7576:
 [PARM] [PARM]
  
-Returns the ASCII representation of the number of parameters to the currently active Rexx procedure. This may not be the same value as the built-in function ARG() returns, but is the number ArgCount in RexxStart(). The two might differ if a routine was called with trailing omitted parameters.+Returns the ASCII representation of the number of parameters to the currently active REXX procedure. This may not be the same value as the built-in function ARG() returns, but is the number ArgCount in RexxStart(). The two might differ if a routine was called with trailing omitted parameters.
  
 [PARM.n] [PARM.n]
Line 7588: Line 7588:
 [SOURCE] [SOURCE]
  
-Returns the same string that is used in the PARSE SOURCE clause in Rexx, at the current procedure level of interpretation.+Returns the same string that is used in the PARSE SOURCE clause in REXX, at the current procedure level of interpretation.
  
 [VERSION] [VERSION]
  
-Returns the same string that is used in the PARSE VERSION clause in Rexx.+Returns the same string that is used in the PARSE VERSION clause in REXX.
  
 The value returned by a variable pool request is a bit uncommon. A return value is computed for each request, and stored in the shvret field. This is a one-byte field, of which the most significant bit is never set. A symbolic value RXSHV_OK is defined as the value zero, and the shvret field will be equal to this name if none if the flags listed below is set. The symbolic value for these flags are: The value returned by a variable pool request is a bit uncommon. A return value is computed for each request, and stored in the shvret field. This is a one-byte field, of which the most significant bit is never set. A symbolic value RXSHV_OK is defined as the value zero, and the shvret field will be equal to this name if none if the flags listed below is set. The symbolic value for these flags are:
Line 7632: Line 7632:
 RXSHV_BADN is returned if the supplied shvname contains a value that is not legal in this context. For the symbolic set, fetch and drop operations, that means a symbol that is a legal variable name; both upper and lower case letters are allowed. For the direct set, fetch and drop operations, that means a variable name after normalization and tail substitution is not a legal variable name. For RXSHV_PRIV, it must be one of the values listed above. RXSHV_BADN is returned if the supplied shvname contains a value that is not legal in this context. For the symbolic set, fetch and drop operations, that means a symbol that is a legal variable name; both upper and lower case letters are allowed. For the direct set, fetch and drop operations, that means a variable name after normalization and tail substitution is not a legal variable name. For RXSHV_PRIV, it must be one of the values listed above.
  
-There is a small subtlety in the above description. TRL states that when a Rexx assignment assigns a value to a stem variable, all possible variables having that stem are assigned a new value (independent of whether they had an explicit value before). So, strictly speaking, if a stem is set, then a RXSHV_NEXTV sequence should return an (almost) infinite sequence of compound variables for that stem. Of course, that is completely useless, so you can assume that only compound variables of that stem given an explicit value after the stem was assigned a value will be returned by RXSHV_NEXTV. However, because of that subtlety, the variables returned by RXSHV_NEXTV for compound variables might not be representative for the state of the variables.+There is a small subtlety in the above description. TRL states that when a REXX assignment assigns a value to a stem variable, all possible variables having that stem are assigned a new value (independent of whether they had an explicit value before). So, strictly speaking, if a stem is set, then a RXSHV_NEXTV sequence should return an (almost) infinite sequence of compound variables for that stem. Of course, that is completely useless, so you can assume that only compound variables of that stem given an explicit value after the stem was assigned a value will be returned by RXSHV_NEXTV. However, because of that subtlety, the variables returned by RXSHV_NEXTV for compound variables might not be representative for the state of the variables.
  
-e.g. what would a sequence of RXSHV_NEXT requests return after the following Rexx code: +e.g. what would a sequence of RXSHV_NEXT requests return after the following REXX code: 
  
 <code rexx> <code rexx>
Line 7689: Line 7689:
 ===== The System Exit Handler Interface ===== ===== The System Exit Handler Interface =====
  
-The exit handlers provide a mechanism for governing important aspects of the Rexx interpreter from the application: It can trap situations like the interpreter writing out text, and then handle them itself, e.g. by displaying the text in a special window. You can regard system exits as a sort of hooks.+The exit handlers provide a mechanism for governing important aspects of the REXX interpreter from the application: It can trap situations like the interpreter writing out text, and then handle them itself, e.g. by displaying the text in a special window. You can regard system exits as a sort of hooks.
  
 ==== The System Exit Handler ‌ ==== ==== The System Exit Handler ‌ ====
Line 7732: Line 7732:
 The RXFNC system exit handler provides hooks for external functions. It has only one subfunction; RXFNCCAL, which allows an application program to intervene and handle any external function or subroutine. The RXFNC system exit handler provides hooks for external functions. It has only one subfunction; RXFNCCAL, which allows an application program to intervene and handle any external function or subroutine.
  
-Do not confuse this exit handler with the external function routines which allow you to define new Rexx, semi-built-in functions. The exit handler is called for all invocations of external routines, and can be called for function names which you were unaware of.+Do not confuse this exit handler with the external function routines which allow you to define new REXX, semi-built-in functions. The exit handler is called for all invocations of external routines, and can be called for function names which you were unaware of.
  
  
Line 7859: Line 7859:
 === RXMSQ - The External Data Queue Exit Handler === === RXMSQ - The External Data Queue Exit Handler ===
  
-The external data queue exit handler is used as a hook for operations manipulating the external data queue (or the stack). Unfortunately, the stack is a borderline case of what is relevant to the Rexx SAA API. Operations like putting something on, retrieving a string from, obtaining the size, etc. of the stack is not part of the SAA API.+The external data queue exit handler is used as a hook for operations manipulating the external data queue (or the stack). Unfortunately, the stack is a borderline case of what is relevant to the REXX SAA API. Operations like putting something on, retrieving a string from, obtaining the size, etc. of the stack is not part of the SAA API.
  
 However, some of this functionality is seemingly here; but not all. For instance for the RXMSQPLL subfunction, SAA API is called by the interpreter before the interpreter calls whatever system-specific call is available for retrieving a string from the stack. However, some of this functionality is seemingly here; but not all. For instance for the RXMSQPLL subfunction, SAA API is called by the interpreter before the interpreter calls whatever system-specific call is available for retrieving a string from the stack.
Line 7942: Line 7942:
 Called whenever the interpreter need to read from the standard input stream during a PULL or PARSE PULL instruction. Note that it will not be called if there is sufficient data on the stack to satisfy the operation. Called whenever the interpreter need to read from the standard input stream during a PULL or PARSE PULL instruction. Note that it will not be called if there is sufficient data on the stack to satisfy the operation.
  
-Note that these function are only called for the exact situations that are listed above. e.g. the RXSIOSAY is not called during a call to the Rexx built-in function LINEOUT() that writes to the default output stream. TRL says that SAY is identical to calling LINEOUT() for the standard output stream, but SAA API still manages to see the difference between stem variables and compound variables with a ``zero-length-string'' tail. Please bear with this inconsistency.+Note that these function are only called for the exact situations that are listed above. e.g. the RXSIOSAY is not called during a call to the REXX built-in function LINEOUT() that writes to the default output stream. TRL says that SAY is identical to calling LINEOUT() for the standard output stream, but SAA API still manages to see the difference between stem variables and compound variables with a ``zero-length-string'' tail. Please bear with this inconsistency.
  
 Depending on the subfunction, the ParmBlock parameter will have four only slightly different definitions. It is kind of frustrating that the ParmBlock takes so many different datatypes, but it can be handled easily using unions, see a later section. The definitions are: Depending on the subfunction, the ParmBlock parameter will have four only slightly different definitions. It is kind of frustrating that the ParmBlock takes so many different datatypes, but it can be handled easily using unions, see a later section. The definitions are:
Line 7972: Line 7972:
 === RXHLT - The Halt Condition Exit Handler === === RXHLT - The Halt Condition Exit Handler ===
  
-Note: Because the RXHLT exit handler is called after every Rexx instruction, enabling this exit slows Rexx program execution.+Note: Because the RXHLT exit handler is called after every REXX instruction, enabling this exit slows REXX program execution.
  
 The main code for this exit handler has the symbolic value RXHLT. There are two sub-functions:  The main code for this exit handler has the symbolic value RXHLT. There are two sub-functions: 
Line 7978: Line 7978:
 [RXHLTTST] [RXHLTTST]
  
-Called whenever the interpreter polls externally raised HALT conditions; i.e. after every Rexx instruction.+Called whenever the interpreter polls externally raised HALT conditions; i.e. after every REXX instruction.
  
 The definition of the ParmBlock is:  The definition of the ParmBlock is: 
Line 8002: Line 8002:
 RXTER and this exit handler are a bit different from the others. RXINI provides the application programmer with a method of getting control before the execution of the script starts. Its main purpose is to enable manipulation of the variable pool in order to set up certain variables before the script starts, or set the trace mode. RXTER and this exit handler are a bit different from the others. RXINI provides the application programmer with a method of getting control before the execution of the script starts. Its main purpose is to enable manipulation of the variable pool in order to set up certain variables before the script starts, or set the trace mode.
  
-It has only one subfunction, RXINIEXT, called once during each call to RexxStart(): just before the first Rexx statement is interpreted. Variable manipulations performed during this exit will have effect when the script starts.+It has only one subfunction, RXINIEXT, called once during each call to RexxStart(): just before the first REXX statement is interpreted. Variable manipulations performed during this exit will have effect when the script starts.
  
 As there is no information to be communicated during this exit, the value of ParmBlock is undefined. It makes no difference whether you return RXEXIT_HANDLED or RXEXIT_NOT_HANDLED, since there is no situation to handle. As there is no information to be communicated during this exit, the value of ParmBlock is undefined. It makes no difference whether you return RXEXIT_HANDLED or RXEXIT_NOT_HANDLED, since there is no situation to handle.
Line 8008: Line 8008:
 === RXTER - The Termination Exit Handler === === RXTER - The Termination Exit Handler ===
  
-This exit resembles RXINI. Its sole subfunction is RXTEREXT, which is called once, just after the last statement of the Rexx script has been interpreted. The state of all variables are intact during this call; so it can be used to retrieve the values of the variables at the exit of a script. (In fact, that is the whole purpose of this exit handler.)+This exit resembles RXINI. Its sole subfunction is RXTEREXT, which is called once, just after the last statement of the REXX script has been interpreted. The state of all variables are intact during this call; so it can be used to retrieve the values of the variables at the exit of a script. (In fact, that is the whole purpose of this exit handler.)
  
 Like RXINI, there is no information to be communicated during the exit, so ParamBlock is undefined in this call. And also like RXINI, it is more of a hook than an exit handler, so it does not matter whether you return RXEXIT_HANDLED or RXEXIT_NOT_HANDLED. Like RXINI, there is no information to be communicated during the exit, so ParamBlock is undefined in this call. And also like RXINI, it is more of a hook than an exit handler, so it does not matter whether you return RXEXIT_HANDLED or RXEXIT_NOT_HANDLED.
Line 8014: Line 8014:
 === RXENV - The External Environment Exit Handler === === RXENV - The External Environment Exit Handler ===
  
-This System Exit is specific to Regina, so caution should be exercised if you plan on making your code portable to other Rexx interpreters.+This System Exit is specific to Regina, so caution should be exercised if you plan on making your code portable to other REXX interpreters.
  
 The main code for this exit handler has the symbolic value RXENV. There are four sub-functions:  The main code for this exit handler has the symbolic value RXENV. There are four sub-functions: 
Line 8057: Line 8057:
 ==== The RexxRegisterExitExe() function ==== ==== The RexxRegisterExitExe() function ====
  
-This function is used to register a system exit handler with the interface. The system exit handler must be a procedure located within the code of the application. After registration, the Rexx interpreter will execute the system exit handler when the approriate event is triggered in the interpreter.+This function is used to register a system exit handler with the interface. The system exit handler must be a procedure located within the code of the application. After registration, the REXX interpreter will execute the system exit handler when the approriate event is triggered in the interpreter.
  
 The prototype for RexxRegisterExitExe() is: The prototype for RexxRegisterExitExe() is:
Line 8113: Line 8113:
 ==== The RexxRegisterExitDll() function ==== ==== The RexxRegisterExitDll() function ====
  
-This function is used to set up a routine that is located in a module in a dynamic link library, as a system exit handler. After registration, the Rexx interpreter will execute the system exit handler when the approriate event is triggered in the interpreter.+This function is used to set up a routine that is located in a module in a dynamic link library, as a system exit handler. After registration, the REXX interpreter will execute the system exit handler when the approriate event is triggered in the interpreter.
  
 Some operating systems don't have dynamic linking, and thus cannot make use of this facility. The prototype of this function is: Some operating systems don't have dynamic linking, and thus cannot make use of this facility. The prototype of this function is:
Line 8250: Line 8250:
 ===== The External Queue Interface ===== ===== The External Queue Interface =====
  
-The external queue interface provide a mechanism for interacting with the interpreter's external queues. This interface is analogous to a Rexx program's use of PUSH, QUEUE, PULL, and RXQUEUE(). Note that this interface only works with the external queues, it cannot interface to the internal named queues that exists within the interpreter.+The external queue interface provide a mechanism for interacting with the interpreter's external queues. This interface is analogous to a REXX program's use of PUSH, QUEUE, PULL, and RXQUEUE(). Note that this interface only works with the external queues, it cannot interface to the internal named queues that exists within the interpreter.
  
 ==== The RexxCreateQueue() function ==== ==== The RexxCreateQueue() function ====
Line 8458: Line 8458:
 ===== The Macro Space Interface ===== ===== The Macro Space Interface =====
  
-The macro space interface provide a mechanism for pre-loading external Rexx programs into the current interpreter's macro space, so that the macros can be executed faster than reading them from disk each time they are called. This interface is not available in Regina at this stage.+The macro space interface provide a mechanism for pre-loading external REXX programs into the current interpreter's macro space, so that the macros can be executed faster than reading them from disk each time they are called. This interface is not available in Regina at this stage.
  
 ==== The RexxAddMacro() function ==== ==== The RexxAddMacro() function ====
Line 8488: Line 8488:
 ===== Allocating and De-allocating Space ===== ===== Allocating and De-allocating Space =====
  
-For several of the functions described in this chapter, the application calling them must allocate or de-allocate dynamic memory. Depending on the operating system, compiler and Rexx interpreter, the method for these allocations and de-allocations vary. Because of this, Regina supplies the API function calls RexxAllocateMemory() and RexxFreeMemory(). These functions are wrappers for the appropriate compiler or operating system memory functions.+For several of the functions described in this chapter, the application calling them must allocate or de-allocate dynamic memory. Depending on the operating system, compiler and REXX interpreter, the method for these allocations and de-allocations vary. Because of this, Regina supplies the API function calls RexxAllocateMemory() and RexxFreeMemory(). These functions are wrappers for the appropriate compiler or operating system memory functions.
  
 ==== The RexxAllocateMemory() function ==== ==== The RexxAllocateMemory() function ====
Line 8523: Line 8523:
 RexxFreeMemory() always return 0. RexxFreeMemory() always return 0.
  
-===== Calling back into running Rexx Code =====+===== Calling back into running REXX Code =====
  
-This section describes the RexxCallBack() function, which allows the application to execute a procedure within the running Rexx program. This function is particularly useful for building a Rexx interface to those library applications that operate using a callback mechanism.+This section describes the RexxCallBack() function, which allows the application to execute a procedure within the running REXX program. This function is particularly useful for building a REXX interface to those library applications that operate using a callback mechanism.
  
 A callback mechanism is one where certain events within a particular application can be connected to a particular function, so that when a particular event occurs, the connected function is executed. Many C library applications use a callback mechanism. A callback mechanism is one where certain events within a particular application can be connected to a particular function, so that when a particular event occurs, the connected function is executed. Many C library applications use a callback mechanism.
  
-This function is specific to Regina, so caution should be exercised if you plan on making your code portable to other Rexx interpreters.+This function is specific to Regina, so caution should be exercised if you plan on making your code portable to other REXX interpreters.
  
 ==== The RexxCallBack() function ==== ==== The RexxCallBack() function ====
  
-This function is used to execute an internal procedure within the running Rexx script. The procedure is executed with the same context as if the procedure were called from within the Rexx program as a function call.+This function is used to execute an internal procedure within the running REXX script. The procedure is executed with the same context as if the procedure were called from within the REXX program as a function call.
  
 <code c> <code c>
Line 8543: Line 8543:
 [ProcedureName] [ProcedureName]
  
-An ASCII NUL terminated string, specifying the name of the internal procedure of the running Rexx script to be executed. This internal procedure name must exist or this function will return with RX_CB_BADN.+An ASCII NUL terminated string, specifying the name of the internal procedure of the running REXX script to be executed. This internal procedure name must exist or this function will return with RX_CB_BADN.
  
 [ArgCount] [ArgCount]
  
-The number of parameter strings given to the procedure. This is the number of defined Rexx-strings pointed to by the ArgList parameter. The default maximum number of arguments that can be passed is 32, but this can be changed by the MAX_ARGS_TO_REXXSTART macro in rexx.h.+The number of parameter strings given to the procedure. This is the number of defined REXX-strings pointed to by the ArgList parameter. The default maximum number of arguments that can be passed is 32, but this can be changed by the MAX_ARGS_TO_REXXSTART macro in rexx.h.
  
 [ArgList] [ArgList]
  
-Pointer to an array of Rexx-strings, constituting the parameters to this call to Rexx. The size of this array is given by the parameter ArgCount. If ArgCount is greater than one, the first and last parameters are ArgList[0] and ArgList[ArgCount-1]. If ArgCount is 0, the value of ArgList is irrelevant.+Pointer to an array of REXX-strings, constituting the parameters to this call to REXX. The size of this array is given by the parameter ArgCount. If ArgCount is greater than one, the first and last parameters are ArgList[0] and ArgList[ArgCount-1]. If ArgCount is 0, the value of ArgList is irrelevant.
  
 If the strptr of one of the elements in the array pointed to by ArgList is NULL, that means that this parameter is empty (i.e. unspecified, as opposed to a string of zero size). If the strptr of one of the elements in the array pointed to by ArgList is NULL, that means that this parameter is empty (i.e. unspecified, as opposed to a string of zero size).
Line 8563: Line 8563:
 [Result] [Result]
  
-Points to a Rexx string into which the result string from the called ProcedureName is written. The caller may or may not let the strptr field be supplied. If supplied (i.e. it is non-NULL), that area will be used, else a new area will be allocated. If the supplied area is used, its size is supposed to be given by the strlength field. If the size if not sufficient, a new area will be allocated, by RexxAllocateMemory(), and the caller must see to that it is properly de-allocated using RexxFreeMemory().+Points to a REXX string into which the result string from the called ProcedureName is written. The caller may or may not let the strptr field be supplied. If supplied (i.e. it is non-NULL), that area will be used, else a new area will be allocated. If the supplied area is used, its size is supposed to be given by the strlength field. If the size if not sufficient, a new area will be allocated, by RexxAllocateMemory(), and the caller must see to that it is properly de-allocated using RexxFreeMemory().
  
 Regina allows the value of this parameter to be NULL if the user is not interested in it. Regina allows the value of this parameter to be NULL if the user is not interested in it.
Line 8573: Line 8573:
 [Negative] [Negative]
  
-indicates that a syntax error occurred during interpretation. In general, you can expect the error value to have the same absolute value as the Rexx syntax error (but opposite signs, of course).+indicates that a syntax error occurred during interpretation. In general, you can expect the error value to have the same absolute value as the REXX syntax error (but opposite signs, of course).
  
 [Zero, or RX_CB_OK] [Zero, or RX_CB_OK]
Line 8583: Line 8583:
 indicates probably that some problem occurred, that made it impossible to execute the procedure, e.g. a bad parameter value. The values that can be return are: RX_CB_BADP bad parameters indicates probably that some problem occurred, that made it impossible to execute the procedure, e.g. a bad parameter value. The values that can be return are: RX_CB_BADP bad parameters
  
-RX_CB_NOTSTARTED there is no running Rexx program RX_CB_TOOMANYP too many parameters supplied RX_CB_BADN the ProcedureName does not exist+RX_CB_NOTSTARTED there is no running REXX program RX_CB_TOOMANYP too many parameters supplied RX_CB_BADN the ProcedureName does not exist
  
 During the course of an execution of RexxCallBack(), subcommand handlers and exit handlers might be called. These may call any function in the application interface, including another invocation of RexxCallBack(). During the course of an execution of RexxCallBack(), subcommand handlers and exit handlers might be called. These may call any function in the application interface, including another invocation of RexxCallBack().
Line 8589: Line 8589:
 ====== Implementation Limits ====== ====== Implementation Limits ======
  
-This chapter lists the implementation limits required by the Rexx standard. All implementations are supposed to support at least these limits.+This chapter lists the implementation limits required by the REXX standard. All implementations are supposed to support at least these limits.
  
  
Line 8596: Line 8596:
 Why use implementation limits at all? Often, a program (ab)uses a feature in a language to an extent that the implementor did not foresee. Suppose an implementor decides that variable names can not be longer than 64 bytes. Sooner or later, a programmer gets the idea of using very long variable names to encode special information in the name; maybe as the output of a machine generated program. The result will be a program that works only for some interpreters or only for some problems. Why use implementation limits at all? Often, a program (ab)uses a feature in a language to an extent that the implementor did not foresee. Suppose an implementor decides that variable names can not be longer than 64 bytes. Sooner or later, a programmer gets the idea of using very long variable names to encode special information in the name; maybe as the output of a machine generated program. The result will be a program that works only for some interpreters or only for some problems.
  
-By introducing implementation limits, Rexx tells the implementors to what extent a implementation is required to support certain features, and simultaneously it tells the programmers how much functionality they can assume is present.+By introducing implementation limits, REXX tells the implementors to what extent a implementation is required to support certain features, and simultaneously it tells the programmers how much functionality they can assume is present.
  
 Note that these limited are required minimums for what an implementation must allow. An interpreter is not supposed to enforce these limits unless there is a good reason to. Note that these limited are required minimums for what an implementation must allow. An interpreter is not supposed to enforce these limits unless there is a good reason to.
Line 8607: Line 8607:
 Many interpreters are likely to have "memory" as an implementation limit, meaning that they will allow any size as long as there is enough memory left. Actually, this is equivalent to no limit, since running out of memory is an error with limit enforcing interpreters as well. Some interpreters let the user set the limits, often controlled through the OPTIONS instruction. Many interpreters are likely to have "memory" as an implementation limit, meaning that they will allow any size as long as there is enough memory left. Actually, this is equivalent to no limit, since running out of memory is an error with limit enforcing interpreters as well. Some interpreters let the user set the limits, often controlled through the OPTIONS instruction.
  
-For computers, limit choices are likely to be powers of two, like 256, 1024, 8192, etc. However, the Rexx language takes the side of the user, and defines the limits in units which looks as more "sensible" to computer non-experts: most of the limits in Rexx are numbers like 250, 500, 1000, etc.+For computers, limit choices are likely to be powers of two, like 256, 1024, 8192, etc. However, the REXX language takes the side of the user, and defines the limits in units which looks as more "sensible" to computer non-experts: most of the limits in REXX are numbers like 250, 500, 1000, etc.
  
  
 ===== Required Limits ===== ===== Required Limits =====
  
-These are the implementation minimums defined by Rexx:+These are the implementation minimums defined by REXX:
  
 [Binary strings] [Binary strings]
Line 8671: Line 8671:
 [The stack] [The stack]
  
-(Also called: the external data queue) is not formally defined as a concept of the language itself, but a concept to which the Rexx language has an interface. Several limits might apply to the stack, in particular the maximum length of a line in the stack and the maximum number of lines the stack can hold at once.+(Also called: the external data queue) is not formally defined as a concept of the language itself, but a concept to which the REXX language has an interface. Several limits might apply to the stack, in particular the maximum length of a line in the stack and the maximum number of lines the stack can hold at once.
  
-There might also be also be other limits related to the stack, like a maximum number of buffers or a maximum number of different stack. These concepts are not referred to by Rexx, but the programmer ought to be aware of them.+There might also be also be other limits related to the stack, like a maximum number of buffers or a maximum number of different stack. These concepts are not referred to by REXX, but the programmer ought to be aware of them.
  
 [Files] [Files]
  
-May have several limits not specified by the definition of Rexx, e.g. the number of files simultaneously open, the maximum size of a file, and the length and syntax of file names. Some of these limits are enforced by the operating system rather than an implementation. The programmer should be particularly aware of the maximum number of simultaneously open files, since Rexx does not have a standard construct for closing files.+May have several limits not specified by the definition of REXX, e.g. the number of files simultaneously open, the maximum size of a file, and the length and syntax of file names. Some of these limits are enforced by the operating system rather than an implementation. The programmer should be particularly aware of the maximum number of simultaneously open files, since REXX does not have a standard construct for closing files.
  
 [Expression nesting] [Expression nesting]
Line 8701: Line 8701:
 ===== What an Implementation is Allowed to "Ignore" ===== ===== What an Implementation is Allowed to "Ignore" =====
  
-In order to make the Rexx language implementable on as many machines as possible, the Rexx standard allow implementation to ignore certain features. The existence of these features are recommended, but not required. These features are:+In order to make the REXX language implementable on as many machines as possible, the REXX standard allow implementation to ignore certain features. The existence of these features are recommended, but not required. These features are:
  
 [Floating point numbers] [Floating point numbers]
Line 8709: Line 8709:
 [File operations] [File operations]
  
-Are defined in Rexx, but an implementation seems to be allowed to differ in just about any file operation feature.+Are defined in REXX, but an implementation seems to be allowed to differ in just about any file operation feature.
  
 ===== Limits in Regina ===== ===== Limits in Regina =====
Line 8760: Line 8760:
 Many language interpreters provide a mechanism where code executed within that interpreter is limited to affecting the environment of the interpreter and cannot change the external environment in which the interpreter runs. Many language interpreters provide a mechanism where code executed within that interpreter is limited to affecting the environment of the interpreter and cannot change the external environment in which the interpreter runs.
  
-Restricted mode is used in situations where you need to guarantee that the author of a Rexx program is unable to affect the user's environment.+Restricted mode is used in situations where you need to guarantee that the author of a REXX program is unable to affect the user's environment.
  
 Situations where a restricted mode is applicable include, using Regina as a database procedural language, or as a language plug-in for a Web browser. Situations where a restricted mode is applicable include, using Regina as a database procedural language, or as a language plug-in for a Web browser.
Line 8772: Line 8772:
   * Calling external functions   * Calling external functions
  
-To run Regina in restricted mode, you can start the Regina interpreter from the command line with the '-r' switch, or when using the Rexx SAA API, or-ing RXRESTRICTED to the CallType parameter of RexxStart() function.+To run Regina in restricted mode, you can start the Regina interpreter from the command line with the '-r' switch, or when using the REXX SAA API, or-ing RXRESTRICTED to the CallType parameter of RexxStart() function.
  
  
Line 8801: Line 8801:
 Locale support is very limited in Regina currently. There is no ANSI specification about it and care has been taken to avoid unexpected behaviour for multi-language scripts. The basic intention of the support was the ability to handle special characters in some western locales or on some systems. Locale support is very limited in Regina currently. There is no ANSI specification about it and care has been taken to avoid unexpected behaviour for multi-language scripts. The basic intention of the support was the ability to handle special characters in some western locales or on some systems.
  
-Non-breakable spaces are part of nearly every character set, but they are hard to implement in Rexx programs because of the missing information about the runtime character set when writing the program. Another typical problem came from extra characters in the character sets which allow the translation in some cases. This problem is unsolvable in advance, because some glyphs are characters in one language and they are symbols in other languages. These problems can be solved at runtime only with the knowledge of the country and language.+Non-breakable spaces are part of nearly every character set, but they are hard to implement in REXX programs because of the missing information about the runtime character set when writing the program. Another typical problem came from extra characters in the character sets which allow the translation in some cases. This problem is unsolvable in advance, because some glyphs are characters in one language and they are symbols in other languages. These problems can be solved at runtime only with the knowledge of the country and language.
  
 Regina implements some code which is executed once when the interpreter starts up. This code evaluates the command line parameter or the environment variables and extracts the information about the character set. Note that this operation is not done on a per-thread basis and it is done before any other operation happens. So no change can be done once a program has been loaded into memory and parsed. The use of ADDRESS REXX is recommended for cases where a different character set is required for a called program. Regina implements some code which is executed once when the interpreter starts up. This code evaluates the command line parameter or the environment variables and extracts the information about the character set. Note that this operation is not done on a per-thread basis and it is done before any other operation happens. So no change can be done once a program has been loaded into memory and parsed. The use of ADDRESS REXX is recommended for cases where a different character set is required for a called program.
Line 8809: Line 8809:
   * string comparison if options STRICT_ANSI and STRICT_WHITESPACE_COMPARISON are not set.   * string comparison if options STRICT_ANSI and STRICT_WHITESPACE_COMPARISON are not set.
   * upper-case translation of variable names, see VALUE BIF or the API functions.   * upper-case translation of variable names, see VALUE BIF or the API functions.
-  * white space delimiter detection and elimination at word boundaries or number boundaries at all possible places including cases of reading Rexx programs and processing PARSE operations.+  * white space delimiter detection and elimination at word boundaries or number boundaries at all possible places including cases of reading REXX programs and processing PARSE operations.
   * CASELESS translation in PARSE operations.   * CASELESS translation in PARSE operations.
   * case translation of the builtin functions TRANSLATE, LOWER, UPPER and the instruction   * case translation of the builtin functions TRANSLATE, LOWER, UPPER and the instruction
Line 8820: Line 8820:
 To specify a native language, up to 2 environment variables are used. To specify a native language, up to 2 environment variables are used.
  
-REGINA_LANG environment variable is set to an ISO 639, 2 character language abbreviation as defined in the following table for error messages, optionally followed by a comma and the locale. The locale is explained in Section 1; “Executing Rexx programs With Regina”. The value given at the command line by the parameter "-l" takes precedence if it is given at all, even if the empty string is used.+REGINA_LANG environment variable is set to an ISO 639, 2 character language abbreviation as defined in the following table for error messages, optionally followed by a comma and the locale. The locale is explained in Section 1; “Executing REXX programs With Regina”. The value given at the command line by the parameter "-l" takes precedence if it is given at all, even if the empty string is used.
  
 ^ REGINA_LANG ^ Language ^ Translation By ^ ^ REGINA_LANG ^ Language ^ Translation By ^
Line 8840: Line 8840:
  
  
-===== Rexx and Regina binaries: Why? =====+===== REXX and Regina binaries: Why? =====
  
  
Line 8870: Line 8870:
 Character string is an finite, ordered, and possibly empty set of characters. Character string is an finite, ordered, and possibly empty set of characters.
  
-Clause is a non-empty collection of tokens in a Rexx script. The tokens making up a clause are all the consecutive tokens delimited by two consecutive clause delimiters. [Clauses are further divided into null clauses, instructions, assignments, and commands.]+Clause is a non-empty collection of tokens in a REXX script. The tokens making up a clause are all the consecutive tokens delimited by two consecutive clause delimiters. [Clauses are further divided into null clauses, instructions, assignments, and commands.]
  
-Clause delimiter is a non-empty sequence of elements of a subset of tokens, normally the linefeed and the semicolon. Also the start and end of a Rexx script are considered clause delimiters. Also colon is a clause separator, but it is only valid after a label.+Clause delimiter is a non-empty sequence of elements of a subset of tokens, normally the linefeed and the semicolon. Also the start and end of a REXX script are considered clause delimiters. Also colon is a clause separator, but it is only valid after a label.
  
 Command Command
Line 8890: Line 8890:
 Empty string Empty string
  
-Environment is a interface to which Rexx can route commands and afterwards retrieve status information like return values.+Environment is a interface to which REXX can route commands and afterwards retrieve status information like return values.
  
 Evaluation is the process applied to an expression in order to derive a character string. Evaluation is the process applied to an expression in order to derive a character string.
Line 8902: Line 8902:
 External data queue see "stack". External data queue see "stack".
  
-External subroutine is a script of Rexx code, which is executed as a response to a subroutine or function call that is neither internal nor built-in.+External subroutine is a script of REXX code, which is executed as a response to a subroutine or function call that is neither internal nor built-in.
  
 FIFO FIFO
Line 8914: Line 8914:
 Hexadecimal string is a character string that consists only of the hexadecimal digits, and with optional whitespace to divide the hexadecimal digits into groups. Leading or trailing whitespace is illegal. All groups except the first must consist of an even number of digits. If the first group have an odd number of digits, an extra leading zero is implied under some circumstances. Hexadecimal string is a character string that consists only of the hexadecimal digits, and with optional whitespace to divide the hexadecimal digits into groups. Leading or trailing whitespace is illegal. All groups except the first must consist of an even number of digits. If the first group have an odd number of digits, an extra leading zero is implied under some circumstances.
  
-Instruction is a clause that is recognized by the fact that the first token is a special keyword, and that the clause is not an assignment or label. Instructions typically are well-defined Rexx language components, such as loops and function calls.+Instruction is a clause that is recognized by the fact that the first token is a special keyword, and that the clause is not an assignment or label. Instructions typically are well-defined REXX language components, such as loops and function calls.
  
-Interactive trace is a trace mode, where the interpreter halts execution between each clause, and offer the user the possibility to specify arbitrary Rexx statements to be executed before the execution continues.+Interactive trace is a trace mode, where the interpreter halts execution between each clause, and offer the user the possibility to specify arbitrary REXX statements to be executed before the execution continues.
  
 Label LIFO Label LIFO
Line 8924: Line 8924:
 Literal name is a name which will always be interpreted as a constant, i.e. that no variable substitution will take place. Literal name is a name which will always be interpreted as a constant, i.e. that no variable substitution will take place.
  
-Literal string is a token in a Rexx script, that basically is surrounded by quotation marks, in order to make a character string containing the same characters as the literal string.+Literal string is a token in a REXX script, that basically is surrounded by quotation marks, in order to make a character string containing the same characters as the literal string.
  
 Keyword is a element from finite set of symbols. Keyword is a element from finite set of symbols.
Line 8936: Line 8936:
 Operating system Parameters Parsing Procedure level Operating system Parameters Parsing Procedure level
  
-Program is a collection of Rexx code, which may be zero or more scripts, or other repositories of Rexx code. However, a program must contain a all the code to be executed.+Program is a collection of REXX code, which may be zero or more scripts, or other repositories of REXX code. However, a program must contain a all the code to be executed.
  
 Queue see "external data queue" or "stack". Queue see "external data queue" or "stack".
  
-Routine is a unit during run-time, which is a procedural level. Certain settings are saved across routines. One routine (the caller routine) can be temporarily suspended while another routine is executed (the called routine). With such nesting, the called routine must be terminated before execution of the caller routine can be resumed. Normally, the CALL instruction or a function call is used to do this. Note that the main level of a Rexx script is also a routine.+Routine is a unit during run-time, which is a procedural level. Certain settings are saved across routines. One routine (the caller routine) can be temporarily suspended while another routine is executed (the called routine). With such nesting, the called routine must be terminated before execution of the caller routine can be resumed. Normally, the CALL instruction or a function call is used to do this. Note that the main level of a REXX script is also a routine.
  
-Script is a single file containing Rexx code.+Script is a single file containing REXX code.
  
 Space separated Stack Space separated Stack
Line 8952: Line 8952:
 Subkeyword is a keyword, but the prefix "sub" stresses the fact that a symbol is a keyword only in certain contexts [e.g. inside a particular instruction]. Subkeyword is a keyword, but the prefix "sub" stresses the fact that a symbol is a keyword only in certain contexts [e.g. inside a particular instruction].
  
-Subroutine is a routine which has been invoked from another Rexx routine; i.e. it can not be the "main" program of a Rexx script.+Subroutine is a routine which has been invoked from another REXX routine; i.e. it can not be the "main" program of a REXX script.
  
 Symbol Symbol table Symbol Symbol table
Line 8970: Line 8970:
 norm. bin string packed char string norm. bin string packed char string
  
-Character strings is the only type of data available in Rexx, but to some extent there are 'subtypes' of character strings; character strings which contents has certain format. These special formats is discussed below.+Character strings is the only type of data available in REXX, but to some extent there are 'subtypes' of character strings; character strings which contents has certain format. These special formats is discussed below.
  
  
Line 8993: Line 8993:
 [SYMPOS3] [SYMPOS3]
  
-Proceedings of the Rexx Symposium for Developers and Users. Stanford: Stanford Linear Accelerator Center, 1992+Proceedings of the REXX Symposium for Developers and Users. Stanford: Stanford Linear Accelerator Center, 1992
  
 [TRH:PRICE] [TRH:PRICE]