@X @~
~L3 COUK1247
80
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H             LIB042B
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL
~
~
                                                            ISSUE 11~
~V9 -1
~P
~V9 1
~YLIB042B
~S~M~OLIBRARY IMPLEMENTATION DESCRIPTION
~S~M~OSection 4 Version 2B
~S~OSection 4.2B Stream Management
~S~O1. General Description
~BThis module provides facilities for defining streams,
enquiring about the status of a stream, and for releasing
streams.
~S~O2. Interfaces
~3
~
Library procedures:~
   INIT.IO()~
   DEFINE.INPUT(STREAM,DOCUMENT,MODE,UNIT SIZE)STREAM~
   DEFINE.OUTPUT(STREAM,DOCUMENT,MODE,SECTION SIZE)STREAM~
   DEFINE.IO(STREAM,DOCUMENT1,DOCUMENT2,MODE,SECTION SIZE)STREAM~
   DEFINE.STRING.IO(STREAM,STRING,MODE)STREAM~
   END.INPUT(STREAM,REASON)~
   END.OUTPUT(STREAM,REASON)~
   CURRENT.INPUT()STREAM~
   CURRENT.OUTPUT()STREAM~
   I.MODE()MODE~
   O.MODE()MODE~
   I.SEG()SEG~
   O.SEG()SEG~
   I.SOURCE(SOURCE)~
   I.ENQ()STATUS~
   I.SIZE()SIZE~
   O.SIZE()SIZE~
   I.DOC()FILE NAME~
   O.DOC()FILE NAME~
   R.SIZE()SIZE~
   SELECT.INPUT(STREAM)~
   SELECT.OUTPUT(STREAM)~
   CHANGE.DEST(STREAM,DEST)~
~0
~S~O3. Implementation
~S~O3.1 Outline of Operation
~BThe variables associated with a stream in an I/O control area.
An area is allocated from a pool whenever a stream is defined.
Thus, the number of areas define the maximum sum of input and
output streams that can exist concurrently.  The last area is
never assigned, and all undefined input and output streams are initialised
to refer to this area.  The effect of this is that accesses to
undefined streams are detected as a consequence of referring to the
pointers etc. in this I/O control area.
~BThe association between an input or output stream number and an
I/O control area is achieved using the vectors I.STREAM and O.STREAM,
which are indexed by stream number and hold the corresponding area
number.
~BTo enable rapid access to the current input (or output) stream, some
global variables are initialised to point to the stream information.
These are CURRENT.IN (CURRENT.OUT) which gives the current input
(output) stream number, and INPUT (OUTPUT) which are pointers to the
corresponding I/O control area.
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H                LIB042B
~V9 -1
~F
@TITLE LIB04(2B,11)
@COL 1S-2R
@BOX 1.0
STREAM MANAGEMENT OPERATIONS
@BOX 2.0
PROCEDURES IN SUB-SECTION
    1 INIT.IO
    2 DEFINE INPUT
    3 DEFINE OUTPUT
    4 DEFINE IO
    5 DEFINE STRING IO
    7 END INPUT
    8 END OUTPUT
    9 DEFINE STREAM
   10 RELEASE STREAM
   11 ALLOCATE LIMITS
   12 CURRENT INPUT
   13 CURRENT OUTPUT
   14 I MODE
   15 O MODE
   16 I SEG
   17 O SEG
   18 I SOURCE
   19 I ENQ
   20 I SIZE
   21 O SIZE
   22 SELECT INPUT
   23 SELECT OUTPUT
   24 CHANGE DEST
   25 I DOC
   26 O DOC
   27 R SIZE
@BOX 1.1
::STREAM MANAGEMENT OPERATIONS
@BOX 2.1
#LIB04.1
#LIB04.2
#LIB04.3
#LIB04.4
#LIB04.5
#LIB04.7
#LIB04.8
#LIB04.9
#LIB04.10
#LIB04.11
#LIB04.12
#LIB04.13
#LIB04.14
#LIB04.15
#LIB04.16
#LIB04.17
#LIB04.18
#LIB04.19
#LIB04.20
#LIB04.21
#LIB04.22
#LIB04.23
#LIB04.24
#LIB04.25
#LIB04.26
#LIB04.27
**IN -1
@END


@TITLE LIB04/1(2B,11)

@COL 1S

@BOX 1.0
STREAM MANAGEMENT PSPECS
@BOX 1.1
LSPEC INIT.IO ();
LSPEC DEFINE.INPUT (INTEGER, ADDR [LOGICAL8], INTEGER32) /INTEGER;
LSPEC DEFINE.OUTPUT (INTEGER, ADDR [LOGICAL8], INTEGER32, INTEGER32) / INTEGER;
LSPEC DEFINE.IO (INTEGER, ADDR [LOGICAL8], INTEGER32, INTEGER32) / INTEGER;
LSPEC DEFINE.STRING.IO (INTEGER, ADDR [LOGICAL8], INTEGER32) / INTEGER;
LSPEC END.INPUT (INTEGER, INTEGER);
LSPEC END.OUTPUT (INTEGER, INTEGER);
PSPEC DEFINE.STREAM (INTEGER, LOGICAL32, ADDR [LOGICAL8]) / INTEGER;
PSPEC RELEASE.STREAM (INTEGER, ADDR [LOGICAL8]);
PSPEC ALLOCATE.LIMITS (INTEGER, INTEGER32);
LSPEC CURRENT.INPUT () / INTEGER
LSPEC CURRENT.OUTPUT () / INTEGER
LSPEC I.MODE () / INTEGER32;
LSPEC O.MODE () / INTEGER32
LSPEC I.SEG () / INTEGER;
LSPEC O.SEG () / INTEGER;
LSPEC I.SOURCE (ADDR [INTEGER])
LSPEC I.ENQ () / INTEGER
LSPEC I.SIZE () / INTEGER32;
LSPEC O.SIZE () / INTEGER32;
LSPEC SELECT.INPUT (INTEGER);
LSPEC SELECT.OUTPUT (INTEGER);
LSPEC CHANGE.DEST (INTEGER, ADDR [INTEGER]);
LSPEC I.DOC () / ADDR [LOGICAL8];
LSPEC O.DOC () / ADDR [LOGICAL8];
LSPEC R.SIZE () / INTEGER32;
**IN -1
@END

