This is the user's guide for Kilowatt Software L.L.C.'s
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.
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
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
roo programName [argumentText] [ < inFile ] [ [>]> outFile ]
roo programName [argumentText] [ < inFile ] | programB
programA | roo programName [argumentText] [ [>]> outFile ]
programA | roo programName [argumentText] | programB |
Within this line, roo is a request to execute the
The
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 ROOPATH 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 program 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 ROOPATH 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 ROOPATH environment variable, then that file will be
executed. Often this will cause an error message to appear, because the file is not a
In the fifth example above, a search for an implicit default program extension will not be conducted.
Argument text is accessed in the 5 Optional additional text arguments:
The following shows how to prepare a
/* try.rooProgram -- uses the try.roo class twice usage: roo tryRoo */ /* the following is a usage of the 'try' class. an instance of the 'try' class is created, and assigned to the 'obj' variable. the 'toString' method is invoked using the 'obj' variable's value. the instance of the 'try' class is removed when the 'obj' variable is dropped, which occurs when the procedure terminates. */ obj = ^^ try.roo( 'yo', 'dude' ) say obj ^ toString() /* the following is a similar usage of the 'try' class. an instance of the 'try' is created, and the 'toString' method is invoked using the newly created instance in place. the instance of the 'try' class is removed when the say instruction concludes. In this usage, the '.roo' extension is implicitly used when the 'try' class is created. */ say ^^ try( 'abra', 'ca', 'dabra' ) ^ toString() |
Here is the definition of the 'try' class.
/* try.roo -- defines the 'try' class */ local greeting /* greeting is a LOCAL variable -- initialized to '' */ initialize : method greeting = '' do i=1 to arg() greeting = greeting arg( i ) end greeting = strip( greeting ) return '' /* indicates a successful initialization */ toString : /* notice the absence of the METHOD instruction */ return greeting |
The above program shows:
yo dude
abra ca dabra |
Note: the class instruction is absent within the 'try' class definition. Consequently, the class is
defined as a simple
The following environment variables can be specified to customize the execution of
Note: When ROO.DLL is accessed within a different folder (directory) than the location
The optional ROO_ALLOW_UNQUALIFIED_SOURCE environment variable controls whether checking that REXX programs begin with a source comment is made. When the ROO_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 ROO_ALLOW_UNQUALIFIED_SOURCE=N |
When the ROO_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 ROO_ALLOW_UNQUALIFIED_SOURCE=Y |
When the ROO_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 ROO_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,
The ROO_DEFAULT_PROGRAM_EXT environment variable can include multiple alternative extensions separated by semicolons -- such as:
.rooProgram;rex;cmd |
A search for a
The following causes interactive tracing to be activated, with intermediate results listed.
set ROO_EXECTRAC=?i |
roo 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 ROO_TRACE_factorial_ice=?i |
The following causes interactive tracing to be activated, with intermediate results listed, when methods in the mathXX_ice class are invoked.
set ROO_TRACE_CLASS_mathXX_ice=?i |
The following causes interactive tracing to be activated, with intermediate results listed, when the lnGammaFunction method, within the mathXX_ice class, is invoked .
set ROO_TRACE_METHOD_mathXX_ice~lnGammaFunction=?i |
When the first letter of the ROOCOMMANDWAIT is 'Y',
An example of setting the ROOCOMMANDWAITenvironment variable value follows:
set ROOCOMMANDWAIT=Yes
This indicates that
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 ROOLINEBREAK environment variable value follows:
set ROOLINEBREAK=\n
This indicates that lines are terminated by an Ascii line feed only.
The default setting is:
set ROOLINEBREAK=\r\n
Lines can be terminated by other sequences as well, for example:
set ROOLINEBREAK=<br>
Which is the standard HTML line break sequence.
When backslashes are encountered in the ROOLINEBREAK 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 ROOLINEBREAK=\\r\\n
Ends each line with the character sequence '\r\n'.
Note: this environment variable is also used to locate external procedures that are
invoked by the
If the ROOPATH environment variable is not defined, the default path will be the folder (directory) that contains the ROO.EXE module, or the ROO.DLL module.
Hint: if you put the ROO.EXE module, or the ROO.DLL module, in the same directory as
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 |
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
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 ROOPATH=c:\roo!;c:\rexx |
set ROOLINEBREAK=\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.
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' ) ) |
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:\ROO!\HELLO.ROOPROGRAM |
* | (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-roo 4.00 dd Mon yyyy |
where: dd is build day, Mon is build month, yyyy is build year |
Observe: the first word is REXX-rooDLL when
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
Commands sent to the system can include file redirections, and command pipelines. For example:
'dir *.rooProgram | roo! 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 at the end of the command.
The following is an example of the use of the "(stack" command line directive.
'dir *.rooProgram (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 and rooTry.rooProgram examples show 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.rooProgram */
call value 'magic', 'abracadabra', 'system' /* set magic environment variable */ say value( 'magic', , 'system' ) /* get magic environment variable */ |
Access to system registry information allows
Due to the sensitivity of system registry information,
As an extra precaution, registry revisions are only permitted when the ROOREGISTRYWRITE 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 a
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.rooProgram */
root = 'HKEY_CURRENT_USER' keypath = 'Software\Kilowatt Software\DoReg' regvalue = 'Magic' /* enable registry revision */ call value 'ROOREGISTRYWRITE', 'Y', 'system' /* set ROOREGISTRYWRITE=Y */ /* revise registry value */ call value root'\'keypath'['regvalue']', 'abracadabra', 'registry' /* disable registry revision */ call value 'ROOREGISTRYWRITE', 'N', 'system' /* set ROOREGISTRYWRITE=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.
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 |
purge | Erases file if not open. Sets read/write positions to 0 if open.12 | Stream name | N/A |
recycle | Sends file to recycle bin.13 | Stream name | N/A |
1 If the directory name is absent, the CHDIR request returns the currently active directory associated with the current disk.
2 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 |
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.
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 operation of a PURGE request depends on whether the file is currently open or not.
|
13 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. |
The following are examples of STREAM builtin function usage. You can copy the text within these
examples and paste it into your
/* DISKTELL.rooProgram */
say "Current disk:" stream( '', 'C', 'ChDisk' ) say "Current directory:" stream( '', 'C', 'ChDir' ) |
/* DIRS.rooProgram */
ndirs = stream( arg(1), 'c', 'dirs' ) do i=1 to ndirs pull directory say directory end |
/* DRIVES.rooProgram */
ndrives = stream( "", 'c', 'drives' ) do i=1 to ndrives pull drive say drive end |
/* DRIVE.rooProgram */
drive = arg(1) if drive = '' then call drives /* invoke external procedure DRIVES.rooProgram (see above) */ else say stream( drive, 'c', 'drive' ) |
/* EXISTS.rooProgram */
file = arg(1) if stream( file, 'c', 'exists' ) then say 'Yea! File' file 'exists.' else say 'File' file 'DOES NOT exist.' |
/* FILES.rooProgram */
nfiles = stream( arg(1), 'c', 'files' ) do i=1 to nfiles pull file say file end |
/* FILEINFO.rooProgram */
file = arg(1) say stream( file, 'c', 'fileinfo' ) |
/* FILEDATE.rooProgram */
file = arg(1) say word( stream( file, 'c', 'fileinfo' ), 1 ) |
/* FILESIZE.rooProgram */
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.rooProgram */
dir = arg(1) if stream( dir, 'c', 'isdir' ) then say dir 'is a directory.' else say dir 'IS NOT a directory.' |
/* LINEBREAK.rooProgram */
file = arg(1) call stream file, 'c', 'linebreak' \n' |
/* 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 |
There are various occasions when you will want to convert roo! 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.
Note: there is an alternate executable module named: rooChilledOnly.exe. You can distribute chilled files and rooChilledOnly.exe to other users, who have not purchased a product license.
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 (Note: you can use roo instead of r4 to run chill.rex) |
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.
magic = 'abracadabra' ~ changestr( 'abra', 'dabra' ) |
The ANSI variant can be optionally activated by setting the R4_ANSI environment variable to Yes.
The syntax of the function variants is:
result = Changestr( haystack, needle, replacement ) [NetRexx/Roo! variant] |
result = Changestr( needle, haystack, replacement ) [ANSI 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 NetRexx/Roo! variant is illustrated.
say '(dabracaddabra)' changestr( 'abracadabra', 'abra', 'dabra' ) say '(abracadabra)' changestr( 'abracadabra', '', 'dabra' ) |
count = 'abracadabra' ~ countstr( 'abra' ) |
The ANSI variant can be optionally activated by setting the R4_ANSI environment variable to Yes.
The syntax of the function variants is:
result = Countstr( haystack, needle ) [NetRexx/Roo! variant] |
result = Countstr( needle, haystack ) [ANSI 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 NetRexx/Roo! variant is illustrated.
say '(2)' Countstr( 'abracadabra', 'abra' ) 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:
roo! COPYFILE < infile > outfile |
The following shows how the lines of the DIR command can be counted:
DIR /b *.rooProgram | roo! COUNTLINES |
The associated programs follow:
/* COPYFILE.rooProgram -- character version */
do while chars() > 0 call charout , charin() end |
/* COPYFILE.rooProgram -- lines version */
do while lines() > 0 call lineout , linein() end |
/* COUNTLINES.rooProgram -- unredirected version */
lno = 0 do while lines() > 0 lin = linein() lno = lno + 1 end say lno |
/* COUNTLINES.rooProgram -- redirected or pipeline version */
say lines() |
The following is a simple program that interacts with the console user:
/* GREET.rooProgram */
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 all lines from the top of the external data queue to a buffer position within a stack division, only if a prior MAKEBUF position is established. If a prior MAKEBUF position was not established, then a DROPBUF request is ignored -- all lines in the stack division remain.
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.
A dynamic link library version of roo! is also provided. This allows you to use numerous roo! capabilities from a C/C++ program, or similar environment. When built-in functions and built-in classes are used, there is no transformation of a roo! source program. The name of the dynamic link library module is roo.dll.
Note: When ROO.DLL is accessed within a different folder (directory) than the location
The following diagram may help you understand the relationship between a C/C++ program and roo! when the DLL version is used (roo.dll).
The roo.dll module exports the following DLL entry points. The following is an extract of rooDll.h, which is provided as a product distribution file.
Several of the entry points have two alternate forms, with or without an associated callback context. For example, the 'Perform' entry point does not have a callback context, but the PerformWithCallback has a callback context. A callback allows the roo! DLL environment to send information back to the calling C/C++ context. In addition, the C/C++ context can return information to the roo! DLL environment, via the result.
typedef GLOBALHANDLE (CALLBACK* callback_method_t ) ( const char* invocationContext, const char* pCallbackOption, ... ); // set callback function ROODLL_API void WINAPI SetCallback( const char* invocationContext, callback_method_t YourCallbackFunctionName, ... ); // initialize |
The invocationContext and pCallbackOption parameters are values that are meaningful for the calling context. Both of these values are provided to the calling context when a callback operation is performed (see the next section). The YourCallbackFunctionName argument is the name of a function in the calling context. The pInitialProcedure argument is the name of the rooProgram to execute.
Additional arguments can be specified after the pProcedureName, pBuiltinFunctionName, pClassName, and pMethodName parameters; where the ellipses (...) appear. At the end of the argument list you must pass a NULL pointer. When there are no additional arguments, a NULL pointer must be passed after pProcedureName, pBuiltinFunctionName, etc.
Note: you should ensure that the Terminate entry is invoked, before your program concludes. The Terminate entry performs final cleanup for various resources that were used; such as, streams ! If you do not invoke the Terminate entry proper cleanup of these resources may not be possible.
Documentation revision (Tue, 12 Nov 2002):
Observe: a special value is used to indicate optional arguments for built-in functions or class methods. The special value is:
"->nil<-"
The special "->nil<-" is only necessary as a placeholder, when additional actual arguments follow. Trailing "->nil<-" placeholder arguments are unnecessary.
Note also: values returned from built-in functions or class methods may contain binary values. You may encounter difficulties determining the length of the value, if you convert the GLOBALHANDLE to a C/C++ character string (const char*, etc.). To determine the length of the value you should use the GlobalSize Win32 function, with the returned GLOBALHANDLE as an argument.
Logic in the calling C/C++ context can also be invoked by using the roo! callback built-in function. The function signature of a C/C++ callback function is:
GLOBALHANDLE CALLBACK YourCallbackFunctionName( const char* invocationContext, const char* pCallbackOption, ... ); |
The callback built-in function provides the optional additional arguments, which are passed after the pCallbackOption above.
Click here to review the testRooDll.cpp example program that uses the DLL entry points described above.
The roo! DLL now supports invocations by Java native interface (JNI) capability. The supported interfaces are:
// Java interfaces ROODLL_API jstring JNICALL Java_roo_Initialize( JNIEnv* pJavaEnvironment, jobject rJavaObject, jstring sMessageBoxCaption ); ROODLL_API void JNICALL Java_roo_Terminate( JNIEnv* pJavaEnvironment, jobject rJavaObject ); ROODLL_API jstring JNICALL Java_roo_Perform( JNIEnv* pJavaEnvironment, jobject rJavaObject, jstring optionalCallbackMethodName, jstring sProcedureName, jobjectArray aArgument ); // an array of strings -- java: String[ ], can be null ROODLL_API jstring JNICALL Java_roo_ExecuteFunction( JNIEnv* pJavaEnvironment, jobject rJavaObject, jstring optionalCallbackMethodName, jstring sFunctionName, jobjectArray aArgument ); // an array of strings -- java: String[ ], can be null ROODLL_API jstring JNICALL Java_roo_CreateClass( JNIEnv* pJavaEnvironment, jobject rJavaObject, jstring optionalCallbackMethodName, jstring sClassName, jobjectArray aArgument ); // an array of strings -- java: String[ ], can be null ROODLL_API jstring JNICALL Java_roo_InvokeMethod( JNIEnv* pJavaEnvironment, jobject rJavaObject, jstring optionalCallbackMethodName, jstring sInstanceLocator, jstring sMethodName, jobjectArray aArgument ); // an array of strings -- java: String[ ], can be null ROODLL_API jstring JNICALL Java_roo_RemoveInstance( JNIEnv* pJavaEnvironment, jobject rJavaObject, jstring sInstanceLocator ); |
The Java definitions of the JNI interface can be found in distribution file: roo.java. The corresponding class file, roo.class, can be used to perform the invocations.
Note: the roo.java program also includes simple examples of Java callback methods, that are invoked using the roo! callback built-in function.
A simple example program that uses JNI capabilities can be found in distribution file: TestRoo.java.
The MineSwp.java program is an extensive example of the use of roo! capabilities by a Java program. The supporting roo! program is MineSwp.roo. The MineSwp.java program is a Java implementation of the MineSweeper game.
Note: you should ensure that the Java_roo_Terminate entry is invoked, before your program concludes. The Java_roo_Terminate entry performs final cleanup for various resources that were used; such as, streams ! If you do not invoke the Java_roo_Terminate entry proper cleanup of these resources may not be possible.
roo! is accompanied by the Revu text file viewing accessory. This related product is particularly helpful when viewing roo! source files. It is similarly useful for viewing C/C++, Java, JavaScript, Perl, XML and HTML files.
Revu is implicitly used by roo! 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.
The following revisions were made to this document. Document revisions are displayed with blue text on a gray background.
Date | Description |
---|---|
12 Nov 2002 | description of optional DLL invocation arguments description of binary values returned from DLL invocations. |
23 Dec 2002 | added Java native interfaces. |
When
http://www.kilowattsoftware.com/latest/
If you have comments, questions, or concerns regarding