objpas.inc 24 KB

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