MODULE KernelLog;
IMPORT SYSTEM, Trace, Machine, Objects;
CONST
BufSize = 8000;
VAR
traceBufDef: ARRAY BufSize OF CHAR;
traceBufAdr: SYSTEM.ADDRESS; traceBufSize: SYSTEM.SIZE;
traceHead, traceTail: SYSTEM.ADDRESS;
column*: LONGINT;
PROCEDURE Send*(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: LONGINT);
VAR next: SYSTEM.ADDRESS; c: CHAR;
BEGIN
INC(len, ofs);
Machine.Acquire(Machine.TraceOutput);
LOOP
IF ofs >= len THEN EXIT END;
c := buf[ofs];
IF c = 0X THEN EXIT END;
IF c = 0AX THEN column := 0 ELSE INC(column) END;
next := (traceTail+1) MOD traceBufSize;
IF next # traceHead THEN
SYSTEM.PUT8(traceBufAdr+traceTail, c);
traceTail := next
ELSE
SYSTEM.PUT8(traceBufAdr + (traceTail-1) MOD traceBufSize, 3X)
END;
Trace.Char (c);
INC(ofs)
END;
Machine.Release(Machine.TraceOutput)
END Send;
PROCEDURE String*(CONST s: ARRAY OF CHAR);
VAR len, n: LONGINT;
BEGIN
len := 0; n := LEN(s);
WHILE (len # n) & (s[len] # 0X) DO INC(len) END;
Send(s, 0, len, FALSE, n)
END String;
PROCEDURE Ln*;
BEGIN Char (0DX); Char (0AX);
END Ln;
PROCEDURE Char*(c: CHAR);
TYPE Str = ARRAY 1 OF CHAR;
BEGIN
String(SYSTEM.VAL(Str, c))
END Char;
PROCEDURE Int*(x, w: LONGINT);
VAR i, x0: LONGINT; a: ARRAY 12 OF CHAR;
BEGIN
IF x < 0 THEN
IF x = MIN(LONGINT) THEN
DEC(w, 11);
WHILE w > 0 DO Char(" "); DEC(w) END;
String("-2147483648");
RETURN
ELSE
DEC(w); x0 := -x
END
ELSE
x0 := x
END;
i := 0;
REPEAT
a[i] := CHR(x0 MOD 10 + 30H); x0 := x0 DIV 10; INC(i)
UNTIL x0 = 0;
WHILE w > i DO Char(" "); DEC(w) END;
IF x < 0 THEN Char("-") END;
REPEAT DEC(i); Char(a[i]) UNTIL i = 0
END Int;
PROCEDURE Boolean*(x : BOOLEAN);
BEGIN
IF x THEN String("TRUE") ELSE String("FALSE") END
END Boolean;
PROCEDURE IntSuffix*(x, w: LONGINT; CONST suffix: ARRAY OF CHAR);
CONST K = 1024; M = K*K; G = K*M;
VAR mult: CHAR;
BEGIN
IF x MOD K # 0 THEN
Int(x, w)
ELSE
IF x MOD M # 0 THEN mult := "K"; x := x DIV K
ELSIF x MOD G # 0 THEN mult := "M"; x := x DIV M
ELSE mult := "G"; x := x DIV G
END;
Int(x, w-1); Char(mult)
END;
String(suffix)
END IntSuffix;
PROCEDURE Hex*(x: HUGEINT; w: LONGINT);
VAR i, j: LONGINT; buf: ARRAY 10 OF CHAR;
BEGIN
IF w >= 0 THEN j := 8 ELSE j := 2; w := -w END;
FOR i := j+1 TO w DO Char(" ") END;
FOR i := j-1 TO 0 BY -1 DO
buf[i] := CHR(x MOD 10H + 48);
IF buf[i] > "9" THEN
buf[i] := CHR(ORD(buf[i]) - 48 + 65 - 10)
END;
x := x DIV 10H
END;
buf[j] := 0X;
String(buf)
END Hex;
PROCEDURE Address* (x: SYSTEM.ADDRESS);
BEGIN Hex (x, SYSTEM.SIZEOF (SYSTEM.ADDRESS) * 2)
END Address;
PROCEDURE HIntHex*(x: HUGEINT; w: LONGINT);
BEGIN
Hex(SHORT (Machine.ASHH(x, -32)), w-8);
Hex(SHORT (x), 8)
END HIntHex;
PROCEDURE Memory*(adr: SYSTEM.ADDRESS; size: SYSTEM.SIZE);
VAR i, j: SYSTEM.ADDRESS; ch: CHAR;
BEGIN
Char(0EX);
size := adr+size-1;
FOR i := adr TO size BY 16 DO
Address (i); Char (' ');
FOR j := i TO i+15 DO
IF j <= size THEN
SYSTEM.GET(j, ch);
Hex(ORD(ch), -3)
ELSE
String(" ")
END
END;
String(" ");
FOR j := i TO i+15 DO
IF j <= size THEN
SYSTEM.GET(j, ch);
IF (ch < " ") OR (ch >= CHR(127)) THEN ch := "." END;
Char(ch)
END
END;
Ln
END;
Char(0FX)
END Memory;
PROCEDURE Buffer*(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT);
BEGIN
Memory(SYSTEM.ADR(buf[ofs]), len)
END Buffer;
PROCEDURE Bits*(x: SET; ofs, n: LONGINT);
BEGIN
REPEAT
DEC(n);
IF (ofs+n) IN x THEN Char("1") ELSE Char("0") END
UNTIL n = 0
END Bits;
PROCEDURE Enter*;
BEGIN
Machine.Acquire(Machine.KernelLog);
String("{P cpuid= "); Int(Machine.ID(), 0); String (", pid= "); Int (Objects.GetProcessID (), 0); Char (' ');
END Enter;
PROCEDURE Exit*;
BEGIN
Char("}"); Ln;
Machine.Release(Machine.KernelLog)
END Exit;
PROCEDURE SwitchToBuffer(adr: SYSTEM.ADDRESS; size: SYSTEM.SIZE);
VAR tail: SYSTEM.ADDRESS; c: CHAR;
BEGIN
tail := 0; ASSERT(size > 0);
WHILE (traceHead # traceTail) & (tail+1 # size) DO
SYSTEM.GET (traceBufAdr + traceHead, c);
SYSTEM.PUT (adr + tail, c);
traceHead := (traceHead+1) MOD traceBufSize;
INC(tail)
END;
traceBufAdr := adr; traceBufSize := size;
traceHead := 0; traceTail := tail
END SwitchToBuffer;
PROCEDURE OpenBuffer*(adr: SYSTEM.ADDRESS; size: SYSTEM.SIZE): BOOLEAN;
VAR ok: BOOLEAN;
BEGIN
Machine.Acquire(Machine.TraceOutput);
IF traceBufAdr = SYSTEM.ADR(traceBufDef[0]) THEN
SwitchToBuffer(adr, size); ok := TRUE
ELSE
ok := FALSE
END;
Machine.Release(Machine.TraceOutput);
RETURN ok
END OpenBuffer;
PROCEDURE GetBuffer*(VAR val: ARRAY OF CHAR);
VAR i, m: LONGINT;
BEGIN
i := 0; m := LEN(val)-1;
Machine.Acquire(Machine.TraceOutput);
WHILE (i < m) & (traceHead # traceTail) DO
val[i] := CHR(SYSTEM.GET8(traceBufAdr + traceHead));
traceHead := (traceHead+1) MOD traceBufSize;
INC(i)
END;
Machine.Release(Machine.TraceOutput);
val[i] := 0X
END GetBuffer;
PROCEDURE CloseBuffer*;
BEGIN
Machine.Acquire(Machine.TraceOutput);
IF traceBufAdr # SYSTEM.ADR(traceBufDef[0]) THEN
SwitchToBuffer(SYSTEM.ADR(traceBufDef[0]), LEN(traceBufDef))
END;
Machine.Release(Machine.TraceOutput)
END CloseBuffer;
BEGIN
traceBufAdr := SYSTEM.ADR(traceBufDef[0]);
traceBufSize := LEN(traceBufDef);
traceHead := 0; traceTail := 0; column := 0;
END KernelLog.
(**
Notes
This module provides low-level output facilities for Aos. It is similar to the Out module of Oberon, but it can be called from anywhere, even from active object bodies and interrupt handlers. It can write to the text display (when not using a graphics mode), a serial port, a memory buffer, or all of the above. This is controlled by the TraceMode and related config strings (see Aos.Par).
Typically, a memory buffer is used. The buffer is installed by the LogWindow.Open, or with the System.StartLog command when using Oberon. The latter is recommended, as it also interprets traps specially and opens a new viewer for them. The displaying of the buffer is done off-line by the LogWindow or Oberon threads, thereby allowing the procedures here to be called from anywhere.
Control characters:
0X end of string (can not be printed)
1X start of trap (if System.StartLog active then trap viewer will be opened and output redirected)
2X end of trap (if System.StartLog active then it will revert output to the kernel log text)
3X signal log overflow
9X TAB (or single space)
0DX CR (or NL and LF ignored)
0AX LF (ignored if CR is NL)
0EX set fixed-width font
0FX set proportial font (default)
*)
(*
TraceMode:
0 1 Screen
2 4 V24
*)
(*
03.03.1998 pjm First version
16.06.2000 pjm Cleaned up
29.11.2000 pjm buffering
12.06.2001 pjm moved Flags to Traps, moved SegDesc and TSS to AosFragments
*)