Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-06 - 43,50362/iolib5.man
Click 43,50362/iolib5.man to see without markup as text/plain
There are no other files named iolib5.man in the archive.












                          IOLIB Reference Manual
                          ----- --------- ------





                                 Rob Cook
                    LaTrobe University Computer Centre
                                 10-Aug-74

















                                      NOTE

         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 University.

         Actual distribution of the software described in this document
         will be subject to terms and conditions that will be announced
         by the author.
IOLIB Reference Manual















                                    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.
IOLIB Reference Manual
Table of Contents


                             Table of Contents

     Chapter 1 - IOLIB Explained                                       

     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


     Chapter 2 - Concepts                                              

     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


     Chapter 3 - Programming Techniques                                

     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


     Chapter 4 - IOLIB Tables                                          

     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


     Chapter 5 - Memory Management                                     

     5.1   General Description                                        5-1
     5.2   Dynamic Memory Management                                  5-2
IOLIB Reference Manual
Table of Contents


     5.3   Static Memory Management                                   5-2


     Chapter 6 - Basic IO Routines                                     

     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


     Chapter 7 - Formatted Reading and Writing                         

     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


     Chapter 8 - Tempcore Routines                                     

     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
IOLIB Reference Manual
Table of Contents


     Chapter 9 - Error Reporting                                       

     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


     Chapter 10 - Utility Routines                                     

     10.1  General Description                                        10-1
     10.2  $MATCH - Match a Name in a Table of Names                  10-1


     Chapter 11 - Examples                                             

     11.1  Formatted IO                                               11-1
     11.2  Copy a File to LPT                                         11-2
     11.3  Subroutine to Read a Filename                              11-2


     Appendix A - List of all IOLIB Routines                           

     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


     Appendix B - List of all IOLIB macros                             

     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


     Appendix C - Contents of the FDB                                  

     C.1   Details of Words in the FDB                                C-1
     C.2   Bit Definitions for $FDCHN                                 C-4
IOLIB Reference Manual
Table of Contents


     C.3   Bit Definitions for $FDMOD and $FDMOM                      C-4


     Appendix D - Contents of the IDB                                  


     Appendix E - IO Error Codes                                       

     E.1   UUO IO Error Codes                                         E-1
     E.2   IO Error Codes                                             E-2


     Appendix F - IOLIB Standard Error IDs                             











                                CHAPTER 1

                              IOLIB EXPLAINED



     1.1  WHAT IS IOLIB?

          IOLIB  is  a  MACRO-10  assembly  language   programming   system
     comprising  subroutines  and  definitions  of macros and symbols.  The
     subroutines are a collection of routines commonly  used  and  commonly
     written  by  assembly language programmers.  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.
IOLIB EXPLAINED                                                    Page 1-2
SOME FEATURES OF IOLIB


     1.2  SOME FEATURES OF IOLIB


     *  basic IO module for executing IO UUOs on any file.

     *  files described by standard data block.  A large number of defaults
        are supplied.

     *  buffer sizes are variable because IOLIB creates buffer rings itself

     *  any IO call for a file ensures  that  all  prerequisites  for  that
        function are fulfilled first.

     *  routines for writing data in a wide variety of  formats;   decimal,
        date/time, filename, cash ...  IOLIB has them all

     *  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.

     *  dynamic memory management using the ALGOL heap algorithm

     *  comprehensive routines for reporting errors  in  the  DEC  standard
        format.  Verbosity level can be set by program or user.

     *  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.

     *  a macro to call each IOLIB routine, making code  shorter  and  more
        readable.

     *  a macro to write program initialisation code

     *  macros to define file data blocks

     *  all the SAVEn and POPJ/POPJ1 utility routines

     *  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.

     *  DEC compatibility

     *  will run on 5.06 and later monitors only.



     1.3  WHO CAN USEFULLY USE IOLIB?

     IOLIB is aimed at 3 main classes of programmer:

     1.  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
IOLIB EXPLAINED                                                    Page 1-3
WHO CAN USEFULLY USE IOLIB?


         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
         C.MAC.  Together, IOLIB and C form  a  programming  standard  that
         could  usefully  be  adopted  by  installations  to  make programs
         readable and maintainable.

     2.  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.

     3.  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$  macro.   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.




     1.4  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
