SDK/Lib/System.pas

507 lines
12 KiB
ObjectPascal
Raw Normal View History

2020-05-22 00:01:43 +02:00
(*
KolibriOS RTL System unit
2020-05-22 00:01:43 +02:00
*)
unit System;
interface
2020-06-18 20:27:19 +02:00
const
RTLVersion = CompilerVersion;
UnicodeCompiler = CompilerVersion >= 20;
2020-06-18 20:30:35 +02:00
2020-05-22 00:01:43 +02:00
type
PPAnsiChar = ^PAnsiChar;
2020-05-22 00:01:43 +02:00
KolibriChar = AnsiChar;
PKolibriChar = PAnsiChar;
PPKolibriChar = PPAnsiChar;
KolibriString = AnsiString;
{$IF CompilerVersion < 15}
UInt64 = Int64;
{$IFEND}
THandle = LongWord;
PByte = ^Byte;
PWord = ^Word;
PLongWord = ^LongWord;
PLongInt = ^LongInt;
PInt64 = ^Int64;
2020-06-09 22:03:10 +02:00
{$IF CompilerVersion >= 15}
PUInt64 = ^UInt64;
{$IFEND}
PCardinal = ^Cardinal;
PInteger = ^Integer;
PExtended = ^Extended;
PCurrency = ^Currency;
PShortString = ^ShortString;
PVariant = ^Variant;
2020-05-22 00:01:43 +02:00
TGUID = record
D1: LongWord;
D2: Word;
D3: Word;
D4: array [0..7] of Byte;
end;
PProcedure = procedure;
TPackageUnitEntry = packed record
Init, Finalize: PProcedure;
end;
PUnitEntryTable = ^TUnitEntryTable;
TUnitEntryTable = array [0..99999999] of TPackageUnitEntry;
PPackageInfo = ^TPackageInfo;
TPackageInfo = packed record
UnitCount: Integer;
UnitInfo: PUnitEntryTable;
end;
2020-05-22 00:01:43 +02:00
PInitContext = ^TInitContext;
TInitContext = record
InitTable: PPackageInfo;
InitCount: Integer;
2020-05-22 00:01:43 +02:00
OuterContext: PInitContext;
end;
const
vtInteger = 0;
vtBoolean = 1;
vtChar = 2;
vtExtended = 3;
vtString = 4;
vtPointer = 5;
vtPChar = 6;
vtObject = 7;
vtClass = 8;
vtWideChar = 9;
vtPWideChar = 10;
vtAnsiString = 11;
vtCurrency = 12;
vtVariant = 13;
vtInterface = 14;
vtWideString = 15;
vtInt64 = 16;
2020-06-18 20:30:35 +02:00
{$IFDEF UnicodeCompiler}
vtUnicodeString = 17;
{$ENDIF}
2020-06-09 22:03:10 +02:00
type
PVarRec = ^TVarRec;
TVarRec = record
case Byte of
vtInteger: (VInteger: Integer; VType: Byte);
vtBoolean: (VBoolean: Boolean);
vtChar: (VChar: KolibriChar);
vtExtended: (VExtended: PExtended);
vtString: (VString: PShortString);
vtPointer: (VPointer: Pointer);
vtPChar: (VPChar: PKolibriChar);
vtObject: (VObject: Pointer);
vtClass: (VClass: Pointer);
vtWideChar: (VWideChar: WideChar);
vtPWideChar: (VPWideChar: PWideChar);
vtAnsiString: (VAnsiString: Pointer);
vtCurrency: (VCurrency: PCurrency);
vtVariant: (VVariant: PVariant);
vtInterface: (VInterface: Pointer);
vtWideString: (VWideString: Pointer);
vtInt64: (VInt64: PInt64);
2020-06-18 20:30:35 +02:00
{$IFDEF UnicodeCompiler}
vtUnicodeString: (VUnicodeString: Pointer);
{$ENDIF}
end;
PTextBuf = ^TTextBuf;
TTextBuf = array[0..127] of KolibriChar;
TTextRec = packed record
Handle: THandle;
Mode, Flags: Word;
BufSize, BufPos, BufEnd: Cardinal;
BufPtr: PKolibriChar;
OpenFunc, InOutFunc, FlushFunc, CloseFunc: Pointer;
UserData: array[1..32] of Byte;
Name: array[0..259] of Char;
Buffer: TTextBuf;
end;
procedure _Halt0;
2020-05-22 00:01:43 +02:00
procedure _HandleFinally;
procedure _StartExe(InitTable: PPackageInfo);
2020-05-22 00:01:43 +02:00
2020-06-21 23:42:17 +02:00
var
Default8087CW: Word = $1332; // for Extended type
function Get8087CW: Word;
procedure Set8087CW(Value: Word);
2020-06-21 23:53:37 +02:00
var
RandSeed: LongWord;
RandCounter: LongWord;
2020-12-26 23:51:04 +01:00
function _RandInt(Range: LongInt): LongInt;
2020-06-21 23:53:37 +02:00
function _RandExt: Extended;
procedure Randomize;
2020-06-21 22:02:21 +02:00
function UpCase(Ch: KolibriChar): KolibriChar;
function _LStrLen(const S: KolibriString): LongInt;
function _LStrToPChar(const S: KolibriString): PKolibriChar;
var
IOResult: Integer;
Input, Output: Text;
2020-12-26 23:34:54 +01:00
IsConsole: Boolean;
function _Flush(var T: TTextRec): Integer;
procedure __IOTest;
function _ReadChar(var T: TTextRec): KolibriChar;
procedure _ReadCString(var T: TTextRec; Str: PKolibriChar; MaxLength: LongInt);
procedure _ReadString(var T: TTextRec; Str: PShortString; MaxLength: LongInt);
procedure _ReadLn(var T: TTextRec);
procedure _Write0Bool(var T: TTextRec; Value: Boolean);
procedure _Write0Char(var T: TTextRec; Ch: KolibriChar);
procedure _Write0Long(var T: TTextRec; Value: LongInt);
procedure _Write0String(var T: TTextRec; const S: ShortString);
procedure _Write0CString(var T: TTextRec; S: PKolibriChar);
procedure _Write0LString(var T: TTextRec; const S: KolibriString);
procedure _WriteBool(var T: TTextRec; Value: Boolean; Width: LongInt);
procedure _WriteChar(var T: TTextRec; Ch: KolibriChar; Width: LongInt);
procedure _WriteCString(var T: TTextRec; S: PKolibriChar; Width: LongInt);
procedure _WriteLong(var T: TTextRec; Value, Width: LongInt);
procedure _WriteString(var T: TTextRec; const S: ShortString; Width: LongInt);
procedure _WriteLString(var T: TTextRec; const S: KolibriString; Width: LongInt);
procedure _WriteLn(var T: TTextRec);
2020-12-26 23:34:54 +01:00
var
AppPath, CmdLine: PKolibriChar;
{ Console Library API }
type
con_gets2_callback = function(KeyCode: Integer; var Str: PKolibriChar; var Count, Pos: Integer): Integer; stdcall;
const
CON_COLOR_BLUE = $01;
CON_COLOR_GREEN = $02;
CON_COLOR_RED = $04;
CON_COLOR_BRIGHT = $08;
CON_BGR_BLUE = $10;
CON_BGR_GREEN = $20;
CON_BGR_RED = $40;
CON_BGR_BRIGHT = $80;
CON_IGNORE_SPECIALS = $100;
CON_WINDOW_CLOSED = $200;
// TODO: con_gets2_callback constants
con_cls: procedure; stdcall = nil;
con_exit: procedure(CloseWindow: Boolean); stdcall = nil;
con_getch: function: Integer; stdcall = nil;
con_getch2: function: Word; stdcall = nil;
con_get_cursor_pos: procedure(var X, Y: Integer); stdcall = nil;
con_get_cursor_height: function: Integer; stdcall = nil;
con_get_flags: function: LongWord; stdcall = nil;
con_get_font_height: function: Integer; stdcall = nil;
con_gets: function(Str: PKolibriChar; Length: Integer): PKolibriChar; stdcall = nil;
con_gets2: function(Callback: con_gets2_callback; Str: PKolibriChar; Count: Integer): PKolibriChar; stdcall = nil;
con_init: procedure(WndWidth, WndHeight, ScrWidth, ScrHeight: LongWord; Title: PKolibriChar); stdcall = nil;
con_kbhit: function: Boolean; stdcall = nil;
con_printf: function(Str: PKolibriChar): Integer; cdecl varargs = nil;
con_set_flags: function(Flags: LongWord): LongWord; stdcall = nil;
con_set_cursor_height: function(Height: Integer): Integer; stdcall = nil;
con_set_cursor_pos: procedure(X, Y: Integer); stdcall = nil;
con_set_title: procedure(Title: PKolibriChar); stdcall = nil;
con_write_asciiz: procedure(Str: PKolibriChar); stdcall = nil;
con_write_string: procedure(Str: PKolibriChar; Length: LongWord); stdcall = nil;
2020-05-22 00:01:43 +02:00
implementation
uses
SysInit;
var
InitContext: TInitContext;
2020-05-22 00:01:43 +02:00
procedure _HandleFinally;
asm
2020-12-29 22:45:11 +01:00
MOV EAX, 1
2020-05-22 00:01:43 +02:00
end;
procedure InitUnits;
var
Idx: Integer;
begin
if InitContext.InitTable <> nil then
with InitContext.InitTable^ do
begin
Idx := 0;
while Idx < UnitCount do
begin
with UnitInfo[Idx] do
begin
if Assigned(Init) then
Init;
end;
Inc(Idx);
InitContext.InitCount := Idx;
end;
end;
end;
procedure FinalizeUnits;
begin
if InitContext.InitTable <> nil then
begin
with InitContext do
begin
while InitCount > 0 do
begin
Dec(InitCount);
with InitTable.UnitInfo[InitCount] do
if Assigned(Finalize) then
Finalize;
end;
end;
end;
end;
procedure _StartExe(InitTable: PPackageInfo);
begin
InitContext.InitTable := InitTable;
InitContext.InitCount := 0;
InitUnits;
end;
procedure _Halt0;
2020-12-29 22:45:11 +01:00
asm
CALL FinalizeUnits
OR EAX, -1
INT $40
end;
2020-06-21 23:42:17 +02:00
function Get8087CW: Word;
asm
PUSH 0
FNSTCW [ESP].Word
POP EAX
end;
procedure Set8087CW(Value: Word);
2020-12-29 22:45:11 +01:00
asm
MOV Default8087CW, AX
FNCLEX
FLDCW Default8087CW
2020-06-21 23:42:17 +02:00
end;
2020-06-21 23:53:37 +02:00
// Produce random values in a given range [MinValue..MaxValue]
// Note: Always return 0 if range = [0..$FFFFFFFF]
// cause (MaxValue - MinValue + 1) * eax + MinValue = 0
// uses variation of XorShift based algorithm
function RandInt(MinValue, MaxValue: LongWord): LongWord; stdcall;
asm
MOV EAX, RandSeed
MOV ECX, EAX
SHL EAX, 13
XOR ECX, EAX
MOV EAX, ECX
SHR EAX, 17
XOR ECX, EAX
MOV EAX, ECX
SHL EAX, 5
XOR EAX, ECX
ADD RandCounter, 361275
MOV RandSeed, EAX
ADD EAX, RandCounter
MOV EDX, MaxValue
SUB EDX, MinValue
INC EDX
MUL EDX
MOV EAX, EDX
ADD EAX, MinValue
end;
2020-12-26 23:51:04 +01:00
function _RandInt(Range: LongInt): LongInt;
2020-06-21 23:53:37 +02:00
begin
Result := RandInt(0, Range - 1);
end;
function _RandExt: Extended;
begin
2020-12-26 23:51:04 +01:00
Result := RandInt(0, $FFFFFFFE) / $FFFFFFFF;
2020-06-21 23:53:37 +02:00
end;
procedure Randomize;
asm
RDTSC
MOV RandSeed, EAX
end;
2020-06-21 22:02:21 +02:00
function UpCase(Ch: KolibriChar): KolibriChar;
begin
if Ch in ['a'..'z'] then
Dec(Ch, Ord('a') - Ord('A'));
Result := Ch;
end;
type
PStrRec = ^TStrRec;
TStrRec = packed record
{$IFDEF UnicodeCompiler}
CodePage, CharSize: Word;
{$ENDIF}
RefCount, Length: LongInt;
end;
function _LStrLen(const S: KolibriString): LongInt;
begin
Result := PStrRec(PKolibriChar(Pointer(S)) - SizeOf(TStrRec)).Length;
end;
function _LStrToPChar(const S: KolibriString): PKolibriChar;
const
EmptyString = '';
begin
if Pointer(S) = nil then
Result := EmptyString
else
Result := Pointer(S);
end;
function _Flush(var T: TTextRec): Integer;
asm
end;
procedure __IOTest;
asm
// TODO: I/O error call
end;
const
Booleans: array[Boolean] of PKolibriChar = ('False', 'True');
function _ReadChar(var T: TTextRec): KolibriChar;
begin
Result := Chr(con_getch);
end;
procedure _ReadCString(var T: TTextRec; Str: PKolibriChar; MaxLength: LongInt);
var
P, Limit: PKolibriChar;
begin
con_gets(Str, MaxLength);
P := Str;
Limit := P + MaxLength;
while (P < Limit) and not (P^ in [#0, #10]) do
Inc(P);
P^ := #0;
end;
procedure _ReadString(var T: TTextRec; Str: PShortString; MaxLength: LongInt);
var
P, Limit: PKolibriChar;
begin
P := PKolibriChar(Str) + 1;
con_gets(P, MaxLength);
Limit := P + MaxLength;
while (P < Limit) and not (P^ in [#0, #10]) do
Inc(P);
PByte(Str)^ := P - PKolibriChar(Str) - 1;
end;
procedure _ReadLn(var T: TTextRec);
asm
end;
procedure _Write0Bool(var T: TTextRec; Value: Boolean);
begin
con_write_asciiz(Booleans[Value]);
end;
procedure _Write0Char(var T: TTextRec; Ch: KolibriChar);
begin
con_write_string(@Ch, 1);
end;
procedure _Write0Long(var T: TTextRec; Value: LongInt);
begin
con_printf('%d', Value);
end;
procedure _Write0String(var T: TTextRec; const S: ShortString);
begin
con_write_string(@S[1], Length(S));
end;
procedure _Write0CString(var T: TTextRec; S: PKolibriChar);
begin
con_write_asciiz(S);
end;
procedure _Write0LString(var T: TTextRec; const S: KolibriString);
begin
con_write_string(Pointer(S), Length(S));
end;
procedure _WriteBool(var T: TTextRec; Value: Boolean; Width: LongInt);
begin
con_printf('%*s', Width, Booleans[Value]);
end;
procedure _WriteChar(var T: TTextRec; Ch: KolibriChar; Width: LongInt);
begin
con_printf('%*c', Width, Ch);
end;
procedure _WriteCString(var T: TTextRec; S: PKolibriChar; Width: LongInt);
begin
con_printf('%*s', Width, S);
end;
procedure _WriteLong(var T: TTextRec; Value, Width: LongInt);
begin
con_printf('%*d', Width, Value);
end;
procedure _WriteString(var T: TTextRec; const S: ShortString; Width: LongInt);
begin
con_printf('%*s', Width, @S[1]);
end;
procedure _WriteLString(var T: TTextRec; const S: KolibriString; Width: LongInt);
begin
con_printf('%*s', Width, Pointer(S));
end;
procedure _WriteLn(var T: TTextRec);
begin
con_write_string(#10, 1);
end;
2020-06-21 23:53:37 +02:00
initialization
2020-12-26 23:34:54 +01:00
asm // InitFPU
FNINIT
FWAIT
FLDCW Default8087CW
end;
AppPath := PPKolibriChar(32)^;
CmdLine := PPKolibriChar(28)^;
2020-06-21 23:53:37 +02:00
end.