@X @~
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H            MTL162
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL~
~
~
                                                             ISSUE 11~
~V9 -1
~P
~YMTL162
~S~M~OMUTL IMPLEMENTATION DESCRIPTION
~S~M~OSection 16 Version 2
~S~OSection 16.2 Library
~S1~O1. General Description
~BThis module provides procedures for defining programs
and libraries and checking references to entities contained
in previously defined libraries. This version of the module
interfaces with LIB022 to define programs and libraries.
~S1~O2. Interfaces
~
Interface Procedures:~
   INIT.FILES(MODE,FILE.NAME,DIR.SIZE)~
   CLOSE.FILES()~
   ADD.LIB.PROC(PTR.TO.PROC.E)~
   CHECK.LIB.PROC(PROC.MUTL.NAME,PTR.TO.PROC.E)STATUS~
~S1~O2.1 Hardware Interface
~BAny machine.
~S1~O2.2 Software Interface
~BThe specification of these procedures is given in MTL161.
~S1~O3. Implementation
~S1~O3.1 Outline of Operation
~BStraightforward.
~S1~O3.2 Data Structures
~BNone.
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H               MTL162
~V9 -1
~F
@TITLE MTL16(2,8)
@COL 1S-2R-3R-4R-5R-7F
@FLOW 1-2-3-4-5-7
@BOX 1.0
SECTION 16
OUTPUT FILE CONTROL
@BOX 2.0
EXTERNAL ENVIRONMENT[MTL16/1]
MODULE HEADING
@BOX 3.0
EXPORTED TYPES
@BOX 4.0
VARIABLE AND LITERAL DECLARATIONS
@BOX 5.0
PROCEDURE DECLARATION
INTERFACE PROCEDURES
16.1:INIT.FILES
16.2:CLOSE.FILES
16.3:ADD.LIB.PROC
16.4: CHECK.LIB.PROC
INTERNAL PROCEDURES
16.10: GET.LIB.TYPE
16.11: PROCESS.LIB.TYPE
16.12: CREATE.LIB.TYPE
16.13: CHECK.USER.TYPE
@BOX 7.0
END
@BOX 1.1
::MTL16
@BOX 2.1
IMPORT TYPE PROC.ADDR.TY;
MODULE(PROC.ENTRY.TY);
TYPE PROC.ENTRY.TY IS
   PROC.ADDR.TY PROC.ADDR
   OR $LO32 PROC.FIND.N;
*END;
#MTL16/1
MODULE(INIT.FILES,CLOSE.FILES,ADD.LIB.PROC,CHECK.LIB.PROC);
@BOX 3.1
@BOX 4.1
;LITERAL/ADDR[$LO8] NIL.STR=
;LITERAL/ADDR PAR.E NIL.PAR=
;LITERAL/ADDR COM.E NIL.COM=
;LITERAL/ADDR STORE.E NIL.STORE=
;LITERAL/ADDR TYPE.E  NIL.TYPE=
;LITERAL/ADDR FIELD.E NIL.FIELD=
;*GLOBAL 9
;$IN DIR.SEG,LIB.TYPE,DECL.LIB.TYPE
;ADDR [$LO8] CUR.LIB.NAME
;*GLOBAL 0
@BOX 5.1
;PSPEC INIT.FILES($IN,ADDR[$LO8],$IN)
;PSPEC CLOSE.FILES()
;PSPEC ADD.LIB.PROC($IN)
;PSPEC CHECK.LIB.PROC($IN,ADDR PROC.E)/$IN
;PSPEC CHECK.USER.TYPE(ADDR TYPE.E,$LO32,$IN)/$IN
;PSPEC GET.LIB.TYPE($IN,ADDR TYPE.E,$IN)/$IN
;PSPEC PROCESS.LIB.TYPE(ADDR FIELD.E)/$IN
;PSPEC CREATE.LIB.TYPE(ADDR TYPE.E,ADDR[$LO])
;*CODE 3
#MTL16.1
#MTL16.2
#MTL16.3
#MTL16.4
#MTL16.10
#MTL16.11
#MTL16.12
#MTL16.13
@BOX 7.1
;*END
@END
@TITLE MTL16/1(2,11)
@COL 1S-2R-3R-4R-5F
@FLOW 1-2-3-4-5
@BOX 1.0
EXTERNAL ENVIRONMENT
@BOX 2.0
TYPES
@BOX 3.0
VARIABLES AND LITERALS
@BOX 4.0
PROCEDURES
@BOX 5.0
END
@BOX 1.1
::EXTERNAL ENVIRONMENT
@BOX 2.1
;IMPORT TYPE STORE.ADDR.TY, VAR.ADDR.TY
;IMPORT TYPE PROC.ADDR.TY
;TYPE FIELD.E;
;TYPE TYPE.E IS
   ADDR FIELD.E TYPE.FIELD.P
   $LO8 TYPE.AL, TYPE.FL
   $LO16 TYPE.Z,TYPE.LIB,TYPE.NAME
