-- ListSymbols.mesa; 
--   modified by Sandman, July 8, 1980  9:29 AM
--   modified by Sweet, August 28, 1980  9:47 AM

DIRECTORY
  AltoDefs USING [PageNumber, PageCount],
  CommanderDefs USING [CommandBlockHandle, AddCommand],
  ComData USING [definitionsOnly, errorStream],
  CompilerUtil USING [PrintSymbols, PrintBodies],
  Inline USING [LowHalf],
  IODefs USING [WriteString],
  ListerDefs USING [
    IncorrectVersion, Load, MultipleModules, NoCode, NoFGT, NoSymbols,
    SetRoutineSymbols, WriteFileID, WriteVersions],
  LiteralOps USING [Initialize],
  OutputDefs USING [
    OpenOutput, CloseOutput, outStream, PutString, PutCR, PutDecimal],
  SegmentDefs USING [
    FileSegmentHandle, FileNameError, NewFileSegment, Read, DefaultVersion,
    InvalidSegmentSize, SwapError, DeleteFileSegment, NewFile],
  String USING [AppendString],
  SymbolTable USING [Acquire, Release, Base, TableForSegment],
  TreeOps USING [Initialize];

ListSymbols: PROGRAM
  IMPORTS
    CommanderDefs, CompilerUtil, data: ComData, Inline, IODefs, ListerDefs, 
    LiteralOps, OutputDefs, SegmentDefs, String, SymbolTable, TreeOps
  EXPORTS ListerDefs =
  BEGIN OPEN ListerDefs;
  
  symbols: SymbolTable.Base;
  sseg: SegmentDefs.FileSegmentHandle;
  commandType: {bodies, symbols};
  
  PrintSyms: PROCEDURE =
    BEGIN
    data.definitionsOnly ← symbols.stHandle.definitionsFile;
    data.errorStream ← OutputDefs.outStream;
    SELECT commandType FROM
      symbols => CompilerUtil.PrintSymbols[];
      bodies => CompilerUtil.PrintBodies[];
      ENDCASE;
    OutputDefs.CloseOutput[];
    SymbolTable.Release[symbols];
    SegmentDefs.DeleteFileSegment[sseg ! SegmentDefs.SwapError => CONTINUE]
    END;
    
  GetSymbolTable: PROCEDURE [seg: SegmentDefs.FileSegmentHandle] =
    BEGIN
    symbols ← SymbolTable.Acquire[SymbolTable.TableForSegment[seg]];
    ListerDefs.SetRoutineSymbols[symbols];
    TreeOps.Initialize[];
    LiteralOps.Initialize[];
    END;
    
  MakeBcdFilename: PROCEDURE [bcd, root: STRING] =
    BEGIN OPEN String;
    i: CARDINAL;
    AppendString[bcd, root];
    FOR i IN [0..bcd.length) DO IF bcd[i] = '. THEN RETURN; ENDLOOP;
    AppendString[bcd, ".bcd"L];
    END;
    
  DoSymbols: PROCEDURE [root: STRING] =
    BEGIN
    bcdFile: STRING ← [40];
    MakeBcdFilename[bcdFile, root];
    BEGIN
    [symbols: sseg] ← Load[
      bcdFile ! NoCode => RESUME ; NoFGT => RESUME ;
      NoSymbols, IncorrectVersion, MultipleModules =>
	BEGIN IODefs.WriteString["Bad format"]; GOTO giveup END;
      SegmentDefs.FileNameError =>
	BEGIN IODefs.WriteString["File not found"]; GOTO giveup END];
    GetSymbolTable[sseg];
    OutputDefs.OpenOutput[root, ".sl"L];
    ListerDefs.WriteFileID[];
    PrintSyms[];
    EXITS giveup => NULL;
    END;
    END;
    
  DoSymbolSegment: PROCEDURE [
    root: STRING, base: AltoDefs.PageNumber, pages: AltoDefs.PageCount] =
    BEGIN OPEN SegmentDefs;
    bcdFile: STRING ← [40];
    MakeBcdFilename[bcdFile, root];
    BEGIN
    sseg ← NewFileSegment[
      NewFile[bcdFile, Read, DefaultVersion ! FileNameError => GO TO NoFile],
      base, pages, Read ! InvalidSegmentSize => GO TO BadSegment];
    GetSymbolTable[sseg];
    OutputDefs.OpenOutput[root, ".sl"L];
    OutputDefs.PutString["Symbol Table in file: "L];
    OutputDefs.PutString[root];
    OutputDefs.PutString[", base: "L];
    OutputDefs.PutDecimal[base];
    OutputDefs.PutString[", pages: "L];
    OutputDefs.PutDecimal[pages];
    OutputDefs.PutCR[];
    ListerDefs.WriteVersions[
      Inline.LowHalf[@symbols.stHandle.version], 
      Inline.LowHalf[@symbols.stHandle.creator]];
    PrintSyms[];
    EXITS
      NoFile => IODefs.WriteString["File not found"];
      BadSegment => IODefs.WriteString["Bad Segment"];
    END;
    END;
    
  Symbols: PROCEDURE [root: STRING] =
    BEGIN commandType ← symbols; DoSymbols[root] END;
    
  SymbolSegment: PROCEDURE [
    root: STRING, base: AltoDefs.PageNumber, pages: AltoDefs.PageCount] =
    BEGIN commandType ← symbols; DoSymbolSegment[root, base, pages] END;
    
  Bodies: PROCEDURE [root: STRING] =
    BEGIN commandType ← bodies; DoSymbols[root] END;
    
  BodySegment: PROCEDURE [
    root: STRING, base: AltoDefs.PageNumber, pages: AltoDefs.PageCount] =
    BEGIN commandType ← bodies; DoSymbolSegment[root, base, pages] END;
    
  Init: PROCEDURE =
    BEGIN OPEN CommanderDefs;
    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"];
    END;
    
  Init[];
  
  END...