This guide contains the following sections:
r4 is a Classic Rexx language interpreter. This product implements features of the REXX language as documented in Michael Cowlishaw's famous book:
The Rexx Language : A Practical Approach to Programming [SECOND EDITION] Author: Michael Cowlishaw Published in 1990 by Prentice-Hall, Inc. ISBN 0-13-780651-5
The book identified above is commonly referenced as TRL-2. r4 implements all REXX language features described in TRL-2.
The TRL-2 book can be obtained at one of the following internet sites:
Amazon | http://www.amazon.com/ |
Barnes & Noble | https://www.bn.com/ |
Fat Brain | https://www.fatbrain.com/ |
SoftPro | https://www.softpro.com/ |
A new 500 page Rexx book, written by Howard Fosdick, has been published by Wiley (ISBN: 0764579967). The book describes how to make the best use of Rexx tools and interfaces, with examples for both Linux and Microsoft® Windows®. A tutorial is provided with lots of examples to help you get up and running with Rexx. The book is available at the following online bookstores Amazon and Barnes and Noble.
Some other helpful REXX language internet sites are:
Kilowatt Software L.L.C.'s Classic Rexx Tutorial | http://www.kilowattsoftware.com/tutorial/rexx/ |
Rexx Language page at IBM Hursley | http://www2.hursley.ibm.com/rexx/ |
An online Rexx tutorial | http://www.kyla.co.uk/other/rexx1.htm |
An online Rexx tutorial | http://www.ilook.fsnet.co.uk/index/rexx_idx.htm |
A good source for other Rexx information | http://www.rexx.org.uk |
A good source for other Rexx information | http://www.rexxfiles.com |
TRL-2 defines language capabilities for multiple system environments. The guide your are now viewing describes features that are specific to the r4 implementation of Classic Rexx. Some features are adaptations associated with the Microsoft® Windows® system environments. If you have written Rexx programs in IBM mainframe environments you should be aware that Microsoft® Windows® environments use Ascii character encodings, instead of EBCDIC.
Kilowatt Software L.L.C. provides an extensive online Classic Rexx Tutorial. This tutorial describes all Rexx instructions and built-in functions. There are numerous example programs. If you are learning how to write Rexx programs you should spend some time reading the online tutorial. You should also obtain the TRL-2 book.
The r4 program operates as a Microsoft® Windows® 32 console application. The following is the syntax of a r4 program request, that is entered as a DOS command prompt. There are four variations. In the first variation, r4 is the only program that is executed. The remaining variations are command pipelines. The vertical bars separate pipeline command segments.
r4 programName [argumentText] [ < inFile ] [ [>]> outFile ]
r4 programName [argumentText] [ < inFile ] | programB
programA | r4 programName [argumentText] [ [>]> outFile ]
programA | r4 programName [argumentText] | programB |
Within this line, r4 is a request to execute the r4 program, which has a file name R4.EXE. You should add the directory that contains R4.EXE to your system PATH environment variable. See the environment setup section to determine how to revise the PATH environment variable.
The r4 program can also process redirected files. The r4 program can also participate in command pipelines.
When a fully qualified program name is specified, that program is executed if it exists.
When a partially qualified program name is specified, a search is conducted for the program. This
search begins in the current directory, and then proceeds through directories that are defined in
the R4PATH environment variable. If a file is found, then that program is executed.
Otherwise, an additional search is performed for a program with a default program extension.
Suggestion: always name your REXX program with the default program extension extension, and never create a
file that has the same name without the extension. If both files exist, you will
have to specify an explicit program extension with the programName argument of the r4
command.
In the first example above, only the fully qualified file name is tried.
In the second example above, an attempt is made to perform the named file, and then an implicit default
extension is tried.
In the third example above, a search is performed for the named file in the current directory, and
in the directories defined by the R4PATH environment variable.
In the fourth example above, if an extension-less file named 'copyfile' exists in the current
directory, or the directories defined by the R4PATH environment variable, then that file will be
executed. Often this will cause an error message to appear, because the file is not a REXX program.
In the fifth example above, a search for an implicit default' extension will not be conducted.
Argument text is accessed in the REXX procedure by using either the ARG( 1 )
builtin function, the ARG keyword instruction, or the PARSE ARG keyword instruction.
Optional additional text arguments:
/* HELLO.REX */
call charout , "Please enter your name: " say 'Hello' linein( ! ) '!' |
cd c:\r4
r4 hello |
An assortment of REXX programs are provided for your reference. A summary of these follows:
AnnVal.rex | Compute compounded value of an annuity (used with Bizzy.TopHat form) |
Anova.rex | Analysis of means, standard deviations, and variances |
Anova2.rex | Analysis of means, standard deviations, and variances -- detailed |
Asc2html.rex | Converts a marked up Ascii text file to HTML |
Ascii.rex | Dislays the Ascii character code table |
Box.rex | Encloses input within box characters |
Caldisp.rex | A calendar preparation program |
Caldisp2.rex | A faster calendar preparation program |
ChgAll.rex | replace all occurrences of one string, by another |
ChangeStr.rex | an external procedure that emulates the 'changestr' builtin function -- DEPRECATED. |
CompVal.rex | Perform compound interest computation (used with Bizzy.TopHat form) |
CsvDef.rex | Creates a new comma-separated value (CSV) file (used with CsvDef.TopHat form) |
CsvMaker.rex | Generates a TopHat form, and a REXX program, that adds lines to a CSV file |
Csv2xml.rex | Converts comma-separated value (CSV) files to XML files |
DatePick.rex | Demonstration of program that uses DATEPICK.EXE |
Deal.rex | Deals a hand of cards in Bridge format |
Difference.rex | Computes difference of two sets |
Easter.rex | Calculates Easter |
Factorial.rex | Calculates factorial |
FileDlg.rex | File selection dialog program that uses FILEDLG.EXE |
FinCalc.rex | Financial ratio computations (used with FinCalc.TopHat and FinCalcOut.TopHat forms) |
Gcd.rex | Computes greatest common divisor of two numbers |
GetContact.rex | Get contact information (used with Contact.TopHat form) |
Hanoi1.rex | A 'towers of hanoi' program |
Hanoi2.rex | Animated 'towers of hanoi' program |
HtmlMiner.rex | Extracts text within an HTML file that is not part of a tag |
Intersection.rex | Computes intersection of two sets |
Lcm.rex | Computes least common multiple of two numbers |
LoanCalc.rex | Perform loan computations (used with Bizzy.TopHat form) |
Lottery.rex | Picks 6 lottery numbers |
Matrix.rex | Displays input as a matrix with M rows and N columns |
Messager.rex | Demonstration of program that uses MSGBOX.EXE |
MetricArea.rex | Metric area conversions (used with Metric.TopHat form) |
MetricDistance.rex | Metric distance conversions (used with Metric.TopHat form) |
MetricVolume.rex | Metric volume conversions (used with Metric.TopHat form) |
MetricWeight.rex | Metric weight conversions (used with Metric.TopHat form) |
MetricTemperature.rex | Metric temperature conversions (used with Metric.TopHat form) |
Picker.rex | Demonstration of program that uses PICKLIST.EXE |
Powers2.rex | Shows 'powers of 2' table |
PresVal.rex | Perform present value computation (used with Bizzy.TopHat form) |
Prompter.rex | Demonstration of program that uses PROMPT.EXE |
Qt.rex | Shows the present time in English |
Rexxtry.rex | An interactive REXX shell |
Roman.rex | Converts a number to roman numerals |
Sayit.rex | A tiny full function calculator |
Sieve.rex | Prime number algorithm -- the 'sieve of Eratosthenes' algorithm |
Sqrt.rex | Computes square root using Newton's algorithm -- an external procedure |
Sumdisk.rex | The best example -- summarizes disk space usage |
TopoSort.rex | Topological sort -- dependency analyzer |
Union.rex | Computes union of two sets |
The following environment variables can be specified to customize the execution of
The optional R4_ALLOW_UNQUALIFIED_SOURCE environment variable controls whether checking that REXX programs begin with a source comment is made. When the R4_ALLOW_UNQUALIFIED_SOURCE environment variable starts with the letter 'N', then files will be checked to ensure that they begin with a comment. The following shows the associated command line to enter:
set R4_ALLOW_UNQUALIFIED_SOURCE=N |
When the R4_ALLOW_UNQUALIFIED_SOURCE environment variable starts with the letter 'Y', then any file will be accepted as a REXX source program. The following shows the associated command line to enter:
set R4_ALLOW_UNQUALIFIED_SOURCE=Y |
When the R4_ALLOW_UNQUALIFIED_SOURCE environment variable is not set the default is to allow source files to be executed, even though they do not begin with a source comment.
You are encouraged to define the R4_ALLOW_UNQUALIFIED_SOURCE environment variable to 'N'. Otherwise, you might have to debug some perplexing difficulties. For example, if the data file XX is empty, r4 will process an empty program. When you look at the source of the XX.REX program you will not easily be able to understand why the program is not executed. By defining the R4_ALLOW_UNQUALIFIED_SOURCE environment variable to 'N' you will not have to endure such aggravation.
The R4_DEFAULT_PROGRAM_EXT environment variable can include multiple alternative extensions separated by semicolons -- such as:
.rex;rexx;cmd |
The following causes interactive tracing to be activated, with intermediate results listed.
set R4_EXECTRAC=?i |
r4 progName > outFile 2>&1 |
The above redirects the output of progName to outFile. Trace output will also be present in outFile.
The following causes interactive tracing to be activated, with intermediate results listed, when the factorial_ice procedure is invoked.
set R4_TRACE_factorial_ice=?i |
When the first letter of the R4COMMANDWAIT is 'Y', R4 will wait for the completion of commands which are Microsoft® Windows® applications. Otherwise, R4 will use the system command processor to process the command.
An example of setting the R4COMMANDWAITenvironment variable value follows:
set R4COMMANDWAIT=Yes
This indicates that R4 will wait for the completion of
commands which are Microsoft® Windows® applications.
The default line termination characters are the Microsoft® Windows® standard; an Ascii carriage return (decimal 13 -- symbolically \r) followed by an Ascii line feed (decimal 10 -- symbolically \r).
An example of setting the R4LINEBREAK environment variable value follows:
set R4LINEBREAK=\n
This indicates that lines are terminated by an Ascii line feed only.
The default setting is:
set R4LINEBREAK=\r\n
Lines can be terminated by other sequences as well, for example:
set R4LINEBREAK=<br>
Which is the standard HTML line break sequence.
When backslashes are encountered in the R4LINEBREAK setting, if the next character is neither
an 'r' nor an 'n', then the next character is included in the line termination sequence. For
example,
set R4LINEBREAK=\\r\\n
Ends each line with the character sequence '\r\n'.
If the R4PATH environment variable is not defined, the default path will be the folder (directory) that contains the R4.EXE module.
Note: this environment variable is also used to locate external procedures that are invoked by the REXX program.
v1 = v2 = v3 = '' parse value with v4 v5 v6 |
All six variables above are initialized to the empty string.
parse value 'abc def ghi' with v1 v2 v3 UPPER v1 v2 v3 |
The value of variables v1, v2, and v3 are converted to uppercase:
v1 --> ABC
v2 --> DEF
v3 --> GHI
say 'what is your name ?' parse EXTERNAL name say 'Hello' name |
parse NUMERIC digits fuzz form say 'The current DIGITS setting is:' digits say 'The current FUZZ setting is:' fuzz say 'The current FORM setting is:' form |
parse LOWER value 'ABRACADABRA' with magic say 'magic:' magic => abracadabra |
parse caseless value 'abracadabra' with bef 'CA' +2 aft say 'bef:' bef => abra say 'aft:' aft => dabra parse caseless value 'ABRACADABRA' with bef 'ca' +2 aft say 'bef:' bef => ABRA say 'aft:' aft => DABRA |
call fn( arg1, arg2, ... ) |
In strict mode the above would be considered invalid. The proper form of the call instruction does not have a left parenthesis immediately following the subroutine name. The correct way to call the subroutine is:
call fn arg1, arg2, ... |
By default r4 operates in strict mode.
If you have never revised an environment variable, you might ask a friend or colleague who is familiar with this process to help you make this change.
set R4PATH=c:\r4;c:\rexx |
set R4LINEBREAK=\n |
set PATH=c:\windows;c:\windows\system32 |
Add the new directory to the path, separating it from other directories by a semicolon.
If you have never revised the AUTOEXEC.BAT file, you might ask a friend or colleague who is familiar with this process to help you make this change.
r4 implements TRL-2 language features using values that are generally limited by available Microsoft® Windows® memory. This means that variable names and values can be very large. The NUMERIC DIGITS setting can also be large. The following features are implemented with more finite limits.
Default input stream and default output stream accesses are not buffered. The 'start' value is not valid for CHARIN and CHAROUT builtin function requests associated with the default input or default output stream. Similarly, the 'line' value is not valid for LINEIN and LINEOUT builtin function requests associated with these streams.
Ascii table |
---|
0 1 2 3 4 5 6 7 8 9 A B C D E F 00 NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI 10 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US 20 spc ! " # $ % & ' ( ) * + , - . / 30 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 40 @ A B C D E F G H I J K L M N O 50 P Q R S T U V W X Y Z [ \ ] ^ _ 60 ` a b c d e f g h i j k l m n o 70 p q r s t u v w x y z { | } ~ DEL |
'spc' indicates a space. |
Entries in this table are determined by taking the two hexadecimal digits at the left hand side of the table, and adding the hexadecimal value at the top of the table. |
The letter X is in the row that starts with 50, and column 8. Thus, the Ascii value of X is hexadecimal 58. |
The letter O is in the row that starts with 40, and column F. Thus, the Ascii value of O is hexadecimal 4F. |
Character values less than hexadecimal 20 are control characters. HT ('09'x) is a horizontal tab, which is commonly referred to as a tab. LF ('0A'x) is a line feed character. CR ('0D'x) is a carriage return. |
'DEL' ('7F'x) is a rubout control character. |
Character values in excess of hexadecimal 7F are extended Ascii characters, these are omitted in the above table because of their effect on HTML browsers. You can execute the ASCII.REX program to view extended Ascii characters. |
Note: uppercase letters are less than lowercase letters in collating order. This can be significant during string comparisons -- i.e. the Compare built-in function, and comparison operators (=, <=, etc.). Consequently, 'Bob' will be considered less than 'bill' when character case is significant.
The sequence of lower case Ascii characters can be generated by the XRANGE builtin function as follows:
xrange( 'a', 'z' ) |
A text value can be converted to lower case by using the XRANGE and TRANSLATE builtin functions as follows:
lowercaseValue = translate( textValue, xrange( 'a', 'z' ), , xrange( 'A', 'Z' ) ) |
/= | not equal |
/< | greater than or equal |
/> | less than or equal |
/== | strictly not equal |
/<< | strictly greater than or equal |
/>> | strictly less than or equal |
Observe: if the first word of a command is associated with an .EXE or .BAT file that can be located in
any directory (folder) that is defined in the PATH environment variable, then the EXE or BAT file is invoked
instead of the external procedure. This avoids a recursion problem that might occur if the REXX external procedure
tried to invoke an EXE or BAT file with the same name as the procedure. This problem was reported !
MAKEBUF command |
DROPBUF command |
NEWSTACK command |
DELSTACK command |
EXECIO command |
Win32 | (always) |
COMMAND, FUNCTION, or SUBROUTINE | |
full file name, with spaces replaced by carets | i.e. C:\R4\HELLO.REX |
* | (always |
* | (always) |
invocation name | i.e. HELLO |
Note: all of the above values are in UPPERCASE, with the exception of the leading 'Win32' value.
REXX-r4 4.00 dd Mon yyyy |
where: dd is build day, Mon is build month, yyyy is build year |
carriage return THEN line feed | decimal 13, decimal 10 |
line feed THEN carriage return | decimal 10, decimal 13 |
line feed only | decimal 10 |
carriage return only | decimal 13 |
This allows your programs to easily process text files that are received from other system environments; such as, UNIX, or Linux.
The environment variable access section below shows how to set and reference environment variable values.
The registry value access section below shows how to access and revise system registry values.
Observe: if temporary is contained anywhere within the name of the selector pool then values are not saved when the R4 program terminates.
Commands sent to the system can include file redirections, and command pipelines. For example:
'dir *.rex | r4 countlines >> outfile' |
As mentioned previously, you should consult Microsoft® Windows® documentation for the use of file redirection and command pipelines.
When you perform commands, you should make sure that the <, >, and | characters are enclosed within quotes. Otherwise, these will be treated as LESS THAN, GREATER THAN, or OR operator requests.
Note: the output of the command is redirected to an implicit temporary file. When you use the "(stack" directive, you must avoid using the '>' file redirection operator elsewhere within the command.
The following is an example of the use of the "(stack" command line directive.
'dir *.rex (stack'
say queued() do queued() parse pull qline say qline end |
As with the "(stack" directive, implicit temporary files are used for "<!queue" and ">!queue" command redirection requests. You you must avoid using the '<' elsewhere within the command if the "<!queue" directive is specified. And, you you must avoid using the '>' elsewhere within the command if the ">!queue" directive is specified.
The following is an example of the use of "<!queue" and ">!queue" command redirection requests.
'newstack' /* prepare 10 random numbers between 1 and 99 in the external data queue */ do 10 push right( random( 1, 99 ), 2, '0' ) end 'sort <!queue >!queue' /* sort the numbers ! */ /* after the above command completes the numbers are now sorted ! */ /* show the sorted numbers */ do queued() parse pull qline say qline end 'delstack' |
The REXXTRY.REX example shows how the HALT condition can be handled.
A '1A'X character can be written to output streams that are associated with disk files. Subsequent output will appear in the disk files.
The following shows how the VALUE function is used to set and reference environment variable values.
/* DOENV.REX */
call value 'magic', 'abracadabra', 'system' /* set magic environment variable */ say value( 'magic', , 'system' ) /* get magic environment variable */ |
Access to system registry information allows r4 to prepare and reference information that is used by other system software. This is a powerful capability. However, since system registry information is critical to correct system operation, r4 can only perform some registry operations. You should be particularly careful when revising registry values. Erroneous revisions can have serious consequences. These changes cannot be undone.
Due to the sensitivity of system registry information, r4 can only be used to access and revise registry values. The product does not provide capabilities for accessing registry keys directly, and registry keys and values can not be removed. All registry values that are accessed by r4 must be strings. No other registry value format is supported.
As an extra precaution, registry revisions are only permitted when the R4REGISTRYWRITE environment variable has value: 'Y'. You can locally alter this value, as shown in the example below. No error occurs if this environment variable has not been set.
You are strongly advised to B-A-C-K-U-P the system registry before attempting to revise it with an R4 program.
If you are unfamiliar with the detailed characteristics of the system registry, you should discuss what you plan to do with a business colleague or friend, BEFORE attempting to revise registry information.
Registry values are accessed using a three part name, that has the following structure:
root\keyPath[valueName]
The keyPath consists of a hierarchy of keys separated by backslashes.
The valueName must be enclosed in square brackets.
The root must be one of the following:
'HKEY_CLASSES_ROOT'
'HKEY_CURRENT_USER'
'HKEY_LOCAL_MACHINE'
'HKEY_USERS'
'HKEY_CURRENT_CONFIG'
'HKEY_DYN_DATA'
The following root aliases are supported:
'HKCU' | HKEY_CURRENT_USER |
'HKLM' | HKEY_LOCAL_MACHINE |
'HKCR' | HKEY_CLASSES_ROOT |
'HKU' | HKEY_USERS |
'HKCC' | HKEY_CURRENT_CONFIG |
'HKDD' | HKEY_DYN_DATA |
The following shows how the VALUE function is used to access and revise system registry values.
/* DOREG.REX */
root = 'HKEY_CURRENT_USER' keypath = 'Software\Kilowatt Software\DoReg' regvalue = 'Magic' /* enable registry revision */ call value 'R4REGISTRYWRITE', 'Y', 'system' /* set R4REGISTRYWRITE=Y */ /* revise registry value */ call value root'\'keypath'['regvalue']', 'abracadabra', 'registry' /* disable registry revision */ call value 'R4REGISTRYWRITE', 'N', 'system' /* set R4REGISTRYWRITE=N */ /* registry values can still be retrieved */ /* get registry value */ say value( root'\'keypath'['regvalue']', , 'registry' ) |
The implementation of the STREAM builtin function is customized to the Microsoft® Windows® system environment. r4 supports the following STREAM syntax, that conforms with TRL-2:
STREAM( name, [operation, [streamcommand option] ) |
name is the name of the item associated with the request, which may be a stream, a file name, a directory name, and so forth.
operation is either Command, Description, or State. All are treated as described in TRL-2.
streamcommand is the name of the stream associated with the request. These are interpreted as described in the table below. The character case of the stream command is insignificant. Thus, chdir, CHDIR, and ChDir are equivalent.
option is optional text associated with the streamcommand.
The following table summarizes the supported stream commands. You should study the STREAM examples below to gain an improved understanding of these requests.
Stream command | Description | Name | Option |
---|---|---|---|
chdir | Changes active directory | Directory name1 | N/A |
chdisk | Changes active disk | Disk name2 | N/A |
close | Closes a specific stream | Stream name | N/A |
dirs | Queues directories3 under the active directory | Directory pattern4 | N/A |
drive | Gets disk drive information5 | Drive name | N/A |
drives | Queues all disk drive information6 | N/A | N/A |
exists | Returns '1' if a file exists, otherwise '0' | File or directory name | N/A |
fileinfo | Gets file information7 | File name | N/A |
files | Queues file information8 | File pattern9 | N/A |
getkey | Gets a two byte keystroke combination from the console10 | N/A | N/A |
isdir | Returns '1' if the name is a directory, otherwise '0' | File or directory name | N/A |
linebreak | Sets line break characters for specific stream | Stream name | line break characters11 |
longname | Shows long name associated with file or directory | Stream name | N/A12 |
purge | Erases file if not open. Sets read/write positions to 0 if open.13 | Stream name | N/A |
recycle | Sends file to recycle bin.14 | Stream name | N/A |
shortname | Shows short name associated with file or directory | Stream name | N/A15 |
1 If the CHDIR request succeeds it returns the name of the previous directory associated with the current disk. If the CHDIR request FAILS, it returns the empty string.
If the directory name is absent, the CHDIR request returns the currently active directory associated with the current disk.
2 If the CHDSK request succeeds it returns the name of the previously active disk. If the CHDSK request FAILS, it returns the empty string.
If the disk name is absent, the CHDISK request returns the currently active disk.
3 The DIRS request returns the number of directories that were located. Directory names are stored in the external data queue, and are accessed by using PARSE PULL for the number of directories that were located.
4 If the directory pattern is absent, the DIRS request returns all directories under the active directory.
5 The DRIVE request gets information describing a specific disk drive. The information has the following format.
driveLetter driveType totalSpace freeSpace clusterSize activeDirectory |
If disk space information is unavailable, then totalSpace, freeSpace, and clusterSize are all underscores. |
6 The DRIVES request returns the number of disk drives that were located. Disk drive information is stored in the external data queue, and is accessed by using PARSE PULL for the number of disk drives that were located. Each line of drive information returned by a DRIVES request has the same format as a DRIVE request.
7 The FILEINFO request gets information describing a specific file. The information has the following format.
fileModificationDateAndTime dirOrSize accessability |
The fileModificationDateAndTime value is formatted as YYYY/MM/DD-HH:MM:SS
The dirOrSize value is 'DIR' if the file is a directory, otherwise it is the number of bytes withinin the file.
The accessability value is 'RW' if the file is writeable, and 'RO' if the file is read-only.
8 The FILES request returns the number of files that were located. File names are stored in the external data queue. The names can be acquired by using PARSE PULL for the number of files that were located.
9 If the file pattern is absent, the FILES request returns all files under the active directory.
10 The GETKEY request returns a two byte hexadecimal literal associated with a console keystroke; such as, F1, F2, or an arrow key. The values that are returned do not follow a particular pattern. Thus, the following quote is appropriate:
Life is like a box of chocolates - you never know what you're going to get. [Tom Hanks, as Forrest Gump in "Forrest Gump" (1994)] |
The GETKEY example below provides a simple program that you can use experimentally to determine the values that are returned for specific console keystrokes.
Hint: The first character is '00'x or 'E0'x when a function key, or a special key is pressed.
11 The LINEBREAK option string is formatted as described in the R4LINEBREAK section above.
12 The stream name can be a short MS-DOS 8.3 name of a file or directory. The corresponding long name is returned.
13 The operation of a PURGE request depends on whether the file is currently open or not.
|
14 A RECYCLE request implicitly fully-qualifies the file name. It is recommended that the file name parameter be fully-qualified. You should also consider prompting before sending files to the recycle bin.
The following values are returned from a recycle request.
0 | The file was sent to the recycle bin. |
1 | An error occurred sending the file to the recycle bin. The file might be currently open. |
15 The short name of a file or directory is in MS-DOS 8.3 format.
The following are examples of STREAM builtin function usage. You can copy the text within these examples and paste it into your REXX programs.
/* CHDIR example */
subdirectoryName = arg(1) if stream( subdirectoryName, 'C', 'ChDir' ) <> '' then 'dir *.rex' |
/* CHDSK example */
targetDisk = arg(1) if stream( targetDisk, 'C', 'ChDisk' ) <> '' then 'tree' |
/* DISKTELL.REX */
say "Current disk:" stream( '', 'C', 'ChDisk' ) say "Current directory:" stream( '', 'C', 'ChDir' ) |
/* DIRS.REX */
ndirs = stream( arg(1), 'c', 'dirs' ) do i=1 to ndirs pull directory say directory end |
/* DRIVES.REX */
ndrives = stream( "", 'c', 'drives' ) do i=1 to ndrives pull drive say drive end |
/* DRIVE.REX */
drive = arg(1) if drive = '' then call drives /* invoke external procedure DRIVES.REX (see above) */ else say stream( drive, 'c', 'drive' ) |
/* EXISTS.REX */
file = arg(1) if stream( file, 'c', 'exists' ) then say 'Yea! File' file 'exists.' else say 'File' file 'DOES NOT exist.' |
/* FILES.REX */
nfiles = stream( arg(1), 'c', 'files' ) do i=1 to nfiles pull file say left( fileName, max( length( fileName ), 40 ) ) stream( fileName, 'C', 'fileInfo' ) end |
/* FILEINFO.REX */
file = arg(1) say stream( file, 'c', 'fileinfo' ) |
/* FILEDATE.REX */
file = arg(1) say word( stream( file, 'c', 'fileinfo' ), 1 ) |
/* FILESIZE.REX */
file = arg(1) say word( stream( file, 'c', 'fileinfo' ), 2 ) |
/* GETKEY.REX */
call charout !, 'Press a console keyboard character: ' say c2x( stream( !, 'c', 'getkey' ) ) |
/* ISDIR.REX */
dir = arg(1) if stream( dir, 'c', 'isdir' ) then say dir 'is a directory.' else say dir 'IS NOT a directory.' |
/* LINEBREAK.REX */
file = arg(1) call stream file, 'c', 'linebreak' \n' |
/* LONGNAME.REX */
file = arg(1) longName = stream( file, 'c', 'longname' ) |
/* PURGE.REX -- external procedure
if file is not open it is erased if file is open the contents are removed. */ file = arg(1) call stream file, 'c', 'purge' |
/* RECYCLE.REX -- external procedure sends file to the recycle bin A message box is displayed with style value of 292 (4 + 32 + 256): show 'Yes' and 'No' buttons 4 the 'question mark' icon is displayed + 32 the 'No' button initially has the focus + 256 ===== total: 292 */ file = arg(1) 'MsgBox' '"/CRecycle' file '?" /S292 Are you sure you want to recycle' file '?' if rc = 6 then do cc = stream( file, 'c', 'recycle' ) if cc = 0 then say "'"file"' was sent to the recycle bin." else say "An error occurred recycling file'"file"'. The file may be open." end |
/* SHORTNAME.REX */
file = arg(1) shortName = stream( file, 'c', 'shortname' ) |
There are various occasions when you will want to convert r4 source programs to binary equivalents, so that others can use your program without being able to see your logic. Some algorithms are copyrighted with provisions that you can distribute them to others as long as the source is unreadable. The CHILL.REX program allows you to do prepare binary programs that can be executed, without associated visible source.
The process of converting a REXX program to a 'chilled' binary file is fairly simple. Here are several examples
r4 chill myCoolProgram.rex r4 chill myCool.rooProgram r4 chill myCoolClass.roo |
Chilled programs (aka _ice files) are created in the .\ice subdirectory. Chilled programs have the same name and extension as the original file, with '_ice' added before the extension. For example, if the original program is named:
myCoolProgram.rex |
then, the chilled program will be in the .\ice subdirectory with the following name:
myCoolProgram_ice.rex |
When a program is chilled it is imperative to retain the corresponding source program. This allows you to debug problems when 'chilled' programs are used on other systems. The corresponding source files are saved in the .\iceSource subdirectory. The saved source programs have the same name and extension as the original file, with a date and time suffix added before the extension. For example, if the original program is named:
myCoolProgram.rex |
then, the saved source file program will be in the .\iceSource subdirectory with the following name:
myCoolProgram_030326_105756.rex |
Saved source files are created with the read-only attribute. This is a precaution to avoid accidental renaming or removal.
Warning: you should backup saved source files files on alternate media .. i.e. CD-ROM.
The CHILL.REX program keeps a log of all requests in file CHILL.LOG. The log file is maintained in the active working directory when CHILL.REX is started. When you need to find which saved source file corresponds with a specific '_ice' file you can locate the associated information in the CHILL.LOG file as follows:
'sourceFile_ice.rex #N .. source is unavailable' or, 'sourceFile_ice.rooProgram #N .. source is unavailable' or, 'sourceFile_ice.roo #N .. source is unavailable' |
ESC = '1B'x |
call charout , ESC'[33;40m' || 'Hello' |
The following tables identify the numeric values associated with foreground and background colors.
Foreground colors | |
---|---|
30 | Black |
31 | Red |
32 | Green |
33 | Yellow |
34 | Blue |
35 | Magenta (Pink) |
36 | Cyan (Turquoise |
37 | White |
38 | Black |
Background colors | |
---|---|
40 | Black |
41 | Red |
42 | Green |
43 | Yellow |
44 | Blue |
45 | Magenta (Pink) |
46 | Cyan (Turquoise |
47 | White |
48 | Black |
The foreground color can be normal or highlighted. A numeric escape value of 1 highlights the foreground text color. For example, the 1 after the '[' turns on highlighting below.
ESC = '1B'x |
call charout , ESC'[1;33;40m' || 'Hello' |
A numeric escape value of 0 deactivates highlighting. For example, the 0 after the '[' turns off highlighting below.
ESC = '1B'x |
call charout , ESC'[0;33;40m' || 'Hello' |
No other ANSI.SYS escape sequences are emulated.
The syntax of the function variants is:
result = Changestr( needle, haystack, replacement ) [ANSI variant] |
result = Changestr( haystack, needle, replacement ) [NetRexx/Roo!(TM) variant] |
The result of the Changestr function replaces all non-overlapping occurrences of needle in haystack with replacement. When needle is the empty string, then the result is haystack.
The following examples illustrate the operation of the Changestr function. The parenthesized value following the say keyword is the result of the associated Changestr function request. In these examples, only the ANSI variant is illustrated
say '(dabracaddabra)' changestr( 'abra', 'abracadabra', 'dabra' ) say '(abracadabra)' changestr( '', 'abracadabra', 'dabra' ) |
The syntax of the function variants is:
result = Countstr( needle, haystack ) [ANSI variant] |
result = Countstr( haystack, needle ) [NetRexx/Roo! variant] |
The result of the Countstr function counts all non-overlapping occurrences of needle in haystack. When needle is the empty string, then the result is 0.
The following examples illustrate the operation of the Countstr function. The parenthesized value following the say keyword is the result of the associated Countstr function request. In these examples, only the ANSI variant is illustrated
say '(2)' Countstr( 'abra', 'abracadabra' ) say '(0)' Countstr( '', 'abracadabra' ) |
result = Find( string, word ) |
The Find builtin function is identical in operation to the Wordpos builtin function, with the exception that the string and word arguments are in the opposite order.
result = Index( haystack, needle [ , start ] ) |
The Index builtin function is identical in operation to the Pos builtin function, with the exception that the haystack and needle arguments are in the opposite order.
result = Justify( string, length [ , pad ] ) |
The result of the Justify function always returns a string with length: length. There is always at least one word in the result, which might be truncated (as in the first example below). When more than one word is present in the result, the last word is not truncated. Spaces are added between the words as necessary to produce a result that has the requested length. If specified pad characters are added instead of spaces.
The following examples illustrate the operation of the Justify function. The parenthesized value following the say keyword is the result of the associated Justify function request.
say '(Hooptedoo)' justify( 'Hooptedoodle!', 9 ) say '(The blue)' justify( 'The blue sky', 9 ) say '(The++blue)' justify( 'The blue sky', 9, '+' ) say '(The++++)' justify( 'The blue sky', 7, '+' ) say '(The++blue++sky)' justify( 'The blue sky', 14, '+' ) say '(The++blue+++sky)' justify( 'The blue sky', 15, '+' ) say '(The++azure+++blue+++sky)' justify( 'The azure blue sky', 23, '+' ) say '(The blue)' justify( 'The blue sky', 8 ) say '(++++)' justify( '', 4, '+' ) say '()' justify( '', 0 ) say '()' justify( 'The blue sky', 0 ) |
result = Linesize( ) |
The result of the Linesize function is the number of characters per console line -- i.e. 80.
result = Qualify( [ streamName ] ) |
The result of the Qualify function is the fully qualified name of streamName, in UPPERCASE. The empty string is returned if streamName is absent, or an empty string.
The following examples illustrate the operation of the Justify function. The parenthesized value following the say keyword is the result of the associated Justify function request.
-- assume these are executed in the C:\R4 directory (folder) say '(C:\R4\R4.EXE)' qualify( 'r4.exe' ) say '(C:\R4\R4.EXE)' qualify( './r4.exe' ) say '(C:\R4\R4.EXE)' qualify( '.\r4.exe' ) say '()' qualify( '' ) call qualify nonExistentFileName --> syntax error !!! |
result = Scrsize( ) |
The result of the Scrsize function is two numbers separated by a space. The first number is the number of console lines (i.e. 24), the second number is the number of characters per console line (i.e. 80).
result = Userid( ) |
The result is set to: ComputerName/Userid
parse value userid() with ComputerName '/' UserName say 'Hello' UserName'.' say 'Your computer name is:' ComputerName'.' |
x: | disk change, where: 'x' is a drive letter |
CD directoryPath | change directory |
CHDIR directoryPath | change directory |
SET environmentVariable'='value | set environment variable value |
The above commands should be properly quoted. Otherwise, backslashes within directory paths are treated as REXX not operators, and the '=' sign in a SET command is a relational operator.
The following shows how a COPYFILE program can be used with redirected files:
r4 COPYFILE < infile > outfile |
The following shows how the lines of the DIR command can be counted:
DIR /b *.rex | r4 COUNTLINES |
The associated programs follow:
/* COPYFILE.REX -- character version */
do while chars() > 0 call charout , charin() end |
/* COPYFILE.REX -- lines version */
do while lines() > 0 call lineout , linein() end |
/* COUNTLINES.REX -- unredirected version */
lno = 0 do while lines() > 0 lin = linein() lno = lno + 1 end say lno |
/* COUNTLINES.REX -- redirected or pipeline version */
say lines() |
The following is a simple program that interacts with the console user:
/* GREET.REX */
call charout !, "Please enter your name: " call lineout !, 'Hello' linein( ! ) |
Notice that the exclamation point does not require quotes.
When the default input stream is not redirected from a file (or pipeline), the CHARS and LINES functions both return '1' when more input is available, and '0' when the end of the input stream is encountered.
When the default input stream is redirected from a file (or pipeline), the CHARS and LINES functions return the actual number of characters or lines remaining in the stream.
For file streams the CHARS and LINES functions return the actual number of characters or lines remaining in the stream.
For the 'console' stream the CHARS and LINES functions both return '1' when more input is available, and '0' when the end of the input stream is encountered. The only difference is that the order of the first two arguments is reversed.
If you are a new REXX programmer you can skip the description of these capabilities.
With respect to the MAKEBUF, DROPBUF, NEWSTACK, and DELSTACK commands, the external data queue is divided into a sequence of stacks, each of which can contain a sequence of buffers. Initially there is a single stack that contains a single buffer.
A NEWSTACK command establishes a new stack division within the external data queue.
A MAKEBUF command establishes a new buffer position within a stack division. Subsequent QUEUE requests will insert lines after a buffer position, but before all other lines within that buffer. A QUEUED builtin function request returns the number of lines that follow a buffer position.
The following diagram shows how the external data queue is divided into stack divisions and buffers.
A DROPBUF request removes a buffering position established by a prior MAKEBUF command.
Similarly, a DELSTACK request removes all lines from the top of the external data queue to a stack division point, only if a prior NEWSTACK division is established. If a prior NEWSTACK division was not established, then a DELSTACK request is ignored -- all lines in the external data queue remain.
PUSH requests are unaffected by any of these commands. Pushed lines are always added at the last position of the external data queue.
The MAKEBUF command returns a queue position, which is assigned to the RC variable. This queue position can optionally be passed to the DROPBUF command. The following shows how to use the queue position.
push z makebuf queue c makebuf queuePosition = rc queue a queue b dropbuf queuePosition queue x queue y say "Output lines to the marked position should appear in order: a, b, c, x, y" do queued() pull qline say qline end dropbuf say "The final queued line should be: z" do queued() pull qline say qline end |
The R4XFORM program allows you to create executable modules (EXEs) that encapsulate your REXX programs. The created modules can then be performed at command prompts, within batch scripts, or DOSKEY macros.
The R4XFORM program operates as a standard Microsoft® Windows® application. The following is the syntax of an R4XFORM program request, that is entered as a DOS command prompt.
R4XFORM [moduleName] |
Within this line, R4XFORM is a request to execute the R4XFORM program, which has a file name R4XFORM.EXE. You should add the directory that contains R4XFORM.EXE to your system PATH environment variable. See the environment setup section to determine how to revise the PATH environment variable.
The optional moduleName argument is specified when you want to revise a previously created R4XFORM executable module. Spaces are not permitted in the moduleName argument.
Spaces should NOT be entered in the Module name field.
The 'Search' button on the right side of this input field allows you to use the system file explorer to locate the R4 source program.
Spaces should NOT be entered in the R4 source program field. If there are spaces in the directory path that you located with the 'Search' button, then you should move the leading directory name to the R4PATH input field.
The 'Search' button on the right side of this input field allows you to use the system folder search facility to locate an existing directory.
The underlined characters above are accelerator keys. When you hold down the 'Alt' key, and press one of the underlined characters the cursor will move to the associated input field.
The 'OK' button is disabled until the module name AND the R4 source program AND the working directory field ALL contain text.
Here is an example of how to convert an R4 program to an executable module.
The following is a simple program that shows a greeting.
/* GREET.REX */
say 'Hello' arg( 1 ) |
After you click the OK button, look in the same directory as the R4XFORM program, and you will observe that a new GREET.EXE file exists.
Start a command prompt window. Switch to the directory that contains the program. Then enter:
greet |
Hello Pat |
If instead you enter:
greet -- Have a nice day ! |
Hello Pat -- Have a nice day ! |
In order to use R4XFORM effectively you need to understand how it works. Perhaps you believe that R4XFORM compiled the REXX program into an executable module. This is not the case. R4XFORM works as follows:
\\HKEY_LOCAL_MACHINE\Software\Kilowatt Software\Become\GREET
And,
\\HKEY_LOCAL_MACHINE\Software\Kilowatt Software\Become\GREET\Environment
You can use the standard system registry editor to see the information that was created. You can start this program by Selecting 'Run' from the 'Start' menu, and entering the command REGEDIT. Search downwards through the registry tree for the path shown above. You will locate the registry information that was prepared for the GREET program.
If you comprehend the above process you will find that you can use the combination of TEENSY.EXE and BECOME.EXE to encapsulate other command shells as well. These two programs are not directly interrelated with r4 or the R4XFORM program.
r4 is accompanied by the Revu text file viewing accessory. This related product is particularly helpful when viewing Rexx source files. It is similarly useful for viewing C/C++, Java, JavaScript, Perl, XML and HTML files. Click here to study the related Revu program.
Revu is implicitly used by r4 for source presentation during interactive tracing. The current line is continually updated, as the program is debugged. When the program being debugged concludes, the associated Revu window is automatically closed.
When r4 is updated, the latest version of R4.EXE and
the updated User's Guide R4.HTM can be found in the following
internet location:
http://www.kilowattsoftware.com/latest/
REXX programming examples may be found in the same location. These are files that have a '.rex' extension.
If you have comments, questions, or concerns regarding r4 you can send these via e-mail to: