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; 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. φMBParse.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Sandman on 6-Aug-81 15:42:09 Lewis on 18-Sep-81 15:00:15 Levin on January 16, 1984 9:34 am Russ Atkinson (RRA) March 8, 1985 5:29:41 pm PST Syntax for RESIDENT, RESIDENTDESCRIPTOR, IN, NOTRAP, and CONTROL: Resident ::= RESIDENT : list ; ResidentDescriptor ::= RESIDENTDESCRIPTOR : list ; In ::= IN : list ; NoTrap ::= NOTRAP : moduleList ; Control ::= CONTROL : nameList ; list ::= listItem | list , listItem listItem ::= configPart | CODE [ configPartList ] GLOBALFRAME [ configPartList ] SPACE [ nameList ] | CODEPACK [ nameList ] | FRAME [ nameList ] | FRAMEPACK [ nameList ] | BCD [ nameList ] | configPartList ::= configPart | configPartList , configPart configPart ::= module | configName [ moduleList ] moduleList ::= module | moduleList , module module ::= name | name . instance nameList ::= name | nameList , name Bootmesa file parsing This procedure exists solely to ensure that the lists are garbage-collected promptly. put at end of list for printing by EchoInput Bootmesa file interrogation The syntax equations ensure that we will not recur under the following call of DoModules. This is important since SetConfig and ResetConfig do not follow a stack discipline. Κ™˜codešœ™Kšœ Οmœ1™—˜K˜D—˜K˜B—˜ Kšœžœ ˜šžœ ž˜Kšœžœ&˜D˜Kšœ˜K˜K˜K˜—Kšžœ˜—Kšœ˜—K˜HK˜EK˜6K˜1K˜2Kšžœ˜—K˜Kšžœ˜—šœ˜K˜——š  œžœžœ˜+Kšœžœ ˜Kšžœžœ žœ*žœ ˜]Kšžœžœ žœžœžœžœžœ˜EKšœ žœ&žœ ˜?K˜K˜—š œžœ˜*šžœž˜Kšœ žœ,žœ˜S—Kšœ˜K˜—š œžœžœžœ˜CK˜šž˜K˜K˜'Kšžœžœžœ˜7Kšžœ˜—šœ˜K˜——š  œžœžœ˜*Kšœžœ ˜šžœžœž˜˜8Kšœžœžœ.˜J—˜9Kšœžœžœ.˜J—˜Kšœžœžœ,˜H—˜!Kšœžœžœ:˜V—˜Kšœžœžœ3˜O—Kšžœ˜#—šœ˜K˜——š œžœžœ˜9K˜K˜K˜K˜K˜—š œžœžœ˜0Kšœžœ˜ šž˜K˜Kšœ0˜0Kšžœžœžœ˜7Kšžœ˜—šœ˜K˜——š  œžœžœžœ˜6K˜šžœžœ˜Kšœžœžœ1˜MK˜K˜—Kšžœ,˜0Kšœ˜K˜—š  œžœžœžœ˜BK˜šž˜K˜K˜%Kšžœžœžœ˜7Kšžœ˜—Kšœ˜K˜—š   œžœ žœžœžœ˜