@X @~
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H             LIB061
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL
~
~
                                                           ISSUE 11~
~V9 -1
~P
~V9 1
~YLIB061
~M~OLIB IMPLEMENTATION DESCRIPTION
~
~M~OSection 6 Version 1
~S1~OSection 6.1 Advanced Input / Output Operations
~S1~O1. General Description
~BThis module provides a set of input / output functions operating
on character streams, as described in Chapter 4 of the MUSS User
Manual.
~S1~O2. Interface
~
Library procedures~
   IN.I () INTEGER~
   IN.OCT () OCTAL NUMBER~
   IN.HEX () HEXADECIMAL NUMBER~
   IN.C.LIT () CHARACTER LITERAL~
   IN.NAME () NAME~
   IN.C.STR (BUFFER) SIZE~
   IN.STR (BUFFER) SIZE)~
   SPACES (NUMBER)~
   NEWLINES (NUMBER)~
   CAPTION (TEXT)~
   OUT.I (INTEGER32, FIELD WIDTH)~
   OUT.OCT (NUMBER)~
   OUT.HEX (NUMBER,~K NUMBER.OF.DIGITS)~K~
   OUT.TIME ()~
   OUT.DATE ()~
   OUT.TD (TIME / DATE)~
   OUT.LINE.NO (PAGE / LINE)~
   OUT.NAME (NAME)~
   OUT.FN (FILE NAME)~
   OUT.STACK (START, FINISH)~
   ECHO.LINE ()~
Configuration Parameters~
   BITS.PER.WORD~
   BYTES.PER.WORD~
~S11) BITS.PER.WORD
~BThe size of a machine word in bits.
~S12) BYTES.PER.WORD
~BThe number of bytes in each word.
~S1~O3. Implementation
~S1~O3.1 Outline of Operation
~BNone
~S1~O3.2 Data Structures
~BNone
~S1~O3.3 Special Notes
~BNone
~
~Y
~V9 -1
~P
~V9 -1
~D15
~HFLOWCHARTS
~
~
~H                LIB061
~V9 -1
~F
@TITLE LIB06(1,11)
@COL 1S-2R-3R-4R-5R-6F
@FLOW 1-2-3-4-5-6
@BOX 1.0
ADVANCED INPUT / OUTPUT PROCEDURES
@BOX 4.0
SUB-SECTIONS IN MODULE:
   1 INPUT PROCEDURES
   2 OUTPUT PROCEDURES
@BOX 6.0
END
@BOX 1.1
#LIB06/1
MODULE (IN.I, IN.OCT, IN.HEX, IN.C.LIT, IN.NAME,
   IN.C.STR, IN.STR, spACES, nEWlINES, capTION,
   OUT.I, OUT.OCT, OUT.HEX, OUT.TIME, OUT.DATE,
   OUT.TD, OUT.LINE.NO, OUT.NAME, OUT.FN, OUT.STACK, ECHO.LINE);
@BOX 3.1
LITERAL SP = %20;
@BOX 4.1
*CODE 1;
:: INPUT PROCEDURES
#LIB06.1
:: OUTPUT PROCEDURES
#LIB06.2
@BOX 6.1
*END
@END
@TITLE LIB06/1(1,11)
@COL 1S-2R-3R-4R
@FLOW 1-2-3-4
@BOX 1.0
OTHER MODULES REFERENCED
@BOX 4.0
LIB04 BASIC I/O OPERATIONS
@BOX 1.1
::EXTERNAL ENVIRONMENT
@BOX 2.1
IMPORT LITERAL BITS.PER.WORD, STORE.SIZE;
IMPORT LITERAL BYTES.PER.WORD, HX.PER.ADDR, HX.PER.INTEGER;
@BOX 4.1
PSPEC LIB04.LAST.CH () / INTEGER;
PSPEC PROCESS.NAME (ADDR [LOGICAL8]) / ADDR [LOGICAL8];
LSPEC TIME.AND.DATE ();
PSPEC IN.CH () / INTEGER;
PSPEC IN.BACKSPACE (INTEGER);
PSPEC OUT.CH (INTEGER);
PSPEC O.MODE () / INTEGER32;
PSPEC I.MODE () / INTEGER32;
PSPEC I.POS () / INTEGER32;
PSPEC ENTER.TRAP (INTEGER, INTEGER);
PSPEC BREAK.OUTPUT (INTEGER);
ADDR PW1, PW2;
LOGICAL64 PWW1, PWW2;
@END
@TITLE LIB06.1(1,11)
@COL 1S-2R
@FLOW 1-2
@BOX 1.0
INPUT OPERATIONS
@BOX 2.0
PROCEDURES IN SUB-SECTION:
   1 IN I
   2 IN OCT
   3 IN HEX
   4 IN C LIT
   5 IN NAME
   6 IN C STR
   7 IN STR
   8 IN HEX PAIR
