(****************************************
*                                       *
*     MODULA-2 Multi-Pass Compiler      *
*     ****************************      *
*                                       *
*         PDP11 Implementation          *
*                                       *
*                                       *
*     MCPublic:                         *
*                                       * 
*     public part of the common base    *
*     of the MC compiler               *
*                                       * 
*                                       *
*     Leo Geissmann                     *
*     Institut fuer Informatik          *
*     ETH-Zuerich                       *
*     CH-8092 Zuerich                   *
*                                       *
*                                       *
*     VAX native version                *
*                                       *
****************************************)

IMPLEMENTATION MODULE MCPublic;

IMPORT Storage (* for initialisation of storage procedures *),
       NewStreams (* for initialisation of module streams *);

  
FROM M2Files IMPORT CreateInput, CreateOutput, Extension;
FROM Streams IMPORT Stream, ErrorCode;
FROM WriteStrings IMPORT  WriteString, WriteLn;
FROM UnixArgs IMPORT argCount,GetArg;
FROM SYSTEM IMPORT UNIXCALL;
FROM UnixCalls IMPORT exit;
FROM M2Init IMPORT Init, Modulename;
FROM M2Pass1 IMPORT Pass1;
FROM M2Pass2 IMPORT Pass2;
FROM M2Pass3 IMPORT Pass3;
FROM M2Pass4 IMPORT Pass4;
FROM M2Listing IMPORT Listing;
FROM M2SymFile IMPORT SymFile;
IMPORT FileStream, Strings;    (* just for MakeHideFile *)
  

  TYPE Passes = (init,pass1,pass2,pass3,pass4,lister,symfile,terminate);

  VAR passindicator: Passes;
      argcnt : CARDINAL;
      message : ARRAY [0..9] OF CHAR;
      ok : BOOLEAN;
      tpname : FileName;
      reply,pos: INTEGER;
      loadfile : Passes;

PROCEDURE MakeHideFile(VAR fdesc : CARDINAL; ext: Extension);
VAR
   void: INTEGER;
   s: Stream;
   filename: FileName; dot: ARRAY [0..1] OF CHAR;
BEGIN
  s := CreateOutput(Modulename, ext);
  IF s^.status # Success THEN
    IF (Strings.EqualCC(ext, "lst")) OR (Strings.EqualCC(ext, "mcd")) THEN
    (*  these are not hidden, although they ought to be *)
        Strings.CopyCC(Modulename, filename);
        dot[0] := '.'; dot[1] := 0C;
        Strings.ConcatCC(dot, filename, filename);
        Strings.ConcatCC(ext, filename, filename);
        s := FileStream.CreateOutput(filename);
    END (* if *);
    IF s^.status # Success THEN
        WriteString('Could not create file with extension: ');
        WriteString(ext); WriteLn;
        void := UNIXCALL(exit, 1);
    END (* if *);
  END;
  fdesc := CARDINAL(s);
END MakeHideFile;


  PROCEDURE Compilation;
  BEGIN

    IF listings IN compstat THEN MakeHideFile(lstFile,"lst") END;
    passindicator := pass1;     
    LOOP
      loadfile := passindicator;
      CASE passindicator OF
        pass1:
	  message := "p1";

       |pass2:
          IF symerrs IN compstat THEN (* stop compilation *)
            WriteString(" ---- symbolfiles missing");
            WriteLn;
            INCL(compstat,globerrs); 
            EXIT 
          ELSE
	    message := "p2";
            IF NOT (defs IN compstat) THEN
                MakeHideFile(refFile,'ref');
            END;
          END;

       |pass3:
          IF defs IN compstat THEN
            IF globerrs IN compstat THEN (* error listing *)
		message := "Lister";
                loadfile := lister; 
                passindicator := terminate;
            ELSE (* symbol file generation *)
		MakeHideFile(symFile,"sym");
		message := "Symfile";
                loadfile := symfile; 
            END;
          ELSE
	    message := "p3";
          END;

       |pass4:
          IF (globerrs IN compstat) THEN (* error listing *)
	      message := "Lister";
              loadfile :=lister; 
              passindicator := terminate;
          ELSIF (defs IN compstat) THEN
	    IF (listings IN compstat) THEN
	      message := "Lister";
              loadfile :=lister; 
              passindicator := terminate;
	    ELSE EXIT;
  	    END;
	  ELSE
	    message := "p4";
	    MakeHideFile(objFile, 'mcd');
          END;

       | lister:
	  IF listings IN compstat THEN
		INCL(compstat, finis);
		message := "Lister";
		loadfile := lister;
		passindicator := terminate;
	  ELSE EXIT;
	  END;

      END; (* CASE *)
(*      WriteString(message); WriteLn; *)
      Call(loadfile);
        (* error handling *) 
        IF passerrs IN compstat THEN 
          INCL(compstat,globerrs); 
        END; 
        IF passindicator = terminate THEN EXIT END;
        EXCL(compstat,passerrs); 
        INC(passindicator); 
    END; (* LOOP *)  

    (* termination *)   
(*    EndStream(STREAM(il1File));
    EndStream(STREAM(il2File));
    IF modFile # 0 THEN EndStream(STREAM(modFile)); END;
    IF listings IN compstat THEN EndStream(STREAM(lstFile)) END;
    IF objFile # 0 THEN EndStream(STREAM(objFile)); END;
    IF refFile # 0 THEN EndStream(STREAM(refFile)); END;
    IF (defs IN compstat) AND (symFile # 0) THEN
      EndStream(STREAM(symFile));
    END;
*)
  END Compilation;

PROCEDURE Call(p: Passes);
BEGIN
    CASE p OF
        init:Init;
    |   pass1:Pass1;
    |   pass2:Pass2;
    |   pass3:Pass3;
    |   pass4:Pass4;
    |   lister:Listing;
    |   symfile:SymFile;
    END;
END Call;


VAR void :INTEGER;

PROCEDURE Compile;
BEGIN 
  objFile := 0; modFile := 0; refFile := 0;
  comptime[0]:=0;comptime[1]:=0;comptime[2]:=0;
  compstat := Statset{};
  ok := TRUE;
  IF argCount < 2 THEN 
    WriteString('m2m [flags] file1 file2 ..'); WriteLn;
  ELSE
  argcnt := 1;
  WHILE argcnt < argCount DO
     EXCL(compstat,compiles); EXCL(compstat, defs);
     GetArg(argcnt,tpname);
     IF tpname[0]# '-' THEN
      filenam:=tpname;
      Call(init);
      sourcefilename := filenam;
      IF (compiles IN compstat) THEN Compilation;
      ELSE INCL(compstat, globerrs); END;
     END;
     INC(argcnt);
  END; (* WHILE  *)
  END;

(*  Return Status of 1 if compilation failed *)

    IF globerrs IN compstat THEN
  	void := UNIXCALL(exit, 1);
    END;
END Compile;

END MCPublic.
