SunNFSFSRemoteNameImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Demers, November 3, 1987 10:00:09 am PST
DIRECTORY
Ascii USING [Lower],
Convert USING [CardFromRope, Error, RopeFromCard],
FSBackdoor USING [highestVersion, lowestVersion, noVersion, Version],
FSName USING [VersionFromRope],
RefText USING [Append, AppendChar, AppendRope, New, ObtainScratch, ReleaseScratch, TrustTextRopeAsText],
Rope USING [Cat, FindBackward, Flatten, FromRefText, InlineFetch, InlineLength, IsPrefix, Length, ROPE, Substr],
SunNFSFSRemoteFile USING [caseFileNamePrefix, NameReaderObject, NameWriterObject, VersionInfo]
;
SunNFSFSRemoteNameImpl: CEDAR PROGRAM
IMPORTS Ascii, Convert, FSName, RefText, Rope, SunNFSFSRemoteFile
EXPORTS SunNFSFSRemoteFile
~ {
Copied Types
NameReader: TYPE ~ REF NameReaderObject;
NameReaderObject: TYPE ~ SunNFSFSRemoteFile.NameReaderObject;
NameWriter: TYPE ~ REF NameWriterObject;
NameWriterObject: TYPE ~ SunNFSFSRemoteFile.NameWriterObject;
ROPE: TYPE ~ Rope.ROPE;
Version: TYPE ~ FSBackdoor.Version;
VersionInfo: TYPE ~ SunNFSFSRemoteFile.VersionInfo;
Parameters
initialNameWriterBytes: CARDINAL ← 40;
versionPartLeftBracket: PUBLIC ROPE ← ".~";
versionPartLeftBracketLen: PUBLIC INT ← Rope.Length[versionPartLeftBracket];
versionPartRightBracket: PUBLIC CHAR ← '~;
versionPartRightBracketLen: PUBLIC INT ← 1;
versionPartBracketsLen: INT ← versionPartLeftBracketLen + versionPartRightBracketLen;
File Name Readers / Writers
Parsing
DecodeVersionFromNFSName: PUBLIC PROC [name: ROPE, checkCase: BOOL]
RETURNS [nameWithoutVersion: ROPE, version: Version, caseOK: BOOL] ~ {
nameLen, bangPos: INT;
versionNumber: CARD;
versionNumberRope: ROPE;
nameWithoutVersion ← name;
version ← FSBackdoor.noVersion;
caseOK ← FALSE;
nameLen Rope.InlineLength[name];
IF Rope.IsPrefix[SunNFSFSRemoteFile.caseFileNamePrefix, name, FALSE] THEN RETURN; -- accelerator
bangPos ← Rope.FindBackward[name, versionPartLeftBracket];
IF bangPos < 0 THEN bangPos ← nameLen;
nameWithoutVersion ← Rope.Flatten[name, 0, bangPos];
IF checkCase THEN {
caseOK ← TRUE;
FOR i: INT IN [0 .. bangPos) DO
c: CHAR ~ Rope.InlineFetch[nameWithoutVersion, i];
IF (c >= 'A) AND (c <= 'Z) THEN { caseOK ← FALSE; EXIT };
ENDLOOP;
};
IF bangPos > (nameLen-versionPartBracketsLen) THEN RETURN;
IF Rope.InlineFetch[name, nameLen-1] = versionPartRightBracket
THEN versionNumberRope ← Rope.Substr[name, bangPos+versionPartLeftBracketLen, nameLen-bangPos-versionPartBracketsLen]
ELSE versionNumberRope ← Rope.Substr[name, bangPos+versionPartLeftBracketLen];
versionNumber ← Convert.CardFromRope[versionNumberRope, 10
! Convert.Error => {versionNumber ← CARDINAL.LAST; CONTINUE }];
version ← SELECT versionNumber FROM
0 => FSBackdoor.noVersion,
>= CARDINAL.LAST => FSBackdoor.noVersion,
ENDCASE => [CARDINAL[versionNumber]];
};
EncodeVersionInNFSName: PUBLIC PROC [name: ROPE, version: Version]
RETURNS [nameWithVersion: ROPE] ~ {
versionNumber: CARDINAL ← version;
bangPos: INT ← Rope.FindBackward[name, ".~"];
IF bangPos >= 0 THEN name ← Rope.Substr[name, 0, bangPos];
nameWithVersion ← Rope.Cat[ name, ".~", Convert.RopeFromCard[versionNumber, 10, FALSE], "~" ];
};
Name Readers
ReadDirComponent: PUBLIC PROC [nR: NameReader, case: BOOL] RETURNS [component: ROPENIL] ~ {
t: REF READONLY TEXT ← nR.text;
tLen: CARDINAL ← t.length;
buf: REF TEXT ← RefText.ObtainScratch[tLen-nR.index];
iTo: CARDINAL ← 0;
i: CARDINAL ← nR.index;
DO
c: CHAR;
IF i >= tLen THEN GOTO NotFound;
SELECT (c ← t[i]) FROM
'!, '* => GOTO NotFound;
'> => GOTO Found;
ENDCASE => {
buf[iTo] ← IF case THEN c ELSE Ascii.Lower[c];
i ← i + 1;
iTo ← iTo + 1;
};
REPEAT
Found => {
buf.length ← iTo;
component ← Rope.FromRefText[buf];
nR.index ← i + 1;
};
NotFound => {
NULL;
};
ENDLOOP;
RefText.ReleaseScratch[buf];
};
ReadBaseComponent: PUBLIC PROC [nR: NameReader, case, stripVersion: BOOL]
RETURNS [base: ROPE, vI: VersionInfo, version: Version, isPattern: BOOLFALSE, patternHead: ROPENIL] ~ {
The base contains whatever version info was specified in the nR source, unless "stripVersion" is TRUE.
t: REF READONLY TEXT ← nR.text;
tLen: CARDINAL ← t.length;
buf: REF TEXT ← RefText.ObtainScratch[tLen-nR.index];
iTo: CARDINAL ← 0;
i: CARDINAL ← nR.index;
lenWithoutVersion: CARDINAL;
c: CHAR;
DO
IF i >= tLen THEN {
vI ← missing;
lenWithoutVersion ← iTo;
EXIT;
};
c ← t[i];
buf[iTo] ← IF case THEN c ELSE Ascii.Lower[c];
iTo ← iTo + 1;
i ← i + 1;
SELECT c FROM
'* => IF NOT isPattern THEN {
buf.length ← iTo-1;
patternHead ← Rope.FromRefText[buf];
isPattern ← TRUE;
};
'> => {
IF NOT isPattern THEN ERROR; -- my software bug ???
};
'! => {
vI ← bang;
lenWithoutVersion ← iTo - 1;
EXIT;
};
ENDCASE;
ENDLOOP;
buf.length ← iTo;
IF i >= tLen
THEN {
version ← FSBackdoor.noVersion;
}
ELSE {
SELECT (c ← t[i]) FROM
'* => {
vI ← bangStar;
version ← FSBackdoor.noVersion;
buf ← RefText.AppendChar[buf, '*];
};
'l, 'L => {
vI ← bangL;
version ← FSBackdoor.lowestVersion;
buf ← RefText.AppendChar[buf, 'l];
};
'h, 'H => {
vI ← bangH;
version ← FSBackdoor.highestVersion;
buf ← RefText.AppendChar[buf, 'h];
};
ENDCASE => {
vI ← bangNumber;
version ← FSName.VersionFromRope[Rope.FromRefText[t, i]];
buf ← RefText.Append[buf, t, i];
};
};
base ← IF stripVersion
THEN Rope.FromRefText[buf, 0, lenWithoutVersion]
ELSE Rope.FromRefText[buf];
nR.index ← tLen;
};
CreateNameReader: PUBLIC PROC [r: ROPE] RETURNS [nR: NameReader] ~ {
t: REF READONLY TEXT;
t ← RefText.TrustTextRopeAsText[Rope.Flatten[r]];
nR ← NEW[NameReaderObject ← [t, 0]];
ResetNameReader[nR, 0];
};
ResetNameReader: PUBLIC PROC [nR: NameReader, position: INTEGER] ~ {
t: REF READONLY TEXT ~ nR.text;
i: CARDINAL;
IF position >= 0
THEN {
SELECT TRUE FROM
(t.length = 0) OR (t[0] # '<) => i ← 0;
(t.length = 1) OR (t[1] # '>) => i ← 1;
ENDCASE => i ← 2;
THROUGH [1..position] DO
DO
c: CHAR;
IF i >= t.length THEN EXIT;
c ← t[i]; i ← i + 1;
IF c = '> THEN EXIT;
ENDLOOP;
ENDLOOP;
}
ELSE {
i ← nR.index;
THROUGH (position..0] DO
IF i > 0 THEN {
i ← i - 1;
WHILE (i > 0) AND (t[i-1] # '>) DO i ← i - 1 ENDLOOP;
};
ENDLOOP;
};
nR.index ← i;
};
Name Writers
CreateNameWriter: PUBLIC PROC RETURNS [nW: NameWriter] ~ {
nW ← NEW[NameWriterObject ← [RefText.New[initialNameWriterBytes]]];
};
WriteDirComponent: PUBLIC PROC [nW: NameWriter, component: ROPE] ~ {
IF nW.text.length > 0 THEN nW.text ← RefText.AppendChar[nW.text, '>];
nW.text ← RefText.AppendRope[nW.text, component];
};
WriteBaseComponent: PUBLIC PROC [nW: NameWriter, component: ROPE] ~ {
nW.text ← RefText.AppendChar[nW.text, '>];
nW.text ← RefText.AppendRope[nW.text, component];
};
WriteBase: PUBLIC PROC [nW: NameWriter, base: ROPE, v: FSBackdoor.Version] ~ {
nW.text ← RefText.AppendChar[nW.text, '>];
nW.text ← RefText.AppendRope[nW.text, FSName.BangVersionFile[base, v]];
};
RetractComponent: PUBLIC PROC [nW: NameWriter] ~ {
t: REF TEXT ~ nW.text;
IF t.length > 0 THEN {
i: CARDINAL ← t.length - 1;
WHILE (i > 0) AND (t[i] # '>) DO i ← i - 1 ENDLOOP;
t.length ← i;
};
};
RetractAndReturnComponent: PUBLIC PROC [nW: NameWriter] RETURNS [r: ROPE] ~ {
t: REF TEXT ~ nW.text;
i: CARDINAL ← t.length;
IF i = 0 THEN ERROR;
WHILE (i > 0) AND (t[i] # '>) DO i ← i - 1 ENDLOOP;
r ← Rope.FromRefText[t, i+1];
t.length ← i;
};
RopeFromNameWriter: PUBLIC PROC [nW: NameWriter] RETURNS [ROPE] ~ {
RETURN [Rope.FromRefText[nW.text]] };
}...