@BOX 1.1
:: INPUT OPERATIONS
@BOX 2.1
LSPEC IN.I () / ADDR;
LSPEC IN.OCT () / INTEGER;
LSPEC IN.HEX () / LOGICAL64;
LSPEC IN.CLIT () / LOGICAL64;
LSPEC IN.NAME () / LOGICAL64;
LSPEC IN.C.STR (ADDR [LOGICAL8]) / INTEGER;
LSPEC IN.STR (ADDR [LOGICAL8]) / INTEGER;
PSPEC IN.HEX.PAIR () / INTEGER;
   #LIB06.1.1
   #LIB06.1.2
   #LIB06.1.3
   #LIB06.1.4
   #LIB06.1.5
   #LIB06.1.6
   #LIB06.1.7
   #LIB06.1.8
@END
@TITLE LIB06.1.1(1,9)
@COL 1S-2R-3R-4T-5R-6R-7F
@COL 8R
@ROW 5-8
@FLOW 1-2-3-4NO-5-6-7
@FLOW 4YES-8-6
@BOX 1.0
IN I () ADDR
@BOX 2.0
IGNORE LEADING BLANKS
@BOX 3.0
NOTE SIGN OF RESULT
@BOX 4.0
IS FIRST CHARACTER AFTER
SIGN NON - NUMERIC?
@BOX 5.0
READ REMAINING DIGITS IN NUMBER
@BOX 6.0
RETURN NUMBER WITH CORRECT SIGN
@BOX 7.0
END
@BOX 8.0
ENTER TRAP (6, 8)
ILLEGAL SYMBOL IN NUMBER
@BOX 1.1
PROC IN.I;
INTEGER SIGN, CH;
ADDR ANS;
@BOX 2.1
WHILE IN.CH () => CH =< " " DO OD
@BOX 3.1
IF CH = "-" THEN
   1 => SIGN;
   IN.CH () => CH;
ELSE
   0 => SIGN;
   IF CH = "+" THEN
      IN.CH () => CH;
   FI
FI
@BOX 4.1
IF CH - "0" => ANS < 0
   OR ANS > 9
@BOX 5.1
WHILE IN.CH () - "0" => CH >= 0 =< 9 DO
   ANS * 10 + CH => ANS;
OD
@BOX 6.1
IN.BACKSPACE (1);
IF SIGN = 0 THEN
   ANS => IN.I;
ELSE
   0 - ANS => IN.I;
FI
@BOX 7.1
END
@BOX 8.1
ENTER.TRAP (6, 8);
@END
@TITLE LIB06.1.2(1,6)
@COL 1S-2R-3T-4R-5R-6F
@COL 7R
@ROW 4-7
@FLOW 1-2-3NO-4-5-6
@FLOW 3YES-7-5
@BOX 1.0
IN OCT () INTEGER
@BOX 2.0
IGNORE LEADING BLANKS
@BOX 3.0
IS NEXT CHARACTER
NOT AN OCTAL DIGIT?
@BOX 4.0
READ REMAINING DIGITS IN NUMBER
@BOX 5.0
RETURN OCTAL NUMBER AS RESULT
@BOX 6.0
END
@BOX 7.0
ENTER TRAP (6, 8)
ILLEGAL SYMBOL IN NUMBER
@BOX 1.1
PROC IN.OCT;
INTEGER CH, ANS;
@BOX 2.1
WHILE IN.CH () => CH =< " " DO OD
@BOX 3.1
IF CH - "0" => ANS < 0
   OR ANS > 7
@BOX 4.1
WHILE IN.CH () - "0" => CH >= 0 =< 7 DO
   ANS <<- 3 + CH => ANS;
