-*-Text-*- Documentation of MIDAS .INSRT libraries.
File: LIB Node: Top Up: (DIR)
.INSRT'able Subroutine Libraries for MIDAS Programs
ITS now has several libraries of commonly useful subroutines
for MIDAS programs. This file tells how to use them and
what the existing libraries do.
* Menu:
* General:: What libraries expect from their callers
These libraries exist now
* RFN:: Reading and printing filenames
* DATIME:: Reading, printing and converting dates and times
* NETWRK:: Accessing the ARPANET
* LSRTNS:: Accessing the INQUIR data base
* FORMAT: (SYSENG;FORMAT) Output made easy. Like Lisp's FORMAT function.
* MSGS: (SYSENG;MSGS) Accessing the :MSGS date data base
* BYELIB: (SYSENG;BYELIB) Obtaining epigrams a la BYE
File: LIB, Node: General, Up: Top, Previous: Top, Next: RFN
The Calling Conventions of the .INSRT'able Libraries
MIDAS libraries are designed to be requested with a .INSRT, because
of the fact that MIDAS programs are usually absolute assemblies.
A library named FOO resides (unless otherwise stated) in the file
SYSENG;FOO > on all ITS machines, and can be requested with
.INSRT SYSENG;FOO
Every library clothes itself in a MIDAS symbol block named after the
library. Almost all of the symbols of the library live within this
block, and thus cannot interfere with the calling program. Some
libraries define their normal entry points in the outer block, while
others define NO symbols except in their own block. Routines in
libraries of the latter sort must be referred to in MIDAS with an
explicit block name, as in RFN"PFN for the PFN routine in the library
RFN.
Because libraries are included in the assembly with .INSRT,
they inherit (unless you specify otherwise) the symbol definitions
of the program that is calling them. Subroutines use specific
accumulator names for their arguments, rather than specific
accumulator numbers, and they expect to be called with a PUSHJ P,
where P is whatever the .INSRT'ing program defines it to be.
Most libraries require a block of four or five accumulators, named
A, B, C, and D, and perhaps E. Usually, the code assumes that those
accumulators are consecutive, and the caller should assume that this
is required. Some libraries require another pair of consecutive
accumulators named T and TT. Of course, every library requires a
stack named P. Each library will say exactly which accumulators it
requires and which must be consecutive.
If your existing program does not provide suitably named
accumulators, you can still use the library if you define the required
names within the library's symbol block. For example, if your program
defines the accumulator names A=1, B=2, C=3, T=4, D=5,, while the
library FOO insists on A through D consecutively, you can do
FOO"D=4
causing the name D within FOO to refer to the program's accumulator T.
Within FOO, A through D are now consecutive, but D outside of FOO
continues to have its old value of 5. The only disadvantage of this
is that arguments to FOO's routines cannot be set up in D=5, but must
be placed in T or FOO"D, which are names for 4.
Library subroutines are almost always intended to be called
with a "PUSHJ P,". Each subroutine's documentation will specify
whether it can skip return, what arguments are expected in which
accumulators, which values are to be counted on in which accumulators,
and which accumulators are randomly clobbered. Accumulators in the
set used by the library which are not mentioned in the documentation
may be used temporarily if they are saved and restored. Accumulators
not among those "used by the library" are not touched even for an
instant.
Some libraries assume that the symbols CPOPJ and POPJ1 have been
defined by the caller in the standard manner:
POPJ1: AOS (P)
CPOPJ: POPJ P,
They may also expect the user to define specifically named routines to
serve as subroutines for the library to call. This is to allow the
user to customize the behavior of the library. Each library says
which such symbols are required by which routines. Of course, all
libraries assume that the predefined symbols of MIDAS are available.
If you redefine them carefully, you may succeed in faking the
libraries into doing something interesting. If you redefine them
carelessly, you will lose.
Because many callers will not need all the routines in a library,
the caller can specify which parts of the library should be assembled
by defining some control parameters before .INSRT'ing the library.
Such parameters have names starting with "$$". Each library has its
own set of control parameters, which it documents; those not defined
will usually be taken to be zero, and the associated features NOT
assembled. Thus, the caller must set to one the control parameters
associated with the routines he wishes to use (some libraries may use
the opposite default, assembling all routines except those whose
control parameters are set to zero by the caller). Since it cannot be
assumed that no two libraries will have control paramaters with the
same name, it is good practise to make the control paramaters local to
the library's symbol block, as in:
RFN"$$RFN==1 ;Assemble the RFN routine.
RFN"$$PFN==1 ;Assemble the PFN routine.
Libraries know which parts depend on other parts as subroutines, and
automatically assemble the subroutines of any part that is explicitly
requested.
All code assembled by libraries at the point where they are
.INSRT'ed is pure code. Most libraries create impure static storage
using .SCALAR and .VECTOR. A library that never uses them and has no
static variables will say so; others should be assumed to use them.
Routines that use or return a text string generally expect to find a
byte pointer to the beginning of it in D. They then advance D as they
read or write the text, returning with D pointing at the last
character read or written. Some routines that write text will store a
null character after the last real character of output, to make the
string ASCIZ; D will not be advanced past the null.
File: LIB Node: RFN, Up: Top, Previous: General, Next: Datime
The RFN library contains filename reading and printing routines.
ACS: This file requires acs A, B, C, D, and E, which NEED NOT be
consecutive, and P.
VARS: This file defines no static variables. It is entirely pure.
EXITS: Required exits can include SWITCH, RSIXTP, PSIXTP, MNAME,
and MSNAME, depending on the routines assembled.
ENTRIES:
The entries defined are RFN, PFN, PFNMCH, and PFNBRF, and
RMNAME. They are defined only in the symbol block RFN.
None of them skips.
The control parameters all default to zero:
$$RFN enables the filename reading routines.
Requires the RSIXTP be defined.
$$SWITCH enables the portion that handles switches.
Requires that SWITCH be defined.
$$RUC inhibits the definition of the RUC subroutine, used
for reading input, so that the user can define it.
Requires that RUC be defined.
$$PFN enables the PFN filename printing routine.
Requires that PSIXTP be defined.
$$PFNBRF as well enables the PFNBRF printing routine.
Requires that MSNAME be defined.
$$MNAME enables the PFNMCH printing routine.
It also enables the RMNAME routine that sets up MNAME.
Requires that MNAME be defined.
A Filename Block is a four-word block which holds the four names of a
file in the order DEVICE, FN1, FN2 and SNAME, each as a word
of SIXBIT. These words are in the same order as the arguments
to a symbolic OPEN call.
Filename Reading: $$RFN==1 to enable.
The routine RFN"RFN parses a file specification. It expects in D a
byte pointer to the text, and in B the address of a filename block in
which to store the parsed names. On return, B and C are unchanged,
while D is updated to point at the terminating character, which is
left in A. E contains flags indicating which of the four names were
specified by the filespec. The other words of the filename block are
not changed. The flags are bits 3.1, 3.2, 3.3 and 3.4 set to indicate
that the device, fn1, fn2 and sname, respectively, were specified.
These flags are best written as 1_RFN"DEV, 1_RFN"FN1, 1_RFN"FN2,
and 1_RFN"SNM.
Filenames as parsed by RFN"RFN recognize the special characters
Space, Colon for the device name, Semicolon for the sname, ^X for
referring to the default fn1, ^Y for referring to the default fn2, and
^Q for quoting a special character to include it in a filename.
All control characters other than ^Q, ^X and ^Y terminate the
filespec.
Additional filespec terminating characters are specified by the
caller by defining the routine RSIXTP, which should skip if the
character in A is one which should terminate the filespec.
Default filenames can be supplied by storing them in the filename
block before calling RFN. For more control, you can examine the flags
returned in E to find which names were specified, and default the
others. However, ^X and ^Y will always take their defaults from the
contents of the second and third words of the filename block.
RFN reads characters from the input string using the subroutine
RFN"RUC. The caller may set $$RUC==1 and define RUC himself, to cause
RFN to get its input from another source. RUC should return the next
input character in A, converted to upper case, and not skip.
Filename Reading with Switches: $$SWITCH==1 to enable
Setting $$SWITCH causes RFN"RFN to call a routine SWITCH, which the
caller must define, whenever a switch is encountered. A slash is
followed by a single switch, while a "(" is followed by several
switches, terminated by a ")".
The caller's SWITCH routine is called once for each slash, and
several times as appropriate for each "(". It should read and process
one switch, assuming that the first character of the switch is in A.
If it returns without skipping, RFN assumes that the last character
read was part of the switch. If SWITCH skips, RFN assumes that the
last character read, which must be left in A, was a terminator that
was not part of the switch. This terminator is reprocessed.
SWITCH must not clobber C or E.
Note that slash and "(" are not recognized by RFN unless RSIXTP
skips for them. This gives the caller run-time control over whether
to accept switches.
Filename Printing: $$PFN==1 to enable.
The routine RFN"PFN takes a filename block address in B and prints
the filenames, depositing the text down the byte pointer in D, which
is updated. No accumulator other than D is changed.
PFN knows how to put ^Q in front of characters that need it.
It requires that the user define a routine PSIXTP that takes a
character in A and skips if that character requires a ^Q. However,
the characters Space, Colon and Semicolon get ^Q's and are not passed
to PSIXTP. Thus, PSIXTP can be the same routine as RSIXTP.
The routine RFN"PFNBRF is similar to PFN except that it suppresses
mention of the device name if it is DSK, or the sname if it is the
default one. The user must set $$PFNBRF==1 to enable this, and must
define MSNAME to contain the default sname.
Filename Printing using AI: instead of DSK: $$MNAME to enable.
The routine RFN"PFNMCH prints filenames just like PFN except that a
device name of DSK is printed as the running machine's name.
The user must define a location MNAME and store the machine's name
there. A routine RFN"RMNAME is provided which initializes MNAME
correctly.
File: LIB, Node: DATIME, Up: Top, Previous: RFN, Next: NETWRK
The DATIME library contains routines for handling dates and times.
ACS: A, B, C, D and E, which must be consecutive, as well as P.
VARS: ENGDTP and TMSYST are internal static variables.
EXITS: None.
The control parameters all default to zero:
$$OUT enables output as mm/dd/yy hh:mm:ss
$$OUTF enables output as, eg, 3 Mar 1975 1020
$$OUTZ as well enables routines for outputting time zone
(EST vs EDT).
$$IN enables input of the form mm/dd/yy hh:mm:ss
$$INF enables flexible input allowing named months
$$ABS enables routines to convert dates in y-m-d format
to number of days since 1900, routines to add and subtract
dates, etc.
$$SVNG enables routines to determine whether daylight
savings time was in effect at a given time.
$$UPTM enables conversion of time into how long ITS had
been up at that time.
Data Formats:
A date and time are usually expressed in the form of a time
word. A time word is a single word containing the time in
units of half a second, and one century worth of date. It is
also known as the "ITS disk-format date/time".
It has these fields:
; Mask Field Bits Range Units Actual Range
TM%SEC== 777776 ; 2.9-1.2 0-131K seconds 0-86399.
TM%DAY== 37,,0 ; 3.5-3.1 0-31 days 1-31
TM%MON== 740,,0 ; 3.9-3.6 0-15 months 1-12
TM%YR== 177000,,0 ; 4.7-4.1 0-127 years 0-127
relative to 1900 (1900-2027)
Those four symbols, and byte pointer left halves named
TM$YR, TM$MON, TM$DAY and TM$SEC, are defined in DATIME.
So you can do LDB B,[DATIME"TM$YR,,A] to extract the year
from A into B, for example.
One routine which is always assembled is TIMGET, which returns the
current time as a time word in A. -1 is returned if ITS doesn't know
what the time is.
Output of date/time:
$$OUT==1 enables the routines DATASC, TIMASC and TWDASC which output
a date and time from a time word in A in the format mm/dd/yy hh:mm:ss,
stuffing the text down the byte pointer in D. A null character is
deposited at the end of the string, but the byte pointer in D is not
advanced over it. B and C are untouched.
DATASC outputs just the date, TIMASC outputs just the time,
and TWDASC outputs the date and time with a space between.
All three place a null character after the text they output.
$$OUTF==1 enables the routine TIMENG which, called like TWDASC,
outputs the date and time in the format "7 AUG 1976 0831".
There is also DATENG, called the same way, which outputs only the
date, in the form "7 AUG 1976".
$$OUTZ==1 enables routines TIMSTD and TIMEXP which know about the
difference between standard time and daylight saving time.
They are both called just like TIMENG. But whereas TIMENG simply
outputs the hour it is told, without worrying about the time zone,
TIMSTD assumes that the time was specified in EST, and converts it to
EDT if EDT was in effect at that time, and then prints the time with
EDT or EST as appropriate.
TIMEXP, on the other hand, assumes that the time was specified in
whichever time, EST or EDT, was in effect at that time. It prints the
time like TIMENG, followed by EST or EDT as appropriate.
$$OUTT==1 enables the tables DOWTAB and DOWLNG of names of days of
the week. Each is seven words long. DOWTAB's words contain an ASCIZ
string each, such as ASCIZ/SUN/ in the first word. DOWLNG's words
contain pointers to ASCIZ strings of the full names of the days.
DOWTAB and DOWLNG should be used in conjunction with TIMDOW, which is
assembled when $$ABS==1. Another table, MONTAB, contains pointers to
the ASCIZ full names of the months, indexed by month number (Jan = 1).
Input of date/time:
$$IN==1 enables the routine ASCTWD which is the inverse of TWDASC.
It accepts in D a pointer to an ASCIZ string, and returns a time word
in A, advancing D past the text that was used.
$$INF==1 enables the "flexible format" input routines which accept
such input formats as "march 5, 1971" and "3mar71" for the date, and
"0800", "08:00" "0800:00" and "08:00:00" for the time. They take a
byte pointer in D pointing to the string, and advance it past the text
that they use. The routines are ENGTWD, ENGTIM and ENGDAT.
ENGTWD reads a date and a time, whereas ENGDAT reads just a date and
ENGTIM reads just a time.
Addition and Subtraction of Times: $$ABS==1 to enable.
The time word format, while convenient for I/O and for comparison of
times, is not suitable for computation of the number of days or
seconds between two instants. The routines enabled by $$ABS allow you
do to that sort of thing.
TIMADY converts the date in the time word in A to the number of days
past Jan 1 1900, which is returned in A. TIMSEC converts the date and
time in the time word in A to the number of seconds since Jan 1, 1900,
returned in A.
ADYTIM and SECTIM perform the inverse transformations, of an
absolute number of days or seconds since 1900 into a time word. The
argument and value are again in A.
Slightly higher level routines are TIMADD and TIMSUB. TIMADD adds
the number of seconds in B to the time word in A, returning the new
time as a time word in A. TIMSUB returns in A the number of seconds
from the time in B to the time in A, both arguments being in the form
of time words.
TIMDOW takes a time word in A and returns in B the day-of-the-week
index (Sunday = 0) of that date.
TIMNET takes a time word in A and returns in A the same time in
32-bit Arpanet standard format.
The routines UPTIME and UPINI can convert a time word into the
system up-time in 30'ths of a second. They are assembled if
$$UPTM==1. UPTIME takes a time word in A, and returns the
corresponding system up-time. This works only for times since the
system came up, of course. Before using UPTIME, UPINI must be called
to initialize the variable TMSYST.
Daylight Savings Time: $$SVNG==1 to enable.
The routines ODAYL and IDAYL know at which times daylight savings
time is in effect.
ODAYL takes a time word in A, assumed to be standard time, and skips
if standard time was really in effect at that time. Thus, it can be
used to decide whether the time ought to be converted to daylight time
before being printed.
Such conditional conversion can be done this way:
MOVEI B,3600.
PUSHJ P,DATIME"ODAYL ;If daylight time now in effect,
PUSHJ P,DATIME"TIMADD ;convert to daylight time before printing.
IDAYL takes a time word in A, which might be either standard or
daylight time, whichever was in effect at that time. Thus, it is the
sort of quantity that you get if you simply ask for the current time
or a file's creation time and do not convert the zone. IDAYL skips if
the argument supplied is presumably standard time.
This is useful for converting such an unspecified-zone quantity
specifically into standard time, which can be done this wat:
MOVNI B,3600.
PUSHJ P,DATIME"IDAYL ;If at a time when daylight time is in use,
PUSHJ P,DATIME"TIMADD ;convert daylight to standard.
File: LIB, Node: NETWRK, Previous: DATIME, Up: Top, Next: LSRTNS
SYSENG;NETWRK > Contains ARPANET-Handling Routines
NETWRK is the oldest library, and makes more demands on the caller
than the others do. *Note NCP: (.INFO.;ITS NCP)*, for other
information that you will need for writing programs that use the
ARPANET.
ACS: A, B, C, D, and E, which need not be consecutive, and
T and TT, which must be consecutive, and P.
All main entry points clobber T and TT.
VARS: SKTBAS and HSTADR are internal static variables.
EXITS: CPOPJ and POPJ1 must have the standard definitions.
GETCHR, PUTCHR, SPCHAN and DEBUG may be required.
PUTCHR is used by several routines to "print" a character.
It should expect the character in T, and not skip.
Entries:
HSTMAP accesses the host name table file.
HSTLOOK converts a host name string to a host number.
HOSTNM reads a host name from the terminal with completion.
ICP connects to a foreign server.
SERVE in a server listens for and connects to a user.
ANALYZ prints an error message
CONNECT makes a single connection.
CONFIN completes a connection made asynchronously.
HSTSRC converts a host number to a host name.
HSTSIX converts a host number to a concise abbreviation
for its name.
Other conventions:
The major entry points of NETWRK all skip if succesful. They
are all defined in the containing symbol block, not just in
the block named NETWRK. They all clobber T and TT.
A rigid correspondance between socket numbers and I/O channels
is assumed. See under the CONNECT routine for how and why.
Control parameters default to zero:
$$HSTMAP enables mapping in the host names and characteristics
data base, and the conversion of a host number to a host
name.
$$HOSTNM enables the routines to convert host names to host
numbers. The following switches select one or both of
them.
$$SYMLOOK enables the non-interactive host name lookup.
$$SYMGET enables the interactive one.
$$HSTSIX enables the routine to generate a six-character
abbreviation for a specified host name such abbreviations
are used by servers to put in the LOGIN to be printed on
the system console.
$$CONNECT enables the routine to open a connection.
$$ICP enables the routine for a network user program's ICP.
$$SERVE enables the routine for a server's ICP.
$$SYSDBG tells the server ICP routine NOT to refuse
most connections when SYSDBG is on.
$$ERRHAN enables an automatic error message printout when
making a connection fails.
$$ANAYLZE enables the routine for printing an error message
when an error occurs using the net.
Host Name Lookup:
Programs that use the Arpanet often accept the name of a host as
input and contact that host. NETWRK provides routines for converting
a host name to the host's number.
The first requirement for parsing a host name is to access the ITS
host name table, the file SYSBIN;HOSTS1 >. All programs should use
this table rather than have their own, because it is kept up-to-date.
The routine NETWRK"HSTMAP maps this file into core starting at the
page whose number is specified in A, making temporary use of an I/O
channel specified in B. HSTMAP skips if it is successful (it will
fail only if the file is clobbered), returning in rh(A) the number of
the first page not used. NETWRK"HSTADR will retain the address of the
beginning of the file, so NETWRK can access it.
HSTMAP is assembled if $$HSTMAP==1. This should always be so.
The basic operation of looking a name up in the table is performed
by the HSTLOOK routine, which takes in A the address of an ASCIZ string
containing the host name (or a host number in octal, or decimal
followed by a point). HSTLOOK skips if the name is valid and
unambiguous, returning the host number in A. If HSTLOOK does not skip, the name
was meaningless if B contains 0, or ambiguous if B is not 0. E, T and
TT are clobbered. To get HSTLOOK assembled, set $$HOSTNM and
$$SYMLOOK.
If you wish simply to read a host name from the terminal, you can
call HOSTNM, which provides completion and help facilities. HOSTNM
requires no arguments when called, but it expects the user to define
the subroutines GETCHR, PUTCHR and SPCHAN which it calls. GETCHR is
used to read input (from the terminal, presumably); PUTCHR, to echo
the input and print error messages and completions; SPCHAN, to handle
control characters, etc. returned by GETCHR. HOSTNM skips if it
succeeds, returning the host number in A. To get HOSTNM assembled,
set $$HOSTNM and $$SYMGET.
The user-provided subroutines of HOSTNM must have these calling
conventions:
PUTCHR should expect the character in T, and not skip.
GETCHR should return an input character in T,
skipping unless there is "no more input available".
SPCHAN is used by the interactive host-name lookup routine to
handle "special" input characters, not recognized.
The special character is passed in T, and the number of
characters read so far in TT. If SPCHAN skips, the
character is then ignored. If SPCHAN does not skip, the
read-in process is restarted, ignoring all input so far.
Of course, SPCHAN can collude with GETCHR to feed the
previous input or part of it to HOSTNM again.
HOSTNM and HSTLOOK accept abbreviations as long as they are
unambiguous. The precise criterion is that, if the specified name
abbreviates more than one known host name, then one of those host
names must abbreviate all the rest. Thus, "Rut" is a valid
abbreviation for "Rutgers" even though "Rugters-10" and "Rutgers-Tip"
both exist and are different machines, because "Rutgers" abbreviates
both of the other two possibilities. If "Rutabaga" also existed, then
none of the four possible completions of "Rut" would abbreviate all
the others, and "Rut" would be invalid. This is an extension of the
normal rule that an exact match is valid even if it is also an
abbreviation for something else.
In addition, HOSTNM and HSTLOOK accept an octal number, or a decimal
number terminated by a decimal point.
HOSTNM, the interactive reader, types a bell whenever an invalid
name is entered, and ignores the invalid character. At any time, the
user can type "?" or Altmode to see a list of all the hosts whose
names are abbreviated by what he has typed so far. "?" or Altmode at
the beginning of a host name will type a list of all known hosts.
Routines for Servers:
Arpanet server programs need to listen for and then establish
connections, and often need to be able to translate a host number into
the host's official name. Also, standard practise is for the server
to log in after accepting a connection, and supply as the "terminal
name" argument of the LOGIN symbolic system call a six-character
abbreviation of the host name, which will be printed on the log
console. NETWRK provides subroutines SERVE, HSTSRC and HSTSIX for
these functions.
SERVE, assembled if $$SERVE==1, is the routine which listens for and
establishes a connection. It takes several arguments:
A contains the number of the first of three consecutive I/O channels.
The first is the ICP listen channel,
the second is the input channel for the TELNET connection,
and the third is the output channel for it.
B contains the local socket number to listen on.
C contains ,,