-- ContextPack.Mesa
-- Edited by: Bruce October 8, 1980 6:46 PM
-- Edited by: Johnsson September 16, 1980 5:08 PM
-- Edited by: Sandman July 18, 1980 10:24 AM
DIRECTORY
BcdDefs USING [Base, CTIndex, CTNull, GFTIndex, MTIndex, NameRecord],
BcdOps USING [
BcdBase, CTHandle, FindName, MTHandle, NameString, ProcessConfigs, ProcessModules],
DContext USING [],
DebugOps USING [Abort, Numeric, ShortREAD, StringExpToOctal, UserAborted],
DLoadState USING [
Acquire, AcquireBcd, Enumerate, GetMap, Invalid, Map, MapConfigToReal,
MapRealToConfig, ReleaseBcd, Release, ReleaseMap],
DOutput USING [Blanks, Char, Decimal, EOL, Line, Octal, SubString, Text],
DPsb USING [Current, Frame],
Frames USING [Invalid],
Gf USING [
Check, CopiedFrame, Deleted, Display, DisplayGFTEntry, Frame, GFI, Handle,
Name, Original, Validate],
Lf USING [GF, Handle, NoAccessLink, Validate],
MachineDefs USING [
ConfigIndex, FHandle, GFHandle, GfiToFrame, GFTIndex, NullConfig, NullGF,
nullPHandle, PHandle],
State USING [AllStrings, Get, GetGS, GSHandle, Handle, strings, Strings],
Storage USING [String],
String USING [AppendString],
Strings USING [EqualSubStrings, SubStringDescriptor],
UserInput USING [userAbort];
ContextPack: PROGRAM
IMPORTS BcdOps, DebugOps, DOutput, Strings, Frames, Gf, Lf, DLoadState,
DPsb, MachineDefs, State, Storage, String, UserInput
EXPORTS DContext =
BEGIN OPEN BcdDefs, BcdOps, MachineDefs;
strings: State.Strings ← State.AllStrings[];
data: State.GSHandle ← State.GetGS[];
-- setting
Reset: PUBLIC PROC =
BEGIN
h: State.Handle ← State.Get[];
SetLocal[DebugOps.ShortREAD[@data.StatePtr.dest !
DebugOps.Abort => CONTINUE]];
h.pContext ← DPsb.Current[];
h.howSet ← state;
END;
SetOctal: PUBLIC PROC [p: POINTER] =
BEGIN IF ~Gf.Validate[p] THEN SetLocal[p] ELSE SetGlobal[p] END;
SetGlobal: PUBLIC PROC [gf: MachineDefs.GFHandle] =
BEGIN
h: State.Handle ← State.Get[];
IF ~Gf.Validate[gf] THEN {CleanupInvalidContext[gf]; RETURN};
WriteContext[gf];
h.gContext ← gf;
h.lContext ← NIL;
h.pContext ← nullPHandle;
h.howSet ← global;
END;
SetLocal: PUBLIC PROC [lf: MachineDefs.FHandle] =
BEGIN
h: State.Handle ← State.Get[];
gf: MachineDefs.GFHandle ← NIL;
IF ~Lf.Validate[lf] THEN {CleanupInvalidContext[lf]; RETURN};
gf ← Lf.GF[lf ! Frames.Invalid, Lf.NoAccessLink => CONTINUE];
WriteContext[gf];
h.lContext ← lf;
h.gContext ← gf;
h.howSet ← local;
END;
SetProcess: PUBLIC PROC [p: MachineDefs.PHandle] =
BEGIN
h: State.Handle ← State.Get[];
SetLocal[DPsb.Frame[p]];
h.pContext ← p;
h.howSet ← psb;
END;
CleanupInvalidContext: PROCEDURE [f: UNSPECIFIED] =
BEGIN OPEN DOutput;
EOL[]; Octal[f]; Text[" is not a valid frame!"L];
IF ~data.initBCD THEN SIGNAL DebugOps.Abort ELSE InitConfig[];
RETURN
END;
InitConfig: PROCEDURE =
BEGIN
h: State.Handle ← State.Get[];
bcd: BcdOps.BcdBase;
h.lContext ← NIL; h.gContext ← NIL; h.pContext ← nullPHandle;
h.config ← DLoadState.Acquire[ ! DLoadState.Invalid =>
{h.config ← NullConfig; h.cti ← CTNull; GOTO noContext}] - 1;
bcd ← DLoadState.AcquireBcd[h.config];
h.cti ← IF bcd.nConfigs = 0 AND bcd.nModules = 1
THEN CTNull ELSE FIRST[CTIndex];
data.initBCD ← FALSE;
Cleanup[bcd];
EXITS
noContext => NULL;
END;
WriteContext: PROCEDURE [f: MachineDefs.GFHandle] =
BEGIN
h: State.Handle ← State.Get[];
cgfi: GFTIndex;
config: ConfigIndex;
bcd: BcdOps.BcdBase;
FindWhichModule: PROCEDURE[mth: MTHandle, mti: MTIndex] RETURNS [BOOLEAN] =
BEGIN
IF cgfi IN [mth.gfi..mth.gfi+mth.ngfi) THEN
BEGIN h.cti ← mth.config; RETURN[TRUE]; END;
RETURN[FALSE];
END;
h.pContext ← nullPHandle;
[] ← DLoadState.Acquire[ ! DLoadState.Invalid =>
{h.lContext ← NIL; h.gContext ← NIL; GOTO noContext}];
[cgfi, config] ← MapRC[Gf.Original[f]];
IF config = NullConfig THEN ERROR Frames.Invalid[f];
h.config ← config;
bcd ← DLoadState.AcquireBcd[config];
[] ← BcdOps.ProcessModules[bcd, FindWhichModule ! UNWIND => Cleanup[bcd]];
data.initBCD ← FALSE;
Cleanup[bcd];
RETURN
EXITS noContext => NULL;
END;
SetRootConfig: PUBLIC PROC [config: STRING] =
BEGIN
Rcount: CARDINAL ← 0;
configdesc: Strings.SubStringDescriptor;
savecti: CTIndex ← CTNull;
saveconfig: ConfigIndex;
data: State.Handle ← State.Get[];
GetSetUp: PROCEDURE [config: ConfigIndex] RETURNS [BOOLEAN] =
BEGIN
found: BOOLEAN ← FALSE;
bcd: BcdBase;
CheckForRoot: PROC [cth: CTHandle, cti: CTIndex] RETURNS [BOOLEAN] =
BEGIN
IF UserInput.userAbort THEN Cleanup[bcd,TRUE];
IF cth.config # CTNull THEN RETURN[FALSE];
IF ~(found ← TestName[cth.name]) THEN
IF cth.namedInstance
THEN found ← TestName[FindName[bcd,[config[cti]]]];
IF found THEN
BEGIN savecti ← cti; Rcount ← Rcount+1; saveconfig ← config; END;
RETURN[FALSE]
END;
TestName: PROCEDURE [name: NameRecord] RETURNS [BOOLEAN] =
BEGIN OPEN Strings;
tempssb: NameString = LOOPHOLE[bcd+bcd.ssOffset];
ssd: SubStringDescriptor ←
[base: @tempssb.string, offset: name, length: tempssb.size[name]];
RETURN[EqualSubStrings[@configdesc, @ssd]]
END;
bcd ← DLoadState.AcquireBcd[config];
IF bcd.nConfigs = 0 AND bcd.nModules = 1 THEN
BEGIN
mth: MTHandle ← @LOOPHOLE[bcd+bcd.mtOffset, Base][FIRST[MTIndex]];
IF ~(found ← TestName[mth.name]) THEN
IF mth.namedInstance
THEN found ← TestName[FindName[bcd,[module[FIRST[MTIndex]]]]];
IF found THEN
BEGIN Rcount ← Rcount+1; saveconfig ← config; savecti ← CTNull; END;
END
ELSE [] ← ProcessConfigs[bcd, CheckForRoot];
DLoadState.ReleaseBcd[bcd];
RETURN[FALSE]
END;
strings[rconfig] ← config;
configdesc ← Strings.SubStringDescriptor[
base: config, offset: 0, length: config.length];
[] ← DLoadState.Acquire[];
[] ← DLoadState.Enumerate[recentfirst,GetSetUp ! UNWIND => DLoadState.Release[]];
SELECT Rcount FROM
= 0 => BEGIN DLoadState.Release[]; NotFound[config] END;
= 1 => SetupRootConfig[saveconfig, savecti];
ENDCASE => {DLoadState.Release[]; WriteAmbiguousContext[config, Rcount]};
RETURN
END;
SetConfig: PUBLIC PROC [config: STRING] =
BEGIN
bcd: BcdBase;
count: CARDINAL ← 0;
configdesc: Strings.SubStringDescriptor;
savecti: CTIndex;
data: State.Handle ← State.Get[];
CheckConfigName: PROC [cth: CTHandle, cti: CTIndex] RETURNS [BOOLEAN] =
BEGIN
found: BOOLEAN ← FALSE;
ssb: NameString ← LOOPHOLE[bcd+bcd.ssOffset];
TestName: PROCEDURE [ssb: NameString, name: NameRecord] RETURNS [BOOLEAN] =
BEGIN OPEN Strings;
ssd: SubStringDescriptor ←
[base: @ssb.string, offset: name, length: ssb.size[name]];
RETURN[EqualSubStrings[@configdesc, @ssd]]
END;
IF UserInput.userAbort THEN SIGNAL DebugOps.UserAborted;
IF ~SameConfig[bcd, cth.config, data.cti] THEN RETURN[FALSE];
IF ~(found ← TestName[ssb, cth.name]) THEN
IF cth.namedInstance THEN
found ← TestName[ssb, FindName[bcd,[config[cti]]]];
IF found THEN BEGIN count ← count + 1; savecti ← cti; END;
RETURN[FALSE]
END;
strings[config] ← config;
configdesc ← Strings.SubStringDescriptor[
base: config, offset: 0, length: config.length];
IF data.cti = CTNull
THEN BEGIN DOutput.Text[" -- Not allowed !"L]; RETURN END;
[] ← DLoadState.Acquire[];
bcd ← DLoadState.AcquireBcd[data.config];
[] ← ProcessConfigs[bcd, CheckConfigName ! UNWIND => Cleanup[bcd]];
SELECT count FROM
= 0 => NotFound[config];
= 1 => IF SetupConfig[bcd, savecti, data.config] THEN data.cti ← savecti;
ENDCASE => WriteAmbiguousContext[config, count ! UNWIND => Cleanup[bcd]];
Cleanup[bcd];
RETURN
END;
NotFound: PROC [s: STRING]= {
DOutput.EOL[]; DOutput.Text[s]; DOutput.Line[" not found!"L]};
SetModule: PUBLIC PROC [mod: STRING] = {
gf: MachineDefs.GFHandle ←
IF DebugOps.Numeric[mod] THEN LOOPHOLE[DebugOps.StringExpToOctal[mod]]
ELSE Gf.Frame[mod ! Gf.CopiedFrame => RESUME];
strings[module] ← mod;
IF gf = NIL THEN RETURN;
SetGlobal[gf]};
-- retrieving
GetOctal: PUBLIC PROC RETURNS [p: POINTER] =
BEGIN RETURN [State.Get[].h.lContext] END;
GetGlobal: PUBLIC PROC RETURNS [gf: MachineDefs.GFHandle] =
BEGIN RETURN [State.Get[].h.gContext] END;
GetLocal: PUBLIC PROC RETURNS [lf: MachineDefs.FHandle] =
BEGIN RETURN [State.Get[].h.lContext] END;
GetProcess: PUBLIC PROC RETURNS [p: MachineDefs.PHandle] =
BEGIN RETURN [State.Get[].h.pContext] END;
GetRootConfig: PUBLIC PROC RETURNS [config: STRING] =
BEGIN config ← strings[rconfig] END;
GetConfig: PUBLIC PROC RETURNS [config: STRING] =
BEGIN config ← strings[config] END;
GetModule: PUBLIC PROC RETURNS [mod: STRING] =
BEGIN
mod ← strings[module];
IF mod # NIL THEN RETURN;
mod ← Storage.String[40];
strings[module] ← mod;
Gf.Name[mod,GetGlobal[]];
END;
GetRootConfigIndex: PUBLIC PROC
RETURNS [config: ConfigIndex] =
BEGIN RETURN [State.Get[].h.config] END;
GetConfigIndex: PUBLIC PROC RETURNS [cti: BcdDefs.CTIndex] =
BEGIN RETURN [State.Get[].h.cti] END;
-- utilities
DisplayCurrent: PUBLIC PROCEDURE =
BEGIN OPEN DLoadState;
h: State.Handle ← State.Get[];
module: STRING ← [40];
bcd: BcdOps.BcdBase ← NIL;
BEGIN ENABLE UNWIND => Cleanup[bcd];
[] ← DLoadState.Acquire[ ! DLoadState.Invalid => GOTO noContext];
DOutput.EOL[];
Gf.Display[h.gContext, "Module:"L];
IF h.lContext # NIL THEN
BEGIN DOutput.Text[", L"L]; WCS[]; DOutput.Octal[h.lContext]; END;
IF h.pContext # nullPHandle THEN
BEGIN DOutput.Text[", PSB"L]; WCS[]; DOutput.Octal[h.pContext]; END;
DOutput.EOL[];
bcd ← DLoadState.AcquireBcd[h.config];
IF bcd.nConfigs # 0 THEN
BEGIN
cth: CTHandle ← @LOOPHOLE[bcd+bcd.ctOffset, Base][h.cti];
ssb: NameString ← LOOPHOLE[bcd+bcd.ssOffset];
DOutput.Text[" Configuration"L]; WCS[];
IF cth.namedInstance THEN
BEGIN
PrintName[ssb, BcdOps.FindName[bcd,[config[h.cti]]]];
WCS[];
END;
PrintName[ssb,cth.name];
DOutput.EOL[];
END;
END;
Cleanup[bcd];
RETURN
EXITS
noContext => DOutput.Text["No valid context!!"L];
END;
ListConfigs: PUBLIC PROCEDURE =
BEGIN
PrintConfigs: PROCEDURE [config: ConfigIndex] RETURNS [BOOLEAN] =
BEGIN
bcd: BcdBase;
tempssb: NameString;
ListSons: PROCEDURE [level: CARDINAL, parent: CTIndex] =
BEGIN
WriteNames: PROC [cth: CTHandle, cti: CTIndex] RETURNS [BOOLEAN] =
BEGIN
IF cth.config = parent THEN
BEGIN
IF UserInput.userAbort THEN Cleanup[bcd,TRUE];
DOutput.EOL[];
DOutput.Blanks[level*2];
IF cth.namedInstance THEN
BEGIN
PrintName[tempssb, FindName[bcd,[config[cti]]]];
DOutput.Text[": "L];
END;
PrintName[tempssb, cth.name];
ListSons[level+1, cti];
END;
RETURN[FALSE]
END;
[] ← EnumerateConfigNames[bcd, WriteNames];
RETURN
END;
bcd ← DLoadState.AcquireBcd[config];
tempssb ← LOOPHOLE[bcd+bcd.ssOffset];
ListSons[0, CTNull];
DLoadState.ReleaseBcd[bcd];
RETURN[FALSE]
END;
[] ← DLoadState.Acquire[];
[] ← DLoadState.Enumerate[recentfirst, PrintConfigs ! UNWIND => DLoadState.Release[]];
DLoadState.Release[];
RETURN
END;
EnumerateConfigNames: PROCEDURE [
bcd: BcdBase, proc: PROCEDURE [CTHandle, CTIndex] RETURNS [BOOLEAN]]
RETURNS[CTIndex]=
BEGIN
mth: MTHandle = @LOOPHOLE[bcd+bcd.mtOffset, Base][FIRST[MTIndex]];
tempssb: NameString = LOOPHOLE[bcd+bcd.ssOffset];
IF bcd.nConfigs = 0 AND bcd.nModules = 1 THEN
BEGIN
DOutput.EOL[];
IF mth.namedInstance THEN
BEGIN
PrintName[tempssb, FindName[bcd,[module[FIRST[MTIndex]]]]];
DOutput.Text[": "L];
END;
PrintName[tempssb, mth.name];
RETURN[CTNull];
END;
RETURN[ProcessConfigs[bcd, proc].cti]
END;
DisplayConfig: PUBLIC PROCEDURE =
BEGIN
bcd: BcdBase ← NIL;
ssb: NameString;
map: DLoadState.Map;
data: State.Handle ← State.Get[];
PrintModules: PROCEDURE [mth: MTHandle, mti: MTIndex] RETURNS [BOOLEAN] =
BEGIN
IF UserInput.userAbort THEN Cleanup[bcd,TRUE];
DOutput.EOL[];
IF ~SameConfig[bcd, mth.config, data.cti] THEN RETURN[FALSE];
IF mth.namedInstance THEN
BEGIN
PrintName[ssb, FindName[bcd,[module[mti]]]];
DOutput.Text[": "L];
END;
PrintName[ssb, mth.name]; DOutput.Text[", G: "L];
Gf.DisplayGFTEntry[map[mth.gfi]];
RETURN[FALSE];
END;
BEGIN ENABLE UNWIND => Cleanup[bcd];
[] ← DLoadState.Acquire[];
bcd ← DLoadState.AcquireBcd[data.config];
map ← DLoadState.GetMap[data.config];
ssb ← LOOPHOLE[bcd+bcd.ssOffset];
DOutput.Blanks[2];
IF bcd.nConfigs # 0 THEN
BEGIN
cth: CTHandle ← @LOOPHOLE[bcd+bcd.ctOffset, Base][data.cti];
IF cth.namedInstance THEN
BEGIN
PrintName[ssb, FindName[bcd,[config[data.cti]]]];
DOutput.Text[": "L];
END;
PrintName[ssb, cth.name];
END;
[] ← ProcessModules[bcd,PrintModules];
DLoadState.ReleaseMap[map];
END;
Cleanup[bcd];
RETURN;
END;
SetupRootConfig: PROCEDURE [config: ConfigIndex, cti: CTIndex] =
BEGIN
-- LoadState already in
bcd: BcdBase ← DLoadState.AcquireBcd[config];
IF SetupConfig[bcd, cti, config] THEN
BEGIN
data: State.Handle ← State.Get[];
data.config ← config;
data.cti ← cti;
END;
Cleanup[bcd]; -- releases LoadState
RETURN
END;
SetupConfig: PROCEDURE [
bcd: BcdBase, cti: CTIndex, config: ConfigIndex] RETURNS [BOOLEAN] =
BEGIN
mth: MTHandle;
data: State.Handle ← State.Get[];
FindFirstModule: PROC [mth: MTHandle, mti: MTIndex] RETURNS [BOOLEAN] =
BEGIN
RETURN[SameConfig[bcd, mth.config, cti] AND
~Gf.Deleted[DLoadState.MapConfigToReal[mth.gfi, config]]]
END;
mth ← ProcessModules[bcd, FindFirstModule].mth;
IF mth # NIL THEN
BEGIN
data.gContext ← GfiToFrame[DLoadState.MapConfigToReal[mth.gfi, config]];
data.lContext ← NIL;
data.pContext ← nullPHandle;
data.howSet ← global;
RETURN[TRUE];
END
ELSE
BEGIN
DOutput.Text[" -- Not Allowed !"L];
RETURN[FALSE];
END;
END;
Enumerate: PUBLIC PROCEDURE [
proc: PROCEDURE [MachineDefs.GFHandle] RETURNS [BOOLEAN]] =
--sequences through frames of modules in current config
BEGIN
bcd: BcdBase;
map: DLoadState.Map;
data: State.Handle ← State.Get[];
SearchModules: PROCEDURE [mth: MTHandle, mti: MTIndex] RETURNS [BOOLEAN] =
BEGIN
frame: MachineDefs.GFHandle;
IF UserInput.userAbort THEN SIGNAL DebugOps.UserAborted;
IF ~SameConfig[bcd, mth.config, data.cti] THEN RETURN[FALSE];
frame ← GfiToFrame[map[mth.gfi]];
IF frame = NullGF THEN RETURN[FALSE];
Gf.Check[frame];
IF proc[frame] THEN RETURN[TRUE];
RETURN[FALSE];
END;
CleanupMap: PROCEDURE [map: DLoadState.Map, bcd: BcdBase] =
BEGIN
DLoadState.ReleaseMap[map];
Cleanup[bcd];
RETURN
END;
[] ← DLoadState.Acquire[ ! DLoadState.Invalid => GOTO nil];
map ← DLoadState.GetMap[data.config];
[] ← ProcessModules[bcd ← DLoadState.AcquireBcd[data.config], SearchModules
! UNWIND => CleanupMap[map, bcd]];
CleanupMap[map, bcd];
RETURN
EXITS
nil => RETURN;
END;
WriteAmbiguousContext: PROCEDURE [s: STRING, c: CARDINAL] =
BEGIN OPEN DOutput;
Char['!]; Text[s]; Text[" has "L]; Decimal[c];
Line[" instances -- this is an ambiguous reference."L];
RETURN
END;
MapRC: PUBLIC PROCEDURE [f: MachineDefs.GFHandle]
RETURNS [cgfi: MachineDefs.GFTIndex, config: MachineDefs.ConfigIndex] =
BEGIN
[cgfi, config] ← DLoadState.MapRealToConfig[Gf.GFI[f]];
RETURN
END;
CheckForExtension: PROCEDURE [name, ext: STRING] =
BEGIN
i: CARDINAL;
FOR i IN [0..name.length) DO
IF name[i] = '. THEN RETURN;
ENDLOOP;
String.AppendString[name, ext];
RETURN
END;
Cleanup: PROCEDURE [bcd: BcdBase, abort: BOOLEAN ← FALSE] =
BEGIN
IF bcd # NIL THEN DLoadState.ReleaseBcd[bcd];
DLoadState.Release[];
IF abort THEN SIGNAL DebugOps.UserAborted;
END;
PrintName: PROCEDURE [ssb: NameString, name: NameRecord] =
BEGIN
ssd: Strings.SubStringDescriptor ←
[base: @ssb.string, offset: name, length: ssb.size[name]];
DOutput.SubString[@ssd];
RETURN
END;
WCS: PROC = {DOutput.Text[": "L]};
SameConfig: PUBLIC PROC [bcd: BcdOps.BcdBase, child, parent: CTIndex]
RETURNS [BOOLEAN]=
BEGIN OPEN BcdDefs;
cti: BcdDefs.CTIndex;
ctb: Base = LOOPHOLE[bcd+bcd.ctOffset];
--checks to see if child is related to parent
FOR cti ← child, ctb[cti].config UNTIL cti = CTNull DO
IF cti = parent THEN RETURN[TRUE];
ENDLOOP;
RETURN[parent = CTNull]
END;
END.