SUBGROUPGFIO - An I/O library for George 3
In order to simplify the task of porting the programs from Kernighan and
Plauger's "Software Tools", which are written to use ASCII as the internal
character set I decided to write an I/O library
that allowed use of the
ICL ECMA character set.
The library also provides a Unix style
"open" routine, allowing opening of
filestore files at runtime.
All I/O to the terminal is performed using *TR (pseudo tape-reader) and *TP
(pseudo tape-punch) devices in NORMAL (upper/lowercase) mode. I/O to
filestore files uses *FR (file reader), *FW (file writer) and *FH (file
handler - allows reading and writing) devices.
The library is somewhat based on Unix, the "open" routine returns a small
integer representing the connection to the file, this number is passed to
the read/write/close routines indicating which file is to be operated on.
This number is conventionally referred to as the "fd" or "file descriptor".
The fd's 0, 1, 2 can be used without an open call, they will be automatically
attached to the MOP console or job source/output. fd 0 is conventionally used
as standard input, fd 1 as standard output and fd 1 is used for
"standard error".
When fd 0 is used SUBGROUPIO checks to see if *FR0 is ASSIGNED, if it
is then *FR0 will be used, if not it will try to use *TR0 in a MOP job,
ONLINE to the mop console, or *FR0 in a background job, ASSIGNed to the
job source.
In a similar fashion fd 1 will be *FW0 or *TP0 and fd 2 will be *FW1 or
*TP1.
The equivalent of the Unix:
$ wc -l <file
would be:
12.23.45_ AS *FR, FILE
12.23.48_ LE PROGRAM WC,,PARAM(LINES)
The current versions of the routines are written to be callable from
FORTRAN or Algol. They use the
standard calling convention, routines are
called with the link in X1, instructions are placed after the call which
load the addresses of the arguments into X3 which the routine picks up
with OBEY instructions. The return value from the routines is placed in
X6.
When used from Algol all arguments are passed by value, except the buffers
and character strings which are passed as integer arrays by name.
All routine names are prefixed with GF to indicate that they are Fortran
callable.
The source code for the current versions can be found
here, or linked to from the routine
descriptions.
A magtape image containing all the source and instructions for compiling
and installing the library can be found here.
Example program using subgroupgfio
An implementation of the Unix cat(1) command:
LIST
LIBRARY (SUBGROUPGFIO)
PROGRAM (CAT)
COMPRESS INTEGER AND LOGICAL
EXTENDED
END
MASTER CAT
INTEGER GFGETARG, GFOPEN, GFCLOSE
INTEGER ARG(100)
I = 1
100 CONTINUE
L = GFGETARG (-1, ARG, 400)
IF (L .LT. 0) GOTO 200
M = GFOPEN (ARG, L, 0, 0)
IF (M .LT. 0) STOP 'OPEN'
CALL COPY (M, 1)
IF (GFCLOSE (M) .LT. 0) STOP 'IO - CLOSE'
I = I + 1
GOTO 100
200 IF (I .EQ. 1) CALL COPY (0, 1)
STOP
END
SUBROUTINE COPY (IFROM, ITO)
INTEGER GFREADLN, GFWRITELN, GFREADECMA, GFWRITEECMA
INTEGER BUF (1)
100 IF (GFREADLN (IFROM).LE.0) GOTO 900
200 CONTINUE
K = GFREADECMA (IFROM)
IF (K .LT. 0) GOTO 300
BUF (1) = K
IF (GFWRITEECMA (ITO, BUF, 1) .LT. 0) STOP 'IO - WRITECH'
GOTO 200
300 IF (GFWRITELN (ITO) .LT. 0) STOP 'IO - WRITELN'
GOTO 100
900 RETURN
END
Routine descriptions
open - Open a file
integer procedure gf open (name, namelen, mode, type);
value namelen, mode, type;
integer namelen, mode, type;
integer array name [];
the return value is the fd if positive or a negative error code.
- name
- is the filename, in ICL 6 bit code. It should be passed as an
array element, Hollerith constant or an array name, but not a simple variable.
(A later version of the
routines may allow for passing an Algol string).
-
namelen
- is the length in characters of the name.
-
mode
-
- 0
- read buffered. In this mode the file is read one block at a time,
which is much faster than reading a record at a time. When a file is being
read in buffered mode it is not possible to change the current read position
other than a "rewind" to start reading the file from the beginning.
- 1
- read. The file will be read a record at a time. The setpos
function can be used to position to any record in the file.
- 2
- read/write. The file can be read or written. By default writes
append to the end of the file. The writemode function can be used
to change to rewrite last record read mode. The delete function
can be used to delete the last record read.
- 3
- write (empty file). The file is emptied if it exists.
- 4
- append. New data will be appended to an existing file.
- type
-
- 0
- don't care (implies AMORPHOUS for create)
- 1
- GRAPHIC
- 2
- NORMAL
- 3
- ALLCHAR
We implement this using the *FR, *FW and *FH devices,
with appropriate qualifiers on the ASSIGN.
close - Close a file
integer procedure gf close (fd);
value fd;
integer fd;
the return value is zero or a negative error code.
Any partly written data will be flushed.
write6 - Write 6 bit characters to a file
integer procedure gf write6 (fd, buf, pos, len);
value fd, pos, len;
integer fd, buf, pos, len;
integer array buf [];
the return value is positive or zero if no error occurs or a negative error code.
- fd
- The file to be written
- buf
- The data to write, in ICL 6 bit character set. This should be
an array element, Hollerith constant or an array name, but not a simple
variable.
- pos
- The offset in the buffer to start writing from (the first character
is at position "0").
- len
- The number of characters to write.
writeint - Write an integer to a file
integer procedure gf writeint (fd, val, len);
value fd, val, len;
integer fd, val, len;
the return value is positive or zero if no error occurs or a negative error code.
- fd
- The file to be written.
- val
- The value to write. It will be output preceded by a "-" if
negative.
- len
- The width of the field. If the width is negative the number will
be written left justified. If the representation requires more space than
the field width requested then the width will be expanded as necessary.
For example:
writeint (fd, 314, 5) - writes | 314|
writeint (fd, -314, 5) - writes | -314|
writeint (fd, 314, -5) - writes |314 |
writeint (fd, -314, -5) - writes |-314 |
writeint (fd, 314, 2) - writes |314|
writeint (fd, -314, 2) - writes |-314|
writespaces - Write spaces to a file
integer procedure gf writespaces (fd, len);
value fd, len;
integer fd, len;
the return value is positive or zero if no error occurs or a negative error code.
- fd
- The file to be written
- len
- The number of spaces to write.
writeecma - Write ECMA 7 bit characters to a file
integer procedure gf writeecma (fd, buf, len);
value fd, len;
integer fd, len;
integer array buf [1:len];
the return value is positive or zero if no error occurs or a negative error code.
- fd
- The file to be written
- buf
- The data to write, in ECMA 7 bit character set. This should be
an array element, or an array name, but not a simple variable.
If the calling code is
Fortran it should be compiled with COMPRESS INTEGER AND LOGICAL. (A later
version of the routine may work without this restriction).
The characters
are stored one per array element, not packed.
- len
- The number of characters to write.
writeln - Write a line to a file
integer procedure gf writeln (fd);
value fd;
integer fd;
the return value is positive or zero if no error occurs or a negative error code.
- fd
- The file to be written
All data in the current buffer is written to the file and a new record is
started.
readln - Read a line from a file
integer procedure gf readln (fd);
value fd;
integer fd;
the return value is positive if no error occurs, zero for eof or a negative error code.
- fd
- The file to be read.
A line is read from the indicated file into an internal buffer.
readecma - Read a character from a file
integer procedure gf readecma (fd);
value fd;
integer fd;
the return value is the character read, or negative if there are no more
characters left on the line.
- fd
- The file to be read.
If readecma returns -ve then
readln must be called before more
characters can be read.
openstr - open a memory buffer for I/O
integer procedure gf openstr (shift, str, pos, len);
value shift, pos, len;
integer shift, pos, len;
integer array str [];
the return value is a fd which can be used to do I/O from the memory buffer
passed in str.
- shift
- The initial shift. -1 indicates that the I/O should be
unshifted, 0 (or any even number) that it starts in alpha shift or 1
(or any odd number) that it starts in beta shift.
- str
- The string buffer to write to. It should be an array element,
or an array name, but not a simple variable.
- pos
- The position of the first character to write to or read from
in the buffer,
starting from zero.
- len
- The available buffer length in six bit characters.
Initially the fd is set for reading, readecma will read characters from the string. If the fd is
written to it will be written from the start.
If the fd is written to the number of 6bit characters in the buffer can be
found by using the
written function.
Example:
INTEGER BUF (5)
DATA BUF /'ABCDEF'/
I = GFOPENSTR (0, BUF(1), 0, 20)
K = READECMA (I)
C - K will be set to 65
K = GFWRITEECMA (I, 97, 1)
C - 1st two characters in buffer will be "]A"
K = GFWRITTEN(I)
C - K is now 2.
openci - open a command issuer channel
integer procedure gf openci ();
the return value is a fd which can be used to write commands to George.
Currently only an "unanticipated" command issuer is implemented so
the commands will be run in the current job.
If a command produces an error the return from
writeln will be negative.
getarg - get a program argument
integer procedure gf getarg (argno, buf, len);
value argno, len;
integer argno, len;
integer array buf [];
the return value is the length of the argument, or negative if there is no
such argument.
- argno
- The argument number to read, or -1 to read the arguments
in sequence starting with the first.
- buf
- A buffer to hold the argument value, in ICL 6 bit code. It
should be an array element or an array name, but not a simple variable.
- len
- The maximum number of characters to write to the buffer.
written - get characters written to fd
integer procedure gf written (fd);
value fd;
integer fd;
the return value is the number of 6 bit characters that have been written
to the internal buffer of fd. This is useful for determining how much of
the user supplied buffer to openstr
is used.
- fd
- The fd.
pack8 - pack 8 bit characters into a buffer
procedure gf pack8 (from, len, to, pos);
value len, pos;
integer len, pos;
integer array from [1:len], to[];
pack
len 8 bit characters from from to
to starting at offset pos
- from
- Source,one character per word
- len
- Number of characters to copy
- to
- destination
- pos
- offset (in the characters) from the start of the destination.
unpack8 - unpack 8 bit characters from a buffer
procedure gf unpack8 (from, pos, to, len);
value pos, len;
integer pos, len;
integer array from [], to[1:len];
unpack
len 8 bit characters from from, starting at pos to
to
- from
- Source,three character per word
- pos
- offset (in the characters) from the start of the source.
- to
- destination
- len
- Number of characters to copy
move - move words
procedure gf move (from, to, words);
value words;
integer words;
integer array from [1:words], to[1:words];
move
len words from from, to
to
- from
- Source
- to
- Destination
- words
- Number of words to copy
The move will be done as fast as possible, with the MOVE instruction unless that would overwrite the source with the destination