IOLIB EXPLAINED                                                    Page 1-4
HOW TO USE THIS MANUAL


     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 full.

          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.



     1.5  SOFTWARE SUPPORT

          The IOLIB system is  maintained  at  Latrobe  University  by  the
     author.   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.



     1.6  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.











                                CHAPTER 2

                                 CONCEPTS



     2.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  of
     IOLIB.REL.   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 definition.

          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:

     1.  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.

     2.  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.

     3.  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.

     4.  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.
CONCEPTS                                                           Page 2-2
COMPONENTS OF IOLIB


     5.  routines to handle tempcore files (input, output and delete).

     6.  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.

     7.  the IOLIB data base


          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.

     1.  useful symbol definitions for all accumulators

     2.  a macro to call each IOLIB routine

     3.  a macro to initialise a program that includes setting up  a  stack
         and  the  IOLIB  data  base, handling CCL calls and concealed mode
         entry.

     4.  symbolic definition of all  independant  words  and  bits  in  the
         various data blocks

     5.  macros to build file data blocks

     6.  macros to create calls to the error messages writers

     7.  macros to control version numbering

     8.  macros to aid assembly by  setting  assembly  into  high  and  low
         segments etc




     2.2  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
     $LOSFD).  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
CONCEPTS                                                           Page 2-3
FILES AND FDBS


     assembly time, and fills it.  The defaults are:

                         device         DSK
                         name           null
                         extension      null
                         PPN            null
                         IO mode        .IOASC
                         buffers        2; standard size for device
                         sequential IO starting at block 1

          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  .RBCNT
     to .RBVER.  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.

             $LNFDB==$FDRIB+.RBALC+1 ;all FDBs continue until .RBALC

          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 FDB'.  So, to execute a
     LOOKUP on a file described by an FDB at location INPFDB:

             ...
             MOVEI   D,INPFDB        ;load current FDB
             LUKUP$                  ;execute LOOKUP (including OPEN)
               JRST  ERROR           ;
             ...

          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 pointer.  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.

     To write a message to the job's terminal:

             ...
             SETZ    D,              ;set TTCALL IO
             WTEXT$  <End of execution>
             ...

     To read a character from an incore buffer called TMPBUF:
CONCEPTS                                                           Page 2-4
FILES AND FDBS


             ...
             MOVE    D,[POINT 7,TMPBUF]  ;set up pointer
             RCHAR$                  ;read a character into ac(T1)
             ...

          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.



     2.3  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
     programmer.  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.



     2.4  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.

             OPEN$                   ;calls $OPEN to execute an OPEN UUO

             WDECL$  10              ;calls $WDECL to write decimal 10

          Using the macros makes the program more readable (expansions  are
     SALLed by default) and helps to cut down programming errors.
CONCEPTS                                                           Page 2-5
ROUTINES AND MACROS


          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.



     2.5  ERROR MESSAGES

          IOLIB  includes  routines  for  writing  error  messages  in  DEC
     standard format.  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.

             ...
             LUKUP$                  ;LOOKUP a file
               FATAL$                ;errors are fatal
             ...

     might produce:

             ?RENAEF RENAME(4), Already exists: IOLIB.BAK

          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.

             ...
             RFILE$                  ;read a filename
               FATAL$ ,SY            ;write a syntax error message
             ...

     might produce:

             ?DELILC Illegal character: <BEL>



     2.6  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
CONCEPTS                                                           Page 2-6
REPLACEABLE ROUTINES


     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:

             $$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)



     2.7  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  character.   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'.



     2.8  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.
CONCEPTS                                                           Page 2-7
USER PROGRAM STRUCTURE


          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.











                                 CHAPTER 3

                          PROGRAMMING TECHNIQUES



     3.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 macros.  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.



     3.2  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.:

                               .COMPIL/CREF MYPROG

          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.

                               .EXECUT MYPROG,@MAC:IOHI

                               .DEBUG MYPROG,@MAC:IOLO
PROGRAMMING TECHNIQUES                                             Page 3-2
PROGRAM STRUCTURE


     3.3  PROGRAM STRUCTURE

          A suggested layout for the  user  program  is  as  follows.   The
     reasons for the various parts are explained in the comments:

             TITLE   MYPROG - EXAMPLE OF PROGRAM LAYOUT
             SUBTTL  ROB COOK        
      
             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
      
     COMMENT ;
             ...
             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
             ...
             END     MYPROG

          The ordering of most items is not important and  most  items  are
     optional, but are included in the majority of programs.

          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.

             ...
             WTEXT$  <All done>      ;end of program
             MONRT$                  ;back to monitor
             JRST    START           ;restart on 'CONTINUE'
             END     START           ;
