Kilowatt Software L.L.C.
User's Guide

Hop into the future !

# 1 Index

This is the user's guide for Kilowatt Software L.L.C.'s roo!™ product. The guide contains the following sections:

Introduction roo!™ language specification Command line usage Program search Writing your first roo!™ program Program examples Environment variables How to add or revise environment variables Implementation limits Portability considerations Special command redirections -- (stack, <queue, and >queue Ascii character code table Special not-sign (¬) character | ROO_PLUS -- inter-system extensions Tabs and spaces Stream built-in function Stream built-in function examples Preparing binary programs, with CHILL.REX Remarks Dynamic link library (DLL) execution mode Java native interface (JNI) capabilities Document revision history Text file viewing program (Revu™) Product updates Support

# 2 Introduction:

roo!™ is a Classic Rexx language interpreter, with object-oriented extensions. The name roo!™ is derived from the first letters in the following words: Rexx object-oriented. The language's object-oriented extensions are described in the guide you are viewing. Rexx language features are 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. roo!™ 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 roo!™ 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.

# 3 Command line usage:

The roo!™ program operates as a Microsoft® Windows® console application. The following is the syntax of a roo!™ program request, that is entered as a DOS command prompt. There are four variations. In the first variation, roo!™ is the only program that is executed. The remaining variations are command pipelines. The vertical bars separate pipeline command segments.

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 roo!™ program, which has a file name ROO.EXE. You should add the directory that contains ROO.EXE to your system PATH environment variable. See the environment setup section to determine how to revise the PATH environment variable.

The roo!™ program can also process redirected files. The roo!™ program can also participate in command pipelines.

# 4 Required program name argument:

- programName .. the name of the roo!™ program to perform. This can be a partially or fully qualified Microsoft® Windows® file name. An optional default extension is assumed. The default extension can be defined by setting the ROO_DEFAULT_PROGRAM_EXT environment variable. If this environment variable is not defined the default extension is: .rooProgram

  1. The following is an example of a fully qualified program name.
     c:\roo\copyfile.rooProgram

  2. The following is an example of a fully qualified program that lacks a file extension.
     c:\roo\copyfile

  3. The following is an example of a partially qualified program name.
     copyfile.rooProgram

  4. The following is an example of a partially qualified program name that lacks a file extension.
     copyfile

  5. The following is an example of a partially qualified program name that has an empty file extension.
     copyfile.

## 4.1 Program search:

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 roo!™ program.

In the fifth example above, a search for an implicit default program extension will not be conducted.

# 5 Optional additional text arguments:

- argumentText .. argument text that is passed to the top level roo!™ procedure. This text includes all spaces and quotes that were present in the command request.

  Argument text is accessed in the roo!™ procedure by using either the ARG( 1 ) builtin function, the ARG keyword instruction, or the PARSE ARG keyword instruction.

# 6 Writing your first roo!™ program

The following shows how to prepare a roo!™ program called try.rooProgram. It uses a roo!™ class definition called try.roo.

      /* 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 roo!™ class.

# 7 Environment variables:

The following environment variables can be specified to customize the execution of roo!™ programs. For normal program execution you will not need to define any of these environment variables.

Note: When ROO.DLL is accessed within a different folder (directory) than the location roo!™ source files, you will need to assign the ROOPATH environment variable.

ROO_ALLOW_UNQUALIFIED_SOURCE
ROO_ANSI -- ANSI-compatibility option
ROO_DEFAULT_CLASS_EXT
ROO_DEFAULT_PROGRAM_EXT
ROO_EXECTRAC
ROO_TRACE_procedureName
ROO_TRACE_CLASS_className
ROO_TRACE_METHOD_className~methodName
ROOCOMMANDWAIT
ROOLINEBREAK
ROOPATH
ROO_PLUS -- inter-system extensions
R4_STRICT -- strict and non-strict modes
ROO_TRACE_LOCAL -- confine tracing to current procedure level

  ROO_ALLOW_UNQUALIFIED_SOURCE

roo!™ optionally requires source programs to begin with a source comment -- i.e. the first two characters of the first line must be '/*' or '--'. This avoids a nuisance, when files that do not have an extension, are accidently considered to be programs. For example, if you are trying to run program xx.rooProgram, but a data file named XX also exists, the data file could be mistakenly processed as the source program. By assuring that the file begins with a source comment, the data file will be ignored, and the xx.rooProgram program will be properly located instead.

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, roo!™ will process an empty program. When you look at the source of the xx.rooProgram program you will not easily be able to understand why the program is not executed. By defining the ROO_ALLOW_UNQUALIFIED_SOURCE environment variable to 'N' you will not have to endure such aggravation.

  ROO_ANSI -- ANSI-compatibility option

The CHANGESTR and COUNTSTR built-in functions have alternate specifications, ANSI and NetRexx/Roo!™. By default roo!™ supports the NetRexx/Roo!™ specification of these functions. The alternative ANSI behavior can be established by setting the ROO_ANSI environment variable to YES (Default: NO).

  ROO_DEFAULT_CLASS_EXT

the ROO_DEFAULT_CLASS_EXT environment variable establishes the default extension that is used to locate roo!™ class source files. If this environment variable is not defined, the default extension that is used is: .roo

  ROO_DEFAULT_PROGRAM_EXT

the ROO_DEFAULT_PROGRAM_EXT environment variable establishes the default extension that is used to locate roo!™ procedures. If this environment variable is not defined, the default extensions that are used are: .rooProgram;.rex;.cmd

The ROO_DEFAULT_PROGRAM_EXT environment variable can include multiple alternative extensions separated by semicolons -- such as:

.rooProgram;rex;cmd

Note: an implicit period is assumed before an extension.

A search for a roo!™ procedure is performed for the following cases:

1. to find the initial program that is specified on the roo!™ command line
2. to find external procedures that are CALLed as subroutines
3. to find external procedures that are invoked as functions

  ROO_EXECTRAC

the ROO_EXECTRAC environment variable establishes the trace setting when the main procedure is started. The value of the environment variable is processed exactly as though the string was the parameter of the trace built-in function.

The following causes interactive tracing to be activated, with intermediate results listed.

set ROO_EXECTRAC=?i

  Redirecting trace output to a file

Often when you set the ROO_EXECTRAC environment variable, you would also like trace output written to a file instead of the display. In Microsoft® Windows® XP environments you can redirect trace output to a file. This is done as follows:

roo progName > outFile 2>&1

The above redirects the output of progName to outFile. Trace output will also be present in outFile.

  ROO_TRACE_procedureName

the ROO_TRACE_procedureName environment variable establishes the trace setting when a specific procedure is invoked. The value of the environment variable is processed exactly as though the string was the parameter of the trace built-in function.

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

  ROO_TRACE_CLASS_className

the ROO_TRACE_CLASS_className environment variable establishes the trace setting when a methods of a specific class are invoked. The value of the environment variable is processed exactly as though the string was the parameter of the trace built-in function.

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

  ROO_TRACE_METHOD_className~methodName

the ROO_TRACE_METHOD_className~methodName environment variable establishes the trace setting when a specific class method is invoked. The value of the environment variable is processed exactly as though the string was the parameter of the trace built-in function.

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

  ROOCOMMANDWAIT

The optional ROOCOMMANDWAIT environment variable identifies when roo!™ should wait for the completion of commands. This option is necessary when a command will operate as an interactive Microsoft® Windows® application. roo!™ always waits for the completion of internal system commands; such as, MORE or XCOPY.

When the first letter of the ROOCOMMANDWAIT is 'Y', roo!™ will wait for the completion of commands which are Microsoft® Windows® applications. Otherwise, roo!™ will use the system command processor to process the command.

An example of setting the ROOCOMMANDWAITenvironment variable value follows:
set ROOCOMMANDWAIT=Yes
This indicates that roo!™ will wait for the completion of commands which are Microsoft® Windows® applications.

  ROOLINEBREAK

The optional ROOLINEBREAK environment variable identifies characters that terminate lines that are written by the LINEOUT builtin function. The ROOLINEBREAK environment variable also identifies character line terminators for selector pools that are accessed by the VALUE builtin function.

The ROOLINEBREAK environment variable has no effect on the characters that terminate lines that are read by the LINEIN builtin function. See the LINEIN terminators section below.

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'.

  ROOPATH

The optional ROOPATH environment variable identifies a sequence of one or more Microsoft® Windows® directories separated by semicolons. These define the directories that will be searched for the roo!™ program that is performed. The Program Search section above describes how roo!™ programs are located.

Note: this environment variable is also used to locate external procedures that are invoked by the roo!™ program.

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 r4™ then roo!™ will automatically locate r4™ programs.

  ROO_PLUS -- inter-system extensions

roo!™ can provide compatibility with other REXX environments, when the ROO_PLUS environment variable is set to YES (Default: NO). The following additional capabilities are provided:

  +1. Assignment instructions without expressions

Some REXX language processors allow assignment expressions to lack expressions after the equal sign. In this case, the variable is set to the empty string. For example,

      v1 =
      v2 =
      v3 = ''
      parse value with v4 v5 v6

All six variables above are initialized to the empty string.

  +2. UPPER instruction

Some REXX language processors provide the UPPER instruction, which converts the value of one or more variables to uppercase. For example,

      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

  +3. parse EXTERNAL

Some REXX language processors use the EXTERNAL keyword with the PARSE instruction. This is equivalent to the LINEIN keyword. For example,

      say 'what is your name ?'

      parse EXTERNAL name

      say 'Hello' name

  ROO_STRICT -- strict and non-strict modes

roo!™ can provide compatibility with other REXX environments, that have relaxed conformance with REXX language specifications. This is accomplished by setting the ROO_STRICT environment variable to NO (Default: YES). In this case, the following is permitted:

      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 roo!™ operates in strict mode.

  ROO_TRACE_LOCAL -- confine tracing to current procedure level

roo!™ can optionally confine tracing to the current procedure level, instead of tracing into internal or external procedures. This can be helpful when you are trying to locally debug a specific procedure, independently of the subroutines or functions that it invokes. This is accomplished by setting the ROO_TRACE_LOCAL environment variable to YES (Default: NO).

## 7.1 How to define or revise an environment variable,
in Microsoft® Windows® NT/2000/XP

1. Select 'Settings' of the 'Start' menu.
2. Select the 'System' applet on the 'Control Panel',
3. Click the 'Environment' tab.
4. Locate the variable name in the 'System' or 'User' list if you are revising an existing value.
5. Or, enter the variable name in the 'Variable' input field.
6. Type or revise the value of the variable in the 'Value' input field.
7. Click the 'Set' button.
8. Click the 'OK' button.

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.

## 7.2 How to define or revise an environment variable,
in Microsoft® Windows® 98 or ME

1. Edit the C:\AUTOEXEC.BAT file

2. If you are adding an environment variable, add a line similar to the following:

   set ROOPATH=c:\roo!;c:\rexx
   set ROOLINEBREAK=\n

3. If you are revising the PATH or ROOPATH environment variable, locate a line similar to the following:

   set PATH=c:\windows;c:\windows\system32

   Add the new directory to the path, separating it from other directories by a semicolon.

4. Save your changes to the AUTOEXEC.BAT.

5. Then, restart your computer so that the AUTOEXEC.BAT file changes will take effect.

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.

# 8 Implementation limits:

roo!™ 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.

1. The largest C2D result is 18446744073709551615.

2. The largest D2C numeric argument is 18446744073709551615.

3. The largest D2X numeric argument is 18446744073709551615.

4. The largest X2D numeric argument is 'FFFFFFFFFFFFFFFF'x => 18446744073709551615.

5. File stream accesses are buffered in memory until the roo!™ program finishes processing.

   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.

# 9 Portability considerations:

1. The Microsoft® Windows® environment uses text characters that are encoded in the Ascii representation. This differs significantly from the EBCDIC representation that is used on IBM mainframe computers. The following is the character layout of the Ascii representation:

   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' ) )

2. Tab characters within text values are problematic, as these have an appearance similar to spaces. The roo!™ implementation attempts to treat tabs as equivalent to spaces for most circumstances where spaces have special meaning; such as, the WORD... set of builtin functions. Tabs are also considered equivalent to spaces within the value that is parsed by the PARSE, ARG, and PULL keyword instructions. You can parse for an explicit tab character in the PARSE, ARG, and PULL keyword instructions by specifying '09'x in the parse template.

3. The standard character that is supported for the not operator is a backslash ('\'). A backslash is the only not operator character that is recommended in Ansi REXX. r4™ also accepts the Ascii code page 37 'AA'x character (¬) as an alternate not-sign character. If you are porting programs to/from mainframe environments, then you should ensure that the mainframe not-sign character ('5F'x) is converted to an Ascii 'AA'x character. You can make this character appear like a not-sign character in your programs if you set your editor's font to OEM Fixed.

4. When the first word of a command is the name of an roo!™ program, the program is invoked as an external procedure. The remainder of the command line is passed as the first and only argument of the external procedure. For example:
   'execio * diskr INDD (LIFO OPEN FINIS'
   Invokes EXECIO.REX as an external procedure, if EXECIO.REX can be located by a procedure search (ROOPATH).
   (EXECIO.REX is distributed in R4.ZIP)

   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 !

5. roo!™ allows an external procedure to begin with the PROCEDURE instruction. This enables exposure of the caller's variables to the external procedure. In addition, the EXPOSEALL keyword is supported on the PROCEDURE instruction.
   The example EXECIO.REX program uses the EXPOSEALL keyword, in order to reference or revise the caller's stem variables.

6. The TRL-2 book does not specify the following capabilities that are found in some other REXX programming environments:

   MAKEBUF command
   DROPBUF command
   NEWSTACK command
   DELSTACK command
   EXECIO command

   All of the above commands, except EXECIO, are implemented internally within roo!™. The EXECIO command is supported in EXECIO.REX (in R4.ZIP), which is an external procedure that executes as a command.

7. The positional values associated with the SOURCE option of the PARSE keyword instruction are:

   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.

8. The value associated with the VERSION option of the PARSE keyword instruction is:

   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 roo!™ is processing in dynamic link library (DLL) mode.

9. Lines that are read by the LINEIN builtin function are terminated when one of the following Ascii character sequences is discovered:

   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.

10. The CHARIN builtin function obtains all character values, including line terminators, exactly as these arrive from the input stream.

11. The CHAROUT builtin function writes all character values, including line terminators, exactly as these are passed in the string value. Isolated line feed or carriage return characters are not converted to a carriage return THEN line feed sequence, as performed by other programming languages.

12. When the selector option of the VALUE function is specified, it is interpreted as follows:

    - If the selector option is 'system', then values are associated with environment variables of the roo!™ program scope. Revisions to environment variables will be seen by commands started by roo!™. These revisions are lost when the roo!™ program concludes. Thus, roo!™ programs can not permanently alter environment variables.

      The environment variable access section below shows how to set and reference environment variable values.

    - The 'registry' selector option is used to access and revise system registry values. Revisions to registry values are permanently altered.

      The registry value access section below shows how to access and revise system registry values.

    - Any other selector option is considered to be the name of a file. If the file name does not have a backslash, then the file is stored in the same directory as ROO.EXE. Values are stored when the roo!™ program terminates. These values are restored when the selector pool with the same name is referenced in a subsequent roo!™ program execution.

      Observe: if temporary is contained anywhere within the name of the selector pool then values are not saved when the roo!™ program terminates.

13. Interactive trace requests can not exceed 255 characters.

14. The only supported address associated with the ADDRESS keyword instruction is:
    'system'
    which is the Microsoft® Windows® system command interpreter.

    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.

15. External procedures are programmed in REXX only -- EXEs are not invoked.

16. The trace marker >A> indicates variable assignment.

17. Trace markers >V> and >A> show the associated variable name in square brackets at the end of the trace output line.

18. roo!™ supports the special "(stack" command line directive. The end of a command is compared with the characters " (stack", which can include upper case characters. When this special directive is specified, the command's standard output lines are queued to the roo!™ external data queue.

    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

19. Similarly, roo!™ supports special "<!queue" and ">!queue" command redirection requests, each of which may include upper case characters. When the "<!queue" directive is specified, contents of the external data queue are passed to the command's standard input stream. When the ">!queue" directive is specified, the command's standard output lines are queued to the R4 external data queue.

    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'

20. The HALT condition is activated, from the keyboard, by pressing either the Ctrl and the C keys simultaneously, or by pressing the Ctrl and the Break keys simultaneously. There are two Ctrl keys, on either side of the space bar. The Break key is usually near the top right of the keyboard.

    The rexxtry.rex and rooTry.rooProgram examples show how the HALT condition can be handled.

21. When a '1A'X character is written to the default output stream it acts as an explicit end of file character. This is standard operational behavior for Microsoft® Windows® system environments. This impacts output that is written to the console, to a redirected file, or in command pipeline redirections. Subsequent output written to the default output stream is not transferred.

    A '1A'X character can be written to output streams that are associated with disk files. Subsequent output will appear in the disk files.

## 9.1 Environment variable access

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 */

## 9.2 Registry value access

Access to system registry information allows roo!™ 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, roo!™ 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, roo!™ 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 roo!™ must be strings. No other registry value format is supported.

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 roo!™ 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.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' )

# 10 STREAM builtin function

The implementation of the STREAM builtin function is customized to the Microsoft® Windows® system environment. roo!™ 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.

## 10.1 Supported STREAM commands

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

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.

## 10.2 STREAM builtin function examples

The following are examples of STREAM builtin function usage. You can copy the text within these examples and paste it into your roo!™ programs.

/* 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'

# 11 Preparing binary programs, with CHILL.REX

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.

## 11.1 Executing CHILL.REX

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)

### 11.1.1 The .\ice subdirectory contains 'chilled' programs

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

### 11.1.2 The .\iceSource subdirectory contains source of 'chilled' programs

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.

### 11.1.3 Log of 'chilled' programs

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:

1. Search for the name of the '_ice' file
2. Make sure the file date and time match the '_ice' files date and time
3. The name of the corresponding source file is contained on the same line

### 11.1.4 Other CHILL.REX considerations

- The related CHILL.EXE program performs the associated encryption.
- There is no means of thawing a chilled program.
- When chilled programs are executed, the SOURCELINE built-in function shows:

  'sourceFile_ice.rex #N .. source is unavailable' or, 'sourceFile_ice.rooProgram #N .. source is unavailable' or, 'sourceFile_ice.roo #N .. source is unavailable'

- Similar, output is displayed when errors occur, or during trace output.
- You can 'trace' the activities of chilled programs, by using the following environment variables.

  ROO_EXECTRAC

  ROO_TRACE_procedureName

  ROO_TRACE_CLASS_className

  ROO_TRACE_METHOD_className~methodName

## 11.2 Remarks:

1. If you are going to use stream output to replace the contents of an existing file, you probably want to ERASE the file beforehand. Otherwise, if the new content is less extensive than the file's prior contents, then some of the prior contents will remain at the end. This phenomenon is quite surprising when you first encounter it.

2. The MS-DOS® environment supported various escape sequences for changing the screen via the ANSI.SYS driver. Among the escape sequences was the ability to alter the foreground color of text, and the corresponding background color. When text is written to the display (via CHAROUT, LINEOUT, or SAY) roo!™ emulates the ANSI.SYS escape sequences that alter text foreground and background color. A text escape sequence is coded as '1B'x (ESC), followed by '[', a series of decimal numbers separated by semicolons, and concludes with a lower case 'm'. The following shows the word Hello with a yellow foreground color, and a black background color.

   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.

3. The Changestr builtin function is provided for compatibility with other REXX implementations. There are 2 variants of the Changestr function -- ANSI and NetRexx/Roo!™. By default roo!™ supports the NetRexx/Roo!™ variant. This allows a Changestr request to be performed as a method invocation:

         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' )

4. The Countstr builtin function is provided for compatibility with other REXX implementations. There are 2 variants of the Countstr function -- ANSI and NetRexx/Roo!™. By default roo!™ supports the NetRexx/Roo!™ variant. This allows a Countstr request to be performed as a method invocation:

         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', '' )

5. The Find builtin function is provided for compatibility with other REXX implementations. The function syntax is:

   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.

6. The Index builtin function is provided for compatibility with other REXX implementations. The function syntax is:

   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.

7. The Justify builtin function is provided for compatibility with other REXX implementations. The function syntax is:

   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 )

8. The Linesize builtin function is provided for compatibility with other REXX implementations. The function syntax is:

   result = Linesize( )

   The result of the Linesize function is the number of characters per console line -- i.e. 80.

9. The Qualify builtin function is provided for compatibility with other REXX implementations. The function syntax is:

   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 !!!

10. The Scrsize builtin function is provided for compatibility with other REXX implementations. The function syntax is:

    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).

11. The Userid builtin function is provided for compatibility with other REXX implementations. The function syntax is:

    result = Userid( )

    The result is set to: ComputerName/Userid

    The following is an example of the operation of the Userid function.

          parse value userid() with ComputerName '/' UserName
          say 'Hello' UserName'.'
          say 'Your computer name is:' ComputerName'.'

12. The following commands are performed within roo!™. The modifications associated with these are effective within roo!™ program's execution scope. When roo!™ returns the prior state is automatically restored.

    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.

13. The default input stream and default output stream are connected to the standard Microsoft® Windows® files that are identified as stdin and stdout respectively. This allows your REXX programs to operate with redirected files, and participate in command pipelines. Consult Microsoft® Windows® documentation for the use of file redirection and command pipelines.

    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()

14. 'console' is a special stream name. Stream builtin functions that access the 'console' stream interact with the Microsoft® Windows® command console. A single exclamation point ('!') is an abbreviated alias for the 'console' stream.

    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.

15. The CHARS and LINES functions operate differently, depending on whether input is being typed from the keyboard, or received from a file.

    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.

16. The MAKEBUF, DROPBUF, NEWSTACK, and DELSTACK commands are builtin into the roo!™ command environment. These builtin commands are provided for compatibility with other REXX implementations; such as, IBM's MVS TSO and VM implementations. All of these commands have no additional arguments.

    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.

## 11.3 Dynamic link library (DLL) execution mode

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 roo!™ source files, you will need to assign the ROOPATH environment variable.

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 roo!™ DLL usage

    	ROODLL_API void WINAPI Initialize(
    		LPCTSTR pMessageBoxCaption );

    	// conclude roo!™ DLL usage

    	ROODLL_API void WINAPI Terminate();

    	// perform roo!™ external procedure

    	ROODLL_API GLOBALHANDLE WINAPI Perform(
    		LPCTSTR pProcedureName,
    		... );

    	ROODLL_API GLOBALHANDLE WINAPI PerformWithCallback(
    		LPCTSTR invocationContext,
    		LPCTSTR pCallbackOption,
    		LPCTSTR pProcedureName,
    		... );

    	// perform roo!™ built-in function

    	ROODLL_API GLOBALHANDLE WINAPI ExecuteFunction(
    		LPCTSTR pBuiltinFunctionName,
    		... );

    	// create roo!™ class instance

    	ROODLL_API GLOBALHANDLE WINAPI CreateClass(
    		LPCTSTR pClassName,
    		... );

    	ROODLL_API GLOBALHANDLE WINAPI CreateClassWithCallback(
    		LPCTSTR invocationContext,
    		LPCTSTR pCallbackOption,
    		LPCTSTR pClassName,
    		... );

    	// invoke roo!™ class instance method

    	ROODLL_API GLOBALHANDLE WINAPI InvokeMethod(
    		LPCTSTR pInstanceLocator,
    		LPCTSTR pMethodName,
    		... );

    	ROODLL_API GLOBALHANDLE WINAPI InvokeMethodWithCallback(
    		LPCTSTR invocationContext,
    		LPCTSTR pCallbackOption,
    		LPCTSTR pInstanceLocator,
    		LPCTSTR pMethodName,
    		... );

    	// remove roo!™ class instance

    	ROODLL_API GLOBALHANDLE WINAPI RemoveInstance(
    		LPCTSTR pInstanceLocator,
    		... );

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.

### 11.3.1 Invoking logic in the C/C++ caller's context (DLL callback)

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.

#### 11.3.1.1 DLL usage example program

Click here to review the testRooDll.cpp example program that uses the DLL entry points described above.

#### 11.3.1.2 Java native interface (JNI)

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.

## 11.4 Text file viewing program --Revu™

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.

## 11.5 Document revision history

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.

### 11.5.1 Product updates:

When roo!™ is updated, the latest version of ROO.EXE and the updated User's Guide ROO.HTM can be found in the following internet location:
http://www.kilowattsoftware.com/latest/

roo!™ programming examples may be found in the same location. These are files that have a '.rooProgram', or '.roo' extension.

### 11.5.2 Support:

If you have comments, questions, or concerns regarding roo!™ you can send these via e-mail to:

E-Mail: rooSupport@kilowattsoftware.com

Enjoy roo!™ -- hop into the future !

Kilowatt Software L.L.C. also offers:
r4™ -- A Classic Rexx interpreter
Poof!™ -- A collection of Microsoft® Windows® command line utilities
AuroraWare!™ -- A collection of helpful Microsoft® Windows® visual accessories

r o o ! ™
Copyright © 2002-2007
All Rights Reserved.
E-Mail: rooSupport@kilowattsoftware.com

Last updated on: 5 Jan 2007