<> <> <> DIRECTORY BasicTime USING [GMT, Now, nullGMT], FS USING [StreamOpen], IO USING [Close, PutChar, PutRope], PasPrivate, PasPrivateVars, Process USING [Yield], RefText USING [AppendChar], Rope USING [Balance, Concat, Fetch, FromChar, FromRefText, Length]; PasOut: CEDAR PROGRAM IMPORTS BasicTime, FS, IO, PasPrivateVars, Process, RefText, Rope EXPORTS PasPrivate = BEGIN OPEN PasPrivate, PasPrivateVars; lastTimeFileWasOutput: BasicTime.GMT _ BasicTime.nullGMT; <> <> <> <> FlushOutBuf: PROCEDURE = BEGIN q: OutputQueuePtr = outQStk[outLevel]; IF outBuf.length # 0 THEN BEGIN q.contents _ Rope.Concat[q.contents, Rope.FromRefText[outBuf]]; outBuf.length _ 0; END; END; -- of FlushOutBuf CharToQueue: PUBLIC PROCEDURE [c: CHARACTER, q: OutputQueuePtr _ NIL] = BEGIN IF q = NIL THEN q _ outQStk[outLevel]; IF q = outQStk[outLevel] THEN BEGIN IF outBuf.length = outBuf.maxLength THEN FlushOutBuf[]; [] _ RefText.AppendChar[to: outBuf, from: c]; -- new char will fit cause we just checked END ELSE q.contents _ Rope.Concat[q.contents, Rope.FromChar[c]]; END; -- of CharToQueue CharToQueueStart: PUBLIC PROCEDURE [c: CHARACTER, q: OutputQueuePtr _ NIL] = BEGIN IF q = NIL THEN q _ outQStk[outLevel]; q.contents _ Rope.Concat[Rope.FromChar[c], q.contents]; END; -- of CharToQueueStart StringToQueue: PUBLIC PROCEDURE [s: ROPE, q: OutputQueuePtr _ NIL] = BEGIN IF q = NIL THEN q _ outQStk[outLevel]; IF q = outQStk[outLevel] THEN BEGIN sLen: NAT _ s.Length[]; bufLen: NAT _ outBuf.length; IF sLen + bufLen > outBuf.maxLength THEN FlushOutBuf[]; IF sLen + bufLen > outBuf.maxLength THEN -- still too big {q.contents _ Rope.Concat[q.contents, s]; RETURN}; FOR i:NAT IN [0..sLen) DO outBuf[bufLen+i] _ s.Fetch[i]; ENDLOOP; outBuf.length _ bufLen+sLen; END ELSE q.contents _ Rope.Concat[q.contents, s]; END; -- of StringToQueue StringToQueueStart: PUBLIC PROCEDURE [s: ROPE, q: OutputQueuePtr _ NIL] = BEGIN IF q = NIL THEN q _ outQStk[outLevel]; q.contents _ Rope.Concat[s, q.contents]; END; -- of StringToQueueStart MergeQueue: PUBLIC PROCEDURE [ from: OutputQueuePtr, to: OutputQueuePtr _ NIL] = BEGIN IF to = NIL THEN to _ outQStk[outLevel]; IF to = outQStk[outLevel] OR from = outQStk[outLevel] THEN FlushOutBuf[]; to.contents _ Rope.Concat[to.contents, from.contents]; ClearQueue[from]; END; -- of MergeQueue MergeQueueStart: PUBLIC PROCEDURE [ from: OutputQueuePtr, to: OutputQueuePtr _ NIL] = BEGIN IF to = NIL THEN to _ outQStk[outLevel]; IF to = outQStk[outLevel] OR from = outQStk[outLevel] THEN FlushOutBuf[]; to.contents _ Rope.Concat[from.contents, to.contents]; ClearQueue[from]; END; -- of MergeQueueStart CopyQueue: PUBLIC PROCEDURE [ from: OutputQueuePtr, to: OutputQueuePtr _ NIL] = BEGIN -- not especially efficient IF to = NIL THEN to _ outQStk[outLevel]; IF to = outQStk[outLevel] OR from = outQStk[outLevel] THEN FlushOutBuf[]; to.contents _ Rope.Concat[to.contents, from.contents]; END; -- of CopyQueue ClearQueue: PUBLIC PROCEDURE [q: OutputQueuePtr _ NIL] = BEGIN IF q = NIL THEN q _ outQStk[outLevel]; IF q = outQStk[outLevel] THEN FlushOutBuf[]; IF q.fileName.Length[] # 0 THEN BEGIN s: STREAM; TRUSTED {WHILE lastTimeFileWasOutput = BasicTime.Now[] DO Process.Yield[] ENDLOOP}; s _ FS.StreamOpen[q.fileName, $create]; s.PutRope[q.contents]; s.Close[]; TRUSTED {lastTimeFileWasOutput _ BasicTime.Now[]}; commandHandle.out.PutChar['.]; END; q.contents _ ""; q.fileName _ ""; END; -- of ClearQueue BalanceQueue: PUBLIC PROCEDURE [q: OutputQueuePtr _ NIL] = BEGIN IF q = NIL THEN q _ outQStk[outLevel]; IF q = outQStk[outLevel] THEN FlushOutBuf[]; q.contents _ Rope.Balance[base: q.contents]; END; -- of BalanceQueue PushOut: PUBLIC PROCEDURE [q: OutputQueuePtr _ NIL] = BEGIN IF outLevel # 0 THEN FlushOutBuf[]; outLevel _ outLevel + 1; IF q = NIL THEN outQStk[outLevel] _ Z.NEW[OutputQueue_[contents: "", fileName: ""]] ELSE BEGIN outQStk[outLevel] _ q END; END; CopyAndPopOut: PUBLIC PROCEDURE RETURNS [OutputQueuePtr] = BEGIN q: OutputQueuePtr _ outQStk[outLevel]; FlushOutBuf[]; outQStk[outLevel] _ NIL; outLevel _ outLevel - 1; RETURN[q]; END; PopOut: PUBLIC PROCEDURE = BEGIN ClearQueue[outQStk[outLevel]]; outLevel _ outLevel - 1; END; END. -- of PasOut --