INTERFACE M3Path; (***************************************************************************) (* 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. *) (***************************************************************************) (* Copyright (C) 1990, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) IMPORT SList, IO; IMPORT M3Extension, M3FindFile; CONST FileName = "m3path"; (* default name for path file *) CurrentDir = ""; (* denotation for current directory *) EXCEPTION BadDirName(TEXT); TYPE Elem <: ElemPublic; ElemPublic = SList.TextElem OBJECT unexpanded: TEXT; readOnly := FALSE; METHODS copy(): Elem; END; (* Read returns an SList.T of these. "Elem.text" is the directory name after any environment variables have been expanded. "Elem".unexpanded is the unexpanded form. "copy" returns a fresh copy. *) PROCEDURE Read( dir := ""; name := FileName; doTransitiveClosure := TRUE) : SList.T RAISES {IO.Error, BadDirName}; (* Reads the named m3path file in the named directory. If 'dir' is the null text 'name' is used as the complete name of the file. An m3path file has a system dependent format but always contains a list of directory names. This routine returns these names as a list of texts. The names are NOT transformed to be relative to the current directory e.g. if one name on the list was "foo" it means subdirectory "foo" in directory 'dir' not "foo" in the current directory. A directory may be indicated as read-only, in which case the 'readOnly' field will be TRUE. This is intended as an optimisation, to avoid repeated scanning of zillions of directories. If the named m3path file does not exist (or is inaccessible so that it is impossible to determine if it exists or not) the result will be NIL. Read will raise 'IO.Error' if a stream error occurs while opening and processing the m3path file. Read will raise 'BadDirName' if it finds a directory name which is obviously incorrect i.e. uses characters not allowed by the filing system. It does not check if the names it finds actually correspond to existing directories. If 'doTransitiveClosure' then the list returned is the transitive closure of the directories on the m3path. Duplicates are removed, the list is constructed breadth first. The elements of the SList returned are subtypes of SList.TextElem. *) PROCEDURE EnsureCurrentFirst() RAISES {}; (* All calls to 'Read' (or 'Find') will return a path which has the current directory first on the list. *) TYPE Finder <: FinderPublic; FinderPublic = M3FindFile.T OBJECT METHODS findDir(name: TEXT; ext: M3Extension.T): Elem RAISES {M3FindFile.Failed}; (* If the file denoted by "name" and "ext" can be found, return its directory as an "Elem". *) END; PROCEDURE Find( exts: M3Extension.TSet; dir := ""; name := FileName; doTransitiveClosure := TRUE; forceRead := FALSE) : Finder RAISES {IO.Error, BadDirName}; (* Returns a finder object for the given directory, path-file and set of extensions. Repeat calls may return the same finder object, unless 'forceRead := TRUE', in which case a new finder is guaranteed. If new, uses 'Read' to read the named path file in the named directory. Then builds a file finder object whose 'find' method will look for the file corresponding to a name and extension in each of the directories listed in the path file. The search is ordered so if there are two file names in different directories which match a given name and extension the file name earliest on the directory list will be returned. 'exts' gives the extensions for which the returned finder object will be valid. The effect of altering the directories given in the path list while the find object is in use is undefined (e.g. the implementation of 'Find' may build a cache which will become out of date). Use 'forceRead := TRUE' to be sure you get the current truth. If as the result of a 'forceRead=TRUE' call, the directories are re-read then those marked as read-only are NOT reread. If the original call to 'Read' fails the exceptions are passed through by 'Find'. *) PROCEDURE FinderDirs(f: Finder): SList.T RAISES {}; (* This call returns the list of directories that were returned by the implicit call of 'Read' when 'f' was created. *) PROCEDURE Same(e1, e2: Elem): BOOLEAN; (* Returns TRUE iff "e1" and "e2" represent the same directory. *) PROCEDURE ElemFrom(dir: TEXT): Elem RAISES {}; (* Return an "Elem" object for "dir" *) PROCEDURE SetReadOnly(dir: Elem; ro: BOOLEAN := TRUE) RAISES {}; (* Set the "readOnly" status of "dir" to "ro". This sets "dir.readOnly := ro", but has no other effect until a new call of "Read". *) (* ITERATOR *) TYPE Iter <: REFANY; PROCEDURE NewIter(f: Finder): Iter RAISES {}; (* If the implementation caches files in a finder this call will return an iterator on the cache. Otherwise, it will return NIL. *) PROCEDURE Next( iter: Iter; VAR (*out*) unitName: TEXT; VAR (*out*) ext: M3Extension.T; VAR (*out*) dir: Elem) : BOOLEAN RAISES {}; (* Return FALSE if iteration is exhausted, else the unit name plus extension and directory of the next member of the finder cache. Returning the result in this form makes extension filtering, directory- specific operations easier. However, the full pathname can be had by the call: PathName.Full(dir.text, M3Extension.Extend(unitName, ext)) *) PROCEDURE SetProperty( f: Finder; unitName: TEXT; ext: M3Extension.T; value: REFANY) RAISES {}; (* associate 'value' with file defined by triple "unitName,ext,dir" *) PROCEDURE GetProperty( f: Finder; unitName: TEXT; ext: M3Extension.T) : REFANY RAISES {BadDirName}; (* retrieve 'value' with file defined by triple "unitName,ext,dir" NIL is returned if no value associated. *) (* DEFAULT SEARCH PATH *) PROCEDURE AddDefault(t: TEXT; readOnly := TRUE) RAISES {}; (* Add the directory 't' (prepended) to the default search path. The default search path is added to the end of the search path built up by 'Read' or 'AddExplicit'. A call with "t=NIL" resets the path to empty. *) (* EXPLICIT SEARCH PATH *) PROCEDURE AddExplicit(t: TEXT; readOnly := TRUE) RAISES {}; (* This call is intended to support the "-Dpath" notion beloved of the DEC SRC compiler. Any call to this disables the reading of 'm3path' files completely, replacing it with the path built up by calls to this procedure. If 't' is NIL, the search path is reset to empty, otherwise the directories are prepended to the existing path. All calls the above procedures that normally read 'm3path' files, e.g 'Read', will use this path instead. If 'readOnly=TRUE', then this directory is marked as read-only - see Find for what that means. The initial path is empty. A call of 'EnsureCurrentFirst' is effective in conjunction with this procedure. *) PROCEDURE ReEnableM3Path(); (* A call to this procedure re-enables the reading of 'm3path' files, and resets any explicit search path to empty. *) END M3Path.