OD
@BOX 5.1
IN.BACKSPACE (1);
ANS => IN.OCT;
@BOX 6.1
END
@BOX 7.1
ENTER.TRAP (6, 8);
@END
@TITLE LIB06.1.3(1,6)
@COL 2N-15N-3R-4T-5R-16N
@COL 1S-6R-7T-8N-9T-10T-11R-17N-12R-13F
@COL 14R-18N
@ROW 2-8-14
@ROW 15-9
@ROW 16-17-18
@FLOW 1-6-7NO-8-9NO-10NO-11-8
@FLOW 7YES-14-18-17-12-13
@FLOW 9YES-15-3-4NO-5-16-17
@FLOW 4YES-2-8
@FLOW 10YES-17
@BOX 1.0
IN HEX () HEXADECIMAL NUMBER
@BOX 3.0
REPEAT PREVIOUS HEX CHARACTER
REQUIRED NUMBER OF TIMES
@BOX 4.0
IS NEXT CHARACTER ")"?
@BOX 5.0
ENTER TRAP (6, 8)
ILLEGAL SYMBOL IN NUMBER
@BOX 6.0
IGNORE LEADING CONTROL CHARACTERS
@BOX 7.0
FIRST CHARACTER NOT HEXADECIMAL?
@BOX 9.0
IS NEXT CHARACTER "("?
@BOX 10.0
NEXT CHARACTER NOT HEXADECIMAL?
@BOX 11.0
EVALUATE PARTIAL ANSWER
@BOX 12.0
RETURN HEX NUMBER
AS RESULT
@BOX 13.0
END
@BOX 14.0
ENTER TRAP (6, 8)
ILLEGAL SYMBOL IN NUMBER
@BOX 1.1
PROC IN.HEX;
INTEGER CH, COUNT;
LOGICAL64 ANS;
@BOX 3.1
ANS & %F => CH;
IN.I () => COUNT;
FOR COUNT - 1 DO
   ANS <<- 4 ! CH => ANS;
OD
@BOX 4.1
IF IN.CH () = ")"
@BOX 5.1
ENTER.TRAP (6, 8);
@BOX 6.1
WHILE IN.CH () => CH =< " " DO OD;
@BOX 7.1
IF CH >= "0" =< "9" THEN
   "0" -> CH;
ELSE
   IF CH >= "A" =< "F" THEN
      "A" - 10 -> CH;
   FI
FI
CH => ANS;
IF CH > 15
@BOX 9.1
IF IN.CH () => CH = "("
@BOX 10.1
IF CH >= "0" =< "9" THEN
   "0" -> CH;
ELSE
   IF CH >= "A" =< "F" THEN
      "A" - 10 -> CH;
   ELSE
      16 => CH;
   FI
FI
IF CH > 15
@BOX 11.1
ANS <<- 4 ! CH => ANS;
@BOX 12.1
IN.BACKSPACE (1);
ANS => IN.HEX;
@BOX 13.1
END
@BOX 14.1
ENTER.TRAP (6, 8);
@END
@TITLE LIB06.1.4(1,6)
@COL 1S-2R-3T-4T-5T-6T-7R-8R-9F
@COL 10R
@ROW 4-10
@FLOW 1-2-3NO-4OTHER-5NO-6OK-7-4
@FLOW 3YES-10-8-9
@FLOW 4QUOTE-8
@FLOW 5YES-7
@FLOW 6FAULTY-8
@BOX 1.0
IN C LIT () CHARACTER LITERAL
@BOX 2.0
SET RESULT TO ZERO
@BOX 3.0
IS NEXT CHARACTER
NOT QUOTE SYMBOL?
@BOX 4.0
READ CHARACTER OF LITERAL
@BOX 5.0
CHARACTER NOT EXCLAMATION MARK?
@BOX 6.0
IN HEX PAIR
[LIB06.1.8]
@BOX 7.0
INCLUDE CHARACTER IN LITERAL
@BOX 8.0
RETURN CHARACTER LITERAL
AS RESULT
@BOX 9.0
END
@BOX 10.0
ENTER TRAP (6, 9)
ILLEGAL DELIMITER
@BOX 1.1
PROC IN.C.LIT;
INTEGER CH;
LOGICAL64 LIT;
@BOX 2.1
0 => LIT;
@BOX 3.1
IF IN.CH () /= '"
@BOX 4.1
IF IN.CH () => CH = '"
@BOX 5.1
IF CH /= "!"
@BOX 6.1
IF IN.HEX.PAIR () => CH < 0
@BOX 7.1
LIT <<- 8 ! CH => LIT;
@BOX 8.1
LIT => IN.C.LIT;
@BOX 9.1
END
@BOX 10.1
IN.BACKSPACE (1);
ENTER.TRAP (6, 9);
@END
@TITLE LIB06.1.5(1,6)
@COL 1S-2R-3R-4T-5T-6T-7R-8R-9F
@FLOW 1-2-3-4OTHER-5NO-6OK-7-4TERMINATOR-8-9
@FLOW 5YES-7
@FLOW 6FAULTY-8
@BOX 1.0
IN NAME () NAME
@BOX 2.0
SET RESULT TO ZERO
@BOX 3.0
IGNORE LEADING BLANKS
@BOX 4.0
READ CHARACTER OF NAME
@BOX 5.0
CHARACTER NOT EXCLAMATION MARK?
@BOX 6.0
IN HEX PAIR
[LIB06.1.8]
@BOX 7.0
INCLUDE CHARACTER IN NAME
@BOX 8.0
RETURN NAME AS RESULT
@BOX 9.0
END
@BOX 1.1
PROC IN.NAME;
INTEGER CH;
LOGICAL64 NAME;
@BOX 2.1
0 => NAME;
@BOX 3.1
WHILE IN.CH () =< " " DO OD
IN.BACKSPACE (1);
@BOX 4.1
IF IN.CH () => CH = " "
   OR CH = "$L" OR CH = "$P"