@TITLE LIB04.1(2B,11)
@COL 1S-6R-2R-3R-4R-5F
@FLOW 1-6-2-3-4-5
@BOX 1.0
INIT I/O ()
@BOX 2.0
SET ALL STREAMS UNDEFINED
@BOX 3.0
CLEAR ALL I/O CONTROL AREAS,
RELEASING ANY BUFFERS
@BOX 4.0
SET I/O CONTROL AREA COUNT,
AND OUTPUT POINTERS TO ZERO
@BOX 5.0
END
@BOX 6.0
CREATE SEGMENT
@BOX 1.1
PROC INIT.IO;
INTEGER I, J;
ADDR [LOGICAL8] IO.CTRL.PTR;
@BOX 2.1
FOR I < MAX.STREAM.NO DO
   NO.OF.STREAMS => I.STREAM [I] => O.STREAM [I];
OD
@BOX 3.1
FOR I < NO.OF.IO.CONTROL.AREAS DO
   SELECT IO.CONTROL [I];
   IF MODE & DEFINED /= 0 AND SEG /= 0 THEN
      RELEASE.SEGMENT (SEG);
   FI
   0 => MODE;
OD
@BOX 4.1
0 => IO.AREA.COUNT => CURRENT.IN => CURRENT.OUT;
FOR I < NO.OF.BUFFERS DO
   NO.OF.STREAMS => BUFFER [I];
OD
^IO.CONTROL [NO.OF.STREAMS] => INPUT => OUTPUT;
@BOX 5.1
END
@BOX 6.1
RELEASE.SEGMENT (IO.CONTROL.SEG);
CREATE.SEGMENT (IO.CONTROL.SEG, SYS14.SEG.SIZE);
MAP (IO.CONTROL.SEG, MAPPED.IO.CONTROL.SEG, 0);
PW6 * SYS14.SEG.SIZE => IO.BUFFER.VA;
IO.BUFFER.BLOCK * SYS14.PAGE.SIZE +> IO.BUFFER.VA;
@END

@TITLE LIB04.2(2B,11)
@COL 1S-17T-3T-4T-12R-13R-5T-15R-6R-8R-9F
@COL 10T-11R-14R
@ROW 10-4
@FLOW 1-17-3-4OTHER-5OK-15-6-8-9
@FLOW 3CURRENT-10NO-11-8
@FLOW 10YES-14-8
@FLOW 4PREDEFINED-12-13-8
@FLOW 5FAILED-8
@FLOW 17FILE-5
@BOX 1.0
DEFINE INPUT (STREAM, SOURCE, MODE) STREAM NO
@BOX 3.0
CURRENT STREAM?
@BOX 4.0
PREDEFINED STREAM?
@BOX 5.0
ALLOCATE A STREAM NUMBER AND
INITIALISE I/O CONTROL AREA
@BOX 6.0
GET FIRST SECTION OF
INPUT STREAM
@BOX 8.0
SET RESULT TO
STREAM NUMBER
@BOX 9.0
END
@BOX 10.0
CURRENT STREAM UNACCEPTABLE?
@BOX 11.0
FIND NUMBER OF CURRENT STREAM
@BOX 12.0
ASSIGN STREAM NUMBER
@BOX 13.0
REDEFINE EXISTING STREAM
@BOX 14.0
ENTER TRAP (5, 2)
NO CURRENT FILE AVAILABLE
@BOX 15.0
NOTE SOURCE INFORMATION
@BOX 17.0
IS SOURCE A FILE?
@BOX 1.1
PROC DEFINE.INPUT (STREAM, SOURCE, STR.MODE);
INTEGER STR, AREA, I, SRC.TYPE, S;
LOGICAL64 N1, N2;
@BOX 3.1
IF SRC.TYPE = 0 AND
   LIB07.CURRENT.FILE.AVAILABLE () = 0
@BOX 4.1
IF SRC.TYPE /= 4
@BOX 5.1
IF DEFINE.STREAM (STREAM, STR.MODE ! IN, ^I.STREAM)
   => STREAM < 0
@BOX 6.1
BREAK.INPUT (STREAM);
@BOX 8.1
^IO.CONTROL [I.STREAM [CURRENT.IN]] => INPUT;
STREAM => DEFINE.INPUT;
@BOX 9.1
END
@BOX 10.1
IF STR.MODE & STREAM.OPTION /= 0
   OR STREAM  >= 0