PROGRAMMING TECHNIQUES                                             Page 3-3
SYMBOL NAMING CONVENTIONS


     3.4  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:

     Template      Use
     --------      ---

             $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'

          All symbols for entry points to IOLIB routines are  of  the  form
     '$xxxxx'.   The  routines  advertised  as replaceable, as well as some
     concealed routines and debug points, have entry  points  of  the  form
     '$$xxxx'.   The  first characters of the entry point name indicate the
     broad type of the routine:

             $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

          Secondary entry points are  normally  identical  to  the  primary
     entry point except that the last character is replaced by a digit:

             $RFILE  read a file specification
             $RFIL0  as above, but with different arguments

          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.



     3.5  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
PROGRAMMING TECHNIQUES                                             Page 3-4
ACCUMULATOR CONVENTIONS


     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 routine.  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.

          IOLIB defines symbols  for  the  various  acs  as  given  in  the
     following table:

                  Ac     Name        Use
                  --     ----        ---

                  0       T0      temporary (never by IOLIB)
                  1       T1          "     (used by IOLIB)
                  2       T2          "            "
                  3       T3          "            "
                  4       T4          "            "


                  5       P1      preserved
                  6       P2          "
                  7       P3          "
                  10      P4          "

                  11      G1      global
                  12      G2         "
                  13      G3         "
                  14      G4         "
                  15      G5         "  (reserved to IOLIB)
                  16      G6         "  (reserved to IOLIB)
                  17      G7         "  (reserved to IOLIB)

                  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
PROGRAMMING TECHNIQUES                                             Page 3-5
ACCUMULATOR CONVENTIONS


          IOLIB contains routines ($SAVEn) to save from 1  to  4  preserved
     acs  and  to ensure that they are restored correctly on return.  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.

     SUBROU:
             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

          There are routines, $SAVET and $RESTT, that save and restore  the
     4  temporary accumulators, T1-T4.  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.



     3.6  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 also.  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'.

             PUSHJ   P,SUBROU        ;call subroutine
               error return          ;abnormal
PROGRAMMING TECHNIQUES                                             Page 3-6
SUBROUTINE CALLS


             o.k. return             ;normal

     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.

             PJUMPE  T1,$POPJ##      ;return if zero

             PJRST   $POPJ1##        ;skip return now

          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 return.

          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.



     3.7  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.

             FT$DBG==-1              ;debug feature required

          The assembly  switches  defined  in  IO.MAC  and  their  standard
     settings and effects are:

     Switch    Value   Effect
     ------    -----   ------

     Switches which the programmer may set:

     FT$ALC    -1      nonzero for dynamic memory management; zero for
                       static memory management
     FT$CCL    0       nonzero for CCL entry points to be included in
                       the BEGIN$ macro; zero for no CCL entry points
     FT$DBG    0       nonzero for debug features (such as caller address
                       printed in error messages); zero for no debug
                       features

     Switches which the installation may change:
PROGRAMMING TECHNIQUES                                             Page 3-7
ASSEMBLY SWITCHES


     FT$SFD    6       level of SFDs supported by IOLIB.
                       Note that the level of SFDs supported by the monitor
                       will take
                       precedence.



     3.8  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 stack.  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:

     $PTSTK::
             IOWD    STLEN,$STACK    ;stack pointer
     $STACK::
             BLOCK   STLEN           ;stack block



     3.9  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.

     1.  unless  FT$DBG  is  on,  SALL,  to  suppress  listings  of   macro
         expansions.   If  debugging, load the patch area and special debug
         code, otherwise load nondebug code.

     2.  if FT$ALC is zero, set the replaceable entry  points,  $$ALLC  and
         $$DALC, to the memory manager to use static management.

     3.  

              produce PORTAL instructions for normal and CCL  entry  points
         to implement concealed mode.

     4.  set T1=0 for normal entry and T1=-1 for CCL entry.

     5.  RESET UUO

     6.  load ac(P) from $PTSTK to set up the push down stack pointer.

     7.  call $INIID to initialise the  IDB  by  clearing  it  and  setting
         default values.
PROGRAMMING TECHNIQUES                                             Page 3-8
BEGIN$ - PROGRAM INITIALISATION


     8.  set the program name, extension, device and PPN  provided  in  the
         acs by the monitor into the IDB.

     9.  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.

    10.  set the current file, ac(D), from the command file  point  in  the
         IDB.




     3.10  GLOBAL PARAMETERS

          The IDB contains program parameters  which  may  be  set  by  the
     programmer  or  by a user through standard switches.  These parameters
     are:

     1.  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.

                    MOVEI   T0,^D16*^D1024
                    MOVEM   T0,$IDTOP(I)

     2.  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.

                       MOVSI   T0,'IOL'
                       HLLM    T0,$IDECD(I)

     3.  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.

     4.  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.

     5.  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.

     6.  the default FDB for filename decoding.  A point to a  default  FDB
         may be set into the right half of $IDDFD(I).
