@X @~
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H             LIB042F
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL
~
~
                                                            ISSUE 11~
~V9 -1
~P
~V9 1
~YLIB042F
~S~M~OLIBRARY IMPLEMENTATION DESCRIPTION
~S~M~OSection 4 Version 2F
~S~OSection 4.2F Character and Record Input/Output Operations
~S~O1. General Description
~BThis module provides facilities for reading and writing
characters to any stream, and for moving to the next record within a stream.
~S~O2. Interfaces
~
Library procedures:~
   IN.CH()CH~
   NEXT.CH()CH~
   IN.BACKSPACE(NO)~
   IN.LINE(LINE)SIZE~
   SKIP.LINE()~
   IN.BIN(SIZE)BIN~
   IN.REC()SIZE~
   OUT.CH(CH)~
   OUT.LINE(LINE,CONTROL)~
   OUT.BIN(BIN,SIZE)~
   OUT.REC()~
   OUT.BACKSPACE(NO)~
   BACKREC()~
~
~
Interface procedures~
   LAST.CH () CHAR
~S~O2.1 Software Interface
~
~
1) LAST.CH () CHAR
~BThis procedure returns the value of the last character
printed on the current output stream.
~S~O3. Implementation
~S~O3.1 Outline of Operation
~BNone.
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H                LIB042F
~V9 -1
~F
@TITLE LIB04(2F,11)
@COL 1S-2R
@FLOW 1-2
@BOX 1.0
CHARACTER AND BINARY
INPUT/OUTPUT OPERATIONS
@BOX 2.0
PROCEDURES IN SUB-SECTION:
   1 IN CH
   2 NEXT CH
   3 IN BACKSPACE
   4 IN LINE
   5 SKIP LINE
   6 IN BIN
   7 IN REC
   8 OUT CH
   9 OUT LINE
   10 OUT BIN
   11 OUT REC
   12 OUT BACKSPACE
   13 BACKSPACE
   14 LAST CH
   15 BACKREC
@BOX 1.1
::CHARACTER AND BINARY
::INPUT/OUTPUT OPERATIONS
@BOX 2.1
#LIB04.1
#LIB04.2
#LIB04.3
#LIB04.4
#LIB04.5
#LIB04.6
#LIB04.7
#LIB04.8
#LIB04.9
#LIB04.10
#LIB04.11
#LIB04.12
#LIB04.13
#LIB04.14
#LIB04.15
**IN -1
@END
@TITLE LIB04/1(2F,11)

@COL 1S

@BOX 1.0
CHARACTER AND BINARY PSPECS
@BOX 1.1
LSPEC IN.CH () / INTEGER;
LSPEC NEXT.CH () / INTEGER;
LSPEC IN.BACKSPACE (INTEGER);
LSPEC IN.LINE (ADDR [LOGICAL8]) / INTEGER;
LSPEC SKIP.LINE ();
LSPEC IN.BIN (INTEGER) / LOGICAL32;
LSPEC IN.REC () / INTEGER32;
LSPEC OUT.CH (INTEGER);
LSPEC OUT.LINE (ADDR [LOGICAL8], INTEGER);
LSPEC OUT.BIN (LOGICAL32, INTEGER);
LSPEC OUT.REC ();
LSPEC OUT.BACKSPACE (INTEGER);
PSPEC BACKSPACE (INTEGER, INTEGER);
PSPEC LIB04.LAST.CH () / INTEGER;
LSPEC BACKREC ();
**IN -1
@END



@TITLE LIB04.1(2F,11)

@COL 1S-2T-3T-4R-5T-6T-7R-8T-9T-10R-11F
@COL 12R-13R

@ROW 3-12
@ROW 6-13

@FLOW 1-2AT END-3NO-4-2-12
@FLOW 3YES-5NO-6SEPARATE-7-2
@FLOW 5YES-13-11
@FLOW 6-8-2
@FLOW 8END OF SECTION-9CHAR REQ-10-11
@FLOW 9-8