;TYPE FIELD.E IS
   ADDR FIELD.E NEXT.FIELD.P
   $LO16 FIELD.POS,FIELD.TYPE
   ADDR TYPE.E FIELD.TYPE.P
   $IN  FIELD.TAG
   ADDR  FIELD.DIM
;TYPE STORE.E IS
   ADDR STORE.I,STORE.Z,STORE.EQ.Z
   $LO8 STORE.KIND,SEG.NO
   STORE.ADDR.TY  STORE.ADDR
   $LO8 STORE.TX
   ADDR STORE.C.ADDR
   $LO32 STORE.R.ADDR
  $LO8 STORE.BASE, STORE.ACCESS
;TYPE VAR.E IS
    $LO16 VAR.TYP
    ADDR VAR.DIM
    $LO16 VAR.F
    ADDR TYPE.E VAR.TYP.P
    VAR.ADDR.TY VAR.ADDR
;TYPE PAR.E IS
   ADDR PAR.E N.PAR.P
   $LO8 PAR.TYP
   ADDR  PAR.DIM
   ADDR  TYPE.E  PAR.TYP.P
   ADDR VAR.E PAR.REF.V.P, PAR.VAL.V.P
;TYPE PROC.ENTRY.TY IS
   PROC.ADDR.TY PROC.ADDR
   OR $LO32 PROC.FIND.N
;TYPE PROC.E IS
   $LO8 PROC.NAT
   $LO8 PROC.RES.TYP
   $LO8 PROC.INFO
   ADDR PAR.E PROC.PAR.P
   ADDR TYPE.E PROC.RES.TYP.P
   PROC.ENTRY.TY ENTRY
;TYPE COM.E IS
   ADDR COM.E N.COM.P
   ADDR[$LO8] COM.NAME.P
   ADDR STORE.E COM.STORE.P
   $IN32 COM.I,COM.Z
   $LO8 COM.NAT
@BOX 3.1
;IMPORT LITERAL SEG.SHIFT,SEG.Z
;$LO64 PWW1
;$IN TL.M
;STORE.E[SEG.Z] SEG.T
;ADDR PROC.E CUR.PROC.P
;ADDR COM.E COM.HD
@BOX 4.1
;LSPEC INIT.DIR(ADDR [$LO8],$IN)/$IN
;LSPEC CLOSE.DIR($IN)
;LSPEC CHANGE.ACCESS($IN, $LO)
;LSPEC ADD.SEGMENT($IN,$IN,$LO32,$LO,$IN32)
;LSPEC CHANGE.SIZE($IN,ADDR)
;LSPEC ADD.PROC($IN,ADDR[$LO8],ADDR[$LO])/$IN
;LSPEC ADD.TYPE($IN, ADDR[$LO8], ADDR[$LO])/$IN
;LSPEC FINDN(ADDR[$LO8],$IN)/$LO32
;LSPEC FINDP($LO32,$IN,$IN)/$IN
;LSPEC FINDF($LO32,$IN,$IN)/$IN
;PSPEC PROP.PTR($IN,$IN)
;PSPEC FAULT($IN, ADDR[$LO8])
;PSPEC YIELD.SYMB.NAME($IN)/ADDR[$LO8]
;PSPEC SYMB.NAME($IN)/ADDR[$LO8]
@BOX 5.1
::END
@END
@TITLE MTL16.1(2,12)
@COL 1S-2R-3R-4R-5F
@FLOW 1-2-3-4-5
@BOX 1.0
INIT.FILES(MODE,FILE.NAME,DIR.SIZE)
@BOX 2.0
OBTAIN FILENAME
AND DIRECTORY NAME FROM P2
@BOX 3.0
INITIALISE LIB VARIABLES
@BOX 4.0
INITIALISE DIRECTORY
@BOX 5.0
END
@BOX 1.1
;PROC INIT.FILES(M,FN,DZ)
;INTEGER I,J,FN.SIZE
;ADDR [$LO8] NAME
;LOGICAL8 CH;
@BOX 2.1
SIZE (FN) => FN.SIZE;
-1 => J;
FOR I < FN.SIZE DO
   IF FN^ [I] => CH = "/" OR CH = ":" THEN
      I => J;
   FI;
