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