5.13.9 Stream I/O in ARexx 1.15
ARexx differs considerably from standard REXX with respect to
stream I/O. In fact, none of the standard stream functionality of
REXX is available in ARexx. Instead, a completely distinct set of
functions are used. The differences are so big, that it is useless
to describe ARexx stream I/O in terms of standard REXX stream I/O,
and everything said so far in this chapter is irrelevant for
ARexx. Therefore, we explain the ARexx functionality from scratch.

All in all, the ARexx file I/O interface resembles the functions
of the Standard C I/O library, probably because ARexx is written
in C, and the ARexx I/O functions are “just” interfaces to the
underlying C functions. You may want to check up the documentation
for the ANSI C I/O library as described in [ANSIC], [KR], and
[PJPlauger].

ARexx uses a two level naming scheme for streams. The file names
are bound to a stream name using the OPEN() built-in function. In
all other I/O functions, only the stream name is used.


OPEN(name,filename[,mode])

You use the OPEN() built-in function to open a stream connected to
a file called filename in AmigaDOS. In subsequent I/O calls, you
refer to the stream as name. These two names can be different.

The name parameter cannot already be in use by another stream.  If
so, the OPEN() function fails. Note that the name parameter is
case-sensitive. The filename parameter is not strictly case-
sensitive: the case used when creating a new file is preserved,
but when referring to an existing file, the name is case-
insensitive. This is the usual behavior of AmigaDOS.

If any of the other I/O operations uses a stream name that has not
been properly opened using OPEN(), that operation fails, because
ARexx has no auto-open-on-demand feature.

The optional parameter mode can be any of Read, Write, or Append.
The mode Read opens an existing file and sets the current position
to the start of the file. The mode Append is identical to Read,
but sets the current positions to the end-of-file. The mode Write
creates a new file, i.e. if a file with that name already exists,
it is deleted and a new file is created. Thus, with Write you
always start with an empty file.  Note that the terms “read,”
“write,” and “append” are only remotely connected to the mode in
which the file is opened.  Both reading and writing are allowed
for all of these three modes; the mode names only reflect the
typical operations of these modes.

The result from OPEN() is a boolean value, which is 1 if a file by
the specified name was successfully opened during the OPEN() call,
and 0 otherwise.

The number of simultaneously open files is no problem because
AmigaDOS allocates files handles dynamically, and thus only
limited by the available memory. One system managed 2000
simultaneously open files during a test.

    OPEN(‘infile’,‘work:DataFile’)      1 if successful
               
    OPEN(‘work’,‘RAM:FooBar’,‘Read’)    0 if didn’t exist

    OPEN(‘output’, ‘TmpFile’,‘W’)       1 (re)creates file
               


CLOSE(name)

You use the CLOSE() built-in function to close a stream.  The
parameter name must match the first parameter in a call to OPEN()
earlier in the same program, and must refer to an open stream.
The return value is a boolean value that reflects whether there
was a file to close (but not whether it was successfully closed).

               CLOSE(‘in file’)  1 if stream was previously
                                   open
               CLOSE(‘outfile’)  0 if stream wasn’t previously
                                   open


WRITELN(name,string)

The WRITELN() function writes the contents of string as a line to
the stream name. The name parameter must match the value of the
first parameter in an earlier call to OPEN(), and must refer to an
open stream. The data written is all the characters in string
immediately followed by the newline character (ASCII <Ctrl-J> for
AmigaDOS).

The return value is the number of characters written, including
the terminating newline. Thus, a return value of 0 indicates that
nothing was written, while a value which is one more than the
number of characters in string indicates that all data was
successfully written to the stream.

When writing a line to the middle of a stream, the old contents is
written over, but the stream is not truncated; there is no way to
truncate a stream with the ARexx built-in functions. This
overwriting can leave partial lines in the stream.

    WRITELN(‘tmp’, ‘Hello, world!’)      1  if successful
                                         4
    WRITELN(‘work’, ‘Hi there’)          0  nothing was
                                            written
    WRITELN(‘tmp’, ‘Hi there’)           5  partially
                                            successful


WRITECH(name,string)

The WRITECH() function is identical to WRITELN(), except that the
terminating newline character is not added to the data written
out.  Thus, WRITELN() is suitable for line-wise output, while
WRITECH() is useful for character-wise output.

    WRITECH(‘tmp’,   ‘Hello, world!’)    1  if successful
                                         3
    WRITECH(‘work’, ‘Hi there’)          0  nothing was
                                            written
    WRITECH(‘tmp’, ‘Hi there’)           5  partially
                                            successful


