objpas.inc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. This unit makes Free Pascal as much as possible Delphi compatible
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {****************************************************************************
  13. Internal Routines called from the Compiler
  14. ****************************************************************************}
  15. { the reverse order of the parameters make code generation easier }
  16. function fpc_do_is(aclass : tclass;aobject : tobject) : boolean;[public,alias: 'FPC_DO_IS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  17. begin
  18. fpc_do_is:=assigned(aobject) and assigned(aclass) and
  19. aobject.inheritsfrom(aclass);
  20. end;
  21. { the reverse order of the parameters make code generation easier }
  22. function fpc_do_as(aclass : tclass;aobject : tobject): tobject;[public,alias: 'FPC_DO_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  23. begin
  24. if assigned(aobject) and not(aobject.inheritsfrom(aclass)) then
  25. handleerrorframe(219,get_frame);
  26. result := aobject;
  27. end;
  28. {$ifndef HASINTF}
  29. { dummies for make cycle with 1.0.x }
  30. procedure intf_decr_ref(var i: pointer);[public,alias: 'FPC_INTF_DECR_REF'];
  31. begin
  32. end;
  33. procedure intf_incr_ref(const i: pointer);[public,alias: 'FPC_INTF_INCR_REF'];
  34. begin
  35. end;
  36. procedure intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN'];
  37. begin
  38. end;
  39. procedure intf_as(var D: pointer; const S: pointer; const iid: TGUID);[public,alias: 'FPC_INTF_AS'];
  40. begin
  41. end;
  42. {$else HASINTF}
  43. { interface helpers }
  44. procedure fpc_intf_decr_ref(var i: pointer);[public,alias: 'FPC_INTF_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  45. begin
  46. if assigned(i) then
  47. IUnknown(i)._Release;
  48. i:=nil;
  49. end;
  50. {$ifdef hascompilerproc}
  51. { local declaration for intf_decr_ref for local access }
  52. procedure intf_decr_ref(var i: pointer); [external name 'FPC_INTF_DECR_REF'];
  53. {$endif hascompilerproc}
  54. procedure fpc_intf_incr_ref(const i: pointer);[public,alias: 'FPC_INTF_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  55. begin
  56. if assigned(i) then
  57. IUnknown(i)._AddRef;
  58. end;
  59. {$ifdef hascompilerproc}
  60. { local declaration of intf_incr_ref for local access }
  61. procedure intf_incr_ref(const i: pointer); [external name 'FPC_INTF_INCR_REF'];
  62. {$endif hascompilerproc}
  63. procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; {$ifdef hascompilerproc} compilerproc; {$endif}
  64. begin
  65. if assigned(S) then
  66. IUnknown(S)._AddRef;
  67. if assigned(D) then
  68. IUnknown(D)._Release;
  69. D:=S;
  70. end;
  71. procedure fpc_intf_as(var D: pointer; const S: pointer; const iid: TGUID);[public,alias: 'FPC_INTF_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  72. const
  73. S_OK = 0;
  74. var
  75. tmpi: pointer; // _AddRef before _Release
  76. begin
  77. if assigned(S) then
  78. begin
  79. if IUnknown(S).QueryInterface(iid,tmpi)<>S_OK then
  80. handleerror(219);
  81. if assigned(D) then IUnknown(D)._Release;
  82. D:=tmpi;
  83. end
  84. else
  85. intf_decr_ref(D);
  86. end;
  87. {$endif HASINTF}
  88. {****************************************************************************
  89. TOBJECT
  90. ****************************************************************************}
  91. constructor TObject.Create;
  92. begin
  93. end;
  94. destructor TObject.Destroy;
  95. begin
  96. end;
  97. procedure TObject.Free;
  98. begin
  99. // the call via self avoids a warning
  100. if self<>nil then
  101. self.destroy;
  102. end;
  103. class function TObject.InstanceSize : LongInt;
  104. type
  105. plongint = ^longint;
  106. begin
  107. { type of self is class of tobject => it points to the vmt }
  108. { the size is saved at offset 0 }
  109. InstanceSize:=plongint(self)^;
  110. end;
  111. procedure InitInterfacePointers(objclass: tclass;instance : pointer);
  112. var
  113. intftable : pinterfacetable;
  114. i : longint;
  115. begin
  116. {$ifdef HASINTF}
  117. if assigned(objclass.classparent) then
  118. InitInterfacePointers(objclass.classparent,instance);
  119. intftable:=objclass.getinterfacetable;
  120. if assigned(intftable) then
  121. for i:=0 to intftable^.EntryCount-1 do
  122. ppointer(@(PChar(instance)[intftable^.Entries[i].IOffset]))^:=
  123. pointer(intftable^.Entries[i].VTable);
  124. {$endif HASINTF}
  125. end;
  126. class function TObject.InitInstance(instance : pointer) : tobject;
  127. begin
  128. fillchar(instance^,self.instancesize,0);
  129. { insert VMT pointer into the new created memory area }
  130. { (in class methods self contains the VMT!) }
  131. ppointer(instance)^:=pointer(self);
  132. {$ifdef HASINTF}
  133. InitInterfacePointers(self,instance);
  134. {$endif HASINTF}
  135. InitInstance:=TObject(Instance);
  136. end;
  137. class function TObject.ClassParent : tclass;
  138. begin
  139. { type of self is class of tobject => it points to the vmt }
  140. { the parent vmt is saved at offset vmtParent }
  141. classparent:=pclass(pointer(self)+vmtParent)^;
  142. end;
  143. class function TObject.NewInstance : tobject;
  144. var
  145. p : pointer;
  146. begin
  147. getmem(p,instancesize);
  148. InitInstance(p);
  149. NewInstance:=TObject(p);
  150. end;
  151. procedure TObject.FreeInstance;
  152. var
  153. p : Pointer;
  154. begin
  155. CleanupInstance;
  156. { self is a register, so we can't pass it call by reference }
  157. p:=Pointer(Self);
  158. FreeMem(p,InstanceSize);
  159. end;
  160. function TObject.ClassType : TClass;
  161. begin
  162. ClassType:=TClass(Pointer(Self)^)
  163. end;
  164. type
  165. tmethodnamerec = packed record
  166. name : pshortstring;
  167. addr : pointer;
  168. end;
  169. tmethodnametable = packed record
  170. count : dword;
  171. entries : packed array[0..0] of tmethodnamerec;
  172. end;
  173. pmethodnametable = ^tmethodnametable;
  174. class function TObject.MethodAddress(const name : shortstring) : pointer;
  175. var
  176. UName : ShortString;
  177. methodtable : pmethodnametable;
  178. i : dword;
  179. c : tclass;
  180. begin
  181. UName := UpCase(name);
  182. c:=self;
  183. while assigned(c) do
  184. begin
  185. methodtable:=pmethodnametable((Pointer(c)+vmtMethodTable)^);
  186. if assigned(methodtable) then
  187. begin
  188. for i:=0 to methodtable^.count-1 do
  189. if UpCase(methodtable^.entries[i].name^)=UName then
  190. begin
  191. MethodAddress:=methodtable^.entries[i].addr;
  192. exit;
  193. end;
  194. end;
  195. c:=c.ClassParent;
  196. end;
  197. MethodAddress:=nil;
  198. end;
  199. class function TObject.MethodName(address : pointer) : shortstring;
  200. var
  201. methodtable : pmethodnametable;
  202. i : dword;
  203. c : tclass;
  204. begin
  205. c:=self;
  206. while assigned(c) do
  207. begin
  208. methodtable:=pmethodnametable((Pointer(c)+vmtMethodTable)^);
  209. if assigned(methodtable) then
  210. begin
  211. for i:=0 to methodtable^.count-1 do
  212. if methodtable^.entries[i].addr=address then
  213. begin
  214. MethodName:=methodtable^.entries[i].name^;
  215. exit;
  216. end;
  217. end;
  218. c:=c.ClassParent;
  219. end;
  220. MethodName:='';
  221. end;
  222. function TObject.FieldAddress(const name : shortstring) : pointer;
  223. type
  224. PFieldInfo = ^TFieldInfo;
  225. TFieldInfo = packed record
  226. FieldOffset: LongWord;
  227. ClassTypeIndex: Word;
  228. Name: ShortString;
  229. end;
  230. PFieldTable = ^TFieldTable;
  231. TFieldTable = packed record
  232. FieldCount: Word;
  233. ClassTable: Pointer;
  234. { Fields: array[Word] of TFieldInfo; Elements have variant size! }
  235. end;
  236. var
  237. UName: ShortString;
  238. CurClassType: TClass;
  239. FieldTable: PFieldTable;
  240. FieldInfo: PFieldInfo;
  241. i: Integer;
  242. begin
  243. if Length(name) > 0 then
  244. begin
  245. UName := UpCase(name);
  246. CurClassType := ClassType;
  247. while CurClassType <> nil do
  248. begin
  249. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  250. if FieldTable <> nil then
  251. begin
  252. FieldInfo := PFieldInfo(Pointer(FieldTable) + 6);
  253. for i := 0 to FieldTable^.FieldCount - 1 do
  254. begin
  255. if UpCase(FieldInfo^.Name) = UName then
  256. begin
  257. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  258. exit;
  259. end;
  260. Inc(Pointer(FieldInfo), 7 + Length(FieldInfo^.Name));
  261. end;
  262. end;
  263. { Try again with the parent class type }
  264. CurClassType := CurClassType.ClassParent;
  265. end;
  266. end;
  267. fieldaddress:=nil;
  268. end;
  269. function TObject.SafeCallException(exceptobject : tobject;
  270. exceptaddr : pointer) : longint;
  271. begin
  272. safecallexception:=0;
  273. end;
  274. class function TObject.ClassInfo : pointer;
  275. begin
  276. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  277. end;
  278. class function TObject.ClassName : ShortString;
  279. begin
  280. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  281. end;
  282. class function TObject.ClassNameIs(const name : string) : boolean;
  283. begin
  284. ClassNameIs:=Upcase(ClassName)=Upcase(name);
  285. end;
  286. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  287. var
  288. c : tclass;
  289. begin
  290. c:=self;
  291. while assigned(c) do
  292. begin
  293. if c=aclass then
  294. begin
  295. InheritsFrom:=true;
  296. exit;
  297. end;
  298. c:=c.ClassParent;
  299. end;
  300. InheritsFrom:=false;
  301. end;
  302. class function TObject.stringmessagetable : pstringmessagetable;
  303. type
  304. pdword = ^dword;
  305. begin
  306. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  307. end;
  308. type
  309. tmessagehandler = procedure(var msg) of object;
  310. tmessagehandlerrec = packed record
  311. proc : pointer;
  312. obj : pointer;
  313. end;
  314. procedure TObject.Dispatch(var message);
  315. type
  316. tmsgtable = record
  317. index : dword;
  318. method : pointer;
  319. end;
  320. pmsgtable = ^tmsgtable;
  321. pdword = ^dword;
  322. var
  323. index : dword;
  324. count,i : longint;
  325. msgtable : pmsgtable;
  326. p : pointer;
  327. vmt : tclass;
  328. msghandler : tmessagehandler;
  329. begin
  330. index:=dword(message);
  331. vmt:=ClassType;
  332. while assigned(vmt) do
  333. begin
  334. // See if we have messages at all in this class.
  335. p:=pointer(vmt)+vmtDynamicTable;
  336. If Assigned(p) and (Pdword(p)^<>0) then
  337. begin
  338. msgtable:=pmsgtable(pdword(P)^+4);
  339. count:=pdword(pdword(P)^)^;
  340. end
  341. else
  342. Count:=0;
  343. { later, we can implement a binary search here }
  344. for i:=0 to count-1 do
  345. begin
  346. if index=msgtable[i].index then
  347. begin
  348. p:=msgtable[i].method;
  349. tmessagehandlerrec(msghandler).proc:=p;
  350. tmessagehandlerrec(msghandler).obj:=self;
  351. msghandler(message);
  352. { we don't need any longer the assembler
  353. solution
  354. asm
  355. pushl message
  356. pushl %esi
  357. movl p,%edi
  358. call *%edi
  359. end;
  360. }
  361. exit;
  362. end;
  363. end;
  364. vmt:=vmt.ClassParent;
  365. end;
  366. DefaultHandler(message);
  367. end;
  368. procedure TObject.DispatchStr(var message);
  369. type
  370. pdword = ^dword;
  371. var
  372. name : shortstring;
  373. count,i : longint;
  374. msgstrtable : pmsgstrtable;
  375. p : pointer;
  376. vmt : tclass;
  377. msghandler : tmessagehandler;
  378. begin
  379. name:=pshortstring(@message)^;
  380. vmt:=ClassType;
  381. while assigned(vmt) do
  382. begin
  383. p:=(pointer(vmt)+vmtMsgStrPtr);
  384. If (P<>Nil) and (PDWord(P)^<>0) then
  385. begin
  386. count:=pdword(pdword(p)^)^;
  387. msgstrtable:=pmsgstrtable(pdword(P)^+4);
  388. end
  389. else
  390. Count:=0;
  391. { later, we can implement a binary search here }
  392. for i:=0 to count-1 do
  393. begin
  394. if name=msgstrtable[i].name^ then
  395. begin
  396. p:=msgstrtable[i].method;
  397. tmessagehandlerrec(msghandler).proc:=p;
  398. tmessagehandlerrec(msghandler).obj:=self;
  399. msghandler(message);
  400. { we don't need any longer the assembler
  401. solution
  402. asm
  403. pushl message
  404. pushl %esi
  405. movl p,%edi
  406. call *%edi
  407. end;
  408. }
  409. exit;
  410. end;
  411. end;
  412. vmt:=vmt.ClassParent;
  413. end;
  414. DefaultHandlerStr(message);
  415. end;
  416. procedure TObject.DefaultHandler(var message);
  417. begin
  418. end;
  419. procedure TObject.DefaultHandlerStr(var message);
  420. begin
  421. end;
  422. procedure TObject.CleanupInstance;
  423. var
  424. vmt : tclass;
  425. begin
  426. vmt:=ClassType;
  427. while vmt<>nil do
  428. begin
  429. if Assigned(Pointer((Pointer(vmt)+vmtInitTable)^)) then
  430. int_finalize(Pointer(Self),Pointer((Pointer(vmt)+vmtInitTable)^));
  431. vmt:=vmt.ClassParent;
  432. end;
  433. end;
  434. procedure TObject.AfterConstruction;
  435. begin
  436. end;
  437. procedure TObject.BeforeDestruction;
  438. begin
  439. end;
  440. {$ifdef HASINTF}
  441. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  442. begin
  443. IsGUIDEqual:=
  444. (guid1.D1=guid2.D1) and
  445. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  446. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  447. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  448. end;
  449. function TObject.getinterface(const iid : tguid;out obj) : boolean;
  450. var
  451. IEntry: pinterfaceentry;
  452. begin
  453. IEntry:=getinterfaceentry(iid);
  454. if Assigned(IEntry) then begin
  455. PDWORD(@obj)^:=DWORD(PDWORD(Self))+IEntry^.IOffset;
  456. intf_incr_ref(pointer(obj)); { it must be an com interface }
  457. getinterface:=True;
  458. end
  459. else begin
  460. PDWORD(@Obj)^:=0;
  461. getinterface:=False;
  462. end;
  463. end;
  464. function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
  465. var
  466. IEntry: pinterfaceentry;
  467. begin
  468. IEntry:=getinterfaceentrybystr(iidstr);
  469. if Assigned(IEntry) then begin
  470. PDWORD(@obj)^:=DWORD(PDWORD(Self))+IEntry^.IOffset;
  471. if Assigned(IEntry^.iid) then { for Com interfaces }
  472. intf_incr_ref(pointer(obj));
  473. getinterfacebystr:=True;
  474. end
  475. else begin
  476. PDWORD(@Obj)^:=0;
  477. getinterfacebystr:=False;
  478. end;
  479. end;
  480. class function TObject.getinterfaceentry(const iid : tguid) : pinterfaceentry;
  481. var
  482. i: integer;
  483. intftable: pinterfacetable;
  484. Res: pinterfaceentry;
  485. begin
  486. getinterfaceentry:=nil;
  487. intftable:=getinterfacetable;
  488. if assigned(intftable) then begin
  489. i:=intftable^.EntryCount;
  490. Res:=@intftable^.Entries[0];
  491. while (i>0) and
  492. not (assigned(Res^.iid) and IsGUIDEqual(Res^.iid^,iid)) do begin
  493. inc(Res);
  494. dec(i);
  495. end;
  496. if (i>0) then
  497. getinterfaceentry:=Res;
  498. end;
  499. end;
  500. class function TObject.getinterfaceentrybystr(const iidstr : string) : pinterfaceentry;
  501. var
  502. i: integer;
  503. intftable: pinterfacetable;
  504. Res: pinterfaceentry;
  505. begin
  506. getinterfaceentrybystr:=nil;
  507. intftable:=getinterfacetable;
  508. if assigned(intftable) then begin
  509. i:=intftable^.EntryCount;
  510. Res:=@intftable^.Entries[0];
  511. while (i>0) and (Res^.iidstr^<>iidstr) do begin
  512. inc(Res);
  513. dec(i);
  514. end;
  515. if (i>0) then
  516. getinterfaceentrybystr:=Res;
  517. end;
  518. end;
  519. class function TObject.getinterfacetable : pinterfacetable;
  520. begin
  521. getinterfacetable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  522. end;
  523. {****************************************************************************
  524. TINTERFACEDOBJECT
  525. ****************************************************************************}
  526. function TInterfacedObject.QueryInterface(
  527. const iid : tguid;out obj) : longint;stdcall;
  528. begin
  529. if getinterface(iid,obj) then
  530. result:=0
  531. else
  532. result:=longint($80004002);
  533. end;
  534. function TInterfacedObject._AddRef : longint;stdcall;
  535. begin
  536. inclocked(frefcount);
  537. _addref:=frefcount;
  538. end;
  539. function TInterfacedObject._Release : longint;stdcall;
  540. begin
  541. if declocked(frefcount) then
  542. begin
  543. destroy;
  544. _Release:=0;
  545. end
  546. else
  547. _Release:=frefcount;
  548. end;
  549. procedure TInterfacedObject.AfterConstruction;
  550. begin
  551. { we need to fix the refcount we forced in newinstance }
  552. { further, it must be done in a thread safe way }
  553. declocked(frefcount);
  554. end;
  555. procedure TInterfacedObject.BeforeDestruction;
  556. begin
  557. if frefcount<>0 then
  558. HandleError(204);
  559. end;
  560. class function TInterfacedObject.NewInstance : TObject;
  561. begin
  562. NewInstance:=inherited NewInstance;
  563. TInterfacedObject(NewInstance).frefcount:=1;
  564. end;
  565. {$endif HASINTF}
  566. {****************************************************************************
  567. Exception Support
  568. ****************************************************************************}
  569. {$i except.inc}
  570. {****************************************************************************
  571. Initialize
  572. ****************************************************************************}
  573. {
  574. $Log$
  575. Revision 1.17 2001-09-29 21:32:47 jonas
  576. * almost all second pass typeconvnode helpers are now processor independent
  577. * fixed converting boolean to int64/qword
  578. * fixed register allocation bugs which could cause internalerror 10
  579. * isnode and asnode are completely processor indepent now as well
  580. * fpc_do_as now returns its class argument (necessary to be able to use it
  581. properly with compilerproc)
  582. Revision 1.16 2001/08/01 15:00:10 jonas
  583. + "compproc" helpers
  584. * renamed several helpers so that their name is the same as their
  585. "public alias", which should facilitate the conversion of processor
  586. specific code in the code generator to processor independent code
  587. * some small fixes to the val_ansistring and val_widestring helpers
  588. (always immediately exit if the source string is longer than 255
  589. chars)
  590. * fixed fpc_dynarray_high and fpc_dynarray_length if the dynarray is
  591. still nil (used to crash, now return resp -1 and 0)
  592. Revision 1.15 2001/05/27 14:28:44 florian
  593. + made the ref. couting MT safe
  594. Revision 1.14 2001/04/13 22:30:04 peter
  595. * remove warnings
  596. Revision 1.13 2000/12/20 21:38:23 florian
  597. * is-operator fixed
  598. Revision 1.12 2000/11/12 23:23:34 florian
  599. * interfaces are basically running
  600. Revision 1.11 2000/11/09 17:50:12 florian
  601. * Finalize to int_finalize renamed
  602. Revision 1.10 2000/11/07 23:42:21 florian
  603. + AfterConstruction and BeforeDestruction implemented
  604. + TInterfacedObject implemented
  605. Revision 1.9 2000/11/06 22:03:12 florian
  606. * another fix
  607. Revision 1.8 2000/11/06 21:53:38 florian
  608. * another fix for interfaces
  609. Revision 1.7 2000/11/06 21:35:59 peter
  610. * removed some warnings
  611. Revision 1.6 2000/11/06 20:34:24 peter
  612. * changed ver1_0 defines to temporary defs
  613. Revision 1.5 2000/11/04 17:52:46 florian
  614. * fixed linker errors
  615. Revision 1.4 2000/11/04 16:29:54 florian
  616. + interfaces support
  617. Revision 1.3 2000/07/22 14:52:01 sg
  618. * Resolved CVS conflicts for TObject.MethodAddress patch
  619. Revision 1.1.2.1 2000/07/22 14:46:57 sg
  620. * Made TObject.MethodAddress case independent
  621. }