Make your own free website on
5.13.11 Stream I/O in BRexx 1.0b
BRexx contains a set of I/O which shows very close relations with
the C programming language I/O library. In fact, you should
consider consulting the C library documentation for in-depth
documentation on this functionality.

BRexx contains a two-level naming scheme: in REXX, streams are
referred to by a stream handle, which is an integer; in the
operating system files are referred to by a file name, which is a
normal string.  The function OPEN() is used to bind a file name to
a stream handle. However, BRexx I/O functions generally have the
ability to get a reference either as a file name and a stream
handle, and open the file if appropriate. However, if the name of
a file is an integer which can be interpreted as a file descriptor
number, it is interpreted as a descriptor rather than a name.
Whenever you use BRexx and want to program robust code, always use
OPEN() and the descriptor.

If a file is opened by specifying the name in a I/O operation
other than OPEN(), and the name is an integer and only one or two
higher than the highest current file descriptor, strange things
may happen.

Five special streams are defined,  having the pseudo file names:
<STDIN>, <STDOUT>, <STDERR>, <STDAUX>, and <STDPRN>; and are
assigned pre-defined stream handles from 0 to 4, respectively.
These refer to the default input, default output, and default
error output, default auxiliary output, and printer output. The
two last generally refer to the COM1: and LPT1: devices under MS-
DOS. Either upper or lower case letter can be used when referring
to these four special names.

However, note that if any of these five special files are closed,
they can not be reopened again. The reopened file will be just a
normal file, having the name e.g. <STDOUT>.

There is a few things you should watch out for with the special
files.  I/O involving the <STDAUX> and <STDPRN> can cause the
Abort, Retry, Ignore message to be shown once for each character
that was attempted read or written. It can be boring and tedious
to answer R or I if the text string is long. If A is answered,
BRexx terminates.

You should never write data to file descriptor 0 (<STDIN>),
apparently, it will only disappear. Likewise, never read data to
file descriptors 1 and 2 (<STDOUT> and <STDERR>), the former seems
to terminate the program while the latter apparently just returns
the nullstring. Also be careful with reading from file descriptors
3 and 4, since your program may hang if no data is available.


The OPEN() built-in function opens a file named by file, in mode
mode, and returns an integer which is the number of the stream
handle assigned to the file. In general, the stream handle is a
non-negative integer, where 0 to 4 are pre-defined for the default
streams. If an error occurred during the open operation, the value
-1 is returned.

The mode parameter specifies the mode in which the file is opened.
It consists of two parts: the access mode, and the file mode.  The
access mode part consists of one single character, which can be r
for read, w for write, and a for append. In addition, the +
character can be appended to open a file in both read and write
mode.  The file mode part can also have of one additional
character which can be t for text files and b for binary files.
The t mode is default.

The following combinations of + and access mode are possible:

r is non-destructive open for reading; w is destructive open for
write-only mode; a is non-destructive open for in append-only
mode, i.e. only write operations are allowed, and all write
operations must be performed at the end-of-file; r+ is non-
destructive open for reading and writing; w+ is destructive open
for reading and writing; and a+ is non-destructive open in append
update, i.e. reading is allowed anywhere, but writing is allowed
only at end-of-file. Destructive mode means that the file is
truncated to zero length when opened.

In addition, the b and t characters can be appended in order to
open the file in binary or text mode.