PROGRAMMING TECHNIQUES                                             Page 3-9
GLOBAL PARAMETERS


     7.  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$.

     8.  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.

     9.  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 file).

    10.  the next character to be  read  by  the  command  character  input
         routine,  $RCCHR.   An  ASCII character or endline code may be set
         into $IDNXC(I).  The character should be right-justified.

    11.  the default path for the job should be changed by setting the path
         into $IDJPT and then using the PATH.  UUO.




     3.11  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
     program.

             TITLE   2SEGEX - two segment example
      
             HISEG$                  ;set high segment
      
     SEGEX:
             BEGIN$
             ...
             high segment code
             ...
             LOSEG$                  ;change to low segment
             ...
             low segment code
             ...
             HISEG$                  ;back to high segment
             END     SEGEX
PROGRAMMING TECHNIQUES                                            Page 3-10
FDESC$ - BUILD AN FDB AND SET VALUES


     3.12  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

                  FDESC$   dev,nam,ext,<path>,mode,length

     where:

      dev      is the name of a device
      nam      is the file name
      ext      is the file extension
      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.
      mode     is the IO mode.  In fact a complete IO status  halfword  may
               be given.
      length   is the length of the FDB to be created.  The  default  is  a
               standard length FDB.

     For example:

             FDESC$  DSK,ACCT,SYS,<,,ACCOUN>,.IOBIN

     makes an FDB for the file  'DSK:ACCT.SYS[,,ACCOUN]'  and  sets  binary
     mode.



     3.13  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:

              MAKFD$   dev,nam,ext,<path>,mode,length,address

     where:

      dev      is the name of a device
      nam      is the file name
      ext      is the file extension
      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.
      mode     is the IO mode.  In fact a complete IO status  halfword  may
               be given.
      length   is the length of the FDB to be created.  The  default  is  a
               standard length FDB.
      address  is the address of an existing FDB.  If no address  is  given
PROGRAMMING TECHNIQUES                                            Page 3-11
MAKFD$ - PRODUCE CODE TO BUILD AN FDB


               the  macro  creates  a  new  FDB  in space obtained from the
               memory manager.

             MAKFD$   DSK,INPFIL,DAT,<104,427>,,,INPFDB

     creates the code to call $CLRFD for the FDB, and then set the  details
     for 'DSK:INPFIL.DAT[104,427]' into the FDB.



     3.14  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.

               VERSN$   major-version,edit-number,who-edited

     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.

                         PATCH$   <patch numbers>

     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.

                                  JBVER$

     The JBVER$ macro takes no arguments, and sets the version number  into
     .JBVER.

                                  VTEXT$


     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.

     e.g.
             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'
PROGRAMMING TECHNIQUES                                            Page 3-12
DEBUGGING AIDS


     3.15  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.











                                CHAPTER 4

                               IOLIB TABLES



     4.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 string.  He
     can define his own switches in a switch table using macros defined  in
     IO.MAC.



     4.2  $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 others.  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:

          Index     Symbol    Write Routine
          -----     ------    ----- -------

          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
IOLIB TABLES                                                       Page 4-2
SWITCH TABLES


     4.3  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 argument.
     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:

                   Value/
     Name         Keywords           Default Deposit
     ----         --------           ------- -------

     BLOCKSIZE    decimal            4000    buffer size in FDB
     DENSITY      INSTAL/200/556/800 INSTAL  FM$DEN in $FDMOD/MOM
     HELP         TEXT/SWITCHES      TEXT    call $WHELP to write text
     MAXCOR       kword              28K     $IDTOP(I)
     PARITY       ODD/EVEN           ODD     FM$PAR in $FDMOD/MOM
     PHYSICAL                                FM$PHY in $FDMOD/MOM
     PROTECTION   octal              157     FM$PRO in $FDMOD/MOM
     RUN          filename                   rh($IDRUN(I))
     RUNOFFSET    octal              1       lh($IDRUN(I))
     VERBOSITY    LOW/STANDARD/HIGH  STD     rh($IDECD(I))



     4.4  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 switch.  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.
