MBParse.mesa
Copyright © 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
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;
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
ROPE: TYPE = Rope.ROPE;
data: MB.Handle ← NIL;
source: IO.STREAMNIL;
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
Bootmesa file parsing
InitParse: PUBLIC PROC [h: MB.Handle] = {
data ← h;
ClearGlobals[];
};
FinishParse: PUBLIC PROC = {
BreakCircularities: PROC = {
This procedure exists solely to ensure that the lists are garbage-collected promptly.
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
put at end of list for printing by EchoInput
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: BOOLTRUE] = {
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: ROPENIL] 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: CARDINALCARDINAL.FIRST, high: CARDINALCARDINAL.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
};
Bootmesa file interrogation
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];
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.
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.