ProcMapImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Russ Atkinson, March 7, 1985 4:11:01 am PST
Sweet November 21, 1985 5:01:01 pm PST
DIRECTORY
AMTypes,
BcdDefs,
ConvertUnsafe,
ProcMap,
Rope,
RTSymbolDefs,
RTSymbols,
Symbols,
SymbolSegment,
SymbolTable;
ProcMapImpl:
CEDAR PROGRAM
IMPORTS AMTypes, ConvertUnsafe, Rope, RTSymbols
EXPORTS ProcMap
= BEGIN
Item: TYPE = ProcMap.Item;
Object: TYPE = ProcMap.Object;
Handle: TYPE = ProcMap.Handle;
ROPE: TYPE = Rope.ROPE;
SubString: TYPE = ConvertUnsafe.SubString;
BodyInfo: TYPE = Symbols.BodyInfo;
BTIndex:
TYPE = Symbols.BTIndex;
BTNull: BTIndex = Symbols.BTNull;
CBTIndex: TYPE = Symbols.CBTIndex;
FGTEntry: TYPE = SymbolSegment.FGTEntry;
HTIndex:
TYPE = Symbols.HTIndex;
HTNull: HTIndex = Symbols.HTNull;
ISEIndex:
TYPE = Symbols.ISEIndex;
ISENull: ISEIndex = Symbols.ISENull;
SEIndex:
TYPE = Symbols.SEIndex;
SENull: SEIndex = Symbols.SENull;
FromSource:
PUBLIC PROC [h: Handle, src:
INT]
RETURNS [
ROPE] =
BEGIN
l, u, m: INTEGER;
IF h = NIL THEN RETURN["<anon>"];
l ← 0; u ← h.length - 1;
WHILE l <= u
DO
m ← (l+u)/2;
SELECT h[m].firstSource
FROM
< src => l ← m + 1;
> src => u ← m - 1;
ENDCASE => RETURN [h[m].proc];
ENDLOOP;
-- By Knuth 6.2.1, exercise 1, source[u] < src < source[l] (if unique keys)
RETURN [IF u = -1 THEN "<anon>" ELSE h[u].proc]
END;
Create:
PUBLIC
PROC [module:
ROPE]
RETURNS [h: Handle] =
TRUSTED {
sth: RTSymbolDefs.SymbolTableHandle ← RTSymbolDefs.nullHandle;
rstb: RTSymbolDefs.SymbolTableBase;
stb: SymbolTable.Base;
sth ← RTSymbols.GetSTHForModule[
stamp: BcdDefs.NullVersion,
fileName: module,
moduleName: NIL ! AMTypes.Error => CONTINUE];
IF sth = RTSymbolDefs.nullHandle THEN RETURN [NIL];
rstb ← RTSymbols.AcquireSTB[sth];
WITH rstb
SELECT
FROM
x => stb ← e;
y => stb ← e;
ENDCASE;
h ← ProduceSourceMap[stb ! UNWIND => RTSymbols.ReleaseSTB[rstb]];
RTSymbols.ReleaseSTB[rstb];
};
ProduceSourceMap:
PUBLIC
PROC[stb: SymbolTable.Base]
RETURNS[h: Handle] =
TRUSTED {
DigestFGT:
PROC =
TRUSTED {
bti: BTIndex;
proc: ROPE;
n: CARDINAL ← 0;
AddMyEntry:
PROC [source:
INT] =
TRUSTED {
IF n = h.maxLength
THEN {
oldFGT: Handle ← h;
myFGTSize: CARDINAL ← myFGTSize + myFGTSize/2 + 16;
h ← NEW[Object[myFGTSize]];
IF oldFGT #
NIL
THEN
FOR i:
NAT
IN [0..oldFGT.maxLength)
DO
h[i] ← oldFGT[i] ENDLOOP;
};
h[n] ← [firstSource: source, proc: proc];
h.length ← n ← n + 1;
};
AddBodyFGT:
PROC [bti: Symbols.CBTIndex] =
TRUSTED {
info: BodyInfo[External] = NARROW[stb.bb[bti].info, BodyInfo[External]];
fgLast: CARDINAL = info.startIndex + info.indexLength - 1;
lastSource: INT ← stb.bb[bti].sourceIndex;
FOR i:
CARDINAL
IN [info.startIndex..fgLast]
DO
f: FGTEntry = stb.fgTable[i];
WITH f
SELECT
FROM
normal => {
lastSource ← lastSource + deltaSource;
AddMyEntry[lastSource]};
step =>
IF which = $source THEN lastSource ← lastSource + delta;
ENDCASE;
ENDLOOP;
};
Sort:
PROC =
TRUSTED {
i: CARDINAL;
temp: Item;
SiftUp:
PROC [l, u:
CARDINAL] =
TRUSTED {
s: CARDINAL;
key: Item ← h[l-1];
DO
s ← l*2;
IF s > u THEN EXIT;
IF s < u AND h[s+1-1].firstSource > h[s-1].firstSource THEN s ← s+1;
IF key.firstSource > h[s-1].firstSource THEN EXIT;
h[l-1] ← h[s-1];
l ← s;
ENDLOOP;
h[l-1] ← key};
FOR i DECREASING IN [2..n/2] DO SiftUp[i, n]; ENDLOOP;
FOR i
DECREASING
IN [2..n]
DO
SiftUp[1, i];
temp ← h[1-1];
h[1-1] ← h[i-1];
h[i-1] ← temp;
ENDLOOP;
}; -- end of Sort procedure
h ← NEW[Object[stb.fgTable.LENGTH + 1]]; -- probably big enough
bti ← BTIndex.FIRST; proc ← NIL;
IF stb.bb[bti].sourceIndex # 0
THEN
AddMyEntry[source: 0];
DO
WITH stb.bb[bti]
SELECT
FROM
Callable =>
IF ~inline
THEN {
cbti: CBTIndex = LOOPHOLE[bti];
proc ← BodyName[cbti];
AddBodyFGT[cbti]};
ENDCASE;
IF stb.bb[bti].firstSon # BTNull
THEN bti ← stb.bb[bti].firstSon
ELSE
DO
prev: BTIndex ← bti;
bti ← stb.bb[bti].link.index;
IF bti = BTNull THEN GO TO Done;
IF stb.bb[prev].link.which # $parent THEN EXIT;
ENDLOOP;
REPEAT Done => NULL;
ENDLOOP;
Sort[];
};
BodyName:
PROC[bti: Symbols.CBTIndex]
RETURNS[
ROPE] =
TRUSTED {
sei: ISEIndex = stb.bb[bti].id;
hti: HTIndex;
IF sei = Symbols.SENull OR (hti ← stb.seb[sei].hash) = HTNull THEN RETURN["<anon>"]
ELSE
TRUSTED {
ss: SubString = stb.SubStringForName[hti];
rt: REF TEXT = NEW[TEXT[ss.length]];
ConvertUnsafe.AppendSubStringToRefText[to: rt, from: ss];
RETURN[Rope.FromRefText[rt]];
};
};
Executable part of SearchForLog.
IF stb.stHandle.definitionsFile THEN RETURN [NIL];
DigestFGT[];
};