@BOX 5.1
IF CH /= "!"
@BOX 6.1
IF IN.HEX.PAIR () => CH < 0
@BOX 7.1
NAME <<- 8 ! CH => NAME;
@BOX 8.1
IN.BACKSPACE (1);
NAME => IN.NAME;
@BOX 9.1
END
@END
@TITLE LIB06.1.6(1,6)
@COL 1S-2R-3T-4T-5T-6T-7T-8R-9R-10F
@COL 11R
@ROW 4-11
@FLOW 1-2-3NO-4OTHER-5NO-6NO-7OK-8-4
@FLOW 3YES-11-9-10
@FLOW 4QUOTE-9
@FLOW 5YES-4
@FLOW 6YES-8
@FLOW 7FAULTY-9
@BOX 1.0
IN C STR (BUFFER) SIZE
@BOX 2.0
FIND SIZE OF BUFFER
@BOX 3.0
IS NEXT CHARACTER
NOT QUOTE SYMBOL?
@BOX 4.0
READ CHARACTER
@BOX 5.0
BUFFER FULL?
@BOX 6.0
CHARACTER NOT EXCLAMATION MARK?
@BOX 7.0
IN HEX PAIR
[LIB06.1.8]
@BOX 8.0
COPY CHARACTER TO BUFFER
@BOX 9.0
RETURN SIZE OF
INFORMATION IN BUFFER
@BOX 10.0
END
@BOX 11.0
ENTER TRAP (6, 9)
ILLEGAL DELIMITER
@BOX 1.1
PROC IN.C.STR (BUFFER);
INTEGER CH, LIMIT, COUNT;
@BOX 2.1
0 => COUNT;
SIZE (BUFFER) => LIMIT;
@BOX 3.1
IF IN.CH () /= '"
@BOX 4.1
IF IN.CH () => CH = '"
@BOX 5.1
IF COUNT = LIMIT
@BOX 6.1
IF CH /= "!"
@BOX 7.1
IF IN.HEX.PAIR () => CH < 0
@BOX 8.1
CH => BUFFER^ [COUNT];
1 +> COUNT;
@BOX 9.1
COUNT => IN.C.STR;
@BOX 10.1
END
@BOX 11.1
IN.BACKSPACE (1);
ENTER.TRAP (6, 9);
@END
@TITLE LIB06.1.7(1,6)
@COL 1S-2R-3R-4T-5T-6T-7T-8R-9R-10F
@FLOW 1-2-3-4OTHER-5NO-6NO-7OK-8-4
@FLOW 4TERMINATOR-9-10
@FLOW 5YES-4
@FLOW 6YES-8
@FLOW 7FAULTY-9
@BOX 1.0
IN STR (BUFFER) SIZE
@BOX 2.0
FIND SIZE OF BUFFER
@BOX 3.0
IGNORE LEADING BLANKS
@BOX 4.0
READ CHARACTER
@BOX 5.0
BUFFER FULL?
@BOX 6.0
CHARACTER NOT EXCLAMATION MARK?
@BOX 7.0
IN HEX PAIR
[LIB06.1.8]
@BOX 8.0
COPY CHARACTER TO BUFFER
@BOX 9.0
RETURN SIZE OF
INFORMATION IN BUFFER
@BOX 10.0
END
@BOX 1.1
PROC IN.STR (BUFFER);
INTEGER CH, LIMIT, COUNT;
@BOX 2.1
0 => COUNT;
SIZE (BUFFER) => LIMIT;
@BOX 3.1
WHILE IN.CH () =< " " DO OD
IN.BACKSPACE (1);
@BOX 4.1
IF IN.CH () => CH = " "
   OR CH = "$L" OR CH = "$P"
