<> <> <> 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 ~ { <> 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; <> initialNameWriterBytes: CARDINAL _ 40; versionPartLeftBracket: PUBLIC ROPE _ ".~"; versionPartLeftBracketLen: PUBLIC INT _ Rope.Length[versionPartLeftBracket]; versionPartRightBracket: PUBLIC CHAR _ '~; versionPartRightBracketLen: PUBLIC INT _ 1; versionPartBracketsLen: INT _ versionPartLeftBracketLen + versionPartRightBracketLen; <> <> 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], "~" ]; }; <> ReadDirComponent: PUBLIC PROC [nR: NameReader, case: BOOL] RETURNS [component: ROPE _ NIL] ~ { 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: BOOL _ FALSE, patternHead: ROPE _ NIL] ~ { <> 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; }; <> 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]; }; <> <];>> <> <<};>> <<>> 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]] }; }...