objpas.inc 24 KB

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