-- MCrossRefOutput.mesa
				-- kap&wsh 16-Mar-80 13:12
				-- pdr September 20, 1982 1:09 pm
DIRECTORY
  Ascii USING[CR],
  Atom USING[GetPName],
  FileIO USING[Open],
  IO USING[Handle, PutChar, Close, Put, card, PutRope],
  Convert USING[ValueToRope],
  Inline USING[LowHalf],
  MCrossRefDefs,
  MCrossSorter USING[Enumerate],
  Rope USING[ROPE, Size, Fetch, Concat];

------------------------------------------------------------------

MCrossRefOutput: PROGRAM 

  IMPORTS Atom, FileIO, IO, Convert, Inline,
          MCrossSorter, Rope
  EXPORTS MCrossRefDefs
=

BEGIN OPEN MCrossRefDefs;

outputStream: IO.Handle ← NIL;
linePosition: CARDINAL ← 0;
linesTabPosition: CARDINAL ← 0;
tabPosition: PUBLIC CARDINAL;
CurrentPageNumber: CARDINAL ← 0;
WantNewLine: BOOLEAN ← FALSE;

originalOutputFileName: Rope.ROPE;
outputFileName: Rope.ROPE;

maxLinesPerOutputFile: LONG CARDINAL = 7000;
linesInThisOutputFile: LONG CARDINAL;
thisExtension: CARDINAL ← 0;

execTS: IO.Handle;

SetMCrossOutputStream: PUBLIC PROCEDURE[fileName: Rope.ROPE] =
   {outputFileName ← originalOutputFileName ← fileName;
    outputStream ← FileIO.Open
                      [fileName: outputFileName, accessOptions: overwrite];
    linesInThisOutputFile ← 0};

SetNextMCrossOutputStream: PROCEDURE =
  {IF thisExtension = 0 THEN IO.PutRope[execTS, "\n"];
    IO.PutRope[execTS, "***** "];
    IO.PutRope[execTS, outputFileName];
    IO.PutRope[execTS, " is filled. The "];
    IF thisExtension # 0 THEN IO.PutRope[execTS, "next "];
    IO.PutRope[execTS, "overflow file is named "];
    thisExtension ← thisExtension + 1;
    DestroyMCrossOutputStream[];
    outputFileName ← Rope.Concat[originalOutputFileName,
                                 Convert.ValueToRope[[signed[signed: thisExtension]]]];
    outputStream ← FileIO.Open
                      [fileName: outputFileName, accessOptions: overwrite];
    linesInThisOutputFile ← 0;
    IO.PutRope[execTS, outputFileName];
    IO.PutRope[execTS, "\n"]};

DestroyMCrossOutputStream: PUBLIC PROCEDURE =
  {IO.Close[outputStream]; outputStream ← NIL};

OutputLine: PUBLIC PROCEDURE [s: Rope.ROPE] =
 {OutputString[s];
  outputStream.PutChar[Ascii.CR];
  linesInThisOutputFile ← linesInThisOutputFile + 1};

OutputString: PUBLIC PROCEDURE [s: Rope.ROPE] =
 {FOR i: INT IN [0..Rope.Size[s]) DO outputStream.PutChar[Rope.Fetch[s,i]]; ENDLOOP};

OutputChar: PUBLIC PROCEDURE [ch: CHARACTER] = {outputStream.PutChar[ch]};