IOLIB TABLES                                                       Page 4-3
SWITCH TABLE BUILDING MACROS


          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.

     e.g.
             ;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
      
     DEFINE SWIT$$,<
             SL$     <*HELP>,<-1,,SWHELP>,HELP,HELPTEXT
             SP$     <MAXCOR>,<$IDTOP(I)>,$SWKWD,MXC
             SS$     <PHYSICAL>,<POINT 1,$FDMOD(T1),3>,1
     >
      
     HMPTAB:                         ;address of table
             SWTAB$  HMP             ;define tables
      
             KEYWD$  HELP,<SWITCHES,TEXT> ;define HELP keywords

     SWTAB$
     ------

          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).
IOLIB TABLES                                                       Page 4-4
SWITCH TABLE BUILDING MACROS


          SWTAB$     UTB             ;define switch tables

     The name table is called UTB$$N, the pointer table UTB$$P, the maximum
     table UTB$$M, and the default table UTB$$D.

     SWIT$$
     ------

          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$
     ---

          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

                       SS$  name,deposit-point,value

     SP$
     ---

          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.

              SP$  name,deposit-point,value-code,abbreviation

     SL$
     ---

          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.

            SL$  name,deposit-point,keyword-table,default-index

     DM$
     ---
IOLIB TABLES                                                       Page 4-5
SWITCH TABLE BUILDING MACROS


          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 given.  The symbols  defined  are,  MX$xxx,
     PD$xxx and AD$xxx respectively.  Call:

               DM$   abbreviation,MX-value,AD-value,PD-value

     KEYWD$
     ------

          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.  Call:

                         KEYWD$   name,<keywords>

     e.g.    KEYWD$  DEN,<200,556,800,INSTALLATION>

     The symbols for the indices of each keyword are DENS20, DENS55, DENS80
     and DENSIN.











                                CHAPTER 5

                             MEMORY MANAGEMENT



     5.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.
     LINK-10).   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
MEMORY MANAGEMENT                                                  Page 5-2
GENERAL DESCRIPTION


     the first unused location (pointed at by

          .JBFF in  the  job  data  area).   Chunks  of  memory  cannot  be
     deallocated   using  static  management.   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
     switch.   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.



     5.2  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 list.  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 word.
MEMORY MANAGEMENT                                                  Page 5-3
STATIC MEMORY ALLOCATION


     5.3  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 ac(T1).

          The static deallocator gives an immediate return.  The  space  is
     not made available for reallocation.











                                CHAPTER 6

                             BASIC IO ROUTINES



     6.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 program.  $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.
BASIC IO ROUTINES                                                  Page 6-2
GENERAL DESCRIPTION


          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 arguments.  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 below.



     6.2  $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:

     1.  check the tempcore input flag (FC$TCI in $FDCHN(D)).  If on,  give
         an immediate endfile return.

     2.  call $LUKUP to execute OPEN and LOOKUP UUOs if  not  already  done
         for this file.

     3.  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).

     4.  load the next block number from $FDNBK(D) and call $USETI to  find
         the required physical record.

     5.  set [this block number,,next block number] into $FDNBK(D).

     6.  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.

     7.  if ok, return double-skip now.  Otherwise, call $GETST to read the
         IO  channel  status,  then  call $SETST to clear error and endfile
         bits.

     8.  calculate the error code from the error and endfile bits in the IO
         channel status.

     9.  skip return if endfile.  Otherwise normal return.


     FDB words altered:
     --- ----- --------
BASIC IO ROUTINES                                                  Page 6-3
$INPUT - READ A PHYSICAL RECORD FROM A FILE


     $FDNBK set  to  [this-record-number,,next-record-number].   The   next
            record is just this record+1 for sequential reads.
     $FDSTS on error and endfile, right half set to IO channel status word.

     FDB words used:
     --- ----- -----
     $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.

     $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.

     $FDIOW addressed by the INPUT UUO instruction.  The user must  set  up
            this word for dump mode IO.



     6.3  $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:

     1.  call $ENTER to execute OPEN and ENTER UUOs if not already done for
         this file.

     2.  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).

     3.  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.

     4.  load the next block number from $FDNBK(D) and call $USETO to  find
         the required physical record.

     5.  set this block number,,next block number into $FDNBK(D).

     6.  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.

     7.  if ok, return skip now.  Otherwise, call $GETST  to  read  the  IO
         channel status, then call $SETST to clear error bits.

     8.  calculate the error code from the error bits  in  the  IO  channel
         status.