OD;
@BOX 3.1
;256 => LIB.TYPE
;260 => DECL.LIB.TYPE
@BOX 4.1
;IF 1+>J = FN.SIZE THEN
   ;NIL.STR => NAME
;ELSE
   ;PART(FN, J, FN.SIZE - 1) => NAME
;FI
;INIT.DIR(NAME,DZ) => DIR.SEG
@BOX 5.1
;END
@END
@TITLE MTL16.2(2,12)
@COL 1S-11T-15R-3R-4T-5R-8T-6R-9R-10F
@FLOW 1-11N-15-3-4N-5-8N-6-9-10
@FLOW 11Y-3
@FLOW 4Y-8-4
@BOX 1.0
CLOSE.FILES
@BOX 3.0
GET FIRST MUTL SEGMENT
@BOX 4.0
MUTL SEGMENT NOT USED OR
NO RUN TIME ALLOCATION REQUIRED
@BOX 5.0
CLOSE SEGMENT [16.2.1]
@BOX 6.0
CLOSE FILE SEGMENT FOR
ALL COMMON AREAS [16.2.1]
@BOX 8.0
MORE SEGMENTS?
@BOX 9.0
CLOSE DIRECTORY
@BOX 10.0
END
@BOX 11.0
SEGMENTS NOT BEING FILED
@BOX 15.0
SET ACCESS ON ALL SEGMENTS
@BOX 1.1
;PROC CLOSE.FILES
;ADDR COM.E C.P
;$IN I
;PSPEC CLOSE.SEGMENT(ADDR STORE.E)
#MTL16.2.1
@BOX 3.1
;0 => I
@BOX 4.1
;SELECT SEG.T[I]
;IF STORE.KIND & 1 = 0 OR STORE.C.ADDR = -3
@BOX 5.1
;CLOSE.SEGMENT(^SEG.T[I])
@BOX 6.1
;COM.HD => C.P
;WHILE C.P /= NIL.COM DO
   ;SELECT C.P^
   ;IF COM.STORE.P /= NIL.STORE
      AND STORE.KIND OF COM.STORE.P^ & 1 /= 0
      AND STORE.C.ADDR OF COM.STORE.P^ /= -3 THEN
          ;CLOSE.SEGMENT(COM.STORE.P)
   ;FI
   ;N.COM.P => C.P
;OD
@BOX 8.1
;IF 1 +> I < SEG.Z
@BOX 9.1
;CLOSE.DIR(DIR.SEG)
@BOX 10.1
;END
@BOX 11.1
;IF DIR.SEG /= 0
@BOX 15.1
;BEGIN
;FOR I < SEG.Z DO
   ;SELECT SEG.T[I]
      ;IF STORE.KIND & 1 /= 0 AND
          STORE.C.ADDR /= -3 AND
          STORE.C.ADDR /= -2  THEN
              ;CHANGE.ACCESS(STORE.C.ADDR ->> SEG.SHIFT, STORE.ACCESS)
      ;FI
;OD
;END
@END
@TITLE MTL16.2.1(2,12)
@COL 1S-12T-5T-6R-2T-16T-17R-13R-7R-10F
@COL 3T-8T-4R
@ROW 16-3
@FLOW 1-12N-5N-6-2N-16N-17-13-7-10
@FLOW 12Y-3N-8N-4-13-7
@FLOW 2Y-10
@FLOW 8Y-10
@FLOW 3Y-13
@FLOW 5Y-16
@FLOW 16Y-7
@BOX 1.0
CLOSE.SEGMENT(SEG.PTR)
@BOX 2.0
NO STORAGE ALLOCATED
@BOX 3.0
NOT FILING PROGRAM
@BOX 4.0
CREATE SEGMENT
@BOX 5.0
CHANGE SIZE NOT REQUIRED
@BOX 6.0
CHANGE ITS SIZE
@BOX 7.0
ADD SEGMENT TO FILED IMAGE
@BOX 8.0
NO STORAGE ALLOCATED
@BOX 10.0
END
@BOX 12.0
IS IT A RUN TIME SCRATCH SEGMENT
@BOX 13.0
NOTE COMPILE TIME SEGMENT
NEED NOT BE FILED.
@BOX 16.0
INITIALIZED SEGMENT OR
NOT FILING SEGMENTS?
@BOX 17
RELEASE SEGMENT
@BOX 1.1
;PROC CLOSE.SEGMENT(ST.P)
;ADDR C.ADDR
;$IN ACCESS
@BOX 2.1
;IF STORE.Z = 0
@BOX 3.1
;IF DIR.SEG = 0
@BOX 4.1
;CREATE.SEGMENT(STORE.R.ADDR->>SEG.SHIFT, STORE.Z)
@BOX 5.1
;CADDR ->> SEG.SHIFT => C.ADDR
;IF STORE.KIND & %80 = 0
@BOX 6.1
;IF STORE.I => STORE.Z < STORE.EQ.Z THEN
   ;STORE.EQ.Z => STORE.Z