OutputRefCoord: PUBLIC PROCEDURE [coord: Coord] =
 {ln: LineNumberRange ← coord.ln;
  page: CARDINAL ← (ln-1)/Gacha8linesPerPage + 1;
  line: CARDINAL ← ln MOD Gacha8linesPerPage;
  NumberSize: CARDINAL ← 0;
  stringPosition : CARDINAL ← 0;
  i : CARDINAL← 0; -- loop index for spacing
  IF line = 0 THEN line ← Gacha8linesPerPage;--fix up MOD hiccup

  IF CurrentPageNumber # page
  THEN
   {IF CurrentPageNumber # 0 THEN
	{OutputLine[""]; 
 	 FOR i IN [0..tabPosition) DO OutputChar[' ];
	 ENDLOOP};
    WantNewLine ← FALSE; -- wipe out old value
    linePosition ← tabPosition;
    OutputString["Page: "];
    CurrentPageNumber ← page;
    NumberSize ←  SELECT page FROM
		IN [0..9] =>  1,
		IN [10..99] => 2,
		IN [100..999] => 3,
		ENDCASE => 4;
    linesTabPosition ← stringPosition ← NumberSize + 14;

    IO.Put[outputStream, IO.card[page]];
    OutputString[" Lines: "]}
  ELSE -- not a new page number 
   { IF WantNewLine
          THEN {OutputLine[""]; 
		linePosition ← tabPosition + linesTabPosition;
		FOR i IN [0..linePosition) DO OutputChar[' ] ENDLOOP;
		WantNewLine ← FALSE}
	  ELSE {stringPosition ← stringPosition + 2;
   		OutputString[", "]}};

  NumberSize ←  SELECT line FROM
		IN [0..9] =>  1,
		IN [10..99] => 2,
		ENDCASE => 3;
  stringPosition ← stringPosition + NumberSize;

  IO.Put[outputStream, IO.card[line]];
  IF coord.defn THEN
   {OutputString["[D]"];
    stringPosition ← stringPosition + 3};
  linePosition ← linePosition + stringPosition;
  IF linePosition + stringPosition >= Gacha8charsPerLine THEN
	WantNewLine ← TRUE};  -- END OutputRefCoord


      -- Here to print the XRef;
PrintXREF: PUBLIC PROCEDURE[tsStream: IO.Handle] =
    { execTS ← tsStream;
      OutputLine[""];
      OutputLine["***** Cross Reference *****"];
      OutputLine[""];

      [] ← MCrossSorter.Enumerate[OutputToken, increasing]};

OutputToken: PROC[t: TokenHandle] RETURNS[stop: BOOLEAN] =
      {   f: fileNHandle;
          x: XRefHandle;

          OutputString[Atom.GetPName[t.name]];

          FOR f ← t.fileNHead, f.next UNTIL f = NIL DO  -- for each file
             fNameString: Rope.ROPE = Atom.GetPName[f.name];
             OutputLine[""];
             OutputString["  "];  --  indent file names
             OutputString[fNameString];		-- filename
             OutputString[":  "];
             linePosition ← Inline.LowHalf[Rope.Size[fNameString]] + 5;
             FOR j: CARDINAL IN [linePosition..tabPosition) DO OutputChar[' ]; ENDLOOP;

             CurrentPageNumber ← 0;		-- force new page number

             FOR x ← f.xrefHead, x.next UNTIL x = NIL DO  -- For each ref in a file
                FOR j: CARDINAL IN [1..x.nRefs] DO OutputRefCoord[x.coords[j]]; ENDLOOP;
               ENDLOOP; 	-- For each ref in a file
           ENDLOOP;		-- for each file

          OutputLine[""];
          IF linesInThisOutputFile >= maxLinesPerOutputFile THEN
           { nextOutputFileName: Rope.ROPE ← NIL;
             OutputLine[""];
             OutputString[" ***** Cross Reference continued on "];
             nextOutputFileName ← Rope.Concat[originalOutputFileName, Convert.ValueToRope[[signed[signed: thisExtension + 1]]]];
	     OutputLine[nextOutputFileName];

             SetNextMCrossOutputStream[];

             OutputLine[""];
             OutputLine[""];
             OutputString[" ***** Cross Reference continued from "];
             IF thisExtension = 1
	      THEN nextOutputFileName ← originalOutputFileName
	      ELSE nextOutputFileName ← Rope.Concat[originalOutputFileName, Convert.ValueToRope[[signed[signed: thisExtension - 1]]]];
             OutputLine[nextOutputFileName];
             OutputLine[""];
             OutputLine[""];
             OutputLine[""]};
          RETURN[FALSE]};

	 
END.