@BOX 11.1
CURRENT.IN => STREAM;
ASSIGNED !> MODE OF INPUT^;
@BOX 12.1
IF STREAM < 0 AND
   I.STREAM [STR] => AREA /= NO.OF.STREAMS THEN
   STR => STREAM;
   ASSIGNED !> MODE OF IO.CONTROL [AREA];
FI
@BOX 13.1
IF STR /= STREAM THEN
   RELEASE.STREAM (STREAM, ^I.STREAM);
   I.STREAM [STR] => I.STREAM [STREAM];
   NO.OF.STREAMS => I.STREAM [STR];
FI
@BOX 14.1
ENTER.TRAP (5, 2);
@BOX 15.1
SELECT IO.CONTROL [I.STREAM [STREAM]];
STR => IN.CHANNEL;
SRC.TYPE => DOC.TYPE;
N1 => NAME1;
N2 => NAME2;
IF SRC.TYPE = 1 THEN
   COPY.NAME (SOURCE, ^MESSAGE) => IO.FILE;
FI
@BOX 17.1
PROCESS.NAME (SOURCE) => SOURCE;
PWW1 => N1;
PWW2 => N2;
PW2 => STR;
IF PW1 => SRC.TYPE = 1
@END

@TITLE LIB04.3(2B,11)
@COL 1S-15T-3T-4T-12R-13R-5T-6R-7R-9R-10F
@COL 11R
@ROW 11-4
@FLOW 1-15-3-4OTHER-5OK-6-7-9-10
@FLOW 3CURRENT-11-9
@FLOW 4PREDEFINED-12-13-9
@FLOW 5FAILED-9
@FLOW 15FILE-5
@BOX 1.0
DEFINE OUTPUT (STREAM, DEST, MODE, SECTION SIZE) STREAM NO
@BOX 3.0
CURRENT STREAM?
@BOX 4.0
PREDEFINED STREAM?
@BOX 5.0
ALLOCATE A STREAM AND
INITIALISE I/O CONTROL AREA
@BOX 6.0
SET SECTION SIZE AND DESTINATION
IN I/O CONTROL AREA
@BOX 7.0
SET UP FIRST SECTION
OF OUTPUT STREAM
@BOX 9.0
SET RESULT TO STREAM
ALLOCATED
@BOX 10.0
END
@BOX 11.0
FIND CURRENT STREAM NUMBER
@BOX 12.0
ASSIGN STREAM NUMBER
@BOX 13.0
REDEFINE EXISTING STREAM
@BOX 15.0
IS DESTINATION A FILE?
@BOX 1.1
PROC DEFINE.OUTPUT (STREAM, DEST, STR.MODE, SECT.SIZE);
INTEGER STR, AREA, DEST.SIZE, I, DEST.TYPE, S;
LOGICAL64 N1, N2;
@BOX 3.1
IF DEST.TYPE = 0 AND STR.MODE & STREAM.OPTION /= 0
@BOX 4.1
IF DEST.TYPE /= 4
@BOX 5.1
IF DEFINE.STREAM (STREAM, STR.MODE ! OUT, ^O.STREAM)
   => STREAM < 0
@BOX 6.1
SELECT IO.CONTROL [O.STREAM [STREAM] => AREA];
DEST.TYPE => DOC.TYPE;
ALLOCATE.LIMITS (AREA, SECT.SIZE);
N1 => NAME1;
N2 => NAME2;
STR => REPLY.TO.STREAM;
IF DEST.TYPE = 1 THEN
   COPY.NAME (DEST, ^MESSAGE) => IO.FILE;
FI
@BOX 7.1
BREAK.OUTPUT (STREAM);
@BOX 9.1
^IO.CONTROL [O.STREAM [CURRENT.OUT]] => OUTPUT;
STREAM => DEFINE.OUTPUT;
@BOX 10.1
END
@BOX 11.1
IF STREAM < 0 THEN
   CURRENT.OUT => STREAM;
   ASSIGNED !> MODE OF OUTPUT^;
ELSE
   ENTER.TRAP (5, 1);
FI
@BOX 12.1
IF STREAM < 0 AND
   O.STREAM [STR] => AREA /= NO.OF.STREAMS THEN
   STR => STREAM;
   ASSIGNED !> MODE OF IO.CONTROL [AREA];
FI
@BOX 13.1
IF STR /= STREAM THEN
   RELEASE.STREAM (STREAM, ^O.STREAM);
   O.STREAM [STR] => O.STREAM [STREAM];
   NO.OF.STREAMS => O.STREAM [STR];
FI
@BOX 15.1
PROCESS.NAME (DEST) => DEST;
PWW1 => N1;
PWW2 => N2;
PW2 => STR;
IF PW1 => DEST.TYPE =1
@END

