<> <> <> <> <<>> <> <<>> DIRECTORY Basics USING [Card32FromF, CompareCard, FWORD], IO, RedBlackTree, Rope, SparcSymbols; SparcSymbolsImpl: CEDAR PROGRAM IMPORTS Basics, IO, RedBlackTree, Rope EXPORTS SparcSymbols ~ BEGIN Tables: TYPE ~ SparcSymbols.Tables; Symbol: TYPE ~ REF SymbolRec; SymbolRec: TYPE ~ RECORD[ txt: Rope.ROPE _ NIL, type: Basics.FWORD _ [[0, 0], [0, 0]], val: CARD32 _ 0 ]; <> GetUnsigned: PROC [s: IO.STREAM] RETURNS [u: CARD32] ~ { RETURN[Basics.Card32FromF[IO.GetFWord[s]]]; }; GetLocAndSize: PROC [s: IO.STREAM] RETURNS [off, size: INT] ~ { text, data, trsize, drsize: CARD32; [] _ GetUnsigned[s]; --machine flags etc text _ GetUnsigned[s]; data _ GetUnsigned[s]; [] _ GetUnsigned[s]; --bss not actually present in the file size _ GetUnsigned[s]; [] _ GetUnsigned[s]; --entry point: don't care trsize _ GetUnsigned[s]; drsize _ GetUnsigned[s]; off _ text+data+trsize+drsize; }; StopOnZero: IO.BreakProc ~ {RETURN[IF char='\000 THEN break ELSE other]}; GetOneSymbol: PROC [s: IO.STREAM, strOff: INT] RETURNS [sym: Symbol] ~ { index: INT; txtOff: INT _ GetUnsigned[s]; sym _ NEW[SymbolRec]; sym.type _ IO.GetFWord[s]; sym.val _ GetUnsigned[s]; index _ IO.GetIndex[s]; IF txtOff=0 THEN RETURN; IO.SetIndex[s, strOff+txtOff]; sym.txt _ IO.GetTokenRope[stream: s, breakProc: StopOnZero].token; IO.SetIndex[s, index]; }; XtractAddr: RedBlackTree.GetKey ~ {RETURN[data]}; XtractName: RedBlackTree.GetKey ~ {RETURN[NARROW[data, Symbol].txt]}; CompareAddr: RedBlackTree.Compare ~ {RETURN[Basics.CompareCard[ NARROW[k, Symbol].val, NARROW[data, Symbol].val ]]}; CompareName: RedBlackTree.Compare ~ {RETURN[Rope.Compare[ NARROW[k], NARROW[data, Symbol].txt ]]}; GetSymbols: PUBLIC PROC [s: IO.STREAM] RETURNS [tables: Tables] ~ { <> symOff, strOff, symSize, strSize: INT; IO.SetIndex[s, 0]; -- just in case the stream has already been red [symOff, symSize] _ GetLocAndSize[s]; strOff _ symOff+symSize; IO.SetIndex[s, strOff]; strSize _ GetUnsigned[s]; IO.SetIndex[s, symOff]; tables _ NEW[SparcSymbols.TablesRec _ [ byAddr: RedBlackTree.Create[XtractAddr, CompareAddr], byName: RedBlackTree.Create[XtractName, CompareName] ]]; WHILE IO.GetIndex[s] CONTINUE]; ENDLOOP; }; <<>> <> GetClosestName: PUBLIC PROC [addr: CARD32, tables: Tables] RETURNS [name: Rope.ROPE] ~ { lookupSym: Symbol _ NEW[SymbolRec _ [val: addr]]; sym: Symbol _ NARROW[RedBlackTree.Lookup[tables.byAddr, lookupSym]]; IF sym=NIL THEN sym _ NARROW[RedBlackTree.LookupNextSmaller[tables.byAddr, lookupSym]]; RETURN[sym.txt]; }; GetAddress: PUBLIC PROC [name: Rope.ROPE, tables: Tables] RETURNS [addr: CARD32] ~ { sym: Symbol _ NARROW[RedBlackTree.Lookup[tables.byName, name]]; RETURN[IF sym=NIL THEN 0 ELSE sym.val]; }; <> ListTable: PROC [out: IO.STREAM, table: RedBlackTree.Table] ~ { PrintEachEntry: RedBlackTree.EachNode ~ { sym: Symbol _ NARROW[data]; IO.PutF[out, "%g\t\t(%8x) =\t%d\n", IO.rope[sym.txt], IO.card[LOOPHOLE[sym.type]], IO.card[sym.val]]; }; RedBlackTree.EnumerateIncreasing[table, PrintEachEntry]; }; ListTables: PUBLIC PROC [out: IO.STREAM, tables: Tables] ~ { IO.PutRope[out, "\nMap by address: \n"]; ListTable[out, tables.byAddr]; IO.PutRope[out, "\nMap by name: \n"]; ListTable[out, tables.byName]; }; END.