DIRECTORY BasicTime USING [GMT], Camelot USING [tidT], File USING [wordsPerPage], FileStream USING [StreamFromOpenFile], FS USING [FileType, Lock, OpenFile, tUnspecified], FSBackdoor USING [CreateProcsOpenFile, CreateFileProcs, FileProcs], IO USING [STREAM], PBasics USING [bytesPerWord, Move, Word], Rope USING [ROPE], YggBuffMan USING [ReadPages, WritePages, VMPageSet], YggDID USING [], YggFile USING [FileHandle, Info, SetByteSize, SetSize, WordsForPages], YggFileStream USING [], YggFileInternal USING [FileHandleRep], YggInternal USING [FileHandle]; YggFileStreamImpl: CEDAR PROGRAM IMPORTS FileStream, FSBackdoor, PBasics, YggBuffMan, YggFile EXPORTS YggFile, YggFileStream, YggInternal ~ BEGIN ROPE: TYPE ~ Rope.ROPE; FileProcs: REF FSBackdoor.FileProcs; FileHandle: TYPE = YggInternal.FileHandle; FileHandleRep: PUBLIC TYPE = YggFileInternal.FileHandleRep; FileDataRep: TYPE = RECORD [ openFile: YggFile.FileHandle, tid: Camelot.tidT ]; wordsPerPage: INT _ 1024; bytesPerPage: INT _ wordsPerPage * PBasics.bytesPerWord; unitsPerPage: INT _ wordsPerPage * UNITS[PBasics.Word]; fileBytesPerPage: INT _ File.wordsPerPage * BYTES[WORD]; filePagesPerMyPage: INT _ bytesPerPage/fileBytesPerPage; FileFromComponentFiles: PUBLIC PROC [componentFiles: LIST OF FileHandle, fileUse: ATOM] RETURNS [file: FileHandle _ NIL] ~ { FOR cf: LIST OF FileHandle _ componentFiles, cf.rest UNTIL cf = NIL DO IF cf.first.fileUse = fileUse THEN { RETURN[cf.first]; }; ENDLOOP; }; FileUseFromComponentFiles: PUBLIC PROC [componentFiles: LIST OF FileHandle] RETURNS [fileUses: LIST OF ATOM] ~ { FOR cf: LIST OF FileHandle _ componentFiles, cf.rest UNTIL cf = NIL DO fileUses _ CONS[cf.first.fileUse, fileUses]; ENDLOOP; }; StreamFromComponentFilesAndTid: PUBLIC PROC [componentFiles: LIST OF YggInternal.FileHandle, fileUse: ATOM, tid: Camelot.tidT, readOnly: BOOL] RETURNS [stream: IO.STREAM _ NIL] = { FOR cf: LIST OF FileHandle _ componentFiles, cf.rest UNTIL cf = NIL DO IF cf.first.fileUse = fileUse THEN { stream _ StreamFromOpenFileAndTid[cf.first, tid, readOnly]; }; ENDLOOP; }; StreamFromOpenFileAndTid: PUBLIC PROC [file: YggFile.FileHandle, tid: Camelot.tidT, readOnly: BOOL] RETURNS [stream: IO.STREAM _ NIL] = { fsOpenFile: FS.OpenFile; fileDataRep: REF FileDataRep; fileDataRep _ NEW[FileDataRep _ [openFile: file, tid: tid]]; fsOpenFile _ FSBackdoor.CreateProcsOpenFile[clientFile: fileDataRep, fileProcs: FileProcs]; stream _ FileStream.StreamFromOpenFile[fsOpenFile, IF readOnly THEN $read ELSE $write]; }; GetClass: PROC [clientFile: REF] RETURNS [ATOM] = { RETURN [$Yggdrasil]; }; SameFile: PROC [clientFile1, clientFile2: REF] RETURNS [BOOL] = { ERROR; }; GetName: PROC [clientFile: REF] RETURNS [fullFName, attachedTo: Rope.ROPE] = { WITH clientFile SELECT FROM fileData: REF FileDataRep => { RETURN [NIL, NIL]; }; ENDCASE => ERROR; }; GetInfo: PROC [clientFile: REF] RETURNS [keep: CARDINAL _ 1, pages, bytes: INT, created: BasicTime.GMT, lock: FS.Lock _ write, fileType: FS.FileType _ FS.tUnspecified] = { WITH clientFile SELECT FROM fileData: REF FileDataRep => { [size: pages, byteSize: bytes] _ YggFile.Info[file: fileData.openFile, tid: fileData.tid]; pages _ pages*filePagesPerMyPage; }; ENDCASE => ERROR; }; SetPageCount: PROC [clientFile: REF, pages: INT] = { WITH clientFile SELECT FROM fileData: REF FileDataRep => { YggFile.SetSize[file: fileData.openFile, size: (pages + filePagesPerMyPage - 1)/filePagesPerMyPage, tid: fileData.tid]; }; ENDCASE => ERROR; }; SetByteCountAndCreatedTime: PROC [clientFile: REF, bytes: INT, created: BasicTime.GMT] = { WITH clientFile SELECT FROM fileData: REF FileDataRep => { YggFile.SetByteSize[file: fileData.openFile, byteSize: bytes, tid: fileData.tid]; }; ENDCASE => ERROR; }; Read: UNSAFE PROC [clientFile: REF, from, nPages: INT, to: LONG POINTER] = { WITH clientFile SELECT FROM fileData: REF FileDataRep => { toPtr: LONG POINTER _ to; nPagesLeft: INT _ nPages; vMPageSet: YggBuffMan.VMPageSet; IF from MOD filePagesPerMyPage # 0 THEN ERROR; vMPageSet _ YggBuffMan.ReadPages[fileHandle: fileData.openFile, tid: fileData.tid, pageRun: [from/filePagesPerMyPage, (nPages + filePagesPerMyPage - 1) /filePagesPerMyPage]]; FOR vmp: YggBuffMan.VMPageSet _ vMPageSet, vmp.rest UNTIL vmp = NIL DO nowPages: INT _ MIN[vmp.first.pageRun.pages, nPagesLeft]; TRUSTED {PBasics.Move[dst: toPtr, src: vmp.first.buffer, nWords: YggFile.WordsForPages[nowPages]]; }; toPtr _ toPtr + YggFile.WordsForPages[nowPages]*UNITS[WORD]; nPagesLeft _ nPagesLeft _ nowPages; ENDLOOP; }; ENDCASE => ERROR; }; Write: PROC [clientFile: REF, to: INT, nPages: INT, from: LONG POINTER] = { WITH clientFile SELECT FROM fileData: REF FileDataRep => { IF to MOD filePagesPerMyPage # 0 THEN ERROR; YggBuffMan.WritePages[fileHandle: fileData.openFile, tid: fileData.tid, to: to/filePagesPerMyPage, nPages: (nPages + filePagesPerMyPage - 1) /filePagesPerMyPage, from: from]; }; ENDCASE => ERROR; }; Close: PROC [clientFile: REF] = { }; FileProcs _ FSBackdoor.CreateFileProcs[GetClass, SameFile, GetName, GetInfo, SetPageCount, SetByteCountAndCreatedTime, Read, Write, Close]; END. àYggFileStreamImpl.mesa Copyright Ó 1988 by Xerox Corporation. All rights reserved. Bob Hagmann January 20, 1989 3:40:53 pm PST YggFile procs Select a file Find the uses of all the files FS file procs Initialization Êþ˜code•Mark outsideHeaderšœ™Kšœ<™