Componentes.Terceros.DevExp.../official/x.38/Innerfuse Pascal Script/Sources/ifpicall.pas
2008-08-27 11:56:15 +00:00

1758 lines
58 KiB
ObjectPascal

unit ifpicall;
{
Innerfuse Pascal Script Call unit
You may not copy a part of this unit, only use it as whole, with
Innerfuse Pascal Script Script Engine.
}
{$I ifps3_def.inc}
interface
uses
ifps3, ifps3utl, ifps3common{$IFDEF HAVEVARIANT}{$IFDEF D6PLUS}, variants{$ENDIF}{$ENDIF}, SysUtils;
type
TCallingConvention = (ccRegister, ccPascal, CCCdecl, CCStdCall);
PResourcePtrSupportFuncs = ^TResourcePtrSupportFuncs;
TResourcePtrToStrProc = function (PSelf: PResourcePtrSupportFuncs; Sender: TIFPSExec; P: PIFVariant): string;
TVarResourcePtrToStrProc = function (PSelf: PResourcePtrSupportFuncs; Sender: TIFPSExec; P: PIFVariant): string;
TResultToRsourcePtr = procedure(PSelf: PResourcePtrSupportFuncs; Sender: TIFPSExec; Data: Longint; P: PIFVariant);
TRPSResultMethod = (rmParam, rmRegister);
TResourcePtrSupportFuncs = record
Ptr: Pointer;
PtrToStr: TResourcePtrToStrProc;
VarPtrToStr: TVarResourcePtrToStrProc;
ResultMethod: TRPSResultMethod;
ResToPtr: TResultToRsourcePtr;
ProcPtrToStr: TResourcePtrToStrProc;
end;
function InnerfuseCall(SE: TIFPSExec; Self, Address: Pointer; CallingConv: TCallingConvention; Params: TIfList; res: PIfVariant; SupFunc: PResourcePtrSupportFuncs): Boolean;
{$IFDEF HAVEVARIANT}
function PIFVariantToVariant(Sender: TIFPSExec; Src: PIFVariant; var Dest: Variant): Boolean;
function VariantToPIFVariant(Sender: TIFPSExec; const Src: Variant; Dest: PIFVariant): Boolean;
{$ENDIF}
implementation
{$IFDEF HAVEVARIANT}
var
VNull: Variant;
const
VariantType: TIFTypeRec = (ext:nil;BaseType: btVariant);
VariantArrayType: TIFTypeRec = (ext:@VariantType;basetype: btArray);
{$ENDIF}
function RealFloatCall_Register(p: Pointer;
_EAX, _EDX, _ECX: Cardinal;
StackData: Pointer;
StackDataLen: Longint // stack length are in 4 bytes. (so 1 = 4 bytes)
): Extended; Stdcall; // make sure all things are on stack
var
E: Extended;
begin
asm
mov ecx, stackdatalen
jecxz @@2
mov eax, stackdata
@@1:
mov edx, [eax]
push edx
sub eax, 4
dec ecx
or ecx, ecx
jnz @@1
@@2:
mov eax,_EAX
mov edx,_EDX
mov ecx,_ECX
call p
fstp tbyte ptr [e]
end;
Result := E;
end;
function RealFloatCall_Other(p: Pointer;
StackData: Pointer;
StackDataLen: Longint // stack length are in 4 bytes. (so 1 = 4 bytes)
): Extended; Stdcall; // make sure all things are on stack
var
E: Extended;
begin
asm
mov ecx, stackdatalen
jecxz @@2
mov eax, stackdata
@@1:
mov edx, [eax]
push edx
sub eax, 4
dec ecx
or ecx, ecx
jnz @@1
@@2:
call p
fstp tbyte ptr [e]
end;
Result := E;
end;
function RealFloatCall_CDecl(p: Pointer;
StackData: Pointer;
StackDataLen: Longint // stack length are in 4 bytes. (so 1 = 4 bytes)
): Extended; Stdcall; // make sure all things are on stack
var
E: Extended;
begin
asm
mov ecx, stackdatalen
jecxz @@2
mov eax, stackdata
@@1:
mov edx, [eax]
push edx
sub eax, 4
dec ecx
or ecx, ecx
jnz @@1
@@2:
call p
fstp tbyte ptr [e]
@@5:
mov ecx, stackdatalen
jecxz @@2
@@6:
pop edx
dec ecx
or ecx, ecx
jnz @@6
end;
Result := E;
end;
function RealCall_Register(p: Pointer;
_EAX, _EDX, _ECX: Cardinal;
StackData: Pointer;
StackDataLen: Longint; // stack length are in 4 bytes. (so 1 = 4 bytes)
ResultLength: Longint; ResEDX: Pointer): Longint; Stdcall; // make sure all things are on stack
var
r: Longint;
begin
asm
mov ecx, stackdatalen
jecxz @@2
mov eax, stackdata
@@1:
mov edx, [eax]
push edx
sub eax, 4
dec ecx
or ecx, ecx
jnz @@1
@@2:
mov eax,_EAX
mov edx,_EDX
mov ecx,_ECX
call p
mov ecx, resultlength
cmp ecx, 0
je @@5
cmp ecx, 1
je @@3
cmp ecx, 2
je @@4
mov r, eax
jmp @@5
@@3:
xor ecx, ecx
mov cl, al
mov r, ecx
jmp @@5
@@4:
xor ecx, ecx
mov cx, ax
mov r, ecx
@@5:
mov ecx, resedx
jecxz @@6
mov [ecx], edx
@@6:
end;
Result := r;
end;
function RealCall_Other(p: Pointer;
StackData: Pointer;
StackDataLen: Longint; // stack length are in 4 bytes. (so 1 = 4 bytes)
ResultLength: Longint; ResEDX: Pointer): Longint; Stdcall; // make sure all things are on stack
var
r: Longint;
begin
asm
mov ecx, stackdatalen
jecxz @@2
mov eax, stackdata
@@1:
mov edx, [eax]
push edx
sub eax, 4
dec ecx
or ecx, ecx
jnz @@1
@@2:
call p
mov ecx, resultlength
cmp ecx, 0
je @@5
cmp ecx, 1
je @@3
cmp ecx, 2
je @@4
mov r, eax
jmp @@5
@@3:
xor ecx, ecx
mov cl, al
mov r, ecx
jmp @@5
@@4:
xor ecx, ecx
mov cx, ax
mov r, ecx
@@5:
mov ecx, resedx
jecxz @@6
mov [ecx], edx
@@6:
end;
Result := r;
end;
function RealCall_CDecl(p: Pointer;
StackData: Pointer;
StackDataLen: Longint; // stack length are in 4 bytes. (so 1 = 4 bytes)
ResultLength: Longint; ResEDX: Pointer): Longint; Stdcall; // make sure all things are on stack
var
r: Longint;
begin
asm
mov ecx, stackdatalen
jecxz @@2
mov eax, stackdata
@@1:
mov edx, [eax]
push edx
sub eax, 4
dec ecx
or ecx, ecx
jnz @@1
@@2:
call p
mov ecx, resultlength
cmp ecx, 0
je @@5
cmp ecx, 1
je @@3
cmp ecx, 2
je @@4
mov r, eax
jmp @@5
@@3:
xor ecx, ecx
mov cl, al
mov r, ecx
jmp @@5
@@4:
xor ecx, ecx
mov cx, ax
mov r, ecx
@@5:
mov ecx, stackdatalen
jecxz @@2
@@6:
pop eax
dec ecx
or ecx, ecx
jnz @@6
mov ecx, resedx
jecxz @@7
mov [ecx], edx
@@7:
end;
Result := r;
end;
{$IFDEF HAVEVARIANT}
function PIFVariantToVariant(Sender: TIFPSExec; Src: PIFVariant; var Dest: Variant): Boolean;
function CreateArrayVariant: Boolean;
var
v: Variant;
i: Integer;
begin
Dest := VarArrayCreate([0, GetIFPSArrayLength(Sender, Src)-1], vtVariant);
for i := GetIFPSArrayLength(Sender, Src) -1 downto 0 do
begin
if (not PIFVariantToVariant(Sender, Src^.tArray.Fields[i], v)) or (VarIsArray(v)) then
begin
Result := False;
exit;
end;
Dest[i] := v;
end;
Result := True;
end;
begin
if Src^.FType.BaseType = btVariant then Src := Src^.tvariant;
if Src^.Ftype = nil then
begin
Dest := null;
Result := True;
exit;
end;
case Src^.FType^.BaseType of
btArray:
begin
if not CreateArrayVariant then
begin
Result := False;
exit;
end;
end;
btU8: Dest := Src^.tu8;
btS8: Dest := Src^.ts8;
btU16: Dest := Src^.tu16;
btS16: Dest := Src^.ts16;
btU32: Dest := Longint(Src^.tu32);
btS32: Dest := Src^.ts32;
btSingle: Dest := Src^.tsingle;
btDouble: Dest := Src^.tdouble;
btExtended: Dest := Src^.textended;
btPChar, btString: Dest := tbtString(Src^.tstring);
{$IFNDEF NOINT64}
{$IFDEF D6PLUS} btS64: Dest := Src^.ts64; {$ELSE} bts64: begin Result := False; exit; end; {$ENDIF}
{$ENDIF}
btChar: Dest := src^.tChar;
{$IFNDEF NOWIDESTRING}
btWideString: Dest := tbtWideString(src^.twidestring);
btWideChar: Dest := src^.twidechar;
{$ENDIF}
else
begin
Result := False;
exit;
end;
end;
Result := True;
end;
function VariantToPIFVariant(Sender: TIFPSExec; const Src: Variant; Dest: PIFVariant): Boolean;
var
I: Longint;
L: Cardinal;
PT: PIFTypeRec;
begin
if Dest^.FType.BaseType <> btVariant then begin Result := False; exit; end;
if VarIsArray(Src) then
begin
if VarArrayDimCount(Src) > 1 then
begin
Result := False;
exit;
end;
l := 0;
repeat
pt := Sender.FindType(l, btArray, l);
if PIFTypeRec(Sender.GetTypeNo(Cardinal(pt^.Ext)))^.BaseType = btVariant then break;
until pt = nil;
if pt = nil then pt := @VariantArrayType;
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF}Dest^.tvariant, pt);
SetIFPSArrayLength(Sender, Dest^.tvariant, VarArrayHighBound(Src, 1) - VarArrayLowBound(Src, 1)+1);
for i := VarArrayLowBound(Src, 1) to VarArrayHighBound(Src, 1) do
begin
if not VariantToPIFVariant(Sender, Src[i], Dest^.tVariant^.tArray^.Fields[i - VarArrayLowBound(Src, 1)]) then
begin
Result := False;
Exit;
end;
end;
end else
begin
case VarType(Src) of
varEmpty:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, nil);
end;
varSmallint:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btS16));
Dest^.tvariant.ts16 := Src;
end;
varInteger:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btS32));
Dest^.tvariant.ts32 := Src;
end;
varSingle:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btSingle));
Dest^.tvariant.tsingle := Src;
end;
varDate, varCurrency, varDouble:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btDouble));
Dest^.tvariant.tDouble := Src;
end;
{$IFNDEF NOWIDESTRING}
varOleStr:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btWideString));
tbtWideString(Dest^.tvariant.twidestring) := Src;
end;
{$ENDIF}
varBoolean:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btu8));
Boolean(Dest^.tvariant.tu8) := Src;
end;
{$IFDEF D6PLUS} varShortInt:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btS8));
Dest^.tvariant.ts8 := Src;
end;
varByte:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btu8));
Dest^.tvariant.tu8 := Src;
end;
varWord:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btS16));
Dest^.tvariant.tu16 := Src;
end;
varLongWord:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btu32));
Dest^.tvariant.tu32 := Src;
end;
{$IFNDEF NOINT64}
varInt64:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btS64));
Dest^.tvariant.ts16 := Src;
end;
{$ENDIF}{$ENDIF}
varStrArg, varString:
begin
ChangeVariantType({$IFNDEF NOSMARTMM}Sender.MemoryManager, {$ENDIF} Dest^.tvariant, Sender.FindType2(btstring));
tbtstring(Dest^.tvariant.tstring) := Src;
end;
else
begin
Result := False;
exit;
end;
end;
end;
Result := True;
end;
{$ENDIF}
type
POpenArray = ^TOpenArray;
TOpenArray = record
AType: Byte; {0}
OrgVar: PIFVariant;
ElementSize,
ItemCount: Longint;
Data: string;
VarParam: Boolean;
end;
{$IFDEF HAVEVARIANT}
PVariant = ^TVariant;
TVariant = record
AType: Byte; {1}
OrgVar: PIFVariant;
P: Variant;
VarParam: Boolean;
end;
{$ENDIF}
PRecord = ^TRecord;
TRecord = record
AType: Byte; {2}
OrgVar: PIFVariant;
Data: string;
VarParam: Boolean;
end;
{$IFDEF DYNARRAY}
PDynArray = ^TDynArray;
TDynArray = record
AType: Byte; {3}
OrgVar: PIfVariant;
VarParam: Boolean;
Data: Pointer;
end;
{$ENDIF}
{$IFDEF HAVEVARIANT}
function CreateVariant(VarParam: Boolean; Sender: TIFPSExec; SupFunc: PResourcePtrSupportFuncs; Val: PIFVariant): PVariant;
begin
New(Result);
Result.AType := 1;
Result.OrgVar := Val;
Result.VarParam := VarParam;
if not PIFVariantToVariant(Sender, Val, Result^.P) then
begin
Dispose(Result);
Result := nil;
exit;
end;
end;
procedure DestroyVariant(Sender: TIFPSExec; SupFunc: PResourcePtrSupportFuncs; V: PVariant);
begin
if V.VarParam then
begin
VariantToPIFVariant(Sender, V^.P, V^.OrgVar);
end;
Dispose(V);
end;
{$ENDIF}
function CreateOpenArray(VarParam: Boolean; Sender: TIFPSExec; SupFunc: PResourcePtrSupportFuncs; Val: PIFVariant): POpenArray;
var
p: Pointer;
i: Longint;
{$IFDEF HAVEVARIANT}
fv: PIFVariant;
temps: string;
{$ENDIF}
begin
if Val.FType^.BaseType <> btArray then
begin
Result := nil;
exit;
end;
New(Result);
Result.AType := 0;
Result.OrgVar := Val;
Result.VarParam := VarParam;
Result^.ItemCount := GetIFPSArrayLength(Sender, Val);
case Sender.GetTypeNo(Longint(Val^.FType^.Ext))^.BaseType of
{$IFDEF HAVEVARIANT}
btVariant:
begin
if Val^.FType.ExportName = '!OPENARRAYOFVARIANT' then
Result^.ElementSize := SizeOf(Variant)
else
Result^.ElementSize := SizeOf(TVarRec);
end;
{$ENDIF}
btU8, bts8: Result^.ElementSize := 1;
btu16, bts16: Result^.ElementSize := 2;
btu32, bts32: Result^.ElementSize := 4;
btsingle: Result^.ElementSize := 4;
btdouble: Result^.ElementSize := 8;
btextended: Result^.ElementSize := SizeOf(Extended);
btstring, btpchar: Result^.ElementSize := 4;
btchar: Result^.ElementSize := 1;
{$IFNDEF NOINT64}
btS64: Result^.ElementSize := 8;
{$ENDIF}
{$IFNDEF NOWIDESTRING}
btWidestring: Result^.ElementSize := 4;
btwidechar: Result^.ElementSize := 2;
{$ENDIF}
else
begin
Dispose(Result);
Result := nil;
exit;
end;
end;
SetLength(Result^.Data, Result^.ItemCount * Result^.ElementSize);
P := @Result^.Data[1];
FillChar(p^, Result^.ItemCount * Result^.ElementSize, 0);
case Sender.GetTypeNo(Longint(Val^.FType^.Ext))^.BaseType of
btPChar, btChar, {$IFNDEF NOWIDESTRING}btWideChar, {$ENDIF}btU8, btS8, btU16, btS16, btu32, bts32, btSingle, btDouble, btExtended:
begin
for i := 0 to Result^.ItemCount -1 do
begin
Move(Val^.tArray.Fields[i].tu8, p^, Result^.elementsize);
p := PChar(p) + Result^.ElementSize;
end;
end;
{$IFNDEF NOWIDESTRING}
btWideString:
begin
for i := 0 to Result^.ItemCount -1 do
begin
tbtwidestring(p^) := tbtwidestring(Val^.tArray.Fields[i].twidestring);
p := PChar(p) + Result^.ElementSize;
end;
end;
{$ENDIF}
btString:
begin
for i := 0 to Result^.ItemCount -1 do
begin
string(p^) := string(Val^.tArray.Fields[i].tstring);
p := PChar(p) + Result^.ElementSize;
end;
end;
{$IFDEF HAVEVARIANT}
btVariant:
begin
if Val^.FType.ExportName = '!OPENARRAYOFVARIANT' then
begin
for i := 0 to Result^.ItemCount -1 do
begin
Initialize(variant(p^));
PIFVariantToVariant(Sender, val^.Tarray.Fields[i], Variant(p^));
p := PChar(p) + Result^.ElementSize;
end;
end
else
begin
for i := 0 to Result^.ItemCount -1 do
begin
fv := val^.tArray.Fields[i];
if fv^.tvariant^.FType = nil then
begin
tvarrec(p^).VType := vtVariant;
tvarrec(p^).VVariant := @VNull;
end else begin
case fv^.tvariant^.ftype^.BaseType of
btchar: begin
tvarrec(p^).VType := vtChar;
tvarrec(p^).VChar := fv^.tvariant^.tchar;
end;
btSingle:
begin
tvarrec(p^).VType := vtExtended;
New(tvarrec(p^).VExtended);
tvarrec(p^).VExtended^ := fv^.tvariant^.tsingle;
end;
btExtended:
begin
tvarrec(p^).VType := vtExtended;
New(tvarrec(p^).VExtended);
tvarrec(p^).VExtended^ := fv^.tvariant^.textended;
end;
btDouble:
begin
tvarrec(p^).VType := vtExtended;
New(tvarrec(p^).VExtended);
tvarrec(p^).VExtended^ := fv^.tvariant^.tdouble;
end;
{$IFNDEF NOWIDESTRING}
btwidechar: begin
tvarrec(p^).VType := vtWideChar;
tvarrec(p^).VWideChar := fv^.tvariant^.twidechar;
end;
btwideString: begin
tvarrec(p^).VType := vtWideString;
widestring(TVarRec(p^).VWideString) := widestring(fv^.tvariant^.twidestring);
end;
{$ENDIF}
btU8: begin
tvarrec(p^).VType := vtInteger;
tvarrec(p^).VInteger := fv^.tvariant^.tu8;
end;
btS8: begin
tvarrec(p^).VType := vtInteger;
tvarrec(p^).VInteger := fv^.tvariant^.ts8;
end;
btU16: begin
tvarrec(p^).VType := vtInteger;
tvarrec(p^).VInteger := fv^.tvariant^.tu16;
end;
btS16: begin
tvarrec(p^).VType := vtInteger;
tvarrec(p^).VInteger := fv^.tvariant^.ts16;
end;
btU32: begin
tvarrec(p^).VType := vtInteger;
tvarrec(p^).VInteger := Longint(fv^.tvariant^.tu32);
end;
btS32: begin
tvarrec(p^).VType := vtInteger;
tvarrec(p^).VInteger := fv^.tvariant^.ts32;
end;
btString: begin
tvarrec(p^).VType := vtAnsiString;
string(TVarRec(p^).VAnsiString) := string(fv^.tvariant^.tstring);
end;
{$IFNDEF NOINT64}
btS64:
begin
tvarrec(p^).VType := vtInt64;
new(tvarrec(p^).VInt64);
tvarrec(p^).VInt64^ := fv^.tvariant^.ts64;
end;
{$ENDIF}
btPChar: begin
tvarrec(p^).VType := vtPchar;
TVarRec(p^).VPChar := pointer(fv^.tvariant^.tstring);
end;
btResourcePointer: begin
temps := SupFunc.PtrToStr(supfunc, Sender, fv^.tvariant);
if length(temps) =4 then
begin
tvarrec(p^).VType := vtObject;
TVarRec(p^).VObject := Pointer((@temps[1])^);
end;
end;
end;
end;
p := PChar(p) + Result^.ElementSize;
end;
end;
end;
{$ENDIF}
end;
end;
procedure DestroyOpenArray(Sender: TIFPSExec; SupFunc: PResourcePtrSupportFuncs; V: POpenArray);
var
p: Pointer;
fv: PIFVariant;
i: Longint;
begin
p := @v^.Data[1];
case Sender.GetTypeNo(Longint(V^.OrgVar^.FType^.Ext))^.BaseType of
btPChar, btU8, btS8, btU16, btS16, btu32, bts32, btSingle, btDouble, btExtended, btChar{$IFNDEF NOWIDESTRING}, btWidechar{$ENDIF}:
begin
if v^.VarParam then
begin
for i := 0 to v^.ItemCount -1 do
begin
Move(p^, v^.orgvar^.tArray.Fields[i].tu8, v^.ElementSize);
p := pchar(p) + v^.ElementSize;
end;
end;
end;
{$IFNDEF NOWIDESTRING}
btWideString:
begin
for i := 0 to v^.ItemCount -1 do
begin
if v^.varparam then
widestring(v^.OrgVar^.tArray.Fields[i].twidestring) := widestring(p^);
Finalize(widestring(p^));
p := pchar(p) + v^.ElementSize;
end;
end;
{$ENDIF}
btString:
begin
for i := 0 to v^.ItemCount -1 do
begin
if v^.varparam then
string(v^.OrgVar^.tArray.Fields[i].tstring) := string(p^);
Finalize(string(p^));
p := pchar(p) + v^.ElementSize;
end;
end;
btVariant:
begin
{$IFDEF HAVEVARIANT}
if v^.OrgVar^.FType.ExportName = '!OPENARRAYOFVARIANT' then
begin
for i := 0 to v^.ItemCount -1 do
begin
if v^.varparam then
VariantToPIFVariant(Sender, variant(p^), v^.OrgVar^.tArray.Fields[i]);
Finalize(variant(p^));
p := pchar(p) + v^.ElementSize;
end;
end
else
{$ENDIF}
begin
for i := 0 to v^.ItemCount -1 do
begin
fv := v^.OrgVar^.tArray.Fields[i];
if fv^.tvariant^.FType = nil then
begin
tvarrec(p^).VType := vtInteger;
end else begin
case fv^.tvariant^.ftype^.BaseType of
btU8: begin
if v^.varParam then
fv^.tvariant^.tu8 := tvarrec(p^).VInteger;
end;
btS8: begin
if v^.varParam then
fv^.tvariant^.ts8 := tvarrec(p^).VInteger;
end;
btU16: begin
if v^.varParam then
fv^.tvariant^.tu16 := tvarrec(p^).VInteger;
end;
btS16: begin
if v^.varParam then
fv^.tvariant^.ts16 := tvarrec(p^).VInteger;
end;
btU32: begin
if v^.varParam then
fv^.tvariant^.tu32 := tvarrec(p^).VInteger;
end;
btS32: begin
if v^.varParam then
fv^.tvariant^.ts32 := tvarrec(p^).VInteger;
end;
btChar: begin
if v^.VarParam then
fv^.tvariant^.tchar := tvarrec(p^).VChar;
end;
btSingle: begin
if v^.VarParam then
fv^.tvariant^.tsingle := tvarrec(p^).vextended^;
dispose(tvarrec(p^).vextended);
end;
btDouble: begin
if v^.VarParam then
fv^.tvariant^.tdouble := tvarrec(p^).vextended^;
dispose(tvarrec(p^).vextended);
end;
btExtended: begin
if v^.VarParam then
fv^.tvariant^.textended := tvarrec(p^).vextended^;
dispose(tvarrec(p^).vextended);
end;
{$IFNDEF NOINT64}
btS64:
begin
if v^.VarParam then
fv^.tvariant^.tu8 := tvarrec(p^).VInt64^;
dispose(tvarrec(p^).VInt64);
end;
{$ENDIF}
{$IFNDEF NOWIDESTRING}
btWideChar: begin
if v^.varParam then
fv^.tvariant^.twidechar := tvarrec(p^).VWideChar;
end;
btWideString:
begin
if v^.VarParam then
widestring(fv^.tvariant^.twidestring) := widestring(TVarRec(p^).VWideString);
finalize(widestring(TVarRec(p^).VWideString));
end;
{$ENDIF}
btString: begin
if v^.VarParam then
string(fv^.tvariant^.tstring) := string(TVarRec(p^).VAnsiString);
finalize(string(TVarRec(p^).VAnsiString));
end;
btResourcePointer: begin
if v^.varparam then
begin
SupFunc.ResToPtr(SupFunc, Sender, Longint(TVarRec(p^).VObject), fv);
end;
end;
end;
end;
p := pchar(p) + v^.ElementSize;
end;
end;
end;
end;
Dispose(V);
end;
procedure CreateRecordData(Rec: PIFVariant; var Data: string; SE: TIFPSExec; SupFunc: PResourcePtrSupportFuncs);
var
I: Longint;
begin
while Rec^.FType^.BaseType = btPointer do
begin
Rec := Rec^.tPointer;
if Rec = nil then begin Data := Data + #0#0#0#0; Exit; end;
end;
case Rec^.FType^.BaseType of
btchar, btS8, btU8: Data := Data + Chr(Rec^.tu8);
{$IFNDEF NOWIDESTRING}btWideChar, {$ENDIF}btU16, btS16: begin Data := Data + #0#0; Word((@Data[Length(Data)-1])^) := Rec^.tu16; end;
btS32, btU32: begin Data := Data + #0#0#0#0; Cardinal((@Data[Length(Data)-3])^) := Rec^.tu32; end;
btSingle: begin Data := Data + #0#0#0#0; Single((@Data[Length(Data)-3])^) := Rec^.tsingle; end;
btDouble: begin Data := Data + #0#0#0#0#0#0#0#0; Double((@Data[Length(Data)-7])^) := Rec^.tdouble; end;
btExtended: begin Data := Data + #0#0#0#0#0#0#0#0#0#0; Extended((@Data[Length(Data)-9])^) := Rec^.tExtended; end;
btString, btPChar: begin Data := Data + #0#0#0#0; tbtString((@Data[Length(Data)-3])^) := tbtString(Rec^.tString); end;
{$IFNDEF NOWIDESTRING}
btWideString: begin Data := Data + #0#0#0#0; tbtWideString((@Data[Length(Data)-3])^) := tbtWideString(Rec^.twidestring); end;
{$ENDIF}
btRecord, btArray:
begin
if Rec^.trecord <> nil then
begin
for i := 0 to Rec^.trecord^.FieldCount -1 do
begin
CreateRecordData(Rec^.trecord^.Fields[I], Data, Se, SupFunc);
end;
end;
end;
btResourcePointer:
begin
Data := Data + SupFunc^.PtrToStr(SupFunc, Se, Rec);
end;
{$IFNDEF NOINT64}btS64: begin Data := Data + #0#0#0#0#0#0#0#0; int64((@Data[Length(Data)-7])^) := Rec^.ts64; end;{$ENDIF}
end;
end;
function CreateRecord(VarParam: Boolean; Sender: TIFPSExec; SupFunc: PResourcePtrSupportFuncs; Val: PIFVariant): PRecord;
begin
New(Result);
Result^.AType := 2;
Result^.orgvar := Val;
Result^.varparam:= VarParam;
CreateRecordData(Val, Result^.Data, Sender, SupFunc);
end;
procedure DestroyRecord_(CopyBack: Boolean; Rec: PIFVariant; var Position: Longint; const Data: string; SE: TIFPSExec; SupFunc: PResourcePtrSupportFuncs);
var
I: Longint;
P: Pointer;
procedure GetP(var D; Len: Longint);
begin
if Position + Len -1 <= Length(Data) then
begin
if CopyBack then Move(Data[Position], D, Len);
Position := Position + Len;
end else Position := Length(Data) + 1;
end;
begin
while Rec^.FType^.BaseType = btPointer do
begin
Rec := Rec^.tPointer;
if Rec = nil then begin Inc(position, 4); Exit; end;
end;
case Rec^.FType^.BaseType of
btS8, btU8: GetP(Rec^.tu8, 1);
btU16, btS16: GetP(Rec^.tu16, 2);
btS32, btU32: GetP(Rec^.tu32, 4);
btSingle: GetP(Rec^.tsingle, 4);
btDouble: GetP(Rec^.tdouble, 8);
btExtended: GetP(Rec^.TExtended, 10);
btString, btPChar: begin GetP(P, 4); tbtString(Rec^.tString) := string(p); Finalize(tbtString(Rec^.tString)); end;
{$IFNDEF NOWIDESTRING}
btWideString: begin GetP(P, 4); tbtWideString(Rec^.tWideString) := WideString(p); Finalize(tbtwideString(Rec^.twideString)); end;
{$ENDIF}
btRecord, btArray:
begin
if Rec^.trecord <> nil then
begin
for i := 0 to Rec^.trecord^.FieldCount -1 do
begin
DestroyRecord_(CopyBack, Rec^.trecord^.Fields[I], Position, Data, Se, SupFunc);
end;
end;
end;
btResourcePointer:
begin
GetP(I, 4);
SupFunc^.ResToPtr(SupFunc, SE, I, Rec);
end;
{$IFNDEF NOINT64}btS64: begin GetP(Rec^.ts64, 8); end;{$ENDIF}
end;
end;
procedure DestroyRecord(Sender: TIFPSExec; SupFunc: PResourcePtrSupportFuncs; V: PRecord);
var
Pos: Longint;
begin
Pos := 1;
DestroyRecord_(V^.varparam, V^.orgvar, Pos, V^.Data, Sender, SupFunc);
Dispose(v);
end;
{$IFDEF DYNARRAY}
type
TArrU8 = array of byte;
TArrS8 = array of ShortInt;
TArrU16 = array of SmallInt;
TArrS16 = array of Word;
TArrU32 = array of Cardinal;
TArrS32 = array of Longint;
TArrSingle = array of Single;
TArrDouble = array of Double;
TArrExtended = array of Extended;
TArrString = array of String;
{$IFDEF HAVEVARIANT}
TArrVariant = array of Variant;
{$ENDIF}
{$IFNDEF NOINT64}
TArrS64 = array of Int64;
{$ENDIF}
TArrChar = array of Char;
{$IFNDEF NOWIDESTRING}
TArrWideString = array of WideString;
TArrWideChar = array of WideChar;
{$ENDIF}
function CreateDynamicArray(VarParam: Boolean; Sender: TIFPSExec; SupFunc: PResourcePtrSupportFuncs; Val: PIFVariant): PDynArray;
var
I, Len: Longint;
begin
New(Result);
Result^.AType := 3;
Result^.OrgVar := Val;
Result^.VarParam := VarParam;
Result^.Data := nil;
Len := GetIFPSArrayLength(Sender, Val);
case Sender.GetTypeNo(Longint(Val^.FType^.Ext))^.BaseType of
btU8:
begin
SetLength(TArrU8(Result^.Data), Len);
for i := Length(TArrU8(Result^.Data)) -1 downto 0 do
TArrU8(Result^.Data)[i] := Val.tarray.fields[i].tu8;
end;
btS8:
begin
SetLength(TArrS8(Result^.Data), Len);
for i := Length(TArrS8(Result^.Data)) -1 downto 0 do
TArrS8(Result^.Data)[i] := Val.tarray.fields[i].tS8;
end;
btU16:
begin
SetLength(TArrU16(Result^.Data), Len);
for i := Length(TArrU16(Result^.Data)) -1 downto 0 do
TArrU16(Result^.Data)[i] := Val.tarray.fields[i].tu16;
end;
btS16:
begin
SetLength(TArrs16(Result^.Data), Len);
for i := Length(TArrs16(Result^.Data)) -1 downto 0 do
TArrS16(Result^.Data)[i] := Val.tarray.fields[i].ts16;
end;
btU32:
begin
SetLength(TArrU32(Result^.Data), Len);
for i := Length(TArrU32(Result^.Data)) -1 downto 0 do
TArrU32(Result^.Data)[i] := Val.tarray.fields[i].tu32;
end;
bts32:
begin
SetLength(TArrS32(Result^.Data), Len);
for i := Length(TArrS32(Result^.Data)) -1 downto 0 do
TArrS32(Result^.Data)[i] := Val.tarray.fields[i].ts8;
end;
btSingle:
begin
SetLength(TArrU8(Result^.Data), Len);
for i := Length(TArrU8(Result^.Data)) -1 downto 0 do
TArrU8(Result^.Data)[i] := Val.tarray.fields[i].tu8;
end;
btDouble:
begin
SetLength(TArrDouble(Result^.Data), Len);
for i := Length(TArrDouble(Result^.Data)) -1 downto 0 do
TArrDouble(Result^.Data)[i] := Val.tarray.fields[i].tdouble;
end;
btExtended:
begin
SetLength(TArrExtended(Result^.Data), Len);
for i := Length(TArrExtended(Result^.Data)) -1 downto 0 do
TArrExtended(Result^.Data)[i] := Val.tarray.fields[i].tExtended;
end;
btString:
begin
SetLength(TArrString(Result^.Data), Len);
for i := Length(TArrString(Result^.Data)) -1 downto 0 do
TArrString(Result^.Data)[i] := tbtstring(Val.tarray.fields[i].tstring);
end;
{$IFDEF HAVEVARIANT}
btVariant:
begin
SetLength(TArrVariant(Result^.Data), Len);
for i := Length(TArrVariant(Result^.Data)) -1 downto 0 do
begin
if not PIFVariantToVariant(Sender, Val.tarray.fields[i], TArrVariant(Result^.Data)[i]) then
begin
SetLength(TArrVariant(Result^.Data), 0);
Dispose(result);
exit;
end;
end;
end;
{$ENDIF}
{$IFNDEF NOINT64}
btS64:
begin
SetLength(TArrS64(Result^.Data), Len);
for i := Length(TArrS64(Result^.Data)) -1 downto 0 do
TArrS64(Result^.Data)[i] := Val.tarray.fields[i].ts64;
end;
{$ENDIF}
btChar:
begin
SetLength(TArrchar(Result^.Data), Len);
for i := Length(TArrchar(Result^.Data)) -1 downto 0 do
TArrchar(Result^.Data)[i] := Val.tarray.fields[i].tchar;
end;
{$IFNDEF NOWIDESTRING}
btWideString:
begin
SetLength(TArrwidestring(Result^.Data), Len);
for i := Length(TArrwidestring(Result^.Data)) -1 downto 0 do
TArrwidestring(Result^.Data)[i] := tbtwidestring(Val.tarray.fields[i].twidestring);
end;
btWideChar:
begin
SetLength(TArrWidechar(Result^.Data), Len);
for i := Length(TArrWidechar(Result^.Data)) -1 downto 0 do
TArrWidechar(Result^.Data)[i] := Val.tarray.fields[i].twidechar;
end;
{$ENDIF}
else begin
Dispose(Result);
Result := nil;
exit;
end;
end;
end;
procedure DestroyDynamicArray(Sender: TIFPSExec; SupFunc: PResourcePtrSupportFuncs; V: PDynArray);
var
C, I: Longint;
begin
case Sender.GetTypeNo(Longint(V^.OrgVar^.FType^.Ext))^.BaseType of
btU8:
begin
if v.VarParam then
begin
c := Length(TArrU8(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].tu8 := TArrU8(v^.Data)[i];
end;
SetLength(TArrU8(V^.Data), 0);
end;
btS8:
begin
if v.VarParam then
begin
c := Length(TArrs8(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].ts8 := TArrs8(v^.Data)[i];
end;
SetLength(TArrs8(V^.Data), 0);
end;
btU16:
begin
if v.VarParam then
begin
c := Length(TArrU16(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].tu16 := TArrU16(v^.Data)[i];
end;
SetLength(TArrU16(V^.Data), 0);
end;
btS16:
begin
if v.VarParam then
begin
c := Length(TArrs16(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].ts16 := TArrs16(v^.Data)[i];
end;
SetLength(TArrs16(V^.Data), 0);
end;
btU32:
begin
if v.VarParam then
begin
c := Length(TArrU32(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].tu32 := TArrU32(v^.Data)[i];
end;
SetLength(TArrU32(V^.Data), 0);
end;
bts32:
begin
if v.VarParam then
begin
c := Length(TArrs32(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].ts32 := TArrs32(v^.Data)[i];
end;
SetLength(TArrs32(V^.Data), 0);
end;
btSingle:
begin
if v.VarParam then
begin
c := Length(TArrsingle(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].tsingle := TArrsingle(v^.Data)[i];
end;
SetLength(TArrsingle(v^.Data), 0);
end;
btDouble:
begin
if v.VarParam then
begin
c := Length(TArrDouble(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].tdouble := TArrDouble(v^.Data)[i];
end;
SetLength(TArrDouble(V^.Data), 0);
end;
btExtended:
begin
if v.VarParam then
begin
c := Length(TArrextended(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].tExtended := TArrextended(v^.Data)[i];
end;
SetLength(TArrextended(V^.Data), 0);
end;
btString:
begin
if v.VarParam then
begin
c := Length(TArrString(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
tbtstring(V.OrgVar.tarray.fields[i].tstring) := TArrString(v^.Data)[i];
end;
SetLength(TArrString(V^.Data), 0);
end;
{$IFDEF HAVEVARIANT}
btVariant:
begin
if v.VarParam then
begin
c := Length(TArrVariant(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
VariantToPIFVariant(Sender,TArrVariant(v^.Data)[i], V.OrgVar.tarray.fields[i]);
end;
SetLength(TArrVariant(V^.Data), 0);
end;
{$ENDIF}
{$IFNDEF NOINT64}
btS64:
begin
if v.VarParam then
begin
c := Length(TArrs64(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].ts64 := TArrs64(v^.Data)[i];
end;
SetLength(TArrU8(V^.Data), 0);
end;
{$ENDIF}
btChar:
begin
if v.VarParam then
begin
c := Length(TArrChar(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].tchar := TArrChar(v^.Data)[i];
end;
SetLength(TArrchar(V^.Data), 0);
end;
{$IFNDEF NOWIDESTRING}
btWideString:
begin
if v.VarParam then
begin
c := Length(TArrWideString(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
tbtwidestring(V.OrgVar.tarray.fields[i].twidestring) := TArrWideString(v^.Data)[i];
end;
SetLength(TArrWideString(V^.Data), 0);
end;
btWideChar:
begin
if v.VarParam then
begin
c := Length(TArrWideChar(V^.Data));
SetIFPSArrayLength(Sender, v.OrgVar, c);
for i := c -1 downto 0 do
V.OrgVar.tarray.fields[i].twidechar := TArrWideChar(v^.Data)[i];
end;
SetLength(TArrU8(V^.Data), 0);
end;
{$ENDIF}
end;
Dispose(V);
end;
{$ENDIF}
function InnerfuseCall(SE: TIFPSExec; Self, Address: Pointer; CallingConv: TCallingConvention; Params: TIfList; res: PIfVariant; SupFunc: PResourcePtrSupportFuncs): Boolean;
var
Stack: ansistring;
I: Longint;
RegUsage: Byte;
CallData: TIfList;
pp: ^Byte;
EAX, EDX, ECX: Longint;
function GetPtr(fVar: PIfVariant): Boolean;
var
varPtr: Pointer;
UseReg: Boolean;
tempstr: string;
p: Pointer;
begin
Result := False;
if fVar^.RefCount >= IFPSAddrStackStart then begin
fvar^.RefCount := FVar^.RefCount and not IFPSAddrStackStart;
case fVar^.FType^.BaseType of
btArray:
begin
if Copy(fvar^.Ftype^.ExportName, 1, 10) = '!OPENARRAY' then
begin
p := CreateOpenArray(True, SE, SupFunc, FVar);
if p = nil then exit;
CallData.Add(p);
case RegUsage of
0: begin EAX := Longint(@POpenArray(p)^.Data[1]); Inc(RegUsage); end;
1: begin EDX := Longint(@POpenArray(p)^.Data[1]); Inc(RegUsage); end;
2: begin ECX := Longint(@POpenArray(p)^.Data[1]); Inc(RegUsage); end;
else begin
Stack := #0#0#0#0 + Stack;
Pointer((@Stack[1])^) := @POpenArray(p)^.Data[1];
end;
end;
case RegUsage of
0: begin EAX := Longint(POpenArray(p)^.ItemCount - 1); Inc(RegUsage); end;
1: begin EDX := Longint(POpenArray(p)^.ItemCount -1); Inc(RegUsage); end;
2: begin ECX := Longint(POpenArray(p)^.ItemCount -1); Inc(RegUsage); end;
else begin
Stack := #0#0#0#0 + Stack;
Longint((@Stack[1])^) := POpenArray(p)^.ItemCount -1;
end;
end;
Result := True;
Exit;
end else begin
{$IFDEF DYNARRAY}
p := CreateDynamicArray(True, Se, SupFunc, FVar);
if p = nil then exit;
varPtr := @(PDynArray(p)^.Data);
CallData.Add(p);
{$ELSE}
Exit;
{$ENDIF}
end;
end;
{$IFDEF HAVEVARIANT}
btVariant:
begin
p := CreateVariant(True, SE, SupFunc, FVar);
VarPtr := @(PVariant(p)^.P);
CallData.Add(p);
end;
{$ENDIF}
btRecord:
begin
p := CreateRecord(True, SE, SupFunc, FVar);
VarPtr := @(PRecord(P).Data[1]);
CallData.Add(p);
end;
btResourcePointer:
begin
if SupFunc = nil then exit;
tempstr := SupFunc^.VarPtrToStr(SupFunc, SE, fVar);
if length(tempstr) <> 4 then exit;
VarPtr := Pointer((@tempstr[1])^);
end;
btString: VarPtr := @tbtString(fvar^.tstring);
btU8, btS8, btU16, btS16, btU32, btS32, btSingle, btDouble,
btExtended{$IFNDEF NOINT64}, bts64{$ENDIF}: VarPtr := @(fVar^.tu8);
else begin
exit; //invalid type
end;
end; {case}
case RegUsage of
0: begin EAX := Longint(VarPtr); Inc(RegUsage); end;
1: begin EDX := Longint(VarPtr); Inc(RegUsage); end;
2: begin ECX := Longint(VarPtr); Inc(RegUsage); end;
else begin
Stack := #0#0#0#0 + Stack;
Pointer((@Stack[1])^) := VarPtr;
end;
end;
end else begin
UseReg := True;
case fVar^.FType^.BaseType of
btArray:
begin
if Copy(fvar^.Ftype^.ExportName, 1, 10) = '!OPENARRAY' then
begin
p := CreateOpenArray(False, SE, SupFunc, FVar);
if p =nil then exit;
CallData.Add(p);
case RegUsage of
0: begin EAX := Longint(@POpenArray(p)^.Data[1]); Inc(RegUsage); end;
1: begin EDX := Longint(@POpenArray(p)^.Data[1]); Inc(RegUsage); end;
2: begin ECX := Longint(@POpenArray(p)^.Data[1]); Inc(RegUsage); end;
else begin
Stack := #0#0#0#0 + Stack;
Pointer((@Stack[1])^) := @POpenArray(p)^.Data[1];
end;
end;
case RegUsage of
0: begin EAX := Longint(POpenArray(p)^.ItemCount -1); Inc(RegUsage); end;
1: begin EDX := Longint(POpenArray(p)^.ItemCount -1); Inc(RegUsage); end;
2: begin ECX := Longint(POpenArray(p)^.ItemCount -1); Inc(RegUsage); end;
else begin
Stack := #0#0#0#0 + Stack;
Longint((@Stack[1])^) := POpenArray(p)^.ItemCount -1;
end;
end;
Result := True;
exit;
end else begin
{$IFDEF DYNARRAY}
p := CreateDynamicArray(True, Se, SupFunc, FVar);
if p = nil then exit;
CallData.Add(p);
TempStr := #0#0#0#0;
Pointer((@TempStr[1])^) := PDynArray(P)^.Data;
{$ELSE}
Exit;
{$ENDIF}
end;
end;
{$IFDEF HAVEVARIANT}
btVariant:
begin
p := CreateVariant(False, Se, SupFunc, FVar);
if p = nil then exit;
TempStr := #0#0#0#0;
Pointer((@TempStr[1])^) := @(PVariant(p).P);
CallData.Add(p);
end;
{$ENDIF}
btRecord:
begin
p := CreateRecord(False, SE, SupFunc, Fvar);
CallData.Add(p);
TempStr := #0#0#0#0;
Pointer((@TempStr[1])^) := @(PRecord(p).Data[1]);
end;
btDouble: {8 bytes} begin
TempStr := #0#0#0#0#0#0#0#0;
UseReg := False;
double((@TempStr[1])^) := fVar^.tdouble;
end;
btSingle: {4 bytes} begin
TempStr := #0#0#0#0;
UseReg := False;
Single((@TempStr[1])^) := fVar^.tsingle;
end;
btExtended: {10 bytes} begin
UseReg := False;
TempStr:= #0#0#0#0#0#0#0#0#0#0#0#0;
Extended((@TempStr[1])^) := fVar^.textended;
end;
btChar,
btU8,
btS8: begin
TempStr := char(fVar^.tu8) + #0#0#0;
end;
{$IFNDEF NOWIDESTRING}btWideChar, {$ENDIF}
btu16, btS16: begin
TempStr := #0#0#0#0;
Word((@TempStr[1])^) := fVar^.tu16;
end;
btu32, bts32: begin
TempStr := #0#0#0#0;
Longint((@TempStr[1])^) := fVar^.tu32;
end;
btPChar, btString: begin
TempStr := #0#0#0#0;
Pointer((@TempStr[1])^) := fVar^.tstring;
end;
{$IFNDEF NOWIDESTRING}
btWideString: begin
TempStr := #0#0#0#0;
Pointer((@TempStr[1])^) := fVar^.twidestring;
end;
{$ENDIF}
btProcPtr:
begin
if SupFunc = nil then exit;
TempStr := SupFunc^.ProcPtrToStr(SupFunc, SE, fVar);
if Length(TempStr) > 4 then
UseReg := False
else
SetLength(TempStr, 4);
end;
btResourcePointer:
begin
if SupFunc = nil then exit;
TempStr := SupFunc^.PtrToStr(SupFunc, SE, fVar);
if Length(TempStr) > 4 then
UseReg := False
else
SetLength(TempStr, 4);
end;
{$IFNDEF NOINT64}bts64: begin
TempStr:= #0#0#0#0#0#0#0#0;
Int64((@TempStr[1])^) := fvar^.ts64;
UseReg := False;
end;{$ENDIF}
end; {case}
if UseReg then
begin
case RegUsage of
0: begin EAX := Longint((@Tempstr[1])^); Inc(RegUsage); end;
1: begin EDX := Longint((@Tempstr[1])^); Inc(RegUsage); end;
2: begin ECX := Longint((@Tempstr[1])^); Inc(RegUsage); end;
else Stack := TempStr + Stack;
end;
end else begin
Stack := TempStr + Stack;
end;
end;
Result := True;
end;
begin
InnerfuseCall := False;
if Address = nil then
exit; // need address
Stack := '';
CallData := TIfList.Create;
res := rp(res);
if res <> nil then
res^.RefCount := res^.RefCount or IFPSAddrStackStart;
try
try
case CallingConv of
ccRegister: begin
EAX := 0;
EDX := 0;
ECX := 0;
RegUsage := 0;
if assigned(Self) then begin
RegUsage := 1;
EAX := Longint(Self);
end;
for I := 0 to Params.Count - 1 do
begin
if not GetPtr(rp(Params.GetItem(I))) then Exit;
end;
if assigned(res) then begin
case res^.FType^.BaseType of
btResourcePointer:
begin
if SupFunc = nil then exit;
if SupFunc^.ResultMethod = rmParam then GetPtr(res);
end;
{$IFNDEF NOWIDESTRING}btWideString, {$ENDIF}btrecord, btstring{$IFDEF HAVEVARIANT}, btVariant{$ENDIF}: GetPtr(res);
end;
case res^.FType^.BaseType of
btSingle: res^.tsingle := RealFloatCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4);
btDouble: res^.tdouble:= RealFloatCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4);
btExtended: res^.textended:= RealFloatCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4);
btchar,btU8, btS8: res^.tu8 := RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 1, nil);
{$IFNDEF NOWIDESTRING}btWideChar, {$ENDIF}btu16, bts16: res^.tu16:= RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 2, nil);
btu32, bts32: res^.tu32:= RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil);
btPChar: TBTSTRING(res^.tstring) := Pchar(RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil));
{$IFNDEF NOINT64}bts64:
begin
EAX := RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, @EDX);
res^.ts64 := (EDX shl 32) or EAX;
end;
{$ENDIF}
{$IFDEF HAVEVARIANT}btVariant, {$ENDIF}
{$IFNDEF NOWIDESTRING}btWidestring: RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil); {$ENDIF}
btrecord, btstring: RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
btResourcePointer: if SupFunc^.ResultMethod = rmParam then
RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil)
else
SupFunc^.ResToPtr(SupFunc, SE, RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil), res);
else
exit;
end;
end else
RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
Result := True;
end;
ccPascal: begin
RegUsage := 3;
for I := 0 to Params.Count - 1 do begin
if not GetPtr(Params.GetItem(i)) then Exit;
end;
if assigned(res) then begin
case res^.FType^.BaseType of
btResourcePointer:
begin
if SupFunc = nil then exit;
if SupFunc^.ResultMethod = rmParam then GetPtr(res);
end;
{$IFNDEF NOWIDESTRING}btWideString, {$ENDIF}btrecord, btstring{$IFDEF HAVEVARIANT}, btVariant{$ENDIF}: GetPtr(res);
end;
end;
if assigned(Self) then begin
Stack := #0#0#0#0 +Stack;
Pointer((@Stack[1])^) := Self;
end;
if assigned(res) then begin
case res^.FType^.BaseType of
btSingle: res^.tsingle := RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
btDouble: res^.tdouble:= RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
btExtended: res^.textended:= RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
btChar, btU8, btS8: res^.tu8 := RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 1, nil);
{$IFNDEF NOWIDESTRING}btWideChar, {$ENDIF}btu16, bts16: res^.tu16:= RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 2, nil);
btu32, bts32: res^.tu32:= RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil);
btPChar: TBTSTRING(res^.tstring) := Pchar(RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil));
{$IFNDEF NOINT64}bts64:
begin
EAX := RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, @EDX);
res^.ts64 := (EDX shl 32) or EAX;
end;
{$ENDIF}
{$IFDEF HAVEVARIANT}btVariant, {$ENDIF}
btrecord, btstring: RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
btResourcePointer: if SupFunc^.ResultMethod = rmParam then
RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil)
else
SupFunc^.ResToPtr(SupFunc, SE, RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil), res);
else
exit;
end;
end else
RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
Result := True;
end;
CCCdecl: begin
RegUsage := 3;
if assigned(Self) then begin
Stack := #0#0#0#0;
Pointer((@Stack[1])^) := Self;
end;
for I := Params.Count - 1 downto 0 do begin
if not GetPtr(Params.GetItem(I)) then Exit;
end;
if assigned(res) then begin
case res^.FType^.BaseType of
btSingle: res^.tsingle := RealFloatCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
btDouble: res^.tdouble:= RealFloatCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
btExtended: res^.textended:= RealFloatCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
btCHar, btU8, btS8: res^.tu8 := RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 1, nil);
{$IFNDEF NOWIDESTRING}btWideChar, {$ENDIF}btu16, bts16: res^.tu16:= RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 2, nil);
btu32, bts32: res^.tu32:= RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil);
btPChar: TBTSTRING(res^.tstring) := Pchar(RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil));
{$IFNDEF NOINT64}bts64:
begin
EAX := RealCall_CDecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, @EDX);
res^.ts64 := (EDX shl 32) or EAX;
end;
{$ENDIF}
{$IFDEF HAVEVARIANT}btVariant, {$ENDIF}{$IFNDEF NOWIDESTRING}btWideString, {$ENDIF}
btrecord, btstring: begin GetPtr(res); RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil); end;
btResourcePointer: begin
if SupFunc = nil then exit;
if SupFunc^.ResultMethod = rmParam then begin
GetPtr(res);
RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
end else
SupFunc^.ResToPtr(SupFunc, SE, RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil), res);
end;
else
exit;
end;
end else begin
RealCall_CDecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
end;
Result := True;
end;
CCStdCall: begin
RegUsage := 3;
if assigned(Self) then begin
Stack := #0#0#0#0;
Pointer((@Stack[1])^) := Self;
end;
for I := Params.Count - 1 downto 0 do begin
if not GetPtr(Params.GetItem(I)) then exit;
end;
if assigned(res) then begin
case res^.FType^.BaseType of
btSingle: res^.tsingle := RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
btDouble: res^.tdouble:= RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
btExtended: res^.textended:= RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
btChar, btU8, btS8: res^.tu8 := RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 1, nil);
{$IFNDEF NOWIDESTRING}btWideChar, {$ENDIF}btu16, bts16: res^.tu16:= RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 2, nil);
btu32, bts32: res^.tu32:= RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil);
btPChar: TBTSTRING(res^.tstring) := Pchar(RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil));
{$IFNDEF NOINT64}bts64:
begin
EAX := RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, @EDX);
res^.ts64 := (EDX shl 32) or EAX;
end;
{$ENDIF}
{$IFDEF HAVEVARIANT}btVariant, {$ENDIF}{$IFNDEF NOWIDESTRING}btWideString, {$ENDIF}
btrecord, btstring: begin GetPtr(res); RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil); end;
btResourcePointer: begin
if SupFunc = nil then exit;
if SupFunc^.ResultMethod = rmParam then begin
GetPtr(res);
RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
end else
SupFunc^.ResToPtr(SupFunc, SE, RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil), res);
end;
else
exit;
end;
end else begin
RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
end;
Result := True;
end;
end;
except
on e: Exception do
begin
SE.CMD_Err2(erCustomError, e.Message);
Result := False;
end;
end;
finally
if res <> nil then
res^.RefCount := res^.RefCount and not IFPSAddrStackStart;
for i := CallData.Count -1 downto 0 do
begin
pp := CallData.GetItem(i);
case pp^ of
0: DestroyOpenArray(SE, SupFunc, Pointer(pp));
{$IFDEF HAVEVARIANT}1: DestroyVariant(SE, SupFunc, Pointer(pp)); {$ENDIF}
2: DestroyRecord(SE, SupFunc, Pointer(pp));
{$IFDEF DYNARRAY}3: DestroyDynamicArray(SE, SupFunc, Pointer(pp));{$ENDIF}
end;
end;
CallData.Free;
end;
end;
{$IFDEF HAVEVARIANT}
begin
VNull := Null;
{$ENDIF}
end.