1,418 → 1,120 |
(* |
Copyright 2016, 2017 Anton Krotov |
(* |
BSD 2-Clause License |
|
This file is part of Compiler. |
|
Compiler 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. |
|
Compiler 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 Compiler. If not, see <http://www.gnu.org/licenses/>. |
Copyright (c) 2018, 2019, Anton Krotov |
All rights reserved. |
*) |
|
MODULE UTILS; |
|
IMPORT sys := SYSTEM, H := HOST, ERRORS; |
IMPORT HOST, UNIXTIME; |
|
|
CONST |
|
OS* = H.OS; |
Slash* = H.Slash; |
Ext* = ".ob07"; |
MAX_PATH = 1024; |
MAX_PARAM = 1024; |
Date* = 1509580800; (* 2017-11-02 *) |
slash* = HOST.slash; |
|
TYPE |
bit_depth* = HOST.bit_depth; |
maxint* = HOST.maxint; |
minint* = HOST.minint; |
|
STRING* = ARRAY MAX_PATH OF CHAR; |
OS = HOST.OS; |
|
ITEM* = POINTER TO rITEM; |
|
rITEM* = RECORD |
Next*, Prev*: ITEM |
END; |
VAR |
|
LIST* = POINTER TO RECORD |
First*, Last*: ITEM; |
Count*: INTEGER |
END; |
time*: INTEGER; |
|
STRCONST* = POINTER TO RECORD (rITEM) |
Str*: STRING; |
Len*, Number*: INTEGER |
END; |
eol*: ARRAY 3 OF CHAR; |
|
VAR |
maxreal*: REAL; |
|
Params: ARRAY MAX_PARAM, 2 OF INTEGER; |
ParamCount*, Line*, Unit*: INTEGER; |
FileName: STRING; |
|
PROCEDURE SetFile*(F: STRING); |
BEGIN |
FileName := F |
END SetFile; |
PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; |
RETURN HOST.FileRead(F, Buffer, bytes) |
END FileRead; |
|
PROCEDURE IsInf*(x: LONGREAL): BOOLEAN; |
RETURN ABS(x) = sys.INF(LONGREAL) |
END IsInf; |
|
PROCEDURE GetChar(adr: INTEGER): CHAR; |
VAR res: CHAR; |
BEGIN |
sys.GET(adr, res) |
RETURN res |
END GetChar; |
PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; |
RETURN HOST.FileWrite(F, Buffer, bytes) |
END FileWrite; |
|
PROCEDURE ParamParse(count: INTEGER); |
VAR c: CHAR; cond, p: INTEGER; |
|
PROCEDURE ChangeCond(A, B, C: INTEGER); |
BEGIN |
cond := C; |
CASE c OF |
|0X: cond := 6 |
|1X..20X: cond := A |
|22X: cond := B |
ELSE |
END |
END ChangeCond; |
PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; |
RETURN HOST.FileCreate(FName) |
END FileCreate; |
|
BEGIN |
p := H.GetCommandLine(); |
cond := 0; |
WHILE (count < MAX_PARAM) & (cond # 6) DO |
c := GetChar(p); |
CASE cond OF |
|0: ChangeCond(0, 4, 1); IF cond = 1 THEN Params[count, 0] := p END |
|4: ChangeCond(5, 0, 5); IF cond = 5 THEN Params[count, 0] := p END |
|1: ChangeCond(0, 3, 1); IF cond IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END |
|3, 5: ChangeCond(cond, 1, cond); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END |
ELSE |
END; |
INC(p) |
END; |
ParamCount := count - 1 |
END ParamParse; |
|
PROCEDURE ParamStr*(VAR str: ARRAY OF CHAR; n: INTEGER); |
VAR i, j, len: INTEGER; c: CHAR; |
PROCEDURE FileClose* (F: INTEGER); |
BEGIN |
j := 0; |
IF n <= ParamCount THEN |
len := LEN(str) - 1; |
i := Params[n, 0]; |
WHILE (j < len) & (i <= Params[n, 1]) DO |
c := GetChar(i); |
IF c # 22X THEN |
str[j] := c; |
INC(j) |
END; |
INC(i) |
END |
END; |
str[j] := 0X |
END ParamStr; |
HOST.FileClose(F) |
END FileClose; |
|
PROCEDURE GetMem*(n: INTEGER): INTEGER; |
RETURN H.malloc(n) |
END GetMem; |
|
PROCEDURE CloseF*(F: INTEGER); |
BEGIN |
H.CloseFile(F) |
END CloseF; |
PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; |
RETURN HOST.FileOpen(FName) |
END FileOpen; |
|
PROCEDURE Read*(F, Buffer, Count: INTEGER): INTEGER; |
RETURN H.FileRW(F, Buffer, Count, FALSE) |
END Read; |
|
PROCEDURE Write*(F, Buffer, Count: INTEGER): INTEGER; |
RETURN H.FileRW(F, Buffer, Count, TRUE) |
END Write; |
|
PROCEDURE FileSize*(F: INTEGER): INTEGER; |
RETURN H.FileSize(F) |
END FileSize; |
|
PROCEDURE CharC*(x: CHAR); |
VAR str: ARRAY 2 OF CHAR; |
PROCEDURE GetArg* (i: INTEGER; VAR str: ARRAY OF CHAR); |
BEGIN |
str[0] := x; |
str[1] := 0X; |
H.OutString(str) |
END CharC; |
HOST.GetArg(i, str) |
END GetArg; |
|
PROCEDURE Int*(x: INTEGER); |
VAR i: INTEGER; buf: ARRAY 11 OF INTEGER; |
BEGIN |
i := 0; |
REPEAT |
buf[i] := x MOD 10; |
x := x DIV 10; |
INC(i) |
UNTIL x = 0; |
REPEAT |
DEC(i); |
CharC(CHR(buf[i] + ORD("0"))) |
UNTIL i = 0 |
END Int; |
|
PROCEDURE Ln*; |
PROCEDURE Exit* (code: INTEGER); |
BEGIN |
CharC(0DX); |
CharC(0AX) |
END Ln; |
HOST.ExitProcess(code) |
END Exit; |
|
PROCEDURE OutString*(str: ARRAY OF CHAR); |
BEGIN |
H.OutString(str) |
END OutString; |
|
PROCEDURE ErrMsg*(code: INTEGER); |
VAR str: ARRAY 1024 OF CHAR; |
BEGIN |
ERRORS.ErrorMsg(code, str); |
OutString("error: ("); Int(code); OutString(") "); OutString(str); Ln |
END ErrMsg; |
PROCEDURE GetTickCount* (): INTEGER; |
RETURN HOST.GetTickCount() |
END GetTickCount; |
|
PROCEDURE ErrMsgPos*(line, col, code: INTEGER); |
VAR s: STRING; |
BEGIN |
ErrMsg(code); |
OutString("file: "); OutString(FileName); Ln; |
OutString("line: "); Int(line); Ln; |
OutString("pos: "); Int(col); Ln; |
END ErrMsgPos; |
|
PROCEDURE UnitLine*(newUnit, newLine: INTEGER); |
PROCEDURE OutChar* (c: CHAR); |
BEGIN |
Unit := newUnit; |
Line := newLine |
END UnitLine; |
HOST.OutChar(c) |
END OutChar; |
|
PROCEDURE Align*(n: INTEGER): INTEGER; |
RETURN (4 - n MOD 4) MOD 4 |
END Align; |
|
PROCEDURE CAP(x: CHAR): CHAR; |
BEGIN |
IF (x >= "a") & (x <= "z") THEN |
x := CHR(ORD(x) - 32) |
END |
RETURN x |
END CAP; |
PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; |
RETURN HOST.splitf(x, a, b) |
END splitf; |
|
PROCEDURE streq*(a, b: ARRAY OF CHAR): BOOLEAN; |
VAR i: INTEGER; |
BEGIN |
i := -1; |
REPEAT |
INC(i) |
UNTIL (CAP(a[i]) # CAP(b[i])) OR (a[i] = 0X) OR (b[i] = 0X) |
RETURN a[i] = b[i] |
END streq; |
|
PROCEDURE concat*(VAR L: STRING; R: STRING); |
VAR i, n, pos: INTEGER; |
BEGIN |
n := LENGTH(R); |
i := 0; |
pos := LENGTH(L); |
WHILE (i <= n) & (pos < LEN(L)) DO |
L[pos] := R[i]; |
INC(pos); |
INC(i) |
END |
END concat; |
PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; |
RETURN HOST.isRelative(path) |
END isRelative; |
|
PROCEDURE GetStr*(this: LIST; str: STRING): STRCONST; |
VAR res: STRCONST; |
BEGIN |
res := this.First(STRCONST); |
WHILE (res # NIL) & (res.Str # str) DO |
res := res.Next(STRCONST) |
END |
RETURN res |
END GetStr; |
|
PROCEDURE Push*(this: LIST; item: ITEM); |
PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); |
BEGIN |
IF this.Count = 0 THEN |
this.First := item; |
item.Prev := NIL |
ELSE |
this.Last.Next := item; |
item.Prev := this.Last |
END; |
INC(this.Count); |
this.Last := item; |
item.Next := NIL |
END Push; |
HOST.GetCurrentDirectory(path) |
END GetCurrentDirectory; |
|
PROCEDURE Insert*(this: LIST; item, prev: ITEM); |
BEGIN |
IF prev # this.Last THEN |
item.Next := prev.Next; |
item.Prev := prev; |
prev.Next := item; |
item.Next.Prev := item; |
INC(this.Count) |
ELSE |
Push(this, item) |
END |
END Insert; |
|
PROCEDURE Clear*(this: LIST); |
BEGIN |
this.First := NIL; |
this.Last := NIL; |
this.Count := 0 |
END Clear; |
PROCEDURE UnixTime* (): INTEGER; |
VAR |
year, month, day, hour, min, sec: INTEGER; |
res: INTEGER; |
|
PROCEDURE Revers(VAR str: STRING); |
VAR a, b: INTEGER; c: CHAR; |
BEGIN |
a := 0; |
b := LENGTH(str) - 1; |
WHILE a < b DO |
c := str[a]; |
str[a] := str[b]; |
str[b] := c; |
INC(a); |
DEC(b) |
END |
END Revers; |
|
PROCEDURE Split*(FName: STRING; VAR Path, Name, Ext: STRING); |
VAR i, j, k: INTEGER; |
BEGIN |
i := LENGTH(FName) - 1; |
j := 0; |
WHILE (i >= 0) & (FName[i] # Slash) DO |
Name[j] := FName[i]; |
DEC(i); |
INC(j) |
END; |
Name[j] := 0X; |
Revers(Name); |
j := 0; |
k := LENGTH(Name) - 1; |
WHILE (k >= 0) & (Name[k] # ".") DO |
Ext[j] := Name[k]; |
DEC(k); |
INC(j) |
END; |
IF k >= 0 THEN |
Name[k] := 0X; |
Ext[j] := "."; |
INC(j) |
IF OS = "LINUX" THEN |
res := HOST.UnixTime() |
ELSE |
j := 0 |
END; |
Ext[j] := 0X; |
Revers(Ext); |
FOR j := 0 TO i DO |
Path[j] := FName[j] |
END; |
Path[i + 1] := 0X |
END Split; |
|
PROCEDURE LinuxParam; |
VAR p, i, str: INTEGER; c: CHAR; |
BEGIN |
p := H.GetCommandLine(); |
sys.GET(p, ParamCount); |
sys.GET(p + 4, p); |
FOR i := 0 TO ParamCount - 1 DO |
sys.GET(p + i * 4, str); |
Params[i, 0] := str; |
REPEAT |
sys.GET(str, c); |
INC(str) |
UNTIL c = 0X; |
Params[i, 1] := str - 1 |
END; |
DEC(ParamCount) |
END LinuxParam; |
|
PROCEDURE Time*; |
VAR sec, dsec: INTEGER; |
BEGIN |
OutString("elapsed time "); |
H.Time(sec, dsec); |
sec := sec - H.sec; |
dsec := dsec - H.dsec; |
dsec := dsec + sec * 100; |
Int(dsec DIV 100); CharC("."); |
dsec := dsec MOD 100; |
IF dsec < 10 THEN |
Int(0) |
END; |
Int(dsec); OutString(" sec"); Ln |
END Time; |
|
PROCEDURE HALT*(n: INTEGER); |
BEGIN |
Time; |
H.ExitProcess(n) |
END HALT; |
|
PROCEDURE MemErr*(err: BOOLEAN); |
BEGIN |
IF err THEN |
ErrMsg(72); |
HALT(1) |
HOST.now(year, month, day, hour, min, sec); |
res := UNIXTIME.time(year, month, day, hour, min, sec) |
END |
END MemErr; |
|
PROCEDURE CreateList*(): LIST; |
VAR nov: LIST; |
BEGIN |
NEW(nov); |
MemErr(nov = NIL) |
RETURN nov |
END CreateList; |
RETURN res |
END UnixTime; |
|
PROCEDURE CreateF*(FName: ARRAY OF CHAR): INTEGER; |
RETURN H.CreateFile(FName) |
END CreateF; |
|
PROCEDURE OpenF*(FName: ARRAY OF CHAR(*; Mode: INTEGER*)): INTEGER; |
RETURN H.OpenFile(FName) |
END OpenF; |
|
PROCEDURE Init; |
VAR p: INTEGER; |
|
PROCEDURE last(VAR p: INTEGER); |
BEGIN |
WHILE GetChar(p) # 0X DO INC(p) END; |
DEC(p) |
END last; |
|
BEGIN |
H.init; |
IF OS = "WIN" THEN |
ParamParse(0) |
ELSIF OS = "KOS" THEN |
ParamParse(1); |
Params[0, 0] := H.GetName(); |
Params[0, 1] := Params[0, 0]; |
last(Params[0, 1]) |
ELSIF OS = "LNX" THEN |
LinuxParam |
END |
END Init; |
|
BEGIN |
Init |
time := GetTickCount(); |
COPY(HOST.eol, eol); |
maxreal := 1.9; |
PACK(maxreal, 1023) |
END UTILS. |