-- ProcessingOrderImpl.mesa
-- Last edited by Lewis on 31-Dec-80 10:07:15
-- Last edited by Levin on July 6, 1982 4:36 pm
DIRECTORY
Alloc USING [AddNotify, DropNotify, Handle, Notifier, Words],
BcdDefs USING [MTRecord, MTIndex, MTNull],
Error USING [ImplicitCDIncludesModule, ModuleInTwoSegments],
PackagerDefs USING [
globalData, packctreetype, packtreetype, packsttype, packpotype],
PackHeap USING [GetSpace, FreeSpace],
ProcessingOrder,
SemanticEntry USING [STIndex, STRecord],
SourceBcd USING [
ComponentKind, CTreeIndex, EnumerateModules, EnumerateModulesInConfig,
IsModuleInConfig, IsTableCompiled, moduleCount, ModuleNum,
NullModuleNum, ModuleNumForMti],
SymTabDefs USING [HTIndex],
Table USING [Base, Limit],
Tree: FROM "PackTree" USING [Index, Link, NullIndex, root, Scan, Test],
TreeOps: FROM "PackTreeOps" USING [ListHead, ListLength, ScanList, SearchList];
ProcessingOrderImpl: PROGRAM
IMPORTS Alloc, Error, PackagerDefs, PackHeap, SourceBcd, Tree, TreeOps
EXPORTS ProcessingOrder =
BEGIN OPEN PackagerDefs, ProcessingOrder;
POerror: PROC = {ERROR FindPOerror};
FindPOerror: PUBLIC ERROR = CODE;
-- Parse tree, semantic entry, config tree, and processing order table bases
table: Alloc.Handle ← NIL;
tb, stb, ctreeb, pob: Table.Base;
Notifier: Alloc.Notifier =
BEGIN
tb ← base[PackagerDefs.packtreetype];
stb ← base[PackagerDefs.packsttype];
ctreeb ← base[PackagerDefs.packctreetype];
pob ← base[PackagerDefs.packpotype];
END;
-- ********************* Global Data Structures *********************** --
orderDetermined: BOOLEAN ← FALSE;
-- Head and tail of chain of PORecords for each module
POChainHead: LONG DESCRIPTOR FOR ARRAY SourceBcd.ModuleNum OF POIndex;
POIndex: TYPE = Table.Base RELATIVE POINTER [0..Table.Limit) TO PORecord;
PONull: POIndex = LAST[POIndex];
-- Indicates the next component description to process
PORecord: TYPE = RECORD [
treeNode: Tree.Index, -- component description's parse tree node
link: POIndex]; -- next PORecord in module's chain
InitializeChainHeads: PROC =
BEGIN
i: SourceBcd.ModuleNum;
IF SourceBcd.moduleCount # 0 THEN
BEGIN
POChainHead ← DESCRIPTOR[
PackHeap.GetSpace[SourceBcd.moduleCount*SIZE[POIndex]], SourceBcd.moduleCount];
FOR i IN [0..SourceBcd.moduleCount) DO
POChainHead[i] ← PONull;
ENDLOOP;
END
ELSE POChainHead ← DESCRIPTOR[NIL, 0];
END;
ReleaseChainHeads: PROC =
{IF BASE[POChainHead] # NIL THEN PackHeap.FreeSpace[BASE[POChainHead]]};
InsertInPOChain: PROC [mti: BcdDefs.MTIndex, cdNode: Tree.Index] =
BEGIN -- enter component description tree node in mti's p. o. chain
mNum: SourceBcd.ModuleNum;
newPO, p, last: POIndex;
IF mti # BcdDefs.MTNull THEN
BEGIN
mNum ← SourceBcd.ModuleNumForMti[mti];
IF POChainHead[mNum] = PONull THEN -- empty chain
BEGIN
newPO ← NewPORecord[];
pob[newPO] ← PORecord[treeNode: cdNode, link: PONull];
POChainHead[mNum] ← newPO;
END
ELSE
FOR p ← POChainHead[mNum], pob[p].link UNTIL p = PONull DO
IF pob[p].treeNode = cdNode THEN RETURN; -- already in p.o. chain
last ← p;
REPEAT
FINISHED =>
BEGIN
newPO ← NewPORecord[];
pob[newPO] ← PORecord[treeNode: cdNode, link: PONull];
pob[last].link ← newPO;
END;
ENDLOOP;
END;
END;
NewPORecord: PROC RETURNS [newPO: POIndex] =
BEGIN
newPO ← table.Words[PackagerDefs.packpotype, SIZE[PORecord]];
pob[newPO] ← PORecord[treeNode: Tree.NullIndex, link: PONull];
END;
-- ***************** Module Processing Order Determination ******************
Determine: PUBLIC PROC =
BEGIN
IF orderDetermined THEN POerror[];
table ← PackagerDefs.globalData.ownTable;
table.AddNotify[Notifier];
InitializeChainHeads[];
WITH Tree.root SELECT FROM
subtree =>
BEGIN
EnterExplicitComponentDescs[];
EnterImplicitComponentDescs[];
EnterMainOfComponentDescs[]; -- in fact, these are implicit also
orderDetermined ← TRUE;
VerifyModulesInOneSegment[];
END;
ENDCASE => POerror[];
END;
Destroy: PUBLIC PROC =
BEGIN
IF ~orderDetermined THEN POerror[];
ReleaseChainHeads[];
table.DropNotify[Notifier];
orderDetermined ← FALSE;
END;
IsEmpty: PUBLIC PROC [mti: BcdDefs.MTIndex] RETURNS [reply: BOOLEAN] =
BEGIN
-- return TRUE if no component description nodes to be processed for mti
mNum: SourceBcd.ModuleNum = SourceBcd.ModuleNumForMti[mti];
IF ~orderDetermined THEN POerror[];
IF mNum = SourceBcd.NullModuleNum THEN POerror[];
RETURN[ (POChainHead[mNum] = PONull) ];
END;
Enumerate: PUBLIC PROC [
mti: BcdDefs.MTIndex,
userProc: PROC [cdNode: Tree.Index] RETURNS [stop: BOOLEAN]] =
BEGIN -- output component description nodes to be processed for mti
mNum: SourceBcd.ModuleNum = SourceBcd.ModuleNumForMti[mti];
i: POIndex;
IF ~orderDetermined THEN POerror[];
IF mNum = SourceBcd.NullModuleNum THEN POerror[];
FOR i ← POChainHead[mNum], pob[i].link UNTIL i = PONull DO
IF userProc[pob[i].treeNode] THEN RETURN;
ENDLOOP;
END;
--****** Put Explicit Component Descriptions in Processing Order Chains ******
EnterExplicitComponentDescs: PROC =
{TreeOps.ScanList[Tree.root, EnterExplicitCDsInSegments]};
EnterExplicitCDsInSegments: Tree.Scan =
BEGIN
WITH t SELECT FROM
subtree =>
BEGIN segNode: Tree.Index = index;
IF tb[segNode].name = codeSeg THEN EnterExplicitCDsInOneSeg[segNode];
END;
ENDCASE => POerror[];
END;
EnterExplicitCDsInOneSeg: PROC [segNode: Tree.Index] =
BEGIN
saveIndex: CARDINAL = globalData.textIndex;
globalData.textIndex ← tb[segNode].info;
TreeOps.ScanList[tb[segNode].son[2], EnterExplicitCDsInOneCodePack];
globalData.textIndex ← saveIndex;
END;
EnterExplicitCDsInOneCodePack: Tree.Scan =
BEGIN
ProcessOneCD: Tree.Scan =
BEGIN
WITH t SELECT FROM
subtree =>
BEGIN cdNode: Tree.Index = index;
saveIndex: CARDINAL = globalData.textIndex;
globalData.textIndex ← tb[cdNode].info;
SELECT tb[cdNode].name FROM
allComp => EnterAllCompCD[cdNode];
compItems => EnterCompItemsCD[cdNode];
exceptItems => EnterExceptItemsCD[cdNode];
ENDCASE;
globalData.textIndex ← saveIndex;
END;
ENDCASE => POerror[];
END;
WITH t SELECT FROM
subtree =>
BEGIN cpNode: Tree.Index = index;
TreeOps.ScanList[tb[cpNode].son[2], ProcessOneCD];
END;
ENDCASE => POerror[];
END;
EnterAllCompCD: PROC [cdNode: Tree.Index] =
BEGIN -- ComponentDesc ::= Component
EnterOneModule: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
{InsertInPOChain[mti, cdNode]; RETURN[FALSE]};
WITH tb[cdNode].son[1] SELECT FROM
symbol =>
BEGIN componentSE: SemanticEntry.STIndex = index;
WITH stb[componentSE] SELECT FROM
module => InsertInPOChain[mti, cdNode];
config => SourceBcd.EnumerateModulesInConfig[
kind: prototype, configTreeNode: cNode, userProc: EnterOneModule];
ENDCASE;
END;
ENDCASE => POerror[];
END;
EnterCompItemsCD: PROC [cdNode: Tree.Index] =
BEGIN -- ComponentDesc ::= Component [ItemList]
EnterOneItem: Tree.Scan =
BEGIN
EnterOneModule: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
{InsertInPOChain[mti, cdNode]; RETURN[FALSE]};
WITH t SELECT FROM
symbol =>
BEGIN itemSE: SemanticEntry.STIndex = index;
WITH stb[itemSE] SELECT FROM
module => InsertInPOChain[mti, cdNode];
config => SourceBcd.EnumerateModulesInConfig[
kind: prototype, configTreeNode: cNode, userProc: EnterOneModule];
ENDCASE;
END;
ENDCASE => POerror[];
END;
WITH tb[cdNode].son[1] SELECT FROM
symbol =>
BEGIN componentSE: SemanticEntry.STIndex = index;
WITH stb[componentSE] SELECT FROM
module => InsertInPOChain[mti, cdNode];
config => TreeOps.ScanList[tb[cdNode].son[2], EnterOneItem];
ENDCASE;
END;
ENDCASE => POerror[];
END;
EnterExceptItemsCD: PROC [cdNode: Tree.Index] =
BEGIN -- ComponentDesc ::= Component EXCEPT [ItemList]
WITH tb[cdNode].son[1] SELECT FROM
symbol =>
BEGIN componentSE: SemanticEntry.STIndex = index;
WITH stb[componentSE] SELECT FROM
module => InsertInPOChain[mti, cdNode];
config => ExcludeItems[cdNode, tb[cdNode].son[2], cNode];
ENDCASE;
END;
ENDCASE => POerror[];
END;
ExcludeItems: PROC [
cdNode: Tree.Index,
itemList: Tree.Link, configNode: SourceBcd.CTreeIndex] =
BEGIN -- enter config's modules that are not (in/equal to) any item
EnterModuleIfNotInList: PROC [
module: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
BEGIN
inAnItem: BOOLEAN;
CheckIfModuleInItem: Tree.Test =
BEGIN
SeeIfModuleFound: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
{IF module = mti THEN inAnItem ← TRUE; RETURN[inAnItem]};
WITH t SELECT FROM
symbol => -- item is either a module or a subconfiguration
BEGIN itemSE: SemanticEntry.STIndex = index;
WITH stb[itemSE] SELECT FROM
module => IF module = mti THEN inAnItem ← TRUE;
config => SourceBcd.EnumerateModulesInConfig[
kind: prototype, configTreeNode: cNode, userProc: SeeIfModuleFound];
ENDCASE;
END;
ENDCASE => POerror[];
RETURN[inAnItem]; -- continue search until found or end of list
END;
inAnItem ← FALSE;
TreeOps.SearchList[itemList, CheckIfModuleInItem];
IF ~inAnItem THEN InsertInPOChain[module, cdNode];
RETURN[FALSE];
END;
SourceBcd.EnumerateModulesInConfig[
kind: prototype, configTreeNode: configNode, userProc: EnterModuleIfNotInList];
END;
--***** Put Implicit Component Descriptions in Processing Order Chains *****--
EnterImplicitComponentDescs: PROC =
{TreeOps.ScanList[Tree.root, EnterImplicitCDsInSegments]};
EnterImplicitCDsInSegments: Tree.Scan =
BEGIN
WITH t SELECT FROM
subtree =>
BEGIN segNode: Tree.Index = index;
IF tb[segNode].name = codeSeg THEN EnterImplicitCDsInOneSeg[segNode];
END;
ENDCASE => POerror[];
END;
EnterImplicitCDsInOneSeg: PROC [segNode: Tree.Index] =
BEGIN
saveIndex: CARDINAL = globalData.textIndex;
globalData.textIndex ← tb[segNode].info;
TreeOps.ScanList[tb[segNode].son[2], EnterImplicitCDsInOneCodePack];
globalData.textIndex ← saveIndex;
END;
EnterImplicitCDsInOneCodePack: Tree.Scan =
BEGIN
ProcessOneCD: Tree.Scan =
BEGIN
WITH t SELECT FROM
subtree =>
BEGIN cdNode: Tree.Index = index;
saveIndex: CARDINAL = globalData.textIndex;
globalData.textIndex ← tb[cdNode].info;
SELECT tb[cdNode].name FROM
exceptPacks => EnterExceptPacksCD[cdNode];
itemsExceptPacks => EnterItemsExceptPacksCD[cdNode];
exceptPacksItems => EnterExceptPacksItemsCD[cdNode];
ENDCASE;
globalData.textIndex ← saveIndex;
END;
ENDCASE => POerror[];
END;
WITH t SELECT FROM
subtree =>
BEGIN cpNode: Tree.Index = index;
TreeOps.ScanList[tb[cpNode].son[2], ProcessOneCD];
END;
ENDCASE => POerror[];
END;
EnterExceptPacksCD: PROC [cdNode: Tree.Index] =
BEGIN -- ComponentDesc ::= Component EXCEPT PackList
EnterOneImplicitCDModule: PROC [
mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
BEGIN
InsertImplicitCDModuleInPOChain[mti, cdNode, tb[cdNode].son[2]];
RETURN[FALSE];
END;
WITH tb[cdNode].son[1] SELECT FROM
symbol =>
BEGIN componentSE: SemanticEntry.STIndex = index;
WITH stb[componentSE] SELECT FROM
module => InsertImplicitCDModuleInPOChain[
mti, cdNode, tb[cdNode].son[2]];
config => SourceBcd.EnumerateModulesInConfig[
kind: prototype, configTreeNode: cNode, userProc: EnterOneImplicitCDModule];
ENDCASE;
END;
ENDCASE => POerror[];
END;
InsertImplicitCDModuleInPOChain: PROC [
mti: BcdDefs.MTIndex, cdNode: Tree.Index, packList: Tree.Link] =
BEGIN
implicitCDIncludesMti: BOOLEAN ← FALSE;
CheckCDsOfOnePack: Tree.Scan =
BEGIN
WITH t SELECT FROM
symbol =>
BEGIN cpSE: SemanticEntry.STIndex = index;
WITH stb[cpSE] SELECT FROM
codePack =>
implicitCDIncludesMti ← DoesImplicitCDInPackIncludeMti[
cpId: hti, cpNode: treeNode, module: mti];
ENDCASE;
END;
ENDCASE => POerror[];
END;
-- check that CDs in PackList that reference module mti are all explicit
TreeOps.ScanList[packList, CheckCDsOfOnePack];
IF ~implicitCDIncludesMti THEN InsertInPOChain[mti, cdNode];
END;
DoesImplicitCDInPackIncludeMti: PROC [
cpId: SymTabDefs.HTIndex, cpNode: Tree.Index, module: BcdDefs.MTIndex]
RETURNS [reply: BOOLEAN] =
BEGIN
ProcessOneCD: Tree.Scan =
BEGIN
WITH t SELECT FROM
subtree =>
BEGIN cdNode: Tree.Index = index;
SELECT tb[cdNode].name FROM
exceptPacks, itemsExceptPacks, exceptPacksItems =>
BEGIN -- see if component includes/is module
WITH tb[cdNode].son[1] SELECT FROM
symbol =>
BEGIN componentSE: SemanticEntry.STIndex = index;
WITH stb[componentSE] SELECT FROM
module =>
IF mti = module THEN
BEGIN
Error.ImplicitCDIncludesModule[
error, hti, cpId, module];
reply ← TRUE;
END;
config =>
IF SourceBcd.IsModuleInConfig[prototype, module, cNode] THEN
BEGIN
Error.ImplicitCDIncludesModule[
error, hti, cpId, module];
reply ← TRUE;
END;
ENDCASE;
END;
ENDCASE => POerror[];
END;
ENDCASE; -- not an implicit component description
END;
ENDCASE => POerror[];
END;
reply ← FALSE;
TreeOps.ScanList[tb[cpNode].son[2], ProcessOneCD];
END;
EnterItemsExceptPacksCD: PROC [cdNode: Tree.Index] =
BEGIN -- ComponentDesc ::= Component [ItemList] EXCEPT PackList
EnterOneItem: Tree.Scan =
BEGIN
EnterOneImplicitCDModule: PROC [
mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
BEGIN
InsertImplicitCDModuleInPOChain[mti, cdNode, tb[cdNode].son[3]];
RETURN[FALSE];
END;
WITH t SELECT FROM
symbol =>
BEGIN itemSE: SemanticEntry.STIndex = index;
WITH stb[itemSE] SELECT FROM
module => InsertImplicitCDModuleInPOChain[
mti, cdNode, tb[cdNode].son[3]];
config => SourceBcd.EnumerateModulesInConfig[
kind: prototype, configTreeNode: cNode, userProc: EnterOneImplicitCDModule];
ENDCASE;
END;
ENDCASE => POerror[];
END;
WITH tb[cdNode].son[1] SELECT FROM
symbol =>
BEGIN componentSE: SemanticEntry.STIndex = index;
WITH stb[componentSE] SELECT FROM
config => TreeOps.ScanList[tb[cdNode].son[2], EnterOneItem];
ENDCASE;
END;
ENDCASE => POerror[];
END;
EnterExceptPacksItemsCD: PROC [cdNode: Tree.Index] =
BEGIN -- ComponentDesc ::= Component EXCEPT PackList, [ItemList]
WITH tb[cdNode].son[1] SELECT FROM
symbol =>
BEGIN componentSE: SemanticEntry.STIndex = index;
WITH stb[componentSE] SELECT FROM
module => InsertImplicitCDModuleInPOChain[
mti, cdNode, tb[cdNode].son[2]];
config => ExcludeImplicitCDItems[
cdNode, tb[cdNode].son[3], tb[cdNode].son[3], cNode];
ENDCASE;
END;
ENDCASE => POerror[];
END;
ExcludeImplicitCDItems: PROC [
cdNode: Tree.Index, packList: Tree.Link,
itemList: Tree.Link, configNode: SourceBcd.CTreeIndex] =
BEGIN -- enter config's modules that are not (in/equal to) any item
EnterModuleIfNotInList: PROC [
module: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
BEGIN
inAnItem: BOOLEAN;
CheckIfModuleInItem: Tree.Test =
BEGIN
SeeIfModuleFound: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
{IF module = mti THEN inAnItem ← TRUE; RETURN[inAnItem]};
WITH t SELECT FROM
symbol => -- item is either a module or a subconfiguration
BEGIN itemSE: SemanticEntry.STIndex = index;
WITH stb[itemSE] SELECT FROM
module => IF module = mti THEN inAnItem ← TRUE;
config => SourceBcd.EnumerateModulesInConfig[
kind: prototype, configTreeNode: cNode, userProc: SeeIfModuleFound];
ENDCASE;
END;
ENDCASE => POerror[];
RETURN[inAnItem]; -- continue search until found or end of list
END;
inAnItem ← FALSE;
TreeOps.SearchList[itemList, CheckIfModuleInItem];
IF ~inAnItem THEN
InsertImplicitCDModuleInPOChain[module, cdNode, packList];
RETURN[FALSE];
END;
SourceBcd.EnumerateModulesInConfig[
kind: prototype, configTreeNode: configNode, userProc: EnterModuleIfNotInList];
END;
-- ***** Put MAIN OF Component Descriptions in Processing Order Chains *****
EnterMainOfComponentDescs: PROC =
{TreeOps.ScanList[Tree.root, EnterMainOfCDsInSegments]};
EnterMainOfCDsInSegments: Tree.Scan =
BEGIN
WITH t SELECT FROM
subtree =>
BEGIN segNode: Tree.Index = index;
IF tb[segNode].name = codeSeg THEN EnterMainOfCDsInOneSeg[segNode];
END;
ENDCASE => POerror[];
END;
EnterMainOfCDsInOneSeg: PROC [segNode: Tree.Index] =
BEGIN
saveIndex: CARDINAL = globalData.textIndex;
globalData.textIndex ← tb[segNode].info;
TreeOps.ScanList[tb[segNode].son[2], EnterMainOfCDsInOneCodePack];
globalData.textIndex ← saveIndex;
END;
EnterMainOfCDsInOneCodePack: Tree.Scan =
BEGIN
ProcessOneCD: Tree.Scan =
BEGIN
WITH t SELECT FROM
subtree =>
BEGIN cdNode: Tree.Index = index;
IF tb[cdNode].name = mainProcs THEN EnterMainOfCD[cdNode];
END;
ENDCASE => POerror[];
END;
WITH t SELECT FROM
subtree =>
BEGIN cpNode: Tree.Index = index;
TreeOps.ScanList[tb[cpNode].son[2], ProcessOneCD];
END;
ENDCASE => POerror[];
END;
EnterMainOfCD: PROC [cdNode: Tree.Index] =
BEGIN -- ComponentDesc ::= MAIN OF PackList
saveIndex: CARDINAL = globalData.textIndex;
packList: Tree.Link = tb[cdNode].son[1];
firstInList: Tree.Link;
EnterModulesOfOneOfSegsPacks: Tree.Scan =
BEGIN
WITH t SELECT FROM
subtree =>
BEGIN cpNode: Tree.Index = index;
InsertOneMainOfPacksModules[cpNode: cpNode, mainOfCdNode: cdNode];
END;
ENDCASE => POerror[];
END;
EnterModulesOfOneMainOfPack: Tree.Scan =
BEGIN
WITH t SELECT FROM
symbol =>
BEGIN cpSE: SemanticEntry.STIndex = index;
WITH stb[cpSE] SELECT FROM
codePack => InsertOneMainOfPacksModules[
cpNode: treeNode, mainOfCdNode: cdNode];
ENDCASE;
END;
ENDCASE => POerror[];
END;
globalData.textIndex ← tb[cdNode].info;
IF TreeOps.ListLength[packList] = 1 THEN
BEGIN -- packlist might only be name of current code segment
firstInList ← TreeOps.ListHead[packList];
WITH firstInList SELECT FROM
symbol =>
BEGIN firstSE: SemanticEntry.STIndex = index;
WITH stb[firstSE] SELECT FROM
segment =>
BEGIN segNode: Tree.Index = treeNode;
TreeOps.ScanList[
tb[segNode].son[2], EnterModulesOfOneOfSegsPacks];
RETURN;
END;
ENDCASE;
END;
ENDCASE => POerror[];
END;
TreeOps.ScanList[packList, EnterModulesOfOneMainOfPack];
globalData.textIndex ← saveIndex;
END;
InsertOneMainOfPacksModules: PROC [
cpNode: Tree.Index, mainOfCdNode: Tree.Index] =
BEGIN -- enter all modules in a code pack referenced by a MAIN OF
ProcessOneCD: Tree.Scan =
BEGIN
InsertAMainOfPacksModule: PROC [
mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
{InsertInPOChain[mti, mainOfCdNode]; RETURN[FALSE]};
WITH t SELECT FROM
subtree =>
BEGIN cdNode: Tree.Index = index;
IF tb[cdNode].name # mainProcs THEN
WITH tb[cdNode].son[1] SELECT FROM
symbol =>
BEGIN componentSE: SemanticEntry.STIndex = index;
WITH stb[componentSE] SELECT FROM
module =>
IF ~SourceBcd.IsTableCompiled[mti] THEN
InsertInPOChain[mti, mainOfCdNode];
config => SourceBcd.EnumerateModulesInConfig[
kind: prototype, configTreeNode: cNode, userProc: InsertAMainOfPacksModule];
ENDCASE;
END;
ENDCASE => POerror[];
END;
ENDCASE => POerror[];
END;
TreeOps.ScanList[tb[cpNode].son[2], ProcessOneCD];
END;
-- ************ Verify That a Module Appears in Only One Segment ************-
VerifyModulesInOneSegment: PROC =
BEGIN
SourceBcd.EnumerateModules[VerifyAModuleInOneSegment];
END;
VerifyAModuleInOneSegment: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
BEGIN
modulesSeg: Tree.Index;
CheckOneCDNode: PROC [cdNode: Tree.Index] RETURNS [stop: BOOLEAN] =
BEGIN
IF modulesSeg = Tree.NullIndex THEN modulesSeg ← tb[cdNode].seg
ELSE IF modulesSeg # tb[cdNode].seg THEN
BEGIN
segId1, segId2: SymTabDefs.HTIndex;
WITH tb[modulesSeg].son[1] SELECT FROM
hash => segId1 ← index;
ENDCASE => POerror[];
WITH tb[tb[cdNode].seg].son[1] SELECT FROM
hash => segId2 ← index;
ENDCASE => POerror[];
Error.ModuleInTwoSegments[error, mti, segId1, segId2];
RETURN[TRUE];
END;
RETURN[FALSE];
END;
modulesSeg ← Tree.NullIndex;
Enumerate[mti, CheckOneCDNode];
RETURN[FALSE];
END;
END.