@TITLE LIB04.4(2B,11)
@COL 1S-2R-23T-3T-14R-15T-17R-4T-18R-6R-19N-7R-8F
@COL 9T-10R-11R-12R-16R-20N
@ROW 19-20
@ROW 14-9
@FLOW 1-2-23NO-3NO-14-15NO-17-4OK-18-6-19-7-8
@FLOW 3YES-9NO-10-11-20-19
@FLOW 9YES-12-20
@FLOW 4FAIL-19
@FLOW 15YES-16-20
@FLOW 23YES-14
@BOX 1.0
DEFINE IO (STREAM, DOC, MODE, SECTION SIZE) STREAM NO
@BOX 2.0
READ SOURCE AND DESTINATION NAMES
@BOX 3.0
REQUEST FOR PREDEFINED STREAM?
@BOX 4.0
ALLOCATE A STREAM
@BOX 6.0
SET UP FIRST SECTION OF STREAM
@BOX 7.0
SET RESULT TO STREAM ALLOCATED
@BOX 8.0
END
@BOX 9.0
PREDEFINED STREAM
UNACCEPTABLE?
@BOX 10.0
ASSIGN STREAM NUMBER
@BOX 11.0
REDEFINE EXISTING STREAM
@BOX 12.0
ENTER TRAP (5, 3)
ILLEGAL STREAM NAME
@BOX 14.0
ASSIGN STREAM NUMBER
IF REQUIRED
@BOX 15.0
NO STREAMS AVAILABLE?
@BOX 16.0
ENTER TRAP (5, 1)
NO STREAM AVAILABLE
@BOX 17.0
RELEASE INPUT AND
OUTPUT STREAMS
@BOX 18.0
SET SECTION SIZE AND DOCUMENT
IN I/O CONTROL AREA
@BOX 23.0
DOCUMENT A FILE?
@BOX 1.1
PROC DEFINE.IO (STREAM, IO.DOC, STR.MODE, SECT.SIZE);
INTEGER STR, AREA, I, S, IO.DOC.TYPE, IO.STR;
LOGICAL64 N1, N2;
@BOX 2.1
PROCESS.NAME (IO.DOC) => IO.DOC;
PWW1 => N1;
PWW2 => N2;
PW2 => IO.STR;
PW1 => IO.DOC.TYPE;
@BOX 3.1
IF IO.DOC.TYPE = 4
@BOX 4.1
IF DEFINE.STREAM (STREAM,
   STR.MODE ! DIRECT.ACCESS ! IN ! OUT, ^I.STREAM)
   => STREAM < 0
@BOX 6.1
IF IO.DOC.TYPE /= 1  OR
   MODE & %40 /= 0 THEN
   BREAK.OUTPUT (STREAM);
ELSE
   READ.FILE.STATUS (IO.FILE, N1);
   IF PW0 /= 0 THEN
      %40 !> MODE;
      BREAK.OUTPUT (STREAM);
   ELSE
      BREAK.INPUT (STREAM);
   FI
FI
@BOX 7.1
^IO.CONTROL [I.STREAM [CURRENT.IN]] => INPUT;
^IO.CONTROL [O.STREAM [CURRENT.OUT]] => OUTPUT;
STREAM => DEFINE.IO;
@BOX 8.1
END
@BOX 9.1
IO.STR => STR;
IF I.STREAM [STR] => AREA = NO.OF.STREAMS
   OR MODE OF IO.CONTROL [AREA] & DIRECT.ACCESS = 0
@BOX 10.1
IF STREAM < 0 THEN
   STR => STREAM;
   ASSIGNED !> MODE OF IO.CONTROL [AREA];
FI
@BOX 11.1
IF STR /= STREAM THEN
   RELEASE.STREAM (STREAM, ^I.STREAM);
   RELEASE.STREAM (STREAM, ^O.STREAM);
   I.STREAM [STR] => I.STREAM [STREAM];
   O.STREAM [STR] => O.STREAM [STREAM];
   NO.OF.STREAMS => I.STREAM [STR]
      => O.STREAM [STR];
FI
@BOX 12.1
ENTER.TRAP (5, 3);
@BOX 14.1
IF STREAM < 0 OR STREAM >= MAX.STREAM.NO THEN
   -1 => STREAM;
   WHILE 1 +> STREAM < MAX.STREAM.NO
      AND [I.STREAM [STREAM] /= NO.OF.STREAMS
      OR O.STREAM [STREAM] /= NO.OF.STREAMS] DO OD
FI
@BOX 15.1
IF STREAM = MAX.STREAM.NO
@BOX 16.1
ENTER.TRAP (5, 1);
@BOX 17.1
RELEASE.STREAM (STREAM, ^I.STREAM);
RELEASE.STREAM (STREAM, ^O.STREAM);
@BOX 18.1
I.STREAM [STREAM] => O.STREAM [STREAM] => AREA;
SELECT IO.CONTROL [AREA];
IO.DOC.TYPE => DOC.TYPE;
N1 => NAME1;
N2 => NAME2;
IO.STR => IN.CHANNEL => REPLY.TO.STREAM;
IF IO.DOC.TYPE = 1 THEN
   COPY.NAME (IO.DOC, ^MESSAGE) => IO.FILE;
FI
ALLOCATE.LIMITS (AREA, SECT.SIZE);
@BOX 23.1
IF IO.DOC.TYPE = 1
@END

@TITLE LIB04.5(2B,11)
@COL 1S-2T-3R-5R-6F
@FLOW 1-2OK-3-5-6
@FLOW 2FAIL-5
@BOX 1.0
DEFINE STRING IO (STREAM, STRING, MODE) STREAM NO
@BOX 2.0
ALLOCATE A STREAM NUMBER AND
INITIALISE I/O CONTROL AREA
@BOX 3.0
SET POINTERS TO STRING
@BOX 5.0
SET RESULT TO STREAM NUMBER
@BOX 6.0
END
@BOX 1.1
PROC DEFINE.STRING.IO (STREAM, STRING, STR.MODE);
@BOX 2.1
IF DEFINE.STREAM (STREAM, STR.MODE ! DIRECT.ACCESS ! STRING.IO ! IN ! OUT, ^I.ST
REAM)
   => STREAM < 0
