perm filename IOSER.PUB[IMS,AIL] blob
sn#093276 filedate 1974-03-26 generic text, type T, neo UTF8
.require "pubdis.dfs[sm,ith]" source_file;
.macro here(x) ⊂break
↓_%x%_↓:
.once center⊃
.macro h ⊂here⊃
.sk←"TENEX error codes are returned in EXTERNAL INTEGER !SKIP!, which is 0 if no errors occurred."
.sec Introduction
This is the preliminary documentation on a set of SAIL runtime routines written
at IMSSS, Stanford. They are all written in FAIL, using the standard SAIL conventions as developed
at the SU-AI, Stanford. The TSAIL compiler at IMSSS has these routines predeclared, so they
have the full status of SAIL runtimes.
An effort has been made to maintain maximum compatibility with the philosophy and
implementatation of SAIL at SU-AI, and at the same time extend the utility and efficiency
of SAIL on the TENEX timesharing system.
DEC-SAIL (as we shall refer to the SAIL implemented for the DEC system) allowed
the user close contact with the DEC timesharing system. TENEX-SAIL likewise has
a complete set of TENEX oriented routines. Routines that are named after jsys'es (e.g., GTJFN)
generally just execute that jsys, although sometimes it is necessary to do a bit more
for the sake of clarity. Several routines (e.g., OPENFILE and INDEXFILE) are a bit
higher level than jsys'es, and allow the user to avoid TENEX bit-twiddling for the
common operations. For data transfer routines, the emphasis has been on preserving the
syntax and semantics of the old routines, for example INPUT, ARRYOUT. These routines
are closely related to the data types available in the SAIL language.
For purposes of compatibility with old programs,
routines LOOKUP, ENTER, RELEASE et al. have
been implemented without calling the 10-50 emulator, and are described in Section I.
We have implemented a large
number of old DEC-style programs on TENEX-SAIL without modification. PUB, the
document compiler written by Larry Tesler, was for example implemented with only
changing 3 uuo's called from START!CODE.
Programs can use the DEC style and TENEX style routines together with few
problems.
Work that remains to be done include:
(1) removing the DEC system calls from the compiler itself. This has
not been a priority item since it is both straightforward to do and irrelevant
to the user, except for the decrease in compilation time.
(2) adding a TENEX interrupt system. To do this correctly, a clock
interrupt will have to be added to TENEX.
(3) the code needs to be merged into the SAIL source files at SU-AI.
(4) the entire system requires much better documentation than is given
here.
.sec DEC-Style Runtime Routines
The design of the new routines is to allow "standard"
programs written for the DEC io to run on TENEX-SAIL. The routines
described in this section are the old routines. Refer to the SAIL
manual for a complete description of these routines.
Some routines (e.g., LOOKUP) return error numbers. In TENEX-SAIL,
these error numbers are the TENEX error numbers (in the sense of the ERSTR jsys)
rather than the DEC error bits. The justification for this is that (1) few SAIL
programs check, for example, the nature of a LOOKUP error (illegal PPN, illegal file,
file being modified, etc); and (2) any program that was examining information that closely
would require recoding using the TENEX error numbers, which apply more sensibly on a
job written on TENEX.
The CALL routine described on {yonpage callpage⎇ is a somewhat special function, in that
in DEC-SAIL it is intended to provide special system calls. We
have implemented in TENEX-SAIL those calls that are most likely
to be used in a user SAIL program dating from the period of time
that SAIL has been available at IMSSS.
.HERE(OPEN)
OPEN(CHAN,"DEV",MODE,IBUF,OBUF,@COUNT,@BRK,@EOF)
.HERE(LOOKUP)
LOOKUP(CHAN,"FILE",@FLAG)
LOOKUP, ENTER, AND RENAME in TENEX-SAIL all accept either DEC or
TENEX file specification. Thus, both
.stoptext
FOOOOOOO.BAZ[SM,ITH]
or
<SMITH>FOOOOOOO.BAZ;14
.STARTTEXT
are legal as the "FILE" argument. This is consistent with systems where the
1050-emulator assumes that PPN's are sixbit.
.HERE(ENTER)
ENTER(CHAN,"FILE",@FLAG)
.HERE(RENAME)
RENAME(CHAN,"NEW!NAME",PROTECTION,@FLAG)
The PROTECTION feature does not work at present.
.HERE(USETI)
USETI(CHAN,BLOCK)
USETI and USETO do not work on the dectapes, since TENEX (v. 128) cannot
set the file pointers on the dectapes.
.HERE(USETO)
USETO(CHAN,BLOCK)
.HERE(CLOSIN)
CLOSIN(CHAN)
.HERE(CLOSO)
CLOSO(CHAN)
.HERE(CLOSE)
CLOSE(CHAN)
.HERE(RELEASE)
RELEASE(CHAN)
.HERE(MTAPE)
MTAPE(CHAN,FUNCTION)
.HERE(GETCHAN)
NEW!CHAN←GETCHAN
.HERE(CVJFN)
REAL!JFN←CVJFN(CHAN)
This is an important function conceptually, although you may never
need it. SAIL uses channels for both the DEC style I/O and the
TENEX style I/O. For most purposes, you do not need to know
what the TENEX JFN "really" is, since ↓_all_↓ the routines in
TENEX-SAIL use the channel numbers. But, if you really want to
have the 36-bit JFN (including flags in the left half), this
function will provide that information.
If a TENEX-SAIL program does not use the OPEN function, but
only GTJFN and/or OPENFILE for file accesses, then this function
is irrelevant. Likewise, a purely DEC-style SAIL program could never need
this function.
.CALLPAGE: PAGE
.H CALL
RESULT ← CALL(ACCUMULATOR!ARGUMENT,"FUNCTION")
The CALL function in SAIL was designed to call whichever
CALLIs were defined in the particular time-sharing system. The
following CALLIs are supported (in pure TENEX coding) in the
TENEX-SAIL. Any other call will give a non-fatal SAIL error,
from which continuation is possible.
Implemented CALLIs:
.stoptext
EXIT
DATE
LOGOUT
TIMER
MSTIME
GETPPN
RUNTIM
PJOB
RUN
In addition, the IMSSS version has the following special CALLIs
defined.
DATSAV
PUTINF
GETINF
RANDOM
.starttext
It is believed that this includes most of the CALLIs likely to
be made from a SAIL program. Other TENEX-SAIL installations can
readily add any CALLI's that are desired (as we did at IMSSS).
.sec Utility TENEX System Calls
The functions in this chapter do minor utility calls on
TENEX. An effort has been made to provide calls that read and write strings,
which may be inconvenient for the user to perform in START!CODE. It
should be noted that the TENEX-SAIL compiler has the TENEX jsys nmemonics
defined in START!CODE.
.HERE(ODTIM)
"DATE!TIME" ← ODTIM(DT,FORMAT)
The string representation of the date and time DT are returned
in format specified by FORMAT. DT is in internal TENEX representation.
.STOPTEXT
TENEX Defaults:
DT -1 Current date and time
FORMAT -1 Standard format
.starttext
.HERE(IDTIM)
DT←IDTIM("DATE!TIME")
DATE!TIME is the date and time as a string, in some reasonable format.
The internal TENEX representation is returned. {sk⎇
.HERE(RUNTM)
RUNNING!TIME ← RUNTM(FORK,@CONSOLE!TIME)
The running time in milliseconds for FORK is returned, and the
console connect time is returned in CONSOLE!TIME.
.HERE(GTAD)
DT ← GTAD
The current date and time, in TENEX representation, is returned.
.HERE(GJINF)
JOBNO ← GJINF(@LOGDIR,@CONDIR,@TTYNO)
The jobnumber is returned as the value of the call. Reference
values are: the number of the logged directory, the connected
directory, and the TENEX Teletype number.
.H STDIR
DIRECTORY!NUMBER ← STDIR("DIRECTORY",DORECOGNIZTION)
Returns the directory number associated with a string.
Any problems are returned in !SKIP! with the code:
.STOPTEXT
1 string does not match
2 string is ambiguous.
.STARTTEXT
.H DIRST
"DIRECTORY" ← DIRST(DIRECTORY!NUMBER)
Returns the string name for directory I. Any problems
cause !SKIP! to be set TRUE.
.H(RUNPRG)
RUNPRG("PROGRAM",INCREM,NEWFORK)
This does two entirely different things dep
ending on whether
NEWFORK is true or not.
If NEWFORK then a new fork is created, capabilities transmitted,
and PROGRAM is run there (with the current fork suspending
with a WFORK). INCREM is added to
the entry vector location.
If NEWFORK is false, then the current job is replaced with
PROGRAM.
In this case, RUNPRG is like the DEC RUN uuo, and hence
if the increment is 1, the program is started at the CCL address.
If the routine returns at all, there was a problem with the
file.
Remember to say .SAV as the PROGRAM extension.
.sec Obtaining and Releasing Files
The routines in this section replace the DEC routines
OPEN, LOOKUP, AND ENTER. They allow that these operations can
be done, relative to the SAIL data structures, with much of the
full generality of TENEX.
The main procedure is OPENFILE. In terms of TENEX, OPENFILE
does a GTJFN and OPENF. Additional routines provide support to
OPENFILE including SETINPUT, SETPL, INDEXFILE, and CFILE.
.H OPENFILE
CHAN ← OPENFILE("NAME","OPTIONS")
NAME is the name of the file to be opened. If it is null, then
OPENFILE goes to the user's console for the filname (with recognition).
The value of the call is the CHAN returned to the user.
OPTIONS is a string of options available to the user. Legal
options are:
.stoptext
Read or write:
R read
W write
A append
Version numbering, old-new
O old file
N new file
T temporary file
* index with INDEXFILE routine
Independent bits to be set
C require confirmation
D ignore deleted bit
H "thawed" access
Error handling
E return errors to user in the external
integer !skip!. TENEX error codes are used.
(CHAN will be released in this case.)
.starttext
OPENFILE does a GTJFN followed by a OPENF. If some error
occurs with the file, an error message is printed by OPENFILE, and an
attempt is made to obtain a file name, from the user's console. This
internal handling of erros can be avoided with the "E" mode. If an
error occurs when the "E" mode was set, OPENFILE will return -1 to the
user, and the TENEX error code will be put into EXTERNAL INTEGER
!SKIP!.
.H SETINPUT
SETINPUT(CHAN,@COUNT,@BRCHAR,@EOF)
This routine relates to the functions of the last three
arguments of the OPEN function in DEC-SAIL. When the user wishes
to use the COUNT, BRCHAR, and EOF features of the input routines,
SETINPUT will associate the reference locations COUNT,BRCHAR, and
EOF with the input from CHAN. The INPUT function (see Section XI)
uses 200 as the default value of COUNT if no location has been
associated with CHAN.
As an added convenience, all IO transfer routines set !SKIP! to indicate
end-of-file and IO errors. For example, on return from INPUT
(see Section XI),
!SKIP! will be -1 if an end-of-file occurred, a TENEX error number if an error occurred,
or 0 if not end-of-file and no error.
.h SETPL
SETPL(CHAN,@LINNUM,@PAGNUM,@SOSNUM)
This routine extends the usefulness of the INPUT function
in reading through a file. Often, one wants to read a file, but
be able to keep track of where in the file one is at. This routine
allows the user to
name the variables to be used by the INPUT
function for counting the line-feeds (12), formfeeds (14)
seen by INPUT, as well as keeping the current SOS line
number, if any.
SETPL initializes all three variables to 0. Each time a formfeed is
seen, LINNUM is set to 0. Hence, LINNUM is a count of the number
of line-feeds seen on the current page.
Only input with the INPUT function is examined here. In
particular, REALIN, INTIN, CHARIN, and SINI do not affect these
locations. If users feel that this is wrong, it can be changed.
.h INDEXFILE
FOUND!ANOTHER!FILE ← INDEXFILE(CHAN)
This routine is useful when Openfile is used with the "*"
option, which indexes through many files. (This is the way that
"DIRECTORY" works in TENEX.) INDEXFILE returns TRUE as long as
another file can be found.
The following SAIL statements illustrates the use of OPENFILE,
SETINPUT, and INDEXFILE.
.stoptext GROUP
JFN ← OPENFILE("<JONES>*.SAI;*","RO*"); COMMENT Read all of Jones's SAIL programs.;
SETINPUT(JFN,200,0,EOF);
DO
BEGIN "INDEX"
DO
BEGIN "READ FILE"
STRING S;
S ← INPUT(JFN,BREAK!TABLE);
COMMENT process ...;
END "READ FILE" UNTIL EOF;
END "INDEX" UNTIL NOT INDEXFILE(JFN);
.APART
.starttext
For those familiar with the DEC system, the "*" option
takes the place of reading the MFD and the UFD's.
.h GTJFN
CHAN ← GTJFN("FILENAME",FLAGS)
Ordinarily, this routine will not be needed, since the
more facile routine OPENFILE is available. (GTJFN, OPENF,
GNJFN, CLOSF, RLJFN, AND DVCHR are all in this category of being
included only for completeness, and not necessary for most input
needs.)
Does a GTJFN. If FILENAME is non-null, it is the filename, otherwise
the routine goes to the user's console for a file. FLAGS are used for
accumulator 1, and any error code is returned in !SKIP! The value
of the call is the CHAN, if obtained.
Defaults for FLAGS: 0 means ordinary input, 1 means ordinary
output.
.h GNJFN
MORE!FILES ← GNJFN(INTEGER CHAN)
Does the GNJFN jsys.
.H DELF
DELF(CHAN)
Deletes file open on CHAN. {sk⎇
.h UNDELETE
UNDELETE(CHAN)
Undeletes file open on CHAN. {SK⎇
.H SIZEF
SIZE!IN!PAGES ← SIZEF(INTEGER CHAN)
Gets the size in pages of the file open on CHAN. {SK⎇
.H JFNS
"FILENAME" ← JFNS(CHAN,FLAGS)
Returns the name of the file associated with CHAN.
FLAGS are for ac 3 as described in the jsys manual. 0 IS
the reasonable default for FLAGS.
.H OPENF
OPENF(CHAN,FLAGS)
Does the OPENF jsys on CHAN, with FLAGS the contents of accumulator
2. {sk⎇.
.stoptext
PARAMETERS:
CHAN the CHAN
FLAGS for accumulator 2.
Some defaults:
FLAGS ACTION
-----------------------
0 INPUT CHARACTERS
1 OUTPUT CHARACTERS
2 INPUT 36-BIT WORDS
3 OUTPUT 36-BIT WORDS
4 DUMP MODE INPUT (USE DUMPI FUNCTION)
5 DUMP MODE OUTPUT (USE DUMPO FUNCTION)
VALUES 6-10 ARE RESERVED FOR EXPANSION
.starttext
Other values of FLAGS are interpreted literally.
Ordinarily the user will use the OPENFILE routine.
.h CFILE
SUCCESS ← CFILE(CHAN)
Closes the file (CLOSF) and releases (RLFJN)
the CHAN. This is the ordinary way the user will use
to dispense with a file.
Returns TRUE if CHAN legal and released, FALSE o.w.
CFILE always returns.
.h CLOSF
CLOSF(CHAN)
Does a CLOSF on the CHAN. Ordinarily the user
will want to use the CFILE routine, which handles errors
internally. The CLOSF is accomplished in such a way that
the CHAN is actually not released.
If the device is a magtape open for output, then
2 eof's are written, followed by a backspace. This writes
a standard end-of-file on the tape.
.H RLJFN
RLJFN(JFN)
Does the RLJFN jsys. Ordinarily the user will want
to use the CFILE routine.
.H GTSTS
STATUS ← GTSTS(CHAN)
Gets the file status with the GTSTS jsys.
WARNING: The results of this call are not necessarily appropriate
for determining the end-of-file
if the file is being page-mapped by SAIL. If you want to check
for end-of-file, examine the EOF variable instead.
.h DEVTYPE
DEVICE!TYPE ← DEVTYPE(CHAN)
Returns (via the DVCHR jsys) the device type of
the device open on CHAN. The more general DVCHR call is
also implemented (below).
.H DVCHR
DEVICE!CHARACTERISTICS ← DVCHR(CHAN,@AC1,AC3)
Does the DEVCHR jsys, returning the flags from AC2 as the
value of the call, and AC1 and AC3 get the contents of ac's 1 and 3.
.SEC Data Transfer Routines
The routines described in this chapter do data transfers.
Character input routines are described in Section XI.
For the most part, these routines are the same
syntactically and semantically
as the routines in DEC-SAIL. Additional routines include
CHAROUT (send a character).
Also included in this section are several routines
such as GTFDB that are associated with IO in TENEX.
.h CHAROUT
CHAROUT(CHAN,CHAR)
.H OUT
OUT(CHAN,"A SAIL STRING")
Outputs a SAIL string to the CHAN.
.H LINOUT
LINOUT(CHAN,VALUE)
This routine has little use, but is included since it was in the
DEC-SAIL. It writes an SOS line number on CHAN.
.H GTFDB
GTFDB(CHAN; REFERENCE INTEGER ARRAY BUF)
Entire FDB of CHAN is read into BUF. No bounds checking,
so BUF should be at least '26 words.
.H WORDIN
WORD ← WORDIN(CHAN)
Reads a word (36-bits) from the file, which must be open for 36-bit
transfers.
.h WORDOUT
WORDOUT(CHAN,BYTE)
Sends a 36-bit BYTE to the CHAN, which must be open for 36-bit
transfers.
.h ARRYIN
ARRYIN(CHAN,@LOC,COUNT)
Reads in COUNT words into LOC from CHAN. The file should be open
for 36-bit bytes for this to work.
WARNING: no array bounds checking.
.h ARRYOUT
ARRYOUT(CHAN,@LOC,COUNT);
Writes COUNT words to CHAN starting at LOC. The file should be open
in 36-bit bytes.
.h MTOPR
MTOPR(CHAN,FUNCTION,VALUE)
Does the MTOPR jsys. The user may find the DEC-style MTAPE funtion
more comfortable.
.H SFPTR
SFPTR(CHAN,POINTER)
Sets the file open on CHAN to byte POINTER (-1 for EOF).
{SK⎇
.H RFPTR
POINTER ← RFPTR(CHAN)
Reads the pointer of CHAN. {SK⎇
.H BKJFN
BKJFN(CHAN)
Does the BKJFN jsys on CHAN. {SK⎇
.H RFBSZ
BYTE-SIZE ← RFBSZ(CHAN)
Reads the byte-size of the file open on CHAN.
.SEC Direct DSK Operations
The routines DSKIN and DSKOUT do direct dsk operations in TENEX-SAIL.
They correspond to the device PAK in the DEC system. These routines
relate only to the IMSSS version of TENEX-SAIL.
.h DSKIN
DSKIN(MODULE,RECNO,COUNT,@LOC)
IMSSS only.
DSKIN does direct IO from the DSK (formerly device "PAK").
Modules 4-7 are legal for everyone. Other modules require enabled
status.
Count words are read into user's core at location LOC, from
MODULE, record RECNO. {sk⎇ WARNING: No bounds checking is performed
to see if the LOC is a legal SAIL array.
.h DSKOUT
DSKOUT(MODULE,RECNO,COUNT,@LOC)
Works like DSKIN, except that it writes instead of reads. No
bounds checking is performed on the locations being written (so
they may not be legal SAIL arrays.)
.SEC Error Handling
When errors occur, sometimes the runtime routines trap
these errors themselves. This practice is held to a bare minimum,
since the error itself may be information that the user is
interested in seeing. Usually, the routines (as marked) put the
TENEX error code in EXTERNAL INTEGER !SKIP!, which you may declare
and examine after any call so marked. The TENEX error numbers
don't always make good sense, but for the cases that they do,
the ERSTR routine will print out on the user's console the
message associated with that error number.
.h ERSTR
ERSTR(ERRNO,FORK)
Using the ERSTR jsys, types out on the console the TENEX error string
associated with ERRNO for FORK fork (0 for the current fork).
Parameters (in
the sense of the ERSTR jsys) are expanded.
Types out the string ERSTR: UNDEFINED ERROR NUMBER if
something is wrong with your error number or fork (and sets !SKIP! to -1).
.sec Terminal Mode Settings
.terminalmodes: subsection!
The routines in this Chapter really refer to terminals only
in the so-called "mini-system" version of TENEX (planned obsolescence).
The argument CHAN may be either a SAIL channel number associated
with a terminal, or a terminal specifier (such as '100 or '101 for
the controlling terminal).
.H RFMOD
MODE!WORD ← RFMOD(CHAN)
Reads a file's mode word.
.H SFMOD
SFMOD(CHAN,AC2)
Sets a file's mode word to argument AC2.
.H RFCOC
RFCOC(CHAN,@AC2,AC3)
Does RFCOC jsys, returning values in AC2 and AC3.
.H SFCOC
SFCOC(CHAN,AC2,AC3)
Does SFCOC jsys, setting to AC2 and AC3.
.SEC Paging the TENEX-SAIL Core Image
Presently, the only page-manipulation routine
available is PMAP. It is clearly desirable that (1) the SAIL
allocation routines (CORGET et al.) be redesigned to take advantage
of the paging environment, and (2) that certain data types be added to
the SAIL language to control allocation. The only feature added at IMSSS
is the PRESET!WITH construction, which is like PRELOAD!WITH except that
the array is placed in the high segment.
.H PMAP
PMAP(AC1,AC2,AC3)
Does the PMAP jsys, with these parameters:
.stoptext
ARGUMENTS:
AC1 contents of AC1
AC2 " of AC2
AC3 " of AC3
.starttext
.SEC Teletype I/O Routines
The usual SAIL routines for teletype I/O are all available in
TENEX SAIL. These routines are:
.begin narrow 8
INCHRW
INCHRS
INCHWL
INCHSL
INSTR
INSTRL
INSTRS
OUTCHR
OUTSTR
CLRBUF
TTYIN
TTYIN
TTYINL
.END
In addition, PBIN, PBOUT, and PSOUT have been added, although
they execute exactly the same code as INCHRW, OUTCHR, and OUTSTR
respectively. TENEX-SAIL sets the modes for Teletype I/O in
a way similar to the DEC system. You may examine and exchange
those modes with the RFMOD,SFMOD,RFCOC, and SFCOC routines described
in {yonss terminalmodes⎇.
One desirable feature of the DEC system was the control-o
"shut up" feature. What happened was that: when the user typed
a control-o, output was suppressed until either the next control-o or
until the program requested input. This feature has been implemented,
under complete user control, with the ENCTLO and DSCTLO routines.
.h PBTIN
CHARACTER ← PBTIN(SECONDS)
Executes the PBTIN jsys, with timing of SECONDS. IMSSS only.
.H INTTY
"INPUT!STRING" ←INTTY
Using the PSTIN jsys, accepts as many as 200 characters from
the user's Teletype, with the standard system breakcharacters. The
breakcharacter itself is removed from the string, and
no timing is available.
If the default of 200 characters is exceeded, then !SKIP! is set
to -1; otherwise, !SKIP! has the break-character upon return from
INTTY. IMSSS only.
.h ENCTLO
ENCTLO
This routine enables control-o as a pseudo interrupt (on
channel 3). Whenever a control-o is typed, EXTERNAL INTEGER CTLOSW
will be negated. If CTLOSW is TRUE, then output is suppressed from the
Teletype routines until
the next input is requested by the teletype routines.
The user may examine or reset CTLOSW at any time.
.h DSCTLO
DSCTLO
This routine disables the pseudo interrupt on channel 3
for control-o. The only way this interrupt is set up is by the
routine ENCTLO.
.SEC Character Input From Files
DEC-SAIL had the following routines for character input:
.begin narrow 8
INPUT
REALIN
INTIN
.END
TENEX-SAIL has these routines, plus additionally the routines
CHARIN (read a single character) and SINI (read a string
upto a specified character). Also, the INPUT function can be
set (using SETPL) to count the page and line numbers in the
file.
.h CHARIN
CHAR←CHARIN(CHAN)
Returns the next character from a file (open for character
reading). Returns 0 if the file is at the end.
.H SINI
"INPUT!STRING" ← SINI(CHAN,MAXLENGTH,BRKCHAR)
Reads in a string of characters, terminated by BRKCHAR or
reaching maxlength, whichever happens first.
!SKIP! will be -1 if call terminated for count, else
it will have the breakcharacter, which will be the last character
read if the end-of-file is encountered.
.h INPUT
"INPUT!STRING" ← INPUT(CHANNEL,BREAK!TABLE!NUMBER)
.H REALIN
REAL←REALIN(CHANNEL!NUMBER)
.H INTIN
INTEGER←INTIN(CHANNEL!NUMBER)
.H STDBRK
STDBRK(CHANNEL)
This routine reads in the standard break-table file on
CHANNEL. (This routine has seldom if ever been used.)
.standard back