(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov All rights reserved. *) MODULE UTILS; IMPORT HOST; CONST slash* = HOST.slash; bit_depth* = HOST.bit_depth; maxint* = HOST.maxint; minint* = HOST.minint; OS = HOST.OS; min32* = -2147483647-1; max32* = 2147483647; TYPE DAYS = ARRAY 12, 31, 2 OF INTEGER; VAR time*: INTEGER; eol*: ARRAY 3 OF CHAR; maxreal*: REAL; target*: RECORD bit_depth*, maxInt*, minInt*, maxSet*, maxHex*: INTEGER; maxReal*: REAL END; bit_diff*: INTEGER; days: DAYS; PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; RETURN HOST.FileRead(F, Buffer, bytes) END FileRead; PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; RETURN HOST.FileWrite(F, Buffer, bytes) END FileWrite; PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; RETURN HOST.FileCreate(FName) END FileCreate; PROCEDURE FileClose* (F: INTEGER); BEGIN HOST.FileClose(F) END FileClose; PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; RETURN HOST.FileOpen(FName) END FileOpen; PROCEDURE GetArg* (i: INTEGER; VAR str: ARRAY OF CHAR); BEGIN HOST.GetArg(i, str) END GetArg; PROCEDURE Exit* (code: INTEGER); BEGIN HOST.ExitProcess(code) END Exit; PROCEDURE GetTickCount* (): INTEGER; RETURN HOST.GetTickCount() END GetTickCount; PROCEDURE OutChar* (c: CHAR); BEGIN HOST.OutChar(c) END OutChar; PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; RETURN HOST.splitf(x, a, b) END splitf; PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; RETURN HOST.isRelative(path) END isRelative; PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); BEGIN HOST.GetCurrentDirectory(path) END GetCurrentDirectory; PROCEDURE GetUnixTime* (year, month, day, hour, min, sec: INTEGER): INTEGER; RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec END GetUnixTime; PROCEDURE UnixTime* (): INTEGER; VAR year, month, day, hour, min, sec: INTEGER; res: INTEGER; BEGIN IF OS = "LINUX" THEN res := HOST.UnixTime() ELSE HOST.now(year, month, day, hour, min, sec); res := GetUnixTime(year, month, day, hour, min, sec) END RETURN res END UnixTime; PROCEDURE SetBitDepth* (BitDepth: INTEGER); BEGIN ASSERT((BitDepth = 16) OR (BitDepth = 32) OR (BitDepth = 64)); bit_diff := bit_depth - BitDepth; ASSERT(bit_diff >= 0); target.bit_depth := BitDepth; target.maxSet := BitDepth - 1; target.maxHex := BitDepth DIV 4; target.minInt := ASR(minint, bit_diff); target.maxInt := ASR(maxint, bit_diff); target.maxReal := 1.9; PACK(target.maxReal, 1023); END SetBitDepth; PROCEDURE Byte* (n: INTEGER; idx: INTEGER): BYTE; RETURN ASR(n, 8 * idx) MOD 256 END Byte; PROCEDURE Align* (VAR bytes: INTEGER; align: INTEGER): BOOLEAN; VAR res: BOOLEAN; BEGIN IF bytes MOD align # 0 THEN res := maxint - bytes >= align - (bytes MOD align); IF res THEN bytes := bytes + align - (bytes MOD align) END ELSE res := TRUE END RETURN res END Align; PROCEDURE Long* (value: INTEGER): INTEGER; RETURN ASR(LSL(value, bit_diff), bit_diff) END Long; PROCEDURE Short* (value: INTEGER): INTEGER; RETURN LSR(LSL(value, bit_diff), bit_diff) END Short; PROCEDURE Log2* (x: INTEGER): INTEGER; VAR n: INTEGER; BEGIN ASSERT(x > 0); n := 0; WHILE ~ODD(x) DO x := x DIV 2; INC(n) END; IF x # 1 THEN n := -1 END RETURN n END Log2; PROCEDURE init (VAR days: DAYS); VAR i, j, n0, n1: INTEGER; BEGIN FOR i := 0 TO 11 DO FOR j := 0 TO 30 DO days[i, j, 0] := 0; days[i, j, 1] := 0; END END; days[ 1, 28, 0] := -1; FOR i := 0 TO 1 DO days[ 1, 29, i] := -1; days[ 1, 30, i] := -1; days[ 3, 30, i] := -1; days[ 5, 30, i] := -1; days[ 8, 30, i] := -1; days[10, 30, i] := -1; END; n0 := 0; n1 := 0; FOR i := 0 TO 11 DO FOR j := 0 TO 30 DO IF days[i, j, 0] = 0 THEN days[i, j, 0] := n0; INC(n0) END; IF days[i, j, 1] = 0 THEN days[i, j, 1] := n1; INC(n1) END END END END init; BEGIN time := GetTickCount(); COPY(HOST.eol, eol); maxreal := 1.9; PACK(maxreal, 1023); init(days) END UTILS.