@BOX 3.1
I.STREAM [STREAM] => O.STREAM [STREAM];
SELECT IO.CONTROL [I.STREAM [STREAM]];
STRING => BYTE.PTR;
-1 => BLOCK;
BYTE (STRING) ->> SYS14.SEG.SHIFT => SEG;
SEG <<- SYS14.SEG.SHIFT -: BYTE (STRING) => REC.START + 4 => PTR.START;
REC.START + SIZE (STRING) - 4 => REC.END => MAX.SECTION.SIZE;
0 => SECTION.SIZE => SEG.STATUS => PTR;
SIZE (STRING) - 8 => PTR.END;
@BOX 5.1
STREAM => DEFINE.STRING.IO;
@BOX 6.1
END
@END

@TITLE LIB04.7(2B,11)
@COL 1S-5R-2T-3T-4R-6F
@COL 7R
@ROW 4-7
@FLOW 1-5-2NO-3NO-4-6
@FLOW 2YES-4
@FLOW 3YES-7-6
@BOX 1.0
END INPUT (STREAM, REASON)
@BOX 2.0
IS REASON NEGATIVE?
@BOX 3.0
HAS THE STREAM BEEN
ASSIGNED?
@BOX 4.0
RELEASE THE STREAM
@BOX 5.0
SET STREAM TO CURRENT STREAM
IF REQUIRED
@BOX 6.0
END
@BOX 7.0
MARK THE STREAM
AS NOT ASSIGNED
@BOX 1.1
PROC END.INPUT (STREAM, REASON);
@BOX 2.1
IF REASON < 0
@BOX 3.1
IF MODE & ASSIGNED /= 0
@BOX 4.1
RELEASE.STREAM (STREAM, ^I.STREAM);
@BOX 5.1
IF STREAM < 0 THEN
   CURRENT.IN => STREAM;
FI
SELECT IO.CONTROL [I.STREAM [MAX.STREAM.MASK &> STREAM]];
@BOX 6.1
END
@BOX 7.1
ASSIGNED -=> MODE;
@END
@TITLE LIB04.8(2B,11)
@COL 1S-2R-4T-5T-6T-9R-10R-11F
@COL 12R
@ROW 9-12
@FLOW 1-2-4NO-5NO-6NO-9-10-11
@FLOW 4YES-6
@FLOW 5YES-10
@FLOW 6YES-12-11
@BOX 1.0
END OUTPUT (STREAM, REASON)
@BOX 2.0
SET STREAM TO CURRENT STREAM
IF REQUIRED
@BOX 4.0
IS REASON POSITIVE?
@BOX 5.0
OUTPUT TO BE DISCARDED
IN CASES OF ERROR?
@BOX 6.0
WAS STREAM ASSIGNED?
@BOX 9.0
BREAK OUTPUT ON STREAM
@BOX 10.0
RELEASE OUTPUT STREAM
@BOX 11.0
END
@BOX 12.0
MARK STREAM NOT ASSIGNED
@BOX 1.1
PROC END.OUTPUT (STREAM, REASON);
@BOX 2.1
IF STREAM < 0 THEN
   CURRENT.OUT => STREAM;
FI
SELECT IO.CONTROL [O.STREAM [MAX.STREAM.MASK &> STREAM]];
@BOX 4.1
IF REASON >= 0
@BOX 5.1
IF [DOC.TYPE > 1 AND MODE & DISCARD /= 0]
   OR [DOC.TYPE =< 1 AND MODE & SAVE = 0]
@BOX 6.1
IF MODE & ASSIGNED /= 0
@BOX 9.1
BREAK.OUTPUT (STREAM);
@BOX 10.1
RELEASE.STREAM (STREAM, ^O.STREAM);
@BOX 11.1
END
@BOX 12.1
ASSIGNED -=> MODE;
@END
@TITLE LIB04.9(2B,11)
@COL 1S-2R-3T-5R-11T-14R-6R-8R-9F
@COL 13R
@ROW 14-13
@FLOW 1-2-3NO-5-11NO-14-6-8-9
@FLOW 3YES-13-8
@FLOW 11YES-13
@BOX 1.0
DEFINE STREAM (STREAM, MODE, IN OR OUT) STREAM NO
@BOX 2.0
ASSIGN A STREAM NUMBER IF
REQUIRED
@BOX 3.0
NO STREAMS AVAILABLE?
@BOX 5.0
RELEASE PRESENT STREAM
@BOX 6.0
INITIALISE I/O CONTROL AREA
@BOX 8.0
SET RESULT TO STREAM ALLOCATED
@BOX 9.0
END
@BOX 11.0
STREAM LIMIT EXCEEDED?
@BOX 13.0
ENTER TRAP (5, 1)
NO STREAM AVAILABLE
@BOX 14.0
FIND A STREAM
AND ALLOCATE IT
@BOX 1.1
PROC DEFINE.STREAM (STREAM, STR.MODE, IO.STREAM);
INTEGER AREA, I;
ADDR [LOGICAL8] IO.CTRL.PTR;
@BOX 2.1
IF STREAM < 0 OR STREAM >= MAX.STREAM.NO THEN
   -1 => STREAM;
   WHILE 1 +> STREAM < MAX.STREAM.NO
      AND IO.STREAM^ [STREAM] /= NO.OF.STREAMS DO OD
