DIRECTORY Ascii USING [DEL, NUL], Basics USING [ByteBlt, charsPerWord, RawBytes, UnsafeBlock], IO USING [STREAM], Rope USING [FromChar, Length, NewText, ROPE, Text, UnsafeMoveChars], YggDID USING [], YggFile USING [FileHandle], YggFileStream USING [OpenFileInDirectory, OpenStreamInDirectory], YggInline USING [BytesForWords, WordsForBytes]; YggDIDImpl: CEDAR PROGRAM IMPORTS Rope, YggFileStream, YggInline EXPORTS YggDID, YggFile SHARES Rope -- for messing with Rope.TextRep ~ BEGIN ROPE: TYPE ~ Rope.ROPE; DID: PUBLIC TYPE ~ REF DIDRep; DIDRep: PUBLIC TYPE ~ ROPE; FirstDID: PUBLIC DID ; LastDID: PUBLIC DID ; AllNulls: PACKED ARRAY [0..Basics.charsPerWord) OF CHAR _ ALL[0C]; StreamsForDID: PUBLIC PROC [did: DID] RETURNS [contents, attributes, links: IO.STREAM _ NIL] ~ { contents _ YggFileStream.OpenStreamInDirectory[did, "$contents"]; attributes _ YggFileStream.OpenStreamInDirectory[did, "$attributes"]; links _ YggFileStream.OpenStreamInDirectory[did, "$links"]; }; FilesForDID: PUBLIC PROC [did: DID] RETURNS [contents, attributes, links: YggFile.FileHandle _ NIL] ~ { contents _ YggFileStream.OpenFileInDirectory[did, "$contents"]; attributes _ YggFileStream.OpenFileInDirectory[did, "$attributes"]; links _ YggFileStream.OpenFileInDirectory[did, "$links"]; }; SizeForDID: PUBLIC PROC [did: DID] RETURNS [bytes: INT] = { ddd: DIDRep; ddd _ did^; bytes _ YggInline.BytesForWords[YggInline.WordsForBytes[Rope.Length[did^]]]; }; StabilizeDID: PUBLIC PROC [did: DID, buffer: LONG POINTER] = { size: INT; nBytes: INT; nullsToMove: INT; size _ Rope.Length[did^]; TRUSTED {nBytes _ Rope.UnsafeMoveChars[block: [buffer, 0, size], rope: did^, start: 0];}; IF nBytes # size THEN ERROR; nullsToMove _ YggInline.BytesForWords[YggInline.WordsForBytes[size+1]] - size; IF nullsToMove <= 0 THEN ERROR; TRUSTED {nBytes _ Basics.ByteBlt[ from: [blockPointer: @AllNulls, startIndex: 0, stopIndexPlusOne: nullsToMove], to: [blockPointer: buffer, startIndex: size, stopIndexPlusOne: size+nullsToMove]]; }; IF nBytes # nullsToMove THEN ERROR; }; VolatilizeDID: PUBLIC PROC [buffer: LONG POINTER] RETURNS [did: DID] = { charBuffer: LONG POINTER TO ARRAY [0..0] OF CHAR; scratch: Rope.Text; scratchRope: ROPE; lenKey: INT; charBuffer _ LOOPHOLE[buffer]; FOR lenKey IN [ 0 .. NAT15.LAST ) DO TRUSTED {IF charBuffer[lenKey] = Ascii.NUL THEN EXIT;}; ENDLOOP; scratch _ Rope.NewText[lenKey]; FOR charNo: INT IN [ 0 .. lenKey ) DO TRUSTED {scratch[charNo] _ charBuffer[charNo];}; ENDLOOP; scratch.length _ lenKey; did _ NEW[DIDRep]; scratchRope _ scratch; did^ _ scratchRope; }; FirstDID _ NEW[DIDRep]; FirstDID^ _ ""; LastDID _ NEW[DIDRep]; LastDID^ _ Rope.FromChar[Ascii.DEL]; END. ΨYggDIDImpl.mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Bob Hagmann May 9, 1988 4:29:30 pm PDT Handle all operations on DID's. For Phase 0, the DIDRep is just a string that names a directory (without the trailing /). Exported procedures Get streams for the DID. Any or all of these objects may be NIL. For objects with few links, the links are stored in the attributes. For objects with small contents, the contents are stored in the attributes. If there are no attributes, there is no file for them. Get the file objects for the DID. Any or all of these objects may be NIL. For objects with few links, the links are stored in the attributes. For objects with small contents, the contents are stored in the attributes. If there are no attributes, there is no file for them. Return the size of the did. The size in in bytes rounded up to the next word. Take a DID and write it to a buffer. Take a buffer and construct a DID. Initialization Κ?˜code•Mark outsideHeaderšœ™Kšœ<™Kšœœ™$Kšœœ˜ Kšœœ˜ Kšœ œ˜Kšœ˜KšœR˜YKšœœœ˜KšœN˜NKšœœœ˜šœ˜!KšœO˜OKšœR˜RK˜—Kšœœœ˜#K˜K™—š  œœœ œœœœ˜HKšœœ™"Kš œ œœœœœœ˜1Jšœ˜Jšœ˜Jšœœ˜ Kšœ œ ˜š œœœœ˜$Icode2š œœœœœ˜7Mšœ˜—Kšœ˜šœ œœ˜%Mšœ)˜0Mšœ˜—Kšœ˜Kšœœ ˜Kšœ˜Kšœ˜K˜K™K™——™K˜K˜K˜Kšœœ˜$—K˜Kšœ˜—…— v