;FI
;CHANGE.SIZE(C.ADDR, STORE.Z)
@BOX 7.1
;ADD.SEGMENT(DIR.SEG,C.ADDR,
             STORE.R.ADDR,ACCESS,STORE.Z)
@BOX 8.1
;IF STORE.I => STORE.Z < STORE.EQ.Z  THEN
   ;STORE.EQ.Z => STORE.Z
;FI
;IF STORE.Z = 0
@BOX 10.1
;0 => STORE.KIND
;END
@BOX 12.1
;SELECT ST.P^
;STORE.ACCESS => ACCESS
;IF STORE.C.ADDR => C.ADDR = -2
@BOX 13.1
;0   => C.ADDR
@BOX 16.1
; IF STORE.KIND & %10 /= 0 OR DIR.SEG = 0
@BOX 17.1
; RELEASE.SEGMENT(C.ADDR)
@END

@TITLE MTL16.3(2,9)
@COL 1S-9T-2R-3R-4R-5R-7R-8F
@FLOW 1-9N-2-3-4-5-7-8
@FLOW 9Y-8
@BOX 1.0
ADD.LIB.PROC(MUTL.NAME)
@BOX 2.0
GET PROP.PTR[MTL18]
GET SYMBOLIC NAME
@BOX 3.0
ADD TYPE OF EACH PARAMETER TO PROP VEC
[MTL16.10]
@BOX 4.0
ADD TYPE OF RESULT TO PROP VEC
[MTL16.10]
@BOX 5.0
ADD PARAM CNT TO VEC
@BOX 7.0
ADD ENTRY FOR PROCEDURE IN ITS DIRECTORY
@BOX 8.0
END
@BOX 9.0
NO DIRECTORY?
@BOX 1.1
;PROC ADD.LIB.PROC(N)
;$IN I,T
;$LO[512] PROP
;ADDR PAR.E PAR
@BOX 2.1
;PROP.PTR(N,6)
;YIELD.SYMB.NAME(N) => CUR.LIB.NAME
@BOX 3.1
;0 => I
;PROC.PAR.P OF CUR.PROC.P^ => PAR
;WHILE PAR /= NIL.PAR DO
   ;GET.LIB.TYPE(PAR.TYP OF PAR^,PAR.TYP.P OF PAR^,PAR.DIM OF PAR^)
            ! PAR.TYP OF PAR^ => PROP[1+>I]
   ;N.PAR.P OF PAR^ => PAR