FI
@BOX 3.1
IF STREAM = MAX.STREAM.NO
@BOX 5.1
RELEASE.STREAM (STREAM, IO.STREAM);
@BOX 6.1
SELECT IO.CONTROL [AREA];
STR.MODE ! DEFINED => MODE;
0 => SEG;
-1 => SECTION.NO => BUF;
@BOX 8.1
^IO.CONTROL [I.STREAM [CURRENT.IN]] => INPUT;
^IO.CONTROL [O.STREAM [CURRENT.OUT]] => OUTPUT;
STREAM => DEFINE.STREAM;
@BOX 9.1
END
@BOX 11.1
IF IO.AREA.COUNT = NO.OF.STREAMS
@BOX 13.1
ENTER.TRAP (5, 1);
-1 => STREAM;
@BOX 14.1
-1 => AREA;
WHILE MODE OF IO.CONTROL [1 +> AREA] /= 0 DO OD
AREA => IO.STREAM^ [STREAM];
1 +> IO.AREA.COUNT;
@END
@TITLE LIB04.10(2B,11)
@COL 1S-2T-5R-7T-8R-9R-10R-11F
@COL 13R
@ROW 13-8
@FLOW 1-2NO-5-7NO-8-9-10-11
@FLOW 2YES-11
@FLOW 7YES-13-9
@BOX 1.0
RELEASE STREAM (STREAM, IN OR OUT)
@BOX 2.0
IS STREAM UNDEFINED?
@BOX 5.0
RELEASE BUFFER SEGMENT
[LIB07]
@BOX 7.0
IS STREAM DIRECT
ACCESS?
@BOX 8.0
RELEASE THE STREAM
@BOX 9.0
RELEASE I/O CONTROL AREA
@BOX 10.0
SET INPUT AND OUTPUT POINTERS
FOR CURRENTLY SELECTED STREAMS
@BOX 11.0
END
@BOX 13.0
RELEASE BOTH INPUT
AND OUTPUT STREAMS
@BOX 1.1
PROC RELEASE.STREAM (STREAM, IO.STREAM);
INTEGER AREA;
@BOX 2.1
IF IO.STREAM^ [MAX.STREAM.MASK &> STREAM] => AREA = NO.OF.STREAMS
@BOX 5.1
SELECT IO.CONTROL [AREA];
LIB07.RELEASE.BUFFER.SEG (SEG);
@BOX 7.1
IF MODE & DIRECT.ACCESS /= 0
@BOX 8.1
NO.OF.STREAMS => IO.STREAM^ [STREAM];
@BOX 9.1
0 => MODE;
1 -> IO.AREA.COUNT;
@BOX 10.1
^IO.CONTROL [I.STREAM [CURRENT.IN]] => INPUT;
^IO.CONTROL [O.STREAM [CURRENT.OUT]] => OUTPUT;
IF BUF >= 0 THEN
   NO.OF.STREAMS => BUFFER [BUF];
   -1 => BUF;
FI
@BOX 11.1
END
@BOX 13.1
NO.OF.STREAMS => I.STREAM [STREAM]
   => O.STREAM [STREAM];
@END
@TITLE LIB04.11(2B,11)

@COL 1S-2T-4R-9R-5F
@COL 8R

@ROW 4-8

@FLOW 1-2NO-4-9-5
@FLOW 2YES-8-9

@BOX 1.0
ALLOCATE LIMITS (AREA, SECTION SIZE)
@BOX 2.0
SHORT MESSAGE STREAM?
@BOX 4.0
SET SECTION SIZE
@BOX 5.0
END
@BOX 8.0
SET SECTION SIZE
@BOX 9.0
ENSURE SECTION SIZE NOT
TOO LARGE
@BOX 1.1
PROC ALLOCATE.LIMITS (AREA, SECT.SIZE);
INTEGER32 X.SEG.SIZE;
@BOX 2.1
SELECT IO.CONTROL [AREA];
IF MODE & SHORT.MSSGE /= 0
@BOX 4.1
IF SECT.SIZE = 0 THEN
   SECT.SIZE.DEFAULT => SECT.SIZE;
FI
SECT.SIZE => MAX.SECTION.SIZE;
0 => SECTION.SIZE;
@BOX 5.1
END
@BOX 8.1
MESSAGE.SIZE => MAX.SECTION.SIZE;
0 => SECTION.SIZE;
@BOX 9.1
IF SYS14.X.SEG.SIZE <<- SYS14.PAGE.SHIFT => X.SEG.SIZE < MAX.SECTION.SIZE THEN
   X.SEG.SIZE => MAX.SECTION.SIZE;
