<> <> <> <> <> <> DIRECTORY Ascii USING [NUL, SP], BasicTime USING [FromPupTime, GMT, nullGMT, ToPupTime], BcdDefs USING [CTHandle, FPHandle, MTHandle, SPHandle], Convert USING [Error, IntFromRope], FS USING [Error, FileInfo, StreamOpen], IO USING [BreakProc, card, char, Close, EndOfStream, Error, GetChar, GetIndex, GetTime, GetTokenRope, PutChar, PutF, PutFR, PutRope, rope, SkipWhitespace, STREAM, time], IOClasses USING [CreateCommentFilterStream], MB USING [Abort, BHandle, DoAllBCDs, DoAllFramePacks, DoAllSpaces, DoAllTopLevelConfigs, Error, GetFrameWeight, GetFsiChain, Handle, InstanceToMTHandle, ListType, NameToCTHandle, NameToFPHandle, NameToG, NameToMTHandle, DoAllModules, NameToSPHandle, ResetConfig, SetConfig, SetFrameWeight, SetFsiChain], PrincOps USING [FrameSizeIndex, FrameVec, GFTIndex, GlobalFrameHandle, Priority, PsbIndex, StateVector, wordsPerPage], Rope USING [Cat, Equal, FromChar, ROPE], SystemVersion USING [Date]; MBParse: CEDAR PROGRAM IMPORTS BasicTime, Convert, FS, IO, IOClasses, MB, Rope EXPORTS MB = BEGIN OPEN MB; <> <> <> <> <> <> <> <> << GLOBALFRAME [ configPartList ]>> << SPACE [ nameList ] | CODEPACK [ nameList ] |>> << FRAME [ nameList ] | FRAMEPACK [ nameList ] |>> << BCD [ nameList ] |>> <> <> <> <> <> ROPE: TYPE = Rope.ROPE; data: MB.Handle _ NIL; source: IO.STREAM _ NIL; noTrapList: Node; controlList: Node; stateLists: ARRAY ListType OF Node; -- circularly linked, pointer is to last element wartConfig, wartModule: ROPE; Node: TYPE = REF Item; Item: TYPE = RECORD [ link: Node, body: SELECT type: * FROM name => [name: ROPE], dot => [module, instance: ROPE], config => [name: ROPE, list: Node], space => [list: Node], frame => [list: Node], globalframe => [list: Node], code => [list: Node], bcd => [list: Node], ENDCASE ]; Separator: TYPE = {semiColon, colon, comma, openBracket, closeBracket, dot}; Keyword: TYPE = { resident, resDesc, in, frame, framepack, space, codepack, globalFrame, code, bcd, wart, noTrap, control, frameweight, framecount, gft, mdsbase, codebase, pdapages, framePages, processes, svSize, nSV, all, version, uCodeDolphin, uCodeDorado, uCodeDandelion, uCodeDicentra}; keywords: ARRAY Keyword OF ROPE = [ "RESIDENT", "RESIDENTDESCRIPTOR", "IN", "FRAME", "FRAMEPACK", "SPACE", "CODEPACK", "GLOBALFRAME", "CODE", "BCD", "WART", "NOTRAP", "CONTROL", "FRAMEWEIGHT", "FRAMECOUNT", "GFT", "MDSBASE", "CODEBASE", "PDAPAGES", "FRAMEPAGES", "PROCESSES", "STATEVECTORSIZE", "STATEVECTORCOUNT", "ALL", "VERSION", "UCODEDOLPHIN", "UCODEDORADO", "UCODEDANDELION", "UCODEDICENTRA"]; separators: ARRAY Separator OF CHAR = [';, ':, ',, '[, '], '.]; lastSep: CHARACTER; InputFile: TYPE = RECORD [ name: ROPE, create: BasicTime.GMT _ BasicTime.nullGMT ]; inputFiles: LIST OF InputFile _ NIL; -- circularly linked; pointer is to last element <> InitParse: PUBLIC PROC [h: MB.Handle] = { data _ h; ClearGlobals[]; }; FinishParse: PUBLIC PROC = { BreakCircularities: PROC = { <> UnloopList: PROC [tail: Node] = { p: Node _ tail; IF p = NIL THEN RETURN; DO p _ p.link; WITH p SELECT FROM p: REF name Item => NULL; p: REF dot Item => NULL; p: REF config Item => UnloopList[p.list]; p: REF space Item => UnloopList[p.list]; p: REF frame Item => UnloopList[p.list]; p: REF globalframe Item => UnloopList[p.list]; p: REF code Item => UnloopList[p.list]; p: REF bcd Item => UnloopList[p.list]; ENDCASE; IF p = tail THEN EXIT; ENDLOOP; tail.link _ NIL; }; IF inputFiles ~= NIL THEN inputFiles.rest _ NIL; FOR list: ListType IN ListType DO UnloopList[stateLists[list]]; ENDLOOP; UnloopList[controlList]; UnloopList[noTrapList]; }; BreakCircularities[]; ClearGlobals[]; data _ NIL; }; ClearGlobals: PROC = { noTrapList _ NIL; controlList _ NIL; stateLists _ ALL[NIL]; wartConfig _ wartModule _ NIL; source _ NIL; inputFiles _ NIL; }; ProcessInput: PUBLIC PROC [file: ROPE] = { inputFileL: LIST OF InputFile = CONS[ InputFile[ name: file, create: FS.FileInfo[file ! FS.Error => IF error.group = $user THEN MB.Error[error.explanation] ].created ], NIL ]; source _ IOClasses.CreateCommentFilterStream[FS.StreamOpen[file]]; ParseInput[]; source.Close[]; -- note: assumed to close the backing stream <> IF inputFiles = NIL THEN inputFileL.rest _ inputFileL ELSE {inputFileL.rest _ inputFiles.rest; inputFiles.rest _ inputFileL}; inputFiles _ inputFileL; }; EchoInput: PUBLIC PROC = { loadmap: IO.STREAM = data.loadmap; EchoList: PROC [tail: Node, topLevel: BOOL _ TRUE] = { p: Node _ tail; IF topLevel THEN loadmap.PutRope[" "] ELSE loadmap.PutChar['[]; IF p ~= NIL THEN DO p _ p.link; WITH p SELECT FROM p: REF name Item => loadmap.PutRope[p.name]; p: REF dot Item => loadmap.PutF["%g.%g", IO.rope[p.module], IO.rope[p.instance]]; p: REF config Item => {loadmap.PutRope[p.name]; EchoList[p.list, FALSE]}; p: REF space Item => {loadmap.PutRope[keywords[codepack]]; EchoList[p.list, FALSE]}; p: REF frame Item => {loadmap.PutRope[keywords[framepack]]; EchoList[p.list, FALSE]}; p: REF globalframe Item => {loadmap.PutRope[keywords[globalFrame]]; EchoList[p.list, FALSE]}; p: REF code Item => {loadmap.PutRope[keywords[code]]; EchoList[p.list, FALSE]}; p: REF bcd Item => {loadmap.PutRope[keywords[bcd]]; EchoList[p.list, FALSE]}; ENDCASE; IF p = tail THEN EXIT; loadmap.PutRope[IF topLevel THEN ",\N " ELSE ", "]; ENDLOOP; IF topLevel THEN loadmap.PutRope[";\N"] ELSE loadmap.PutChar[']]; }; IF inputFiles ~= NIL THEN { inputFileL: LIST OF InputFile _ inputFiles.rest; loadmap.PutF["Parameter File%g:\N\N", IO.rope[IF inputFileL ~= inputFiles THEN "s" ELSE NIL]]; DO loadmap.PutF[" %39j %t\N", IO.rope[inputFileL.first.name], IO.time[inputFileL.first.create] ]; IF inputFileL = inputFiles THEN EXIT; inputFileL _ inputFileL.rest; ENDLOOP; loadmap.PutChar['\N]; }; loadmap.PutRope["Input Parameters:\N\N"]; loadmap.PutF[" Version = %d.%d%g\N", IO.card[data.header.release.major], IO.card[data.header.release.minor], IO.rope[ IF data.header.release.patch = 0 THEN NIL ELSE IO.PutFR[".%d", IO.card[data.header.release.patch]]] ]; loadmap.PutRope[" Earliest acceptable microcode:\N"]; IF data.header.requiredUCode[dolphin] ~= 0 THEN loadmap.PutF[" Dolphin: %t\N", IO.time[BasicTime.FromPupTime[data.header.requiredUCode[dolphin]]] ]; IF data.header.requiredUCode[dorado] ~= 0 THEN loadmap.PutF[" Dorado: %t\N", IO.time[BasicTime.FromPupTime[data.header.requiredUCode[dorado]]] ]; IF data.header.requiredUCode[dandelion] ~= 0 THEN loadmap.PutF[" Dandelion: %t\N", IO.time[BasicTime.FromPupTime[data.header.requiredUCode[dandelion]]] ]; IF data.header.requiredUCode[dicentra] ~= 0 THEN loadmap.PutF[" Dicentra: %t\N", IO.time[BasicTime.FromPupTime[data.header.requiredUCode[dicentra]]] ]; loadmap.PutF["\N GFT length = %d\N PDA pages = %d\N Processes = %d\N", IO.card[data.gftLength], IO.card[data.pdaPages], IO.card[data.nProcesses]]; loadmap.PutF[" MDS base = page %d [%n]\N Code base = page %d [%n]\N\N", IO.card[data.mdsBase], IO.card[data.mdsBase.LONG*PrincOps.wordsPerPage], IO.card[data.codeBase], IO.card[data.codeBase.LONG*PrincOps.wordsPerPage]]; loadmap.PutF[" Statevector length = %d\N Statevector counts:\N", IO.card[data.svSize]]; FOR i: CARDINAL IN PrincOps.Priority DO loadmap.PutF["%6d: %d\N", IO.card[i], IO.card[data.stateVectorCounts[i]]]; ENDLOOP; loadmap.PutF[ "\N Frame heap pages = %d\N Frame distribution: [ FSI (words): %g, next FSI ]\N", IO.card[data.framePages], IO.rope[IF data.framePages = 0 THEN "count" ELSE "weight"]]; FOR i: PrincOps.FrameSizeIndex IN PrincOps.FrameSizeIndex DO loadmap.PutF[" %3d (%4d): %d, %d\N", IO.card[i], IO.card[PrincOps.FrameVec[i]], IO.card[MB.GetFrameWeight[i]], IO.card[MB.GetFsiChain[i]] ]; ENDLOOP; loadmap.PutF["\N Wart: %g", IO.rope[wartModule]]; IF wartConfig ~= NIL THEN loadmap.PutF[" in configuration %g", IO.rope[wartConfig]]; loadmap.PutChar['\N]; IF stateLists[resident] ~= NIL THEN { loadmap.PutRope["\N Resident:\N"]; EchoList[stateLists[resident]]}; IF stateLists[resDesc] ~= NIL THEN { loadmap.PutRope["\N Resident Descriptor:\N"]; EchoList[stateLists[resDesc]]}; IF stateLists[in] ~= NIL THEN { loadmap.PutRope["\N Initially In:\N"]; EchoList[stateLists[in], TRUE]}; IF noTrapList ~= NIL THEN { loadmap.PutRope["\N No Trap:\N"]; EchoList[noTrapList, TRUE]}; IF controlList ~= NIL THEN { loadmap.PutRope["\N Control:\N"]; EchoList[controlList, TRUE]}; loadmap.PutRope["\N\N"]; }; ParseInput: PROC = { lastSep _ Ascii.NUL; DO ENABLE IO.EndOfStream => ErrorMsg["Unexpected end of input"]; SELECT GetKeyword[ ! IO.EndOfStream => EXIT] FROM gft => data.gftLength _ GetNumber[low: PrincOps.GFTIndex.FIRST+1, high: PrincOps.GFTIndex.LAST+1]; mdsbase => data.mdsBase _ GetNumber[]; codebase => data.codeBase _ GetNumber[]; framePages => data.framePages _ GetNumber[low: 0, high: 255]; pdapages => data.pdaPages _ GetNumber[low: 1, high: 256]; processes => data.nProcesses _ GetNumber[low: PrincOps.PsbIndex.FIRST+1, high: PrincOps.PsbIndex.LAST+1]; nSV => { svIndex: CARDINAL = GetNumber[low: PrincOps.Priority.FIRST, high: PrincOps.Priority.LAST]; count: CARDINAL; GetRequiredSep[comma]; count _ GetNumber[]; data.stateVectorCounts[svIndex] _ IF data.stateVectorCounts[svIndex] = CARDINAL.LAST THEN count ELSE data.stateVectorCounts[svIndex] + count; }; svSize => data.svSize _ GetNumber[low: SIZE[PrincOps.StateVector]]; frameweight, framecount => { Fsi: TYPE = PrincOps.FrameSizeIndex; frameIndex: Fsi = GetNumber[low: Fsi.FIRST, high: Fsi.LAST]; sep: Separator; GetRequiredSep[comma]; MB.SetFrameWeight[index: frameIndex, weight: GetNumber[]]; sep _ GetSep[]; SELECT sep FROM semiColon => SaveSep[sep]; comma => MB.SetFsiChain[ index: frameIndex, fsiNext: GetNumber[low: Fsi.FIRST, high: Fsi.LAST]]; ENDCASE => ErrorMsg[Rope.Cat["Unexpected separator '", Rope.FromChar[separators[sep]], "'"]]; }; version => { sep: Separator; data.header.release.major _ GetNumber[]; GetRequiredSep[dot]; data.header.release.minor _ GetNumber[]; sep _ GetSep[]; SELECT sep FROM dot => data.header.release.patch _ GetNumber[]; semiColon => SaveSep[sep]; ENDCASE => ErrorMsg[Rope.Cat["Unexpected separator '", Rope.FromChar[separators[sep]], "'"]]; }; uCodeDolphin => data.header.requiredUCode[dolphin] _ GetUCodeDate[uCodeDolphin]; uCodeDorado => data.header.requiredUCode[dorado] _ GetUCodeDate[uCodeDorado]; uCodeDandelion => data.header.requiredUCode[dandelion] _ GetUCodeDate[uCodeDandelion]; uCodeDicentra => data.header.requiredUCode[dicentra] _ GetUCodeDate[uCodeDicentra]; wart => { r: ROPE = GetID[]; SELECT GetSep[] FROM semiColon => {wartConfig _ NIL; wartModule _ r; SaveSep[semiColon]}; openBracket => { wartConfig _ r; wartModule _ GetID[]; GetRequiredSep[closeBracket]; }; ENDCASE => SyntaxError[wart]; }; resident => stateLists[resident] _ GetGeneralList[stateLists[resident]]; resDesc => stateLists[resDesc] _ GetGeneralList[stateLists[resDesc]]; in => stateLists[in] _ GetGeneralList[stateLists[in]]; noTrap => noTrapList _ GetModuleList[noTrapList]; control => controlList _ GetNameList[controlList]; ENDCASE; GetRequiredSep[semiColon]; ENDLOOP; }; GetKeyword: PROC RETURNS [key: Keyword] = { id: ROPE = GetID[]; IF GetSep[] ~= colon THEN ErrorMsg[IO.PutFR["No colon following keyword '%g'", IO.rope[id]]]; FOR key IN Keyword DO IF id.Equal[keywords[key]] THEN RETURN ENDLOOP; ErrorMsg[IO.PutFR["Unrecognizable keyword '%g'", IO.rope[id]]]; }; GetRequiredSep: PROC [esep: Separator] = { IF GetSep[] ~= esep THEN ErrorMsg[IO.PutFR["Expected separator '%g' not found", IO.char[separators[esep]]]]; }; GetGeneralList: PROC [oldList: Node _ NIL] RETURNS [list: Node] = { list _ oldList; DO sep: Separator; list _ AppendNode[list, GetListItem[]]; IF (sep _ GetSep[]) ~= comma THEN {SaveSep[sep]; EXIT}; ENDLOOP; }; GetListItem: PROC RETURNS [item: Node] = { r: ROPE = GetID[]; SELECT TRUE FROM r.Equal[keywords[space]], r.Equal[keywords[codepack]] => item _ NEW[Item _ [link: NIL, body: space[list: GetBracketedNameList[]]]]; r.Equal[keywords[frame]], r.Equal[keywords[framepack]] => item _ NEW[Item _ [link: NIL, body: frame[list: GetBracketedNameList[]]]]; r.Equal[keywords[bcd]] => item _ NEW[Item _ [link: NIL, body: bcd[list: GetBracketedNameList[]]]]; r.Equal[keywords[globalFrame]] => item _ NEW[Item _ [link: NIL, body: globalframe[list: GetBracketedConfigPartList[]]]]; r.Equal[keywords[code]] => item _ NEW[Item _ [link: NIL, body: code[list: GetBracketedConfigPartList[]]]]; ENDCASE => item _ GetConfigPart[r]; }; GetBracketedConfigPartList: PROC RETURNS [list: Node] = { GetRequiredSep[openBracket]; list _ GetConfigPartList[]; GetRequiredSep[closeBracket]; }; GetConfigPartList: PROC RETURNS [list: Node] = { list _ NIL; DO sep: Separator; list _ AppendNode[list, GetConfigPart[GetID[]]]; IF (sep _ GetSep[]) ~= comma THEN {SaveSep[sep]; EXIT}; ENDLOOP; }; GetConfigPart: PROC [r: ROPE] RETURNS [item: Node] = { sep: Separator = GetSep[]; IF sep = openBracket THEN { item _ NEW[Item _ [link: NIL, body: config[name: r, list: GetModuleList[]]]]; GetRequiredSep[closeBracket]; } ELSE {SaveSep[sep]; item _ GetModule[first: r]}; }; GetModuleList: PROC [oldList: Node _ NIL] RETURNS [list: Node] = { list _ oldList; DO sep: Separator; list _ AppendNode[list, GetModule[]]; IF (sep _ GetSep[]) ~= comma THEN {SaveSep[sep]; EXIT}; ENDLOOP; }; GetModule: PROC [first: ROPE _ NIL] RETURNS [node: Node] = { sep: Separator; IF first = NIL THEN first _ GetID[]; IF (sep _ GetSep[]) = dot THEN node _ NEW[Item _ [link: NIL, body: dot[module: first, instance: GetID[]]]] ELSE { SaveSep[sep]; node _ NEW[Item _ [link: NIL, body: name[name: first]]]; }; }; GetBracketedNameList: PROC RETURNS [list: Node] = { GetRequiredSep[openBracket]; list _ GetNameList[]; GetRequiredSep[closeBracket]; }; GetNameList: PROC [oldList: Node _ NIL] RETURNS [list: Node] = { list _ oldList; DO sep: Separator; list _ AppendNode[list, GetName[]]; IF (sep _ GetSep[]) ~= comma THEN {SaveSep[sep]; EXIT}; ENDLOOP; }; GetName: PROC RETURNS [Node] = { RETURN[NEW[Item _ [link: NIL, body: name[name: GetID[]]]]]}; AppendNode: PROC [list: Node, node: Node] RETURNS [newList: Node] = { IF list = NIL THEN node.link _ node ELSE {node.link _ list.link; list.link _ node}; RETURN[node] }; GetID: PROC RETURNS [ROPE] = { RETURN[source.GetTokenRope[MyIDProc].token] }; GetNumber: PROC [low: CARDINAL _ CARDINAL.FIRST, high: CARDINAL _ CARDINAL.LAST] RETURNS [CARDINAL _ CARDINAL.LAST] = { number: LONG CARDINAL; number _ Convert.IntFromRope[GetID[] ! Convert.Error => GO TO badNumber]; IF ~(number IN [low..high]) THEN ErrorMsg[IO.PutFR["'%d' is out of range", IO.card[number]]]; RETURN[number]; EXITS badNumber => ErrorMsg[IO.PutFR["illegal number"]]; }; MyIDProc: IO.BreakProc = { RETURN[ SELECT char FROM IN [Ascii.NUL..Ascii.SP] => $sepr, IN ['A..'Z], IN ['a..'z], IN ['0..'9] => $other, ENDCASE => $break ] }; GetSep: PROC RETURNS [sep: Separator] = { char: CHAR; IF lastSep ~= Ascii.NUL THEN {char _ lastSep; lastSep _ Ascii.NUL} ELSE { [] _ source.SkipWhitespace[]; char _ source.GetChar[]; }; FOR sep IN Separator DO IF char = separators[sep] THEN EXIT; REPEAT FINISHED => ErrorMsg[IO.PutFR["Illegal character '%g'", IO.char[char]]]; ENDLOOP; }; SaveSep: PROC [sep: Separator] = { IF lastSep ~= Ascii.NUL THEN ERROR; lastSep _ separators[sep]; }; GetUCodeDate: PROC [key: Keyword] RETURNS [SystemVersion.Date] = { RETURN[ BasicTime.ToPupTime[source.GetTime[ ! IO.Error => ErrorMsg[IO.PutFR["Improper date for '%g'", IO.rope[keywords[key]]]] ]] ] }; SyntaxError: PROC [key: Keyword] = { ErrorMsg[IO.PutFR["Bad specification for '%g'", IO.rope[keywords[key]]]]; }; ErrorMsg: PROC [msg: ROPE] = { data.typescript.PutF["\N! Syntax Error [%d]: %g\N", IO.card[source.GetIndex], IO.rope[msg]]; ERROR MB.Abort }; <> WartFrame: PUBLIC PROC RETURNS [g: PrincOps.GlobalFrameHandle] = { IF wartConfig ~= NIL THEN MB.SetConfig[wartConfig]; g _ MB.NameToG[wartModule]; MB.ResetConfig[]; }; EnumerateCode: PUBLIC PROC [ state: ListType, proc: PROC [bh: BHandle, mth: BcdDefs.MTHandle] RETURNS [BOOL]] = { PackageableOnly: PROC [bh: BHandle, mth: BcdDefs.MTHandle] RETURNS [BOOL] = TRUSTED { RETURN[IF mth.packageable THEN proc[bh, mth] ELSE FALSE]}; [] _ DoModules[stateLists[state], PackageableOnly]; }; EnumerateGlobalFrames: PUBLIC PROC [ state: ListType, proc: PROC [bh: BHandle, mth: BcdDefs.MTHandle] RETURNS [BOOL]] = { PackageableOnly: PROC [bh: BHandle, mth: BcdDefs.MTHandle] RETURNS [BOOL] = TRUSTED { RETURN[IF mth.packageable THEN proc[bh, mth] ELSE FALSE]}; p: Node _ stateLists[state]; IF p ~= NIL THEN DO p _ p.link; WITH p SELECT FROM p: REF globalframe Item => IF DoModules[p.list, PackageableOnly] THEN EXIT; ENDCASE; IF p = stateLists[state] THEN EXIT; ENDLOOP; }; EnumerateFramePacks: PUBLIC PROC [ state: ListType, proc: PROC [bh: BHandle, fph: BcdDefs.FPHandle] RETURNS [BOOL]] = { p: Node _ stateLists[state]; IF p ~= NIL THEN DO p _ p.link; WITH p SELECT FROM p: REF frame Item => { PassItOn: PROC [name: ROPE] RETURNS [BOOL] = { bh: BHandle; fph: BcdDefs.FPHandle; IF name.Equal[keywords[all]] THEN { [] _ DoAllFramePacks[proc]; RETURN[TRUE] }; [bh: bh, fph: fph] _ NameToFPHandle[name]; RETURN[proc[bh, fph]] }; IF DoNames[p.list, PassItOn] THEN EXIT; }; ENDCASE; IF p = stateLists[state] THEN EXIT; ENDLOOP; }; EnumerateSpaces: PUBLIC PROC [ state: ListType, proc: PROC [bh: BHandle, sph: BcdDefs.SPHandle, index: CARDINAL] RETURNS [BOOL]] = { p: Node _ stateLists[state]; IF p ~= NIL THEN DO p _ p.link; WITH p SELECT FROM p: REF space Item => { PassItOn: PROC [name: ROPE] RETURNS [BOOL] = { bh: BHandle; sph: BcdDefs.SPHandle; index: CARDINAL; IF name.Equal[keywords[all]] THEN { [] _ DoAllSpaces[proc]; RETURN[TRUE] }; [bh: bh, sph: sph, index: index] _ NameToSPHandle[name]; RETURN[proc[bh, sph, index]] }; IF DoNames[p.list, PassItOn] THEN EXIT; }; ENDCASE; IF p = stateLists[state] THEN EXIT; ENDLOOP; }; EnumerateBCDs: PUBLIC PROC [state: ListType, proc: PROC [bh: BHandle] RETURNS [BOOL]] = { p: Node _ stateLists[state]; IF p ~= NIL THEN DO p _ p.link; WITH p SELECT FROM p: REF bcd Item => { PassItOn: PROC [name: ROPE] RETURNS [BOOL] = { IF name.Equal[keywords[all]] THEN { [] _ DoAllBCDs[proc]; RETURN[TRUE] }; RETURN[proc[NameToCTHandle[name].bh]] }; IF DoNames[p.list, PassItOn] THEN EXIT; }; ENDCASE; IF p = stateLists[state] THEN EXIT; ENDLOOP; }; EnumerateNoTrapModules: PUBLIC PROC [ proc: PROC [bh: BHandle, mth: BcdDefs.MTHandle] RETURNS [BOOL]] = { [] _ DoModules[noTrapList, proc]; }; EnumerateControlList: PUBLIC PROC [ proc: PROC [bh: BHandle, cth: BcdDefs.CTHandle] RETURNS [BOOL]] = { PassItOn: PROC [name: ROPE] RETURNS [BOOL] = { bh: MB.BHandle; cth: BcdDefs.CTHandle; IF name.Equal[keywords[all]] THEN { [] _ DoAllTopLevelConfigs[proc]; RETURN[TRUE] }; [bh, cth] _ NameToCTHandle[name]; RETURN[proc[bh, cth]] }; [] _ DoNames[controlList, PassItOn]; }; DoModules: PROC [ tail: Node, proc: PROC [bh: BHandle, mth: BcdDefs.MTHandle] RETURNS [BOOL]] RETURNS [stopped: BOOL] = { p: Node _ tail; stopped _ TRUE; IF p = NIL THEN RETURN[FALSE]; DO bh: MB.BHandle; mth: BcdDefs.MTHandle; p _ p.link; WITH p SELECT FROM p: REF name Item => IF p.name.Equal[keywords[all]] THEN { IF MB.DoAllModules[proc] THEN RETURN} ELSE { [bh: bh, mth: mth] _ NameToMTHandle[p.name]; IF bh ~= NIL AND proc[bh, mth] THEN RETURN; }; p: REF dot Item => { [bh: bh, mth: mth] _ InstanceToMTHandle[module: p.module, instance: p.instance]; IF bh ~= NIL AND proc[bh, mth] THEN RETURN; }; p: REF config Item => { done: BOOL; MB.SetConfig[p.name]; <> <> <> done _ DoModules[p.list, proc]; MB.ResetConfig[]; IF done THEN RETURN; }; p: REF code Item => IF DoModules[p.list, proc] THEN RETURN; ENDCASE; -- skip over space, frame, globalframe, bcd IF p = tail THEN EXIT; ENDLOOP; RETURN[FALSE] }; DoNames: PROC [tail: Node, proc: PROC [name: ROPE] RETURNS [BOOL]] RETURNS [BOOL] = { p: Node _ tail; IF p ~= NIL THEN DO p _ p.link; WITH p SELECT FROM p: REF name Item => IF proc[p.name] THEN RETURN[TRUE]; ENDCASE => ERROR; IF p = tail THEN EXIT; ENDLOOP; RETURN[FALSE] }; END.