-- CopyOp.mesa -- edited by Schroeder, February 5, 1981 5:18 PM -- edited by Andrew Birrell, January 14, 1981 3:40 PM -- edited by Brotz, November 18, 1981 3:43 PM DIRECTORY opD: FROM "OperationsDefs" USING [Expand, FileError, FileErrorReason, Stuff], Storage USING [CopyString, FreeString], TimeDefs USING [PackedTime]; CopyOp: MONITOR IMPORTS opD, Storage EXPORTS opD = BEGIN OPEN opD; Copy: PUBLIC PROC [source, target: STRING, OverwriteOK: PROC RETURNS [BOOLEAN] ] RETURNS [bytesCopied: LONG CARDINAL] = BEGIN state: {start, bufferEmpty, bufferFull, stop}; resumeExpander, resumeStuffer: CONDITION; bufferP: POINTER; bufferC: CARDINAL; error: FileErrorReason; eString: STRING; ec: FileErrorReason; es: STRING; stufferProcess: PROCESS RETURNS [FileErrorReason, STRING]; stufferStarted: BOOLEAN _ FALSE; GetReady: PROCEDURE [bytes: LONG CARDINAL, created: TimeDefs.PackedTime] = BEGIN stufferProcess _ FORK StartStuffer[created]; stufferStarted _ TRUE; END; -- of GetReady -- StartStuffer: PROCEDURE [t: TimeDefs.PackedTime] RETURNS [error: FileErrorReason, s: STRING] = BEGIN error _ ok; s _ NIL; opD.Stuff[target, Stuffer, OverwriteAllowed, t ! FileError => BEGIN error _ reason; IF errorString # NIL THEN s _ Storage.CopyString[errorString]; CONTINUE; END]; IF error = cancel THEN error _ ok; IF error # ok THEN StopExpander[]; END; -- of StartStuffer -- OverwriteAllowed: PROCEDURE RETURNS [allowed: BOOLEAN] = BEGIN allowed _ OverwriteOK[]; IF NOT allowed THEN StopExpander[]; END; -- of OverwriteAllowed -- Stuffer: ENTRY PROCEDURE RETURNS [p: POINTER, c: CARDINAL, b: BOOLEAN] = BEGIN IF state # stop THEN BEGIN state _ bufferEmpty; NOTIFY resumeExpander; UNTIL state # bufferEmpty DO WAIT resumeStuffer; ENDLOOP; p _ bufferP; c _ bufferC; END; b _ state = bufferFull; END; -- of Stuffer -- StopExpander: ENTRY PROCEDURE = {state _ stop; NOTIFY resumeExpander}; StopStuffer: ENTRY PROCEDURE = {state _ stop; NOTIFY resumeStuffer}; Expander: ENTRY PROCEDURE [p: POINTER, c: CARDINAL] RETURNS [BOOLEAN] = BEGIN UNTIL state # start DO WAIT resumeExpander; ENDLOOP; IF state # stop THEN BEGIN bufferP _ p; bufferC _ c; state _ bufferFull; NOTIFY resumeStuffer; bytesCopied _ bytesCopied + c; END; IF c # 0 THEN UNTIL state # bufferFull DO WAIT resumeExpander; ENDLOOP; RETURN[state = bufferEmpty]; END; -- of Expander -- bytesCopied _ 0; state _ start; error _ ok; eString _ NIL; opD.Expand[source, Expander, GetReady ! FileError => BEGIN error _ reason; IF errorString # NIL THEN eString _ Storage.CopyString[errorString]; CONTINUE; END]; error _ SELECT error FROM ok, cancel => ok, ENDCASE => get; IF stufferStarted THEN BEGIN IF error # ok THEN StopStuffer[]; [ec, es] _ JOIN stufferProcess; IF error = ok THEN BEGIN error _ SELECT ec FROM ok, cancel => ok, ENDCASE => put; IF eString # NIL THEN Storage.FreeString[eString]; eString _ es; END ELSE {IF es # NIL THEN Storage.FreeString[es]}; END; IF error # ok THEN ERROR FileError[error, eString ! UNWIND => IF eString # NIL THEN Storage.FreeString[eString]]; END; -- of Copy -- END. -- of CopyOp --(635)\f1