-- LookupPack.mesa last edit, Johnsson August 8, 1980 6:42 PM
-- Bruce October 9, 1980 3:33 PM
DIRECTORY
Actions USING [],
Ascii USING [SP],
ComData,
Copier USING [Outer],
DContext USING [Enumerate, GetModule],
DebugFormat USING [BBHandle, BitAddress, EXOI, Foo],
DebugOps USING [BitAddress, Display, Foo, Lengthen, ShortREAD, UserAborted],
DHeap USING [AllocFob],
DI USING [
CSEIndex, CTXIndex, HTIndex, ISEIndex, Normalize, SearchCtxForVal, SearchCtxList,
SEIndex, TypeForSe],
DOutput USING [Char, Text],
DSyms USING [FindFrame, GFHandle, GFrameMdi, HTIndex, Item, MDIndex, ModuleMdi],
Frames USING [Invalid],
Gf USING [CheckStarted, DisplayInMsg, FrameGfi, FrameHti, GFI, Validate],
Init USING [CheckSymTabLength],
Lf USING [GF, NoAccessLink, NoPrevious, PC, Previous, Validate],
Lookup USING [Complete, HTIndex, InOut, MakeFoo, Mode, NotRelocated, StringToHti],
MachineDefs USING [FHandle, GFHandle, GFTIndex, MaxParmsInStack, SVPointer],
Pc USING [ContextList, CtxLink, Entry, Exit, FreeContextList],
PrincOps USING [localbase, SignalDesc],
State USING [Get, GetGS, GSHandle, Handle],
Strings USING [SubStringDescriptor],
SymbolOps USING [FirstCtxSe, NextSe, SubStringForHash],
Symbols USING [
ContextLevel, CSEIndex, CTXIndex, CTXNull, ctxType, HTIndex, HTNull,
IncludedCTXIndex, IncludedCTXNull, ISEIndex, ISENull, lG, MDIndex, MDNull,
mdType, RecordSEIndex, RecordSENull, SEIndex, SENull, seType, TransferMode],
SymbolTable USING [Base, Missing],
Table USING [AddNotify, Base, DropNotify, Notifier],
UserInput USING [userAbort];
LookupPack: PROGRAM
IMPORTS com: ComData, DContext, Copier, DebugOps, DHeap, DI, DOutput,
DSyms, Frames, Gf, Init, Lf, Lookup, Pc, State, SymbolOps,
SymbolTable, Table, UserInput
EXPORTS Actions, Lookup =
BEGIN OPEN Lookup, Symbols;
Foo: TYPE = DebugOps.Foo;
GFHandle: TYPE = MachineDefs.GFHandle;
FHandle: TYPE = MachineDefs.FHandle;
HTIndex: TYPE = Symbols.HTIndex;
Fail: PUBLIC SIGNAL [s: STRING] = CODE;
NotAnXfer: ERROR = CODE;
SearchingWrongContext: ERROR = CODE;
data: State.GSHandle ← State.GetGS[];
seb: Table.Base;
ctxb: Table.Base;
mdb: Table.Base;
notifyCnt: CARDINAL ← 0;
Notify: Table.Notifier =
BEGIN OPEN Symbols;
seb ← base[seType]; ctxb ← base[ctxType]; mdb ← base[mdType];
END;
Add: PROCEDURE =
BEGIN
IF notifyCnt = 0 THEN Table.AddNotify[Notify];
notifyCnt ← notifyCnt + 1;
END;
Drop: PROCEDURE =
BEGIN
IF notifyCnt = 1 THEN Table.DropNotify[Notify];
notifyCnt ← notifyCnt - 1;
END;
InCtx: PUBLIC PROCEDURE [id: HTIndex, ctx: CTXIndex] RETURNS [Foo] =
BEGIN
isei: Symbols.ISEIndex ← DI.SearchCtxList[id,ctx];
RETURN [IF isei = ISENull THEN NIL ELSE MakeFoo[isei]];
END;
InGF: PUBLIC PROCEDURE [
id: HTIndex, gf: GFHandle ← NIL, check: BOOLEAN ← TRUE]
RETURNS [Foo] =
BEGIN
mdi: Symbols.MDIndex;
p: POINTER;
IF gf = NIL THEN
BEGIN
p ← State.Get[].h.interpretContext;
gf ← IF ~Gf.Validate[p] THEN Lf.GF[p] ELSE p;
END;
mdi ← DSyms.GFrameMdi[gf ! SymbolTable.Missing => GOTO bailout];
RETURN[GFFoo[id, gf, mdi, check]];
EXITS
bailout => RETURN[NIL]
END;
InMod: PUBLIC PROC [id: HTIndex, mod: HTIndex ← Symbols.HTNull] RETURNS [Foo] =
BEGIN
gf: GFHandle ← NIL;
mdi: Symbols.MDIndex;
IF mod = Symbols.HTNull THEN mod ← StringToHti[DContext.GetModule[]];
gf ← Gf.FrameHti[mod ! Fail => CONTINUE];
mdi ← DSyms.ModuleMdi[mod ! SymbolTable.Missing => GOTO bailout];
RETURN[GFFoo[id, gf, mdi, TRUE ! Lookup.NotRelocated => {
DOutput.Text[" Use Interface.importedVariable, not Interface$importedVariable"L];
GOTO bailout}]];
EXITS
bailout => RETURN[NIL]
END;
InLF: PUBLIC PROCEDURE [
id: HTIndex, lf: FHandle ← NIL, check: BOOLEAN ← TRUE]
RETURNS [f: Foo] =
BEGIN
gf: GFHandle ← NIL;
ex: DebugFormat.EXOI;
list: Pc.CtxLink;
IF lf = NIL THEN lf ← State.Get[].h.interpretContext;
IF Gf.Validate[LOOPHOLE[lf]] THEN RETURN[InGF[id,LOOPHOLE[lf],check]];
SELECT TRUE FROM
Pc.Entry[lf ! SymbolTable.Missing => GOTO bailout] => ex ← entry;
Pc.Exit[lf] => ex ← exit;
ENDCASE => ex ← in;
gf ← Lf.GF[lf ! Frames.Invalid, Lf.NoAccessLink => CONTINUE];
IF (f ← TryCtx[id,[DebugOps.Lengthen[lf],0],LOOPHOLE[2]]) # NIL THEN RETURN;
list ← Pc.ContextList[Lf.PC[lf],gf,search,ex];
IF list = NIL THEN RETURN[InGF[id,gf,check]];
Add[];
f ← SearchList[id,list,lf,gf ! UNWIND => {Pc.FreeContextList[list]; Drop[]}];
Pc.FreeContextList[list];
Drop[];
IF f = NIL THEN RETURN[InGF[id,gf,check]];
EXITS
bailout => RETURN[NIL]
END;
SearchList: PROC [id: HTIndex, list: Pc.CtxLink, lf: FHandle, gf: GFHandle]
RETURNS [f: Foo] =
BEGIN
ba: DebugOps.BitAddress ← [DebugOps.Lengthen[lf],0];
level: ContextLevel;
f ← NIL;
list ← FixupList[list];
level ← GetLevel[list];
IF level = lG THEN ba.base ← DebugOps.Lengthen[gf];
FOR i: Pc.CtxLink ← list, i.link UNTIL i = NIL DO
ba.useStack ← i.onStack;
ba.local ← level # lG;
SELECT GetLevel[i] FROM
= level => NULL;
< level => {
level ← GetLevel[i];
IF level = lG THEN ba.base ← DebugOps.Lengthen[gf]
ELSE {
lf ← DebugOps.ShortREAD[@lf.local[0]] - PrincOps.localbase;
ba.base ← DebugOps.Lengthen[lf]}};
ENDCASE => ERROR SearchingWrongContext;
IF (f ← TryProcCtx[id,ba,i]) # NIL THEN EXIT;
ENDLOOP;
END;
FixupList: PROC [list: Pc.CtxLink] RETURNS [Pc.CtxLink] =
BEGIN
twoBefore, last: Pc.CtxLink;
outOfOrder: BOOLEAN ← TRUE;
WHILE outOfOrder DO
twoBefore ← last ← NIL;
outOfOrder ← FALSE;
FOR i: Pc.CtxLink ← list, i.link UNTIL i = NIL DO
IF last # NIL AND GetLevel[i] > GetLevel[last] THEN
BEGIN
outOfOrder ← TRUE;
last.link ← i.link; i.link ← last;
IF twoBefore = NIL THEN list ← i ELSE twoBefore.link ← i;
EXIT;
END;
twoBefore ← last;
last ← i;
ENDLOOP;
ENDLOOP;
RETURN[list];
END;
GetLevel: PROC [i: Pc.CtxLink] RETURNS [ContextLevel] = {
RETURN[IF i.null THEN i.level ELSE ctxb[i.ictx].level]};
OnStack: PUBLIC PROC [
id: HTIndex, lf: FHandle ← NIL, check: BOOLEAN ← TRUE]
RETURNS [f: Foo] =
BEGIN
h: State.Handle = State.Get[];
IF h.howSet = break THEN RETURN[InBreakBlock[id,h.interpretContext]];
IF lf = NIL THEN lf ← h.interpretContext;
IF data.search THEN RETURN[InLF[id,lf,check]];
IF Gf.Validate[LOOPHOLE[lf]] THEN RETURN[InGF[id,LOOPHOLE[lf],check]];
f ← NIL;
DO
IF lf = NIL THEN EXIT;
IF (f←InLF[id,lf,check !SymbolTable.Missing => CONTINUE])#NIL THEN EXIT;
lf ← Lf.Previous[lf ! Lf.NoPrevious => EXIT];
ENDLOOP;
END;
LocalFrame: PROC [cl: PrincOps.SignalDesc, tm: Symbols.TransferMode]
RETURNS [isei: Symbols.ISEIndex]=
BEGIN
lf: FHandle ← State.Get[].h.interpretContext;
gf: GFHandle ← NIL;
list: Pc.CtxLink;
isei ← Symbols.ISENull;
IF lf = NIL THEN lf ← DebugOps.ShortREAD[@data.StatePtr.dest];
IF ~Lf.Validate[lf] THEN RETURN;
gf ← Lf.GF[lf ! Frames.Invalid, Lf.NoAccessLink => CONTINUE];
list ← Pc.ContextList[Lf.PC[lf],gf,search,in
! SymbolTable.Missing => GOTO bailout];
IF list = NIL THEN RETURN;
isei ← SearchListForValue[cl,tm,list,lf
! UNWIND => Pc.FreeContextList[list]];
Pc.FreeContextList[list];
EXITS
bailout => RETURN[Symbols.ISENull]
END;
SearchListForValue: PROC [
cl: PrincOps.SignalDesc, tm: Symbols.TransferMode, list: Pc.CtxLink,
lf: FHandle]
RETURNS [isei: Symbols.ISEIndex] =
BEGIN
i: Pc.CtxLink;
isei ← Symbols.ISENull;
FOR i ← list, i.link UNTIL i = NIL DO
IF i.null OR i.ictx = Symbols.IncludedCTXNull THEN LOOP;
IF (isei ← DI.SearchCtxForVal[cl,i.ictx,tm]) # Symbols.ISENull THEN EXIT;
ENDLOOP;
END;
InBreakBlock: PUBLIC PROC [id: HTIndex, bb: DebugFormat.BBHandle] RETURNS [f: Foo] =
BEGIN
list: Pc.CtxLink;
list ← Pc.ContextList[bb.pc,bb.gf,search,bb.bt.ex];
IF list # NIL THEN {
Add[];
f ← SearchList[id,list,NIL,bb.gf !
Lookup.NotRelocated => RESUME[NIL];
UNWIND => {Pc.FreeContextList[list]; Drop[]}];
Pc.FreeContextList[list];
Drop[];
IF f # NIL THEN RETURN};
RETURN[InGF[id,bb.gf,FALSE]];
END;
Signal: PUBLIC PROC [cl: PrincOps.SignalDesc]
RETURNS [isei: Symbols.ISEIndex] =
BEGIN RETURN[Xfer[cl,signal]] END;
Proc: PUBLIC PROC [cl: PrincOps.SignalDesc]
RETURNS [isei: Symbols.ISEIndex] =
BEGIN RETURN[Xfer[cl,proc]] END;
Xfer: PROC [cl: PrincOps.SignalDesc, tm: Symbols.TransferMode]
RETURNS [isei: Symbols.ISEIndex] =
BEGIN OPEN Symbols;
gf: GFHandle = Gf.FrameGfi[cl.gfi];
gfi: MachineDefs.GFTIndex;
syms: DSyms.Item;
IF gf = NIL THEN RETURN[ISENull];
gfi ← Gf.GFI[gf] - 1;
syms ← DSyms.FindFrame[gf];
IF syms = NIL THEN {
[] ← DSyms.GFrameMdi[gf ! SymbolTable.Missing => GOTO bailout];
syms ← DSyms.FindFrame[gf]};
cl.gfi ← cl.gfi - gfi;
SELECT TRUE FROM
(isei ← DI.SearchCtxForVal[cl,syms.outerCtx,tm]) # ISENull => NULL;
(isei ← DI.SearchCtxForVal[cl,syms.importCtx,tm]) # ISENull => NULL;
(isei ← DI.SearchCtxForVal[cl,syms.directoryCtx,tm]) # ISENull => NULL;
(isei ← LocalFrame[cl,tm]) # ISENull => NULL;
ENDCASE => RETURN[Symbols.ISENull];
EXITS
bailout => RETURN[Symbols.ISENull]
END;
XferCtx: PUBLIC PROC [sei: SEIndex, base: LONG POINTER, io: InOut]
RETURNS [f: Foo] =
BEGIN
IF sei = SENull THEN RETURN[NIL];
f ← DHeap.AllocFob[]; -- initialized to all zero
f.xfer ← TRUE;
f.there ← TRUE;
f.addr.base ← base;
Add[];
WITH seb[DI.TypeForSe[sei]] SELECT FROM
transfer =>
BEGIN
rsei: Symbols.RecordSEIndex ← IF io = in THEN inRecord ELSE outRecord;
IF rsei = Symbols.SENull THEN {f.addr.base ← NIL; f.tsei ← Symbols.RecordSENull}
ELSE
BEGIN
f.tsei ← rsei;
[f.words, f.bits] ← DI.Normalize[seb[rsei].length];
END;
END;
ENDCASE => {Drop[]; ERROR NotAnXfer};
Drop[];
END;
StateCtx: PUBLIC PROCEDURE [
sei: SEIndex, sv: MachineDefs.SVPointer, io: InOut,
max: CARDINAL ← MachineDefs.MaxParmsInStack]
RETURNS [f: Foo] =
BEGIN
locals: POINTER;
f ← XferCtx[sei,NIL,io];
IF f = NIL OR f.tsei = Symbols.RecordSENull THEN RETURN;
locals ←
IF f.words > max THEN DebugOps.ShortREAD[@sv.stk[0]] ELSE @sv.stk[0];
f.addr.base ← DebugOps.Lengthen[locals];
f.addr.useStack ← TRUE;
END;
GFFoo: PROC [hti: HTIndex, gf: GFHandle, mdi: MDIndex, check: BOOLEAN]
RETURNS [f: Foo] =
BEGIN OPEN SymbolOps;
ba: DebugOps.BitAddress;
syms: DSyms.Item = DSyms.FindFrame[gf];
IF gf # NIL AND check THEN [] ← Gf.CheckStarted[gf];
ba ← [base: DebugOps.Lengthen[gf], offset: 0, local: FALSE];
IF (f ← TryCtx[hti,ba,LOOPHOLE[2]]) # NIL THEN RETURN;
IF (f ← TryCtx[hti,ba,syms.outerCtx]) # NIL THEN RETURN;
IF (f ← SearchImportCtx[hti,ba,syms.importCtx]) # NIL THEN RETURN;
f ← SearchDirectoryCtx[hti,ba,syms.directoryCtx,mdi];
END;
SearchDirectoryCtx: PROC [
hti: HTIndex, ba: DebugOps.BitAddress, ictx: Symbols.CTXIndex,
mdi: MDIndex]
RETURNS [f: Foo] =
BEGIN
mdRoot: MDIndex;
target: CTXIndex;
sei, isei: Symbols.ISEIndex;
ss: Strings.SubStringDescriptor;
found: BOOLEAN;
Search: PROC [base: SymbolTable.Base] =
BEGIN
newMdi: Symbols.MDIndex = base.FindMdi[mdb[mdRoot].stamp];
ihti: Symbols.HTIndex ← base.FindString[@ss];
found ← ihti # Symbols.HTNull AND newMdi # Symbols.MDNull;
IF ~found THEN RETURN;
FOR i: IncludedCTXIndex ← base.mdb[newMdi].ctx,
base.ctxb[i].chain UNTIL i = Symbols.CTXNull DO
IF base.ctxb[i].map # target THEN LOOP;
isei ← base.SearchContext[ihti,i];
EXIT;
REPEAT
FINISHED => isei ← Symbols.ISENull;
ENDLOOP;
found ← isei # Symbols.ISENull;
END;
IF ictx = Symbols.CTXNull THEN RETURN[NIL];
IF (f ← TryCtx[hti,ba,ictx]) # NIL THEN RETURN;
Complete[ictx];
SymbolOps.SubStringForHash[@ss,hti];
Add[];
FOR sei ← SymbolOps.FirstCtxSe[ictx], SymbolOps.NextSe[sei]
UNTIL sei = Symbols.ISENull DO
ictx ← GetCtx[sei];
WITH ctxb[ictx] SELECT FROM
included => {mdRoot ← module; target ← map};
ENDCASE => LOOP;
Copier.Outer[mdi,Search];
IF ~found THEN LOOP;
-- isei ← Copier.TokenSymbol[ictx,LOOPHOLE[isei]];
isei ← DI.SearchCtxList[hti,ictx];
IF isei = Symbols.ISENull THEN EXIT;
SELECT Mode[isei] FROM
refVal, refProc => NULL;
ENDCASE => f ← MakeFoo[isei,ba];
EXIT;
ENDLOOP;
Drop[];
END;
SearchImportCtx: PROC [
hti: HTIndex, ba: DebugOps.BitAddress, ictx: Symbols.CTXIndex]
RETURNS [f: Foo] =
BEGIN OPEN SymbolOps;
isei: Symbols.ISEIndex;
IF ictx = Symbols.CTXNull THEN RETURN[NIL];
IF (f ← TryCtx[hti,ba,ictx]) # NIL THEN RETURN;
Complete[ictx];
Add[];
FOR isei ← FirstCtxSe[ictx], NextSe[isei] UNTIL isei = Symbols.ISENull DO
IF (f ← TryCtx[hti,ba,GetCtx[isei]]) # NIL THEN EXIT;
ENDLOOP;
Drop[];
END;
GetCtx: PROC [isei: Symbols.ISEIndex] RETURNS [ctx: Symbols.CTXIndex] =
BEGIN
csei: Symbols.CSEIndex ← DI.TypeForSe[isei];
DO
WITH seb[csei] SELECT FROM
definition => RETURN[defCtx];
record => RETURN[fieldCtx];
ref => csei ← DI.TypeForSe[refType];
long => csei ← DI.TypeForSe[rangeType];
ENDCASE => RETURN[Symbols.CTXNull];
ENDLOOP;
END;
TryCtx: PROC [hti: HTIndex, ba: DebugOps.BitAddress, ctx: CTXIndex]
RETURNS [f: Foo] =
BEGIN
isei: Symbols.ISEIndex = DI.SearchCtxList[hti,ctx];
SELECT TRUE FROM
UserInput.userAbort => ERROR DebugOps.UserAborted;
isei = ISENull => RETURN[NIL];
ba.useStack => ERROR SearchingWrongContext;
ENDCASE;
RETURN[MakeFoo[isei, ba]];
END;
TryProcCtx: PROC [hti: HTIndex, ba: DebugOps.BitAddress, list: Pc.CtxLink]
RETURNS [f: Foo] =
BEGIN
isei: Symbols.ISEIndex = DI.SearchCtxList[hti,list.ictx];
stack: POINTER;
SELECT TRUE FROM
UserInput.userAbort => ERROR DebugOps.UserAborted;
isei = ISENull => RETURN[NIL];
ba.useStack AND ba.base # NIL AND Lookup.Mode[isei] = val => {
stack ← IF list.indirect THEN DebugOps.ShortREAD[@data.StatePtr.stk[0]]
ELSE @data.StatePtr.stk[0];
ba.base ← DebugOps.Lengthen[stack]};
ENDCASE;
RETURN[MakeFoo[isei, ba]];
END;
FindVar: PUBLIC PROC [var: STRING] =
BEGIN
hti: HTIndex = StringToHti[var];
f: Foo;
gf: GFHandle;
SearchOne: PROC [g: GFHandle] RETURNS [BOOLEAN] =
BEGIN
IF (f←InGF[hti,g]) # NIL THEN {gf ← g; RETURN[TRUE]};
Init.CheckSymTabLength[];
RETURN[FALSE];
END;
DContext.Enumerate[SearchOne];
IF f = NIL THEN SIGNAL Fail[var];
f.hti ← Symbols.HTNull; DOutput.Char[Ascii.SP]; DebugOps.Display[f,TRUE];
Gf.DisplayInMsg[gf, NIL];
END;
END.