BASIC IO ROUTINES                                                  Page 6-4
$OUTPU - WRITE A PHYSICAL RECORD TO A FILE


     9.  non-skip return to show error.


     FDB words altered:
     --- ----- --------
     $FDNBK set  to  [this-record-number,,next-record-number].   The   next
            record is just this record+1 for sequential writes.

     $FDSTS on error, right half set to IO channel status word.

     FDB words used:
     --- ----- -----
     $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.

     $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.

     $FDIOW addressed by the OUTPUT UUO instruction.  The user must set  up
            this word for dump mode IO.



     6.4  $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:

     1.  call $OPEN to execute an OPEN UUO if necessary.

     2.  check whether $LUKUP has already been called for this file (FC$LUK
         in $FDCHN on).  If so, give an immediate skip return.

     3.  execute a LOOKUP UUO.  If  error,  set  error  code  and  non-skip
         return.

     4.  otherwise, set FC$LUK in $FDCHN(D) and skip return.


     FDB words altered:
     --- ----- --------
     $FDCHN FC$LUK is set on a skip return so that $LUKUP  will  know  next
            time it is called.

     $FDRIB see Monitor Calls Handbook for words  affected  by  the  LOOKUP
            UUO.

     FDB words used:
     --- ----- -----
BASIC IO ROUTINES                                                  Page 6-5
$LUKUP - LOOKUP A FILE


     $FDRIB used by LOOKUP UUO



     6.5  $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:

     1.  ENTER entry:  zero $FDPRV(D) and rh($FDEXT(D)).

     2.  ENTE0 entry:  call $OPEN to execute an OPEN UUO if necessary.

     3.  check whether $ENTER has already been called for this file (FC$ENT
         in $FDCHN on).  If so, give an immediate skip return.

     4.  execute a ENTER UUO.   If  error,  set  error  code  and  non-skip
         return.

     5.  otherwise, set FC$ENT in $FDCHN(D) and skip return.


     FDB words altered:
     --- ----- --------
     $FDCHN FC$ENT is set on a skip return so that $ENTER  will  know  next
            time it is called.

     $FDPRV contents of protection field  in  $FDMOD  added  if  masked  by
            $FDMOM.

     $FDRIB see Monitor Calls Handbook for words affected by the ENTER UUO.

     FDB words used:
     --- ----- -----
     $FDMOD protection field used if masked by $FDMOM

     $FDMOM FM$PRO mask used.

     $FDRIB used by ENTER UUO
BASIC IO ROUTINES                                                  Page 6-6
$OPEN - OPEN AN IO CHANNEL


     6.6  $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:

     1.  check whether the channel is already open  ($FDOPN  in  $FDCHN(D))
         and skip return if so.

     2.  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.

     3.  check $FDDEV(D), and set 'DSK' if zero.

     4.  do a DEVTYP UUO.  If the result  is  zero  set  ERNSD%  and  error
         return.  Otherwise, set the result into $FDTYP(D).

     5.  check the DEVTYP word to see whether the device is available.   If
         not, set ERDNA% and error return.

     6.  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.

     7.  execute a DEVSIZ UUO.  if dump mode, goto  step  9.   If  improper
         mode set, set ERIMP$ and error return.

     8.  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 $FDBHD(D).

     9.  check if the device is a magtape.  If not, goto step 11

    10.  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).

    11.  check whether 'physical-only' set in $FDMOD(D) (FM$PHY  masked  in
         $FDMOM(D)) and if so, set it in $FDSTS(D).

    12.  execute the OPEN UUO.  The only unchecked error  is  no  available
         DDBs, so if error, set ERNET% and error return.

    13.  if the next block number is zero, set it to 1

    14.  set FC$OPN in $FDCHN(D) and skip return.


     FDB words altered:
     --- ----- --------
