Trailing-Edge - PDP-10 Archives - decuslib10-06 - 43,50362/chp.rno
There are no other files named chp.rno in the archive.
.ap;.ps 59 75;.nnm;.t IOLIB Reference Manual
.lm 5;.fg 10;.c;^&IOLIB Reference Manual\&
.b 5;.c;Rob Cook
.c;LaTrobe University Computer Centre
.b 15;.nt;This manual describes the subroutine library, IOLIB version 5(205), and the parameter program
IO version 5(153).
The information in this document is subject to change without notice
and should not be construed as a commitment to the author or to LaTrobe
.b;Actual distribution of the software described in this document will
be subject to terms and conditions that will be announced by the
.en;.pg;.fg 11;.nt Abstract
IOLIB is a system of subroutines, macros and parameters for use
in MACRO-10 programs.
The system is intended to provide a prewritten set of commonly
used subroutines and macros that rely on a standardised method of IO,
and that make assembly language programming simple,
and programs readable.
IOLIB may be used by wizards for the most complicated systems
programming, but it is also an extremely useful tool for
teaching assembly language programming.
.en;.pg;.st Table of Contents
.c;Table of Contents
.ts 70;.b;.nf;Chapter 1 - IOLIB Explained	#
.b;1.1###What is IOLIB?	1-1
1.2###Some Features of IOLIB	1-2
1.3###Who can usefully use IOLIB?	1-2
1.4###How to use this manual	1-3
1.5###Software Support	1-4
1.6###Credits	1-4
.b 2;Chapter 2 - Concepts	#
.b;2.1###Components of IOLIB	2-1
2.2###Files and FDBs	2-2
2.3###The IOLIB Data Base	2-4
2.4###Routines and Macros	2-4
2.5###Error Messages	2-5
2.6###Replaceable Routines	2-5
2.7###Formatted IO	2-6
2.8###User Program Structure	2-6
.b 2;Chapter 3 - Programming Techniques	#
.b 1;3.1###General Description	3-1
3.2###Compiling and Loading Programs with IOLIB	3-1
3.3###Program Structure	3-2
3.4###Symbol Naming Conventions	3-3
3.5###Accumulator Conventions	3-3
3.6###Subroutine Calls	3-5
3.7###Assembly Switches	3-6
3.8###Push Down Stack	3-7
3.9###BEGIN$ - Program Initialisation	3-7
3.10##Global Parameters	3-8
3.11##Segmentation	3-9
3.12##FDESC$ - Build an FDB and Set Values	3-9
3.13##MAKFD$ - Produce Code to Build an FDB	3-10
3.14##Version Number Macros	3-11
3.15##Debugging Aids	3-11
.b 2;Chapter 4 - IOLIB Tables	#
.b;4.1###General Description	4-1
4.2###$TBWAD - Table of Write Routine Addresses	4-1
4.3###Switch Tables	4-2
4.4###Switch Table Building Macros	4-2
.b 2;Chapter 5 - Memory Management	#
.b;5.1###General Description	5-1
5.2###Dynamic Memory Management	5-2
5.3###Static Memory Management	5-2
.b 2;Chapter 6 - Basic IO Routines	#
.b;6.1###General Description	6-1
6.2###$INPUT - Read a Physical Record from a File	6-2
6.3###$OUTPU - Write a Physical record to a File	6-3
6.4###$LUKUP - LOOKUP a File	6-4
6.5###$ENTER - ENTER a File	6-5
6.6###$OPEN - OPEN an IO Channel	6-5
6.7###$CLOSE - Disconnect a File from a Channel	6-7
6.8###$RLEAS - Release an IO Channel	6-7
6.9###$RENAM - Change RIB Details for a File	6-8
6.10##$DELET - Delete a File	6-9
6.11##$USETI/O - Set the Disk Record Number	6-9
6.12##$GETST - Read the IO Channel Status	6-9
6.13##$SETST - Set the IO Channel Status	6-9
6.14##$XTUUO - Execute an IO UUO	6-9
6.15##$XTCAL - Execute an IO Oriented CALLI UUO	6-10
6.16##$XTDCL - Execute a Device Oriented CALLI UUO	6-10
6.17##$MKBUF - Make a Ring of Buffers	6-11
6.18##$DLBUF - Delete a Ring of Buffers	6-11
6.19##$UPDAT - Open a File for Updating	6-11
6.20##$UPDWT - Open for Updating, Wait if Being Modified	6-11
6.21##$APEND - Open a File for Appending	6-11
6.22##$APDWT - Open a File for Appending and Wait	6-12
6.23##$MTxxx - Execute an MTAPE UUO for a File	6-12
.b 2;Chapter 7 - Formatted Reading and Writing	#
.b;7.1###General Description	7-1
7.2###$WRITE - Write one Byte to the Current File	7-2
7.3###$$WBYT - Write one Byte to the Current File	7-2
7.4###$$WCHR - Write a Character to the Current File	7-2
7.5###$READ - Read one Byte from the Currrent File	7-3
7.6###$$RBYT - Read one Byte from the Current File	7-3
7.7###$$RCH0 - Read a Character from the Current File	7-4
7.8###$$RCHR - Read a Character from the Current Command File	7-4
7.9###$REDCH - Read a Character and do Basic Editing	7-5
7.10##$RCCHR - Read a Character and Edit as a Command Character	7-5
7.11##$RFILE - Read a File Specification from the Current File	7-6
7.12##Read Path and PPN Specifications	7-7
7.13##$RSWIT - Read a Switch Name and Value	7-7
.b 2;Chapter 8 - Tempcore Routines	#
.b;8.1###General Description	8-1
8.2###$TMPFD - Build a Tempcore FDB	8-1
8.3###$TMPIN - Read a File from Tempcore	8-2
8.4###$TMPDL - Delete a File from Tempcore	8-2
8.5###$TMPOU - Close a Tempcore Output File	8-2
.b 2;Chapter 9 - Error Reporting	#
.b;9.1###General Description	9-1
9.2###Message Format	9-1
9.3###Error Severity	9-3
9.4###$ERROR - The Error Reporter	9-3
9.5###$FATAL and $WARN	9-5
9.6###The FATAL$ and WARN$ macros	9-5
9.7###IO Error Reporting	9-6
9.8###Syntax Error Reporting	9-6
9.9###$$FERR - the Fatal Error Trap Routine	9-7
.b 2;Chapter 10 - Utility Routines	#
.b;10.1##General Description	10-1
10.2##$MATCH - Match a Name in a Table of Names	10-1
.b 2;Chapter 11 - Examples	#
.b;11.1##Formatted IO	11-1
11.2##Copy a File to LPT	11-2
11.3##Subroutine to Read a Filename	11-2
.b 2;Appendix A - List of all IOLIB Routines	#
.b;A.1###Basic IO Routines	A-1
A.2###Formatted Read Routines	A-5
A.3###Formatted Write Routines	A-11
A.4###Core Management Routines	A-14
A.5###Data Block Manipulation Routines	A-15
A.6###Tempcore Routines	A-16
A.7###Error Routines	A-17
A.8###Utility Routines	A-18
.B 2;Appendix B - List of all IOLIB macros	#
.B;B.1###Programming Macros	B-1
B.2###Basic IO Macros	B-3
B.3###Read Macros	B-5
B.4###Write Macros	B-7
B.5###Core Management Macros	B-9
B.6###Data Block Manipulation Macros	B-9
B.7###Tempcore Macros	B-9
B.8###Error Macros	B-10
B.9###Utility Routine Macros	B-11
.B 2;Appendix C - Contents of the FDB	#
.B;C.1###Details of Words in the FDB	C-1
C.2###Bit Definitions for $FDCHN	C-4
C.3###Bit Definitions for $FDMOD and $FDMOM	C-4
.B 2;Appendix D - Contents of the IDB	#
.B 2;Appendix E - IO Error Codes	#
.B;E.1###UUO IO Error Codes	E-1
E.2###IO Error Codes	E-2
.B 2;Appendix F - IOLIB Standard Error IDs	#
.number chapter 1
.ap;.ps 59 75;.ch IOLIB Explained
.lm 5
.hl 1 What is IOLIB?
 IOLIB is a MACRO-10 assembly language programming system
comprising subroutines and definitions of macros and
The subroutines are a collection of routines commonly
used and commonly written by assembly language
IOLIB contains definitive versions of these routines
written to be correct, consistent and versatile
so that they may be used in almost any situation that
requires them, and they can be relied upon.
The programming is modular, all the routines having well-defined
consistent interfaces with each other, and with the caller
and most of the routines are separate units that can be
loaded individually, together with any other routines
that they call.
The base of the system is a module that will
execute the IO UUOs on files described by a standard data block.
The various routines in the module are organised hierarchically,
so that the programmer needs only to call the function he
requires and all prerequisites are
organised for him.
The basic IO module is general enough to be used for the
most complicated algorithms.
 The rest of the package is built on the basic IO module.
There are routines for reading and writing data in a number
of common formats, for memory management, for error
reporting, for tempcore handling and many others.
The routines that read data in various formats make up
a useful command scanner with a power similar to that
of the DEC SCAN module.
 The macros and symbols come in a parameter file which is assembled
with the user programs.
Each IOLIB routine has a corresponding macro, which may
be used to call it, making programs very readable and the
calls shorter.
Other macros are used to write program initialisation
code, to define version numbers and control assembly.
IOLIB forms a useful programming standard that makes 
assembly language programs easier to write and read, and therefore
more maintainable.
 It is so easy to write simple programs in IOLIB that the system
can be used to teach MACRO-10 assembly language programming.
Students can use IOLIB macros for program initialisation
and for all IO, and can concentrate on learning the instruction
set and the use of the assembler and hardware.
.tp 10;.hl 1 Some Features of IOLIB
.b 1;.lm +3;.i -3;*##basic IO module for executing IO UUOs on
any file.
.b;.i -3;*##files described by standard data block. 
A large number of defaults are supplied.
.b;.i -3;*##buffer sizes are variable because IOLIB creates buffer rings itself
.b;.i -3;*##any IO call for a file ensures that all prerequisites for that
function are fulfilled first.
.b;.i -3;*##routines for writing data in a wide variety of formats;
decimal, date/time, filename, cash ... IOLIB has them all
.b;.i -3;*##routines for reading data in all the same formats.
This feature gives a command scanner of similar power to the DEC
SCAN module, but smaller.
.b;.i -3;*##dynamic memory management using the ALGOL heap algorithm
.b;.i -3;*##comprehensive routines for reporting errors in the DEC standard
Verbosity level can be set by program or user.
.b;.i -3;*##critical routines replaceable by user programmer, so that IOLIB's
simple approach can be replaced by something more complicated
for e.g. fatal error traps.
.b;.i -3;*##a macro to call each IOLIB routine, making code
shorter and more readable.
.b;.i -3;*##a macro to write program initialisation code
.b;.i -3;*##macros to define file data blocks
.b;.i -3;*##all the SAVEn and POPJ/POPJ1 utility routines
.b;.i -3;*##all symbols are parametised.
All contain the character '$' so that they are
easily recognisable.
IOLIB uses C.MAC, so that all the C symbols are available to
the programmer.
.b;.i -3;*##DEC compatibility
.b;.i -3;*##will run on 5.06 and later monitors only.
.lm -3;.hl 1 Who can Usefully Use IOLIB?
IOLIB is aimed at 3 main classes of programmer:
.ls;.le;the professional systems programmer,
who spends much of his time coding in assembly langauge.
For him IOLIB is a complete assembly language programming system
of standard modules that he would otherwise write for himself
for each program, as well as offering features that he
might not consider using if the code were not prewritten.
The basic IO routines handle all IO
on all channels in one module.
They are extremely flexible, allowing the programmer to manipulate
his file transactions in the most complicated ways.
Most routines are written independently of the other routines
and are loaded separately so that the programmer can use as
much or as little of the system as he wants, and his
final program is not burdened with unused routines.
Advertised routines are easily replaceable by the programmer's own routines
and the clever programmer can make good use of rewriting
specific critical routines.
Use of IOLIB ensures that programs are reasonably standardised,
and in particular text output and error messages are in a standard form.
 As well as standard routines, IOLIB defines a wealth of
standard symbols and macros and includes all those defined in
Together, IOLIB and C form a programming standard that could
usefully be adopted by installations to make
programs readable and maintainable.
.le;the programmer who writes simple
one-off programs.
The main reason such a user wants to write assembly language
programs is because the higher level languages cannot
provide some feature.
IOLIB can be used to construct one-off programs easily, because
the command decoder, message writer and basic IO are laid on.
At the same time it offers access to all the machine characteristics
that straight assembly language code does.
IOLIB is easy to use reliably without detailed study of
the system.
.le;for teaching MACRO-10.
IOLIB allows students to call macros for 
initialising their programs and for all IO, so that they
can concentrate on the basics of assembly language.
The IOLIB system is so simple that students can be taught
enough to construct simple programs in
a few minutes.
This basic subset includes the use of the SEARCH pseudo-op,
the BEGIN$ macro to start programs, a few formatted
read and write macros, accumulator names and the MONRT$
Later they can be introduced to files through the FDB
system, using all the same macros together with MAKFD$.
Using IOLIB, students can write full assembly langage
programs from the first class; there is no need to
bother with starting them on writing FORTRAN subroutines with
all the addressing technique that that involves.
.els;.hl 1 How to Use this Manual
 The manual is a reference manual rather than a teaching text, and
it is laid out so that the programmer can easily locate details
of a routine or macro to perform a specific task.
The concepts and conventions used in IOLIB are explained in chapters
2 and 3.
Chapters 5 to 10 contain details of critical or
complicated routines, including full algorithms and even code
in some places.
Chapter 4 contains details of IOLIB tables that the user
may need to use, build or modify.
The main reference parts of the manual lie in the appendices.
Appendix A is a full list of all the routines, and entry points,
available in IOLIB.
It contains a specification, including details of return
addresses, input arguments and output results.
Also included are details of the acs altered by the routine,
the size of the routine in words, the macros that call the
routine and a reference to a section in the main part of
the manual that contains further details, if necessary.
Appendix B is a full list of all macros available in the
IOLIB system.
It contains full details of the macro call and specification
of the effect, as well as a reference to further details.
Appendices C and D list the words in the FDB and the IDB,
and explain them fully.
Appendices E and F deal with error messages.
Appendix E gives the codes returned by the basic IO routines
indicating errors, and appendix F gives a list of the 3
character error ids produced by IOLIB and explains them in
 The files constituting this manual are distributed in sections
