(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: Host.m3 *) (* Last modified on Fri Jun 29 01:22:59 1990 by muller *) (* modified on Wed Feb 14 10:09:03 1990 by kalsow *) MODULE Host; IMPORT String, Rd, Wr, M3toC, Cstdlib, Cstdarg, FileStream, Stdio, Wr, Error; IMPORT Text, Filename, TextRd, Emit; CONST DefaultSearchPath = ".:/proj/ultrix/lib/m3"; VAR searchPath: Text.T; PROCEDURE OpenFile (name: Text.T): Rd.T = (* open file in the current directory *) VAR file: Text.T; BEGIN RETURN DoOpenFile (name, file, ".", FALSE); END OpenFile; PROCEDURE DoOpenFile (name: Text.T; VAR (*out*) filename: Text.T; path: Text.T; issueMsg: BOOLEAN := TRUE): Rd.T = BEGIN filename := Filename.SearchPath (path, name); IF (filename = NIL) THEN IF issueMsg THEN Error.Msg ("missing file"); Wr.PutText (errors, " no \"" & name & "\" on path \"" & path & "\"\n"); END; RETURN NIL; END; TRY RETURN FileStream.OpenRead (filename); EXCEPT Rd.Failure => IF issueMsg THEN Error.Msg ("unable to open file"); Wr.PutText (errors, " \"" & filename &"\": ??\n"); END; RETURN NIL; END; END DoOpenFile; PROCEDURE CloseFile (rd: Rd.T) = BEGIN TRY Rd.Close (rd) EXCEPT ELSE END; END CloseFile; PROCEDURE OpenInterface (name: String.T; VAR(*OUT*) filen: String.T): Rd.T = VAR file, fullname: Text.T; rd: Rd.T; BEGIN file := String.ToText (name); rd := DoOpenFile (file & ".i3", fullname, searchPath); IF (rd = NIL) THEN rd := TextRd.New ("INTERFACE " & file & "; END " & file & "."); END; IF (fullname # NIL) THEN filen := String.Add (fullname); Error.Info ("importing from \"" & fullname & "\""); ELSE filen := name; END; RETURN rd; END OpenInterface; PROCEDURE OpenWriter (name: Text.T): Wr.T = BEGIN IF (name = NIL) THEN Error.Msg ("missing output file"); RETURN Stdio.stdout; END; TRY RETURN FileStream.OpenWrite (name); EXCEPT Wr.Failure => Error.Msg ("unable to open output file"); Wr.PutText (errors, " \"" & name & "\": ??\n"); RETURN Stdio.stdout; END; END OpenWriter; <* EXTERNAL *> PROCEDURE exit (i: INTEGER); PROCEDURE Halt (e: INTEGER) = BEGIN TRY Wr.Close (errors); EXCEPT ELSE END; IF e = 0 THEN Emit.Op ("\003"); END; TRY Wr.Close (output); EXCEPT ELSE END; IF e > 0 THEN exit (e); END; END Halt; PROCEDURE Initialize () = BEGIN errors := Stdio.stderr; output := Stdio.stdout; source := NIL; verbose := FALSE; Clines := FALSE; asserts := TRUE; searchPath := NIL; errorDie := -1; standard := FALSE; warnings := 2; coverage := FALSE; inlines := FALSE; incrementalVersion := -1; ProcessOptions (); IF (source = NIL) THEN filename := String.Add (""); source := Stdio.stdin; END; IF (searchPath = NIL) THEN searchPath := DefaultSearchPath; END; END Initialize; PROCEDURE ProcessOptions () = VAR i: INTEGER; t: Text.T; BEGIN i := 1; WHILE (i < Cstdarg.argc) DO t := M3toC.StoT (Cstdarg.argv[i]); IF Text.Equal (Text.Sub (t, 0, 2), "-D") THEN t := Text.Sub (t, 2, LAST (INTEGER)); IF (searchPath = NIL) THEN searchPath := t; ELSE searchPath := searchPath & ":" & t; END; ELSIF (Text.Equal (t, "-v")) THEN verbose := TRUE; warnings := -1; ELSIF (Text.Equal (Text.Sub (t, 0, 2), "-V")) THEN incrementalVersion := GetInt (t, 2); ELSIF (Text.Equal (t, "-a")) THEN asserts := FALSE; ELSIF (Text.Equal (t, "-C")) THEN Clines := TRUE; (* don't generate Modula-3 line numbers *) ELSIF (Text.Equal (t, "-S")) THEN versionStamps := FALSE; (* don't generate version stamps *) ELSIF (Text.Equal (t, "-Std")) THEN standard := TRUE; (* ignore extensions *) ELSIF (Text.Equal (Text.Sub (t, 0, 2), "-P")) THEN toCompile := String.Add (Text.Sub (t, 2, 1000)); ELSIF (Text.Equal (t, "-w")) THEN warnings := 99; ELSIF (Text.Equal (Text.Sub (t, 0, 2), "-w")) THEN warnings := GetInt (t, 2); ELSIF (Text.Equal (t, "-Z")) THEN coverage := TRUE; (* generate line profiling *) ELSIF (Text.Equal (t, "-I")) THEN inlines := TRUE; (* expand inline procedures *) ELSIF (Text.Equal (Text.Sub (t, 0, 2), "-E")) THEN errorDie := GetInt (t, 2); ELSIF (Text.Equal (t, "-o")) THEN INC (i); t := M3toC.StoT (Cstdarg.argv[i]); output := OpenWriter (t); ELSIF (Text.GetChar (t, 0) = '-') THEN Wr.PutText (Stdio.stderr, "unknown option: " & t & "\n"); Halt ( -1); ELSIF (filename = NIL) THEN filename := String.Add (t); source := OpenFile (t); IF source = NIL THEN Wr.PutText (Stdio.stderr, "\"" & t & "\" does not exist.\n"); Halt (-1); END; ELSE Wr.PutText (Stdio.stderr, "multiple files specified: " & t & "\n"); Halt ( -1); END; INC (i); END; END ProcessOptions; PROCEDURE GetInt (t: Text.T; start: INTEGER): INTEGER = VAR c: CHAR; n: INTEGER := 0; BEGIN FOR j := start TO Text.Length (t)-1 DO c := Text.GetChar (t, j); IF (c < '0') OR ('9' < c) THEN RETURN n END; n := n * 10 + ORD (c) - ORD ('0'); END; RETURN n; END GetInt; BEGIN END Host.