-- 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.