so that the appendices may be printed separately and used
alone as a quick reference document.
 To use the manual, digest the contents of chapters 2 and 3
thoroughly and understand the simple examples given in
chapter 11.
After a basic understanding is gained, the programmer
can look up routines that he requires in the appendices
A and B.
.hl 1 Software Support
 The IOLIB system is maintained at Latrobe University by the
Software Performance Reports submitted to the author will be
answered promptly and problems solved as quickly as possible.
Further versions of IOLIB are under development.
 Suggestions for routines to be included in future versions
or for changes and improvements to current routines
are welcomed.
.hl 1 Credits
 The original work and the development of the first 3 versions of
IOLIB was done at the University of Queensland computer centre.
Versions 4 and 5 were written at Latrobe University computer centre.
The author gratefully acknowledges the help and
advice given by all members of the staffs of the two
computer centres.
 When IOLIB was converted from the University of Queensland 4s72
(highly modified) monitor to DEC standard 5-series monitors,
much effort went into achieving DEC compatibility.
Ideas and code from the DEC SCAN and WILD modules were a
great help and influence in meeting this goal.
.number chapter 2
.ap;.ps 59 75;.ts 13 21 37;.ch Concepts
.lm 5
.hl 1 Components of IOLIB
 IOLIB is a set of subroutines contained in the subroutine library file IOLIB.REL and a set of macro and parameter symbol
definitions contained in the UNIVERSAL parameter file IO.UNV, and in
the source file IO.MAC.
Programs using IOLIB must be assembled with the IO and C
symbol tables, and they must be loaded with a library search
Full assembly and loading instructions are given in section 3.2.
All programs written to use IOLIB may use any of the symbols defined
in IO.MAC and the DEC parameter file C.MAC without prior
 IOLIB subroutines fall into several broad categories, with the
main emphasis on making DECsystem-10 IO readily available to the
MACRO-10 programmer, and on giving him a broad range of standard
routines to perform common tasks:
.ls;.le;routines to execute the basic IO UUOs for any file.
These routines smooth out the differences between devices, are
channel independant and are organised in a hierarchic fashion,
so that a call to one routine will ensure calls to other routines
to execute prerequisite UUOs and routines.
For example, $LUKUP will call $OPEN.
.le;routines to read/write one byte with a file using buffered
IO, TTCALL UUOs or byte instructions, for a packing and unpacking
like function.
These routines also ensure that prerequisite UUOs are executed by
calling the basic IO routines.
.le;routines to read and write character strings with files
as described above, in a wide variety of formats.
The formatted input routines read characters
through a command scanning coroutine similar to that in the
DEC SCAN module.
.le;error message printers that will print fatal or warning
messages in DEC standard format.
IO and command syntax errors
can be reported easily by these routines since all necessary
codes are set up on error return from the IO and command scanning routines.
.le;routines to handle tempcore files (input, output and delete).
.le;a variety of utility routines that are commonly used by
assembly language programmers, such as accumulator save/restore
routines, POPJ routines, table scanning, and many others.
.le;the IOLIB data base
.els; The IO.MAC parameter file contains definitions of the IOLIB data
base symbols and of macros and OPDEFs that are useful (and some
almost essential) for writing programs that use IOLIB.
.ls;.le;useful symbol definitions for all accumulators
.le;a macro to call each IOLIB routine
.le;a macro to initialise a program that includes setting up a
stack and the IOLIB data base, handling CCL calls and concealed mode entry.
.le;symbolic definition of all independant words and bits in the
various data blocks
.le;macros to build file data blocks
.le;macros to create calls to the error messages writers
.le;macros to control version numbering
.le;macros to aid assembly by setting assembly into high
and low segments etc
.els;.hl 1 Files and FDBs
 IOLIB is mostly concerned with reading and writing data to
and from files.
Files are described to IOLIB basic IO routines by a standard
data block known as the File Descriptor Block, or FDB.
This block contains all the known information about a file
and includes a RIB area, an OPEN UUO block, two buffer headers,
the channel number, record number, buffering details
and room for wildcard masks and other file attributes associated with
command scanning.
Every file that is to be accessed by IOLIB must be described
by an FDB.
 The programmer is responsible for building the FDB and for filling
