MBParse.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
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;
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 = REF InputFileNode;
InputFileNode: TYPE = RECORD [
next: InputFile ← NIL,
name: ROPE,
create: Time.Packed ← [0]];
inputFiles: 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: 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
put at end of list for printing by EchoInput
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: BOOLTRUE] = {
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: 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.GetId[]]
};
GetNumber: PROC [
low: CARDINALFIRST[CARDINAL], high: CARDINALLAST[CARDINAL]]
RETURNS [CARDINAL] = {
GetCard: PROC [stream: IO.STREAM] RETURNS [LONG CARDINAL] = {
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.
initial: BOOLTRUE;
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: ROPENIL;
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
};
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] = {
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];
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[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.