@BOX 1.0
IN CH () CHARACTER
@BOX 2.0
AT END OF AVAILABLE INPUT?
@BOX 3.0
AT END OF RECORD
@BOX 4.0
SET POINTERS TO NEXT BYTE POSITION
@BOX 5.0
IS RECORD SEPARATOR
CHARACTER REQUIRED?
@BOX 6.0
SEPARATE RECORDS?
@BOX 7.0
ENTER TRAP (6, 2)
ATTEMPT TO READ BEYOND END OF RECORD
@BOX 8.0
MOVE TO NEXT RECORD
@BOX 9.0
IS FILE SEPARATOR
CHARACTER REQUIRED?
@BOX 10.0
RETURN FILE SEPARATOR CHARACTER
@BOX 11.0
END
@BOX 12.0
GET NEXT CHARACTER
AND EXIT
@BOX 13.0
RETURN RECORD SEPARATOR CHARACTER
@BOX 1.1
PROC IN.CH;
SELECT INPUT^;
@BOX 2.1
IF PTR < PTR.END
@BOX 3.1
0 => PTR;
IF PTR.END +> PTR.START = REC.END
@BOX 4.1
SET.BPOS (INPUT, PTR.START);
@BOX 5.1
IF PTR.END >= 0 AND
   MODE & REC.SEP /= 0
@BOX 6.1
IF MODE & SEPARATE.RECORDS = 0
@BOX 7.1
ENTER.TRAP (6, 2);
@BOX 8.1
IF IN.REC () >= 0
@BOX 9.1
IF MODE & FILE.SEP = 0
@BOX 10.1
%1C => IN.CH;
@BOX 11.1
END
@BOX 12.1
BYTE.PTR^ [PTR] => IN.CH;
1 +> PTR;
EXIT;
@BOX 13.1
%1E => IN.CH;
-1 => PTR.END -> PTR.START;
@END
@TITLE LIB04.2(2F,11)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
NEXT CH () CHARACTER
@BOX 2.0
READ NEXT CHARACTER
@BOX 3.0
IN BACKSPACE
@BOX 4.0
END
@BOX 1.1
PROC NEXT.CH;
@BOX 2.1
IN.CH () => NEXT.CH;
@BOX 3.1
IN.BACKSPACE (1);
@BOX 4.1
END
@END
@TITLE LIB04.3(2F,11)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX1.0
IN BACKSPACE (COUNT)
@BOX 2.0
BACKSPACE (INPUT, COUNT)
@BOX 3.0
END
@BOX 1.1
PROC IN.BACKSPACE (COUNT);
@BOX 2.1
SELECT INPUT^;
IF PTR.START > REC.END THEN
   SET.IREC (PREV.REC);
   SET.BPOS (INPUT, REC.END);
FI
BACKSPACE (I.STREAM [CURRENT.IN], COUNT);
@BOX 3.1
END
@END
@TITLE LIB04.4(2F,11)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
IN LINE (BUFFER) CHAR COUNT
@BOX 2.0
COPY CHARACTERS INTO BUFFER UNTIL
A NEWLINE OR NEWPAGE IS COPIED
@BOX 3.0
SET CHAR COUNT
@BOX 4.0
END
@BOX 1.1
PROC IN.LINE (BUFFER);
INTEGER I;
@BOX 2.1
-1 => I;
WHILE IN.CH () => BUFFER^ [1 +> I] /= "$L" /= "$P" DO OD
@BOX 3.1
I => IN.LINE;
@BOX 4.1
END
@END
@TITLE LIB04.5(2F,11)
@COL 1S-2T-3R-4F
@FLOW 1-2NO-3-4
@FLOW 2YES-4
@BOX 1.0
SKIP LINE
@BOX 2.0
NEW LINE OR NEW PAGE
CHARACTER JUST READ?
@BOX 3.0
SKIP TO NEXT NEW LINE
OR NEW PAGE CHARACTER
@BOX 4.0
END
@BOX 1.1
PROC SKIP.LINE;
INTEGER CHAR;
@BOX 2.1
SELECT INPUT^;
IF PTR >= 1 AND
   BYTE.PTR^ [PTR - 1] => CHAR = "$L" OR CHAR = "$P"
