-- 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.