;OD
@BOX 4.1
GET.LIB.TYPE(PROC.RES.TYP OF CUR.PROC.P^,PROC.RES.TYP.P OF CUR.PROC.P^,0) => PRO
P[1+>I]
@BOX 5.1
;I -1 => PROP[0]
@BOX 7.1
;ADD.PROC(DIR.SEG,CUR.LIB.NAME,PART(^PROP,0,I))
@BOX 8.1
;END
@BOX 9.1
;IF DIR.SEG = 0
@END
@TITLE MTL16.4(2,9)
@COL 8R
@COL 1S-10R-2T-3R-4T-5T-6R-7F
@COL 9R
@ROW 8-6-9
@FLOW 1-10-2N-3-4N-5N-6-7
@FLOW 2Y-8-7
@FLOW 4Y-9-6
@FLOW 5Y-9
@BOX 1.0
CHECK.LIB.PROC(MUTN.NAME,PROC.P)STATUS
@BOX 2.0
LIBRARY PROCEDURE NOT FOUND?
@BOX 3.0
OBTAIN NO OF PARAMS
IN LIBRARY PROC
@BOX 4.0
CHECK SPEC OF RESULT
[MTL16.4.1]
ANY FAULTY?
@BOX 5.0
CHECK SPEC OF ALL PARAMETERS
[MTL16.4.1]
NY FAULTS?
@BOX 6.0
NOTE PROC DEFINED
SAVE FIND.NO OF PROC
@BOX 7.0
END
@BOX 8.0
SET FAULT STATUS
@BOX 9.0
SET FAULT STATUS
@BOX 10.0
SUB PROCEDURE
CHECK.P [MTL16.4.1]
@BOX 1.1
;PROC CHECK.LIB.PROC(PR.N,PR)
;$LO32 LIB.NO
;$IN P.CNT,F,I
;ADDR PAR.E PAR
;0 => CHECK.LIB.PROC
@BOX 2.1
;IF FIND.N(YIELD.SYMB.NAME(PR.N),0) => LIB.NO = 0
@BOX 3.1
;FIND.P(LIB.NO,-1,0) => P.CNT
@BOX 4.1
;IF CHECK.P(PROC.RES.TYP OF PR^, PROC.RES.TYP.P OF PR^,
            0,P.CNT+1)/=0
@BOX 5.1
;0 => I => F
;PROC.PAR.P OF PR^ => PAR
;WHILE F=0 DO
   ;IF I = P.CNT AND PAR= NIL.PAR THEN
       ;-1 => F
   ;ELSE IF I=P.CNT OR PAR=NIL.PAR THEN
       ;1 => F
   ;ELSE
       ;CHECK.P(PAR.TYP OF PAR^,PAR.TYP.P OF PAR^,
                PAR.DIM OF PAR^, 1+>I) => F
       ;N.PAR.P OF PAR^ => PAR
   ;FI FI
;OD
;IF F > 0
@BOX 6.1
;%80 !> PROC.NAT OF PR^
;LIB.NO => PROC.FIND.N OF ENTRY OF PR^
@BOX 7.1
;END
@BOX 8.1
;20 => CHECK.LIB.PROC
@BOX 9.1
;22 => CHECK.LIB.PROC
@BOX 10.1
#MTL16.4.1
@END
@TITLE MTL16.4.1(2,11)
@COL 9R
@COL 1S-2R-3T-4T-10T-5T-6T-7T-8F
@ROW 9-6
@FLOW 1-2-3N-4N-10N-5N-6N-7N-8
@FLOW 10Y-8
@FLOW 3Y-9-8
@FLOW 4Y-8
@FLOW 5Y-9
@FLOW 6Y-9
@FLOW 7Y-9
@BOX 1.0
CHECK.P(TYPE,TYPE.P,DIM,PARAM.NO)STATUS
@BOX 2.0
GET LIBRARY TYPE
@BOX 3.0
MUTL TYPE A VECTOR?
@BOX 4.0
BOTH IDENTICAL BASIC TYPES?
@BOX 5.0
EITHER A BASIC TYPE?
@BOX 6.0
SCALAR POINTER BITS DIFFERENT
@BOX 7.0
CHECK USER DEFINED TYPE
[MTL16.13]
DIFFERENT?
@BOX 8.0
END
@BOX 9.0
SET STATUS
@BOX 10.0
BOTH POINTER TYPES AND ONE
IS OF UNDEFINED TYPE?
@BOX 1.1
;PSPEC CHECK.P($IN,ADDR TYPE.E,$IN,$IN)/$IN
;PROC CHECK.P(T,TP,DIM,P.NO)
;$IN L.T
;0 => CHECK.P
@BOX 2.1
;FIND.P(LIB.NO,-1,P.NO) => L.T
@BOX 3.1
;IF DIM /= 0
@BOX 4.1
;IF TP = NIL.TYPE AND T = L.T
@BOX 5.1
;IF TP = NIL.TYPE OR L.T < 256
@BOX 6.1
;IF T & 3 /= L.T & 3
@BOX 7.1
;IF CHECK.USER.TYPE(TP,LIB.NO,L.T) /=0
@BOX 8.1
;END
@BOX 9.1
;1 => CHECK.P
@BOX 10.1
;IF T & 3 = L.T & 3 /= 0 AND
    [L.T & %FFFC = 0 OR T & %FFFC = 0 AND TP = NIL.TYPE]