@BOX 5.1
IF COUNT = LIMIT
@BOX 6.1
IF CH /= "!"
@BOX 7.1
IF IN.HEX.PAIR () => CH < 0
@BOX 8.1
CH => BUFFER^ [COUNT];
1 +> COUNT;
@BOX 9.1
IN.BACKSPACE (1);
COUNT => IN.STR;
@BOX 10.1
END
@END
@TITLE LIB06.1.8(1,6)
@COL 1S-2R-3T-4T-5R-6R-7F
@COL 8R
@ROW 4-8
@FLOW 1-2-3NO-4NO-5-6-7
@FLOW 3YES-8-6
@FLOW 4YES-6
@BOX 1.0
IN HEX PAIR () HEX VALUE
@BOX 2.0
READ NEXT TWO CHARACTERS
@BOX 3.0
NOT HEX DIGITS?
@BOX 4.0
IS NEXT SYMBOL "!"?
@BOX 5.0
ENTER TRAP (6, 9)
ILLEGAL DELIMITER
@BOX 6.0
RETURN HEX VALUE
(NEGATIVE IF FAULTY)
@BOX 7.0
END
@BOX 8.0
ENTER TRAP (6, 8)
ILLEGAL SYMBOL
IN NUMBER
@BOX 1.1
PROC IN.HEX.PAIR;
INTEGER CH, HEX;
@BOX 2.1
0 => HEX;
FOR 2 DO
   IF IN.CH () => CH >= "0" =< "9" THEN
      HEX <<- 4 + CH - "0" => HEX;
   ELSE
      IF CH >= "A" =< "F" THEN
         HEX <<- 4 + CH - "A" + 10 => HEX;
      ELSE
         -1 => HEX;
      FI
   FI
OD
@BOX 3.1
IF HEX < 0
@BOX 4.1
IF IN.CH () = "!"
@BOX 5.1
-1 => HEX;
ENTER.TRAP (6, 9);
@BOX 6.1
HEX => IN.HEX.PAIR;
@BOX 7.1
END
@BOX 8.1
ENTER.TRAP (6, 8);
@END
@TITLE LIB06.2(1,11)
@COL 1S-2R
@FLOW 1-2
@BOX 1.0
OUTPUT OPERATIONS
@BOX 2.0
PROCEDURES IN SUB-SECTION:
   1 SPACES
   2 NEWLINES
   3 CAPTION
   4 OUT I
   5 OUT OCT
   6 OUT HEX
   7 OUT TIME
   8 OUT DATE
   9 OUT TD
   10 OUT LINE
   11 OUT NAME
   12 OUT FN
   13 OUT STACK
   14 ECHO LINE
   15 OUT II
@BOX 1.1
:: OUTPUT OPERATIONS
@BOX 2.1
LSPEC SPACES (INTEGER);::SUBLIB PROC
LSPEC NEWLINES (INTEGER);::SUBLIB PROC
LSPEC CAPTION (ADDR [LOGICAL8]);::SUBLIB PROC
LSPEC OUT.I (INTEGER32, INTEGER);::SUBLIB PROC
LSPEC OUT.OCT (INTEGER);
LSPEC OUT.HEX (LOGICAL32, INTEGER);
LSPEC OUT.TIME ();
LSPEC OUT.DATE ();
LSPEC OUT.TD (LOGICAL64, INTEGER);
LSPEC OUT.LINE.NO (INTEGER32);::SUBLIB PROC
LSPEC OUT.NAME (LOGICAL64);::SUBLIB PROC
LSPEC OUT.FN (ADDR [LOGICAL8]);
LSPEC OUT.STACK (ADDR, ADDR);
LSPEC ECHO.LINE ();
*CODE 27;
   #LIB06.2.1
   #LIB06.2.2
   #LIB06.2.3
   #LIB06.2.15
*CODE 1;
   #LIB06.2.5
   #LIB06.2.6
   #LIB06.2.7
   #LIB06.2.8
   #LIB06.2.9
*CODE 27;
   #LIB06.2.10
   #LIB06.2.11
*CODE 1;
   #LIB06.2.12
   #LIB06.2.13
   #LIB06.2.14
