DIRECTORY PBasics USING [PartialComparison], Rope USING [ROPE, Substr]; PFSNames: CEDAR DEFINITIONS IMPORTS Rope ~ BEGIN ROPE: TYPE = Rope.ROPE; Comparison: TYPE = PBasics.PartialComparison; PATH: TYPE = REF PathObject; PathObject: TYPE = RECORD [REF PrivatePathObject]; PrivatePathObject: TYPE; Component: TYPE = RECORD [ name: RECORD [base: ROPE, start, len: NAT] _ [NIL, 0, 0], version: Version _ [none] ]; VersionKind: TYPE = {numeric, none, lowest, highest, next, all}; Version: TYPE = RECORD [ versionKind: VersionKind, version: CARDINAL _ 0 ]; EmptyPath: READONLY PATH; -- non-NIL PATH semantically equivalent to NIL NarrowPath: PROC [r: REF ANY] RETURNS [PATH]; -- because PathObject is opaque IsPath: PROC [r: REF ANY] RETURNS [BOOL]; -- because PathObject is opaque ConstructName: PROC [components: LIST OF Component, absolute, directory, reverse: BOOL _ FALSE, unparsed: REF _ NIL] RETURNS [name: PATH]; ExpandName: PROC [name: PATH, wDir: PATH _ NIL] RETURNS [PATH]; ComponentCount: PROC [name: PATH] RETURNS [count: NAT]; Compare: PROC [n1, n2: PATH, case: BOOL _ FALSE] RETURNS [Comparison]; Equal: PROC [n1, n2: PATH, case: BOOL _ FALSE] RETURNS [BOOL] ~ INLINE { RETURN[Compare[n1, n2, case]=equal] }; SubName: PROC [name: PATH, start: NAT _ 0, count: NAT _ NAT.LAST, absolute, directory: BOOL _ FALSE] RETURNS [PATH]; ShortName: PROC [name: PATH] RETURNS [shortName: Component]; Cat: PROC [n1, n2: PATH] RETURNS [PATH]; Fetch: PROC [name: PATH, index: NAT] RETURNS [Component]; ComponentRope: PROC [comp: Component] RETURNS [ROPE] ~ INLINE { RETURN [Rope.Substr[comp.name.base, comp.name.start, comp.name.len]]; }; IsAPrefix: PROC [prefix, name: PATH] RETURNS [isa: BOOL, suffix: PATH]; IsADirectory: PROC [name: PATH] RETURNS [BOOL]; EnsureDirectory: PROC [name: PATH] RETURNS [PATH]; IsAbsolute: PROC [name: PATH] RETURNS [BOOL]; EnsureAbsolute: PROC [name: PATH] RETURNS [PATH]; StripVersionNumber: PROC [name: PATH] RETURNS [PATH]; SetVersionNumber: PROC [name: PATH, version: Version] RETURNS [PATH]; ReplaceShortName: PROC [name: PATH, newShortName: Component] RETURNS [PATH]; ReplaceComponent: PROC [name: PATH, index: NAT, new: Component] RETURNS [PATH]; InASubdirectory: PROC [parent: PATH, name: PATH] RETURNS [BOOL]; FirstSubdirectory: PROC [parent: PATH, name: PATH] RETURNS [PATH]; Directory: PROC [name: PATH] RETURNS [PATH]; Parent: PROC [name: PATH] RETURNS [PATH]; ComponentProc: TYPE = PROC[comp: Component, ref: REF]; SeparatorProc: TYPE = PROC[separatorPresent: BOOL, ref: REF]; Map: PROC [name: PATH, componentProc: ComponentProc, separatorProc: SeparatorProc, ref: REF _ NIL]; NonNIL: PROC [p: PATH] RETURNS [PATH] ~ INLINE { RETURN[IF p=NIL THEN EmptyPath ELSE p]; }; CompareComponents: PROC [c1, c2: Component, case: BOOL _ FALSE] RETURNS [Comparison]; EqualComponents: PROC [c1, c2: Component, case: BOOL _ FALSE] RETURNS [BOOL] ~ INLINE { RETURN[CompareComponents[c1, c2, case]=equal]; }; CompareVersions: PROC [v1, v2: Version] RETURNS [Comparison]; EqualVersions: PROC [v1, v2: Version] RETURNS [BOOL] ~ INLINE { RETURN[CompareVersions[v1, v2]=equal]; }; GetUnparsingHint: PROC [p: PATH] RETURNS [REF]; SetUnparsingHint: PROC [p: PATH, r: REF] RETURNS [prev: REF]; END. 2PFSNames.mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Carl Hauser, June 8, 1989 5:17:24 pm PDT PFSNames provides the abstraction of file names used for designating files throughout PFS. Procedures in this interface operate purely on names: they make no inquiry as to the existence of any file. Furthermore, procedures in this interface assign very minimal semantics to names: numeric versions are interpreted (to provide sensible comparison operations), but, for example, there is no implication here that the first component of a name is always a server name (although elsewhere in PFS this may be true). Nor does PFSNames provide any type transfer procedures for going back and forth between names and human-sensible ROPE representations. These are left to parsing/unparsing procedures whose implementation will depend on the exact syntax chosen for the ROPE representations. meaningful only if versionKind=numeric; -- this is really a variant record, but doing it this way works better. Type Manipulation RETURN [NARROW[r, PATH]]; RETURN [ISTYPE[r, PATH]]; Constructing Paths See various name parsing interfaces for conversion to/from ROPEs. Start with PFSCanonicalNames. A convenient way to construct names without parsing. If reverse, the names are in the components list in reverse order--convenient when the list must be constructed by a left-to-right parse of a rope or stream. Operations on Paths If name is not absolute and wDir is absolute then prepends wDir to name. The number of components making up name. The result PATH takes its absolute and directory fields from the arguments (not from name). The last component of a PATH Ignores n1.directory, n2.absolute; NOT index IN [0..ComponentCount[name]) => BoundsFault. If `prefix' is a prefix of name, returns isa=TRUE and the rest of name in `suffix'. Otherwise, isa=FALSE and `suffix' is meaningless. name.directory returns name with TRUE substituted for name.directory; name.absolute returns name with TRUE substituted for name.absolute; returns name with [none[]] substituted for name.lastComp.version. returns name with version substituted for name.lastComp.version. returns name with newShortName substituted for name.lastComp In absolute names, returns name with new substituted for the position-th component. IsAPrefix[parent, name].isa AND ComponentCount[Directory[IsAPrefix[parent, name].suffix]]#0 If NOT InASubdirectory[parent, name] then returns NoWDir. Otherwise, returns the part of name up to and including the first subdirectory after the end of parent. Return the directory part of the name. If name is a directory, then returns the parent directory. If name is a file, then returns the containing directory. In either case, this means that Parent returns the directory which contains the object denoted by name. alternately calls separatorProc and componentProc (beginning and ending with separatorProc). separatorPresent is name.absolute for the first call, name.directory for the last and TRUE for all others. Rather than forever testing whether or not a path is NIL, it is better to convert NIL to an explicit empty path for some operations. Operations on Components Operations on Versions Unparsing Hint Name parsers and unparsers can store hints of their own choosing in a PATH to ease their job in unparsing the PATH (again). Κν˜šœ ™ Icode™