@END
@TITLE MTL16.10(2,8)
@COL 1S-2R-3T-4R-5F
@FLOW 1-2-3N-4-5
@FLOW 3Y-5
@BOX 1.0
GET LIB TYPE(TYPE,TYPE.P,DIM)
@BOX 2.0
PROCESS LIB TYPE [MTL16.11]
@BOX 3.0
NOT A NEW LIBRARY TYPE?
@BOX 4.0
CREATE NEW LIBRARY TYPE
[MTL16.12]
@BOX 5.0
END
@BOX 1.1
;PROC GET.LIB.TYPE(TYP,TYP.P,DIM)
;$LO[256]PROPS
;FIELD.E F
@BOX 2.1
;TYP => FIELD.TYPE OF F
;TYP.P => FIELD.TYPE.P OF F
;DIM => FIELD.DIM OF F
;PROCESS.LIB.TYPE(^F) => GET.LIB.TYPE
@BOX 3.1
;IF GET.LIB.TYPE < DECL.LIB.TYPE
@BOX 4.1
;CREATE.LIB.TYPE(TYP.P,^PROPS)
@BOX 5.1
;END
@END
@TITLE MTL16.11(2,8)
@COL 9R
@COL 1S-2T-3T-4T-5R-6R-7R-8F
@COL 10R
@ROW 9-5-10
@FLOW 1-2N-3N-4N-5-6-7-8
@FLOW 2Y-10-8
@FLOW 3Y-9-8
@FLOW 4Y-7
@BOX 1.0
PROCESS LIB TYPE(OF A FIELD)
@BOX 2.0
TYPE A VECTOR?
@BOX 3.0
MUTL BASIC TYPE?
@BOX 4.0
LIB TYPE NO.ALREADY ALLOCATED?
@BOX 5.0
ALLOCATE A LIB TYPE NO
@BOX 6.0
FOR ALL FIELDS OF TYPE
PROCESS LIB TYPES[MTL16.11]
@BOX 7.0
SET UP LIB TYPE
@BOX 8.0
END
@BOX 9.0
SET UP LIB TYPE
AS MUTL TYPE
@BOX 10.0
FAULT
'VECTOR TYPES NOT ALLOWED'
@BOX 1.1
;PROC PROCESS.LIB.TYPE(F)
;$IN T
;ADDR TYPE.E TP
;ADDR FIELD.E F.P
;SELECT F^
@BOX 2.1
;IF FIELD.DIM /= 0
@BOX 3.1
;FIELD.TYPE => PROCESS.LIB.TYPE
;IF FIELD.TYPE.P => TP = NIL.TYPE
@BOX 4.1
;IF TYPE.LIB OF T.P^ /=0
@BOX 5.1
;4 +> LIB.TYPE => TYPE.LIB OF T.P^
@BOX 6.1
;TYPE.FIELD.P OF TP^ => F.P
;WHILE F.P /= NIL.FIELD DO
   ;PROCESS.LIB.TYPE(FP)
   ;NEXT.FIELD.P OF F.P^ => F.P
;OD
@BOX 7.1
;TYPE.LIB OF TP^ => PROCESS.LIB.TYPE
@BOX 8.1
;END
@BOX 9.1
::IN BOX 3
@BOX 10.1
;FAULT(17,CUR.LIB.NAME)
@END
@TITLE MTL16.12(2,8)
@COL 1S-2R-3R-4R-5F
@FLOW 1-2-3-4-5
@BOX 1.0
CREATE LIB TYPE(TYPE.P,PROP.VEC.PTR)
@BOX 2.0
SET UP TYPE PROPERTY VECTOR
@BOX 3.0
ADD LIBRARY TYPE TO DIRECTORY
NOTE LIBRARY TYPE DECLARED
@BOX 4.0
IF TYPE CONTAINS ANY OTHER
NEW LIBRARY TYPES THEN
CREATE LIBRARY TYPES FOR THEM
@BOX 5.0
END
@BOX 1.1
;PROC CREATE.LIB.TYPE(TYP.P,PROP)
;ADDR FIELD.E F.P
;$IN I
@BOX 2.1
;0 => I
;TYPE.FIELD.P OF TYP.P^ => F.P
;WHILE F.P /= NIL.FIELD DO
   ;FIELD.TAG OF F.P^ & 1 <<- 14!
   PROCESS.LIB.TYPE(F.P) => PROP^[1+>I]
   ;NEXT.FIELD.P OF F.P^ => F.P
