<> <> <> <> DIRECTORY Ascii USING [CR, NUL, SP, TAB], BasicTime USING [GMT--, ToPupTime--], BcdDefs USING [CTHandle, FPHandle, MTHandle, SPHandle], ConvertUnsafe USING [AppendRope], DateAndTime USING [Notes, Parse, Unintelligible], FileIO USING [Open], IO USING [ card, char, CharProc, Close, CreateFilterCommentsStream, EndOfStream, GetCard, GetChar, GetId, GetIndex, GetSequence, PutChar, PutF, PutFR, PutRope, RIS, rope, SkipOver, STREAM, SyntaxError, time], 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, Concat, Equal, FromChar, ROPE], Segments USING [FHandle, FileNameProblem, GetFileTimes, NewFile], SystemVersion USING [Date], Time USING [Packed]; MBParse: PROGRAM IMPORTS --BasicTime, --ConvertUnsafe, DateAndTime, FileIO, IO, MB, Rope, Segments 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 = REF InputFileNode; InputFileNode: TYPE = RECORD [ next: InputFile _ NIL, name: ROPE, create: Time.Packed _ [0]]; inputFiles: 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: p SELECT FROM name => NULL; dot => NULL; config => UnloopList[p.list]; space => UnloopList[p.list]; frame => UnloopList[p.list]; globalframe => UnloopList[p.list]; code => UnloopList[p.list]; bcd => UnloopList[p.list]; ENDCASE; IF p = tail THEN EXIT; ENDLOOP; tail.link _ NIL; }; IF inputFiles ~= NIL THEN inputFiles.next _ 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] = { fileS: STRING _ [40]; fh: Segments.FHandle; inputFile: InputFile = NEW[InputFileNode _ [name: file]]; ConvertUnsafe.AppendRope[to: fileS, from: file]; fh _ Segments.NewFile[fileS ! Segments.FileNameProblem[] => Error["Parameter file not found!"]]; inputFile.create _ Segments.GetFileTimes[fh].create; source _ IO.CreateFilterCommentsStream[FileIO.Open[file]]; ParseInput[]; source.Close[]; -- note: assumed to close the backing stream <> IF inputFiles = NIL THEN inputFile.next _ inputFile ELSE {inputFile.next _ inputFiles.next; inputFiles.next _ inputFile}; inputFiles _ inputFile; }; 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 name => loadmap.PutRope[name]; dot => loadmap.PutF["%g.%g", IO.rope[module], IO.rope[instance]]; config => {loadmap.PutRope[name]; EchoList[list, FALSE]}; space => {loadmap.PutRope[keywords[codepack]]; EchoList[list, FALSE]}; frame => {loadmap.PutRope[keywords[framepack]]; EchoList[list, FALSE]}; globalframe => {loadmap.PutRope[keywords[globalFrame]]; EchoList[list, FALSE]}; code => {loadmap.PutRope[keywords[code]]; EchoList[list, FALSE]}; bcd => {loadmap.PutRope[keywords[bcd]]; EchoList[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 { inputFile: InputFile _ inputFiles.next; loadmap.PutF["Parameter File%g:\N\N", IO.rope[IF inputFile ~= inputFiles THEN "s" ELSE NIL]]; DO loadmap.PutF[" %39j %t\N", IO.rope[inputFile.name], IO.time[inputFile.create]]; IF inputFile = inputFiles THEN EXIT; inputFile _ inputFile.next; 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[[data.header.requiredUCode[dolphin]]]]; IF data.header.requiredUCode[dorado] ~= 0 THEN loadmap.PutF[" Dorado: %t\N", IO.time[[data.header.requiredUCode[dorado]]]]; IF data.header.requiredUCode[dandelion] ~= 0 THEN loadmap.PutF[" Dandelion: %t\N", IO.time[[data.header.requiredUCode[dandelion]]]]; IF data.header.requiredUCode[dicentra] ~= 0 THEN loadmap.PutF[" Dicentra: %t\N", IO.time[[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"]; IO.SyntaxError => ErrorMsg[msg]; }; SELECT GetKeyword[ ! IO.EndOfStream => EXIT] FROM gft => data.gftLength _ GetNumber[low: FIRST[PrincOps.GFTIndex]+1, high: LAST[PrincOps.GFTIndex]+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: FIRST[PrincOps.PsbIndex]+1, high: LAST[PrincOps.PsbIndex]+1]; nSV => { svIndex: CARDINAL = GetNumber[low: FIRST[PrincOps.Priority], high: LAST[PrincOps.Priority]]; count: CARDINAL; GetRequiredSep[comma]; count _ GetNumber[]; data.stateVectorCounts[svIndex] _ IF data.stateVectorCounts[svIndex] = LAST[CARDINAL] 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: FIRST[Fsi], high: LAST[Fsi]]; 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: FIRST[Fsi], high: LAST[Fsi]]]; 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.GetId[]] }; GetNumber: PROC [ low: CARDINAL _ FIRST[CARDINAL], high: CARDINAL _ LAST[CARDINAL]] RETURNS [CARDINAL] = { GetCard: PROC [stream: IO.STREAM] RETURNS [LONG CARDINAL] = { <> initial: BOOL _ TRUE; Digit: IO.CharProc = TRUSTED { SELECT char FROM IN ['0..'9] => {initial _ FALSE; RETURN[quit: FALSE, include: TRUE]}; IN ['A..'Z], IN ['a..'z] => RETURN[quit: TRUE, include: ~initial]; Ascii.SP, Ascii.TAB, Ascii.CR => RETURN[quit: ~initial, include: FALSE]; ENDCASE => RETURN[quit: TRUE, include: FALSE]; }; RETURN[IO.GetCard[IO.RIS[source.GetSequence[Digit]]]] }; number: LONG CARDINAL = --source.GetCard[]-- GetCard[source]; IF ~(number IN [low..high]) THEN ErrorMsg[IO.PutFR["'%d' is out of range", IO.card[number]]]; RETURN [number] }; GetSep: PROC RETURNS [sep: Separator] = { char: CHAR; IF lastSep ~= Ascii.NUL THEN {char _ lastSep; lastSep _ Ascii.NUL} ELSE { source.SkipOver[]; -- skip white space 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 [date: SystemVersion.Date] = { r: ROPE _ NIL; basicTime: BasicTime.GMT; notes: DateAndTime.Notes; DO char: CHAR = source.GetChar[ ! IO.EndOfStream => ErrorMsg[IO.PutFR["Missing ';' for '%g'", IO.rope[keywords[key]]]] ]; IF char = '; THEN EXIT; r _ r.Concat[Rope.FromChar[char]]; ENDLOOP; [dt: basicTime, notes: notes] _ DateAndTime.Parse[r ! DateAndTime.Unintelligible => ErrorMsg[IO.PutFR["Illegal date for '%g'", IO.rope[keywords[key]]]] ]; IF notes ~= normal THEN ErrorMsg[IO.PutFR["Incomplete date specification for '%g'", IO.rope[keywords[key]]]]; SaveSep[semiColon]; RETURN[--BasicTime.ToPupTime[basicTime]--LOOPHOLE[basicTime]] }; 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] = { 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] = { 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 globalframe => IF DoModules[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 frame => { 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[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 space => { 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[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 bcd => { PassItOn: PROC [name: ROPE] RETURNS [BOOL] = { IF name.Equal[keywords[all]] THEN { [] _ DoAllBCDs[proc]; RETURN[TRUE] }; RETURN[proc[NameToCTHandle[name].bh]] }; IF DoNames[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 name => IF name.Equal[keywords[all]] THEN { IF MB.DoAllModules[proc] THEN RETURN} ELSE { [bh: bh, mth: mth] _ NameToMTHandle[name]; IF bh ~= NIL AND proc[bh, mth] THEN RETURN; }; dot => { [bh: bh, mth: mth] _ InstanceToMTHandle[module: module, instance: instance]; IF bh ~= NIL AND proc[bh, mth] THEN RETURN; }; config => { done: BOOL; MB.SetConfig[name]; <> <> <> done _ DoModules[list, proc]; MB.ResetConfig[]; IF done THEN RETURN; }; code => IF DoModules[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 name => IF proc[name] THEN RETURN[TRUE]; ENDCASE => ERROR; IF p = tail THEN EXIT; ENDLOOP; RETURN[FALSE] }; END.