diff --git a/src/engine/e_log.pas b/src/engine/e_log.pas
index 6391f249786c757348f3cafde95974260b7994cf..a1ca45c21e6da75c2948a2a4c99a32b5dc66103d 100644 (file)
--- a/src/engine/e_log.pas
+++ b/src/engine/e_log.pas
-{$MODE DELPHI}
+(* Copyright (C) Doom 2D: Forever Developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *)
+{$INCLUDE ../shared/a_modes.inc}
{$R-}
{ $DEFINE CBLOG}
unit e_log;
type
TWriteMode = (WM_NEWFILE, WM_OLDFILE);
- TRecordCategory = (MSG_FATALERROR, MSG_WARNING, MSG_NOTIFY);
+ TMsgType = (Fatal, Warning, Notify);
procedure e_InitLog (fFileName: String; fWriteMode: TWriteMode);
-procedure e_WriteLog (TextLine: String; RecordCategory: TRecordCategory; WriteTime: Boolean=True);
-function DecodeIPV4 (ip: LongWord): string;
+procedure e_DeinitLog ();
+
+procedure e_SetSafeSlowLog (slowAndSafe: Boolean);
+
+procedure e_WriteLog (TextLine: String; RecordCategory: TMsgType; WriteTime: Boolean=True);
+function DecodeIPV4 (ip: LongWord): string;
// start Write/WriteLn driver. it will write everything to cbuf.
procedure e_InitWritelnDriver ();
+procedure e_LogWritefln (const fmt: AnsiString; args: array of const; category: TMsgType=TMsgType.Notify; writeTime: Boolean=true; writeConsole: Boolean=true);
+procedure e_LogWriteln (const s: AnsiString; category: TMsgType=TMsgType.Notify; writeTime: Boolean=true);
+
+
+procedure e_WriteStackTrace (const msg: AnsiString);
+
var
e_WriteToStdOut: Boolean = False;
implementation
uses
- conbuf;
-
+ {$IFDEF ANDROID}
+ SDL2,
+ {$ENDIF}
+ conbuf, utils;
var
FirstRecord: Boolean;
end;
-procedure e_WriteLog (TextLine: String; RecordCategory: TRecordCategory; WriteTime: Boolean=True);
+function consoleAllow (const s: String): Boolean;
+begin
+ Result := False;
+ if Pos('[Chat] ', s) = 1 then
+ Exit;
+ Result := True;
+end;
+
+
+procedure e_WriteLog (TextLine: String; RecordCategory: TMsgType; WriteTime: Boolean=True);
+begin
+ e_LogWritefln('%s', [TextLine], RecordCategory, WriteTime, consoleAllow(TextLine));
+end;
+
+
+procedure e_LogWriteln (const s: AnsiString; category: TMsgType=TMsgType.Notify; writeTime: Boolean=true);
+begin
+ e_LogWritefln('%s', [s], category, writeTime, consoleAllow(s));
+end;
+
+
+// returns formatted string if `writerCB` is `nil`, empty string otherwise
+//function formatstrf (const fmt: AnsiString; args: array of const; writerCB: TFormatStrFCallback=nil): AnsiString;
+//TFormatStrFCallback = procedure (constref buf; len: SizeUInt);
+
+procedure conwriter (constref buf; len: SizeUInt);
var
- LogFile: TextFile;
- Prefix: ShortString = '';
- OutStr: String;
+ ss: ShortString;
+ slen: Integer;
+ b: PByte;
+{$IFDEF ANDROID}
+ cstr: PChar;
+{$ENDIF}
begin
- if driverInited and (length(TextLine) > 0) then
+ if (len < 1) then exit;
+ b := PByte(@buf);
+
+{$IFDEF ANDROID}
+ cstr := GetMem(len + 1);
+ for slen := 0 to len - 1 do
+ cstr[slen] := Chr(b[slen]);
+ cstr[len] := #0;
+ SDL_Log(cstr, []);
+ Dispose(cstr);
+{$ENDIF}
+
+ while (len > 0) do
+ begin
+ if (len > 255) then slen := 255 else slen := Integer(len);
+ Move(b^, ss[1], slen);
+ ss[0] := AnsiChar(slen);
+ write(ss);
+ b += slen;
+ len -= slen;
+ end;
+end;
+
+
+var
+ xlogFile: TextFile;
+ xlogFileOpened: Boolean = false;
+ xlogPrefix: AnsiString;
+ xlogLastWasEOL: Boolean = false;
+ xlogWantSpace: Boolean = false;
+ xlogSlowAndSafe: Boolean = false;
+
+
+procedure e_SetSafeSlowLog (slowAndSafe: Boolean);
+begin
+ xlogSlowAndSafe := slowAndSafe;
+ if xlogSlowAndSafe and xlogFileOpened then
begin
- case RecordCategory of
- MSG_FATALERROR: write('FATAL: ');
- MSG_WARNING: write('WARNINIG: ');
+ CloseFile(xlogFile);
+ xlogFileOpened := false;
+ end;
+end;
+
+
+procedure logwriter (constref buf; len: SizeUInt);
+var
+ ss: ShortString;
+ slen: Integer;
+ b: PByte;
+begin
+ if (len < 1) then exit;
+ b := PByte(@buf);
+ if xlogLastWasEOL then
+ begin
+ write(xlogFile, xlogPrefix);
+ xlogLastWasEOL := false;
+ xlogWantSpace := true;
+ end;
+ while (len > 0) do
+ begin
+ slen := 0;
+ while (slen < len) and (b[slen] <> 13) and (b[slen] <> 10) do Inc(slen);
+ if (slen > 255) then slen := 255;
+ // print string
+ if (slen > 0) then
+ begin
+ if xlogWantSpace then begin write(xlogFile, ' '); xlogWantSpace := false; end;
+ Move(b^, ss[1], slen);
+ ss[0] := AnsiChar(slen);
+ write(xlogFile, ss);
+ b += slen;
+ len -= slen;
+ continue;
+ end;
+ // process newline
+ if (len > 0) and ((b[0] = 13) or (b[0] = 10)) then
+ begin
+ if (b[0] = 13) then begin len -= 1; b += 1; end;
+ if (len > 0) and (b[0] = 10) then begin len -= 1; b += 1; end;
+ xlogLastWasEOL := false;
+ writeln(xlogFile, '');
+ write(xlogFile, xlogPrefix);
end;
- writeln(TextLine);
end;
+end;
+
- if FileName = '' then Exit;
+procedure e_LogWritefln (const fmt: AnsiString; args: array of const; category: TMsgType=TMsgType.Notify; writeTime: Boolean=true; writeConsole: Boolean=true);
- Assign(LogFile, FileName);
- try
- if FileExists(FileName) then
- Append(LogFile)
- else
- Rewrite(LogFile);
+ procedure xwrite (const s: AnsiString);
+ begin
+ if (Length(s) = 0) then exit;
+ logwriter(PAnsiChar(s)^, Length(s));
+ end;
+
+begin
+ if driverInited and (length(fmt) > 0) and writeConsole then
+ begin
+ case category of
+ TMsgType.Fatal: write('FATAL: ');
+ TMsgType.Warning: write('WARNING: ');
+ end;
+ formatstrf(fmt, args, conwriter);
+ writeln;
+ end;
+
+ if (FileName = '') then exit;
+
+ if not xlogFileOpened then
+ begin
+ AssignFile(xlogFile, FileName);
try
- if FirstRecord then
- begin
- Writeln(LogFile, '--- Log started at '+TimeToStr(Time)+' ---');
- FirstRecord := False;
- end;
- case RecordCategory of
- MSG_FATALERROR: Prefix := '!!!';
- MSG_WARNING: Prefix := '! ';
- MSG_NOTIFY: Prefix := '***';
- end;
- if WriteTime then
- OutStr := '['+TimeToStr(Time)+'] '+Prefix+' '+TextLine
- else
- OutStr := Prefix+' '+TextLine;
- Writeln(LogFile, OutStr);
- if e_WriteToStdOut then
- Writeln(OutStr);
- finally
- Close(LogFile);
+ if FileExists(FileName) then Append(xlogFile) else Rewrite(xlogFile);
+ xlogFileOpened := true;
+ except // sorry
+ exit;
end;
- except // sorry
end;
+
+ if FirstRecord then
+ begin
+ writeln(xlogFile, '--- Log started at ', TimeToStr(Time), ' ---');
+ FirstRecord := false;
+ end;
+
+ xlogPrefix := '';
+ if writeTime then begin xlogPrefix += '['; xlogPrefix += TimeToStr(Time); xlogPrefix += '] '; end;
+ case category of
+ TMsgType.Fatal: xlogPrefix += '!!!';
+ TMsgType.Warning: xlogPrefix += '! ';
+ TMsgType.Notify: xlogPrefix += '***';
+ end;
+ xlogLastWasEOL := true; // to output prefix
+ xlogWantSpace := true; // after prefix
+ formatstrf(fmt, args, logwriter);
+ if not xlogLastWasEOL then writeln(xlogFile, '') else writeln(xlogFile, xlogPrefix);
+
+ if xlogSlowAndSafe and xlogFileOpened then
+ begin
+ CloseFile(xlogFile);
+ xlogFileOpened := false;
+ end;
+
+ //if fopened then CloseFile(xlogFile);
end;
procedure e_InitLog (fFileName: String; fWriteMode: TWriteMode);
begin
- FileName := fFileName;
- if fWriteMode = WM_NEWFILE then
- begin
- try
- if FileExists(FileName) then DeleteFile(FileName);
- except // sorry
- end;
- end;
- FirstRecord := True;
+ if xlogFileOpened then CloseFile(xlogFile);
+ xlogFileOpened := false;
+ FileName := fFileName;
+ if (fWriteMode = TWriteMode.WM_NEWFILE) then
+ begin
+ try
+ if FileExists(FileName) then DeleteFile(FileName);
+ except // sorry
+ end;
+ end;
+ FirstRecord := true;
+end;
+
+
+{$I-}
+procedure e_WriteStackTrace (const msg: AnsiString);
+var
+ tfo: TextFile;
+begin
+ e_LogWriteln(msg, TMsgType.Fatal);
+ if (Length(FileName) > 0) then
+ begin
+ if xlogFileOpened then CloseFile(xlogFile);
+ xlogFileOpened := false;
+ AssignFile(tfo, FileName);
+ Append(tfo);
+ if (IOResult <> 0) then Rewrite(tfo);
+ if (IOResult = 0) then begin writeln(tfo, '====================='); DumpExceptionBackTrace(tfo); CloseFile(tfo); end;
+ end;
+end;
+
+
+procedure e_DeinitLog ();
+begin
+ if xlogFileOpened then CloseFile(xlogFile);
+ xlogFileOpened := false;
end;
begin
- e_InitWritelnDriver();
+ //e_InitWritelnDriver();
end.