MODULE M3CUnit EXPORTS M3CUnit, M3AST_FE, M3CUnit_priv; (***************************************************************************) (* Copyright (C) Olivetti 1989 *) (* All Rights reserved *) (* *) (* Use and copy of this software and preparation of derivative works based *) (* upon this software are permitted to any person, provided this same *) (* copyright notice and the following Olivetti warranty disclaimer are *) (* included in any copy of the software or any modification thereof or *) (* derivative work therefrom made by any person. *) (* *) (* This software is made available AS IS and Olivetti disclaims all *) (* warranties with respect to this software, whether expressed or implied *) (* under any law, including all implied warranties of merchantibility and *) (* fitness for any purpose. In no event shall Olivetti be liable for any *) (* damages whatsoever resulting from loss of use, data or profits or *) (* otherwise arising out of or in connection with the use or performance *) (* of this software. *) (***************************************************************************) IMPORT IO, Fmt, Err, OSError, FileStamp, PathName, PathNameStream; IMPORT M3Extension, M3Files; IMPORT M3CUnit_priv, M3Conventions; IMPORT M3AST_AS; IMPORT M3AST_AS_F, M3AST_SM_F; TYPE ExtSet = M3Extension.TSet; Ext = M3Extension.T; PROCEDURE FindUnit( name: TEXT; unitType: Type; VAR (*inout*) uf: Form; VAR id: Uid) : IO.Stream RAISES {IO.Error} = VAR m3Exts: ExtSet; result: IO.Stream; t: M3Extension.T; CONST Tolerance = 15 * 1000000; (* allow stamps to be 15 seconds in the future to allow for clock skew between local machine clock and stamp on remote file *) BEGIN IF unitType = Type.Interface THEN IF uf # Form.Source THEN m3Exts := ExtSet{Ext.PInt} ELSE m3Exts := M3Extension.Ints; END; ELSE m3Exts := M3Extension.Mods END; IF M3Extension.Has(name, t) AND t # M3Extension.T.Null THEN result := PathNameStream.Open(name, IO.OpenMode.Read); ELSE (* strip to module name *) name := PathName.Name(name); result := OpenFromSet(name, m3Exts); END; IF (result = NIL) AND (uf # Form.Source) THEN IF unitType = Type.Interface THEN m3Exts := M3Extension.Ints; result := OpenFromSet(name, m3Exts); END; END; IF result # NIL THEN IF NOT (Ext.PInt IN m3Exts) THEN id := NEW(Uid, filename := IO.Name(result)); TRY id^.stamp := FileStamp.Get(id^.filename); IF id^.stamp = FileStamp.Bad THEN Err.Print(Fmt.F("timestamp for %s is bad", id.filename), Err.Severity.Warning); ELSIF FileStamp.IsFuture(id^.stamp, Tolerance) THEN Err.Print( Fmt.F("timestamp for %s is in the future", id.filename), Err.Severity.Warning); END; EXCEPT | OSError.E(t) => Err.Print(Fmt.F("problem reading timestamp for %s - %s", id.filename, OSError.ToText(t)), Err.Severity.Error); result := NIL; END; uf := Form.Source; ELSE id := NIL; uf := Form.Ast; END; END; (* if *) RETURN result; END FindUnit; PROCEDURE OpenFromSet( name: TEXT; exts: M3Extension.TSet) : IO.Stream RAISES {IO.Error}= VAR s: IO.Stream; BEGIN FOR ext := FIRST(M3Extension.T) TO LAST(M3Extension.T) DO IF ext IN exts THEN s := M3Files.Open(name, ext, IO.OpenMode.Read); IF s # NIL THEN RETURN s END; END; (* if *) END; (* for *) RETURN NIL; END OpenFromSet; PROCEDURE FindStandard( VAR uf: Form; VAR id: Uid ): IO.Stream RAISES {IO.Error} = BEGIN RETURN FindUnit(M3Conventions.Standard, Type.Interface, uf, id); END FindStandard; PROCEDURE TextName(id: Uid): TEXT RAISES {} = BEGIN RETURN id^.filename; END TextName; PROCEDURE TypeName(ut: Type): TEXT RAISES {} = BEGIN CASE ut OF | Type.Interface => RETURN "interface"; | Type.Module => RETURN "module"; | Type.Interface_gen_def => RETURN "generic interface" | Type.Interface_gen_ins => RETURN "instantiated interface" | Type.Module_gen_def => RETURN "generic module" | Type.Module_gen_ins => RETURN "instantiated module" (*ELSE crash *) END; END TypeName; EXCEPTION NullUNIT; PROCEDURE ToType(u: M3AST_AS.UNIT): Type RAISES {}= BEGIN TYPECASE u OF | NULL => RAISE NullUNIT; | M3AST_AS.Interface => RETURN Type.Interface; | M3AST_AS.Module => RETURN Type.Module; | M3AST_AS.Interface_gen_def => RETURN Type.Interface_gen_def; | M3AST_AS.Module_gen_def => RETURN Type.Module_gen_def; | M3AST_AS.Interface_gen_ins => RETURN Type.Interface_gen_ins; | M3AST_AS.Module_gen_ins => RETURN Type.Module_gen_ins; END; END ToType; PROCEDURE ToGenIns(cu: M3AST_AS.Compilation_Unit; VAR (*inout*) ut: Type): M3AST_AS.Compilation_Unit RAISES {}= BEGIN TYPECASE cu.as_root OF | M3AST_AS.UNIT_GEN_INS(unit_ins) => cu := unit_ins.sm_ins_comp_unit; IF cu # NIL THEN IF ISTYPE(cu.as_root, M3AST_AS.Interface) THEN ut := Type.Interface ELSE ut := Type.Module END; END; ELSE END; (* typecase *) RETURN cu END ToGenIns; PROCEDURE Equal(id1, id2: Uid): BOOLEAN RAISES {} = BEGIN RETURN FileStamp.Compare(id1^.stamp, id2^.stamp) = 0; END Equal; <*INLINE*> PROCEDURE InclState(VAR status: Status; state: State) RAISES {}= BEGIN status := status + Status{state}; END InclState; <*INLINE*> PROCEDURE ExclState(VAR status: Status; state: State) RAISES {}= BEGIN status := status - Status{state}; END ExclState; BEGIN END M3CUnit.