function InnerfuseCall(Self, Address: Pointer; CallingConv: TCallingConvention; Params: PVariableManager; Res: PIFVariant): Boolean; // res should already have been created with the type used for it
function ReadHeader(SE: TIfPasScript; Decl: String; var FuncName, FuncParam: String; Var CC: TCallingConvention): Boolean;
implementation
function ReadHeader(SE: TIfPasScript; Decl: String; var FuncName, FuncParam: String; Var CC: TCallingConvention): Boolean;
var
Parser: TIfPascalParser;
CurrVar: string;
FuncRes,
CurrType: Longint;
E: TIFParserError;
function GetType(const s: string): Longint;
var
t: PTypeRec;
begin
if (S = 'PCHAR') then
begin
t := SE.GetType('!PCHAR');
if t = nil then
begin
t := Se.AddTypeEx('!PCHAR');
t^.Ext := Pointer(1);
end;
GetType := Longint(T);
end else
begin
t := SE.GetType(S);
if not assigned(t) then begin GetType := 0; exit; end;
case T.atypeid of
CSV_UByte,
CSV_SByte,
CSV_UInt16,
CSV_SInt16,
CSV_UInt32,
CSV_SInt32,
CSV_Char,
CSV_String{,
CSV_Record}: GetType := Longint(T);
else GetType := 0;
end;
end;
end;
begin
Parser := TIfPascalParser.Create;
ReadHeader := False;
if not Parser.SetText(Decl, E) then
begin
parser.Free;
exit;
end;
if Parser.CurrTokenId = CSTII_Procedure then
FuncRes := 0
else
FuncRes := 1;
Parser.Next;
FuncName := Parser.GetToken;
Parser.Next;
FuncParam := '';
CurrVar := '';
if Parser.CurrTokenId = CSTI_OpenRound then begin
Parser.Next;
while True do begin
if Parser.CurrTokenId = CSTI_Eof then begin
Parser.Free;
exit;
end;
if Parser.CurrTokenId = CSTII_Var then begin
CurrVar := '!';
Parser.Next;
end; {if}
while True do begin
if Parser.CurrTokenId = CSTI_Eof then begin
Parser.Free;
exit;
end;
if Parser.CurrTokenId <> CSTI_Identifier then begin
if Parser.CurrTokenId = CSTI_CloseRound then begin
Parser.Next;
break;
end; {if}
Parser.Next;
end;
end;
if FuncRes = 1 then begin
Parser.Next;
FuncRes := GetType(Parser.GetToken);
if FuncRes = 0 then begin
Parser.Free;
exit;
end;
Parser.Next;
end;
CC := ccRegister;
if Parser.CurrTokenID = CSTI_Semicolon then
begin
Parser.Next;
if Parser.CurrTokenId = CSTI_Identifier then
begin
if Parser.GetToken = 'STDCALL' then
CC := CCStdCall
else if Parser.GetToken = 'CDECL' then
CC := CCCdecl
else if Parser.GetToken = 'PASCAL' then
CC := ccPascal;
// Register is default.
end;
end;
FuncParam := inttostr(FuncRes) + FuncParam;
ReadHeader := True;
Parser.Free;
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):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
add 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:
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): 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
add 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:
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): 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
add 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 edx
dec ecx
or ecx, ecx
jnz @@6
end;
Result := R;
end;
function InnerfuseCall(Self, Address: Pointer; CallingConv: TCallingConvention; Params: PVariableManager; Res: PIFVariant): Boolean; // res should already have been created with the type used for it
var
Stack: ansistring;
i: Longint;
RegUsage: Byte;
EAX, EDX, ECX: Longint;
begin
InnerfuseCall := False;
if Address = nil then
exit; // need address
stack := '';
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 VM_Count(Params)-1 do
begin
if VM_Get(Params, I)^.vtype^.atypeid = CSV_VAR then // var parameter
begin
case GetVarLink(VM_Get(Params, I))^.vtype^.atypeid of
CSV_Char, CSV_UByte, CSV_SByte: begin
case RegUsage of
0: begin EAX := Longint(@GetVarLink(VM_Get(Params, I))^.CV_UByte); inc(RegUsage);end;
1: begin EDX := Longint(@GetVarLink(VM_Get(Params, I))^.CV_UByte); inc(RegUsage);end;
2: begin ECX := Longint(@GetVarLink(VM_Get(Params, I))^.CV_UByte); inc(RegUsage);end;