(* BSD 2-Clause License Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) MODULE HOST; IMPORT SYSTEM, RTL; CONST slash* = "\"; OS* = "WINDOWS"; bit_depth* = RTL.bit_depth; maxint* = RTL.maxint; minint* = RTL.minint; MAX_PARAM = 1024; OFS_MAXPATHNAME = 128; TYPE POverlapped = POINTER TO OVERLAPPED; OVERLAPPED = RECORD Internal: INTEGER; InternalHigh: INTEGER; Offset: INTEGER; OffsetHigh: INTEGER; hEvent: INTEGER END; OFSTRUCT = RECORD cBytes: CHAR; fFixedDisk: CHAR; nErrCode: SYSTEM.CARD16; Reserved1: SYSTEM.CARD16; Reserved2: SYSTEM.CARD16; szPathName: ARRAY OFS_MAXPATHNAME OF CHAR END; PSecurityAttributes = POINTER TO TSecurityAttributes; TSecurityAttributes = RECORD nLength: INTEGER; lpSecurityDescriptor: INTEGER; bInheritHandle: INTEGER END; TSystemTime = RECORD Year, Month, DayOfWeek, Day, Hour, Min, Sec, MSec: WCHAR END; VAR hConsoleOutput: INTEGER; Params: ARRAY MAX_PARAM, 2 OF INTEGER; argc: INTEGER; eol*: ARRAY 3 OF CHAR; PROCEDURE [windows-, "kernel32.dll", "GetTickCount"] _GetTickCount (): INTEGER; PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] _GetStdHandle (nStdHandle: INTEGER): INTEGER; PROCEDURE [windows-, "kernel32.dll", "GetCommandLineA"] _GetCommandLine (): INTEGER; PROCEDURE [windows-, "kernel32.dll", "ReadFile"] _ReadFile (hFile, Buffer, nNumberOfBytesToRW: INTEGER; VAR NumberOfBytesRW: INTEGER; lpOverlapped: POverlapped): INTEGER; PROCEDURE [windows-, "kernel32.dll", "WriteFile"] _WriteFile (hFile, Buffer, nNumberOfBytesToRW: INTEGER; VAR NumberOfBytesRW: INTEGER; lpOverlapped: POverlapped): INTEGER; PROCEDURE [windows-, "kernel32.dll", "CloseHandle"] _CloseHandle (hObject: INTEGER): INTEGER; PROCEDURE [windows-, "kernel32.dll", "CreateFileA"] _CreateFile ( lpFileName, dwDesiredAccess, dwShareMode: INTEGER; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile: INTEGER): INTEGER; PROCEDURE [windows-, "kernel32.dll", "OpenFile"] _OpenFile (lpFileName: INTEGER; lpReOpenBuff: OFSTRUCT; uStyle: INTEGER): INTEGER; PROCEDURE [windows-, "kernel32.dll", "GetCurrentDirectoryA"] _GetCurrentDirectory (nBufferLength, lpBuffer: INTEGER): INTEGER; PROCEDURE [windows-, "kernel32.dll", "GetSystemTime"] _GetSystemTime (T: TSystemTime); PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] _ExitProcess (code: INTEGER); PROCEDURE ExitProcess* (code: INTEGER); BEGIN _ExitProcess(code) END ExitProcess; PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); VAR n: INTEGER; BEGIN n := _GetCurrentDirectory(LEN(path), SYSTEM.ADR(path[0])); path[n] := slash; path[n + 1] := 0X END GetCurrentDirectory; PROCEDURE GetChar (adr: INTEGER): CHAR; VAR res: CHAR; BEGIN SYSTEM.GET(adr, res) RETURN res END GetChar; PROCEDURE ParamParse; VAR p, count, cond: INTEGER; c: CHAR; PROCEDURE ChangeCond (A, B, C: INTEGER; VAR cond: INTEGER; c: CHAR); BEGIN IF (c <= 20X) & (c # 0X) THEN cond := A ELSIF c = 22X THEN cond := B ELSIF c = 0X THEN cond := 6 ELSE cond := C END END ChangeCond; BEGIN p := _GetCommandLine(); cond := 0; count := 0; WHILE (count < MAX_PARAM) & (cond # 6) DO c := GetChar(p); CASE cond OF |0: ChangeCond(0, 4, 1, cond, c); IF cond = 1 THEN Params[count, 0] := p END |1: ChangeCond(0, 3, 1, cond, c); IF cond IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END |3: ChangeCond(3, 1, 3, cond, c); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END |4: ChangeCond(5, 0, 5, cond, c); IF cond = 5 THEN Params[count, 0] := p END |5: ChangeCond(5, 1, 5, cond, c); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END |6: END; INC(p) END; argc := count END ParamParse; PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); VAR i, j, len: INTEGER; c: CHAR; BEGIN j := 0; IF n < argc THEN len := LEN(s) - 1; i := Params[n, 0]; WHILE (j < len) & (i <= Params[n, 1]) DO c := GetChar(i); IF c # 22X THEN s[j] := c; INC(j) END; INC(i) END END; s[j] := 0X END GetArg; PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; VAR res, n: INTEGER; BEGIN IF _ReadFile(F, SYSTEM.ADR(Buffer[0]), bytes, n, NIL) = 0 THEN res := -1 ELSE res := n END RETURN res END FileRead; PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; VAR res, n: INTEGER; BEGIN IF _WriteFile(F, SYSTEM.ADR(Buffer[0]), bytes, n, NIL) = 0 THEN res := -1 ELSE res := n END RETURN res END FileWrite; PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; RETURN _CreateFile(SYSTEM.ADR(FName[0]), 0C0000000H, 0, NIL, 2, 80H, 0) END FileCreate; PROCEDURE FileClose* (F: INTEGER); BEGIN _CloseHandle(F) END FileClose; PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; VAR ofstr: OFSTRUCT; res: INTEGER; BEGIN res := _OpenFile(SYSTEM.ADR(FName[0]), ofstr, 0); IF res = 0FFFFFFFFH THEN res := -1 END RETURN res END FileOpen; PROCEDURE OutChar* (c: CHAR); VAR count: INTEGER; BEGIN _WriteFile(hConsoleOutput, SYSTEM.ADR(c), 1, count, NIL) END OutChar; PROCEDURE GetTickCount* (): INTEGER; RETURN _GetTickCount() DIV 10 END GetTickCount; PROCEDURE letter (c: CHAR): BOOLEAN; RETURN ("a" <= c) & (c <= "z") OR ("A" <= c) & (c <= "Z") END letter; PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; RETURN ~(letter(path[0]) & (path[1] = ":")) END isRelative; PROCEDURE now* (VAR year, month, day, hour, min, sec: INTEGER); VAR T: TSystemTime; BEGIN _GetSystemTime(T); year := ORD(T.Year); month := ORD(T.Month); day := ORD(T.Day); hour := ORD(T.Hour); min := ORD(T.Min); sec := ORD(T.Sec) END now; PROCEDURE UnixTime* (): INTEGER; RETURN 0 END UnixTime; PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; VAR res: INTEGER; BEGIN a := 0; b := 0; SYSTEM.MOVE(SYSTEM.ADR(x), SYSTEM.ADR(a), 4); SYSTEM.MOVE(SYSTEM.ADR(x) + 4, SYSTEM.ADR(b), 4); SYSTEM.GET(SYSTEM.ADR(x), res) RETURN res END splitf; BEGIN eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; hConsoleOutput := _GetStdHandle(-11); ParamParse END HOST.