-- LowLoader.Mesa, last edit January 6, 1983 2:08 pm
-- the independent modeller loader interface

DIRECTORY
  BcdDefs: TYPE USING [Link, NameRecord, NullLink],
  BcdOps: TYPE USING [BcdBase, EXPHandle, MTHandle, NameString],
  File: TYPE USING [Capability],
  IO: TYPE USING[Handle],
  PrincOps: TYPE USING [ControlLink, ControlModule, GFTIndex, GlobalFrameHandle, 
  	MaxNGfi, NullControl, NullLink],
  Subr: TYPE USING[TTYProcs],
  TimeStamp: TYPE USING [Null, Stamp];
			
			
LowLoader: DEFINITIONS = {

-- this is an Interface Record in the usual parlance
-- for procedures, this ControlLink is [procedure[gfi: gfi, ep: ep, tag: TRUE]
-- for exported variables this is the absolute address of the variable
-- for PROGRAM modules this is a GlobalFramePointer
InterfaceSeq: TYPE = LONG POINTER TO InterfaceSeqRecord;
InterfaceSeqRecord: TYPE = RECORD[
	intname: LONG STRING ← NIL,	-- the interface (module) name
	versstamp: TimeStamp.Stamp ← TimeStamp.Null,	-- func time stamp
	isfromloadstate: BOOL ← FALSE,
	size: CARDINAL ← 0,
	body: SEQUENCE maxsize: CARDINAL OF RECORD[
		clink: PrincOps.ControlLink ← PrincOps.NullLink,	-- the actual link
		blink: BcdDefs.Link ← BcdDefs.NullLink		-- dummy link for exports
		]
	];
-- the storage for intname and the sequence always comes from LoaderImpl

LoadInfoSeq: TYPE = LONG POINTER TO LoadInfoSeqRecord;
LoadInfoSeqRecord: TYPE = RECORD[
	-- if true then this module must be replaced in the load state
	mustreplace: BOOL ← FALSE,
	-- if true then all links for these frames are resolved
	linksresolved: BOOL ← FALSE,
	-- the control module to start
	cm: PrincOps.ControlModule ← PrincOps.NullControl,
	-- the in core bcd
	bcdbase: BcdOps.BcdBase ← NIL,
	dummymapseq: DummyMapSeq ← NIL, -- [0 to bcdbase.firstdummy+bcdbase.nDummies)
	impexpseq: ImpExpSeq ← NIL,	-- [0 to bcdbase.nImports)
	configGfi: PrincOps.GFTIndex ← 0,-- dummy gfi in resulting loaded config
	-- this size is the # of modules in this bcd (= bcdbase.nModules)
	size: CARDINAL ← 0,
	body: SEQUENCE maxsize: CARDINAL OF LoadRecord
	];
LoadRecord: TYPE = RECORD[
	frame: PrincOps.GlobalFrameHandle ← NIL,	-- the gfh for module
	framesize: CARDINAL ← 0,	-- shadows the mth.framesize
	ngfi: CARDINAL ← 0		-- shadows the mth.ngfi
	];
-- the storage for the LoadInfoSeqRecord,  DummyMapSeqRecord,
-- and impexpseq always comes from LoaderImpl
	
-- for dummymapseq[0 .. bcdbase.firstdummy) this is 
-- the real gfi for the module (in a config)
-- for dummymapseq[bcdbase.firstdummy .. bcdbase.ndummies + bcdbase.firstdummy)
-- this is the index into the ImportTable for the dummy gfi's
DummyMapSeq: TYPE = LONG POINTER TO DummyMapSeqRecord;
DummyMapSeqRecord: TYPE = RECORD[
	size: CARDINAL ← 0,
	body: SEQUENCE maxsize: CARDINAL OF RECORD[
		ind: PrincOps.GFTIndex,
		whichone: [0..PrincOps.MaxNGfi)		-- this ranges between 0 and 3
		]
	];

-- the ith element of this is the interface record
-- associated with the ith import
-- import #3 has been matched up with InterfaceRecord impexpseq[3], etc.
ImpExpSeq: TYPE = LONG POINTER TO ImpExpSeqRecord;
ImpExpSeqRecord: TYPE = RECORD[
	size: CARDINAL ← 0,
	body: SEQUENCE maxsize: CARDINAL OF InterfaceSeq
	];

ReplaceResult: TYPE = {ok, configNotReplaceable, frameTooBig, ngfiTooBig,
	cantCopyOldBcd, checkForMRFailed, compilerSaysNo};

-- will read in bcd
LoadBcdAndCount: PROC[cap: File.Capability, bcdsfn: LONG STRING, 
	oldnwords: CARDINAL]
	RETURNS[loadinfoseq: LoadInfoSeq, newnwords, nbcdheaderpages, 
		ncodepages: CARDINAL];
-- will map code segments
LoadFrame: PROC[loadinfoseq: LoadInfoSeq, oldframeptr: POINTER, 
	window: IO.Handle, cap: File.Capability,
	beginning, ending: LONG CARDINAL, oldConfigGfi: PrincOps.GFTIndex] 
	RETURNS[newframeptr: POINTER, newConfigGfi: PrincOps.GFTIndex];

-- will read in bcd header and map code segments
LoadIncremental: PROC[bcdcap: File.Capability, loadinfoseq: LoadInfoSeq, 
	window: IO.Handle] RETURNS[replaceResult: ReplaceResult];

BuildInterface: PROC[loadinfoseq: LoadInfoSeq, eth: BcdOps.EXPHandle] 
	RETURNS[interfaceseq: InterfaceSeq];
BuildFramePtrInterface: PROC[bcdbase: BcdOps.BcdBase, 
	frame: PrincOps.GlobalFrameHandle] RETURNS[interfaceseq: InterfaceSeq];
EqualStringAndName: PROC[sym: LONG STRING, namestring: BcdOps.NameString,
	name: BcdDefs.NameRecord] RETURNS[equal: BOOL];

LinkSegmentLength: PROC[mth: BcdOps.MTHandle, bcd: BcdOps.BcdBase] 
  	RETURNS[CARDINAL];
IthLink: PROC[mth: BcdOps.MTHandle, i: CARDINAL, bcd: BcdOps.BcdBase] 
  	RETURNS[BcdDefs.Link];
CopyNStoLS: PROC[resultstr: LONG STRING, bcdbase: BcdOps.BcdBase, 
	name: BcdDefs.NameRecord];
ConvertLink: PROC [bl: BcdDefs.Link] RETURNS [cl: PrincOps.ControlLink];
Zero: PROC[lp: LONG POINTER, nwords: CARDINAL];
FindVariableLink: PROC[blink: BcdDefs.Link, loadinfoseq: LoadInfoSeq,
	frame: PrincOps.GlobalFrameHandle, bcdbase: BcdOps.BcdBase] 
	RETURNS[clink: PrincOps.ControlLink];


-- load state operations
IncorporateLoadStateChanges: PROC[window: Subr.TTYProcs, askCompiler: BOOL];
GetIntFromLoadState: PROC[intname: LONG STRING, vers: TimeStamp.Stamp] 
	RETURNS[interfaceseq: InterfaceSeq];
AddToLoadState: PROC[interfaceseq: InterfaceSeq];

-- frame link space operations
OpenLinkSpace: PROC [frame: PrincOps.GlobalFrameHandle, 
  	mth: BcdOps.MTHandle, bcd: BcdOps.BcdBase ← NIL]
	RETURNS[LONG POINTER];
ReadLink: PROC [offset: CARDINAL] RETURNS [link: PrincOps.ControlLink];
WriteLink: PROC [offset: CARDINAL, link: PrincOps.ControlLink];
CloseLinkSpace: PROC [frame: PrincOps.GlobalFrameHandle];


-- to alloc/ deallocate the structures that some from above 
-- call these procedures

AllocateLoadInfoSeq: PROC[bcdbase: BcdOps.BcdBase] 
	RETURNS[loadinfoseq: LoadInfoSeq];
FreeInterfaceSeq: PROC[interfaceseq: InterfaceSeq];

AllocateInterfaceSeq: PROC[intname: LONG STRING, size: CARDINAL] 
	RETURNS[interfaceseq: InterfaceSeq];
FreeLoadInfoSeq: PROC[loadinfoseq: LoadInfoSeq];

-- call only once
ShutDown: PROC;
    
}.