FI
@END
@TITLE LIB04.12(2B,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
CURRENT INPUT () STREAM NUMBER
@BOX 2.0
RETURN NUMBER OF
CURRENT INPUT STREAM
@BOX 3.0
END
@BOX 1.1
PROC CURRENT.INPUT;
@BOX 2.1
CURRENT.IN => CURRENT.INPUT;
@BOX 3.1
END
@END

@TITLE LIB04.13(2B,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
CURRENT OUTPUT () STREAM NUMBER
@BOX 2.0
RETURN NUMBER OF
CURRENT OUTPUT STREAM
@BOX 3.0
END
@BOX 1.1
PROC CURRENT.OUTPUT;
@BOX 2.1
CURRENT.OUT => CURRENT.OUTPUT;
@BOX 3.1
END
@END

@TITLE LIB04.14(2B,11)

@COL 1S-3R-4F

@FLOW 1-3-4

@BOX 1.0
I MODE () MODE
@BOX 3.0
RETURN MODE OF
CURRENT INPUT STREAM
@BOX 4.0
END
@BOX 1.1
PROC I.MODE;
@BOX 3.1
MODE OF INPUT^ => I.MODE;
@BOX 4.1
END
@END

@TITLE LIB04.15(2B,11)

@COL 1S-3R-4F

@FLOW 1-3-4

@BOX 1.0
O MODE () MODE
@BOX 3.0
RETURN MODE OF
CURRENT OUTPUT STREAM
@BOX 4.0
END
@BOX 1.1
PROC O.MODE;
@BOX 3.1
MODE OF OUTPUT^ => O.MODE;
@BOX 4.1
END
@END

@TITLE LIB04.16(2B,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
I SEG () SEGMENT NUMBER
@BOX 2.0
RETURN SEGMENT NUMBER FOR
CURRENT INPUT STREAM
@BOX 3.0
END
@BOX 1.1
PROC I.SEG;
@BOX 2.1
SEG OF INPUT^ => I.SEG;
@BOX 3.1
END
@END

@TITLE LIB04.17(2B,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
O SEG () SEGMENT NUMBER
@BOX 2.0
RETURN SEGMENT NUMBER FOR
CURRENT OUTPUT STREAM
@BOX 3.0
END
@BOX 1.1
PROC O.SEG;
@BOX 2.1
SEG OF OUTPUT^ => O.SEG;
@BOX 3.1
END
@END

@TITLE LIB04.18(2B,11)

@COL 1S-2T-3R-4F
@COL 5R

@ROW 3-5

@FLOW 1-2NO-3-4
@FLOW 2YES-5-4

@BOX 1.0
I SOURCE (SOURCE)
@BOX 2.0
NOT A MESSAGE STREAM?
@BOX 3.0
COPY SOURCE INFORMATION
@BOX 4.0
END
@BOX 5.0
ENTER TRAP (5, 5)
STREAM OF INCORRECT TYPE
@BOX 1.1
PROC I.SOURCE (SOURCE);
INTEGER I;
@BOX 2.1
SELECT INPUT^;
IF DOC.TYPE /= 6
@BOX 3.1
FOR I < 4 DO
   PROC.INFO [I] => SOURCE^ [I];
OD
@BOX 4.1
END
@BOX 5.1
ENTER.TRAP (5, 5);
@END

@TITLE LIB04.19(2B,11)

@COL 1S-2R-3T-14T-4R-16T-15T-5T-6R-7T-11R-12F
@COL 13R

@ROW 11-13
@FLOW 1-2-3NO-14NO-4-16NO-15NO-5NO-6-7NO-11-12
@FLOW 3YES-12
@FLOW 14YES-12
@FLOW 16YES-6
@FLOW 15YES-6
@FLOW 5YES-12
@FLOW 7YES-13-12

@BOX 1.0
I ENQ () STATUS
@BOX 2.0
CLEAR RESULT
@BOX 3.0
NOT END OF ANYTHING?
@BOX 4.0
INDICATE END OF RECORD
@BOX 5.0
NOT LAST RECORD?
@BOX 6.0
INDICATE END OF SECTION
@BOX 7.0
MESSAGE STREAM?
@BOX 11.0
INDICATE END OF INPUT
@BOX 12.0
END
@BOX 13.0
INDICATE END OF INPUT IF
NO MESSAGES AVAILABLE
@BOX 14.0
NOT END OR RECORD?
@BOX 15.0
LAST RECORD MARKER REACHED?
@BOX 16.0
SHORT MESSAGE?
@BOX 1.1
PROC I.ENQ;
INTEGER32 REC.MARK;
@BOX 2.1
SELECT INPUT^;
0 => I.ENQ;
@BOX 3.1
IF PTR /= PTR.END
@BOX 4.1
1 => I.ENQ;
@BOX 5.1
4 +> REC.END;
IN.BIN (4) => REC.MARK;
SET.BPOS (INPUT, 4 -> REC.END);
IF REC.MARK >= 0
@BOX 6.1
2 !> I.ENQ;
@BOX 7.1
IF DOC.TYPE = 6
@BOX 11.1
12 !> I.ENQ;
@BOX 12.1
END
@BOX 13.1
READ.CH.STATUS (CURRENT.IN);
IF PW4 = 0 THEN
   4 !> I.ENQ;
   IF MODE & ONLINE = 0 THEN
      8 !> I.ENQ;
   FI
FI
@BOX 14.1
IF PTR.END + PTR.START /= REC.END
@BOX 15.1
IF REC.END - REC.START < 4
@BOX 16.1
IF HDR /= 0
@END

@TITLE LIB04.20(2B,11)

@COL 1S-3R-4F
@FLOW 1-3-4

@BOX 1.0
I SIZE () SIZE
@BOX 3.0
RETURN SECTION SIZE
@BOX 4.0
END
@BOX 1.1
PROC I.SIZE;
SELECT INPUT^;
@BOX 3.1
MAX.SECTION.SIZE => I.SIZE;
@BOX 4.1
END
@END
@TITLE LIB04.21(2B,11)

@COL 1S-3R-4F

@FLOW 1-3-4

@BOX 1.0
O SIZE () SIZE
@BOX 3.0
RETURN SECTION SIZE
@BOX 4.0
END
@BOX 1.1
PROC O.SIZE;
SELECT OUTPUT^;
@BOX 3.1
MAX.SECTION.SIZE => O.SIZE;
@BOX 4.1
END
@END
@TITLE LIB04.22(2B,11)

@COL 1S-2R-4R-3F

@FLOW 1-2-4-3

@BOX 1.0
SELECT INPUT (STREAM)
@BOX 2.0
SET NUMBER OF CURRENT INPUT STREAM
AND POINTER TO INPUT CONTROL AREA
@BOX 3.0
END
@BOX 4.0
GET BUFFER
@BOX 1.1
PROC SELECT.INPUT (STREAM);
INTEGER AREA;
@BOX 2.1
I.STREAM [MAX.STREAM.MASK & STREAM => CURRENT.IN] => AREA;
^IO.CONTROL [AREA] => INPUT;
@BOX 3.1
END
@BOX 4.1
GET.BUFFER (AREA);
@END


@TITLE LIB04.23(2B,11)

@COL 1S-2R-4R-3F

@FLOW 1-2-4-3

@BOX 1.0
SELECT OUTPUT (STREAM)
@BOX 2.0
SET NUMBER OF CURRENT OUTPUT STREAM
AND POINTER TO OUTPUT CONTROL AREA
@BOX 3.0
END
@BOX 4.0
GET BUFFER
@BOX 1.1
PROC SELECT.OUTPUT (STREAM);
INTEGER AREA;
@BOX 2.1
O.STREAM [MAX.STREAM.MASK & STREAM => CURRENT.OUT] => AREA;
^IO.CONTROL [AREA] => OUTPUT;
@BOX 3.1
END
@BOX 4.1
GET.BUFFER (AREA);
@END


@TITLE LIB04.24(2B,11)
@COL 1S-2R-4T-5R-6R-7F
@COL 8R
@ROW 5-8
@FLOW 1-2-4NO-5-6-7
@FLOW 4YES-8-7
@BOX 1.0
CHANGE DEST (STREAM, DESTINATION)
@BOX 2.0
SET STREAM TO CURRENT
OUTPUT STREAM IF REQUIRED
@BOX 4.0
IS STREAM NOT
MESSAGE STREAM?
@BOX 5.0
CHANGE DESTINATION
@BOX 6.0
SET DUMMY DESTINATION NAME
@BOX 7.0
END
@BOX 8.0
ENTER TRAP (5, 5)
WRONG TYPE OF STREAM
@BOX 1.1
PROC CHANGE.DEST (STREAM, DEST);
INTEGER I;
@BOX 2.1
IF STREAM < 0 THEN
   CURRENT.OUT => STREAM;
FI
@BOX 4.1
SELECT IO.CONTROL [O.STREAM [STREAM]];
IF DOC.TYPE /= 2 /= 3
@BOX 5.1
FOR I < 4 DO
   DEST^ [I] => PROC.INFO [I];
OD
@BOX 6.1
2 => DOC.TYPE;
0 => NAME1 => NAME2;
@BOX 7.1
END
@BOX 8.1
ENTER.TRAP (5, 5);
@END

@TITLE LIB04.25(2B,11)

@COL 1S-2R-3R-4F

@FLOW 1-2-3-4

@BOX 1.0
I DOC () NAME
@BOX 2.0
RETURN POINTER TO FILENAME
IF DOCUMENT IS A FILE
@BOX 3.0
RETURN OTHER NAME
INFORMATION IN THE PWWS
@BOX 4.0
END
@BOX 1.1
PROC I.DOC;
@BOX 2.1
SELECT INPUT^;
IF DOC.TYPE => PW1 = 1 THEN
   IO.FILE => I.DOC;
ELSE
   NIL => I.DOC;
FI
@BOX 3.1
NAME1 => PWW1;
NAME2 => PWW2;
@BOX 4.1
END
@END



@TITLE LIB04.26(2B,11)

@COL 1S-2R-3R-4F

@FLOW 1-2-3-4

@BOX 1.0
O DOC () NAME
@BOX 2.0
RETURN POINTER TO FILENAME
IF DOCUMENT IS A FILE
@BOX 3.0
RETURN OTHER NAME
INFORMATION IN THE PWWS
@BOX 4.0
END
@BOX 1.1
PROC O.DOC;
@BOX 2.1
SELECT OUTPUT^;
IF DOC.TYPE => PW1 = 1 THEN
   IO.FILE => O.DOC;
ELSE
   NIL => O.DOC;
FI
@BOX 3.1
NAME1 => PWW1;
NAME2 => PWW2;
@BOX 4.1
END
@END



@TITLE LIB04.27(2B,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
R SIZE () SIZE
@BOX 2.0
RETURN SIZE OF
INPUT RECORD
@BOX 3.0
END
@BOX 1.1
PROC R.SIZE;
@BOX 2.1
SELECT INPUT^;
REC.END - REC.START - 4 => R.SIZE;
@BOX 3.1
END
@END



