-- CTLoad.Mesa, last edit March 10, 1983 11:25 am
-- the compile tool loader interface

DIRECTORY
  BcdDefs: TYPE USING [Link, NameRecord, NullLink],
  BcdOps: TYPE USING [BcdBase, EXPHandle, MTHandle],
  File: TYPE USING [Capability],
  IO: TYPE USING[Handle],
  MiscAlpha: TYPE USING[alpha],
  Mopcodes: TYPE USING [zMISC],
  PilotLoaderOps: TYPE USING[FrameList],
  PilotLoadStateOps: TYPE USING[ConfigIndex, Map],
  PrincOps: TYPE USING [ControlLink, ControlModule, GFTIndex, GlobalFrameHandle, 
  	MaxNGfi, NullControl, NullLink],
  Rope: TYPE USING[Text],
  TimeStamp: TYPE USING [Null, Stamp];
			
			
CTLoad: 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 = REF InterfaceSeqRecord;
InterfaceSeqRecord: TYPE = RECORD[
	name: Rope.Text ← NIL,	-- the interface (module) name
	bcdVers: TimeStamp.Stamp ← TimeStamp.Null,	-- func time stamp
	resolved: BOOL ← FALSE,	-- all clinks have been filled in
	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
		]
	];

LoadInfoSeq: TYPE = REF 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
	map: PilotLoadStateOps.Map ← NIL,	-- map for this bcd, not fake config
	frameList: PilotLoaderOps.FrameList ← NIL,	-- ptrs to frames
	-- 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
	];
	
-- 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 = REF 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 = REF ImpExpSeqRecord;
ImpExpSeqRecord: TYPE = RECORD[
	size: CARDINAL ← 0,
	body: SEQUENCE maxsize: CARDINAL OF InterfaceSeq
	];

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

InvalidFile: ERROR [File.Capability];
-- raised by LoadGlobalFrames and LoadIncremental

LoadGlobalFrames: PROC[cap: File.Capability, config: PilotLoadStateOps.ConfigIndex,
	oldConfigGfi: PrincOps.GFTIndex, out: IO.Handle] 
	RETURNS[loadinfoseq: CTLoad.LoadInfoSeq, 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];

NSToRope: PROC[bcdbase: BcdOps.BcdBase, name: BcdDefs.NameRecord] 
	RETURNS[resultstr: Rope.Text];
ConvertLink: PROC [bl: BcdDefs.Link] RETURNS [cl: PrincOps.ControlLink];

aLongBlkZ: MiscAlpha.alpha = 102B;

Zero: PROC[lp: LONG POINTER, nwords: CARDINAL] RETURNS[LONG POINTER] = 
MACHINE CODE {
	Mopcodes.zMISC, aLongBlkZ
	};

FindVariableLink: PROC[blink: BcdDefs.Link, loadinfoseq: LoadInfoSeq,
	frame: PrincOps.GlobalFrameHandle, bcdbase: BcdOps.BcdBase] 
	RETURNS[clink: PrincOps.ControlLink];

-- 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];
-- always returns NIL
FreeInterfaceSeq: PROC[interfaceseq: InterfaceSeq] RETURNS[InterfaceSeq];

AllocateInterfaceSeq: PROC[name: Rope.Text, size: CARDINAL] 
	RETURNS[interfaceseq: InterfaceSeq];
-- always returns NIL
FreeLoadInfoSeq: PROC[loadinfoseq: LoadInfoSeq] RETURNS[LoadInfoSeq];

}.