-- ListSymbols.mesa; 
--   modified by Bruce, 13-Jan-81 11:02:17
--   modified by Sandman, July 8, 1980  9:29 AM
--   modified by Sweet, 13-Feb-81 14:47:19
--   modified by Satterthwaite, September 20, 1982 1:40 pm

DIRECTORY
  BcdDefs: TYPE USING [VersionStamp],
  CommanderOps: TYPE USING [CommandBlockHandle, AddCommand],
  CompilerUtil: TYPE USING [PrintSymbols, PrintBodies],
  Environment: TYPE USING [PageNumber, PageCount],
  FileSegment: TYPE USING [Pages],
  Heap: TYPE USING [systemZone],
  ListerDefs: TYPE USING [
    IncorrectVersion, Load, MultipleModules, NoCode, NoFGT, NoFile,
    NoSymbols, SetRoutineSymbols, WriteFileID, WriteString, WriteVersions],
  LiteralOps: TYPE USING [Initialize, Finalize],
  OSMiscOps: TYPE USING [FindFile, FileError],
  OutputDefs: TYPE USING [OpenOutput, CloseOutput, PutString, PutCR, PutDecimal],
  Strings: TYPE USING [AppendString],
  SymbolTable: TYPE USING [Acquire, Base, Release, SetCacheSize],
  TreeOps: TYPE USING [Finalize, Initialize];

ListSymbols: PROGRAM
    IMPORTS
      CommanderOps, CompilerUtil, ListerDefs, Heap, LiteralOps,
      OSMiscOps, OutputDefs, Strings, SymbolTable, TreeOps = {
  OPEN ListerDefs;
  
  CommandOption: TYPE = {bodies, symbols};
  SymbolSeg: TYPE = RECORD [
    base: Environment.PageNumber,
    pages: Environment.PageCount];
      

  PrintSyms: PROC [
      sseg: FileSegment.Pages, option: CommandOption, versions: BOOLEAN] = {
    symbols: SymbolTable.Base;
    SymbolTable.SetCacheSize[0];	-- flush cache
    symbols ← SymbolTable.Acquire[sseg];
    ListerDefs.SetRoutineSymbols[symbols];
    IF versions THEN {
      version, creator: BcdDefs.VersionStamp;
      version ← symbols.stHandle.version;
      creator ← symbols.stHandle.creator;
      ListerDefs.WriteVersions[@version, @creator]};
    TreeOps.Initialize[NIL, NIL]; LiteralOps.Initialize[NIL, Heap.systemZone];
    SELECT option FROM
      symbols => CompilerUtil.PrintSymbols[NIL, symbols.stHandle.definitionsFile];
      bodies => CompilerUtil.PrintBodies[NIL];
      ENDCASE;
    OutputDefs.CloseOutput[];
    LiteralOps.Finalize[];  TreeOps.Finalize[];
    SymbolTable.Release[symbols]};
    
  MakeBcdFilename: PROC [bcd, root: STRING] = {
    Strings.AppendString[bcd, root];
    FOR i: CARDINAL IN [0..bcd.length) DO IF bcd[i] = '. THEN RETURN ENDLOOP;
    Strings.AppendString[bcd, ".bcd"L]};
    
  DoSymbols: PROC [root: STRING, option: CommandOption] = {
    bcdFile: STRING ← [40];
    sseg: FileSegment.Pages;
    MakeBcdFilename[bcdFile, root];
    [symbols: sseg] ← Load[bcdFile !
      NoCode => {RESUME};
      NoFGT => {RESUME};
      NoSymbols, IncorrectVersion, MultipleModules => {
	WriteString["Bad format"]; GOTO giveup};
      NoFile => {WriteString["File not found"]; GOTO giveup}];
    OutputDefs.OpenOutput[root, ".sl"L];
    ListerDefs.WriteFileID[];
    PrintSyms[sseg, option, FALSE];
    EXITS  giveup => NULL};
    
  DoSymbolSegment: PROC [
      root: STRING, pages: SymbolSeg, option: CommandOption] = {
    bcdFile: STRING ← [40];
    sseg: FileSegment.Pages;
    MakeBcdFilename[bcdFile, root];
    sseg ← [
      file: OSMiscOps.FindFile[bcdFile ! OSMiscOps.FileError => {GO TO NoFile}],
      span: [pages.base, pages.pages] --! SwapProblem[] => {GO TO BadSegment}--];
    OutputDefs.OpenOutput[root, ".sl"L];
    OutputDefs.PutString["Symbol Table in file: "L];
    OutputDefs.PutString[root];
    OutputDefs.PutString[", base: "L];
    OutputDefs.PutDecimal[pages.base];
    OutputDefs.PutString[", pages: "L];
    OutputDefs.PutDecimal[pages.pages];
    OutputDefs.PutCR[];
    PrintSyms[sseg, option, TRUE];
    EXITS
      NoFile => WriteString["File not found"L];
      --BadSegment => WriteString["Bad Segment"L]--};
    
  Symbols: PROC [root: STRING] = {DoSymbols[root, symbols]};
    
  SymbolSegment: PROC [
      root: STRING, base: Environment.PageNumber, pages: Environment.PageCount] = {
    DoSymbolSegment[root, [base, pages], symbols]};
    
  Bodies: PROC [root: STRING] = {DoSymbols[root, bodies]};
    
  BodySegment: PROC [
      root: STRING, base: Environment.PageNumber, pages: Environment.PageCount] = {
    DoSymbolSegment[root, [base, pages], bodies]};
    
  Init: PROC = {
    OPEN CommanderOps;
    command: CommandBlockHandle;
    command ← AddCommand["Symbols", LOOPHOLE[Symbols], 1];
    command.params[0] ← [type: string, prompt: "Filename"];
    command ← AddCommand["SymbolSegment", LOOPHOLE[SymbolSegment], 3];
    command.params[0] ← [type: string, prompt: "Filename"];
    command.params[1] ← [type: numeric, prompt: "Base"];
    command.params[2] ← [type: numeric, prompt: "Pages"];
    command ← AddCommand["Bodies", LOOPHOLE[Bodies], 1];
    command.params[0] ← [type: string, prompt: "Filename"];
    command ← AddCommand["BodySegment", LOOPHOLE[BodySegment], 3];
    command.params[0] ← [type: string, prompt: "Filename"];
    command.params[1] ← [type: numeric, prompt: "Base"];
    command.params[2] ← [type: numeric, prompt: "Pages"]};
    
  Init[];
  
  }.