DIRECTORY Environment, Inline, PDInterpBasic, PDFileFormat, PDInterpBitmap, PDInterpReader, Space, Mopcodes, UnsafeStorage, PDInterpInput; PDInterpReaderImpl: PROGRAM IMPORTS Inline, PDInterpBitmap, Space, UnsafeStorage, PDInterpInput EXPORTS PDInterpReader ~ BEGIN OPEN PDInterpReader; bitsPerWord: NAT ~ Environment.bitsPerWord; wordsPerPage: NAT ~ Environment.wordsPerPage; scratchWords: INT _ 32000; bufferSize: NAT = 256; ColorTileFromLoad: PUBLIC PROC [handle: Handle, colorTileLoadAddress: INT, scratchPointer: LONG POINTER, scratchWords: INT] RETURNS [PDInterpBitmap.Tile] ~ { private: Private ~ handle.private; tile: LONG POINTER TO PDFileFormat.Tile ~ private.loadPointer + colorTileLoadAddress; words: INT ~ Inline.LongMult[tile.sSize, (tile.fSize+(bitsPerWord-1))/bitsPerWord]; bitmap: PDInterpBitmap.BitmapDesc_ PDInterpBitmap.Reshape[ tile + SIZE[PDFileFormat.Tile], words, [tile.sMin, tile.fMin, tile.sSize, tile.fSize] ]; RETURN [PDInterpBitmap.CreateTile[ rectangle: [tile.sMin, tile.fMin, tile.sSize, tile.fSize], phase: tile.phase, rasterPointer: tile + SIZE[PDFileFormat.Tile], scratchPointer: scratchPointer, scratchWords: scratchWords ]]; }; BlockTransfer: PROC [source: LONG POINTER, count: CARDINAL, dest: LONG POINTER] ~ MACHINE CODE {Mopcodes.zBLTL}; LongBlockTransfer: PROC [source: LONG POINTER, count: INT, dest: LONG POINTER] ~ { WHILE count > LAST[CARDINAL] DO BlockTransfer[source, LAST[CARDINAL], dest]; source _ source + LAST[CARDINAL]; dest _ dest + LAST[CARDINAL]; count _ count - LAST[CARDINAL]; ENDLOOP; BlockTransfer[source, count, dest]; }; Private: TYPE ~ LONG POINTER TO PrivateRep; PrivateRep: PUBLIC TYPE ~ RECORD [ loadSpace: Space.Handle _ Space.nullHandle, loadPointer: LONG POINTER _ NIL, loadWordsAllocated: INT _ 0, bufferOriginPointer: LONG POINTER _ NIL, bufferWordsAllocated: INT _ 0, bufferWordPointer: LONG POINTER _ NIL, bufferWordCount: INT _ 0 ]; zone: UNCOUNTED ZONE = UnsafeStorage.GetSystemUZone[]; Words: TYPE ~ RECORD [ SEQUENCE COMPUTED CARDINAL OF CARDINAL ]; Open: PUBLIC PROC [input: PDInterpInput.Handle] RETURNS [handle: Handle] ~ { private: Private _ zone.NEW[PrivateRep]; handle _ zone.NEW[Rep _ [ herald: [0,0,invalid,0,0,0,0,0,0,0], image: [0,FALSE,FALSE,FALSE,black,0,0,0,0], bandNumber: 0, sMinBand: 0, sSizeBand: 0, colorType: none, colorTileLoadAddress: -1, priority: 0, loadPointer: NIL, loadWords: 0, private: private, input: input, index: 0, page: 0, pass: 0, warningCount: 0 ]]; {ENABLE UNWIND => { zone.FREE[@(handle.private)]; zone.FREE[@(handle)]; }; ReadHerald[handle]; AllocateSpace[handle]; }; }; AllocateSpace: PROC [handle: Handle] ~ { private: Private _ handle.private; loadPages: INT _ (handle.herald.maxLoadWord + (wordsPerPage-1))/wordsPerPage; bufferWords: INT _ (Inline.LongMult[handle.herald.bandSSize, (handle.herald.imageFSize+bitsPerWord-1)/bitsPerWord]+100)*2; bufferPages: INT _ (bufferWords + (wordsPerPage-1))/wordsPerPage; private.loadSpace _ Space.Create[size: loadPages+bufferPages, parent: Space.virtualMemory]; Space.Map[private.loadSpace]; Space.CreateUniformSwapUnits[16, private.loadSpace]; private.loadPointer _ Space.LongPointer[private.loadSpace]; private.loadWordsAllocated _ loadPages*wordsPerPage; private.bufferWordPointer _ private.bufferOriginPointer _ private.loadPointer + private.loadWordsAllocated; private.bufferWordsAllocated _ bufferPages*wordsPerPage; private.bufferWordCount _ 0; }; FillBuffer: PROC [handle: Handle] RETURNS [wordsRemovedFromFront: INT]~ { private: Private _ handle.private; wordsRemovedFromFront _ (private.bufferWordPointer-private.bufferOriginPointer); LongBlockTransfer[source: private.bufferWordPointer, count: private.bufferWordCount, dest: private.bufferOriginPointer]; private.bufferWordPointer _ private.bufferOriginPointer; private.bufferWordCount _ private.bufferWordCount + PDInterpInput.GetBlock[ handle.input, private.bufferWordPointer + private.bufferWordCount, handle.index + private.bufferWordCount, private.bufferWordsAllocated - private.bufferWordCount ]; }; BlockDescription: TYPE ~ RECORD [pointer: LONG POINTER, words: CARDINAL]; ReadLocate: PROC [handle: Handle, words: INT] RETURNS [blockDescription: BlockDescription] ~ { private: Private _ handle.private; IF private.bufferWordCount < words THEN [] _ FillBuffer[handle]; blockDescription.pointer _ private.bufferWordPointer; blockDescription.words _ MIN[private.bufferWordCount, words]; private.bufferWordPointer _ private.bufferWordPointer + blockDescription.words; private.bufferWordCount _ private.bufferWordCount - blockDescription.words; handle.index _ handle.index + blockDescription.words; }; ReadBlock: PROC [handle: Handle, dest: LONG POINTER, words: CARDINAL] ~ { private: Private _ handle.private; IF private.bufferWordCount < words THEN [] _ FillBuffer[handle]; IF private.bufferWordCount < words THEN RaisePDError[handle, unexpectedEOF, 0]; BlockTransfer[source: private.bufferWordPointer, count: words, dest: dest]; private.bufferWordPointer _ private.bufferWordPointer + words; private.bufferWordCount _ private.bufferWordCount - words; handle.index _ handle.index + words; }; ReadLongBlock: PROC [handle: Handle, dest: LONG POINTER, words: INT] ~ { private: Private _ handle.private; inBuffer: INT _ MIN[private.bufferWordCount, words]; LongBlockTransfer[source: private.bufferWordPointer, count: inBuffer, dest: dest]; private.bufferWordPointer _ private.bufferWordPointer + inBuffer; private.bufferWordCount _ private.bufferWordCount - inBuffer; handle.index _ handle.index + inBuffer; dest _ dest + inBuffer; words _ words - inBuffer; IF words > 0 THEN { IF private.bufferWordCount # 0 THEN ERROR; IF words # PDInterpInput.GetBlock[handle.input, dest, handle.index, words] THEN { RaisePDError[handle, unexpectedEOF, 0]; }; handle.index _ handle.index + words; }; }; Close: PUBLIC PROC [handle: Handle] RETURNS [Handle _ NIL] ~ { private: Private _ handle.private; private.loadPointer _ NIL; private.loadWordsAllocated _ 0; IF private.loadSpace # Space.nullHandle THEN Space.Delete[private.loadSpace]; zone.FREE[@(handle.private)]; zone.FREE[@(handle)]; }; ReadHerald: PROC [handle: Handle] ~ { herald: PDFileFormat.Herald; IF PDInterpInput.GetBlock[handle.input, @herald, 0, SIZE[PDFileFormat.Herald]] # SIZE[PDFileFormat.Herald] THEN RaisePDError[handle, unexpectedEOF, 0] ELSE handle.index _ SIZE[PDFileFormat.Herald]; IF herald.password # PDFileFormat.passwordValue THEN { RaisePDError[handle, invalidPassword, SIZE[PDFileFormat.Herald]]; }; IF herald.version # PDFileFormat.versionValue THEN { RaisePDWarning[handle, wrongFormatVersion, SIZE[PDFileFormat.Herald]]; }; IF NOT (herald.sResolution IN [10..10000]) OR NOT (herald.fResolution IN [10..10000]) THEN { RaisePDWarning[handle, unreasonableResolution, SIZE[PDFileFormat.Herald]]; }; IF NOT (herald.bandSSize IN [8..32767]) THEN { RaisePDWarning[handle, unreasonableBandSSize, SIZE[PDFileFormat.Herald]]; }; IF NOT (herald.imageSSize IN [80..32767]) OR NOT (herald.imageFSize IN [80..32767]) THEN { RaisePDWarning[handle, unreasonableImageSize, SIZE[PDFileFormat.Herald]]; }; IF herald.maxLoadWord > 60000 THEN { RaisePDWarning[handle, unreasonableLoadSize, SIZE[PDFileFormat.Herald]]; }; IF NOT (herald.copies IN [1..200]) THEN { RaisePDWarning[handle, unreasonableNumberOfCopies, SIZE[PDFileFormat.Herald]]; }; handle.herald _ herald; handle.sSizeBand _ herald.bandSSize; }; CheckBB: PROC [handle: Handle, sMin, fMin, sSize, fSize: CARDINAL, errorWordCount: INT] ~ { IF LONG[sMin] + sSize > handle.herald.imageSSize OR LONG[fMin] + fSize > handle.herald.imageFSize OR fMin < handle.image.fMinPage OR fMin + fSize > handle.image.fMinPage + handle.image.fSizePage THEN RaisePDError[handle, objectOutOfBounds, errorWordCount]; IF sMin + sSize <= handle.sMinBand OR sMin >= handle.sMinBand+handle.sSizeBand THEN { RaisePDWarning[handle, objectOutOfBand, errorWordCount]; }; }; Get: PUBLIC PROC [handle: Handle] RETURNS [CommandBuffer] ~ { private: Private _ handle.private; command: PDFileFormat.Command; BadLoadReference: PROC [dataWords: INT] ~ { RaisePDError[handle, badLoadReference, SIZE[PDFileFormat.Command]+dataWords]; }; ReadBlock[handle, @command, SIZE[PDFileFormat.Command]]; WITH command SELECT FROM imagingCommand: PDFileFormat.Command.imaging => { IF handle.colorType = none THEN { RaisePDError[handle, missingStartImage, SIZE[PDFileFormat.Command]]; ERROR }; SELECT imagingCommand.com FROM maskSamplesRef => { ans: CommandBuffer.maskSamples; maskSamplesRef: PDFileFormat.MaskSamplesRef; loadAddress: Environment.LongNumber; samples: LONG POINTER TO PDFileFormat.SampleArray; words: INT; ReadBlock[handle, @maskSamplesRef, SIZE[PDFileFormat.MaskSamplesRef]]; loadAddress.highbits _ imagingCommand.addrHighBits; loadAddress.lowbits _ maskSamplesRef.addrLowBits; ans.loadAddress _ loadAddress.li; IF ans.loadAddress < 0 OR ans.loadAddress + SIZE[PDFileFormat.SampleArray] > handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.MaskSamplesRef]]; samples _ private.loadPointer + loadAddress.li; words _ Inline.LongMult[samples.sSize, (samples.fSize+(bitsPerWord-1))/bitsPerWord]; IF ans.loadAddress + SIZE[PDFileFormat.SampleArray] + words > handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.MaskSamplesRef]]; CheckBB[handle, maskSamplesRef.sMin, maskSamplesRef.fMin, samples.sSize, samples.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskSamplesRef]]; ans.samples _ [sOrigin: maskSamplesRef.sMin, fOrigin: maskSamplesRef.fMin, sMin: 0, fMin: 0, sSize: samples.sSize, fSize: samples.fSize, pointer: samples+SIZE[PDFileFormat.SampleArray], rast: (samples.fSize+(bitsPerWord-1))/bitsPerWord, lines: samples.sSize]; RETURN [ans] }; maskRunGroupRef => { ans: CommandBuffer.maskRunGroup; maskRunGroupRef: PDFileFormat.MaskRunGroupRef; loadAddress: Environment.LongNumber; runGroup: LONG POINTER TO PDFileFormat.RunGroup; run: LONG POINTER TO PDFileFormat.Run; s: CARDINAL _ 0; runCount: CARDINAL _ 0; words: INT _ 0; maxRunCount: CARDINAL; fSize: CARDINAL _ 0; ReadBlock[handle, @maskRunGroupRef, SIZE[PDFileFormat.MaskRunGroupRef]]; loadAddress.highbits _ imagingCommand.addrHighBits; loadAddress.lowbits _ maskRunGroupRef.addrLowBits; ans.loadAddress _ loadAddress.li; IF ans.loadAddress < 0 OR ans.loadAddress + SIZE[PDFileFormat.RunGroup] > handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.MaskRunGroupRef]]; runGroup _ private.loadPointer + loadAddress.li; ans.pointer _ run _ private.loadPointer + loadAddress.li + SIZE[PDFileFormat.RunGroup]; maxRunCount _ MAX[(handle.loadWords-loadAddress.li-SIZE[PDFileFormat.RunGroup])/2-1, 0]; WHILE s < runGroup.sSize DO IF run.fSize > fSize THEN fSize _ run.fSize; IF run.lastRun THEN s _ s + 1; run _ run + SIZE[PDFileFormat.Run]; IF (runCount _ runCount + 1) >= maxRunCount THEN BadLoadReference[SIZE[PDFileFormat.MaskRunGroupRef]]; ENDLOOP; ans.runCount _ runCount; CheckBB[handle, maskRunGroupRef.sMin, maskRunGroupRef.fMin, runGroup.sSize, fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskRunGroupRef]]; ans.sMin _ maskRunGroupRef.sMin; ans.fMin _ ans.fOffset _ maskRunGroupRef.fMin; ans.sSize _ runGroup.sSize; ans.fSize _ fSize; RETURN [ans] }; maskRectangle => { ans: CommandBuffer.maskRectangle; maskRectangle: PDFileFormat.MaskRectangle; ReadBlock[handle, @maskRectangle, SIZE[PDFileFormat.MaskRectangle]]; CheckBB[handle, maskRectangle.sMin, maskRectangle.fMin, maskRectangle.sSize, maskRectangle.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskRectangle]]; ans.sMin _ maskRectangle.sMin; ans.fMin _ maskRectangle.fMin; ans.sSize _ maskRectangle.sSize; ans.fSize _ maskRectangle.fSize; RETURN [ans] }; maskTrapezoid => { ans: CommandBuffer.maskTrapezoid; maskTrapezoid: PDFileFormat.MaskTrapezoid; fMin, fMax: INT; ReadBlock[handle, @maskTrapezoid, SIZE[PDFileFormat.MaskTrapezoid]]; fMin _ MIN[maskTrapezoid.fMin, maskTrapezoid.fMinLast]; fMax _ MAX[LONG[maskTrapezoid.fMin] + maskTrapezoid.fSize, LONG[maskTrapezoid.fMinLast] + maskTrapezoid.fSizeLast]; CheckBB[handle, maskTrapezoid.sMin, fMin, maskTrapezoid.sSize, fMax-fMin, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskTrapezoid]]; ans.sMin _ maskTrapezoid.sMin; ans.fMin _ maskTrapezoid.fMin; ans.fMinLast _ maskTrapezoid.fMinLast; ans.sSize _ maskTrapezoid.sSize; ans.fSize _ maskTrapezoid.fSize; ans.fSizeLast _ maskTrapezoid.fSizeLast; RETURN [ans] }; maskRunGroup => { ans: CommandBuffer.maskRunGroup; maskRunGroup: PDFileFormat.MaskRunGroup; runGroup: PDFileFormat.RunGroup; s: CARDINAL _ 0; runCount: INT _ 0; words: INT _ 0; fMin: CARDINAL _ LAST[CARDINAL]; fMax: CARDINAL _ FIRST[CARDINAL]; run: LONG POINTER TO PDFileFormat.Run; ReadBlock[handle, @maskRunGroup, SIZE[PDFileFormat.MaskRunGroup]]; ReadBlock[handle, @runGroup, SIZE[PDFileFormat.RunGroup]]; run _ private.bufferWordPointer; WHILE s < runGroup.sSize DO IF (runCount+1)*SIZE[PDFileFormat.Run] > private.bufferWordCount THEN { run _ run - FillBuffer[handle]; IF (runCount+1)*SIZE[PDFileFormat.Run] > private.bufferWordCount THEN RaisePDError[handle, runGroupTooLong, SIZE[PDFileFormat.MaskRunGroup] + SIZE[PDFileFormat.RunGroup]]; }; IF run.fMin < fMin THEN fMin _ run.fMin; IF LONG[run.fMin] + run.fSize > fMax THEN fMax _ LONG[run.fMin] + run.fSize; IF run.lastRun THEN s _ s + 1; runCount _ runCount + 1; run _ run + SIZE[PDFileFormat.Run]; ENDLOOP; ans.runCount _ runCount; ans.loadAddress _ -1; IF runCount = 0 THEN { ans.pointer _ NIL; RaisePDWarning[handle, emptyRunGroup, SIZE[PDFileFormat.MaskRunGroup]+SIZE[PDFileFormat.RunGroup]]; fMin _ fMax; } ELSE { [[ans.pointer, ----]] _ ReadLocate[handle, runCount*SIZE[PDFileFormat.Run]]; CheckBB[handle, maskRunGroup.sMin, fMin, runGroup.sSize, fMax-fMin, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskRunGroupRef]] }; ans.sMin _ maskRunGroup.sMin; ans.fMin _ fMin; ans.fOffset _ 0; ans.sSize _ runGroup.sSize; ans.fSize _ fMax; RETURN [ans]; }; maskSamples => { ans: CommandBuffer.maskSamples; maskSamples: PDFileFormat.MaskSamples; samples: PDFileFormat.SampleArray; ReadBlock[handle, @maskSamples, SIZE[PDFileFormat.MaskSamples]]; ReadBlock[handle, @samples, SIZE[PDFileFormat.SampleArray]]; CheckBB[handle, maskSamples.sMin, maskSamples.fMin, samples.sSize, samples.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskSamples]+SIZE[PDFileFormat.SampleArray]]; ans.loadAddress _ -1; {raster: BlockDescription _ ReadLocate[ handle, Inline.LongMult[samples.sSize, (samples.fSize+(bitsPerWord-1))/bitsPerWord] ]; ans.samples _ PDInterpBitmap.Reshape[ raster.pointer, raster.words, [maskSamples.sMin, maskSamples.fMin, samples.sSize, samples.fSize] ! PDInterpBitmap.InsufficientSpace => { RaisePDError[handle, bitmapTooBig, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskSamples]+SIZE[PDFileFormat.SampleArray]]; ERROR } ]; }; RETURN [ans]; }; colorSamples => { ans: CommandBuffer.colorSamples; colorSamples: PDFileFormat.ColorSamples; samples: PDFileFormat.SampleArray; ReadBlock[handle, @colorSamples, SIZE[PDFileFormat.ColorSamples]]; ReadBlock[handle, @samples, SIZE[PDFileFormat.SampleArray]]; CheckBB[handle, colorSamples.sMin, colorSamples.fMin, samples.sSize, samples.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.ColorSamples]+SIZE[PDFileFormat.SampleArray]]; {raster: BlockDescription _ ReadLocate[ handle, Inline.LongMult[samples.sSize, (samples.fSize+(bitsPerWord-1))/bitsPerWord] ]; ans.samples _ PDInterpBitmap.Reshape[ raster.pointer, raster.words, [colorSamples.sMin, colorSamples.fMin, samples.sSize, samples.fSize] ! PDInterpBitmap.InsufficientSpace => { RaisePDError[handle, bitmapTooBig, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskSamples]+SIZE[PDFileFormat.SampleArray]]; ERROR } ]; }; RETURN [ans]; }; ENDCASE => { RaisePDError[handle, unrecognisedImagingCommand, SIZE[PDFileFormat.Command]]; ERROR}; }; controlCommand: PDFileFormat.Command.control => { ans: CommandBuffer.stateChange; ans.loadChangeStart _ ans.loadChangeLength _ 0; IF handle.colorType = none THEN SELECT controlCommand.com FROM startImage, deviceCommand, storeLoad, endDocument => NULL; ENDCASE => { RaisePDError[handle, missingStartImage, SIZE[PDFileFormat.Command]]; ERROR }; SELECT controlCommand.com FROM startImage => { startImage: PDFileFormat.StartImage; ReadBlock[handle, @startImage, SIZE[PDFileFormat.StartImage]]; IF startImage.filler # 0 THEN { RaisePDWarning[handle, nonZeroFill, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StartImage]]; }; IF (LONG[startImage.passBands]+startImage.nBands)*handle.sSizeBand >= handle.herald.imageSSize+handle.sSizeBand OR LONG[startImage.fMinPage]+startImage.fSizePage > handle.herald.imageFSize THEN { RaisePDWarning[handle, imageBoundsExceedPageBounds, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StartImage]]; }; IF handle.colorType # none AND handle.bandNumber < handle.image.nBands THEN RaisePDWarning[handle, tooFewBands, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StartImage]]; handle.image _ startImage; ans.whatChanged _ imageStart; handle.priority _ 0; handle.colorType _ ink; handle.bandNumber _ 0; handle.sMinBand _ startImage.passBands*handle.sSizeBand; IF NOT startImage.strip THEN {handle.pass _ handle.pass + 1}; IF startImage.feed THEN {handle.page _ handle.page + 1; handle.pass _ 1}; RETURN [ans] }; setPriority => { priorityLow: PDFileFormat.Priority; priority: Environment.LongNumber; ReadBlock[handle, @priorityLow, SIZE[PDFileFormat.Priority]]; priority.highbits _ controlCommand.rest; priority.lowbits _ priorityLow; handle.priority _ priority.li; ans.whatChanged _ priorityChange; RETURN [ans] }; setColorInk => { handle.colorType _ ink; ans.whatChanged _ colorChange; RETURN [ans] }; setColorClear => { handle.colorType _ clear; ans.whatChanged _ colorChange; RETURN [ans] }; setColorTile => { setColorTile: PDFileFormat.SetColorTile; ReadBlock[handle, @setColorTile, SIZE[PDFileFormat.SetColorTile]]; handle.colorTileLoadAddress _ setColorTile.addr; SELECT controlCommand.rest FROM 0 => handle.colorType _ opaqueTile; 1 => handle.colorType _ transparentTile; ENDCASE => { handle.colorType _ opaqueTile; RaisePDWarning[handle, unknownColorTileFlag, SIZE[PDFileFormat.Command]]; }; ans.whatChanged _ colorChange; RETURN [ans]; }; endBand => { handle.sMinBand _ handle.sMinBand + handle.sSizeBand; handle.bandNumber _ handle.bandNumber + 1; ans.whatChanged _ bandChange; IF handle.bandNumber = handle.image.nBands THEN { ans.whatChanged _ imageEnd; handle.colorType _ none; }; RETURN [ans]; }; endDocument => { ans.whatChanged _ documentEnd; RETURN [ans]; }; storeLoad => { storeLoad: PDFileFormat.StoreLoad; loadWordsAllocated: LONG CARDINAL _ private.loadWordsAllocated; ReadBlock[handle, @storeLoad, SIZE[PDFileFormat.StoreLoad]]; IF storeLoad.firstAddress > loadWordsAllocated OR storeLoad.firstAddress + storeLoad.wordCount > loadWordsAllocated OR storeLoad.firstAddress + storeLoad.wordCount > handle.herald.maxLoadWord THEN {RaisePDError[handle, loadOutOfBounds, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StoreLoad]]; ERROR}; ReadLongBlock[handle, private.loadPointer+storeLoad.firstAddress, storeLoad.wordCount]; ans.whatChanged _ loadChange; ans.loadChangeStart _ storeLoad.firstAddress; ans.loadChangeLength _ storeLoad.wordCount; handle.loadWords _ MAX[handle.loadWords, ans.loadChangeStart + ans.loadChangeLength]; handle.colorTileLoadAddress _ -1; RETURN [ans]; }; deviceCommand => { deviceCommand: CommandBuffer.deviceCommand; wordCount: CARDINAL; block: BlockDescription; ReadBlock[handle, @wordCount, SIZE[CARDINAL]]; block _ ReadLocate[handle, wordCount]; IF block.words < wordCount THEN RaisePDError[handle, unexpectedEOF, block.words+SIZE[CARDINAL]]; deviceCommand.deviceCommandPointer _ block.pointer; deviceCommand.deviceCommandWords _ block.words; RETURN [deviceCommand]; }; ENDCASE => {RaisePDError[handle, unrecognisedControlCommand, SIZE[PDFileFormat.Command]]; ERROR}; }; ENDCASE => {RaisePDError[handle, unrecognisedCommandType, SIZE[PDFileFormat.Command]]; ERROR}; }; Error: PUBLIC ERROR [handle: Handle, code: PDInterpBasic.PDErrorCode, wordIndex, wordCount: INT] ~ CODE; Warning: PUBLIC SIGNAL [handle: Handle, code: PDInterpBasic.PDWarningCode, wordIndex, wordCount: INT] ~ CODE; RaisePDError: PROC [handle: Handle, code: PDInterpBasic.PDErrorCode, words: INT] ~ { ERROR Error[handle, code, handle.index-words, words]; }; RaisePDWarning: PROC [handle: Handle, code: PDInterpBasic.PDWarningCode, words: INT] ~ { handle.warningCount _ handle.warningCount + 1; SIGNAL Warning[handle, code, handle.index-words, words]; }; END. PDInterpReaderImpl.mesa Michael Plass, November 11, 1983 2:11 pm The buffer variables satisfy the invariants (bufferWordPointer + i)^ = InputFileWord[handle.index+i], i IN [0..bufferWordCount) handle.index+bufferWordCount <= inputFileSizeInWords bufferWordPointer-bufferOriginPointer >= 0 bufferWordCount + (bufferWordPointer-bufferOriginPointer) <= bufferWordsAllocated where InputFileWord[k] stands for the kth word of the input file. The buffer storage may get re-used with the next ReadLocate or ReadBlock; Κ˜Jšœ™J™(unitšΟk ˜ Jšœ€˜€—šΟnœ˜Jšœ<˜CJšœ˜Jšœœœ˜—˜Jšœ œ˜+Jšœœ˜-J˜Jšœœ ˜Jšœ œ˜J˜—šžœœœ(œœœœœ˜Jšœ"˜"Jšœœœœ@˜UJšœœI˜Sšœ:˜:Jšœœ˜Jšœ˜Jšœ.˜.J˜—šœ˜"Jšœ:˜:Jšœ˜Jšœœ˜.Jšœ˜Jšœ˜Jšœ˜—J˜J˜—šž œœ œœ œœœ˜OJšœœœ˜ J˜—šžœœ œœ œœœ˜Ršœ œœ˜Jšœœœ ˜,Jšœœœ˜!Jšœœœ˜Jšœœœ˜Jšœ˜—Jšœ#˜#Jšœ˜J˜—Jš œ œœœœ ˜+šœ œœœ˜"Jšœ+˜+Jšœ œ œ˜ Jšœœ˜Jšœœ œ˜(Jšœœ˜Jšœœ œ˜&šœœ˜™+JšœS™SJšœ4™4Jšœ*™*JšœQ™Q—Jšœ'Οuœ™A—Jšœ˜J˜—šœ œœ"˜6J˜—šœœœ˜Jš œœœœ˜&Jšœ˜J˜—šžœœœœ˜LJšœœ ˜(šœœ˜Jšœ$˜$Jšœ œœœ˜+Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ ˜ Jšœ œ˜Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜—šœ˜šœ˜ Jšœœ˜Jšœœ ˜Jšœ˜—Jšœ˜Jšœ˜J˜—Jšœ˜J˜—šž œœ˜(Jšœ"˜"Jšœ œ?˜MJšœ œj˜zJšœ œ1˜AJšœ[˜[Jšœ˜Jšœ4˜4Jšœ;˜;Jšœ4˜4Jšœk˜kJšœ8˜8Jšœ˜Jšœ˜J˜—šž œœœœ˜IJšœ"˜"JšœP˜PJšœx˜xJšœ8˜8šœ3˜3šœ˜Jšœ ˜ Jšœ4˜4Jšœ'˜'Jšœ6˜6Jšœ˜——Jšœ˜J˜—Jš œœœ œœ œ˜Išž œœœ˜-Jšœ)˜0JšœI™IJšœ"˜"Jšœ!œ˜@Jšœ5˜5Jšœœ!˜=JšœO˜OJšœK˜KJšœ5˜5Jšœ˜J˜—šž œœ œ œ˜IJšœ"˜"Jšœ!œ˜@Jšœ!œ(˜OJšœK˜KJšœ>˜>Jšœ:˜:Jšœ$˜$Jšœ˜J˜—šž œœ œ œ˜HJšœ"˜"Jšœ œœ!˜4JšœR˜RJšœA˜AJšœ=˜=Jšœ'˜'Jšœ˜Jšœ˜šœ œ˜Jšœœœ˜*šœIœ˜QJšœ'˜'Jšœ˜—Jšœ$˜$Jšœ˜—Jšœ˜J˜—š žœœœœ œ˜>Jšœ"˜"Jšœœ˜Jšœ˜Jšœ&œ!˜MJšœœ˜Jšœœ ˜Jšœ˜J˜—šž œœ˜%Jšœ˜Jšœ2œœœ'˜–Jšœœ˜.šœ.œ˜6Jšœ&œ˜AJšœ˜—šœ,œ˜4Jšœ+œ˜FJšœ˜—Jšœœœ ˜*šœœœœ˜1Jšœ/œ˜JJšœ˜—šœœœ œ˜.Jšœ.œ˜IJšœ˜—Jšœœœ ˜)šœœœœ˜0Jšœ.œ˜IJšœ˜—šœœ˜$Jšœ-œ˜HJšœ˜—šœœœ œ˜)Jšœ3œ˜NJšœ˜—Jšœ˜Jšœ$˜$Jšœ˜J˜—šžœœ,œœ˜[Jšœœ)˜0Jšœœ)˜0Jšœ˜Jšœ>˜@Jšœ9˜=Jšœ ˜"šœ*œ˜2Jšœ8˜8Jšœ˜—Jšœ˜J˜—šžœœœœ˜=Jšœ"˜"Jšœ˜šžœœ œ˜+Jšœ'œ"˜MJšœ˜—Jšœœ˜8šœ œ˜šžœ#˜1šœœ˜!Jšœ(œ˜DJš˜Jšœ˜—šœ˜šžœ˜Jšœ˜Jšœ,˜,J˜$Jšœ œœœ˜2Jšœœ˜ Jšœ#œ˜FJšœ3˜3Jšœ1˜1Jšœ!˜!Jš œœœ.œœ˜—Jšœ/˜/JšœT˜TJšœœ6œœ˜ˆJšœXœœ˜–Jšœšœe˜ƒJšœ˜ Jšœ˜—šžœ˜Jšœ ˜ Jšœ.˜.J˜$Jšœ œœœ˜0Jšœœœœ˜&Jšœœ˜Jšœ œ˜Jšœœ˜Jšœ œ˜Jšœœ˜Jšœ$œ ˜HJšœ3˜3Jšœ2˜2Jšœ!˜!Jš œœœ+œœ ˜•Jšœ0˜0Jšœ;œ˜WJšœœ"œ!˜Xšœ˜Jšœœ˜,Jšœ œ ˜Jšœ œ˜#Jšœ*œœ ˜fJšœ˜—Jšœ˜JšœSœœ ˜’Jšœ ˜ Jšœ.˜.Jšœ˜Jšœ˜Jšœ˜ Jšœ˜—šž œ˜Jšœ!˜!Jšœ*˜*Jšœ"œ˜DJšœbœœ˜ŸJšœ˜Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ˜ Jšœ˜—šž œ˜Jšœ!˜!Jšœ*˜*Jšœ œ˜Jšœ"œ˜DJšœœ-˜7Jšœœœ,œ4˜sJšœJœœ˜‡Jšœ˜Jšœ˜Jšœ&˜&Jšœ ˜ Jšœ ˜ Jšœ(˜(Jšœ˜ Jšœ˜—šž œ˜Jšœœ ˜ Jšœ(˜(Jšœ ˜ Jšœœ˜Jšœ œ˜Jšœœ˜Jšœœœœ˜ Jšœœœœ˜!Jšœœœœ˜&Jšœ!œ˜BJšœœ˜:Jšœ ˜ šœ˜šœœ-œ˜GJšœ˜Jš œœ-œ'œœ˜«Jšœ˜—Jšœœ˜(Jšœœœœ˜LJšœ œ ˜Jšœ˜Jšœ œ˜#Jšœ˜—Jšœ˜Jšœ˜šœœ˜Jšœœ˜Jšœ&œœ˜cJšœ ˜ Jšœ˜—šœ˜JšœΟcœ!œ˜LJšœDœœ˜‚Jšœ˜—Jšœ˜Jšœ˜J˜Jšœ˜Jšœ˜Jšœ˜ Jšœ˜—šž œ˜Jšœ˜Jšœ&˜&Jšœ"˜"Jšœ œ˜@Jšœœ˜Jšœ5œ˜:šœ˜ Jšœ(œ˜DJš˜Jšœ˜——šœ˜šž œ˜Jšœ$˜$Jšœœ˜>šœœ˜Jšœ$œœ˜^Jšœ˜—Jšœœg˜ošœœFœ˜SJšœ4œœ˜nJšœ˜—šœœ)˜KJšœ$œœ˜^—Jšœ˜Jšœ˜Jšœ˜J˜Jšœ˜Jšœ8˜8Jšœœœ!˜=Jšœœ2˜IJšœ˜ Jšœ˜—šž œ˜Jšœ#˜#Jšœ!˜!Jšœ œ˜=Jšœ(˜(Jšœ˜Jšœ˜Jšœ!˜!Jšœ˜ Jšœ˜—šž œ˜J˜Jšœ˜Jšœ˜ Jšœ˜—šž œ˜J˜Jšœ˜Jšœ˜ Jšœ˜—šž œ˜Jšœ(˜(Jšœ!œ˜BJšœ0˜0šœ˜J˜#Jšœ(˜(šœ˜ J˜Jšœ-œ˜IJšœ˜——Jšœ˜Jšœ˜ Jšœ˜—šžœ˜ Jšœ5˜5Jšœ*˜*Jšœ˜šœ)œ˜1Jšœ˜Jšœ˜Jšœ˜—Jšœ˜ Jšœ˜—šž œ˜Jšœ˜Jšœ˜ Jšœ˜—šž œ˜Jšœ"˜"Jšœœœ˜?Jšœœ˜