-- GetOp.mesa -- Edited by Schroeder, March 3, 1981 10:05 AM. -- Edited by Brotz, October 16, 1980 5:41 PM. -- Edited by Levin, February 24, 1981 4:49 PM. DIRECTORY crD: FROM "CoreDefs", gsD: FROM "GlobalStorageDefs", intCommon: FROM "IntCommon", MailParse, mfD: FROM "MailFormatDefs", opD: FROM "OperationsDefs", ovD: FROM "OverviewDefs", ProcessDefs, StringDefs, vmD: FROM "VirtualMgrDefs"; GetOp: PROGRAM IMPORTS crD, gsD, intC:intCommon, mfD, opD, ProcessDefs, StringDefs, vmD EXPORTS opD SHARES opD = BEGIN OPEN StringDefs; fileAccessError: SIGNAL = CODE; -- Had error return trying to read or write a file GetMailFileOperation: PUBLIC PROCEDURE [mailFile: crD.UFilename] RETURNS [ovD.ErrorCode, vmD.TOCIndex] = BEGIN -- variables for GetMailFileOperation bufferPage: gsD.MemoryPagePtr _ NIL; bufferString: STRING; -- turns the BufferPage into a string nextBufferSlot, bytesInBuffer: CARDINAL; pageInBuffer: crD.PageNumber; pageNeeded: BOOLEAN _ TRUE; -- page needs to be read into buffer dummyBufferRecord: opD.BufferRecord _ opD.BufferRecord[b1: NIL, s1: 0, b2: NIL, s2: 0]; eofPage: crD.PageNumber; eofByte: CARDINAL; charIndex: CARDINAL; nextCharLimit: CARDINAL; errorCode: ovD.ErrorCode; tOCEntry1, tOCEntry2: vmD.TOCFixedPart; -- Buffers for TOC entries tb1: vmD.TOCFixedPartPtr = @tOCEntry1; tb2: vmD.TOCFixedPartPtr = @tOCEntry2; tOCFileName: crD.UFilename; firstUnSeenTOCIndex, lastTOCIndex: vmD.TOCIndex; tOCString: STRING _ [opD.maxTOCStringLength]; parseHandle: mfD.Handle _ NIL; parseStampLimit: CARDINAL = 24; fName: STRING _ [75]; i: CARDINAL; -- internal procedures for GetMailFileOperation PositionNextChar: PROCEDURE [page: crD.PageNumber, byte, limit: CARDINAL] = --sets buffer management variables so NextChar will produce char at specified position BEGIN page _ page + (byte / 512); byte _ byte MOD 512; pageNeeded _ pageNeeded OR page #pageInBuffer; pageInBuffer _ page; nextBufferSlot _ byte; nextCharLimit _ limit; charIndex _ 0; END; -- of PositionNextChar -- NextChar: PROCEDURE RETURNS [lastChar: CHARACTER] = BEGIN IF charIndex >= nextCharLimit THEN lastChar _ MailParse.endOfInput ELSE BEGIN -- normal case IF pageNeeded THEN BEGIN [errorCode, bytesInBuffer] _ crD.ReadPages[bufferPage, 512, pageInBuffer, intC.mailFileHandle]; -- if read is off the end of the file then 0 bytes will be returned IF errorCode # ovD.ok THEN SIGNAL fileAccessError; pageNeeded _ FALSE; END; lastChar _ bufferString[nextBufferSlot]; IF nextBufferSlot < 511 THEN nextBufferSlot _ nextBufferSlot + 1 ELSE -- about to return the last char in this page, so set to get new page next time {nextBufferSlot _ 0; pageInBuffer _ pageInBuffer + 1; pageNeeded _ TRUE}; END; charIndex _ charIndex + 1; END; -- of NextChar -- BackupChar: PROCEDURE = BEGIN charIndex _ charIndex - 1; IF nextBufferSlot = 0 THEN BEGIN nextBufferSlot _ 511; pageInBuffer _ pageInBuffer - 1; pageNeeded _ ~pageNeeded; END ELSE nextBufferSlot _ nextBufferSlot - 1; END; -- of BackupChar -- -- code of GetMailFileOperation BEGIN -- block for EXITS fName.length _ 0; AppendString[fName, mailFile]; mailFile _ fName; FOR i IN [0 .. fName.length) UNTIL fName[i] = '. DO ENDLOOP; IF fName[i] # '. THEN AppendString[fName, ".mail"L]; [errorCode, intC.mailFileHandle] _ crD.OpenFile[intC.user, mailFile, update]; IF errorCode # ovD.ok THEN GOTO simpleReturn; ProcessDefs.Yield[]; ProcessDefs.Yield[]; tOCString.length _ 0; AppendString[tOCString, mailFile]; AppendString[tOCString, "-dmsTOC"L]; tOCFileName _ tOCString; [errorCode, eofPage, eofByte] _ crD.UFileLength[intC.mailFileHandle]; IF errorCode # ovD.ok THEN GOTO errorReturn; IF eofPage = 0 AND eofByte = 0 THEN BEGIN [firstUnSeenTOCIndex, errorCode] _ vmD.VirtualizeTOC[intC.user, tOCFileName, intC.mailFileHandle, new]; IF errorCode = ovD.ok THEN GOTO simpleReturn ELSE GOTO errorReturn; END; bufferPage _ gsD.GetMemoryPages[1]; bufferString _ LOOPHOLE[bufferPage - 2, STRING]; [firstUnSeenTOCIndex, errorCode] _ vmD.VirtualizeTOC[intC.user, tOCFileName, intC.mailFileHandle, old]; IF errorCode # ovD.ok THEN GOTO errorReturn; ProcessDefs.Yield[]; ProcessDefs.Yield[]; lastTOCIndex _ vmD.GetFirstFreeTOCIndex[] - 1; IF lastTOCIndex = 0 THEN PositionNextChar[0, 0, parseStampLimit] -- no toc entries yet ELSE BEGIN -- TOC has some entries already vmD.GetTOCFixedPart[lastTOCIndex, tb1]; PositionNextChar[tb1.firstPage, tb1.firstByte, tb1.offsetToHeader]; IF mfD.ParseStamp[NextChar, tb2 ! fileAccessError => GOTO errorReturn] # ovD.ok OR tb2.textLength # tb1.textLength OR tb2.offsetToHeader # tb1.offsetToHeader THEN BEGIN -- last TOC entry is not reasonable vmD.CleanupTOC[delete]; [firstUnSeenTOCIndex, errorCode] _ vmD.VirtualizeTOC[intC.user, tOCFileName, intC.mailFileHandle, new]; IF errorCode # ovD.ok THEN GOTO errorReturn; PositionNextChar[0, 0, parseStampLimit]; END -- last TOC entry is not reasonable ELSE BEGIN -- TOC is reasonable IF vmD.GetFirstChangedTOCIndex[] <= lastTOCIndex THEN BEGIN -- TOC was not cleaned up last time, so do it. gsD.ReturnMemoryPages[1, bufferPage]; bufferPage _ NIL; errorCode _ opD.ReturnMailFileOperation[@dummyBufferRecord]; IF errorCode # ovD.ok THEN GOTO simpleReturn; [errorCode, firstUnSeenTOCIndex] _ GetMailFileOperation[mailFile]; GOTO simpleReturn; END -- TOC was not cleaned up last time, so do it. ELSE PositionNextChar [tb1.firstPage, tb1.firstByte+ tb1.offsetToHeader+ tb1.textLength, parseStampLimit]; END; -- TOC is reasonable END; -- TOC has some entries already parseHandle _ mfD.InitializeParseHeader[NextChar, BackupChar]; WHILE pageInBuffer < eofPage OR (pageInBuffer = eofPage AND nextBufferSlot < eofByte) DO ProcessDefs.Yield[]; ProcessDefs.Yield[]; tb1.firstPage _ pageInBuffer; tb1.firstByte _ nextBufferSlot; tb1.changed _ FALSE; IF mfD.ParseStamp[NextChar, tb1 ! fileAccessError => GOTO errorReturn] # ovD.ok THEN {errorCode _ ovD.notAMailFile; GOTO errorReturn}; IF ~tb1.deleted THEN BEGIN PositionNextChar[tb1.firstPage, tb1.firstByte+ tb1.offsetToHeader, tb1.textLength]; mfD.ParseHeaderForTOC[tOCString, parseHandle ! fileAccessError=>GOTO errorReturn]; IF firstUnSeenTOCIndex = 0 AND ~tb1.seen THEN firstUnSeenTOCIndex _ vmD.GetFirstFreeTOCIndex[]; errorCode _ vmD.ExtendTOC[tb1, tOCString]; IF errorCode # ovD.ok THEN GOTO simpleReturn; END; PositionNextChar[tb1.firstPage, tb1.firstByte+ tb1.offsetToHeader+ tb1.textLength, parseStampLimit]; ENDLOOP; IF pageInBuffer = eofPage AND nextBufferSlot = eofByte THEN GOTO simpleReturn; --last stamp pointed to first char beyond end of file -- last stamp pointed beyond the end of the file, so contract last stamp gsD.ReturnMemoryPages[1, bufferPage]; bufferPage _ NIL; tb1.textLength _ (eofPage - tb1.firstPage) * 512 + eofByte - tb1.firstByte - tb1.offsetToHeader; lastTOCIndex _ vmD.GetFirstFreeTOCIndex[] - 1; vmD.PutTOCFixedPart[lastTOCIndex, tb1]; errorCode _ opD.ReturnMailFileOperation[@dummyBufferRecord]; IF errorCode # ovD.ok THEN GOTO simpleReturn; [errorCode, firstUnSeenTOCIndex] _ opD.GetMailFileOperation[mailFile]; IF errorCode = ovD.ok THEN errorCode _ ovD.badMailFile; GOTO simpleReturn; EXITS simpleReturn => NULL; errorReturn => BEGIN IF eofByte # 0 OR eofPage # 0 THEN [] _ crD.CloseFile[intC.mailFileHandle] ELSE [] _ crD.DeleteFile[intC.mailFileHandle]; vmD.CleanupTOC[delete]; -- a nop if no toc exists yet intC.mailFileHandle _ NIL; END; END; -- of EXITS block IF parseHandle ~= NIL THEN mfD.FinalizeParseHeader[parseHandle]; IF bufferPage # NIL THEN gsD.ReturnMemoryPages[1, bufferPage]; ProcessDefs.Yield[]; ProcessDefs.Yield[]; RETURN[errorCode, firstUnSeenTOCIndex]; END; -- of GetMailFileOperation -- END. -- of GetOp --z20461(529)\f1