PFSNames.mesa
Copyright Ó 1988, 1991 by Xerox Corporation. All rights reserved.
Carl Hauser, June 8, 1989 5:17:24 pm PDT
Willie-s, August 20, 1991 12:18 pm PDT
DIRECTORY
Basics USING [PartialComparison],
Rope USING [ROPE, Substr];
PFSNames: CEDAR DEFINITIONS
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.
IMPORTS Rope
~ BEGIN
ROPE: TYPE = Rope.ROPE;
Comparison: TYPE = Basics.PartialComparison;
PATH: TYPE = REF PathObject;
PathObject: TYPE = RECORD [REF PrivatePathObject];
PrivatePathObject: TYPE;
ComponentNamePart: TYPE = RECORD [base: ROPE, start, len: NAT];
0 <= start <= start+len <= base.length expected but not enforced; clients are to consider ComponentNamePart's as immutable.
Component: TYPE = RECORD [
name: ComponentNamePart ¬ [NIL, 0, 0],
version: Version ¬ [none]
];
VersionKind: TYPE = {numeric, none, lowest, highest, next, all};
Version: TYPE = RECORD [
versionKind: VersionKind,
version: CARDINAL ¬ 0
meaningful only if versionKind=numeric; -- this is really a variant record, but doing it this way works better.
];
EmptyPath: READONLY PATH; -- non-NIL PATH semantically equivalent to NIL
Type Manipulation
NarrowPath: PROC [r: REF ANY] RETURNS [PATH]; -- because PathObject is opaque
RETURN [NARROW[r, PATH]];
IsPath: PROC [r: REF ANY] RETURNS [BOOL]; -- because PathObject is opaque
RETURN [ISTYPE[r, PATH]];
Constructing Paths
See various name parsing interfaces for conversion to/from ROPEs. Start with PFSCanonicalNames.
ConstructName: PROC [components: LIST OF Component, absolute, directory, reverse: BOOL ¬ FALSE, unparsed: REF ¬ NIL] RETURNS [name: PATH];
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
ExpandName: PROC [name: PATH, wDir: PATH ¬ NIL] RETURNS [PATH];
If name is not absolute and wDir is absolute then prepends wDir to name.
ComponentCount: PROC [name: PATH] RETURNS [count: NAT];
The number of components making up name.
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];
The result PATH takes its absolute and directory fields from the arguments (not from name).
ShortName: PROC [name: PATH] RETURNS [shortName: Component];
The last component of a PATH
ShortNameRope: PROC [name: PATH] RETURNS [shortName: ROPE];
The last component of a PATH as a ROPE (for convenience)
Cat: PROC [n1, n2: PATH] RETURNS [PATH];
Ignores n1.directory, n2.absolute;
Fetch: PROC [name: PATH, index: NAT] RETURNS [Component];
NOT index IN [0..ComponentCount[name]) => BoundsFault.
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];
If `prefix' is a prefix of name, returns isa=TRUE and the rest of name in `suffix'. Otherwise, isa=FALSE and `suffix' is meaningless.
IsADirectory: PROC [name: PATH] RETURNS [BOOL];
name.directory
EnsureDirectory: PROC [name: PATH] RETURNS [PATH];
returns name with TRUE substituted for name.directory;
IsAbsolute: PROC [name: PATH] RETURNS [BOOL];
name.absolute
EnsureAbsolute: PROC [name: PATH] RETURNS [PATH];
returns name with TRUE substituted for name.absolute;
StripVersionNumber: PROC [name: PATH] RETURNS [PATH];
returns name with [none[]] substituted for name.lastComp.version.
SetVersionNumber: PROC [name: PATH, version: Version] RETURNS [PATH];
returns name with version substituted for name.lastComp.version.
ReplaceShortName: PROC [name: PATH, newShortName: Component] RETURNS [PATH];
returns name with newShortName substituted for name.lastComp
ReplaceComponent: PROC [name: PATH, index: NAT, new: Component] RETURNS [PATH];
In absolute names, returns name with new substituted for the position-th component.
InASubdirectory: PROC [parent: PATH, name: PATH] RETURNS [BOOL];
IsAPrefix[parent, name].isa AND ComponentCount[Directory[IsAPrefix[parent, name].suffix]]#0
FirstSubdirectory: PROC [parent: PATH, name: PATH] RETURNS [PATH];
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.
Directory: PROC [name: PATH] RETURNS [PATH];
Return the directory part of the name.
Parent: PROC [name: PATH] RETURNS [PATH];
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.
ConstructComponent: PROC [name: ComponentNamePart, version: Version ¬ [none]]
RETURNS [Component];
VersionToRope: PROC [Version] RETURNS [ROPE];
Replace: PROC [base: PATH, start: INT ¬ 0, len: NAT ¬ NAT.LAST, with: 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];
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.
NonNIL: PROC [p: PATH] RETURNS [PATH] ~ INLINE {
RETURN[IF p=NIL THEN EmptyPath ELSE p];
};
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
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];
};
Operations on Versions
CompareVersions: PROC [v1, v2: Version] RETURNS [Comparison];
EqualVersions: PROC [v1, v2: Version] RETURNS [BOOL] ~ INLINE {
RETURN[CompareVersions[v1, v2]=equal];
};
Unparsing Hint
GetUnparsingHint: PROC [p: PATH] RETURNS [REF];
Name parsers and unparsers can store hints of their own choosing in a PATH to ease their job in unparsing the PATH (again).
SetUnparsingHint: PROC [p: PATH, r: REF] RETURNS [prev: REF];
END.