@BOX 3.1
WHILE IN.CH () /= "$L" /= "$P" DO OD
@BOX 4.1
END
@END
@TITLE LIB04.6(2F,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
IN BIN (SIZE) BIN
@BOX 2.0
GET BINARY DATA OF
REQUIRED SIZE
@BOX 3.0
END
@BOX 1.1
PROC IN.BIN (S);
INTEGER I;
SELECT INPUT^;
@BOX 2.1
0 => IN.BIN => I;
IF PTR + S =< PTR.END THEN
   FOR S DO
      BYTE.PTR^ [PTR] <<- I !> IN.BIN;
      1 +> PTR;
      8 +> I;
   OD
ELSE
   FOR S DO
      IN.CH () <<- I !> IN.BIN;
      8 +> I;
   OD
FI
@BOX 3.1
END
@END
@TITLE LIB04.7(2F,11)

@COL 1S-2T-3R-4N-10R-5F
@COL 6T-7R-8R-9N

@ROW 3-6
@ROW 4-9

@FLOW 1-2NO-3-4-10-5
@FLOW 2YES-6NO-7-4
@FLOW 6YES-8-9-4

@BOX 1.0
IN REC () SIZE
@BOX 2.0
AT END OF SECTION?
@BOX 3.0
MOVE TO NEXT RECORD
IN STREAM
@BOX 5.0
END
@BOX 6.0
SEPARATE SECTIONS REQUIRED?
@BOX 7.0
BREAK INPUT
@BOX 8.0
ENTER TRAP (6, 1)
INPUT ENDED
@BOX 10.0
RETURN SIZE OF RECORD
@BOX 1.1
PROC IN.REC;
SELECT INPUT^;
@BOX 2.1
REC.START => PREV.REC;
IF REC.END - REC.START =< 3
   OR HDR = 1
@BOX 3.1
REC.END => REC.START;
4 +> REC.END;
SET.BPOS (INPUT, REC.START);
IN.BIN (4) +> REC.END;
SET.BPOS (INPUT, REC.START + 4);
@BOX 5.1
END
@BOX 6.1
IF MODE & SEPARATE.SECTIONS /= 0 OR
   DOC.TYPE =< 1
@BOX 7.1
IF MODE & DIRECT.ACCESS /= 0 THEN
   BREAK.OUTPUT (CURRENT.IN);
ELSE
   BREAK.INPUT (-1);
FI
@BOX 8.1
ENTER.TRAP (6, 1);
@BOX 10.1
REC.END - REC.START - 4 => IN.REC;
@END
@TITLE LIB04.8(2F,11)

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

@ROW 3-8

@FLOW 1-2AT END-3NO-4-2-8-9
@FLOW 3YES-5NO-6-2
@FLOW 5YES-7-2

@BOX 1.0
OUT CH (CHARACTER)
@BOX 2.0
AT END OF AVAILABLE INPUT SPACE?
@BOX 3.0
AT END OF SECTION?
@BOX 4.0
MOVE POINTERS TO NEXT BUFFER
@BOX 5.0
SHORT MESSAGES?
@BOX 6.0
ENTER TRAP (6, 3)
OUTPUT LIMIT EXCEEDED
@BOX 7.0
BREAK OUTPUT
@BOX 8.0
COPY CHARACTER
@BOX 9.0
END
@BOX 1.1
PROC OUT.CH (CHAR);
SELECT OUTPUT^;
@BOX 2.1
IF PTR < PTR.END
@BOX 3.1
PTR.END +> PTR.START;
0 => PTR => PTR.END;
IF PTR.START = REC.END
@BOX 4.1
SET.BPOS (OUTPUT, PTR.START);
@BOX 5.1
IF MODE & SHORT.MSSGE /= 0
@BOX 6.1
ENTER.TRAP (6, 3);
@BOX 7.1
BREAK.OUTPUT (-1);
@BOX 8.1
CHAR => BYTE.PTR^ [PTR];
1 +> PTR;
@BOX 9.1
END
@END


@TITLE LIB04.9(2F,11)
@COL 1S-4T-5T-6R-7R-8T-9T-10R-11F
@COL 13R-14R
@ROW 13-6
@ROW 14-10
@FLOW 1-4NO-5NO-6-7-8NO-9NO-10-11
@FLOW 4YES-7
@FLOW 5YES-13-7
@FLOW 8YES-11
@FLOW 9YES-14-11
@BOX 1.0
OUT LINE (BUFFER, CARRIAGE CONTROL)
@BOX 4.0
NO CARRIAGE CONTROL
BEFORE OUTPUT?
@BOX 5.0
LINE FEEDS REQUIRED?
@BOX 6.0
OUTPUT REQUIRED
CHARACTER
@BOX 7.0
OUTPUT BUFFER
@BOX 8.0
NO CARRIAGE CONTROL
AFTER OUTPUT?
@BOX 9.0
NEW PAGE REQUIRED?
@BOX 10.0
OUTPUT LINEFEEDS
@BOX 11.0
END
@BOX 13.0
OUTPUT LINEFEEDS
@BOX 14.0
OUTPUT NEWPAGE
@BOX 1.1
PROC OUT.LINE (BUFFER, CRRGE.CNTRL);
INTEGER I;
@BOX 4.1
IF CRRGE.CNTRL > 64
@BOX 5.1
IF CRRGE.CNTRL > 0 < 64
@BOX 6.1
IF CRRGE.CNTRL = 0 THEN
   OUT.CH (CRRGE.RETURN);
ELSE
   OUT.CH ("$P");
FI
@BOX 7.1
FOR I < SIZE (BUFFER) DO
   OUT.CH (BUFFER^ [I]);
OD
@BOX 8.1
IF CRRGE.CNTRL < 65
@BOX 9.1
IF CRRGE.CNTRL > 127
@BOX 10.1
FOR CRRGE.CNTRL - 64 DO
   OUT.CH ("$L");
OD
@BOX 11.1
END
@BOX 13.1
FOR CRRGE.CNTRL DO
   OUT.CH ("$L");
OD
@BOX 14.1
OUT.CH ("$P");
@END



@TITLE LIB04.10(2F,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
OUT BIN (VALUE, SIZE)
@BOX 2.0
COPY VALUE TO OUTPUT
@BOX 3.0
END
@BOX 1.1
PROC OUT.BIN (VALUE, S);
SELECT OUTPUT^;
@BOX 2.1
IF PTR.END - PTR >= S THEN
   FOR S DO
      VALUE => BYTE.PTR^ [PTR];
      1 +> PTR;
      VALUE ->> 8 => VALUE;
   OD
ELSE
   FOR S DO
      OUT.CH (VALUE);
      VALUE ->> 8 => VALUE;
   OD
FI
@BOX 3.1
END
@END

@TITLE LIB04.11(2F,11)

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

@FLOW 1-2-3-4

@BOX 1.0
OUT REC (SIZE)
@BOX 2.0
UPDATE RECORD SIZE
@BOX 3.0
SET POINTER TO NEXT RECORD
@BOX 4.0
END
@BOX 1.1
PROC OUT.REC;
INTEGER32 S;
SELECT OUTPUT^;
@BOX 2.1
PTR.START + PTR - REC.START - 4 => S;
REC.START => PREV.REC + S + 4 => REC.END;
SET.BPOS (OUTPUT, REC.START);
OUT.BIN (S, 4);
IF REC.END > SECTION.SIZE THEN
   REC.END => SECTION.SIZE;
FI
@BOX 3.1
IF HDR /= 0 THEN
   REC.END + 4 => MAX.SECTION.SIZE;
FI
REC.END => REC.START;
MAX.SECTION.SIZE => REC.END;
SET.BPOS (OUTPUT, REC.START + 4);
@BOX 4.1
END
@END

@TITLE LIB04.12(2F,11)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
OUT BACKSPACE (COUNT)
@BOX 2.0
BACKSPACE (OUTPUT, COUNT)
@BOX 3.0
END
@BOX 1.1
PROC OUT.BACKSPACE (COUNT);
@BOX 2.1
BACKSPACE (O.STREAM [CURRENT.OUT], COUNT);
@BOX 3.1
END
@END
@TITLE LIB04.13(2F,11)
@COL 1S-3T-8R-5T-6T-7R-9T-2R-11F
@COL 4R
@ROW 5-4
@FLOW 1-3NO-8-5NO-6NO-7-9NO-2-11
@FLOW 3YES-4-11
@FLOW 5YES-9
@FLOW 6YES-11
@FLOW 9YES-5
@BOX 1.0
BACKSPACE (STREAM, COUNT)
@BOX 2.0
ADVANCE POINTER BY
ONE CHARACTER
@BOX 3.0
IS COUNT POSITIVE?
@BOX 4.0
COMPUTE NEW POSITION
IN STREAM
@BOX 5.0
IS PREVIOUS CHARACTER POSITION
WITHIN CURRENT BLOCK?
@BOX 6.0
AT START OF RECORD?
@BOX 7.0
GET REQUIRED BLOCK
@BOX 8.0
BACKSPACE ONE CHARACTER
@BOX 9.0
NOT START OF LINE / PAGE CONDITION?
@BOX 11.0
END
@BOX 1.1
PROC BACKSPACE (STREAM, COUNT);
INTEGER32 POS, R;
SELECT IO.CONTROL [STREAM];
REC.START + 4 => R;
@BOX 2.1
SET.BPOS (^IO.CONTROL [STREAM], PTR.START + PTR + 1);
@BOX 3.1
IF COUNT >= 0
@BOX 4.1
IF PTR.START + PTR - COUNT => POS < R THEN
   R => POS;
FI
SET.BPOS (^IO.CONTROL [STREAM], POS);
@BOX 5.1
IF 1 -> PTR >= 0
@BOX 6.1
IF 1 +> PTR + PTR.START = R
@BOX 7.1
SET.BPOS (^IO.CONTROL [STREAM], PTR.START - 1);
@BOX 8.1
BACKSPACE (STREAM, 1);
@BOX 9.1
IF BYTE.PTR^ [PTR] /= "$L" /= "$P"
@BOX 11.1
END
@END
@TITLE LIB04.14(2F,11)

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

@ROW 3-5

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

@BOX 1.0
LAST CH () CHAR
@BOX 2.0
AT START OF SECTION?
@BOX 3.0
RETURN LAST CHARACTER OUTPUT
@BOX 4.0
END
@BOX 5.0
RETURN NEGATIVE VALUE
@BOX 1.1
PROC LIB04.LAST.CH;
@BOX 2.1
SELECT OUTPUT^;
IF PTR + PTR.START =< REC.START + 4
@BOX 3.1
BYTE.PTR^ [PTR - 1] => LIB04.LAST.CH;
@BOX 4.1
END
@BOX 5.1
-1 => LIB04.LAST.CH;
@END


@TITLE LIB04.15(2F,11)

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

@BOX 1.0
BACKREC
@BOX 2.0
POSITION OF PREVIOUS
RECORD KNOWN?
@BOX 3.0
SEARCH FOR RECORD
FROM START OF STREAM
@BOX 4.0
SET POINTERS TO
PREVIOUS RECORD
@BOX 5.0
END
@BOX 1.1
PROC BACKREC;
INTEGER32 TARGET.REC;
SELECT INPUT^;
@BOX 2.1
IF PREV.REC /= REC.START
@BOX 3.1
REC.START => TARGET.REC;
0 => REC.START => PREV.REC;
WHILE REC.START /= TARGET.REC DO
   SET.BPOS (INPUT, REC.START => PREV.REC);
   IN.BIN (4) + 4 +> REC.START;
OD
@BOX 4.1
SET.IREC (PREV.REC);
@BOX 5.1
END
@END






