mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-26 20:23:42 +02:00
801 lines
24 KiB
PHP
801 lines
24 KiB
PHP
{
|
|
$Id$
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 1999-2000 by the Free Pascal development team
|
|
|
|
This unit makes Free Pascal as much as possible Delphi compatible
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program 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.
|
|
|
|
**********************************************************************}
|
|
|
|
{****************************************************************************
|
|
Internal Routines called from the Compiler
|
|
****************************************************************************}
|
|
|
|
{ the reverse order of the parameters make code generation easier }
|
|
function fpc_do_is(aclass : tclass;aobject : tobject) : boolean;[public,alias: 'FPC_DO_IS']; {$ifdef hascompilerproc} compilerproc; {$endif}
|
|
begin
|
|
fpc_do_is:=assigned(aobject) and assigned(aclass) and
|
|
aobject.inheritsfrom(aclass);
|
|
end;
|
|
|
|
|
|
{ the reverse order of the parameters make code generation easier }
|
|
function fpc_do_as(aclass : tclass;aobject : tobject): tobject;[public,alias: 'FPC_DO_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
|
|
begin
|
|
if assigned(aobject) and not(aobject.inheritsfrom(aclass)) then
|
|
handleerrorframe(219,get_frame);
|
|
result := aobject;
|
|
end;
|
|
|
|
{$ifndef HASINTF}
|
|
{ dummies for make cycle with 1.0.x }
|
|
procedure fpc_intf_decr_ref(var i: pointer);saveregisters;[public,alias: 'FPC_INTF_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
|
|
begin
|
|
end;
|
|
|
|
procedure fpc_intf_incr_ref(const i: pointer);saveregisters;[public,alias: 'FPC_INTF_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
|
|
begin
|
|
end;
|
|
|
|
procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; {$ifdef hascompilerproc} compilerproc; {$endif}
|
|
begin
|
|
end;
|
|
|
|
procedure fpc_intf_as(var D: pointer; const S: pointer; const iid: TGUID);[public,alias: 'FPC_INTF_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
|
|
begin
|
|
end;
|
|
|
|
{$else HASINTF}
|
|
|
|
{ interface helpers }
|
|
procedure fpc_intf_decr_ref(var i: pointer);saveregisters;[public,alias: 'FPC_INTF_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
|
|
begin
|
|
if assigned(i) then
|
|
IUnknown(i)._Release;
|
|
i:=nil;
|
|
end;
|
|
|
|
{$ifdef hascompilerproc}
|
|
{ local declaration for intf_decr_ref for local access }
|
|
procedure intf_decr_ref(var i: pointer);saveregisters; [external name 'FPC_INTF_DECR_REF'];
|
|
{$endif hascompilerproc}
|
|
|
|
|
|
procedure fpc_intf_incr_ref(i: pointer);saveregisters;[public,alias: 'FPC_INTF_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
|
|
begin
|
|
if assigned(i) then
|
|
IUnknown(i)._AddRef;
|
|
end;
|
|
|
|
{$ifdef hascompilerproc}
|
|
{ local declaration of intf_incr_ref for local access }
|
|
procedure intf_incr_ref(i: pointer);saveregisters; [external name 'FPC_INTF_INCR_REF'];
|
|
{$endif hascompilerproc}
|
|
|
|
procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; {$ifdef hascompilerproc} compilerproc; {$endif}
|
|
begin
|
|
if assigned(S) then
|
|
IUnknown(S)._AddRef;
|
|
if assigned(D) then
|
|
IUnknown(D)._Release;
|
|
D:=S;
|
|
end;
|
|
|
|
function fpc_intf_as(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_INTF_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
|
|
const
|
|
S_OK = 0;
|
|
var
|
|
tmpi: pointer; // _AddRef before _Release
|
|
begin
|
|
if assigned(S) then
|
|
begin
|
|
if IUnknown(S).QueryInterface(iid,tmpi)<>S_OK then
|
|
handleerror(219);
|
|
fpc_intf_as:=tmpi;
|
|
end
|
|
else
|
|
fpc_intf_as:=nil;
|
|
end;
|
|
|
|
|
|
function fpc_class_as_intf(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_CLASS_AS_INTF']; {$ifdef hascompilerproc} compilerproc; {$endif}
|
|
const
|
|
S_OK = 0;
|
|
var
|
|
tmpi: pointer; // _AddRef before _Release
|
|
begin
|
|
if assigned(S) then
|
|
begin
|
|
if not TObject(S).GetInterface(iid,tmpi) then
|
|
handleerror(219);
|
|
fpc_class_as_intf:=tmpi;
|
|
end
|
|
else
|
|
fpc_class_as_intf:=nil;
|
|
end;
|
|
{$endif HASINTF}
|
|
|
|
|
|
{****************************************************************************
|
|
TOBJECT
|
|
****************************************************************************}
|
|
|
|
constructor TObject.Create;
|
|
|
|
begin
|
|
end;
|
|
|
|
destructor TObject.Destroy;
|
|
|
|
begin
|
|
end;
|
|
|
|
procedure TObject.Free;
|
|
|
|
begin
|
|
// the call via self avoids a warning
|
|
if self<>nil then
|
|
self.destroy;
|
|
end;
|
|
|
|
class function TObject.InstanceSize : LongInt;
|
|
|
|
type
|
|
plongint = ^longint;
|
|
|
|
begin
|
|
{ type of self is class of tobject => it points to the vmt }
|
|
{ the size is saved at offset 0 }
|
|
InstanceSize:=plongint(self)^;
|
|
end;
|
|
|
|
procedure InitInterfacePointers(objclass: tclass;instance : pointer);
|
|
|
|
{$ifdef HASINTF}
|
|
var
|
|
intftable : pinterfacetable;
|
|
i : longint;
|
|
begin
|
|
if assigned(objclass.classparent) then
|
|
InitInterfacePointers(objclass.classparent,instance);
|
|
intftable:=objclass.getinterfacetable;
|
|
if assigned(intftable) then
|
|
for i:=0 to intftable^.EntryCount-1 do
|
|
ppointer(@(PChar(instance)[intftable^.Entries[i].IOffset]))^:=
|
|
pointer(intftable^.Entries[i].VTable);
|
|
end;
|
|
{$else HASINTF}
|
|
begin
|
|
end;
|
|
{$endif HASINTF}
|
|
|
|
class function TObject.InitInstance(instance : pointer) : tobject;
|
|
|
|
begin
|
|
fillchar(instance^,self.instancesize,0);
|
|
{ insert VMT pointer into the new created memory area }
|
|
{ (in class methods self contains the VMT!) }
|
|
ppointer(instance)^:=pointer(self);
|
|
{$ifdef HASINTF}
|
|
InitInterfacePointers(self,instance);
|
|
{$endif HASINTF}
|
|
InitInstance:=TObject(Instance);
|
|
end;
|
|
|
|
class function TObject.ClassParent : tclass;
|
|
|
|
begin
|
|
{ type of self is class of tobject => it points to the vmt }
|
|
{ the parent vmt is saved at offset vmtParent }
|
|
classparent:=pclass(pointer(self)+vmtParent)^;
|
|
end;
|
|
|
|
class function TObject.NewInstance : tobject;
|
|
|
|
var
|
|
p : pointer;
|
|
|
|
begin
|
|
getmem(p,instancesize);
|
|
if p <> nil then
|
|
InitInstance(p);
|
|
NewInstance:=TObject(p);
|
|
end;
|
|
|
|
procedure TObject.FreeInstance;
|
|
|
|
var
|
|
p : Pointer;
|
|
|
|
begin
|
|
CleanupInstance;
|
|
|
|
{ self is a register, so we can't pass it call by reference }
|
|
p:=Pointer(Self);
|
|
FreeMem(p,InstanceSize);
|
|
end;
|
|
|
|
function TObject.ClassType : TClass;
|
|
|
|
begin
|
|
ClassType:=TClass(Pointer(Self)^)
|
|
end;
|
|
|
|
type
|
|
tmethodnamerec = packed record
|
|
name : pshortstring;
|
|
addr : pointer;
|
|
end;
|
|
|
|
tmethodnametable = packed record
|
|
count : dword;
|
|
entries : packed array[0..0] of tmethodnamerec;
|
|
end;
|
|
|
|
pmethodnametable = ^tmethodnametable;
|
|
|
|
class function TObject.MethodAddress(const name : shortstring) : pointer;
|
|
|
|
var
|
|
UName : ShortString;
|
|
methodtable : pmethodnametable;
|
|
i : dword;
|
|
c : tclass;
|
|
|
|
begin
|
|
UName := UpCase(name);
|
|
c:=self;
|
|
while assigned(c) do
|
|
begin
|
|
methodtable:=pmethodnametable((Pointer(c)+vmtMethodTable)^);
|
|
if assigned(methodtable) then
|
|
begin
|
|
for i:=0 to methodtable^.count-1 do
|
|
if UpCase(methodtable^.entries[i].name^)=UName then
|
|
begin
|
|
MethodAddress:=methodtable^.entries[i].addr;
|
|
exit;
|
|
end;
|
|
end;
|
|
c:=c.ClassParent;
|
|
end;
|
|
MethodAddress:=nil;
|
|
end;
|
|
|
|
|
|
class function TObject.MethodName(address : pointer) : shortstring;
|
|
var
|
|
methodtable : pmethodnametable;
|
|
i : dword;
|
|
c : tclass;
|
|
begin
|
|
c:=self;
|
|
while assigned(c) do
|
|
begin
|
|
methodtable:=pmethodnametable((Pointer(c)+vmtMethodTable)^);
|
|
if assigned(methodtable) then
|
|
begin
|
|
for i:=0 to methodtable^.count-1 do
|
|
if methodtable^.entries[i].addr=address then
|
|
begin
|
|
MethodName:=methodtable^.entries[i].name^;
|
|
exit;
|
|
end;
|
|
end;
|
|
c:=c.ClassParent;
|
|
end;
|
|
MethodName:='';
|
|
end;
|
|
|
|
|
|
function TObject.FieldAddress(const name : shortstring) : pointer;
|
|
type
|
|
PFieldInfo = ^TFieldInfo;
|
|
TFieldInfo = packed record
|
|
FieldOffset: LongWord;
|
|
ClassTypeIndex: Word;
|
|
Name: ShortString;
|
|
end;
|
|
|
|
PFieldTable = ^TFieldTable;
|
|
TFieldTable = packed record
|
|
FieldCount: Word;
|
|
ClassTable: Pointer;
|
|
{ Fields: array[Word] of TFieldInfo; Elements have variant size! }
|
|
end;
|
|
|
|
var
|
|
UName: ShortString;
|
|
CurClassType: TClass;
|
|
FieldTable: PFieldTable;
|
|
FieldInfo: PFieldInfo;
|
|
i: Integer;
|
|
|
|
begin
|
|
if Length(name) > 0 then
|
|
begin
|
|
UName := UpCase(name);
|
|
CurClassType := ClassType;
|
|
while CurClassType <> nil do
|
|
begin
|
|
FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
|
|
if FieldTable <> nil then
|
|
begin
|
|
FieldInfo := PFieldInfo(Pointer(FieldTable) + 6);
|
|
for i := 0 to FieldTable^.FieldCount - 1 do
|
|
begin
|
|
if UpCase(FieldInfo^.Name) = UName then
|
|
begin
|
|
fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
|
|
exit;
|
|
end;
|
|
Inc(Pointer(FieldInfo), 7 + Length(FieldInfo^.Name));
|
|
end;
|
|
end;
|
|
{ Try again with the parent class type }
|
|
CurClassType := CurClassType.ClassParent;
|
|
end;
|
|
end;
|
|
|
|
fieldaddress:=nil;
|
|
end;
|
|
|
|
function TObject.SafeCallException(exceptobject : tobject;
|
|
exceptaddr : pointer) : longint;
|
|
|
|
begin
|
|
safecallexception:=0;
|
|
end;
|
|
|
|
class function TObject.ClassInfo : pointer;
|
|
|
|
begin
|
|
ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
|
|
end;
|
|
|
|
class function TObject.ClassName : ShortString;
|
|
|
|
begin
|
|
ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
|
|
end;
|
|
|
|
class function TObject.ClassNameIs(const name : string) : boolean;
|
|
|
|
begin
|
|
ClassNameIs:=Upcase(ClassName)=Upcase(name);
|
|
end;
|
|
|
|
class function TObject.InheritsFrom(aclass : TClass) : Boolean;
|
|
|
|
var
|
|
c : tclass;
|
|
|
|
begin
|
|
c:=self;
|
|
while assigned(c) do
|
|
begin
|
|
if c=aclass then
|
|
begin
|
|
InheritsFrom:=true;
|
|
exit;
|
|
end;
|
|
c:=c.ClassParent;
|
|
end;
|
|
InheritsFrom:=false;
|
|
end;
|
|
|
|
class function TObject.stringmessagetable : pstringmessagetable;
|
|
|
|
type
|
|
pdword = ^dword;
|
|
|
|
begin
|
|
stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
|
|
end;
|
|
|
|
type
|
|
tmessagehandler = procedure(var msg) of object;
|
|
tmessagehandlerrec = packed record
|
|
proc : pointer;
|
|
obj : pointer;
|
|
end;
|
|
|
|
|
|
procedure TObject.Dispatch(var message);
|
|
|
|
type
|
|
tmsgtable = record
|
|
index : dword;
|
|
method : pointer;
|
|
end;
|
|
|
|
pmsgtable = ^tmsgtable;
|
|
|
|
pdword = ^dword;
|
|
|
|
var
|
|
index : dword;
|
|
count,i : longint;
|
|
msgtable : pmsgtable;
|
|
p : pointer;
|
|
vmt : tclass;
|
|
msghandler : tmessagehandler;
|
|
|
|
begin
|
|
index:=dword(message);
|
|
vmt:=ClassType;
|
|
while assigned(vmt) do
|
|
begin
|
|
// See if we have messages at all in this class.
|
|
p:=pointer(vmt)+vmtDynamicTable;
|
|
If Assigned(p) and (Pdword(p)^<>0) then
|
|
begin
|
|
msgtable:=pmsgtable(pdword(P)^+4);
|
|
count:=pdword(pdword(P)^)^;
|
|
end
|
|
else
|
|
Count:=0;
|
|
{ later, we can implement a binary search here }
|
|
for i:=0 to count-1 do
|
|
begin
|
|
if index=msgtable[i].index then
|
|
begin
|
|
p:=msgtable[i].method;
|
|
tmessagehandlerrec(msghandler).proc:=p;
|
|
tmessagehandlerrec(msghandler).obj:=self;
|
|
msghandler(message);
|
|
{ we don't need any longer the assembler
|
|
solution
|
|
asm
|
|
pushl message
|
|
pushl %esi
|
|
movl p,%edi
|
|
call *%edi
|
|
end;
|
|
}
|
|
exit;
|
|
end;
|
|
end;
|
|
vmt:=vmt.ClassParent;
|
|
end;
|
|
DefaultHandler(message);
|
|
end;
|
|
|
|
procedure TObject.DispatchStr(var message);
|
|
|
|
type
|
|
pdword = ^dword;
|
|
|
|
var
|
|
name : shortstring;
|
|
count,i : longint;
|
|
msgstrtable : pmsgstrtable;
|
|
p : pointer;
|
|
vmt : tclass;
|
|
msghandler : tmessagehandler;
|
|
|
|
begin
|
|
name:=pshortstring(@message)^;
|
|
vmt:=ClassType;
|
|
while assigned(vmt) do
|
|
begin
|
|
p:=(pointer(vmt)+vmtMsgStrPtr);
|
|
If (P<>Nil) and (PDWord(P)^<>0) then
|
|
begin
|
|
count:=pdword(pdword(p)^)^;
|
|
msgstrtable:=pmsgstrtable(pdword(P)^+4);
|
|
end
|
|
else
|
|
Count:=0;
|
|
{ later, we can implement a binary search here }
|
|
for i:=0 to count-1 do
|
|
begin
|
|
if name=msgstrtable[i].name^ then
|
|
begin
|
|
p:=msgstrtable[i].method;
|
|
tmessagehandlerrec(msghandler).proc:=p;
|
|
tmessagehandlerrec(msghandler).obj:=self;
|
|
msghandler(message);
|
|
{ we don't need any longer the assembler
|
|
solution
|
|
asm
|
|
pushl message
|
|
pushl %esi
|
|
movl p,%edi
|
|
call *%edi
|
|
end;
|
|
}
|
|
exit;
|
|
end;
|
|
end;
|
|
vmt:=vmt.ClassParent;
|
|
end;
|
|
DefaultHandlerStr(message);
|
|
end;
|
|
|
|
procedure TObject.DefaultHandler(var message);
|
|
|
|
begin
|
|
end;
|
|
|
|
procedure TObject.DefaultHandlerStr(var message);
|
|
|
|
begin
|
|
end;
|
|
|
|
procedure TObject.CleanupInstance;
|
|
|
|
var
|
|
vmt : tclass;
|
|
|
|
begin
|
|
vmt:=ClassType;
|
|
while vmt<>nil do
|
|
begin
|
|
if Assigned(Pointer((Pointer(vmt)+vmtInitTable)^)) then
|
|
int_finalize(Pointer(Self),Pointer((Pointer(vmt)+vmtInitTable)^));
|
|
vmt:=vmt.ClassParent;
|
|
end;
|
|
end;
|
|
|
|
procedure TObject.AfterConstruction;
|
|
|
|
begin
|
|
end;
|
|
|
|
procedure TObject.BeforeDestruction;
|
|
|
|
begin
|
|
end;
|
|
|
|
{$ifdef HASINTF}
|
|
function IsGUIDEqual(const guid1, guid2: tguid): boolean;
|
|
begin
|
|
IsGUIDEqual:=
|
|
(guid1.D1=guid2.D1) and
|
|
(PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
|
|
(PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
|
|
(PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
|
|
end;
|
|
|
|
function TObject.getinterface(const iid : tguid;out obj) : boolean;
|
|
var
|
|
IEntry: pinterfaceentry;
|
|
begin
|
|
IEntry:=getinterfaceentry(iid);
|
|
if Assigned(IEntry) then begin
|
|
PDWORD(@obj)^:=DWORD(PDWORD(Self))+IEntry^.IOffset;
|
|
intf_incr_ref(pointer(obj)); { it must be an com interface }
|
|
getinterface:=True;
|
|
end
|
|
else begin
|
|
PDWORD(@Obj)^:=0;
|
|
getinterface:=False;
|
|
end;
|
|
end;
|
|
|
|
function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
|
|
var
|
|
IEntry: pinterfaceentry;
|
|
begin
|
|
IEntry:=getinterfaceentrybystr(iidstr);
|
|
if Assigned(IEntry) then begin
|
|
PDWORD(@obj)^:=DWORD(PDWORD(Self))+IEntry^.IOffset;
|
|
if Assigned(IEntry^.iid) then { for Com interfaces }
|
|
intf_incr_ref(pointer(obj));
|
|
getinterfacebystr:=True;
|
|
end
|
|
else begin
|
|
PDWORD(@Obj)^:=0;
|
|
getinterfacebystr:=False;
|
|
end;
|
|
end;
|
|
|
|
class function TObject.getinterfaceentry(const iid : tguid) : pinterfaceentry;
|
|
var
|
|
i: integer;
|
|
intftable: pinterfacetable;
|
|
Res: pinterfaceentry;
|
|
begin
|
|
getinterfaceentry:=nil;
|
|
intftable:=getinterfacetable;
|
|
if assigned(intftable) then begin
|
|
i:=intftable^.EntryCount;
|
|
Res:=@intftable^.Entries[0];
|
|
while (i>0) and
|
|
not (assigned(Res^.iid) and IsGUIDEqual(Res^.iid^,iid)) do begin
|
|
inc(Res);
|
|
dec(i);
|
|
end;
|
|
if (i>0) then
|
|
getinterfaceentry:=Res;
|
|
end;
|
|
end;
|
|
|
|
class function TObject.getinterfaceentrybystr(const iidstr : string) : pinterfaceentry;
|
|
var
|
|
i: integer;
|
|
intftable: pinterfacetable;
|
|
Res: pinterfaceentry;
|
|
begin
|
|
getinterfaceentrybystr:=nil;
|
|
intftable:=getinterfacetable;
|
|
if assigned(intftable) then begin
|
|
i:=intftable^.EntryCount;
|
|
Res:=@intftable^.Entries[0];
|
|
while (i>0) and (Res^.iidstr^<>iidstr) do begin
|
|
inc(Res);
|
|
dec(i);
|
|
end;
|
|
if (i>0) then
|
|
getinterfaceentrybystr:=Res;
|
|
end;
|
|
end;
|
|
|
|
class function TObject.getinterfacetable : pinterfacetable;
|
|
begin
|
|
getinterfacetable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
|
|
end;
|
|
|
|
{****************************************************************************
|
|
TINTERFACEDOBJECT
|
|
****************************************************************************}
|
|
|
|
function TInterfacedObject.QueryInterface(
|
|
const iid : tguid;out obj) : longint;stdcall;
|
|
|
|
begin
|
|
if getinterface(iid,obj) then
|
|
result:=0
|
|
else
|
|
result:=longint($80004002);
|
|
end;
|
|
|
|
function TInterfacedObject._AddRef : longint;stdcall;
|
|
|
|
begin
|
|
inclocked(frefcount);
|
|
_addref:=frefcount;
|
|
end;
|
|
|
|
function TInterfacedObject._Release : longint;stdcall;
|
|
|
|
begin
|
|
if declocked(frefcount) then
|
|
begin
|
|
destroy;
|
|
_Release:=0;
|
|
end
|
|
else
|
|
_Release:=frefcount;
|
|
end;
|
|
|
|
procedure TInterfacedObject.AfterConstruction;
|
|
|
|
begin
|
|
{ we need to fix the refcount we forced in newinstance }
|
|
{ further, it must be done in a thread safe way }
|
|
declocked(frefcount);
|
|
end;
|
|
|
|
procedure TInterfacedObject.BeforeDestruction;
|
|
|
|
begin
|
|
if frefcount<>0 then
|
|
HandleError(204);
|
|
end;
|
|
|
|
class function TInterfacedObject.NewInstance : TObject;
|
|
|
|
begin
|
|
NewInstance:=inherited NewInstance;
|
|
TInterfacedObject(NewInstance).frefcount:=1;
|
|
end;
|
|
|
|
{$endif HASINTF}
|
|
|
|
{****************************************************************************
|
|
Exception Support
|
|
****************************************************************************}
|
|
|
|
{$i except.inc}
|
|
|
|
{****************************************************************************
|
|
Initialize
|
|
****************************************************************************}
|
|
|
|
{
|
|
$Log$
|
|
Revision 1.24 2002-08-20 18:24:06 jonas
|
|
* interface "as" helpers converted from procedures to functions
|
|
|
|
Revision 1.23 2002/07/30 17:29:19 florian
|
|
* interface helpers for 1.1 compilers without interface support fixed
|
|
|
|
Revision 1.22 2002/07/01 16:29:05 peter
|
|
* sLineBreak changed to normal constant like Kylix
|
|
|
|
Revision 1.21 2002/04/26 15:19:05 peter
|
|
* use saveregisters for incr routines, saves also problems with
|
|
the optimizer
|
|
|
|
Revision 1.20 2002/04/25 20:14:57 peter
|
|
* updated compilerprocs
|
|
* incr ref count has now a value argument instead of var
|
|
|
|
Revision 1.19 2002/03/30 14:52:59 carl
|
|
* don't crash everything if the class allocation failed
|
|
|
|
Revision 1.18 2001/12/26 21:03:56 peter
|
|
* merged fixes from 1.0.x
|
|
|
|
Revision 1.17 2001/09/29 21:32:47 jonas
|
|
* almost all second pass typeconvnode helpers are now processor independent
|
|
* fixed converting boolean to int64/qword
|
|
* fixed register allocation bugs which could cause internalerror 10
|
|
* isnode and asnode are completely processor indepent now as well
|
|
* fpc_do_as now returns its class argument (necessary to be able to use it
|
|
properly with compilerproc)
|
|
|
|
Revision 1.16 2001/08/01 15:00:10 jonas
|
|
+ "compproc" helpers
|
|
* renamed several helpers so that their name is the same as their
|
|
"public alias", which should facilitate the conversion of processor
|
|
specific code in the code generator to processor independent code
|
|
* some small fixes to the val_ansistring and val_widestring helpers
|
|
(always immediately exit if the source string is longer than 255
|
|
chars)
|
|
* fixed fpc_dynarray_high and fpc_dynarray_length if the dynarray is
|
|
still nil (used to crash, now return resp -1 and 0)
|
|
|
|
Revision 1.15 2001/05/27 14:28:44 florian
|
|
+ made the ref. couting MT safe
|
|
|
|
Revision 1.14 2001/04/13 22:30:04 peter
|
|
* remove warnings
|
|
|
|
Revision 1.13 2000/12/20 21:38:23 florian
|
|
* is-operator fixed
|
|
|
|
Revision 1.12 2000/11/12 23:23:34 florian
|
|
* interfaces are basically running
|
|
|
|
Revision 1.11 2000/11/09 17:50:12 florian
|
|
* Finalize to int_finalize renamed
|
|
|
|
Revision 1.10 2000/11/07 23:42:21 florian
|
|
+ AfterConstruction and BeforeDestruction implemented
|
|
+ TInterfacedObject implemented
|
|
|
|
Revision 1.9 2000/11/06 22:03:12 florian
|
|
* another fix
|
|
|
|
Revision 1.8 2000/11/06 21:53:38 florian
|
|
* another fix for interfaces
|
|
|
|
Revision 1.7 2000/11/06 21:35:59 peter
|
|
* removed some warnings
|
|
|
|
Revision 1.6 2000/11/06 20:34:24 peter
|
|
* changed ver1_0 defines to temporary defs
|
|
|
|
Revision 1.5 2000/11/04 17:52:46 florian
|
|
* fixed linker errors
|
|
|
|
Revision 1.4 2000/11/04 16:29:54 florian
|
|
+ interfaces support
|
|
|
|
Revision 1.3 2000/07/22 14:52:01 sg
|
|
* Resolved CVS conflicts for TObject.MethodAddress patch
|
|
|
|
Revision 1.1.2.1 2000/07/22 14:46:57 sg
|
|
* Made TObject.MethodAddress case independent
|
|
}
|