@END
@TITLE LIB06.2.1(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
SPACES (NO)
@BOX 2.0
OUTPUT REQUIRED NUMBER
OF SPACE CHARACTERS
@BOX 3.0
END
@BOX 1.1
PROC SPACES (NO);
@BOX 2.1
WHILE 1 -> NO >= 0 DO
   OUT.CH (" ");
OD
@BOX 3.1
END
@END
@TITLE LIB06.2.2(1,11)
@COL 1S-2T-3R-9R-4N-5F
@COL 6T-7R-8N
@ROW 3-6
@ROW 4-8
@FLOW 1-2NO-3-9-4-5
@FLOW 2YES-6NO-7-9
@FLOW 6YES-8-4
@BOX 1.0
NEWLINES (NUMBER)
@BOX 2.0
IS NUMBER ZERO?
@BOX 3.0
OUTPUT REQUIRED NUMBER
OF NEWLINE CHARACTERS
@BOX 5.0
END
@BOX 6.0
START OF SECTION?
@BOX 7.0
OUTPUT A NEWLINE CHARACTER
IF NECESSARY
@BOX 9.0
BREAK OUTPUT ON SHORT
MESSAGE STREAM
@BOX 1.1
PROC NEWLINES (NUMBER);
INTEGER LAST.CHAR;
@BOX 2.1
IF NUMBER = 0
@BOX 3.1
WHILE 1 -> NUMBER >= 0 DO
   OUT.CH ("$L");
OD
@BOX 5.1
END
@BOX 6.1
IF LIB04.LAST.CH () => LAST.CHAR < 0
@BOX 7.1
IF LAST.CHAR /= "$L" THEN
   OUT.CH ("$L");
FI
@BOX 9.1
IF O.MODE () & %100 /= 0 THEN
   BREAK.OUTPUT (-1);::MAINLIB CALL
FI
@END
@TITLE LIB06.2.3(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
CAPTION (STRING)
@BOX 2.0
OUTPUT CHARACTERS IN STRING
@BOX 3.0
END
@BOX 1.1
PROC CAPTION (STRING);
INTEGER LIMIT, I;
@BOX 2.1
SIZE (STRING) => LIMIT;
-1 => I;
WHILE 1 +> I /= LIMIT DO
   OUT.CH (STRING^ [I]);
OD
@BOX 3.1
END
@END
@TITLE LIB06.2.5(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
OUT OCT (NUMBER)
@BOX 2.0
OUTPUT DIGITS OF
OCTAL NUMBER
@BOX 3.0
END
@BOX 1.1
PROC OUT.OCT (NUMBER);
INTEGER COUNT;
@BOX 2.1
BITS.PER.WORD + 2 / 3 * 3 => COUNT;
WHILE 3 -> COUNT >= 0 DO
   OUT.CH (NUMBER ->> COUNT & 7 + "0");
OD
@BOX 3.1
END
@END
@TITLE LIB06.2.6(1,10)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
OUT HEX (NUMBER)
@BOX 2.0
OUTPUT DIGITS OF
HEXADECIMAL NUMBER
@BOX 3.0
END
@BOX 1.1
PROC OUT.HEX (NUMBER, NO.OF.DIGITS);
INTEGER CH;
@BOX 2.1
4 *> NO.OF.DIGITS;
WHILE 4 -> NO.OF.DIGITS >= 0 DO
   IF NO.OF.DIGITS /= 0 THEN
      NUMBER ->> NO.OF.DIGITS & %F => CH;
   ELSE
      NUMBER & %F => CH;
   FI
   IF CH > 9 THEN
      OUT.CH (CH + "A" - 10);
   ELSE
      OUT.CH (CH + "0");
   FI
OD
@BOX 3.1
END
@END
@TITLE LIB06.2.7(1,6)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
OUT TIME
@BOX 2.0
TIME AND DATE
@BOX 3.0
PRINT TIME
@BOX 4.0
END
@BOX 1.1
PROC OUT.TIME;
@BOX 2.1
TIME.AND.DATE ();
@BOX 3.1
OUT.TD (PWW1, 0);
@BOX 4.1
END
@END
@TITLE LIB06.2.8(1,6)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
OUT DATE
@BOX 2.0
TIME AND DATE
@BOX 3.0
PRINT DATE
@BOX 4.0
END
@BOX 1.1
PROC OUT.DATE;
@BOX 2.1
TIME.AND.DATE ();
@BOX 3.1
OUT.TD (PWW1, 1);
@BOX 4.1
END
@END
@TITLE LIB06.2.9(1,8)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
OUT TD (SECONDS, TIME / DATE)
@BOX 2.0
OUTPUT SECONDS AS TIME
OR DATE
@BOX 3.0
END
@BOX 1.1
PROC OUT.TD (SECS, TD);
INTEGER TEMP, DAY, MONTH, YEAR, I;
INTEGER32 SECONDS, TIME, DATE;
DATAVEC MONTHS (LOGICAL8)
   "JAN" "FEB" "MAR" "APR" "MAY" "JUN"
   "JUL" "AUG" "SEP" "OCT" "NOV" "DEC"
END
PSPEC OUT.TD.I (INTEGER);
PROC OUT.TD.I (NUM);
   OUT.CH (NUM / 10 + "0");
   OUT.CH (NUM / 10 * 10 -: NUM + "0");
END
@BOX 2.1
SECS => SECONDS ->> 7 / 675 => DATE;::EQUIVALENT TO: SECONDS / 24 / 60 / 60
DATE * 675 <<- 7 -: SECONDS => TIME;
IF TD = 0 THEN
   OUT.TD.I (TIME / 3600 => TEMP);
   OUT.CH (":");
   OUT.TD.I (TEMP * 3600 -> TIME / 60 => TEMP);
   OUT.CH (":");
   OUT.TD.I (TEMP * 60 -: TIME);
ELSE
   59 -> DATE * 4 - 1 => DATE;
   DATE / 1461 => YEAR;
   YEAR * 1461 -: DATE + 4 / 4 => DAY;
   DAY * 5 - 3 => TEMP / 153 => MONTH;
   MONTH * 153 -: TEMP + 5 / 5 => DAY;
   IF 3 +> MONTH > 12 THEN
      12 -> MONTH;
      1 +> YEAR;
   FI
   OUT.TD.I (DAY);
   OUT.CH ("-");
   MONTH - 1 * 3 => MONTH;
   FOR I < 3 DO
      OUT.CH (MONTHS [MONTH + I]);
   OD
   OUT.CH ("-");
   OUT.TD.I (YEAR);
FI
@BOX 3.1
END
@END
@TITLE LIB06.2.10(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
OUT LINE (PAGE / LINE)
@BOX 2.0
OUTPUT PAGE NUMBER
AND LINE NUMBER
@BOX 3.0
END
@BOX 1.1
PROC OUT.LINE.NO (PAGE.LINE);
INTEGER COUNT, LINE;
@BOX 2.1
PAGE.LINE & %FFFF => LINE;
3 => COUNT;
WHILE 10 /> LINE /= 0 DO
   1 -> COUNT;
OD
OUT.I (PAGE.LINE ->> 16, 4);
OUT.CH (".");
OUT.I (PAGE.LINE & %FFFF, 0);
SPACES (COUNT);
@BOX 3.1
END
@END
@TITLE LIB06.2.11(1,6)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
OUT NAME (NAME)
@BOX 2.0
COUNT LEADING NULLS IN NAME
AND OUTPUT REMAINING CHARACTERS
@BOX 3.0
PRINT SPACE FOR EACH
LEADING NULL
@BOX 4.0
END
@BOX 1.1
PROC OUT.NAME (NAME);
INTEGER COUNT, SPACE.COUNT, FLAG, CH;
@BOX 2.1
0 => SPACE.COUNT => FLAG;
64 => COUNT;
WHILE 8 -> COUNT >= 0 DO
   NAME ->> COUNT & %FF => CH;
   IF CH = 0 AND FLAG = 0 THEN
       1 +> SPACE.COUNT;
   ELSE
      OUT.CH (CH);
      1 => FLAG;
   FI
OD
@BOX 3.1
SPACES (SPACE.COUNT);
@BOX 4.1
END
@END
@TITLE LIB06.2.12(1,11)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
OUT FN (FILENAME)
@BOX 2.0
OUTPUT FILE NAME
OR <CFILE> IF ZERO
@BOX 3.0
OUTPUT TIME AND DATE
@BOX 4.0
END
@BOX 1.1
PROC OUT.FN (FILE.NAME);
@BOX 2.1
PROCESS.NAME (FILE.NAME);
IF PW1 /= 0 THEN
   CAPTION (FILE.NAME);
ELSE
   OUT.NAME ("<CFILE> ");
FI
@BOX 3.1
CAPTION (%" AT ");
OUT.TIME ();
CAPTION (%" ON ");
OUT.DATE ();
@BOX 4.1
END
@END
@TITLE LIB06.2.13(1,10)
@COL 1S-2R-3R-4R-5T-6R
@COL 7F
@ROW 6-7
@FLOW 1-2-3-4-5NO-6-3
@FLOW 5YES-7
@BOX 1.0
OUT STACK (START, FINISH)
@BOX 2.0
INITIALISE POINTERS TO STORE
@BOX 3.0
PRINT LINE OF STORE
@BOX 4.0
SCAN STORE LOOKING
FOR A DIFFERENT LINE
@BOX 5.0
FINISH ADDRESS PASSED?
@BOX 6.0
OUTPUT EXTRA NEWLINE
IF STORE LINES DUPLICATED
@BOX 7.0
END
@BOX 1.1
PROC OUT.STACK (START, FINISH);
ADDR PTR, START.PTR, FINISH.PTR;
ADDR [LOGICAL] WORD;
@BOX 2.1
START / BYTES.PER.WORD ->> 3 <<- 3 * BYTES.PER.WORD => START;
FINISH - START / BYTES.PER.WORD => FINISH.PTR;
0 => START.PTR;
MAKE (LOGICAL, STORE.SIZE, START) => WORD;
BYTES.PER.WORD /> START;
NEWLINES (1);
@BOX 3.1
OUT.HEX (START.PTR ->> 3 <<- 3 => START.PTR + START * BYTES.PER.WORD, HX.PER.ADD
R);
SPACES (2);
FOR 8 DO
   OUT.HEX (WORD^ [START.PTR], HX.PER.INTEGER);
   1 +> START.PTR;
   SPACES (1);
OD
NEWLINES (1);
@BOX 4.1
START.PTR => PTR;
WHILE START.PTR =< FINISH.PTR
   AND WORD^ [START.PTR] = WORD^ [START.PTR - 8] DO
   1 +> START.PTR;
OD
@BOX 5.1
IF START.PTR > FINISH.PTR
@BOX 6.1
IF START.PTR - 8 >= PTR THEN
   NEWLINES (1);
FI
@BOX 7.1
END
@END
@TITLE LIB06.2.14(1,11)
@COL 1S-2T-3R-4F
@FLOW 1-2NO-3-4
@FLOW 2YES-4
@BOX 1.0
ECHO LINE ()
@BOX 2.0
IS CURRENT OUTPUT STREAM ONLINE?
@BOX 3.0
PRINT CURRENT LINE OF OUTPUT
@BOX 4.0
END
@BOX 1.1
PROC ECHO.LINE;
INTEGER32 POS;
@BOX 2.1
NEWLINES(0);
IF I.MODE () & %100 /= 0
@BOX 3.1
I.POS () => POS;
IN.BACKSPACE (-1);
WHILE I.POS () /= POS DO
   OUT.CH (IN.CH ());
OD
NEWLINES(0);
@BOX 4.1
END
@END




@TITLE LIB06.2.15(1,11)
@COL 1S-2R-3R-4R-5R-6R-7F
@FLOW 1-2-3-4-5-6-7
@BOX 1.0
OUT I (NUMBER, FIELD)
@BOX 2.0
NOTE SIGN OF NUMBER
@BOX 3.0
CALCULATE ACTUAL FIELD
WIDTH OF NUMBER
@BOX 4.0
OUTPUT SPACES TO GET
REQUIRED FIELD WIDTH
@BOX 5.0
OUTPUT SIGN OF NUMBER
@BOX 6.0
OUTPUT DIGITS OF NUMBER
@BOX 7.0
END
@BOX 1.1
PROC OUT.I (NUMBER, FIELD);
INTEGER32 SIGN, COUNT, TEMP, TEMP1;
@BOX 2.1
IF NUMBER >= 0 THEN
   " " => SIGN;
ELSE
   "-" => SIGN;
   0 -:> NUMBER;
FI
@BOX 3.1
NUMBER => TEMP;
1 => COUNT;
WHILE 10 /> TEMP /= 0 DO
   1 +> COUNT;
OD
@BOX 4.1
SPACES (FIELD - COUNT);
@BOX 5.1
IF FIELD /= 0 OR SIGN /= SP THEN
   OUT.CH (SIGN);
FI
@BOX 6.1
0 => TEMP1;
WHILE 1 -> COUNT >= 0 DO
   TEMP1 * 10 => TEMP;
   NUMBER => TEMP1;
   FOR COUNT DO
      10 /> TEMP1;
   OD
   OUT.CH (TEMP1 - TEMP + "0");
OD
@BOX 7.1
END
@END
