MODULE TrapWriters;
IMPORT Streams, Kernel, KernelLog, Trace, Modules;
CONST
TrapMaxCharacters = 32*1024;
TYPE
Entry= POINTER TO RECORD factory: WriterFactory; next: Entry END;
WriterFactory = PROCEDURE (): Streams.Writer;
TrapWriter = OBJECT (Streams.StringWriter)
VAR
trapped: BOOLEAN;
first, last: Entry;
timer: Kernel.Timer;
contents: ARRAY TrapMaxCharacters OF CHAR;
PROCEDURE Trapped;
BEGIN trapped := TRUE;
END Trapped;
PROCEDURE &InitTrapWriter(f: WriterFactory);
BEGIN
first := NIL; last := NIL; trapped := FALSE;
Add(f);
InitStringWriter (TrapMaxCharacters);
END InitTrapWriter;
PROCEDURE Add(f: WriterFactory);
VAR e: Entry;
BEGIN
Remove(f);
NEW(e); e.factory := f; e.next := NIL;
IF first = NIL THEN first := e; last := e
ELSE last.next := e; last := e
END;
END Add;
PROCEDURE Remove(f: WriterFactory);
VAR e: Entry;
BEGIN
IF first = NIL THEN RETURN
ELSIF first.factory = f THEN
first := first.next;
IF first = NIL THEN last := NIL END;
ELSE e := first;
WHILE (e.next # NIL) & (e.next.factory # f) DO
e := e.next
END;
IF e.next # NIL THEN
IF e.next = last THEN last := e END;
e.next := e.next.next;
END;
END;
END Remove;
PROCEDURE RemoveAll;
BEGIN
first := NIL; last := NIL;
END RemoveAll;
PROCEDURE Write;
VAR len: LONGINT; writer: Streams.Writer;
e: Entry;
BEGIN
GetRaw (contents, len); Reset;
e := first;
WHILE e # NIL DO
writer := e.factory (); writer.Bytes (contents, 0, len); writer.Update;
e := e.next
END;
END Write;
BEGIN {ACTIVE}
NEW(timer);
LOOP
timer.Sleep(100);
IF trapped THEN Write; trapped := FALSE
ELSIF first = NIL THEN RETURN
END;
END;
END TrapWriter;
VAR
defaultWriter: Streams.Writer;
traceWriter, logWriter: Streams.Writer;
trapWriter: TrapWriter;
PROCEDURE InstallTrapWriterFactory*(factory: WriterFactory);
BEGIN
IF factory # NIL THEN
IF trapWriter = NIL THEN
NEW (trapWriter,factory)
ELSE
trapWriter.Add (factory)
END;
END
END InstallTrapWriterFactory;
PROCEDURE UninstallTrapWriterFactory*(factory: WriterFactory);
BEGIN
IF trapWriter # NIL THEN
trapWriter.Remove(factory);
IF trapWriter.first = NIL THEN trapWriter := NIL END;
END
END UninstallTrapWriterFactory;
PROCEDURE GetWriter*(): Streams.Writer;
BEGIN
IF trapWriter = NIL THEN RETURN defaultWriter
ELSE RETURN trapWriter
END
END GetWriter;
PROCEDURE Trapped*;
BEGIN
IF trapWriter # NIL THEN trapWriter.Trapped; trapWriter.Update END;
END Trapped;
PROCEDURE TraceFactory(): Streams.Writer;
BEGIN
RETURN traceWriter
END TraceFactory;
PROCEDURE LogFactory(): Streams.Writer;
BEGIN
RETURN logWriter
END LogFactory;
PROCEDURE InstallTraceWriter*;
BEGIN
InstallTrapWriterFactory(TraceFactory);
END InstallTraceWriter;
PROCEDURE RemoveTraceWriter*;
BEGIN
UninstallTrapWriterFactory(TraceFactory)
END RemoveTraceWriter;
PROCEDURE InstallLogWriter*;
BEGIN
InstallTrapWriterFactory(LogFactory);
END InstallLogWriter;
PROCEDURE RemoveLogWriter*;
BEGIN
UninstallTrapWriterFactory(LogFactory);
END RemoveLogWriter;
PROCEDURE RemoveAll*;
BEGIN
IF trapWriter # NIL THEN trapWriter.RemoveAll; trapWriter := NIL END;
END RemoveAll;
PROCEDURE Cleanup;
BEGIN
RemoveAll
END Cleanup;
BEGIN
Modules.InstallTermHandler(Cleanup);
Streams.OpenWriter(logWriter, KernelLog.Send);
Streams.OpenWriter(traceWriter, Trace.Send);
defaultWriter := logWriter;
trapWriter := NIL;
END TrapWriters.
TrapWriters.