5.13.7 Stream I/O in Regina 0.07a
Regina implements stream I/O in a fashion that closely resembles
how it is described in TRL2. The following list gives the relevant
system-specific information.
[Names for standard streams.]
Regina uses <stdout> and <stdin> as names for the standard
output and input streams. Note that the angle brackets are
part of the names. You may also access the standard error
stream (on systems supporting this stream) under the name
<stderr>. In addition, the nullstring is taken to be
equivalent to an empty first parameter in the I/O-related
built-in functions.
[Implicit opening.]
Regina implicitly opens any file whenever it is first used.
If the first operation is a read, it will be opened in read-
only mode. If the first operation is a write, it is opened in
read-write mode. In this case if the read-write opening does
not succeed, the file is opened in write-only mode. If the
file exists, the opening is non-destructive, i.e. that the
file is not truncated or overwritten when opened, else it is
created if opened in read-write mode.
If you name a file currently open in read-only mode in a
write operation, Regina closes the file, and reopens it in
read-write mode. The only exception is when you call
LINEOUT() with both second and third arguments unspecified,
which always closes a file, both for reading and writing.
Similarly, if the file was opened in write-only mode, and you
use it in a read operation, Regina closes and reopens in read-
write mode.
This implicit reopening is enabled by default. You can turn
it off by unsetting the extension ExplicitOpen.
[Separate current positions.]
The environment in which Regina operates (ANSI C and POSIX)
does not allow separate read and write positions, but only
supplies one position for both operations. Regina handles
this by maintaining the two positions internally, and move
the “real” current position back and forth depending on
whether a read or write operation is next.
[Swapping out file descriptors.]
In order to defend itself against “open-many-close-none”
programming, Regina tries to “swap out” files that have been
unused for some time. Assume that your operating system
limits Regina to 100 simultaneously open files; when your try
to open your 101st file, Regina closes the least recently
used stream, and recycles its descriptor for the new file.
You can enable or disable this recycling with the SwapFilePtr
extension.
During this recycling, Regina only closes the file in the
operating system, but retains all vital information about the
file itself. If you re-access the file later, Regina reopens
it, and positions the current read and write positions at the
correct (i.e. previous) positions. This introduces some
uncertainties into stream processing. Renaming a file affects
it only if it gets swapped out. Since the swap operation is
something the users do not see, it can cause some strange
effects.
Regina will not allow a transient stream to be swapped out,
since they often are connected to some sort of active partner
in the other end, and closing the file might kill the partner
or make it impossible to reestablish the stream. So only
persistent files are swapped out. Thus, you can still fill
the file table in Regina.
[Explicit opening and closing.]
Regina allows streams to be explicitly opened or closed
through the use of the built-in function STREAM(). The exact
syntax of this function is described in section stream. Old
versions of Regina supported two non-standard built-in
functions OPEN() and CLOSE() for these operations. These
functions are still supported for compatibility reasons, but
might be removed in future releases. Their availability is
controlled by the OpenBif and CloseBif extensions.
[Truncation after writing lines.]
If you reposition line-wise the current write position to the
middle of a file, Regina truncates the file at the new
position. This happens whether data is written during the
LINEOUT() or not. If not, the file might contain half a
line, some lines might disappear, and the linecount would in
general be disrupted. The availability of this behavior is
controlled by LineOutTrunc, which is turned on by default.
Unfortunately, the operation of truncating a file is not part
of POSIX, and it might not exist on all systems, so on some
rare systems, this truncating will not occur. In order to be
able to truncate a file, your machine must have the
ftruncate() system call in C. If you don’t have this, the
truncating functionality is not available.
[Caching info on lines left.]
When Regina executes the built-in function LINES() for a
persistent stream, it caches the number of lines left as an
attribute to the stream. In subsequent calls to LINEIN(),
this number is updated, so that subsequent calls to LINES()
can retrieve the cached number instead of having to re-scan
the rest of the stream, provided that the number is still
valid. Some operations will invalidate the count:
repositioning the current read position; reading using the
character oriented I/O, i.e. CHARIN(); and any write
operation by the same interpreter on the stream. Ideally, any
write operation should invalidate the count, but that might
require a large overhead before any operation, in order to
check whether the file has been written to by other programs.
This functionality can be controlled by the extension called
CacheLineNo, which is turned on by default. Note that if you
turn that off, you can experience a serious decrease in
performance.
The following extra built-in functions relating to stream I/O are
defined in Regina. They are provided for extra support and
compatibility with other systems. Their support may be
discontinued in later versions, and they are likely to be moved to
a library of extra support.
CLOSE(streamid)
Closes the stream named by streamid. This stream must have been
opened by implicit open or by the OPEN function call earlier. The
function returns 1 if there was any file to close, and 0 if the
file was not opened. Note that the return value does not indicate
whether the closing was successful. You can use the extension
named CloseBif with the OPTIONS instruction to select or remove
this function. This function is now obsolete, instead you should
use:
STREAM( streamid, ‘Command’, ‘CLOSE’ )
CLOSE(myfile) 1 if stream was open
CLOSE(‘NOSUCHFIL 0 if stream didn’t
E’) exist
OPEN(streamid,access)
Opens the stream named streamid with the access access. If access
is not specified, the access R will be used. access may be the
following characters. Only the first character of the access is
needed.
[R]
(Read) Open for read access. The file pointer will be
positioned at the start of the file, and only read operations
are allowed.
[W]
(Write) Open for write access and position the current write
position at the end of the file. An error is returned if it
was not possible to get appropriate access.
The return value from this function is either 1 or 0, depending on
whether the named stream is in opened state after the operation
has been performed.
Note that if you open the files “foobar” and “./foobar” they will
point to the same physical file, but Regina interprets them as two
different streams, and will open a internal file descriptor for
each one. If you try to open an already open stream, using the
same name, it will have no effect.
You can use the extension OpenBif with the OPTIONS instruction to
control the availability of this function. This function is now
obsolete, but is still kept for compatibility with other
interpreters and older versions of Regina. Instead, with Regina
you should use:
STREAM( streamid, ‘C’, ‘READ’|’WRITE’|’APPEND’|’UPDATE’ )
OPEN(myfile, 1 maybe, if successful
‘write’)
OPEN(passwd, 0 maybe, if no write
‘Write’) access
OPEN(‘DATA’, 0 maybe, if successful
‘READ’)
The return value from this function is either 1 or 0, depending on
whether the named stream is in opened state after the operation
has been performed.
PREV NEXT