BASIC IO ROUTINES                                                  Page 6-7
$OPEN - OPEN AN IO CHANNEL


     $FDCHN channel number into FC$CHN and FC$OPN on.

     $FDTYP filled with result of DEVTYP UUO.

     $FDDEV if zero, filled with 'DSK'.

     $FDBUF if buffered mode, and either half zero,  that  half  is  filled
            with  the  system  default  returned by the monitor on a DEVSIZ
            UUO.

     $FDBHD if buffered mode, filled with points to $FDIBH and $FDOBH.

     $FDSTS may have physical-only and magtape parity and  density  set  if
            those fields are masked by $FDMOM.

     FDB words used:
     --- ----- -----
     $FDCHN if non-zero, channel number is used as  a  starting  point  for
            free channel search.

     $FDOPN see Monitor Calls Handbook for usage by OPEN and DEVSIZ UUOs.

     $FDMOD holds magtape density  and  parity  and  physical-only  bit  if
            corresponding masks in $FDMOM are ones.

     $FDMOM masks for fields in $FDMOD.



     6.7  $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:

     1.  CLOSE entry:  zero CLOSE bits

     2.  CLOS0 entry:  execute CLOSE UUO.

     3.  zero the block number in $FDNBK(D).

     4.  if CL.OUT was not set, clear FC$ENT in $FDCHN(D).

     5.  if CL.IN was not set, clear FC$LUK in $FDCHN(D), and return.


     FDB words altered:
     --- ----- --------
     $FDNBK zeroed

     $FDCHN bits FC$ENT and FC$LUK may be cleared.
BASIC IO ROUTINES                                                  Page 6-8
$RLEAS - RELEASE AN IO CHANNEL


     6.8  $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:

     1.  call $DLBUF to return output buffer ring  to  pool  of  free  core
         chunks

     2.  call $DLBUF to return input buffer ring

     3.  $RLEA0:  execute the RELEAS UUO.

     4.  clear $FDCHN(D) to zero the flags and channel number


     FDB words altered:
     --- ----- --------
     $FDCHN zeroed

     FDB words used:
     --- ----- -----
     $FDBHD to find the buffer headers and rings.



     6.9  $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).

     FDB words altered:
     --- ----- --------
     $FDPRV the protection field is changed if FM$PRO is on in $FDMOM.

     FDB words used:
     --- ----- -----
     $FDRIB used by RENAME UUO.

     $FDMOD used if FM$PRO is on in $FDMOM.

     $FDMOM for FM$PRO mask
BASIC IO ROUTINES                                                  Page 6-9
$DELET - DELETE A FILE


     6.10  $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.



     6.11  $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.

     FDB words altered:
     --- ----- --------
     $FDNBK returns with right half set to this record number, and the left
            half set to this record - 1.



     6.12  $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.

     FDB words altered:
     --- ----- --------
     $FDSTS right half receives IO status word.



     6.13  $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.



     6.14  $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.
BASIC IO ROUTINES                                                 Page 6-10
$XTCAL - EXECUTE AN IO ORIENTED CALLI UUO


     6.15  $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:

     1.  check whether physical only is implemented.   If  not,  clear  the
         indicator.  Goto step 4.

     2.  check whether FM$PHY is set on in $FDMOM(D).  If not, goto step 5.

     3.  read the physical-only setting from FM$PHY in $FDMOD(D)  into  the
         indicator.

     4.  set the indicator into $FDSTS(D).

     5.  check the physical only flag  in  $FDSTS(D).   If  on,  complement
         bit19  of  the  UUO,  to  show physical only.  Execute the UUO and
         return.


     FDB words altered:
     --- ----- --------
     $FDSTS bit0 is set if FM$PHY is on in $FDMOM.  Bit0 is set  to  FM$PHY
            in $FDMOD.

     FDB words used:
     --- ----- -----
     $FDMOD FM$PHY field checked and used.

     $FDMOM FM$PHY mask used



     6.16  $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.

     FDB words altered:
     --- ----- --------
     $FDDEV if empty on entry, it is set to 'DSK'.
BASIC IO ROUTINES                                                 Page 6-11
$MKBUF - BUILD A RING OF BUFFERS


     6.17  $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.

     FDB words used:
     --- ----- -----
     $FDBUF uses both number and size of buffers to create ring



     6.18  $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.



     6.19  $UPDAT - OPEN A FILE FOR UPDATING

          Open the file with a LOOKUP and ENTER on the same channel.



     6.20  $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 up.



     6.21  $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:

     1.  open the file for updating using $UPDAT

     2.  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.
BASIC IO ROUTINES                                                 Page 6-12
$APEND - OPEN A FILE FOR APPENDING


     3.  check the channel IO mode.  If a dump mode, goto step 6.

     4.  do a dummy output for buffered modes

     5.  set the byte pointer in the output buffer header to point  to  the
         first free word, and alter the remaining byte count accordingly.

     6.  set ac(T1) to the count of free words and skip return.


     FDB words used
     --- ----- ----
     $FDSIZ gives the size of the file in words

     $FDSTS gives the channel IO mode

     FDB words altered
     --- ----- -------
     $FDNBK set to the last block of the file

     $FDOBH byte pointer set to the first free word and byte count  set  to
            reflect free bytes remaining



     6.22  $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.



     6.23  $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.











                                CHAPTER 7

                       FORMATTED READING AND WRITING



     7.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.