These modes are the same as under C, although the t mode character
is strictly not in ANSI C. Also note that r, w, and a are mutually
exclusive, but one of them must always be present. The mode + is
optional, but if present, it must always come immediately after r,
w, or a. The t and b modes are optional and mutually exclusive;
the default is t. If present, t or b must be the last character in
the mode string.

               open(‘myfile’  7 perhaps
               open(‘no.such  - if non-existent
               .file’,’r’)    1
               open(‘c:tmp’,  6 perhaps

If two file descriptors are opened to the same file, only the most
recently of them works. However, if the most recently descriptor
is closed, the least recently starts working again. There may be
other strange effects too, so try avoid reopening a file that is
already open.


The CLOSE() built-in function closes a file that is already open.
The parameter file can be either a stream handle returned from
OPEN() or a file name which has been opened (but for which you do
not known the correct stream handle).

The return value of this function seems to be the nullstring in
all cases.

               close(6)     if open
               close(7)     if not open
               close(‘f     perhaps


The EOF() built-in function checks the end-of-file state for the
stream given by file, which can be either a stream descriptor or a
file name. The value returned is 1 if the end-of-file status is
set for the stream, and 0 if it is cleared. In addition, the value
-1 is returned if an error occurred, for instance if the file is
not open.

The end-of-file indicator is set whenever an attempt was made to
read at least one character past the last character of the file.
Note that reading the last character itself will not set the end-
of-file condition.

               eof(foo)    0  if not at eof
               eof(‘8’)    1  if at eof
               eof(‘  -  if file isn’t open
               ch.file’)   1


The READ() built-in function reads data from the file referred to
by the file parameter, which can be either a file name or a stream
descriptor. If it is a file name, and that file is not currently
open, then BRexx opens the file in mode rt. The default value of
the first parameter is the default input stream.  The data is read
from and including the current position.

If the length parameter is not specified, a whole line is read,
i.e. reading forwards to and including the first end-of-line
sequence.  However, the end-of-line sequence itself is not
returned.  If the length parameter is specified, it must be a non-
negative integer, and specified the number of characters to read.

The data returned is the data read, except that if length is not
specified, the terminating end-of-line sequence is stripped off.
If the last line of a file contains a string unterminated by the
end-of-string character sequence, then the end-of-file is
implicitly interpreted as an end-of-line. However, in this case
the end-of-file state is entered, since the end-of-stream was
found while looking for an end-of-line.

               read(‘   one    reads a complete line
               foo’)    line
               read(‘   anoth  reads parts of a line
               read(6   er     using a file descriptor
               )        line
               read()   hello  perhaps, reads line from
                        there  default input stream


The WRITE() built-in function writes a string of data to the
stream specified by the file parameter, or by default the default
output stream. If specified, file can be either a file name or a
stream descriptor. If it is a file name, and that file is not
already open, it is opened using wt mode.

The data written is specified by the string parameter.

The return value is an integer, which is the number of bytes
written during the operation. If the file is opened in text mode,
all ASCII newline characters are translated into ASCII CRLF
character sequences. However, the number returned is not affected
by this translation; it remains independent of any text of binary
mode.  Unfortunately, errors while writing is seldom trapped, so
the number returned is generally the number of character that was
supposed to be written, independent of whether they was actually
written or not.

If a third parameter is specified, the data is written as a line,
i.e. including the end-of-line sequence. Else, the data is written
as-is, without any end-of-line sequence. Note that with BRexx, the
third parameter is considered present if at least the comma in
front of it—-the second comma—-is present. This is a bit
inconsistent with the standard operations of the ARG() built-in
function. The value of the third parameter is always ignored, only
its presence is considered.

If the second parameter is omitted, only an end-of-line action is
written, independent of whether the third parameter is present or

               write(‘bar’,  4    writes four bytes
               write(‘bar’,  4+   write a line
               ’data’,’nl’)  ??
               write(‘bar’,  4+   same as previous
               ’data’,)      ??


The SEEK() built-in function moves the current position to a
location in the file referred to by file. The parameter file can
be either a file name (which must already be open) or a stream
descriptor. This function does not implicitly open files that is
not currently open.

The parameter offset determines the location of the stream and
must be an integer. It defaults to zero. Note that the addressing
of bytes within the stream is zero-based.

The third parameter can be any of TOF, CUR, or EOF, in order to
set the reference point in which to recon the offset location. The
three strings refer to top-of-file, current position, and end-of-
file, and either upper or lower case can be used. The default
value is ???.

The return value of this function is the absolute position of the
position in the file after the seek operation has been performed.

The SEEK() function provides a very important additional feature.
Whenever a file opened for both reading and writing has been used
in a read operation and is to be used in a write operation next
(or vice versa), then a call to SEEK() must be performed between
the two I/O calls. In other words, after a read only a seeking and
reading may occur; after a write, only seeking and writing may
occur; and after a seek, reading, writing, and seeking may occur.