(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: M3Linker.i3 *) (* Last Modified On Fri Feb 28 07:44:33 PST 1992 By kalsow *) INTERFACE M3Linker; IMPORT Rd, Wr; (*------------------------------------------------------------------------*) PROCEDURE ReadUnits (input : Rd.T; filename : TEXT; imported : BOOLEAN; errors : Wr.T): UnitList; (* read and parse the link-info in 'input' and return the resulting UnitList. Each unit will be marked as coming from 'filename'. If there are errors, messages will be written to 'errors' and NIL is returned. If 'errors' is NIL, the error messages are silently dropped. *) PROCEDURE MergeUnit (unit : Unit; base : LinkSet; errors : Wr.T): LinkSet; (* check that the version stamps in 'unit' and the version stamps of the units in 'base' are consistent. If they are, 'base' is updated to include 'unit' and it is returned, otherwise 'base' is left unmodified and NIL is returned. If there are inconsistencies, error messages are written on 'errors'. If 'errors' is NIL, the error messages are silently dropped. It is an unchecked runtime error to modify any of the units or their referents once they've been merged with 'base'. *) PROCEDURE CheckSet (base: LinkSet; m: CheckMode; errors:Wr.T):BOOLEAN; (* check whether 'base' defines a complete set (ie. all version stamps are defined and consistent, all imported interfaces are defined, 'Main' is exported, all types are defined, ...). The particular checks depend on the mode selected. If the units of 'base' form a complete set, 'base' is updated and TRUE is returned, otherwise 'base' is left unmodified and FALSE is returned. If there are inconsistencies, error messages are written on 'errors'. If 'errors' is NIL, the error messages are silently dropped. It is an unchecked runtime error to modify any of the units of 'base'. *) PROCEDURE GenerateMain (base: LinkSet; magic: TEXT; output: Wr.T; verbose: BOOLEAN); (* write the C main program for the units in 'base' on 'output'. It is a checked runtime error if 'base' has not been run through CheckSet. If non-NIL, 'magic' is encoded in the generated program. *) PROCEDURE WriteUnits (base: LinkSet; magic: TEXT; output: Wr.T); (* write the linker info for the units in 'base' on 'output'. This is the inverse of 'ReadUnits' *) PROCEDURE Contents (base: LinkSet): UnitList; (* returns the list of units contained in 'base'. It is an unchecked runtime error to modify this list or any of its referents. *) (*------------------------------------------------------------------------*) (* The data structures processed by the linker are defined below: *) CONST LinkerMagic = "M3 v2.1"; CONST BuiltinUnitName = "M3_BUILTIN"; TYPE LinkSet <: REFANY; TYPE Mode = { Units, Program, BaseProgram, Overlay, Library }; CheckMode = [ Mode.Program .. Mode.Library ]; TYPE NameList = REF RECORD name: Name; next: NameList END; UnitList = REF RECORD unit: Unit; next: UnitList END; TYPE Name = RECORD text: TEXT := NIL; hash: INTEGER; END; TYPE File = REF RECORD name : TEXT := NIL; magic : TEXT := NIL; imported : BOOLEAN := FALSE; END; TYPE Unit = REF RECORD name : Name; file : File; interface : BOOLEAN := FALSE; imported_generics: NameList := NIL; imported_units : NameList := NIL; exported_units : NameList := NIL; imported_symbols : VersionStamp := NIL; exported_symbols : VersionStamp := NIL; undefined_types : UndefinedType := NIL; defined_types : Type := NIL; revelations : Revelation := NIL; END; TYPE VersionStamp = REF RECORD symbol : Name; stamp : StampData; next : VersionStamp; export : BOOLEAN; END; StampData = ARRAY [0..1] OF INTEGER; TYPE Revelation = REF RECORD unit : Name; lhs : Name; rhs : Name; next : Revelation; partial : BOOLEAN; export : BOOLEAN; END; TYPE TypeClass = { None, Array, Enum, Object, Opaque, OpenArray, Packed, Procedure, Record, Ref, Set, Subrange }; TYPE UndefinedType = REF RECORD uid : Name; class : TypeClass; name : TEXT := NIL; next : UndefinedType := NIL; END; TYPE Type = REF RECORD uid : Name; class : TypeClass; name : TEXT := NIL; next : Type := NIL; unit : Unit := NIL; depends : NameList := NIL; preDecl : TEXT := NIL; decl : TEXT := NIL; methodDecl : TEXT := NIL; super : Name; END; (*------------------------------------------------------------------------*) (* A 'link-info' file is a sequence of possibly blank filled lines with the following contents: Zn --- the current file's magic is 'n' In --- start unit: interface 'n' Mn --- start unit: module 'n' Am --- current unit exports interface m Bm --- current unit imports interface m gm --- current unit imports generic unit m in x --- import symbol 'n' with version stamp 'x' en x --- export symbol 'n' with version stamp 'x' Km n x --- import symbol 'n' with verison stamp 'x', node # = m Vm n x --- export symbol 'n' with verison stamp 'x', node # = m Gm --- import copy of symbol with node # = m Wm --- export copy of symbol with node # = m Rx y --- export REVEAL 'x' = 'y' from current unit rm x y --- import REVEAL 'x' = 'y' from interface 'm' Xx y --- export REVEAL 'x' <: 'y' from current unit xm x y --- import REVEAL 'x' <: 'y' from interface 'm' Hm x c --- set current type = 'x', node # = m, class = c Qm --- set current type to a copy of type w/node # m Jm x c --- set current type = 'x', leave it undefined, node# = m, class=c Um --- set current type to a copy of undefined type w/node # m tx c --- set current type = 'x', class = c ux c --- set current type = 'x', leave the type 'undefined', class = c Nn --- user-sensible name for current type is 'n' dx --- current type depends on type 'x' C --- C post-declaration for current type follows D --- C pre-declaration for current type follows O --- C declaration for current type's methods follows Sx --- super type of current type is 'x' * --- end of multi-line entry ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz USED: **** ***** *** *** **** * ** * * * ** * *) END M3Linker.