
    <<LoaderOpsExtras.mesa>>
        <<Copyright © 1985 by Xerox Corporation.  All rights reserved.>>
    <<Satterthwaite on: September 17, 1985 12:13:59 pm PDT>>

    DIRECTORY
        --Atom USING [GetProp, PutProp],
        BcdDefs USING [BcdBase, --Link, MTHandle, NullVersion, --VersionStamp, ModuleIndex],
        FS USING [nullOpenFile, OpenFile],
        --Loader USING [IRItem],
        LoaderOps: TYPE USING [FrameListEntry],
        LoadState USING [ConfigID],
        PrincOps USING [--ControlLink,-- ControlModule--, NullLink, GlobalFrameHandle--],
        Rope USING [ROPE--, Text--];
        --VM USING [Interval];

    LoaderOpsExtras: DEFINITIONS --IMPORTS Atom-- = BEGIN OPEN BcdDefs, LoadState, PrincOps;

    <<Global frame creation>>
        <<>>
        FrameList: TYPE = LIST OF FrameListEntry;
        FrameListEntry: TYPE = LoaderOps.FrameListEntry;

        --FrameListEntry: TYPE = RECORD[
            --SELECT tag: * FROM
                --frame => [ptr: POINTER],
                --mdsInterval => [interval: VM.Interval**pages in mds**]
                --ENDCASE];

        AcquireFileProc: TYPE = PROC [name: Rope.ROPE, version: BcdDefs.VersionStamp]
        RETURNS[file: FS.OpenFile];

        CreateGlobalFrames: PROC[cid: ConfigID, allframelinks: BOOL] RETURNS[fl: FrameList _ NIL];

        AssignCode: PROC [
        config: ConfigID, AcquireFile: AcquireFileProc,
        bcdFile: FS.OpenFile_FS.nullOpenFile, pageOffset: INT_0];    -- for FTSelf

        UpdateCode: PROC [
        config: ConfigID, moduleBase: ModuleIndex,
        bcd: BcdBase,
        AcquireFile: AcquireFileProc,
        bcdFile: FS.OpenFile_FS.nullOpenFile, pageOffset: INT_0];    -- for FTSelf

        AssignControlModules: PROC[config: ConfigID] RETURNS [cm: PrincOps.ControlModule];

        AllocateFrames: PROC[size: CARDINAL, single, resident: BOOL] RETURNS [fl: FrameList, frames: POINTER];
            <<... allocates mds VM for "size" words, either from the frame heap or as a VM.Interval, depending on whether single is TRUE or 
            FALSE, respectively.  It returns a single-element FrameList and a POINTER to the new block of mds storage.>>

        ReleaseFrames: PROC[fl: FrameList, cid: ConfigID];
            <<... releases the frame(s) and/or mds VM intervals listed in fl, then resets the GFT and loadstate entries as per map to "empty" 
            states>>

    END.    -- for now 

        GetModuleLink: PROC[atom: ATOM] RETURNS[link: ControlLink _ NullLink];
            <<exported by CedarLinkerImpl>>

        <<>>
    <<Interface records; linking operations and data structures>>

        IR: TYPE = REF IRRecord;
        IRRecord: TYPE = LoaderOps.IRRecord;
        --IRRecord: TYPE = RECORD[s: SEQUENCE size: NAT OF PrincOps.ControlLink];

        Export: PROC[config: ConfigID];

        Bind: PROC[config: ConfigID] RETURNS[unboundImports: LIST OF Loader.IRItem];

        GetIR: PROC[ -- either the atom or the version must be non-NIL
            atom: ATOM _ NIL, 
            version: VersionStamp _ NullVersion, 
            length: CARDINAL _ 0] -- in case a new one must be created
            RETURNS[name: ATOM, interface: IR, versionStamp: VersionStamp];

        GetFrame: PROC[interface: IR, index: CARDINAL] RETURNS[GlobalFrameHandle];
            <<returns the frame of an exported variable>>

        IsNullLink: PROC[link: UNSPECIFIED] RETURNS[BOOL] = INLINE {
            RETURN[
                LOOPHOLE[link,CARDINAL]=0 --PrincOps.NullLink
                OR LOOPHOLE[link,CARDINAL]=1 -- PrincOps.UnboundLink
                ];
            };

        OpenLinkSpace: PROC[frame: GlobalFrameHandle, mth: MTHandle, bcd: BcdBase _ NIL];

        ReadLink: PROC[offset: CARDINAL] RETURNS [link: ControlLink];

        WriteLink: PROC[offset: CARDINAL, link: ControlLink];

        CloseLinkSpace: PROC[frame: GlobalFrameHandle];

        GetSpace: PROC[nwords: CARDINAL] RETURNS [p: POINTER];

        FreeSpace: PROC[p: POINTER];

        LinkSegmentLength: PROC[mth: MTHandle, bcd: BcdBase] RETURNS[CARDINAL];

        IthLink: PROC[mth: MTHandle, i: CARDINAL, bcd: BcdBase] RETURNS[Link];
        <<>>
        <<>>
    <<Private Definitions>>

        GetPendingList: PRIVATE PROC[interface: ATOM] RETURNS[PendingList] =
        INLINE {RETURN[NARROW[Atom.GetProp[interface, $pending]]]};

        SetPendingList: PRIVATE PROC[interface: ATOM, list: PendingList] =
        INLINE {Atom.PutProp[interface, $pending, list]};

        GetBinding: PROC[bcd: BcdBase] RETURNS[binding: Binding]; -- already filled in

        FindVariableLink: PROC[config: ConfigID, mx: BcdDefs.ModuleIndex, mthLink: Link]
            RETURNS [link: PrincOps.ControlLink, frame: PrincOps.GlobalFrameHandle];

        pendingModules: PRIVATE LIST OF PendingModule;
        <<>>
        <<list of people waiting for a MODULE to be exported>>

        Binding: TYPE = REF BindingSequence;

        BindingSequence: TYPE = RECORD[s: SEQUENCE size: NAT OF BindLink];
        <<>>
        <<A Binding is a mapping between the dummy gfi's within the bcd and real interfaces.  Bindings are only legal for 
        [bcd.firstdummy..bcd.firstdummy+bcd.nDummies) !>>

        BindLink: TYPE = RECORD[
            whichgfi: BcdDefs.ModuleIndex _ 0, -- if there is more than one gfi for this interface 
            atom: ATOM, -- so we can get and set the pending list
            interface: IR];

        PendingList: TYPE = LIST OF Pending;

        Pending: TYPE = RECORD[ -- frame, mth, and bcd are parameters to OpenLinkSpace
            frame: GlobalFrameHandle,
            mth: MTHandle,
            bcd: BcdBase,
            index: CARDINAL, -- index into the links area
            link: PrincOps.ControlLink]; -- either a) an index into the IR or b) the actual link

        PendingModule: TYPE = RECORD[ -- frame, mth, and bcd are parameters to OpenLinkSpace
            frame: PrincOps.GlobalFrameHandle, 
            mth: MTHandle, 
            bcd: BcdBase,
            index: CARDINAL, -- index into the links area
            name: Rope.Text, -- name of module we are waiting for
            version: VersionStamp]; -- version of module we are waiting for

    END. 