;OD
;I => PROP^[0]
@BOX 3.1
;ADD.TYPE(DIR.SEG,SYMB.NAME(TYPE.NAME OF TYP.P^),PART(PROP,0,I))
;4+>DECL.LIB.TYPE
@BOX 4.1
;TYPE.FIELD.P OF TYP.P^ => F.P
;WHILE F.P /= NIL.FIELD DO
   ;IF PROCESS.LIB.TYPE(FP) >= DECL.LIB.TYPE THEN

      ;CREATE.LIB.TYPE(FIELD.TYPE.P OF F.P^,PROP)
   ;FI
   ;NEXT.FIELD.P OF F.P^ => F.P
;OD
@BOX 5.1
;END
@END
@TITLE MTL16.13(2,11)
@COL 1S-2R-3T-17T-5R-6T-7T-8T-18T-9T-10T-11T-12T-13R
@COL 14T-15R-16F
@ROW 5-14
@ROW 13-15
@FLOW 1-2-3N-17N-5-6N-7N-8N-18N-9N-10N-11N-12N-13-3Y-14N-15-16
@FLOW 14Y-16
@FLOW 6Y-15
@FLOW 7Y-15
@FLOW 8Y-13
@FLOW 18Y-13
@FLOW 9Y-15
@FLOW 10Y-15
@FLOW 11Y-13
@FLOW 12Y-15
@FLOW 17Y-15
@BOX 1.0
CHECK.USER.TYPE(MUTL.TYPE,LIB.NO,LIBRARY.TYPE)STATUS
@BOX 2.0
INITIALISE MUTL AND
LIBRARY FIELDS
@BOX 3.0
NO MORE FIELDS IN
MUTL TYPE?
@BOX 5.0
GET LIB TYPE
@BOX 6.0
MUTL TYPE A VECTOR
@BOX 7.0
DIFFERENT ALTERNATIVE TAGS
@BOX 8.0
FIELDS OF IDENTICAL BASIC TYPE
@BOX 9.0
EITHER A BASIC TYPE
@BOX 10.0
SCALAR POINTER BITS DIFFERENT
@BOX 11.0
BOTH POINTERS
@BOX 12.0
CHECK USER TYPES
[MTL16.13]
FAULTY?
@BOX 13.0
GET NEXT FIELDS
@BOX 14.0
END OF LIBRARY TYPE
@BOX 15.0
SET FAULT STATUS
@BOX 16.0
END
@BOX 17.0
NO MORE FIELDS IN LIBRARY
TYPE?
@BOX 18.0
BOTH POINTER TYPES AND IS A
POINTER TO AN UNKNOWN DATA TYPE
@BOX 1.1
;PROC CHECK.USER.TYPE(T,LIB.NO,LT)
;ADDR FIELD.E F
;$IN F.CNT,I,FT,LFT
;ADDR TYPE.E FTP
;0 => CHECK.USER.TYPE
@BOX 2.1
;TYPE.FIELD.P OF T^ => F
;FIND.F(LIB.NO,LT-256->>2=>LT,0) => F.CNT
;0 => I
@BOX 3.1
;IF F = NIL.FIELD
@BOX 5.1
;FIND.F(LIB.NO,LT,1+>I) => LFT
@BOX 6.1
;IF FIELD.DIM OF F^ /= 0
@BOX 7.1
;IF LFT ->> 14 &1 /= FIELD.TAG OF F^ &1
@BOX 8.1
;%3FFF &> LFT
;FIELD.TYPE OF F^ => FT
;FIELD.TYPE.P OF F^ => FTP
;IF FTP = NIL.TYPE AND FT = LFT
@BOX 9.1
;IF FTP = NIL.TYPE OR LFT < 256
@BOX 10.1
;IF FT & 3 /= LFT & 3
@BOX 11.1
;IF FT & 3 /=0
@BOX 12.1
;IF CHECK.USER.TYPE(FTP,LIB.NO,LFT) /=0
@BOX 13.1
;NEXT.FIELD.P OF F^ => F
@BOX 14.1
;IF I >= F.CNT
@BOX 15.1
;1 => CHECK.USER.TYPE
@BOX 16.1
;END
@BOX 17.1
;IF I >= F.CNT
@BOX 18.1
;IF FT & 3 = LFT & 3 /= 0 AND
    [LT & %FFFC = 0 OR FT & %FFFC = 0 AND FTP = NIL.TYPE]
@END

