@X @~
~L3 COUK1247
80
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H            BSC281
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL~
~
~
                                                             ISSUE 11~
~V9 -1
~P
~V9 1
~YBSC281
~S~M~OBASIC COMPILER IMPLEMENTATION DESCRIPTION
~S~M~OSection 28 Version 1
~S1~OSection 28 Format Processing
~S1~O1. General Description
~BThis section contains the procedure to convert a
BASIC format string into an internal encoded
representation.  This encoding is subsequently used to drive
the processing of formatted PRINT statements.  The
procedure is intended for use at compile time and at
program execution time.  This section may be compiled
separately from the remainder of the run-time library
for use at compile time, if the machine environment
makes this necessary.
~S1~O2. Interfaces
~S1~O2.1 Section Interfaces Used
~BNone.
~S1~O2.2 Section Interface
~
Exported procedures~
   BIO.ENC.FORMAT~
~S11) BIO.ENC.FORMAT(PTR.TO.FORMAT.STRING,PTR.TO.ENC.FORMAT)LENGTH
~BThis procedure produces an encoding of a format specifier
from a vector of bytes specified by P1.  The
encoding generated is put in a vector of bytes
specified by P2, and the result of the procedure
gives the length of the encoding.  The encoding
consists of a sequence of characters (literal items) interspersed with
encoded format items and terminated with a byte
containing
~X%`
%FF.  The sequence starts with a 'format header' byte,
encoded as follows:~
~3
~Q 9
~
~
~MBit 7 = 0  character of literal item
~N    7 = 1  format item
~N    6 = 1  left justifier present
~N    5 = 1  right justifier present
~N    4 = 1  floating '+' present
~N    3 = 1  floating '-' present
~N    2 = 1  floating '$' present
~0
~BThe kind of format item is specified by bits
0 and 1 as follows:~
~3
~Q 7
~
~
~NBit 0 = 1  I - format item~
~N    1 = 1  F - format item~
~0
~BFor I, F and E format items, a further four bytes
follow, with the following significance.~
~Q 6
~
~
~MByte 0 : number of characters in formatted output field
~NByte 1 : number of digits in integer part
~NByte 2 : number of digits in fractional part
~NByte 3 : number of characters to be printed for exponent.
~BAdditionally, for an I - format item,
or an F - format item with an I - format component there is a
further sequence of bytes specifying the template to
be used for outputting the integer part of a number.
Each byte specifies a digit-place character, as follows:~
~3
~Q 6
~
~
~M%E1  =  *
~N%E2  =  #
~N%E3  =  %
~N%E4  =  ,
~0
~BThis sequence of bytes is terminated by the next
byte which does not have bits 5, 6 and 7 set.
~BBIO.ENC.FORMAT is called at compile time to
encode a format-string specified by an image statement.
It is also called at program execution time by
BIO.ENC.RUN.FORMAT to encode a format specified
from a string.  If the format specified is faulty the
result of the procedure is the negated index into P1
of the suspected location of the fault.
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H               BSC281
~V9 -1
~F
@TITLE BSC28(1,11)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
FORMAT PROCESSING
@BOX 2.0
MODULE HEADING
@BOX 3.0
PROCEDURE IN MODULE
BIO.ENC.FORMAT [BSC28.1]
@BOX 4.0
END
@BOX 1.1
::FORMAT PROCESSING
#BSC28/1
@BOX 2.1
MODULE (BIO.ENC.FORMAT);
@BOX 3.1
LSPEC BIO.ENC.FORMAT (ADDR [$LO8], ADDR [$LO8])/ $IN;
#BSC28.1
@BOX 4.1
*END
@END
@TITLE BSC28/1(1,11)
@COL 1S-2R
@FLOW 1-2
@BOX 1.0
IMPORTS
@BOX 2.0
@BOX 1.1
::IMPORTS
@BOX 2.1
@END
//16
@TITLE BSC28.1(1,11)
@COL 1S-2R-3R-4T-5T-6R-7T-8R-9R-10T-20T-11R-12R-13T-21T-14R-22T-15R-16F
@COL 17T-18R-19R
@ROW 14-17
@FLOW 1-2-3-4N-5N-6-7N-8-9-10N-20N-11-12-13N-21N-14-4Y-22N-15-16
@FLOW 22Y-19
@FLOW 20Y-19
@FLOW 21Y-4
@FLOW 5Y-19-16
@FLOW 7Y-10Y-13Y-17N-18-3
@FLOW 17Y-19
@BOX 1.0
BIO.ENC.FORMAT (PTR.TO.FORMAT.STRING, PTR.TO.ENC.FORMAT) LENGTH
@BOX 2.0
RESET ENC.BUF INDEX
GET SIZE OF FORMAT STRING
@BOX 3.0
GET CHAR
@BOX 4.0
END OF FORMAT BUFFER ?
@BOX 5.0
INVALID CHARACTER ?
@BOX 6.0
RESET CURRENT FORMAT ITEM
@BOX 7.0
NOT A JUSTIER?
@BOX 8.0
NOTE JUSTIER INFO IN
CURRENT FORMAT ITEM
@BOX 9.0
GET CHAR
@BOX 10.0
NOT A FLOATING CHAR?
@BOX 11.0
NOTE FLOATING INFO IN
MAT ITEM
@BOX 12.0
GET CHAR
@BOX 13.0
IS CHAR A LITERAL
STRING CHARACTER ?
@BOX 14.0
PROCESS E, F, I FORMAT
ITEMS
[28.1.1]
@BOX 15.0
SET FORMAT TERMINATOR BYTE
@BOX 16.0
END
@BOX 17.0
FLOATING CHAR PRESENT
IN CURRENT FORMAT
@BOX 18.0
COPY CURRENT FORMAT
TO ENC.FMT.BUFF
@BOX 19.0
FAULT
RETURN NEGATED INDEX
@BOX 20.0
THIS FLOATING CHAR
ALREADY SEEN ?
@BOX 21.0
NOT A START OF E,F,I
FORMAT ITEMS ?
@BOX 22.0
FLOATING CHAR BUT
NO FMT ITEM ?
@BOX 1.1
PROC BIO.ENC.FORMAT (FMT.STR, ENC.FMT);
DATAVEC CHAR.K ($LO8)
%7[32] %0 %0 %7 %2 %8 %3 %7 %0[3] %1 %20
%4 %10  %5 %0[13] %80 %0 %40 %0  %7 %0[26]
%7[4] %0 %7 %0[26] %7[5]
END

$IN FRAC, EXP, INT, F, F1, F2, F3, FLOAT.CH;
$IN EI, FMT.Z, F.IND, D, PERIOD, T.F,F.F;
$LO8 CH, CH.T, DP.CH, T;
@BOX 2.1
0 => EI => F.F => F1 => F2 => F3 => FLOAT.CH;
-1 => F.IND => F;
$IN XX;
FOR XX < SIZE(ENC.FMT) DO
   0 => ENC.FMT^[XX];
OD
SIZE (FMT.STR) => FMT.Z;
@BOX 3.1
IF 1 +> F.IND >= FMT.Z THEN 0 => CH
ELSE FMT.STR^ [F.IND] => CH FI;
@BOX 4.1
IF CH = 0
@BOX 5.1
IF CHAR.K [CH] => CH.T & %7 = 7
@BOX 6.1
%80 !> ENC.FMT^ [EI];
@BOX 7.1
IF CH.T & %C0 = 0
@BOX 8.1
CH.T ->> 1 !> ENC.FMT^ [EI];
@BOX 9.1
IF 1 +> F.IND = FMT.Z THEN 0 => CH => CH.T
ELSE FMT.STR^ [F.IND] => CH ;
     CHAR.K [CH] => CH.T FI;
@BOX 10.1
IF  CH.T & %38 = 0
@BOX 11.1
1 => FLOAT.CH;
$AL 1 +> F FROM
   CH.T => F1;
   CH.T => F2;
   CH.T => F3;
END
CH.T ->> 1 !> ENC.FMT^ [EI];
1 +> F.F;
@BOX 12.1
IF 1 +> F.IND = FMT.Z THEN 0 => CH => CH.T
ELSE FMT.STR^ [F.IND] => CH ;
     CHAR.K [CH] => CH.T FI;
@BOX 13.1
IF CHAR.K [CH] = 0
@BOX 14.1
#BSC28.1.1
0 => F1 => F2 => F3;
-1 => F;
0 => FLOAT.CH;
@BOX 15.1
%FF => ENC.FMT^[EI];
1 +EI => BIO.ENC.FORMAT;
@BOX 16.1
END
@BOX 17.1
IF FLOAT.CH = 1
@BOX 18.1
IF CH /= 0 THEN
   CH => ENC.FMT^ [EI];
   1 +> EI;
FI;
@BOX 19.1
0 - F.IND => BIO.ENC.FORMAT;
@BOX 20.1
IF CH.T = F1 OR CH.T = F2
   OR CH.T = F3 OR F = 2
@BOX 21.1
IF CH.T & %7 => T = 0
OR T = 7
@BOX 22.1
IF FLOAT.CH = 1
@END
///14
@TITLE BSC28.1.1(1,11)
@COL 1S-2R-30T-31R-3T-4R-5R-6R-7R-8T-9T-10T-11C-12T-13T-14R-15R-16R-17T-18R-19T-
20T
@COL 21R-22T-23R-24R-26R-27R-28F
@ROW 4-21
@ROW 15-24
@FLOW 1-2-30N-31-3N-4-5-6-7-8N-9N-10N-11
@FLOW 30Y-3
@FLOW 3Y-21-22N-23-14-15-16-17N-18-16
@FLOW 8Y-5
@FLOW 9Y-12N-13N-14
@FLOW 10Y-5
@FLOW 22Y-11
@FLOW 17Y-19N-20N-24-26-27-28
@FLOW 12Y-11
@FLOW 13Y-19Y-26
@FLOW 20Y-11
@BOX 1.0
PROCESS E, F, I FORMAT
@BOX 2.0
SET FRAC.DIG.CNT, EXP,
INT.DIG.CNT TO ZERO.
SET FMT.KIND TO I-FORMAT
SET TEMPLATE
@BOX 3.0
CHAR IS PERIOD?
@BOX 4.0
NOTE DIGIT-PLACE CHAR
@BOX 5.0
INCREMENT INT DIG COUNT
@BOX 6.0
PUT ENCODED CHAR
IN ENC.BUFF
@BOX 7.0
GET NEXT CHAR
@BOX 8.0
IS IT DIGIT PLACE CHAR?
@BOX 9.0
NOT A COMMA?
@BOX 10.0
LAST CHAR NOT COMMA?
@BOX 11.0
EXIT-FORMAT FAULT
@BOX 12.0
LAST CHAR A COMMA?
@BOX 13.0
CHAR NOT PERIOD?
@BOX 14.0
SET FORMAT KIND TO
F-FORMAT
@BOX 15.0
NOTE PERIOD SEEN
@BOX 16.0
GET NEXT CHAR
@BOX 17.0
CHAR NOT NUMBER-SIGN?
@BOX 18.0
INCREMENT FRAC.DIG
@BOX 19.0
CHAR NOT ^?
@BOX 20.0
GET NEXT 2 CHARS
EITHER NOT ^?
@BOX 21.0
GET NEXT CHAR
@BOX 22.0
CHAR NOT NUMBER-SIGN?
@BOX 23.0
INCREMENT FRAC.DIG.CNT
@BOX 24.0
GET ANY FOLLOWING ^
AND SET EXP.CNT
@BOX 26.0
CALCULATE TOTAL
FELD WIDTH
@BOX 27.0
SET UP ENC.FMT
IN BUFFER
@BOX 28.0
END
@BOX 30.0
JUSTIFIER NOT PRESENT?
@BOX 31.0
PREPROCESS FORMAT WITH
JUSTIFIER
@BOX 1.1
::PROCESS E, I, F FORMAT
@BOX 2.1
0 => FRAC => EXP => INT => PERIOD; 4 => D;
ENC.FMT ^[EI] & %FC ! %1 => ENC.FMT^ [EI];
@BOX 3.1
IF CH = '.
@BOX 4.1
CH => DP.CH;
@BOX 5.1
IF CH /= "," THEN
   1 +> INT;
ELSE
   1 +> F.F;
FI
@BOX 6.1
CHAR.K[CH] ! %E0 => ENC.FMT^ [1 +> D + EI];
@BOX 7.1
IF 1 +> F.IND = FMT.Z THEN 0 => CH
ELSE FMT.STR^ [F.IND] => CH FI;
@BOX 8.1
IF CH = DP.CH
@BOX 9.1
IF CH /= ',
@BOX 10.1
IF FMT.STR^ [F.IND - 1] /= ',
@BOX 11.1
%1 => CH;
-> OUT;
@BOX 12.1
IF FMT.STR^ [F.IND - 1] = ',
@BOX 13.1
IF CH /= '.
@BOX 14.1
ENC.FMT ^[EI] & %FC ! %2
 => ENC.FMT^ [EI];
@BOX 15.1
1 => PERIOD;
@BOX 16.1
IF 1 +> F.IND = FMT.Z THEN 0 => CH
ELSE FMT.STR^ [F.IND] => CH FI;
@BOX 17.1
IF CH /= '#
@BOX 18.1
1 +> FRAC;
@BOX 19.1
IF CH /= '^
@BOX 20.1
IF FMT.STR^ [1 + F.IND] /= '^ OR
FMT.STR^ [2 + F.IND] /= '^
@BOX 21.1
IF 1 +> F.IND = FMT.Z THEN 0 => CH
ELSE FMT.STR^ [F.IND] => CH FI;
@BOX 22.1
IF CH /= '#
@BOX 23.1
1 +> FRAC;
@BOX 24.1
WHILE CH = '^ DO
    1 +> EXP;
   IF 1 +> F.IND = FMT.Z THEN 0 => CH
   ELSE FMT.STR^[F.IND] => CH FI;
OD;
@BOX 26.1
FRAC + INT + EXP +> F.F;
IF PERIOD = 1 THEN 1 +> F.F FI;
@BOX 27.1
F.F => ENC.FMT^ [EI + 1];
INT => ENC.FMT^ [EI + 2];
FRAC => ENC.FMT^ [EI + 3];
EXP => ENC.FMT^ [EI + 4];
@BOX 28.1
0 => F.F;
D+1 +> EI;
OUT:
@BOX 30.1
IF ENC.FMT^[EI] & %60 = 0
@BOX 31.1
$LO8 CH2;
IF CH = "." THEN
   "#" => CH2;
ELSE
   CH => CH2;
FI
CHAR.K[CH2] ! %E0 => ENC.FMT^[1+>D + EI];
1 +> INT;
@END