in all his non-default values.
The basic IO routines will supply defaults for all
unfilled words.
IOLIB contains routines for obtaining
space for an FDB from the memory manager, for initialising an
FDB and for deallocating the space used by an FDB ($CLRFD and
There are macros for building FDBs and for filling them with
basic data.
The MAKFD$ macro produces inline code to obtain
space (if necessary) and fill in details.
The FDESC$ macro builds an FDB at assembly time, and fills it.
The defaults are:
.b;.nf;.ts 25 40
	device	DSK
	name	null
	extension	null
	PPN	null
	IO mode	.IOASC
	buffers	2; standard size for device
	sequential IO starting at block 1
.f; The last item in an FDB is the RIB area for LOOKUP-class UUOs.
A standard length FDB contains the words of an extended RIB from
If the programmer needs longer extended RIBs, all he has to do
is build a longer FDB.
The routines that create FDBs will accept a length as an argument,
using the standard length by default.
If all FDBs are to be longer than normal, the programmer could
redefine the symbol, $LNFDB, which gives the length of
a standard FDB, e.g.
.b;.ts 13 21 37;.nf;	$LNFDB==$FDRIB+.RBALC+1	;all FDBs continue until .RBALC
.f; The basic IO routines perform their function on the file
described by the FDB pointed at by an accumulator named D.
Therefore ac(D) must be loaded with a pointer to the required
FDB before calling any basic IO routine, and therefore
any routine that uses the basic routines, such as the
formatted IO routines.
The FDB used by the basic IO routines is known as the 'current
So, to execute a LOOKUP on a file described by an FDB at
location INPFDB:
.b;.nf;	...
	MOVEI	D,INPFDB	;load current FDB
	LUKUP$	#	;execute LOOKUP (including OPEN)
.f; The routines which read and write one byte ($READ and $WRITE)
extend the current FDB concept so that it includes TTCALL UUO
for the job's terminal and byte pointers for reading
and writing into memory.
If ac(D) contains zero, the routines use TTCALL.
If bits 0-11 are non-zero, ac(D) contains a byte
Otherwise, the right half of ac(D) is a point to the current FDB.
The file described by this extended pointer is known as the
'current file', and all formatted IO routines perform their IO
with the current file.
IO.MAC defines ac(D) to be ac15, and this ac is reserved for
use as the current file by IOLIB.
.b;.nf;To write a message to the job's terminal:
.b;	...
	WTEXT$	<End of execution>
.b;To read a character from an incore buffer called TMPBUF:
.b;	...
	MOVE	D,[POINT 7,TMPBUF]  ;set up pointer
	RCHAR$	#	;read a character into ac(T1)
.f; The BEGIN$ macro which initialises the IOLIB system at the start
of execution, sets up ac(D) to point to the command input file,
which is either the terminal or a CCL file.
Pointers to the command input and message output
FDBs are kept in the IOLIB data base, and may be loaded into
ac(D) using the CMDFD$ and MSGFD$ macros.
The TRMFD$ macro sets ac(D) to zero for terminal IO.
 The contents of an FDB are explained in detail in Appendix C,
and the descriptions of the basic routines in Chapter 7
explain how each routine uses and changes the FDB.
$RFILE, the filename input routine, also sets (and can create) FDBs.
.hl 1 The IOLIB Data Base
 IOLIB needs to keep a certain amount of data about
the state of the program and of the IOLIB system.
It must be in the low segment so that it is modifiable, and
must be positioned independent of any particular  program so that
high segments can call each other and pass the address of the
IOLIB data base between them.
IOLIB keeps its data in one block, the IOLIB data block, or IDB.
An accumulator is reserved to point to the IDB, and this pointer
may be passed between segments. 
The accumulator is given the name I, and is defined
as ac16 by IO.MAC.
This definition clashes with the standard use of ac16 as ac(L),
the link register, and this clash must be resolved by the user
The IDB contains data used internally by IOLIB routines, such as
the anchor for the linked list of free memory, and parameters
which may be set by the programmer such as the maximum
core which may be used by the program.
The parameters which may be set by the programmer are discussed in
section 3.10, and each word of the IDB is explained in full
in appendix D.
.hl 1 Routines and Macros
 Each IOLIB routine has a corresponding macro associated with it.
This macro may be used to call the routine, and in some cases
the arguments to the routine may be specified in the macro call; e.g.
.b;.nf;	OPEN$	#	;calls $OPEN to execute an OPEN UUO
.b;	WDECL$	10	;calls $WDECL to write decimal 10
.f; Using the macros makes the program more readable (expansions
are SALLed by default) and helps to cut down programming
 The complete list of IOLIB routines, their arguments and results
and calling macros is given in Appendix A.
A complete list of macros is given in Appendix B.
.hl 1 Error Messages
 IOLIB includes routines for writing error messages in DEC standard
The messages may include text and a value, which may be written
in one of several formats.
The routines are called by the FATAL$, WARN$ and ADVIS$ macros, which
take a list of arguments specifying the message in full.
The macros create only one location of inline code, so that they may
be used in an error return location.
 The basic IO routines return an error code in ac(T1), when they
detect an IO error, and a call to the error routines
through the FATAL$ and WARN$ macros with no arguments produces
an informative error message.
.b;.nf;	...
	LUKUP$	#	;LOOKUP a file
	##FATAL$	;errors are fatal
.b;might produce:
.b;	?RENAEF RENAME(4), Already exists: IOLIB.BAK
.f; Some of the command decoding routines detect syntax errors
and these too have an error return with an error code
in ac(T1).
A call to FATAL$ or WARN$ again produces a detailed diagnostic.
.b;.nf;	...
	RFILE$	#	;read a filename
	##FATAL$ ,SY	;write a syntax error message
.b;might produce:
.b;	?DELILC Illegal character: <BEL>
.f;.hl 1 Replaceable Routines
 Since IOLIB.REL is searched as a subroutine library, the user
programmer may replace any of the routines by one of his own
with the same name.
However some routines are specifically designed to be
rewritten by the user.
These routines are called at critical parts of the IO process
where the user may want to gain control to perform some
extra functions.
Examples of these routines are $$FERR, the fatal error trap
routine, and $$RCHR, the routine called by all the formatted
input routines to read one character.
The standard $$FERR merely returns to monitor mode, but the
user programmer might want to clean up his program first,
or restart the program at some point instead.
The standard $$RCHR uses the SCAN type command scanning
code to edit the characters it reads, but the user
might want to do less thorough editing or to treat different
files in different ways.
 The main replaceable routines in the current version
of IOLIB are:
.b;.nf;.ts 13 23;	$$ALLC	allocate a chunk of free memory
	$$DALC	deallocate a chunk of memory
	$$FERR	fatal error trap routine
	$$RBYT	read a byte from the current file
	$$RCHR	read a command character (all formatted input)
	$$RCH0	read a character (all command scanner input)
	$$WBYT	write a byte to the current file
	$$WCHR	write a character (all formatted output)
.f;.ts 13 21 37;.hl 1 Formatted IO
 Formatted IO is the transfer of data formatted in various ways
between the program and files, so that the formatted data
in the files becomes binary data in the correct format in
the program.
An example is the reading of a string of decimal digits
and producing a binary number.
The formatted IO routines are explained fully in Appendix A
with more detail about some of the important routines in
Chapter 6.
 The formatted input routines read characters from the current file
and interpret them according to the format of the data that is
being read.
The general philosophy of the routines is to read
until a character is read which is outside the range of characters
expected at that stage, e.g. an endline, or an erroneous
At that stage, the simple routines return the value read so
far and the terminal character, and it is the caller's
responsibility to work out whether the
character is correct.
The more complicated routines must detect some syntax errors
within their own code, and these routines have error returns.
 In the terminology used throughout this manual, a number of
consecutive characters read or written through the formatted IO
routines is called a 'string' of characters, and a terminal
character is called a 'delimiter'.
.hl 1 User Program Structure
 IOLIB places few restrictions on the way a programmer writes his
code, but those that do exist are important.
Firstly, the program must contain a SEARCH pseudo-op to instruct
the assembler to search the C and IO symbol tables for
missing symbols.
Secondly, the program must start execution with a BEGIN$ macro
which initialises IOLIB.
 IOLIB contains other features which assist the programmer
to structure his program such as the version number macros
and the HISEG$ and LOSEG$ macros which organise programs
into two segments.
.number chapter 3
.ap;.ps 59 75;.ts 13 21 37;.ch Programming Techniques
.lm 5
.hl 1 General Description
 This chapter covers a range of instructions and techniques that
have a bearing on writing programs using IOLIB.
It includes some tables of symbols defined in IO.MAC including the
accumulator definitions, and explains some of the important
The DEC parameter program, C.MAC, is an essential part of
IOLIB since definitions in IO.MAC depend on C.MAC.
C.MAC contains a number of extremely useful macro definitions
and a large range of symbol definitions for all the various
parameters available through the monitor.
Unfortunately the only documentation for C is in the code
of the program itself, and a long explanation is outside
the scope of this manual.
However study and use of the symbols and macros in C.MAC does make
programs clearer and gives a better chance of correctness.
.hl 1 Compiling and Loading Programs with IOLIB
 The following instructions assume that the installation is using MACRO-10
version 50 or later.  They do not apply to MACRO version 47, which does not
support .UNV files.
The files C.UNV and IO.UNV must be on the ersatz device UNV:, and the
library file IOLIB.REL should be on the ersatz device MAC:, although
your installation may prefer to keep it on REL:.
 To compile a user program, ensure that the program contains a SEARCH
pseudo-op for C and IO and then give a normal COMPIL command, e.g.:
 To LOAD, DEBUG or EXECUTE a user program, include the indirect command
file IOLO or IOHI in the command string.  IOLO forces all IOLIB routines
into the low segment, whereas IOHI allows the code to fall into the
default segment which is the high segment.
.hl 1 Program Structure
 A suggested layout for the user program is as follows.
The reasons for the various parts are explained
in the comments:
	SEARCH	C,IO		;search UNIVERSAL files
;define version numbering
	VERSN$	1,101,3	;see section 3.14
	PATCH$	#	;ditto
	JBVER$	#	;set version number into .JBVER
	comments including description of
	program and revision history
	;assembly switch definitions
	;symbol definitions
	;OPDEF and macro definitions
	;global symbol definitions
	HISEG$	#	;only if two segment program
MYPROG:	;start of program code
	BEGIN$	#	;initialisation macro
	program code
	data area definitions
.f; The ordering of most items is not important and most
items are optional, but are included in the majority of
 Logical execution of a program may be terminated by calling
the $MONRT routine which returns the program to monitor mode
with an 'EXIT 1,' UUO.
The routine returns to caller if the user types 'CONTINUE' to
the monitor.
.b;.nf;	...
	WTEXT$	<All done>	;end of program
	MONRT$	#	;back to monitor
	JRST	START	;restart on 'CONTINUE'
.f;.hl 1 Symbol Naming Conventions
 By published DEC standard, symbol names containing the character
'$' are free for use by customers, and IOLIB uses exclusively
symbols containing '$' in an effort to keep the names of
IOLIB symbols distinct from names that DEC or the user might choose.
IOLIB follows DEC conventions for special symbol names as
far as possible, using a '$' where the equivalent DEC
symbol would use a '.' or '%'.
In particular IOLIB uses the following templates for
different types of symbol:
.b;.nf;.ts 13 21;^&Template######Use\&
.b;	$ggsss	number of general category 'gg', specific use 'sss'
	gg$sss	byte of general category 'gg', specific use 'sss'
	mmmmm$	opcode definition, whether by macro or OPDEF
	ggeee$	error code of category 'gg', specific error 'eee'
.f;.ts 13 21 37; All symbols for entry points to IOLIB routines are of the form
The routines advertised as replaceable, as well as some concealed
routines and debug points, have entry points of the form
The first characters of the entry point name indicate
the broad type of the routine:
.b;.nf;	$Rxxxx	formatted read routines
	$Wxxxx	formatted write routines
	$TMPxx	tempcore routines
	$FTLxx	fatal error routines
	$WRNxx	warning error routines
	$ERRxx	collective error routines
	$CNVxx	conversion routines
	$INIxx	initialisation routines
.f; Secondary entry points are normally identical to the primary
entry point except that the last character is replaced
by a digit:
.b;.nf;	$RFILE	read a file specification
	$RFIL0	as above, but with different arguments
.f; The symbols for macro names are all of the form xxxxx$, except
for a few special purpose macros which are xxxx$$.
The macro usually takes its name from the routine it calls.
The replaceable routines are called by macros that have
ordinary names; e.g. $$WCHR is called by the WCHAR$ macro.
.hl 1 Accumulator Conventions
 IOLIB breaks the accumulators down into 3 types of
ac, temporary, preserved and global.
The differences lie in the conventions about the way they
are treated in subroutine calls.
Temporary acs are just that.
They should be used for temporary workspace, and in
particular no caller routine should expect any temporary
ac to be preserved across a subroutine call.
It is the caller's responsibility to save temporary
acs if this is necessary.
 Preserved acs can be used by a routine as workspace
that is permanent for the life of that routine.
Any subroutine must save any preserved ac that
it uses before use, and must restore it before
returning to the caller.
Any routine must be able to rely on all subroutines
obeying this convention.
 Global acs are free for the program to use as it wishes.
They are normally used for quantities that are set
in defined routines and otherwise passed around
from routine to routine.
 IOLIB uses these conventions.
However, not all IOLIB routines destroy temporary acs, and in
particular, frequently called routines, such as the basic
IO routines, are very careful not to destroy temporaries.
Appendix A details the temporaries that are destroyed by each
IOLIB only changes T1-T4 and
always preserves preserved acs.
IOLIB reserves 3 globals for itself.
They are acs 15 16 and 17, and they are used for 
the current file point, the IDB point and the push
down stack point respectively.
They are named D, I and P.
IOLIB never touches any other global.
Acs 0 and 11-14 are always free for the caller.
.tp 31; IOLIB defines symbols for the various acs as given in the
following table:
.b;.nf;.ts 18 25 37;	^&Ac	Name	Use\&
.b;.ts 18 26 34;	0	T0	temporary (never by IOLIB)
	1	T1	    "     (used by IOLIB)
	2	T2	    "            "
	3	T3	    "            "
	4	T4	    "            "
.skip 1
.b;	5	P1	preserved
	6	P2	    "
	7	P3	    "
	10	P4	    "
.b;	11	G1	global
	12	G2	   "
	13	G3	   "
	14	G4	   "
	15	G5	   "  (reserved to IOLIB)
	16	G6	   "  (reserved to IOLIB)
	17	G7	   "  (reserved to IOLIB)
.b;	0	F	flag register (since non-index)
	15	D	current file point
	16	I	IDB point
	16	L	link ac (DEC standard)
	17	P	push down stack point
.f;.ts 13 21 37; IOLIB contains routines ($SAVEn) to save from 1 to 4 preserved acs
and to ensure that they are restored correctly on
These routines should be called by PUSHJ on entry to a routine.
They save preserved acs, starting at P1, on the stack and then
call the rest of the caller routine as a subroutine.
When the caller routine exits by POPJ, control returns to the
$SAVEn routine which restores the saved acs and jumps back
to the original caller.
$SAVE1 preserves P1, and $SAVE3 preserves P1-P3 etc.
	SAVE2$	#	;saves P1 _& P2
	body of subroutine
	may use P1 _& P2
	POPJ	P,	;returns to $SAVE2 to restore P1 _& P2
	#	#	; before returning out of SUBROU
.f; There are routines, $SAVET and $RESTT, that save and restore the 4 temporary accumulators,
These would normally be used by the caller of a subroutine
to ensure that acs are preserved.
 The user programmer does not have to adhere to IOLIB's division
of acs into temporaries, preserved and globals.
He need only be aware that IOLIB reserves G5-G7, and that T1-T4 may
be destroyed by IOLIB calls.
He may decide that he only needs two preserved acs, P1 and P2, and
that P3 and P4 will be used as globals or as temporaries.
The user programmer may define new symbols for the acs as he pleases.
IOLIB defines ac0 as F, a flag register, because many programs
use ac0 as a vector of 1 bit program flags.
Ac0 is convenient for this purpose since it is not an
index register.
IOLIB itself never uses ac0.
.hl 1 Subroutine Calls
 All calls to IOLIB subroutines are by 'PUSHJ P,'
instruction and returns are by a corresponding 'POPJ P,'.
Arguments are passed in acs and values are returned in acs
The IOLIB argument convention is that arguments are passed
in acs T1-T4 except in special cases.
Acs are allocated to arguments in ascending order, so
that T1 is used first.
The special cases are acs D and I.
These acs must almost always be set up to point
to the current file and to the IDB respectively.
Appendix A shows which routines need acs D and I, and which
do not.
 A common convention in MACRO-10
is that a subroutine (or UUO) may have normal and abnormal returns.
In these cases, the convention is that abnormal returns are to
the 'return address' and normal returns are to the 'return address +1'.
.b;.nf;	PUSHJ	P,SUBROU	;call subroutine
	##error return	;abnormal
	o.k. return	;normal
.f;.b;IOLIB routines that have error returns adhere to this convention.
The only exceptions are the $READ and $INPUT routines which have 3 returns, for
error, endfile and normal.
 The routines $POPJ and $POPJ1 can be called to give returns
to the return address and the return address +1; e.g.
.b;.nf;	PJUMPE	T1,$POPJ_#_#	;return if zero
.b;	PJRST	$POPJ1_#_#	;skip return now
.f; It is often useful to be able to pop ac(T1) from the stack and
then return either nonskip or skip.
IOLIB contains routines $TOPJ and $TOPJ1 which are the
same as $POPJ and $POPJ1 except that ac(T1) is popped before
 There are also routines to pop the stack (but not destroy
ac(T1)) and then return.
They are $XOPJ and $XOPJ1.
 Lastly, there are routines $POPJ2 and $TOPJ2 which give a double
skip return as with the normal return from $INPUT.
The user must be careful with these routines as they will
not work with the $SAVEn routines.
.hl 1 Assembly Switches
IO.MAC defines a number of assembly switches, with symbols
FT$xxx for feature tests, that are used to control optional features which
are included for this program.
The programmer may alter the standard settings of these switches
by including a symbol definition in his program.
.b;.nf;.ts 13 37;	FT$DBG==-1	;debug feature required
.f; The assembly switches defined in IO.MAC and their standard settings
and effects are:
.b;.nf;.ts 15 23;^&Switch	Value	Effect\&
.b;Switches which the programmer may set:
.b;.lm +18;.i -18;FT$ALC	-1	nonzero for dynamic memory management; zero for
static memory management
.i -18;FT$CCL	0	nonzero for CCL entry points to be included in
the BEGIN$ macro; zero for no CCL entry points
.i -18;FT$DBG	0	nonzero for debug features (such as caller address
printed in error messages); zero for no debug features
.b;.i -18;Switches which the installation may change:
.b;.i -18;FT$SFD	6	level of SFDs supported by IOLIB.
Note that the level of SFDs supported by the monitor will take
.f;.lm -18;.ts 13 21 37;.hl 1 Push Down Stack
 IOLIB contains a push down stack and a pointer to the top of
the empty stack.
The stack is replaceable, so that the programmer
can define his own stack if he needs a longer or shorter
The IOLIB stack is called $STACK and is 100 (octal)
locations long.
The stack pointer is called $PTSTK and is merely
'IOWD 100,$STACK'.
To define a replacement stack, write:
	IOWD	STLEN,$STACK	;stack pointer
	BLOCK	STLEN	;stack block
.f;.hl 1 BEGIN$ - Program Initialisation
 The BEGIN$ macro performs all the initialisation functions required
at the start of execution of a program.
It must be the first statement following the start address because
it notices whether entry was a 'start', or 'start+1' for the
special CCL entry point.
The code produced by BEGIN$ runs to about 15BEGIN$ produces 5 words of code and calls the $BEGIN (or $BEGCC)
routines. BEGIN$ labels the first word of the user's program with
the internal symbol $$BEG, to aid debugging.
.ls;.le;unless FT$DBG is on, SALL, to suppress listings of macro
If debugging, load the patch area and special debug code, otherwise
load nondebug code.
.le;if FT$ALC is zero, set the replaceable entry points, $$ALLC
and $$DALC, to the memory manager to use static management.
.le; produce PORTAL instructions for normal
and CCL entry points to implement concealed mode.
.le;set T1=0 for normal entry and T1=-1 for CCL entry.
.le;load ac(P) from $PTSTK to set up the push down
stack pointer.
.le;call $INIID to initialise the IDB by clearing it
and setting default values.
.le;set the program name, extension, device and PPN provided
in the acs by the monitor into the IDB.
.le;if FT$CCL is on, test ac(T1), and if entry was at the CCL entry
point build a tempcore FDB, and read the tempcore file.
.le;set the current file, ac(D), from the command file
point in the IDB.
.els;.hl 1 Global Parameters
 The IDB contains program parameters which may be set by
the programmer or by a user through standard switches.
These parameters are:
.ls;.le;memory limit.
A maximum on the amount of memory used by the program can be imposed.
Normally the memory managers will continue expanding the program size
on request, until the monitor refuses to provide any more memory.
But, the memory managers check $IDTOP(I) first and will not
exceed the size set there.
To limit the amount of memory to 16K, say, set $IDTOP(I) to
the memory limit can also be set by the user through the
standard /MAXCOR switch.
The system default is 256K.
16K words +1, e.g.
.b;.nf;.ts 20 28;	MOVEI	T0,_^D16*_^D1024
.f;.ts 13 21 37
.le;program id for error messages (see chapter 10).
A 3 character SIXBIT code can be set into the
left half of $IDECD(I).
The default is none.
.tab stops 20 28
.b;.nf;.ts 23 31;	MOVSI	T0,'IOL'
.f;.ts 13 21 37
.le;error message verbosity.
May be set to 0,1 or 2 for 'low', 'standard' and 'high', by
moving the code into the right half of $IDECD(I).
Also set by the /VERBOSITY switch.
The default is standard verbosity.
.le;standard switch table.
A pointer to the standard switch table can be set into
the right half of $IDSWT(I).
See section 4.3 for details.
.le;help file name.
The SIXBIT name of the file containing help text may be set
into $IDHNM(I).
If no help name is set, and the user gives a /HELP switch,
IOLIB uses the program's name to look
for the help file.
.le;the default FDB for filename decoding.
A point to a default FDB may be set into the right half
of $IDDFD(I).
.skip 1
.indent -7
.le;the command input file.
A point to an FDB may be set into $IDIFD(I), and that point
will be loaded into ac(D) by the CMDFD$ macro.
The command input file is initialised by BEGIN$.
.le;the message output file.
A point to an FDB may be set into $IDOFD(I), and that point
will be loaded by the MSGFD$ macro.
The message output file is initialised by the BEGIN$ macro.
.le;the error messge file.
A point to an FDB may be set into $IDEFD(I), and that point
will be loaded by the ERRFD$ macro, and will be used to write
all error messages (unless it is for an IO error in the message
.le;the next character to be read by the command character
input routine, $RCCHR.
An ASCII character or endline code may be set into
The character should be right-justified.
.le;the default path for the job should be changed by setting
the path into $IDJPT and then using the PATH. UUO.
.els;.hl 1 Segmentation
 The programmer may set the segment that code will
be assembled into through two macros, HISEG$ and LOSEG$.
The macros first check that a change of segment is needed and
then ensure that all outstanding literals are assembled
into the current segment before issuing a RELOC to change segments.
In a two segment program, a call to HISEG$
should appear at the start of a program so that HISEG$ can set
up the TWOSEG pseudo-op to define this program as a two segment
.b;.nf;	TITLE	2SEGEX - two segment example
	HISEG$	#	;set high segment
	high segment code
	LOSEG$	#	;change to low segment
	low segment code
	HISEG$	#	;back to high segment
.f;.hl 1 FDESC$ - Build an FDB and Set Values
 The FDESC$ macro assembles an FDB in inline code
and fills it with any arguments supplied to the macro.
The call is
.b;.lm +10;.i -9;dev######is the name of a device
.i -9;nam######is the file name
.i -9;ext######is the file extension
.i -9;path#####is a path specification (without []).
If no SFD names are given, the PPN is set into $FDPPN;
otherwise the macro builds a path block, sets the
components of the specification into the block and sets
a pointer to the block into $FDPPN.
.i -9;mode#####is the IO mode.
In fact a complete IO status halfword may be given.
.i -9;length###is the length of the FDB to be created.
The default is a standard length FDB.
.b;.lm -10;For example:
.f;.b;makes an FDB for the file 'DSK:ACCT.SYS[,,ACCOUN]' and sets binary
.hl 1 MAKFD$ - Produce Code to Build an FDB
 MAKFD$ writes inline code to create an FDB if none
is given, to initialise the FDB using $CLRFD, and to set values given
as arguments into the FDB.
At the end of execution of the macro code, a point to
the FDB is left in ac(D).
as arguments into the FDB.
The call is:
.b;.lm +10;.i -9;dev######is the name of a device
.i -9;nam######is the file name
.i -9;ext######is the file extension
.i -9;path#####is a path specification (without []).
If no SFD names are given, the PPN is set into $FDPPN;
otherwise the macro writes code to build a path block, set the
components of the specification into the block and set
a pointer to the block into $FDPPN.
.i -9;mode#####is the IO mode.
In fact a complete IO status halfword may be given.
.i -9;length###is the length of the FDB to be created.
The default is a standard length FDB.
.i -9;address##is the address of an existing FDB.
If no address is given the macro creates a new FDB in
space obtained from the memory manager.
.lm -10;.b;.nf;	MAKFD$###DSK,INPFIL,DAT,<104,427>,,,INPFDB
.b;.f;creates the code to call $CLRFD for the FDB, and then
set the details for 'DSK:INPFIL.DAT[104,427]' into the
.hl 1 Version Number Macros
 IOLIB contains 4 macros to help the programmer to define
and update version numbers of programs.
The VERSN$ macro creates symbols for the 4 fields of the
version number and assigns values (given as arguments)
to them.
The PATCH$ macro increments the edit-number for each
patch and defines a patch symbol that can be used 
in conditional assembly of code added
or deleted by the change.
Each call to PATCH$ increments the minor version number.
The JBVER$ macro sets the version number into .JBVER
in the job data area, and VTEXT$ produces an
ASCIZ string of the version number.
.b;the minor version number is set to zero, and is incremented by
the PATCH$ macro.
VERSN$ types out the version numbers of C.MAC and IO.MAC used
during assembly, while being assembled.
.b;.c;PATCH$###<patch numbers>
.b;each patch is assigned a patch number and the numbers are
given as the argument.
PATCH$ creates a symbol '$n' for each number and this
symbol can be used in IFDEF and IFNDEF conditionals.
PATCH$ also increments the edit number for each patch,
and increments the minor version number once per PATCH$ macro.
.b;The JBVER$ macro takes no arguments, and sets the version number
into .JBVER.
.skip 1
.b;The VTEXT$ macro uses the values for the symbols generated
by the VERSN$ and PATCH$ macros to make an ASCIZ string of
the version number.
.nf;	VERSN$	5,7,3	;version 5(7)-3
	PATCH$	<10,11,13,14>	;version 5A(14)-3
	PATCH$	<15,16>	;version 5B(16)-3
	JBVER$	#	;137/  BYTE (3)3(9)5(6)2(18)16
	VTEXT$		;makes the string '5B(16)-3'
.f;.hl 1 Debugging Aids
 Programmers writing programs using IOLIB often have trouble with
debugging when they see control disappearing into the basic
IO routines and then coming out with the wrong answer or with
an illegal memory reference.
IOLIB code is written to be efficient, and does not go to great
lengths to defend itself against misuse, and this can make
life more difficult when debugging.
 One useful technique is to watch the IO UUOs that are being
executed to find out at what point the
trouble starts.
IOLIB provides two special symbols, $$XUUO and $$XCAL,
which label the instructions that execute IO UUOs and
CALLI UUOs concerned with devices.
The debugger can place DDT breakpoints on these symbols
and examine ac(T1) to find the UUO.
The point to the current FDB is always in ac(D).
 Another internal symbol of use is $$BEG, which the BEGIN$ macro
uses to label the first word of the user program following
the BEGIN$ macro code.
 There is an assembly switch, FT$DBG, which invokes debugging
features if set to -1 by the programmer.
In the present version of IOLIB, FT$DBG suppresses the
SALL, so that macros are expanded in listings, and also
ensures that the caller's address is printed in octal
in error messages.
 If FT$DBG is on, a 200 word patch area is loaded from IOLIB,
which the debugger can use to insert extra words of code.
The name of the patch area is $PATCH, and there is a second
symbol, $PAT, which may be moved after inserting each patch
to point to the first free word in the patch area.
Note that LINK-10 and LOADER load a patch area, caled PAT.., if DDT
is loaded.
.number chapter 4
.ap;.ps 59 75;.ts 13 21 37;.ch IOLIB Tables
.lm 5
.hl 1 General Description
 IOLIB contains a number of tables that the programmer may need
to know about so that he can replace them with his own versions
or use the contents.
The table $TBWAD contains addresses of formatted write routines
that will be used to print value in error texts.
It is indexed by the error value code supplied to the FATAL$
or WARN$ macros.
 The programmer who is using IOLIB to read commands will very
likely want to include switch specifictions in his command
He can define his own switches in a switch table using macros
defined in IO.MAC.
.hl 1 $TBEVL - Table of Error Values
 $TBWAD contains the address of the routine which prints the
value supplied by the user for each possible code in the
EC$TYP field in ac(T1) on a call to $ERROR.
The standard IOLIB $TBWAD contains 6 possible types,
but the user is free to define his own table if he needs
Each word in the table contains the address of the formatted
write routine in the right half.
The table must be called $TBWAD and the length symbol
$LNEVL must be defined INTERNal also.
The contents of the standard table are:
.b;.nf;.ts 10 20 30;	^&Index	Symbol	Write Routine\&
.b;	0	$ECTNO	none
	1	$ECTCH	$WFCHA, write a 'funny' character
	2	$ECTDE	$WDECL, write a number in decimal
	3	$ECTFI	$WFILE, write a filename
	4	$ECTOC	$WOCTL, write a number in octal
	5	$ECTTE	$WTEXT, write an ASCIZ string
	6	$ECTWO	$WWORD, write a SIXBIT word
	7	$LNWAD	length symbol
.f;.ts 13 21 37;.hl 1 Switch Tables
 Switch tables are lists of switch names, and details about the values
that those switches can take.
Switch names and values are read by the IOLIB subroutines $RSWIT and
$RFILE (which calls $RSWIT).
The routines may be given the address of a switch table as an
When $RSWIT reads a switch name, it searches the list of names
in the switch table for an unambiguous match.
If it finds a match it uses the details in the associated lists
to read a value (if one is given) check legality of the value,
and set the value wherever the programmer directs.
In fact, $RSWIT can search two tables, the table provided by
the programmer as an argument, and a table of standard switches
pointed at by $IDSWT(I).
Standard switches are ones such as those provided in $TBSSW in
IOLIB, which contains switches for changing parameters in the
IDB, and file switches.
The point to the table of standard switches must be set into
$IDSWT(I) by the programmer.
 A switch table is actually 5 tables, that can all
be built by the one macro, SWTAB$.
There is a table of 4 pointers to the other 4 tables.
These tables are a table of switch names in SIXBIT,
a table that tells $RSWIT where to put the
value of the switch that $RSWIT reads,
a table giving either the address of a
list of keyword values, or a maximum value, and
a table of default values for if no value is given.
All these tables can be built by the one macro SWTAB$.
The switches in $TBSSW are:
.b;.nf;.ts 18 37 45;	#Value/
^&Name	Keywords	Default	Deposit\&
.b;BLOCKSIZE	decimal	4000	buffer size in FDB
MAXCOR	kword	28K	$IDTOP(I)
RUN	filename	#	rh($IDRUN(I))
RUNOFFSET	octal	1	lh($IDRUN(I))
.f;.ts 13 21 37;.hl 1 Switch Table Building Macros
 There are several macros involved in the complicated procedure
of building switch tables.
SWTAB$ is the macro called by the user to do the building,
but the programmer must have already defined a SWIT$$
macro of his own to tell SWTAB$ the switch details.
The programmer's SWIT$$ macro definition contains calls
to the SL$, SP$ and SS$ macros, which define each individual
The switches which take keyword values require a table of
keywords which can be built by the KEYWD$ macro,
and the switches which take numeric values need default
values and maximum values, which can be defined by the
DM$ macro.
 SL$, SP$ and SS$ take several arguments which define the
attributes of the switch, and differ between the
3 macros.
The first argument is the switch name.
If the first character is an '*', then the
first character of the switch is a sufficient abbreviation;
i.e if the name was given as '*HELP', then the user can always
type '/H' to get help, no matter what other switches
begin with letter H.
The second argument is always a pointer, which is used to
deposit the value of the switch.
The pointer may be a byte pointer, or a halfword point to a
full word, or a word with -1 in the left half and the
address of a user routine in the right half.
The user routine does the depositing itself.
The other arguments are different for the different macros.
.nf;	;the DM$ macro defines the symbols MX$MXC and PD$MXC
	; for the /MAXCOR switch
	DM$	MXC,256,28,28	;defaults
	;the SWIT$$ macro contains definitions for 3 switches
	;  HELP   : takes keywords 'TEXT' and 'SWITCHES'
	;             (e.g. /HELP:TEXT)
	;           the default is TEXT (4th argument)
	;           the keyword table is HELP$T
	;           a user routine called 'SWHELP' is called to
	;             deposit the value.
	;  MAXCOR : takes values in pages or Kwords
	;	    the maximum is MX$MXC and the default is PD$MXC
	;	    the value will be set into $IDTOP(I)
	;  PHYSIC : takes no value
	;	    if given, '1' will be set into $FDMOD in an FDB
	;	     at FM$PHY
HMPTAB:	#	#	;address of table
	SWTAB$	HMP	;define tables
	KEYWD$	HELP,<SWITCHES,TEXT>	;define HELP keywords
 A call to SWTAB$ produces the 5 switch tables.
The macro takes one argument, which is a 3 character name
that is concatenated with '$$x' to give names for the
individual tables.
A call to the macro requires that the user has defined a
macro, SWIT$$, that contains calls to macros
which define the individual switch details (see below).
.b;	SWTAB$	UTB	;define switch tables
.b;The name table is called UTB$$N, the pointer table UTB$$P,
the maximum table UTB$$M, and the default table UTB$$D.
 The SWIT$$ macro must be defined by the programmer
calling the SWTAB$ macro.
It contains calls to the macros, SS$, SL$ and SP$
which are defined below.
 SS$ defines a switch which has no value.
If this switch is given by the user, $RSWIT deposits a value
given in the 3rd argument (and usually a 1 bit
flag), into the position specified by the second argument.
For an example, see the definition of SWIT$$ above.
The call is
 SP$ defines switches which have values other than keywords, for
example decimal numbers or kword values.
The 3rd argument is a code for the name of the routine that will
read the value.
Available codes are: DECL, FILE, KWRD, OCTL.
The name of the code is concatenated with '$SW' to form the
name of the value reader.
 The fourth argument is a 3 letter abbreviation for the switch
name, which is concatenated with the characters 'MX$' to
give a symbol for the maximum value, and with 'PD$' to give
one for the default value.
The MX$xxx and PD$xxx symbols are defined by the DM$ macro.
If no maximum or default is wanted, this argument
may be ommitted.
 Defines a switch which takes keyword values.
The keywords can be defined by a separate KEYWD$ macro.
The third argument is a code for the name of
the table defined by the keyword macro.
It is the same name as the first argument of the
appropriate KEYWD$ macro.
 The fourth argument is a symbol for the default index
in the table.
It is a concatenation of the 4 characters of the table name
and the first two characters of the default keyword name.
 Defines three symbols, the maximum value of a parameter,
the default value if the switch is given but no
value, and the default value if the switch is not
The symbols defined are, MX$xxx, PD$xxx and AD$xxx
 Defines a table of keywords for switches and symbols for
the index of each keyword in the table.
The name argument of the macro should be 4 characters long,
and it is concatenated with the first 2 characters of the
keyword name to make the index symbol.
The index symbol for the default value should be used in the
default argument of the SL$ macro.
.b;e.g.	KEYWD$	DEN,<200,556,800,INSTALLATION>
.b;The symbols for the indices of each keyword are
.number chapter 5
.ap;.ps 59 75;.ts 13 21 37;.ch Memory Management
.lm 5
.hl 1 General Description
 Programs use free memory space for various purposes during
their execution, for arrays of data, for buffers,
for linked lists and many others.
Sometimes it is convenient to build all the memory chunks that
a program needs into the program while it is being written.
Often however, it is easy and useful to be
able to ask for and receive a chunk of free memory during
program execution.
On the DECsystem-10, the program is effectively broken into high
and low segments, the high segment being used for reentrant
code, and the low segment for non-reentrant code and data.
Memory is allocated to the program in chunks of 1P on a KI10
and 1K on a KA10 processor.
The last location used by the program is generally not the top
of the allocated memory, and the space between
the last location and the top of allocated memory is free
for use by the user program.
In addition, if this space is insufficient, the user
program can request more memory from the monitor.
 The IOLIB memory management routines allocate this free space
to any routine that requests it, and deallocate the space
when the routine announces that it has finished with it.
The memory management routines first allocate all the sace
that was available when the program was loaded, and then 
ask the monitor for more as required.
All the programmer has to do is to call the memory managers
to ask for a chunk, or to donate chunks back to the pool.
 It is not always a good thing to allow programs to grab as much
memory as they ask for, since some programs are almost insatiable,
but will move onto secondary storage when memory is exhausted (e.g.
IOLIB allows the programmer or user to limit the absolute size of
his program.
The location $IDTOP(I) in the IDB specifies the maximum number of
words that the memory managers may obtain for the program.
The BEGIN$ macro initialises $IDTOP(I) to 256K, the maximum
physically possible (without virtual memory).
The program may alter $IDTOP(I) to any required value, and the
user can use the standard /MAXCOR switch to do the same.
 IOLIB contains two forms of memory management, static
and dynamic.
They may be used in the same program, but this is unsatisfactory and an excessive
code overhead.
Static memory management satisfies each request by finding
extra space starting at the first unused location (pointed at by
 .JBFF in the job data area).
Chunks of memory cannot be deallocated using static
Dynamic memory management maintains a chain of free chunks,
and allocates and deallocates chunks from the chain.
It is much more versatile than static management but the program
overhead is higher and it uses one overhead word for each chunk.
IOLIB automatically selects dynamic management unless the user
opts for static management through the FT$ALC assembly feature test
If FT$ALC is defined as FT$ALC=0, then static management
is used.
 Both memory allocators zero chunks of memory before handing them
to the caller.
.hl 1 Dynamic Memory Management
 The dynamic memory manager is basically the ALGOL heap routine
which was originally written for ALGOL-10 by R.M. DeMorgan,
and was adapted later for FOROTS.
The manager routines keep a linked list of free chunks of memory
anchored to $IDDYC(I) in the IDB.
The list is linked through the first word (the overhead word) of
each chunk, and the last chunk has a link of 0.
The left half of the overhead word is a count of the words in the
chunk including the overhead word, and this count must never be
altered by the programmer.
The linked list of chunks is ordered by size with the smallest chunk first.
 When the manager is asked for a chunk, it scans the list for the
first chunk of the required size or larger.
If there is a chunk of the correct size, it is handed back as a
pointer to the second word, which is the first word available
to the program.
If not, the larger chunk is split and the excess returned to the
If there is no chunk large enough, the manager garbage collects the
list, concatenating adjacent chunks and tries again.
If the search fails again, the manager resorts to asking the monitor
for more memory, and so on until either $IDTOP(I) is
reached, or the monitor refuses to supply any more memory.
On failure, the manager returns code ERNEC% in ac(T1).
 When a user deallocates a chunk, the manager merely inserts the
chunk into the linked list at the correct point.
The user may return a linked list of chunks, linked through
the overhead word.
The chunks need not be in order of size.
When the program returns a chunk, he must supply a point to
the second word of the chunk; the word following the overhead
.hl 1 Static Memory Allocation
 The static allocator is very simple.
It merely looks at .JBFF for the first free location, increases it
by the amount requested and returns a point to the caller.
If the new first free location pointer exceeds the highest available
the allocator requests more memory from the monitor until
either $IDTOP(I) is reached or the monitor refuses to supply
more memory.
If the allocator fails it returns the error code ERNEC% in
 The static deallocator gives an immediate return.
The space is not made available for reallocation.
.number chapter 6
.ap;.ps 59 75;.ts 13 21 37;.ch Basic IO Routines
.lm 5
.hl 1 General Description
 The basic IO routines execute UUOs, manipulate the contents
of FDBs to set default values and keep track of progress through
the labyrinth of monitor calls.
The basic IO routines are called by all formatted read and write 
routines, and by other IOLIB routines that need
to do IO.
 It is quite possible to do IO operations without
realising the existence of the basic routines by setting up
file details in the FDB and using read and write calls.
However, the individual UUOs may be executed by
descending to basic IO calls.
The basic IO routines reflect the structure of the monitor IO UUOs;
there is an $INPUT routine to execute an INPUT UUO and a $CLOSE
routine for the CLOSE UUO.
Most of the routines do much more than execute the UUO
that they are named after.  Firstly, the routines check that
all prerequisite UUOs have been executed, and if not, the
appropriate routines are called.
So if the user calls $INPUT as his first IOLIB call for a file,
$INPUT will call $LUKUP to check whether the LOOKUP has
been done, and $LUKUP in turn will call $OPEN.
After the OPEN UUO is done, control returns to $LUKUP for the
LOOKUP UUO, and finally to $INPUT for the INPUT UUO.
Secondly, some basic routines perform other functions that
would otherwise have to be done separately by the calling
$INPUT will create a buffer ring, if none is set up, with
the number and size of the buffers a parameter in the FDB.
$INPUT also calls $USETI, to find the required record, taking the next record
number from the FDB.
The programmer can control all IO from the highest level
by making changes to the parameters in his FDB and
calling any read or write routine.
IOLIB arranges to call other necessary routines lower
in the hierachy.
 Calls to the basic routines are channel independent.
The programmer need not try to assign channels
to individual files, but should let IOLIB do it for him.
$OPEN assigns the next free channel to the user, starting
with channel 1.
Channel 0 is never used unless the programmer explicitly
directs $OPEN to use it.
The caller cannot specify an exact channel number for
a file, but he can suggest where the search for a free channel should begin.
 All the basic IO routines expect the pointer to the current FDB
to be set up in ac(D), to
describe the file for which the IO operation is to
be performed.
All non-default values must be set in the FDB.
 Because the basic routines are called so frequently, they are careful
to save all acs, including temporaries, except those used to transmit
An exception is the error return, when ac(T1) contains an error
code with a UUO code in the left half and a specific error
code in the right half.
 Most of the basic routines are assembled into one module, IOMOD, which is
always loaded with every program that uses IOLIB.
The calls for the basic routines are explained in Appendices A _& B.
Algorithms for critical routines are given in the sections
.hl 1 $INPUT - Read a Physical Record from a File
 To read a physical record from a file.
There are 3 returns; non-skip on an error, skip on endfile
and double skip on a successful return.
An error code is returned in ac(T1) for both error and 
endfile returns.
The full algorithm is:
.ls;.le;check the tempcore input flag (FC$TCI in $FDCHN(D)).
If on, give an immediate endfile return.
.le;call $LUKUP to execute OPEN and LOOKUP UUOs if not already
done for this file.
.le;if dump mode (check $FDSTS(D)), goto step 4.
Otherwise, if no input buffer ring is established, call $MKBUF to build one taking the size and number of buffers
from $FDBUF(D).
.le;load the next block number from $FDNBK(D) and call $USETI
to find the required physical record.
.le;set [this block number,,next block number] into $FDNBK(D).
.le;execute the input by an 'INPUT ch,@$FDIOW(D)' instruction
so that for dump mode, $FDIOW(D) should point to a chain
of IOWDs, and for buffered modes $FDIOW should normally be zero,
but may point to the next buffer.
.le;if ok, return double-skip now.
Otherwise, call $GETST to read the IO channel status, then
call $SETST to clear
error and endfile bits.
.le;calculate the error code from the error and endfile bits
in the IO channel status.
.le;skip return if endfile.
Otherwise normal return.
.els;.b;^&FDB words altered:\&
.lm +7;.i -7;$FDNBK#set to [this-record-number,,next-record-number].
The next record is just this record+1 for sequential reads.
.i -7;$FDSTS#on error and endfile, right half set to
IO channel status word.
.lm -7;.b;^&FDB words used:\&
.lm +7;.i -7;$FDBUF#to build buffer ring.
$OPEN sets defaults from the monitor if the user does not provide
his own values.
Either number or size of buffers or both may be given.
.b;.i -7;$FDNBK#the right half is used to determine which record
to read next (disk only).
The programmer may set the next record number for random input, otherwise $INPUT will read sequentially starting from the beginning.
.b;.i -7;$FDIOW#addressed by the INPUT UUO instruction.
The user must set up this word for dump mode IO.
.lm -7;.hl 1 $OUTPU - Write a Physical Record to a File
 To write a physical record to a file.
There are 2 returns; non-skip on an error,
and skip on a successful return.
An error code is returned in ac(T1) for error  return.
The full algorithm is:
.ls;.le;call $ENTER to execute OPEN and ENTER UUOs if not already
done for this file.
.le;if dump mode (check $FDSTS(D)), goto step 4.
If an output buffer ring is established, goto step 4 to avoid
a dummy output.
Otherwise call $MKBUF to build one taking the size and number of buffers
from $FDBUF(D).
.le;clear $FDNBK(D) because this is a dummy output.
Before return, $FDNBK(D) will be incremented for the first output.
Goto step 5 to avoid USETO.
.le;load the next block number from $FDNBK(D) and call $USETO
to find the required physical record.
.le;set this block number,,next block number into $FDNBK(D).
.le;execute the output by an 'OUTPUT ch,@$FDIOW(D)' instruction
so that for dump mode, $FDIOW(D) should point to a chain
of IOWDs, and for buffered modes $FDIOW should normally be zero,
but may point to the next buffer.
.le;if ok, return skip now.
Otherwise, call $GETST to read the IO channel status, then
call $SETST to clear error bits.
.le;calculate the error code from the error bits
in the IO channel status.
.le;non-skip return to show error.
.els;.b;^&FDB words altered:\&
.lm +7;.i -7;$FDNBK#set to [this-record-number,,next-record-number].
The next record is just this record+1 for sequential writes.
.b;.i -7;$FDSTS#on error, right half set to
IO channel status word.
.lm -7;.b;^&FDB words used:\&
.lm +7;.i -7;$FDBUF#to build buffer ring.
$OPEN sets defaults from the monitor if the user does not provide
his own values.
Either number or size of buffers or both may be given.
.b;.i -7;$FDNBK#the right half is used to determine which record
to write next (disk only).
The programmer may set the next record number for random output, otherwise $OUTPU will write sequentially starting from the beginning.
.b;.i -7;$FDIOW#addressed by the OUTPUT UUO instruction.
The user must set up this word for dump mode IO.
.lm -7;.hl 1 $LUKUP - LOOKUP a File
 Check if the file has already been LOOKUPed.  If so,
give a good return.
Otherwise, execute a LOOKUP UUO for the file.
The routine executes an extended LOOKUP for disk files, and
a short LOOKUP for all other devices.
The length of the extended LOOKUP is taken from
$FDCNT(D) which is initialised by $CLRFD.
The full algorithm is:
.ls;.le;call $OPEN to execute an OPEN UUO if necessary.
.le;check whether $LUKUP has already been called
for this file (FC$LUK in $FDCHN on).
If so, give an immediate skip return.
.le;execute a LOOKUP UUO.
If error, set error code and non-skip return.
.le;otherwise, set FC$LUK in $FDCHN(D) and skip return.
.els;.b;^&FDB words altered:\&
.lm +7;.i -7;$FDCHN#FC$LUK is set on a skip return so that $LUKUP will know
next time it is called.
.b;.i -7;$FDRIB#see Monitor Calls Handbook for words affected by the LOOKUP UUO.
.lm -7;.b;^&FDB words used:\&
.lm +7;.i -7;$FDRIB#used by LOOKUP UUO
.lm -7;.hl 1 $ENTER - ENTER a File
 Check if the file has already been ENTERed.  If so,
give a good return.
Otherwise, execute a ENTER UUO for the file.
The routine executes an extended ENTER for disk files, and
a short ENTER for all other devices.
The length of the extended ENTER is taken from
$FDCNT(D) which is initialised by $CLRFD.
If FM$PRO is set to ones in $FDMOM(D), then the contents of
FM$PRO in $FDMOD(D) is set into $FDPRV(D).
 $ENTER has two entry points, $ENTER and $ENTE0.
$ENTER assumes that the caller does not want to set the protection,
the mode, or the create time and date from $FDRIB(D), so
it clears $FDPRV(D) and rh($FDEXT(D)).
$ENTE0 does not alter $FDRIB(D) in any way other than that
described below.
Note that all IOLIB routines higher in the hierachy enter
this routine at $ENTER.
The full algorithm is:
.ls;.le;ENTER entry: zero $FDPRV(D) and rh($FDEXT(D)).
.le;ENTE0 entry: call $OPEN to execute an OPEN UUO if necessary.
.le;check whether $ENTER has already been called
for this file (FC$ENT in $FDCHN on).
If so, give an immediate skip return.
.le;execute a ENTER UUO.
If error, set error code and non-skip return.
.le;otherwise, set FC$ENT in $FDCHN(D) and skip return.
.els;.b;^&FDB words altered:\&
.lm +7;.i -7;$FDCHN#FC$ENT is set on a skip return so that $ENTER will know
next time it is called.
.b;.i -7;$FDPRV#contents of protection field in $FDMOD added if masked by $FDMOM.
.b;.i -7;$FDRIB#see Monitor Calls Handbook for words affected by the ENTER UUO.
.lm -7;.b;^&FDB words used:\&
.lm +7;.i -7;$FDMOD#protection field used if masked by $FDMOM
.b;.i -7;$FDMOM#FM$PRO mask used.
.b;.i -7;$FDRIB#used by ENTER UUO
.lm -7;.hl 1 $OPEN - OPEN an IO Channel
 A software IO channel must be OPENed to initiate IO with any file.
$OPEN takes the file described by the current FDB, finds a
free channel, inserts defaults for all values not given by the
caller and then executes an OPEN UUO.
$OPEN does not attempt to reopen a file that has already been OPENed.
The full algorithm is:
.ls;.le;check whether the channel is already open ($FDOPN in $FDCHN(D))
and skip return if so.
.le;call $FRCHN to find the first free channel starting with the
channel number supplied by the user if $FDCHN(D) is non-zero, and with
channel 1 otherwise.
Set the channel number into FC$CHN in $FDCHN(D).
If no free channels are found, set ERNFC$ and non-skip return.
.le;check $FDDEV(D), and set 'DSK' if zero.
.le;do a DEVTYP UUO.
If the result is zero set ERNSD% and error return.
Otherwise, set the result into $FDTYP(D).
.le;check the DEVTYP word to see whether the device is available.
If not, set ERDNA% and error return.
.le;check whether the device is not spooled and is restricted.
If so, check that we have the device assigned and if not
give ERRSD$ and error return.
.le;execute a DEVSIZ UUO. if dump mode, goto step 9.
If improper mode set, set ERIMP$ and error return.
.le;use the user settings or the defaults returned by the DEVSIZ
UUO to set $FDBUF(D) with the buffer number and size.
Set pointers to the buffer headers, $FDIBH(D) and $FDOBH(D) into
.le;check if the device is a magtape.
If not, goto step 11
.le;check whether the magtape parity and density were set
in $FDMOD(D) were they masked in $FDMOM(D)), and if so transfer
the settings to $FDSTS(D).
.le;check whether 'physical-only' set in $FDMOD(D) (FM$PHY
masked in $FDMOM(D)) and if so, set it in $FDSTS(D).
.le;execute the OPEN UUO.
The only unchecked error is no available DDBs, so if error, set
ERNET% and error return.
.le;if the next block number is zero, set it to 1
.le;set FC$OPN in $FDCHN(D) and skip return.
.els;.b;^&FDB words altered:\&
.lm +7;.i -7;$FDCHN#channel number into FC$CHN and FC$OPN on.
.b;.i -7;$FDTYP#filled with result of DEVTYP UUO.
.b;.i -7;$FDDEV#if zero, filled with 'DSK'.
.b;.i -7;$FDBUF#if buffered mode, and either half zero, that half is
filled with the system default returned by the monitor on a
.b;.i -7;$FDBHD#if buffered mode, filled with points to $FDIBH and $FDOBH.
.b;.i -7;$FDSTS#may have physical-only and magtape parity and density
set if those fields are masked by $FDMOM.
.lm -7;.b;^&FDB words used:\&
.lm +7;.i -7;$FDCHN#if non-zero, channel number is used as a starting point for
free channel search.
.b;.i -7;$FDOPN#see Monitor Calls Handbook for usage by OPEN and DEVSIZ UUOs.
.b;.i -7;$FDMOD#holds magtape density and parity and physical-only bit if
corresponding masks in $FDMOM are ones.
.b;.i -7;$FDMOM#masks for fields in $FDMOD.
.lm -7;.hl 1 $CLOSE - Disconnect a File from an IO Channel
 $CLOSE severs the connection between a file and a software channel,
but does not RELEAS the channel.
There are two entry points.
$CLOSE closes both sides of the channel, and does not allow the
caller to set any CLOSE bits.
$CLOS0 takes CLOSE bits as an argument.
$OPEN must have already been called for this file.
The algorithm is:
.ls;.le;CLOSE entry: zero CLOSE bits
.le;CLOS0 entry: execute CLOSE UUO.
.le;zero the block number in $FDNBK(D).
.le;if CL.OUT was not set, clear FC$ENT in $FDCHN(D).
.le;if CL.IN was not set, clear FC$LUK in $FDCHN(D), and return.
.els;.b;^&FDB words altered:\&
.lm +7;.i -7;$FDNBK#zeroed
.b;.i -7;$FDCHN#bits FC$ENT and FC$LUK may be cleared.
.lm -7;.hl 1 $RLEAS - Release an IO Channel
 The IO channel used by the current FDB is released, and any
buffer rings are returned to the pool of free core chunks.
$OPEN should have been called for the current FDB
before calling $RLEAS.
 $RLEAS has two entry points: $RLEAS executes the UUO
and deletes buffer rings but $RLEA0 saves the buffer rings.
The algorithm is:
.ls;.le;call $DLBUF to return output buffer ring to pool of free
core chunks
.le;call $DLBUF to return input buffer ring
.le;$RLEA0: execute the RELEAS UUO.
.le;clear $FDCHN(D) to zero the flags and channel number
.els;.b;^&FDB words altered:\&
.lm +7;.i -7;$FDCHN#zeroed
.lm -7;.b;^&FDB words used:\&
.lm +7;.i -7;$FDBHD#to find the buffer headers and rings.
.lm -7;.hl 1 $RENAM - Change RIB Details for a File
 To execute a RENAME UUO for the current file.
A RENAME can be used to delete a file from disk or DECtape, and
to change the name and extension.
In addition, it can be used to change other details kept in the
RIB block, such as protection and create date/time.
$RENAM does an extended RENAME for disk files using the length in
$FDCNT(D), and a short RENAME for other devices.
 The programmer should call $LUKUP for the file to obtain the
current file details, and then change the FDB and call $RENAM.
If the protection field in $FDMOM(D) is on (FM$PRO is 777)
then the protection code is taken from the FM$PRO field in $FDMOD(D).
.b;^&FDB words altered:\&
.lm +7;.i -7;$FDPRV#the protection field is changed if FM$PRO is on in $FDMOM.
.lm -7;.b;^&FDB words used:\&
.lm +7;.i -7;$FDRIB#used by RENAME UUO.
.b;.i -7;$FDMOD#used if FM$PRO is on in $FDMOM.
.b;.i -7;$FDMOM#for FM$PRO mask
.lm -7;.hl 1 $DELET - Delete a File
 Delete a file from disk or DECtape by calling $LUKUP to find the
file, and then $RENAM to delete the file.
There is no need for the file to have been referenced before a
call to $DELET.
.hl 1 $USETI/O - Set the Disk File Record Number
 These routines execute USETI or USETO UUOs to ensure that the
next block read or written with the disk is the correct one.
A word containing the last record number in the left
helf and the required block number in the right half is an argument.
If the required record is the last record + 1, then
no UUO is executed.
These routines do not defend against asynchronous IO, therefore
they are only suitable for use with dump mode, or with synchronous
buffered modes.
.b;^&FDB words altered:\&
.lm +7;.i -7;$FDNBK#returns with right half set to this record number, and the
left half set to this record - 1.
.lm -7;.hl 1 $GETST - Read the IO Channel Status
 Read the IO channel status from the monitor and store it in the
right half of $FDSTS(D).
This routine requires that $OPEN has already been called.
.b;^&FDB words altered:\&
.lm +7;.i -7;$FDSTS#right half receives IO status word.
.lm -7;.hl 1 $SETST - Set the IO Channel Status
 Set the given IO status word into the monitor for the current FDB.
This routine requires that $OPEN has already been called.
.hl 1 $XTUUO - Execute an IO UUO
 Execute the given IO UUO for the current FDB.
The channel number is obtained from FC$CHN in $FDCHN(D) and
or'ed into the A field of the UUO instruction.
The routine has skip and non-skip returns, but the skip
return may be ignored for UUOs that have no skip return
 A useful feature for debugging programs is that every IO UUO
is executed by an XCT instruction from the location labelled
'$$XUUO', so that a breakpoint on $$XUUO will catch
every IO UUO.
Examine ac(T1), to find the UUO.
.hl 1 $XTCAL - Execute an IO Oriented CALLI UUO
 For some CALLI UUOs it is important to know whether IO on the
associated file is 'physical only' e.g. a GETSEG
UUO must be executed physical only if this is specified.
$XTCAL, checks the current FDB to see whether either UU.PHS
is set in $FDSTS(D) or UU.PHY is set in $FDMOM(D) and $FDMOD(D),
and if so, makes the UUO physical only before executing it.
As a side effect, if physical only was set in $FDMOM, then the
setting in $FDMOD(D) is set into $FDSTS(D).
 A useful debugging feature is that all CALLI UUOs executed
through a $XTCAL (or $XTDCL) call are executed by an XCT instruction
at '$$XCAL'.
Examine ac(T1) to find the UUO.
The full algorithm is:
.ls;.le;check whether physical only is implemented.
If not, clear the indicator.
Goto step 4.
.le;check whether FM$PHY is set on in $FDMOM(D).
If not, goto step 5.
.le;read the physical-only setting from FM$PHY in $FDMOD(D)
into the indicator.
.le;set the indicator into $FDSTS(D).
.le;check the physical only flag in $FDSTS(D). 
If on, complement bit19 of the UUO, to show physical only.
Execute the UUO and return.
.els;.b;^&FDB words altered:\&
.lm +7;.i -7;$FDSTS#bit0 is set if FM$PHY is on in $FDMOM.
Bit0 is set to FM$PHY in $FDMOD.
.lm -7;.b;^&FDB words used:\&
.lm +7;.i -7;$FDMOD#FM$PHY field checked and used.
.b;.i -7;$FDMOM#FM$PHY mask used
.lm -7;.hl 1 $XTDCL - Execute a Device Oriented CALLI UUO
 This routine is an entry point to the $XTCAL routine.
The distinction is that this routine is for CALLI UUOs
that take a device name as an argument.
$XTDCL takes the device name from $FDDEV(D), and uses
'DSK' as a default.
'DSK' is set into $FDDEV(D) if it was empty.
.b;^&FDB words altered:\&
.lm +7;.i -7;$FDDEV#if empty on entry, it is set to 'DSK'.
.lm -7;.hl 1 $MKBUF - Build a Ring of Buffers
 Use the size and number of buffers stored in $FDBUF(D) to build
a ring of buffers of the requied size, and link them into
the given buffer header.
Initialise the ring-use bit.
.b;^&FDB words used:\&
.lm +7;.i -7;$FDBUF#uses both number and size of buffers to create ring
.lm -7;.hl 1 $DLBUF - Delete a Rinf of Buffers
 Given the address of a buffer header, garbage collect the
buffer ring and return all buffers to the pool of free
chunks of core.
This routine is ineffective if static core allocation is
being used.
.hl 1 $UPDAT - Open a File for Updating
 Open the file with a LOOKUP and ENTER on the same channel.
.hl 1 $UPDWT - Open a File for Updating and Wait
 Call $UPDAT to open the file for updating.
If the error return gives 'file being modified',
wait for a given time and try again.
Repeat for a given number of times, and finally give
.hl 1 $APEND - Open a File for Appending
 Open the current file for updating, by executing a call
to $UPDAT, then setup the FDB so that the first block written
will be the last block. If IO is in a buffered mode, set the output
buffer header to point to the first free word of the last block.
Return a count of the number of free words in the last block.
 Note that $APEND assumes that the current file is an append-only
file, and this routine will fail if the protection is more liberal.
 The full algorithm is:
.ls;.le;open the file for updating using $UPDAT
.le;calculate the number of blocks in the file, and the words
remaining in the last block from $FDSIZ. Set $FDNBK to write
the last block.
.le;check the channel IO mode.
If a dump mode, goto step 6.
.le;do a dummy output for buffered modes
.le;set the byte pointer in the output buffer header to point to
the first free word, and alter the remaining byte count accordingly.
.le;set ac(T1) to the count of free words and skip return.
.els;.b;^&FDB words used\&
.lm +7
.i -7;$FDSIZ#gives the size of the file in words
.b;.i -7;$FDSTS#gives the channel IO mode
.lm -7;.b;^&FDB words altered\&
.lm +7;.i -7;$FDNBK#set to the last block of the file
.b;.i -7;$FDOBH#byte pointer set to the first free word and
byte count set to reflect free bytes remaining
.lm -7
.hl 1 $APDWT - Open a File for Appending and Wait
 Call $UPDWT to open the file for updating. If the file is opened
successfully, call $APEND to set up the block number and buffer
header for appending to the file.
.hl 1 $MTxxx - Execute an MTAPE UUO
 There are 12 $MTxxx routines, each of which executes a different function
of the MTAPE UUO for the current file. The 'xxx' is the code for the
various functions e.g. $MTREW does a MTREW. to rewind the tape. A
complete list of functions may be found in the Monitor Calls Handbook.
 The $MTxxx routines all wait for completion of the function
with an MTWAT. before returning control. $MTBSF (backspace file), skips
forward over the endfile unless at beginning of tape.
.number chapter 7
.ap;.ps 59 75;.ts 13 21 37;.ch Formatted Reading and Writing
.lm 5
.hl 1 General Description
 IOLIB contains routines for reading and writing data as ASCII strings
and converting them into an internal form according to a wide variety of formats.
For example, the $RDECL routine reads a string from the current file
and converts it as a signed decimal integer into a binary number.
The $WDECL routine takes a binary number, converts it as a signed
decimal integer into a string and writes it to the current file.
 All the formatted input and output routines work on the
current file, so that they need the current file point set up
in ac(D).
All the input routines use a single routine, $$RCHR, to read the next
character from the file, and all the output routines use
one routine, $$WCHR, to write the next character.
These routines do not have an error return, but assume that all IO
errors are fatal, and trap to the fatal error handler, $FTLIO.
The user programmer may rewrite $$WCHR and $$RCHR to provide his
own error handling or to provide other features at a low level.
$$WCHR merely calls $WRITE, the routine which writes one byte to
the current file, and traps error returns.
$$RCHR interprets the input string as a DECsystem-10 standard
command string, and uses the DEC algorithm to edit the input
string before passing the characters back to the calling routine.
$$RCHR compresses sequences of spaces, removes spaces at the
beginning and end of lines, handles continuation lines and
returns standard codes for endline, endfile and altmode.
The user programmer may redefine $$RCHR to use a lower level of
editing or no editing at all, or even to edit or not depending
on the current file, if he wishes.
 The formatted output routines are straightforward, and full
details may be found in Appendix A.
Formatted input is a little more complicated.
The input routines read the input string interpreting characters
until they find one that does not belong to the format being read.
Then they return the values read to the caller, including the
delimiting character in ac(T1).
Therefore, the caller has the responsibility to check the delimiter
to ensure that it is correct.
The routines to read filenames and switches are special cases
and are dealt with in some detail in this chapter.
.hl 1 $WRITE - Write one Byte to the Current File
 This is the basic buffered-write routine.
It is called to write one byte, of the size defined by the
current file, to that file.
It ensures that all prerequisite UUOs have been performed
and that a buffer ring is built and initialised,
by calling $OUTPU for a dummy output.
It has error and skip returns.
There is a write byte routine, $$WBYT, that performs
the same function as $WRITE, but has no error return and
instead calls $FTLIO.
The algoritm is:
.ls;.le;if the current file point is zero (TTCALL IO), write the
character using OUTCHR and skip return immediately.
.le;if the current file point is a byte pointer (bits 0-11 nonzero),
write the byte using IDPB and skip return immediately.
.le;otherwise, check the byte count in the buffer header $FDOBH(D);
unless the buffer is full, goto step 5.
.le;call $OUTPU to empty the buffer.
This also ensures a dummy OUTPUT on the first call.
If error, nonskip return.
.le;decrement byte pointer in $FDOBH(D) and write the byte into
the buffer.
Skip return.
.els;.b;^&FDB words altered:\&
.lm +7;.i -7;$FDOBH#the buffer header is altered by changing the byte pointer and
byte counts
.lm -7;.hl 1 $$WBYT - Write a Byte to the Current File
 $$WBYT is a replaceable routine.
The IOLIB version calls $WRITE, and returns to caller if $WRITE
gives a skip return, but calls $FTLIO if $WRITE gives an error
The user programmer may rewrite this routine to perform
additional functions if he wishes.
.hl 1 $$WCHR - Write a Character to the Current File
 The IOLIB version of $$WCHR is identical to $$WBYT, but the
routines are separately replaceable.
The distinction is that $$WCHR is called by all formatted
output routines to write characters.
 As an example of a replacement $$WCHR, suppose that a log
file is used for error messages and the point to the
log file FDB is kept in $IDEFD(I).  
We want to send messages that go to the log file, to
the terminal as well, so write:
	CAME	D,$IDEFD(I)	;is this the log file?
	JRST	WCH10	;no
	PUSH	P,T1	;yes, save character
	TRMFD$	#	;set FDB to terminal
	WRITE$	#	;send character to terminal
	##FATAL$	;
	POP	P,T1	;recover character
	MOVE	D,$IDEFD(I)	;recover log file FDB
	WRITE$	#	;send character to file
	##FATAL$	;
	POPJ	P,	;
.f;.hl 1 $READ - Read a Byte from the Current File
 This is the basic buffered-read routine.
It is called to read one byte, of the
size defined by the current file, from the current file.
It ensures that all prerequisite UUOs are executed and that
a buffer ring is built and initialised, by calling
$INPUT to read records from the file.
It has three returns, nonskip for errors, skip for endfile
and double-skip for normal return.
There is a replaceable read byte routine, $$RBYT, that performs
the same function as $READ, but has no error return, and
instead calls $FTLIO.
The algorithm is:
.ls;.le;if the current file point is zero (TTCALL IO), read the
character using INCHWL and double-skip return immediately.
.le;if the current file point is a byte pointer (bits 0-11 nonzero)
read a byte using ILDB.
If the byte is zero, give an endfile return with T1 0; otherwise
give a double skip return.
.le;otherwise, check the byte count in the buffer header, $FDIBH(D),
and unless the buffer is empty, go to step 5.
.le;call $INPUT to read the next record.  If error or endfile,
give the appropriate returns.
.le;read the next character from the buffer, and decrement the
buffer byte count.
Double skip return.
.els;.b;^&FDB words altered:\&
.lm +7;.i -7;$FDIBH#the buffer header is altered by changing the byte pointer and
byte count.
.lm -7;.hl 1 $$RBYT - Read a Byte from the Current File
 $$RBYT is a replaceable routine.
The IOLIB version calls $READ, and returns to caller if $READ
gives endfile or normal returns; endfile is nonskip
and normal is skip.
If $READ gives an error return, $$RBYT calls $FTLIO.
The user programmer may rewrite $$RBYT to perform additional
functions if he wishes.
.hl 1 $$RCH0 - Read a Character frm the Current File
 The IOLIB version of $$RCH0 is identical to $$RBYT, but
the routines are separately replaceable.
The distinction is that $$RCH0 is called by the command
string character editor $REDCH, and is used for reading
all command characters.
 The user programmer may rewrite $$RCH0 to
perform additional functions.
For example, he might want to be able to trap endfile
and move up one level of command file in a system that
allowed nested command files:
	READ$	#	;get next character
	##FATAL$	;
	##CAIA	#	;endfile, so check nesting depth
	PJRST	$POPJ1_#_#	;skip return
	MOVE	T1,CFSTKP	;pick up point to command file stack
	CAMN	T1,CFSTK0	;compare with empty stack
	POPJ	P,	;empty - user typed control-Z
	RLEAS$	#	;lose current command file
	POP	T1,D	;recover next command FDB
	POP	T1,CFSTKP	;recover last character from this file
	EXCH	T1,CFSTKP	;swap stack point and character
	PJUMPE	D,$POPJ1_#_#	;return if TTCALL
	;back to previous command file.  Reopen it
	HLRS	$FDNBK(D)	;reread last block
	PUSH	P,$FDIBH+1(D)	;save buffer header pointer and count
	INPUT$	#	;read block
	##FATAL$	;error
	##FATAL$	;endfile is error too
	POP	P,$FDIBH+2(D)	;set up for next read
	POP	P,$FDIBH+1(D)	;
	PJRST	$POPJ1_#_#	;good return
.f;.hl 1 $$RCHR - Read a Character from the Current Command File
 $$RCHR is the replaceable routine called by all the formatted
read routines to read the next character.
It has no error or endfile returns.
The endfile condition should be converted into a $CHEOF special character.
The IOLIB version of $$RCHR calls $RCALT, which is one of the
entry points to the command character editing coroutine, $RCCHR.
$RCALT has the property that if the last character read was
an altmode ($CHALT), then another altmode is returned to the
caller without reading anything from the input file.
Therefore if the user ends a line with an altmode, and the
altmode condition is not cleared, the caller routine will
have altmodes returned for all subsequent requests for characters.
This is just what is required for a program asking a series
of questions, when an altmode means that all future questions
take the default answer.
If this feature is not required, redefine $$RCHR as a jump
to $RCCHR:
	PJRST	$RCCHR_#_#	;no altmode defaulting
.f;.b;If the command character interpreting is not required, but the basic
editing provided in $REDCH is, then redefine $$RCHR as a jump to
	PJRST	$REDCH_#_#	;just basic editing
.f;.b;Of course, $$RCHR can be rewritten to perform additional functions
as well, but since it is called by all the formatted input
routine it must at least return the codes:
.b;.nf;.ts 20 25 35;	0	$CHALT	altmode (ASCII 033)
	-1	$CHEOL	endline (ASCII 012,013,014)
	-2	$CHEOF	endfile (ASCII 003,032)
.f;.ts 13 21 37
.hl 1 $REDCH - Read a Character and do Basic Command Editing
 Read a character from the current command file and perform some
preliminary editing.
$$RCH0 is used to read the character.
.ls;.le;make the endfile return look like a control-Z character.
.le;ignore nul (ASCII 000), carriage return (ASCII 015) and
delete (ASCII 177).
.le;make tab (ASCII 011) into space (ASCII 040)
.le;if escape (ASCII 033) give terminal user a <cr><lf> and set
code $CHALX (0).
.le;make vertical tab (ASCII 013), form feed (ASCII 014)
and line feed (ASCII 012) into $CHEOL (-1).
.le;if control-C (ASCII 003) clear the command scanning coroutine pc
.le;if either control-C or control-Z (ASCII 032) turn into
$CHEOF (-2).
.els;.hl 1 $RCCHR - Read a Character and Edit as a Command Character
 Return the next character in a command string.
This may involve reading a character from the command file
or rereading a character already processed.
The routine compresses multiple spaces into one space,
ignores leading and trailing spaces on a line,
ignores comments (all characters following a ';') and
ignores endline immediately preceded by a '-', so that
continuation lines are possible.
 $RCCHR is a coroutine whose pc is kept in $IDCPC(I) in the IDB.
The coroutine often has to look ahead one character to
determine the meaning of the current character, and the
lookahead character is kept in $IDLAC(I) in the IDB.
The last character read is always available in $IDLSC(I).
 If any character is set in $IDNXC(I) on entry to
$RCCHR, then the routine will take this character as the next
character to be read.
The programmer can force a character to be read by placing
it in $IDNXC(I).
 There is a second entry point to $RCCHR, $RCALT, which
checks if the last character was an altmode, and
if so returns an altmode immediately instead of reading 
another character.
This is the default entry point to $RCCHR.
.b;Note:##This routine may only be used for one file at a time.
.hl 1 $RFILE - Read a Filename from the Current File
 $RFILE will read a complete file specification written
in a form compatible with that accepted by SCAN, the DEC command
The filename read by $RFILE can contain the components: one device, one name,
one extension, one path specification and a number of switches written in any order.
The name, extension and path specification may contain wild cards.
No individual field is compulsory and the specification is terminated
by some character not belonging to the specification.
 The filename is decoded into an FDB, which may be supplied by the
caller, but if not will be obtained by $RFILE from the memory
The FDB is intialised by calling $CLRFD.
 $RFILE maintains an extra FDB known as the default file FDB.
Any parts of the file specification that are typed before the name
are assumed to be 'sticky' for any other file specifications
typed on the same line, and these sticky defaults are
remembered in the default FDB.
The current defaults are applied to a filename after reading the specification
and before returning to the caller.
The user programmer may supply the default FDB by putting a
point to the FDB into $IDDFD(I) in the IDB.
Otherwise, $RFILE obtains space for the FDB from
the memory manager.
The user programmer may preset defaults into the default
FDB, if for instance he wishes the default extension to be '.REL'.
 Wildcard characters are set into the appropriate fields in the
FDB and are masked by the corresponding field in the appropriate
mask word.
Non-wild characters are masked by ones, and wild characters
are masked by zeros.
The programmer must call $LKWLD The caller can provide a table of switches that may be encountered
in this file specification.
He can also specify standard switches by placing a pointer
to the standard switch table into $IDSWT(I) in the IDB.
IOLIB defines a set of standard file switches in the table
$TBSSW and the user programmer can use this 
as the standard table.
Some of the standard file switches set fields in $FDMOD in the FDB
and set the corresponding mask in $FDMOM.
These switches will also be set in the default FDB, and become
sticky if they are given before the name field.
 $RFILE returns the delimiting character and a point to the FDB.
The point to the FDB is in ac(T2), and the left half of
that ac contains flags:
.b;.ts 10 20 30;.lm +25;.i -20;1B0	FF$NUL	file specification was null except possibly
for switches.
No meaningful file name fields were typed.
.b;.i -20;1B1	FF$WLD	the file specification contains wild characters
.lm -25;.hl 1 Read Path and PPN Specifications
 There are three routines for reading parts of a
path specification.
$RPJPG reads a project-programmer number (without [])
including wildcards, and checks to make sure that
the numbers are within range.
$RPPN reads a full PPN specification including
the [], and $RPATH can read SFD names as well.
 All the routines return a delimiter (in the case of
$RPPN and $RPATH, the character following ']'),
a value, a mask and a flag word which has bit0 set
if the PPN is the default ([-]) and bit1 set if
any wildcards were seen.
The value is the PPN if there were no SFDs, and the
mask is the PPN mask.
If $RPATH did read SFD names, the the value is a point
to a path block, and the mask is a point to a mask
$RPATH obtains the path and mask blocks
from the memory manager.
.hl 1 $RSWIT - Read a Switch Name and Value
 $RSWIT reads a switch name and compares it with a table of switch
names supplied by the caller.
If this does not succeed unambiguously, $RSWIT looks for a
point to a table of standard switches in $IDSWT(I) in the
If there is one, $RSWIT tries to match the switch with those
in this second table.
Assuming that $RSWIT succeeds somewhere, it then uses data
in the switch tables to determine whether to read a
value and if so, what data format to read the value in.
$RSWIT reads the value, and uses further information in the
switch tables to determine where to deposit either the
value, or default data if there was no value.
$RSWIT can deposit data using a byte pointer.
The macros that build switch tables are discussed in sections
4.2 and 4.3.
.number chapter 8
.ap;.ps 59 75;.ts 13 21 37;.ch Tempcore Routines
.lm 5
.hl 1 General Description
 Tempcore is a device whereby small files of data may be kept in
core storage within the monitor for ultra fast
access by user programs.
It is mainly intended for use by the CCL command interpreter
which keeps small files of commands in tempcore for one of
the invoked processors to read.
 The amount of space allocated to tempcore is small and if enough
users generate enough tempcore files at once it overflows.
So the programs that read and write tempcore are built to
try tempcore first, and if that is unsuccessful, to try a file
on the disk with a certain name.
The tempcore read, write and delete routines handle the file
whether it is in tempcore or on the disk.
 A convention on the DECsystem-10 is that if a program is entered
at its start address then everything is normal, but if
the program is entered at the location following the start
address ('start+1'), then commands are to be taken from a
tempcore file.
IOLIB allows this feature as an assembly parameter.
If FT$CCL=-1, then the feature is included.
If FT$CCL=0, it is not.
If it is included and entry is a start+1, IOLIB sets up the command
input file to be a tempcore file.
The user programmer must ensure that he calls $TMPIN before
reading that file, and deletes the file with $TMPDL at some stage.
 Tempcore files have 3 character filenames, and by default IOLIB
chooses the first 3 characters of th program name.
If the file is on disk, the name is 'jjjnnn.TMP', where
jjj is the job number, and nnn is the name.
e.g. 023MAC.TMP
.hl 1 $TMPFD - Build a Tempcore FDB
 $TMPFD obtains an FDB from the memory manager and
initialises it with the extension 'TMP', and a name
made from the job number and the 3 character name supplied.
The point to the FDB is returned in ac(D).
.hl 1 $TMPIN - Read a File from Tempcore
 Build a one buffer ring using $MKBUF, and then try
to read the file from tempcore.
On success, set up the buffer header, so that the first call to $READ will return the first character, and set FC$TCI in
$FDCHN(D) to ensure that the next call to $INPUT will
give an endfile return.
If the tempcore read fails, read the file from disk using
 The technique for reading tempcore files is to define FT$CCL=-1
for assembly, which ensures that the FDB is set up correctly.
Call $TMPIN and then read the file using normal
formatted read routines.
Finally, when the program finishes, delte the tempcore
file with $TMPDL.
.hl 1 $TMPDL - Delete a Tempcore File
 Tempcore files should be deleted after they have been read
so that they don't clutter up an overcrowded tempcore area
and so that the disk directory doesn't fill up with .TMP
$TMPDL deletes the file from both tempcore and disk.
.hl 1 $TMPOU - Close a Tempcore Output File
 Tempcore files are normally short.
If they have exceeded one buffer in length then the file
may already have been entered on the disk, and $TMPOU
merely releases the file.
If not, then $TMPOU attempts to write the file into tempcore,
and if that fails, then the file is written to disk and
 The technique for writing a tempcore file, is to set up
the FDB using $TMPFD (one buffer is sufficient), then
to write to the file normally using formatted output
routines, and finally to end with a call to $TMPOU
instead of to $RLEAS.
.number chapter 9
.ap;.ps 59 75;.ts 13 21 37;.ch Error Reporting
.lm 5
.hl 1 General Description
 IOLIB contains macros and routines for writing error messages to a specified file with the minimum of programmer effort.
The messages are written in the standard DECsystem-10 error format with
a one character severity indicator, then two
optional 3 character codes identifying the program and the error, and
lastly the error text.
A value can be included in the message, printed in one of a number
of possible formats.
Fatal errors do not return to the caller, but fall into a special
trap routine, $$FERR, which may be written by the caller.
The standard $$FERR routine merely tidies up and returns to
monitor mode.
Other errors always return to the caller.
 There are special routines to print error messages for syntax and IO
errors, which may be called on an error return from the command
scanners and IO routines.
These routines print standard messages and give the caller the
decision as to whether the error is fatal or not.
 Any character may be used as a severity indicator, e.g. $ for
messages to the operator from batch programs, but three characters
have special entry points to the error routines. ? is a fatal error,
% is a warning error, and a message enclosed in [] is an advisory
 All the error routines can be called by
the error macros, FATAL$, WARN$ and ADVIS$ which take
arguments which allow the user to define the form of the message
in the macro call.
Each macro call uses only one word of inline code so that the calls may be
used in the error return location from subroutines and UUOs.
 The error reporters are driven by several tables of messages
and output routines, any of which may be replaced by the caller.
.hl 1 Message Format
 The messages have a maximum of 8 fields, although only two, the
severity indicator and the message text are mandatory.
An example of a full message is:
.b;.i +10;?(400140)DELFNF LOOKUP(0), No file: ACCT.SYS[1,2]
.i +10;_^####_^####_^##_^#####_^###_^######_^###########_^
.i +10;s#aaaaaa#pppeee#uuuuuu#c###mmmmmmm##vvvvvvvvvvvvv
.skip 1
.lm +10;.i -5;s####is the severity flag (e.g. '?' '%' '[')
.b;.i -5;a####is the caller's address in octal.
It is only printed if FT$DBG is -1, that is, if the user is debugging his program.
.b;.i -5;p####is the 3 character program identifier.
The program identifier is set by the caller program in the left half
of $IDECD(I).
If these identifier is not set, this field is not printed.
.b;.i -5;e####is the 3 character error identifier.
The error identifier is unique for each message, and
must be supplied as a parameter to the $FATAL and $WARN routines.
All IO and syntax errors provided by IOLIB have an error identifier.
The identifiers and their meanings are detailed in full in Appendix F.
.b;.i -5;u####is a 6 character UUO or type indicator.
This indicator must be supplied as a parameter when calling
IOLIB IO routines put the UUO name of the UUO that found the error into
this field, and syntax errors put the word 'SYNTAX'.
.b;.i -5;c####is an octal code that is traditionally printed for IO errors.
It is printed if a flag is set on the $FATAL or $WARN call.
.b;.i -5;m####is the message text.
.b;.i -5;v####is a value which may be written in one of a variety of formats.
The format is given by a format code in the
routine call, and the value is supplied by the caller.
.lm -10; All the characters in the example not masked in the line below are
added by the IOLIB routine.
Some examples of the messages that can be generated are:
.b;.nf;.lm +15;.sp 2;%DELILC SYNTAX, Illegal character: <BEL>
?REACAS Cannot access system files: ACCT.SYS
[DOR Out of range: 677777]
%Name does not match: FORMET
?I don't like you, go away
.sp 1;.lm -15;.f; Normally the whole of an error message is output, but this can be
controlled through the 'message verbosity'.
The user can set the verbosity so that some combination of the
'prefix', the 'first line' and the 'continuation lines' are
typed, by command to the monitor. If the message level is set
to (PREFIX,NOFIRST) then only the s, a, p and e fields of the
message are typed. If the message level is (NOPREFIX,FIRST), the
u, c, m and v fields are typed. The default is (PREFIX,FIRST).
See Appendix F for explanations of all IOLIB error ids.
.b;.i +15;?(400140)DELFNF
.hl 1 Error Severity
 IOLIB treats fatal errors differently from warnings, advisory
messages and all others.
Fatal errors are those that cause immediate termination of execution
of the program, or a restart from some point in
the program.
Warning errors are normally local to some phase of execution of a
program, and do not necessarily cause termination of the whole program.
The program may proceed normally after issuing a warning, or it may
jump to some other phase of execution.
For example, if a delete program couldn't find one file to delete, it
would only need a warning and it could proceed to delete other
files in the same command, but if all the files were missing it might
prompt a fatal message.
 The $FATAL routine flags fatal errors with a '?', and $WARN flags warning errors with a '%'.
Calls to the $WARN routine write the error message and then
return to the calling routine, but calls to $FATAL trap to a special
routine labelled $$FERR.
The standard IOLIB version of $$FERR merely cleans up and
returns the program to monitor mode, but users may write their own
$$FERR routines to e.g. restart their program at some point.
 Advisory messages are enclosed in square brackets, [], but
are treated in the same way as warnings by the error routines.
Other severity indicators may be used by the appropriate call
to $ERROR and these calls return in the same way.
.hl 1 $ERROR - the Error Reporter
 The routine, $ERROR, is used to handle all error
messages whether fatal or warning.
The inputs to $ERROR are:
.b;.ts 10 20 30;	^&Ac	Bits	Description\&
.b;.lm +25;.i -20;T1	0-4	flags, see full description below
.i -10;5-11	severity flag character in ASCII. FATAL$, WARN$ and
ADVIS$ set up this field. Other severity characters must be set by
the caller before entering $ERROR.
.i -10;12-17	value type code, which is used as the index to a
table of addresses of write routines.
.i -10;18-35	pointer to either ASCIZ message text, or a word containing:
.br;lh:#error code in SIXBIT
.br;rh:#pointer to ASCIZ message text
.br;depending on EC$IND.
.b;.i -20;T2	#	value to be printed in a format specified by the error
code type
.b;.i -20;T3	#	UUO name in SIXBIT, to be printed if flag, EC$UUO, is set
.b;.i -20;P	#	top of stack contains return address that
will be printed if FT$DBG=-1.
.lm -25; The flag field in ac(T1) contains 1 bit flags indicating which fields
of the message are to be printed.
They are:
.lm +25;.b;.i -20;^&Bit	Symbol	Description\&
.b;.i -20;0	EC$IND	right half of ac(T1) points to a word containing
the error id in the left half.
text in the right half.
If not set, then the right half of ac(T1) points to the ASCIZ
message text.
.b;.i -20;1	EC$UUO	the u field is to be written, so that the contents of
ac(T3) are to be interpreted as a SIXBIT name.
.b;.i -20;2-4	#	unused, but reserved
.b;.i -20;5-11	EC$FLG	severity flag character in ASCII
.b;.i -20;12-17	EC$TYP	an index+1 to $TBWAD, the table of address of write routines for printing the value.
The indices to the standard IOLIB $TBWAD are given symbolic values
(see below).
.lm -25;.ts 13 21 37; $ERROR writes the error message to a file described by an FDB
pointed at by $IDEFD(I).
The BEGIN$ macro sets this to the job's terminal, but the programmer
may modify it to be a log file or even to be some flag for
the write routine, $$WCHR, to recognise and send the message to
several files.
 The message verbosity and the program id are taken from $IDECD(I).
The program id is 3 SIXBIT characters in the left half, and
is ignored if blank.
 If the message is fatal, the $ERROR routine prints the message
and then traps to $$FERR. 
Otherwise the routine returns to the caller.
.hl 1 $FATAL, $WARN and $ADVIS
 These routines set the appropriate severity character into EC$FLG
and call $ERROR to do all the hard work.
They may be conveniently called through the FATAL$,
WARN$ and ADVIS$ macros, which use only one instruction of inline
code and set up all the routine parameters from the macro
.hl 1 The FATAL$, WARN$ and ADVIS$ Macros
 These macros normally call the $FATAL, $WARN and $ADVIS routines,
but they may call other routines, depending on the arguments.
The format of the macro call is
.b;.i +5;FATAL$###<message-text>,value-format-code,error-id,UUO-name
 If the first two arguments are absent, the macro generates a call to $FTLIO,
or $WRNIO, which print IO error messages.
If the message-text argument is absent, the macro
generates a call to a routine $FTLxx or $WRNxx, where 'xx'
is the first 2 characters of the value-format-code.
This means that the programmer can write his own routines, and call
them using FATAL$ and WARN$.
The syntax error writing routines, $FTLSY and $WRNSY, may also be
called in this way.
If both the first two arguments are present, then the macro generates
a call to a literal, which sets arguments into acs T1-T3 and calls $FATAL or $WARN.
ADVIS$ always calls $ADVIS. The value-format-codes available in the standard IOLIB table of
value formats are:
.b;.nf;.ts 20 30;	CHAR	ASCII character, right-justified
	DECL	decimal number
	FILE	filename,given by pointer to FDB
	OCTL	octal number
	TEXT	ASCIZ string
.ts 13 21 37;.f;.b;Examples:
	LUKUP$	#	;lookup a file
	##FATAL$	;error - fatal, call $FTLIO.
	RFILE$	#	;read a filename from command string
	##FATAL$  ,SY	;error - call $FTLSY to report
	MOVE	T2,NUMLIN	;pick up number of lines
	WARN$	<End of data at line>,DECL,EOD
	##FATAL$ <Not implemented>,,NIM,DAEMON
.f;.hl 1 IO Error Reporting
 The basic IO modules in IOLIB produce error codes in a standard
form when they detect errors.
An error return is given with ac(T1) containing an error code
in the right half, and a UUO code in the left half.
An endfile return from $INPUT, $READ, $$RBYT or $$RCH0 also have an error code
in ac(T1) so that the caller may treat endfile as an error
if he wishes.
The UUO codes are given in Appendix E.
The error code range is an extension of the range for DEC
DEC error codes, ERxxx%, range from 0 to 27.
The IOLIB codes, ERxxx$, range from -1 to -11, and
include the error bits in the IO status word, endfile,
restricted device, unknown error and others.
In addition, the IOLIB $OPEN, $INPUT and $OUTPU routines can
generate some of the ERxxx% codes, when the message is
The ERxxx$ codes are discussed in Appendix E.
 The routines, $FTLIO and $WRNIO, are called with the error code
in ac(T1) and the pointer to the offending FDB in ac(D).
They write the entire error message.
If the error file was the one with the error, then the routines
use the job's terminal instead of the error file.
 The $FTLIO and $WRNIO routines may be called through the
FATAL$ and WARN$ macros.
The call uses only one word of inline code.
.hl 1 Syntax Error Reporting
 Some of the IOLIB formatted read routines detect syntax errors
while they are scanning the input string.
These routines have an error return, and return an error code
in ac(T1) and the error value in ac(T2).
The routines $FTLSY and $WRNSY process these values and
write error messages from them.
 The $FTLSY and $WRNSY routines may be called through the $FATAL
and WARN$ macros.
The call uses only one word of inline code.
.hl 1 $$FERR - Fatal Error Trap Routine
 The error reporter, $ERROR, transfers control to a routine
called $$FERR after writing any fatal error message.
$$FERR may be a user written routine or it may be the standard
routine from IOLIB.
The standard $$FERR merely tidies up and returns to monitor
mode; the exact code is reproduced below.
A user written $$FERR might do more tidying up before returning
to monitor mode, or might be the same location as the program
start address so that the program starts again, or might
execute some of the same code as the user's
control-C intercept routine.
In any case, the user must have an INTERNal symbol called
$$FERR if he writes his own code.
.b;The code of IOLIB's $$FERR reads:
	CLRBFI		;clear job's terminal input
	MONRT$	#	;return to monitor mode
	HRRZ	T1,.JBSA	;load program start address
	JUMPN	T1,(T1)	;restart program if possible
	EXIT	#	;curses! Thwarted
.number chapter 10
.ap;.ps 59 75;.ts 13 21 37;.ch Utility Routines
.lm 5
.hl 1 General Description
 'Utility Routines' is a convenient heading for all those routines
that do not fall into any other category, and do not form a
sufficiently numerous or important class to merit a chapter
on their own.
.hl 1 $MATCH - Match a SIXBIT Name with a Table
 $MATCH accepts a SIXBIT name as input and the IOWD address
of a table of SIXBIT names.
The routine searches through the table linearly.
If the first character of the table name is '*', and the
second charater matches the
argument name, then the match is found.
Otherwise the whole name may match, or the whole argument
name may match the first n characters of the table name
or there is no match.
If the whole name matches, the search terminates.
If there is no match, the search continues.
If there is a partial match, the index is remembered
and the search continues.
If there is no match, the routine gives an error return with
If there are several partial matches,
error return with ac(T1)=0.
Otherwise normal return, with the index in ac(T1), and
ac(T1)<0 for partial match, and =0 for exact match.
.number chapter 11
.ap;.ps 59 75;.ts 13 21 37;.ch Examples
.lm 5
.hl 1 Formatted IO
.b;To read two numbers and add them together:
	BEGIN$	#	;initialise
	WTEXT$	<First number: >
	RDECL$	#	;read number
	JUMPG	T1,ERRCHR	;error if not endline
	MOVE	G1,T2	;save number
	WTEXT$	< and the second: >
	RDECL$	#	;read number
	JUMPG	T1,ERRCHR	;again, error unless endline
	ADD	G1,T2	;add two numbers
	WLINE$	<Now ADDTWO performs its amazing feat....>
	WTEXT$	<....and the answer is: >
	MOVE	T1,G1	;load number
	WCRLF$	#	;endline
	MONRT$	#	;exit
	JRST	ADDTWO	;start again
ERRCHR:	;here to report errors and start again
	MOVE	T2,T1	;set up value for error message
	WARN$	<Illegal character>,CHAR,ILC
	WLINE$	< we have to start everything again.>
.f;.hl 1 Copy a File to the LPT:
	BEGIN$	#	;as always
COP10:	;loop here to copy each character
	MOVEI	D,INPFDB	;set input FDB
	RBYTE$	#	;read next character
	##JRST	ENDFIL	;end of file
	WBYTE$	#	;write character
	JRST	COP10	;loop back
ENDFIL:	;here at endfile
	RLEAS$	#	;release input file
	WCHAR$	.CHFFD	;send formfeed
	RLEAS$	#	;release LPT
	TRMFD$	#	;tell user good news
	WLINE$	<All done>
	MONRT$	#	;back to monitor
	JRST	COPLPT	;start again
.f;.hl 1 Subroutine to Read a Filename
.b;This subroutine takes an FDB point as input and reads a filename
into that FDB.
If the filename was null, the routine asks for another name.
If the name was wild, the routine prints an error message and
asks again.
If the delimiter was not endline it does the same.
	PUSH	P,T1	;save FDB point
RFN10:	;here to reread a filename after error
	MSGFD$		;load message FDB point
	WTEXT$	<File: >
	CMDFD$	#	;load command FDB point
	SETZ	T1,	;no switch table
	MOVE	T2,(P)	;recover FDB point
	RFILE$	T1	;read filename
	##JRST	SYNERR	;syntax error
	JUMPG	T1,ILCHAR	;endline is ok
	TXNE	T2,FF$NUL	;null specification?
	JRST	RFN10	;yes, reask question
	TXNN	T2,FF$WLD	;any wildcards?
	PJRST	$XOPJ_#_#	;return popping stack
	;wild character in file spec.
	WARN$	<Wild characters illegal>,FILE,WCI,SYNTAX
	JRST	RFN10	;try again
ILCHAR:	;illegal character
	MOVE	T2,T1	;setup character as value
	WARN$	<Illegal character>,CHAR,ILC,SYNTAX
	JRST	RFN10	;try again
SYNERR:	;syntax error
	JRST	RFN10	;try again