Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
en:docs:os2:rexx [2024/09/04 06:49] – [Purpose of this document] prokushev | en: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 " | + | 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 " |
===== 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 | + | The following switches allow the user to control how osFree Classic REXX executes the supplied |
< | < | ||
Line 81: | Line 81: | ||
</ | </ | ||
- | 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. |
< | < | ||
Line 124: | Line 124: | ||
</ | </ | ||
- | 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. |
< | < | ||
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 | + | 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 |
===== Definitions ===== | ===== Definitions ===== | ||
- | A program in the Rexx language consists of clauses, which are divided into four groups: null clauses, commands, assignments, | + | A program in the REXX language consists of clauses, which are divided into four groups: null clauses, commands, assignments, |
Incidentally, | Incidentally, | ||
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 | + | The difference between |
<code rexx> | <code rexx> | ||
Line 436: | Line 436: | ||
- | In this section, all instructions in standard | + | In this section, all instructions in standard |
First some notes on the terminology. What is called an instruction in this document is equivalent to a " | First some notes on the terminology. What is called an instruction in this document is equivalent to a " | ||
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 " | + | The environment term must be a symbol or a literal string. If it is a symbol, its " |
<code rexx> | <code rexx> | ||
Line 555: | Line 555: | ||
- | Rexx maintains a list of environments, | + | REXX maintains a list of environments, |
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: | ||
</ | </ | ||
- | 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 | + | 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 |
- | The definition of Rexx says nothing about which environment is preselected when you invoke the interpreter, | + | The definition of REXX says nothing about which environment is preselected when you invoke the interpreter, |
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, | + | In REXX, recursive routines are allowed. A minimum number of 100 nested internal and external subroutine invocations, |
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 " | + | Although similar constructs in other languages typically provokes an overflow at some point, something " |
If the value of NUMERIC DIGITS is 1, then it will " | If the value of NUMERIC DIGITS is 1, then it will " | ||
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, | + | The following algorithm in REXX code shows the execution of a DO instruction, |
<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: | ||
</ | </ | ||
- | 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 " | + | 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 " |
| | RETURN | | | RETURN | ||
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 | + | If terminating an external routine (i.e. returning to the calling |
==== The IF/ | ==== The IF/ | ||
Line 1075: | Line 1075: | ||
</ | </ | ||
- | The INTERPRET instruction is used to dynamically build and execute | + | The INTERPRET instruction is used to dynamically build and execute |
<code rexx> | <code rexx> | ||
Line 1085: | Line 1085: | ||
executes the statement SAY " | executes the statement SAY " | ||
- | 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 | + | 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 |
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: | ||
</ | </ | ||
- | Unfortunately, | + | Unfortunately, |
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: | ||
</ | </ | ||
- | 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 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, |
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, | + | As explained above, |
<code rexx> | <code rexx> | ||
Line 1239: | Line 1239: | ||
</ | </ | ||
- | The OPTIONS instruction is used to set various interpreter-specific options. Its typical uses are to select certain | + | The OPTIONS instruction is used to set various interpreter-specific options. Its typical uses are to select certain |
- | 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. | + | 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. |
<code rexx> | <code rexx> | ||
Line 1247: | Line 1247: | ||
</ | </ | ||
- | 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: |
< | < | ||
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: |
< | < | ||
Line 1320: | Line 1320: | ||
</ | </ | ||
- | 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, | + | 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 second word is the Rexx language level supported by the interpreter. Note that this is not the same as the version of the interpreter, | + | 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, |
The last three words (date, month, and year) makes up the date part of the string. This is the release date of the interpreter, | The last three words (date, month, and year) makes up the date part of the string. This is the release date of the interpreter, | ||
- | 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, | + | Unfortunately, |
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" | + | 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" |
- | 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), | + | 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), |
After the source string has been selected by the type subclause in the PARSE instruction, | After the source string has been selected by the type subclause in the PARSE instruction, | ||
Line 1347: | Line 1347: | ||
</ | </ | ||
- | 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' | + | 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' |
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, | + | The first restriction, |
- | The second restriction is that the PROCEDURE instruction must be the first statement in the subroutine. This restriction was introduced between | + | The second restriction is that the PROCEDURE instruction must be the first statement in the subroutine. This restriction was introduced between |
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, | + | 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, |
Another important drawback with PROCEDURE is that it only works for internal subroutines; | Another important drawback with PROCEDURE is that it only works for internal subroutines; | ||
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, | + | 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, |
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 | + | 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 |
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, | + | A common problem when trying to port REXX code from a TRL2 interpreter to a TRL1 interpreter, |
<code rexx> | <code rexx> | ||
Line 1675: | Line 1675: | ||
</ | </ | ||
- | 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 | + | 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 |
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, | + | 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, |
==== 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, | + | 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, |
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: | ||
</ | </ | ||
- | 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 | + | 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 |
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: | ||
- | ====== | + | ====== |
- | 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 | + | At the end, there is documentation that describes where and how Regina differs from standard |
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 | + | * (EXT-ANSI) Extended |
* (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:// | Definitions of the AREXX built-in functions were taken verbatim in 2003 from http:// | ||
- | Note that in standard | + | Note that in standard |
<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 " | 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 " | ||
- | Note that the following list does not try to classify any general | + | Note that the following list does not try to classify any general |
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, | Depending on the implementation, | ||
- | 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, | 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, | ||
- | SOURCELINE() has been changed between | + | SOURCELINE() has been changed between |
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) ==== | ||
- | | + | |
| 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 " | + | 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 " |
- | Note that under some operating systems, | + | Note that under some operating systems, |
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, | + | 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, |
(Assuming that the file "/ | (Assuming that the file "/ | ||
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 " | + | With only one parameter, this function identifies the " |
If option is specified too, it will check if string is of a particular datatype, and return either " | If option is specified too, it will check if string is of a particular datatype, and return either " | ||
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 " | + | Note that the " |
- | 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(' | | DATE(' | ||
- | The sep_out and sep_in options are extensions to the ANSI standard originally provided by Object | + | The sep_out and sep_in options are extensions to the ANSI standard originally provided by Object |
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,' | | ERRORTEXT(40.24,' | ||
- | 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, | With OPTIONS STRICT_ANSI, | ||
Line 3094: | Line 3094: | ||
==== FORMAT(number [,[before] [,[after] [,[expp] [, | ==== FORMAT(number [,[before] [,[after] [,[expp] [, | ||
- | 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' | + | Returns the fully qualified file name of the REXX program that called the current program. The optional argument level specifies the level in Regina' |
| GETCALLER() | ' | | GETCALLER() | ' | ||
Line 3179: | Line 3179: | ||
==== GETSPACE(length) - (AREXX) ==== | ==== GETSPACE(length) - (AREXX) ==== | ||
- | Allocates a block of memory of the specified length from the interpreter' | + | Allocates a block of memory of the specified length from the interpreter' |
| GETSPACE(32) | ' | | GETSPACE(32) | ' | ||
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, | Whether or not stream must be explicitly opened before a read operation can be performed, is implementation dependent. In many implementations, | ||
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 " | 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 " | ||
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' | + | 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' |
This command is now deprecated. ADDRESS WITH can do the same thing, and can also capture the command' | This command is now deprecated. ADDRESS WITH can do the same thing, and can also capture the command' | ||
Line 3479: | Line 3479: | ||
==== QUEUED() - (ANSI) ==== | ==== QUEUED() - (ANSI) ==== | ||
- | Returns the number of lines currently in the external data queue (the " | + | Returns the number of lines currently in the external data queue (the " |
| QUEUED() | ' | | QUEUED() | ' | ||
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, | + | Note that depending on the implementation, |
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' | 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' | ||
Line 3562: | Line 3562: | ||
==== RXFUNCADD(externalname, | ==== RXFUNCADD(externalname, | ||
- | 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, | + | 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, |
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) | ' | | SIGN(-12) | ' | ||
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, | + | If lineno is unspecified, |
- | 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 | + | 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 |
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() | ' | | SOURCELINE() | ' | ||
- | | 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[, | ==== STREAM(streamid[, | ||
- | 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 | + | 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 |
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, | + | Note that if VALUE() is used to access variables in pools outside the REXX interpreter, |
- | 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, | The valid value of pool in Regina is one of ENVIRONMENT, | ||
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' | + | 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' |
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 " | + | In this chapter, the REXX concept of " |
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, | + | 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, |
- | 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: | For each condition there is a trap which contains three pieces of status information: | ||
- | 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 set the condition handler, append the term "NAME handler" | ||
- | The trap is said to be " | + | The trap is said to be " |
<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 | + | For conditions trapped by method CALL, standard |
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, | + | 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, |
==== 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 | + | Assume that a condition is being trapped by method SIGNAL, that the state is ON and the handler is MYTH_TRAP. The following |
<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 | + | The following |
<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), | + | 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), |
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, | Unfortunately, | ||
- | 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 | + | 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 does not have anything called a standard condition. There just " | + | REXX does not have anything called a standard condition. There just " |
The terms " | The terms " | ||
- | Standard | + | Standard |
- | The values default-action and delay-action are really non-existing in the Standard | + | The values default-action and delay-action are really non-existing in the Standard |
- | 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, | + | 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, |
- | Consequently, | + | Consequently, |
Unfortunately, | Unfortunately, | ||
- | 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, | + | Another extension could have been included, but have been left out so far. It is the delay-action, |
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), | + | 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), |
- | Although | + | Although |
- | 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 " | + | 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 " |
- | Thus, a file has a flavor of persistency, | + | Thus, a file has a flavor of persistency, |
- | In this documentation, | + | In this documentation, |
===== 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, | + | Opening a stream in REXX is generally done automatically, |
<code rexx> | <code rexx> | ||
Line 4987: | Line 4987: | ||
===== Naming Streams ===== | ===== Naming Streams ===== | ||
- | Unlike most programming languages, | + | Unlike most programming languages, |
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, | 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, | ||
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 | + | Also note that standard |
Sometimes the term " | Sometimes the term " | ||
- | 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, | + | 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, |
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: | ||
</ | </ | ||
- | Theoretically, | + | Theoretically, |
Example: Unix temporary files | Example: Unix temporary files | ||
Line 5032: | Line 5032: | ||
</ | </ | ||
- | 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: | ||
</ | </ | ||
- | 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); | + | 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); |
Whether an implementation treats ././foo and ./foo as different streams is system-dependent; | Whether an implementation treats ././foo and ./foo as different streams is system-dependent; | ||
- | 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, | are typically not available for random access or repeated retrieval, either because it is not stored permanently, | ||
- | 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. | + | In most programming languages, opening a file is the process of binding a file (given by a file name) to an internal handle. |
- | Rexx may open streams "on demand" | + | REXX may open streams "on demand" |
- | 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: | ||
</ | </ | ||
- | A Rexx interpreter might try to defend itself against this sort of open-many-close-none programming, | + | A REXX interpreter might try to defend itself against this sort of open-many-close-none programming, |
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, | + | As already mentioned, |
In SAA, the definition is strengthened to state that the " | In SAA, the definition is strengthened to state that the " | ||
Line 5134: | Line 5134: | ||
- | Basically, the built-in | + | Basically, the built-in |
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 | + | The following |
<code rexx> | <code rexx> | ||
Line 5228: | Line 5228: | ||
===== Determining the Current Position ===== | ===== Determining the Current Position ===== | ||
- | Standard | + | Standard |
The LINES() built-in function returns the number of complete lines left on the stream given as its first parameter. The term " | The LINES() built-in function returns the number of complete lines left on the stream given as its first parameter. The term " | ||
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, | + | REXX supports two strategies for reading and writing streams: character-wise, |
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, | 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, | ||
- | 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, | 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, | ||
- | These initial values for the current read and write positions are the default values. Depending on your Rexx implementation, | + | These initial values for the current read and write positions are the default values. Depending on your REXX implementation, |
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 " | 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 " | ||
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 " | 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 " | ||
- | Depending on your operating system and Rexx interpreter, | + | Depending on your operating system and REXX interpreter, |
- | 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, | 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, | ||
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, | + | Because of the large differences between various operating systems, |
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 | + | This section lists some of the other parts of REXX and the environments around |
[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 section describes some implementations of stream I/O in REXX. Unfortunately, |
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 | + | Regina will be changed to allow it to generate files with holes for system where this is relevant. Although standard |
==== Stream I/O in ARexx 1.15 ==== | ==== Stream I/O in ARexx 1.15 ==== | ||
- | ARexx differs considerably from standard | + | ARexx differs considerably from standard |
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 " | 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 " | ||
Line 5765: | Line 5765: | ||
- | ==== Main Differences from Standard | + | ==== Main Differences from Standard |
- | Now, as the functionality has been explained, let me point out the main conceptual differences from standard | + | Now, as the functionality has been explained, let me point out the main conceptual differences from standard |
[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 | + | Of course, ARexx also has a lot of functionality which is not part of standard |
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 | + | Note that it is difficult to translate between using standard |
<code rexx> | <code rexx> | ||
Line 5811: | Line 5811: | ||
</ | </ | ||
- | It is hard to mechanically translate between them, because of the lack of an EOF() built-in function in standard | + | It is hard to mechanically translate between them, because of the lack of an EOF() built-in function in standard |
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(' | 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(' | ||
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 | + | ===== Extensions and Standard |
- | In standard | + | In standard |
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 " | At the lowest level are these " | ||
- | At the top is " | + | At the top is " |
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 " | + | More and more REXX interpreters (including Regina parsing the program when the interpreter is started. The " |
- | 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 " | + | 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 " |
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, | 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, | ||
- | 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 ' | + | 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 ' |
[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 | + | The following table shows which options are available in different |
[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 " | Another goal of this chapter is to try to describe both the " | ||
Line 6279: | Line 6279: | ||
===== Background and history ===== | ===== Background and history ===== | ||
- | In the various definitions of Rexx, there are numerous references to the " | + | In the various definitions of REXX, there are numerous references to the " |
- | Originally, the references to the stack was introduced into Rexx because of the strong binding between | + | Originally, the references to the stack was introduced into REXX because of the strong binding between |
- | Unfortunately, | + | Unfortunately, |
- | The stack may have " | + | The stack may have " |
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 " | + | 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 " |
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 " | This documentation use the term " | ||
- | 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 | + | This is a common |
<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 | + | The concept of buffers and everything directly related to buffers lay without the domain of 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 | + | This is a common |
<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 | + | The description of multiple stack operations in this section, is not part of standard |
- | 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 " | + | 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 " |
Here, it is instructive to list the commands operating multiple stacks that exists. This list has been taken from the MVS environment, | Here, it is instructive to list the commands operating multiple stacks that exists. This list has been taken from the MVS environment, | ||
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" | 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" | ||
- | Also note that neither multiple stacks nor buffers are part of standard | + | Also note that neither multiple stacks nor buffers are part of standard |
Example: Counting the number of buffers | Example: Counting the number of buffers | ||
Line 6489: | Line 6489: | ||
- | ===== The interface between | + | ===== The interface between |
As defined in TRL, the interface to the stack consists of the PARSE PULL, PULL, PUSH, and QUEUE instructions; | As defined in TRL, the interface to the stack consists of the PARSE PULL, PULL, PUSH, and QUEUE instructions; | ||
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, | + | As mentioned, stacks are rarely a part of the operating system. Therefore, under most operating systems, |
[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 | + | 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 |
[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, | + | Regina supports the standard TRL (and ANSI) REXX stack interface functionality, |
==== 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, | + | In addition to the ANSI standard, there are a few extra built-in functions, which are supposed to provide compatibility with other REXX implementations, |
==== 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; | + | -install installs the NT Service; |
- | -start starts the NT Service; | + | -start starts the NT Service; |
- | -stop stops the NT Service; | + | -stop stops the NT Service; |
- | -remove stops and removes the NT Service; | + | -remove stops and removes the NT Service; |
-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' | Consider the following equivalents for Regina' | ||
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, | + | To enable the use of the REXX stack as a cross-platform, |
< | < | ||
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 | + | ====== Interfacing |
- | 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 | + | 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 |
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(), | + | Holds a definition of a system exit handler. Used when starting a REXX script with RexxStart(), |
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: | ||
</ | </ | ||
- | The strptr field is a pointer to an array of characters making up the contents of the Rexx string', | + | The strptr field is a pointer to an array of characters making up the contents of the REXX string', |
- | Unfortunately, | + | Unfortunately, |
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, | + | 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, |
- | 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, | Each subcommand handler handles one environment, | ||
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, | + | 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 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, | + | 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, |
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, | + | 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, |
- | 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, | + | 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 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 | + | ===== Executing |
- | 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 | + | The number of parameter strings given to the procedure. This is the number of defined |
[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, | 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, | ||
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 | + | Parameter used for storing tokenized |
[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(), | + | 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(), |
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 | + | If Instore is NULL, then ProgramName names the filename of an on-disk |
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(); | 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(); | ||
- | 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, | + | 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, |
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(), | During the course of an execution 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' | Successive requests for RXSHV_NEXTV will traverse the interpreter' | ||
- | 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 | + | Returns the ASCII representation of the number of parameters to the currently active |
[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 | + | e.g. what would a sequence of RXSHV_NEXT requests return after the following |
<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: | + | The exit handlers provide a mechanism for governing important aspects of the REXX interpreter from the application: |
==== 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; | The RXFNC system exit handler provides hooks for external functions. It has only one subfunction; | ||
- | 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 external data queue exit handler is used as a hook for operations manipulating the external data queue (or the stack). Unfortunately, |
However, some of this functionality is seemingly here; but not all. For instance for the RXMSQPLL subfunction, | However, some of this functionality is seemingly here; but not all. For instance for the RXMSQPLL subfunction, | ||
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'' | + | 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'' |
Depending on the subfunction, | Depending on the subfunction, | ||
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, | + | Note: Because the RXHLT exit handler is called after every REXX instruction, |
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, | + | It has only one subfunction, |
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, | 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, | ||
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, | + | 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 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, | + | 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, |
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' | + | The external queue interface provide a mechanism for interacting with 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 | + | The macro space interface provide a mechanism for pre-loading external |
==== 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, | + | 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 RexxAllocateMemory() function ==== | ==== The RexxAllocateMemory() function ==== | ||
Line 8523: | Line 8523: | ||
RexxFreeMemory() always return 0. | RexxFreeMemory() always return 0. | ||
- | ===== Calling back into running | + | ===== Calling back into running |
- | This section describes the RexxCallBack() function, which allows the application to execute a procedure within the running | + | This section describes the RexxCallBack() function, which allows the application to execute a procedure within the running |
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 | + | This function is used to execute an internal procedure within the running |
<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 | + | An ASCII NUL terminated string, specifying the name of the internal procedure of the running |
[ArgCount] | [ArgCount] | ||
- | The number of parameter strings given to the procedure. This is the number of defined | + | The number of parameter strings given to the procedure. This is the number of defined |
[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, | 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, | ||
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(), | + | 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(), |
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 | + | RX_CB_NOTSTARTED there is no running |
During the course of an execution of RexxCallBack(), | During the course of an execution 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, | + | By introducing implementation limits, |
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 " | Many interpreters are likely to have " | ||
- | 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 " | + | 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 " |
===== 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 " | ===== What an Implementation is Allowed to " | ||
- | 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, | + | 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, |
[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 ' | + | To run Regina in restricted mode, you can start the Regina interpreter from the command line with the ' |
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 | + | * white space delimiter detection and elimination at word boundaries or number boundaries at all possible places including cases of reading |
* 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 | + | 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 |
^ 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, | + | 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, |
- | 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 " | External data queue see " | ||
- | 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 | + | 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 |
- | Interactive trace is a trace mode, where the interpreter halts execution between each clause, and offer the user the possibility to specify arbitrary | + | Interactive trace is a trace mode, where the interpreter halts execution between each clause, and offer the user the possibility to specify arbitrary |
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 " | Queue see " | ||
- | 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 | + | Script is a single file containing |
Space separated Stack | Space separated Stack | ||
Line 8952: | Line 8952: | ||
Subkeyword is a keyword, but the prefix " | Subkeyword is a keyword, but the prefix " | ||
- | Subroutine is a routine which has been invoked from another | + | Subroutine is a routine which has been invoked from another |
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 ' | + | Character strings is the only type of data available in REXX, but to some extent there are ' |
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] |