READLN(name)

The READLN() function reads a line of data from the stream
referred to by name. The parameter name must match the first
parameter of an earlier call to OPEN(), i.e. it must be an open
stream.

The return value is a string of characters which corresponds to
the characters in the stream from and including the current
position forward to the first subsequent newline character found.
If no newline character is found, the end-of-file is implicitly
interpreted as a newline and the end-of-file state is set.
However, the data returned to the user never contains the
terminating end-of-line.

To differ between the situation where the last line of the stream
was implicitly terminated by the end-of-file and where it was
explicitly terminated by an end-of-line character sequence, use
the EOF() built-in function. The EOF() returns 1 in the former
case and 0 in the latter case.

There is a limit in ARexx on the length of lines that you can read
in one call to READLN(). If the length of the line in the stream
is more than 1000 characters, then only the first 1000 characters
are returned. The rest of the line can be read by additional
READLN() and READCH() calls. Note that whenever READLN() returns a
string of exactly 1000 characters, then no terminating end-of-line
was found, and a new call to READLN() must be executed in order to
read the rest of the line.

               READLN(‘tmp’)  Hello     maybe
                              world!
               READLN(‘work’)           maybe, if
                                        unsuccessful


READCH(name[,length])

The READCH() built-in function reads characters from the stream
named by the parameter name, which must correspond to the first
parameter in a previous call to OPEN(). The number of characters
read is given by length, which must be a non-negative integer.
The default value of length is 1.

The value returned is the data read, which has the length
corresponding to the length parameter if no errors occurred.

There is a limit in ARexx for the length of strings that can be
read in one call to READCH(). The limit is 65535 bytes, and is a
limitation in the maximum size of an ARexx string.

               READCH(‘tmp’,3)  Hel     maybe
               
               READCH(‘tmp’)    l       maybe
               
               READCH(‘tmp’,6)  oworl   maybe
                                
                                


EOF(name)

The EOF() built-in function tests to see whether the end-of-file
has been seen on the stream specified by name, which must be an
open stream, i.e. the first parameter in a previous call to
OPEN().

The return value is 1 if the stream is in end-of-file mode, i.e.
if a read operation (either READLN() or READCH()) has seen the end-
of-file during its operation. However, reading the last character
of the stream does not put the stream in end-of-file mode; you
must try to read at least one character past the last character.
If the stream is not in end-of-file mode, the return value is 0.

Whenever the stream is in end-of-file mode, it stays there until a
call to SEEK() is made. No read or write operation can remove the
end-of-file mode, only SEEK() (and closing followed by reopening).

               EOF(‘tmp’)   0   maybe
               
               EOF(‘work’)  1   maybe
               


SEEK(name,offset[,mode])

The SEEK() built-in function repositions the current position of
the file specified by the parameter name, which must correspond to
an open file, i.e. to the first parameter of a previous call to
OPEN(). The current position in the file is set to the byte
referred to by the parameter offset. Note that offset is zero-
based, so the first byte in the file is numbered 0. The value
returned is the current position in the file after the seek
operation has been carried through, using Beginning mode.

If the current position is attempted set past the end-of-file or
before the beginning of the file, then the current position is not
moved, and the old current position is returned. Note that it is
legal to position at the end-of-file, i.e. the position
immediately after the last character of the file. If a file
contains 12 characters, the valid range for the resulting new
current position is 0—12.

The last parameter, mode, can take any of the following values:

Beginning, Current, or End. It specify the base of the seeking,
i.e. whether it is relative to the first byte, the end-of-file
position, or the old current position. For instance: for a 20 byte
file with current position 3, then offset 7 for base Beginning is
equivalent to offset —13 for base End and offset 4 for Current.
Note that only the first character of the mode parameter is
required, the rest of that parameter is ignored.

               SEEK(‘tmp’,      1  if successful
               12, ‘B’)         2
               SEEK(‘tmp’, -    1  if previously at 12
               4, ‘Begin’)      2
               SEEK(‘tmp’, -    2  if length is 30
               10, ‘E’)         0
               SEEK(‘tmp’, 5)   1  if previously at 12
                                7
               SEEK(‘tmp’, 5,   1  only first character
               ‘Celcius’)       7  in mode matters
               SEEK(‘tmp’, 0,   0  always to start of
               ‘B’)                file



PREV NEXT