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; 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 Rope.Equal[name, "ALL", TRUE] 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 Rope.Equal[name, "ALL", TRUE] 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 Rope.Equal[name, "ALL", TRUE] 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 Rope.Equal[name, "ALL", TRUE] 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. LMBParse.mesa Edited by Sandman on 6-Aug-81 15:42:09 Edited by Lewis on 18-Sep-81 15:00:15 Edited by Levin on June 22, 1983 10:45 am 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 Use this until (if ever) the real one does what we want (terminates on any punctuation, including "."). Even this requires programming around some infelicities of IO. 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. ÊÓ˜Jšœ™Jšœ&™&Jšœ%™%Jšœ)™)J˜šÏk ˜ Jš œœœœœœ˜Jšœ œÏcœ˜%Jšœœ*˜7Jšœœ˜!Jšœ œ ˜1Jšœœ˜šœœ˜ Jšœ•œœ˜Å—šœœ˜ J˜¥—šœ œ˜Jšœf˜f—Jšœœ œ˜0Jšœ œ3˜AJšœœ˜Jšœœ ˜J˜—šœ ˜Jšœžœ$œœ˜QJšœœ˜ —J˜Jš˜J˜Jšœœ˜J˜JšœA™AItable1šœ™Kšœ2™2Kšœ™Kšœ ™ Kšœ ™ Kšœ#™#Kšœ1™1Kšœ ™ Kšœ.™.Kšœ/™/Kšœ™Kšœ;™;Kšœ1™1Kšœ+™+Kšœ!™!Kšœ#™#J˜J˜Jšœœœ˜J˜Jšœœ œ˜Jšœœœœ˜J˜J˜J˜Jšœ œ œž0˜UJšœœ˜J˜Jšœœœ˜šœœœ˜J˜ šœœ ˜Jšœœ˜Jšœœ˜ Jšœœ˜#J˜J˜J˜J˜J˜Jš˜—šœ˜J˜——Jšœ œ=˜Lšœ œ˜J˜J˜—šœ œ œœ˜#J˜ë—J˜Jšœ œ œœ˜?J˜Jšœ œ˜J˜Jšœ œœ˜$šœœœ˜Jšœœ˜Jšœœ˜ J˜J˜—Jšœœž0˜NJ˜Jšœ™J˜šÏn œœœœ ˜)J˜ Jšœ˜Jšœ˜J˜—šŸ œœœ˜šŸœœ˜JšœU™UšŸ œœ˜!J˜Jšœœœœ˜š˜J˜ šœœ˜Jšœœ˜ Jšœœ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ"˜"Jšœ˜Jšœ˜Jšœ˜—Jšœ œœ˜Jšœ˜—Jšœ œ˜Jšœ˜—Jšœœœœ˜0šœœ ˜!J˜Jšœ˜—J˜J˜J˜—J˜Jšœ˜Jšœœ˜ Jšœ˜J˜—šŸ œœ˜Jšœ œ˜Jšœœ˜Jšœ œœ˜Jšœœ˜Jšœ œ˜ Jšœ œ˜Jšœ˜J˜—šŸ œœœœ˜*Jšœœ˜J˜Jšœœ˜9J˜0šœ˜JšœD˜D—Jšœ4˜4Jšœ œ/˜:J˜ Jšœž,˜=Jšœ,™,Jšœœœ˜3JšœA˜EJ˜J˜J˜—šŸ œœœ˜Jšœ œœ˜"šŸœœœœ˜6J˜Jšœ œœ˜Bšœœ˜š˜J˜ šœœ˜Jšœ˜Jšœœœ˜AJšœ1œ˜9Jšœ>œ˜FJšœ?œ˜GJšœGœ˜OJšœ9œ˜AJšœ7œ˜?Jšœ˜—Jšœ œœ˜Jšœœ œ œ˜6Jšœ˜——Jšœ œ˜'Jšœ˜Jšœ˜—šœœœ˜J˜'šœ%˜%Jš œœœœœ˜7—š˜Jšœœœ˜QJšœœœ˜$J˜Jšœ˜—Jšœ˜Jšœ˜—Jšœ)˜)˜%Jšœ"œ!˜Gšœ˜Jšœœ˜)Jšœœœ"˜9—Jšœ˜—J˜6šœ)˜/Jšœ#œ-˜R—šœ(˜.Jšœ"œ,˜P—šœ+˜1Jšœ%œ/˜V—šœ*˜0Jšœ$œ.˜T—šœI˜IJšœœœ˜K—šœI˜IJšœœœ˜HJšœœœ˜K—JšœCœ˜Yšœœœ˜'Jšœœ œ"˜KJšœ˜—šœ ˜ JšœT˜TJš œœœœ œ ˜V—šœœ˜<šœ&˜&Jšœ ˜ Jšœ˜Jšœœ˜Jšœœ˜J˜—Jšœ˜—Jšœœ˜2Jšœœœ&œ˜TJšœ˜šœœœ˜%JšœD˜D—šœœœ˜$JšœN˜N—šœœœ˜JšœAœ˜H—šœœœ˜Jšœ8œ˜?—šœœœ˜Jšœ9œ˜@—Jšœ˜Jšœ˜J˜—šŸ œœ˜Jšœœ˜š˜šœ˜Jšœ4˜6Jšœ˜ J˜—šœœœ˜1˜˜Jšœœœ˜L——Jšœ&˜&Jšœ(˜(Jšœ=˜=Jšœ9˜9˜ šœ˜Jšœœœ˜L——˜šœ œ˜Jšœœœ˜H—Jšœœ˜J˜J˜˜!Jšœ#œœœ˜>Jšœ)˜-—J˜—Jšœ'œ˜C˜Jšœœ˜$Jšœ!œ œ˜>J˜J˜Jšœ8˜:J˜šœ˜Jšœ˜˜šœ ˜Jšœ+œ œ˜I——šœ˜ JšœR˜R——Jšœ˜—˜ J˜Jšœ(˜(J˜Jšœ(˜(J˜šœ˜Jšœ/˜/J˜šœ˜ JšœR˜R——J˜—˜J˜@—˜J˜>—˜J˜D—˜J˜B—˜ Jšœœ ˜šœ ˜Jšœœ&˜D˜Jšœ˜J˜J˜J˜—Jšœ˜—Jšœ˜—J˜HJ˜EJ˜6J˜1J˜2Jšœ˜—J˜Jšœ˜—šœ˜J˜——šŸ œœœ˜+Jšœœ ˜Jšœœ œ*œ ˜]Jšœœ œœœœœ˜EJšœ œ&œ ˜?J˜J˜—šŸœœ˜*šœ˜Jšœ œ,œ˜S—Jšœ˜J˜—šŸœœœœ˜CJ˜š˜J˜J˜'Jšœœœ˜7Jšœ˜—šœ˜J˜——šŸ œœœ˜*Jšœœ ˜šœœ˜˜8Jšœœœ.˜J—˜9Jšœœœ.˜J—˜Jšœœœ,˜H—˜!Jšœœœ:˜V—˜Jšœœœ3˜O—Jšœ˜#—šœ˜J˜——šŸœœœ˜9J˜J˜J˜J˜J˜—šŸœœœ˜0Jšœœ˜ š˜J˜Jšœ0˜0Jšœœœ˜7Jšœ˜—šœ˜J˜——šŸ œœœœ˜6J˜šœœ˜Jšœœœ1˜MJ˜J˜—Jšœ,˜0Jšœ˜J˜—šŸ œœœœ˜BJ˜š˜J˜J˜%Jšœœœ˜7Jšœ˜—Jšœ˜J˜—š Ÿ œœ œœœ˜