FORMATTED READING AND WRITING                                      Page 7-2
$WRITE - WRITE ONE BYTE TO THE CURRENT FILE


     7.2  $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:

     1.  if the current file point is zero (TTCALL IO), write the character
         using OUTCHR and skip return immediately.

     2.  if the current file point is a byte pointer (bits  0-11  nonzero),
         write the byte using IDPB and skip return immediately.

     3.  otherwise, check the byte count in the  buffer  header  $FDOBH(D);
         unless the buffer is full, goto step 5.

     4.  call $OUTPU to empty the buffer.  This also ensures a dummy OUTPUT
         on the first call.  If error, nonskip return.

     5.  decrement byte pointer in $FDOBH(D) and write the  byte  into  the
         buffer.  Skip return.


     FDB words altered:
     --- ----- --------
     $FDOBH the buffer header is altered by changing the byte  pointer  and
            byte counts



     7.3  $$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 return.  The user programmer may rewrite this
     routine to perform additional functions if he wishes.



     7.4  $$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:

     $$WCHR::
             CAME    D,$IDEFD(I)     ;is this the log file?
FORMATTED READING AND WRITING                                      Page 7-3
$$WCHR - WRITE A CHARACTER TO THE CURRENT 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
     WCH10:
             WRITE$                  ;send character to file
               FATAL$                ;
             POPJ    P,              ;



     7.5  $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:

     1.  if the current file point is zero (TTCALL IO), read the  character
         using INCHWL and double-skip return immediately.

     2.  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.

     3.  otherwise, check the byte count in the buffer  header,  $FDIBH(D),
         and unless the buffer is empty, go to step 5.

     4.  call $INPUT to read the next record.  If error  or  endfile,  give
         the appropriate returns.

     5.  read the next character from the buffer, and decrement the  buffer
         byte count.  Double skip return.


     FDB words altered:
     --- ----- --------
     $FDIBH the buffer header is altered by changing the byte  pointer  and
            byte count.



     7.6  $$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
FORMATTED READING AND WRITING                                      Page 7-4
$$RBYT - READ A BYTE FROM THE CURRENT FILE


     to perform additional functions if he wishes.



     7.7  $$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:

     $$RCH0::
             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
             PUSH    P,$FDIBH+2(D)   ;
             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



     7.8  $$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
FORMATTED READING AND WRITING                                      Page 7-5
$$RCHR - READ A CHARACTER FROM THE CURRENT COMMAND FILE


     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:

     $$RCHR::
             PJRST   $RCCHR##        ;no altmode defaulting

     If the command character interpreting is not required, but  the  basic
     editing  provided  in  $REDCH  is,  then  redefine $$RCHR as a jump to
     $REDCH:

     $$RCHR::
             PJRST   $REDCH##        ;just basic editing

     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:

                    0    $CHALT    altmode (ASCII 033)
                    -1   $CHEOL    endline (ASCII 012,013,014)
                    -2   $CHEOF    endfile (ASCII 003,032)



     7.9  $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.

     1.  make the endfile return look like a control-Z character.

     2.  ignore nul (ASCII 000), carriage return  (ASCII  015)  and  delete
         (ASCII 177).

     3.  make tab (ASCII 011) into space (ASCII 040)

     4.  if escape (ASCII 033) give terminal user a <cr><lf> and  set  code
         $CHALX (0).

     5.  make vertical tab (ASCII 013), form feed (ASCII 014) and line feed
         (ASCII 012) into $CHEOL (-1).

     6.  if control-C (ASCII 003) clear the command scanning coroutine pc

     7.  if either control-C or control-Z  (ASCII  032)  turn  into  $CHEOF
         (-2).
FORMATTED READING AND WRITING                                      Page 7-6
$RCCHR - READ A CHARACTER AND EDIT AS A COMMAND CHARACTER


     7.10  $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.

     Note:  This routine may only be used for one file at a time.



     7.11  $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 scanner.  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 manager.
     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'.
FORMATTED READING AND WRITING                                      Page 7-7
$RFILE - READ A FILENAME FROM THE CURRENT FILE


          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:

          1B0       FF$NUL    file specification was null  except  possibly
                              for switches.  No meaningful file name fields
                              were typed.

          1B1       FF$WLD    the   file   specification   contains    wild
                              characters



     7.12  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