objpas.inc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  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(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. function fpc_intf_as(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_INTF_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  40. begin
  41. end;
  42. function fpc_class_as_intf(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_CLASS_AS_INTF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  43. begin
  44. end;
  45. {$else HASINTF}
  46. { interface helpers }
  47. procedure fpc_intf_decr_ref(var i: pointer);saveregisters;[public,alias: 'FPC_INTF_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  48. begin
  49. if assigned(i) then
  50. IUnknown(i)._Release;
  51. i:=nil;
  52. end;
  53. {$ifdef hascompilerproc}
  54. { local declaration for intf_decr_ref for local access }
  55. procedure intf_decr_ref(var i: pointer);saveregisters; [external name 'FPC_INTF_DECR_REF'];
  56. {$endif hascompilerproc}
  57. procedure fpc_intf_incr_ref(i: pointer);saveregisters;[public,alias: 'FPC_INTF_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  58. begin
  59. if assigned(i) then
  60. IUnknown(i)._AddRef;
  61. end;
  62. {$ifdef hascompilerproc}
  63. { local declaration of intf_incr_ref for local access }
  64. procedure intf_incr_ref(i: pointer);saveregisters; [external name 'FPC_INTF_INCR_REF'];
  65. {$endif hascompilerproc}
  66. procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; {$ifdef hascompilerproc} compilerproc; {$endif}
  67. begin
  68. if assigned(S) then
  69. IUnknown(S)._AddRef;
  70. if assigned(D) then
  71. IUnknown(D)._Release;
  72. D:=S;
  73. end;
  74. function fpc_intf_as(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_INTF_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  75. const
  76. S_OK = 0;
  77. var
  78. tmpi: pointer; // _AddRef before _Release
  79. begin
  80. if assigned(S) then
  81. begin
  82. if IUnknown(S).QueryInterface(iid,tmpi)<>S_OK then
  83. handleerror(219);
  84. fpc_intf_as:=tmpi;
  85. end
  86. else
  87. fpc_intf_as:=nil;
  88. end;
  89. function fpc_class_as_intf(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_CLASS_AS_INTF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  90. const
  91. S_OK = 0;
  92. var
  93. tmpi: pointer; // _AddRef before _Release
  94. begin
  95. if assigned(S) then
  96. begin
  97. if not TObject(S).GetInterface(iid,tmpi) then
  98. handleerror(219);
  99. fpc_class_as_intf:=tmpi;
  100. end
  101. else
  102. fpc_class_as_intf:=nil;
  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. begin
  122. InstanceSize:=plongint(pointer(self)+vmtInstanceSize)^;
  123. end;
  124. procedure InitInterfacePointers(objclass: tclass;instance : pointer);
  125. {$ifdef HASINTF}
  126. var
  127. intftable : pinterfacetable;
  128. i : longint;
  129. begin
  130. while assigned(objclass) do
  131. begin
  132. intftable:=pinterfacetable((pointer(objclass)+vmtIntfTable)^);
  133. if assigned(intftable) then
  134. for i:=0 to intftable^.EntryCount-1 do
  135. ppointer(@(PChar(instance)[intftable^.Entries[i].IOffset]))^:=
  136. pointer(intftable^.Entries[i].VTable);
  137. objclass:=pclass(pointer(objclass)+vmtParent)^;
  138. end;
  139. end;
  140. {$else HASINTF}
  141. begin
  142. end;
  143. {$endif HASINTF}
  144. class function TObject.InitInstance(instance : pointer) : tobject;
  145. begin
  146. { the size is saved at offset 0 }
  147. fillchar(instance^,plongint(pointer(self)+vmtInstanceSize)^,0);
  148. { insert VMT pointer into the new created memory area }
  149. { (in class methods self contains the VMT!) }
  150. ppointer(instance)^:=pointer(self);
  151. {$ifdef HASINTF}
  152. InitInterfacePointers(self,instance);
  153. {$endif HASINTF}
  154. InitInstance:=TObject(Instance);
  155. end;
  156. class function TObject.ClassParent : tclass;
  157. begin
  158. { type of self is class of tobject => it points to the vmt }
  159. { the parent vmt is saved at offset vmtParent }
  160. classparent:=pclass(pointer(self)+vmtParent)^;
  161. end;
  162. class function TObject.NewInstance : tobject;
  163. var
  164. p : pointer;
  165. begin
  166. getmem(p,plongint(pointer(self)+vmtInstanceSize)^);
  167. if p <> nil then
  168. InitInstance(p);
  169. NewInstance:=TObject(p);
  170. end;
  171. procedure TObject.FreeInstance;
  172. begin
  173. CleanupInstance;
  174. FreeMem(Pointer(Self));
  175. end;
  176. class function TObject.ClassType : TClass;
  177. begin
  178. ClassType:=TClass(Pointer(Self))
  179. end;
  180. type
  181. tmethodnamerec = packed record
  182. name : pshortstring;
  183. addr : pointer;
  184. end;
  185. tmethodnametable = packed record
  186. count : dword;
  187. entries : packed array[0..0] of tmethodnamerec;
  188. end;
  189. pmethodnametable = ^tmethodnametable;
  190. class function TObject.MethodAddress(const name : shortstring) : pointer;
  191. var
  192. UName : ShortString;
  193. methodtable : pmethodnametable;
  194. i : dword;
  195. vmt : tclass;
  196. begin
  197. UName := UpCase(name);
  198. vmt:=self;
  199. while assigned(vmt) do
  200. begin
  201. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  202. if assigned(methodtable) then
  203. begin
  204. for i:=0 to methodtable^.count-1 do
  205. if UpCase(methodtable^.entries[i].name^)=UName then
  206. begin
  207. MethodAddress:=methodtable^.entries[i].addr;
  208. exit;
  209. end;
  210. end;
  211. vmt:=pclass(pointer(vmt)+vmtParent)^;
  212. end;
  213. MethodAddress:=nil;
  214. end;
  215. class function TObject.MethodName(address : pointer) : shortstring;
  216. var
  217. methodtable : pmethodnametable;
  218. i : dword;
  219. vmt : tclass;
  220. begin
  221. vmt:=self;
  222. while assigned(vmt) do
  223. begin
  224. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  225. if assigned(methodtable) then
  226. begin
  227. for i:=0 to methodtable^.count-1 do
  228. if methodtable^.entries[i].addr=address then
  229. begin
  230. MethodName:=methodtable^.entries[i].name^;
  231. exit;
  232. end;
  233. end;
  234. vmt:=pclass(pointer(vmt)+vmtParent)^;
  235. end;
  236. MethodName:='';
  237. end;
  238. function TObject.FieldAddress(const name : shortstring) : pointer;
  239. type
  240. PFieldInfo = ^TFieldInfo;
  241. TFieldInfo = packed record
  242. FieldOffset: LongWord;
  243. ClassTypeIndex: Word;
  244. Name: ShortString;
  245. end;
  246. PFieldTable = ^TFieldTable;
  247. TFieldTable = packed record
  248. FieldCount: Word;
  249. ClassTable: Pointer;
  250. { Fields: array[Word] of TFieldInfo; Elements have variant size! }
  251. end;
  252. var
  253. UName: ShortString;
  254. CurClassType: TClass;
  255. FieldTable: PFieldTable;
  256. FieldInfo: PFieldInfo;
  257. i: Integer;
  258. begin
  259. if Length(name) > 0 then
  260. begin
  261. UName := UpCase(name);
  262. CurClassType := ClassType;
  263. while CurClassType <> nil do
  264. begin
  265. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  266. if FieldTable <> nil then
  267. begin
  268. FieldInfo := PFieldInfo(Pointer(FieldTable) + 6);
  269. for i := 0 to FieldTable^.FieldCount - 1 do
  270. begin
  271. if UpCase(FieldInfo^.Name) = UName then
  272. begin
  273. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  274. exit;
  275. end;
  276. Inc(Pointer(FieldInfo), 7 + Length(FieldInfo^.Name));
  277. end;
  278. end;
  279. { Try again with the parent class type }
  280. CurClassType:=pclass(pointer(CurClassType)+vmtParent)^;
  281. end;
  282. end;
  283. fieldaddress:=nil;
  284. end;
  285. function TObject.SafeCallException(exceptobject : tobject;
  286. exceptaddr : pointer) : longint;
  287. begin
  288. safecallexception:=0;
  289. end;
  290. class function TObject.ClassInfo : pointer;
  291. begin
  292. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  293. end;
  294. class function TObject.ClassName : ShortString;
  295. begin
  296. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  297. end;
  298. class function TObject.ClassNameIs(const name : string) : boolean;
  299. begin
  300. ClassNameIs:=Upcase(ClassName)=Upcase(name);
  301. end;
  302. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  303. var
  304. vmt : tclass;
  305. begin
  306. vmt:=self;
  307. while assigned(vmt) do
  308. begin
  309. if vmt=aclass then
  310. begin
  311. InheritsFrom:=true;
  312. exit;
  313. end;
  314. vmt:=pclass(pointer(vmt)+vmtParent)^;
  315. end;
  316. InheritsFrom:=false;
  317. end;
  318. class function TObject.stringmessagetable : pstringmessagetable;
  319. type
  320. pdword = ^dword;
  321. begin
  322. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  323. end;
  324. type
  325. tmessagehandler = procedure(var msg) of object;
  326. tmessagehandlerrec = packed record
  327. proc : pointer;
  328. obj : pointer;
  329. end;
  330. procedure TObject.Dispatch(var message);
  331. type
  332. tmsgtable = record
  333. index : dword;
  334. method : pointer;
  335. end;
  336. pmsgtable = ^tmsgtable;
  337. PSizeUInt = ^SizeUInt;
  338. var
  339. index : dword;
  340. count,i : longint;
  341. msgtable : pmsgtable;
  342. p : pointer;
  343. vmt : tclass;
  344. msghandler : tmessagehandler;
  345. begin
  346. index:=dword(message);
  347. vmt:=ClassType;
  348. while assigned(vmt) do
  349. begin
  350. // See if we have messages at all in this class.
  351. p:=pointer(vmt)+vmtDynamicTable;
  352. If Assigned(p) and (Pdword(p)^<>0) then
  353. begin
  354. msgtable:=pmsgtable(PSizeUInt(P)^+4);
  355. count:=pdword(PSizeUInt(P)^)^;
  356. end
  357. else
  358. Count:=0;
  359. { later, we can implement a binary search here }
  360. for i:=0 to count-1 do
  361. begin
  362. if index=msgtable[i].index then
  363. begin
  364. p:=msgtable[i].method;
  365. tmessagehandlerrec(msghandler).proc:=p;
  366. tmessagehandlerrec(msghandler).obj:=self;
  367. msghandler(message);
  368. exit;
  369. end;
  370. end;
  371. vmt:=pclass(pointer(vmt)+vmtParent)^;
  372. end;
  373. DefaultHandler(message);
  374. end;
  375. procedure TObject.DispatchStr(var message);
  376. type
  377. PSizeUInt = ^SizeUInt;
  378. var
  379. name : shortstring;
  380. count,i : longint;
  381. msgstrtable : pmsgstrtable;
  382. p : pointer;
  383. vmt : tclass;
  384. msghandler : tmessagehandler;
  385. begin
  386. name:=pshortstring(@message)^;
  387. vmt:=ClassType;
  388. while assigned(vmt) do
  389. begin
  390. p:=(pointer(vmt)+vmtMsgStrPtr);
  391. If (P<>Nil) and (PDWord(P)^<>0) then
  392. begin
  393. count:=pdword(PSizeUInt(p)^)^;
  394. msgstrtable:=pmsgstrtable(PSizeUInt(P)^+4);
  395. end
  396. else
  397. Count:=0;
  398. { later, we can implement a binary search here }
  399. for i:=0 to count-1 do
  400. begin
  401. if name=msgstrtable[i].name^ then
  402. begin
  403. p:=msgstrtable[i].method;
  404. tmessagehandlerrec(msghandler).proc:=p;
  405. tmessagehandlerrec(msghandler).obj:=self;
  406. msghandler(message);
  407. exit;
  408. end;
  409. end;
  410. vmt:=pclass(pointer(vmt)+vmtParent)^;
  411. end;
  412. DefaultHandlerStr(message);
  413. end;
  414. procedure TObject.DefaultHandler(var message);
  415. begin
  416. end;
  417. procedure TObject.DefaultHandlerStr(var message);
  418. begin
  419. end;
  420. procedure TObject.CleanupInstance;
  421. var
  422. vmt : tclass;
  423. begin
  424. vmt:=ClassType;
  425. while vmt<>nil do
  426. begin
  427. if Assigned(Pointer((Pointer(vmt)+vmtInitTable)^)) then
  428. int_finalize(Pointer(Self),Pointer((Pointer(vmt)+vmtInitTable)^));
  429. vmt:=pclass(pointer(vmt)+vmtParent)^;
  430. end;
  431. end;
  432. procedure TObject.AfterConstruction;
  433. begin
  434. end;
  435. procedure TObject.BeforeDestruction;
  436. begin
  437. end;
  438. {$ifdef HASINTF}
  439. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  440. begin
  441. IsGUIDEqual:=
  442. (guid1.D1=guid2.D1) and
  443. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  444. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  445. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  446. end;
  447. function TObject.getinterface(const iid : tguid;out obj) : boolean;
  448. var
  449. IEntry: pinterfaceentry;
  450. begin
  451. IEntry:=getinterfaceentry(iid);
  452. if Assigned(IEntry) then begin
  453. PDWORD(@obj)^:=DWORD(PDWORD(Self))+IEntry^.IOffset;
  454. intf_incr_ref(pointer(obj)); { it must be an com interface }
  455. getinterface:=True;
  456. end
  457. else begin
  458. PDWORD(@Obj)^:=0;
  459. getinterface:=False;
  460. end;
  461. end;
  462. function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
  463. var
  464. IEntry: pinterfaceentry;
  465. begin
  466. IEntry:=getinterfaceentrybystr(iidstr);
  467. if Assigned(IEntry) then begin
  468. PDWORD(@obj)^:=DWORD(PDWORD(Self))+IEntry^.IOffset;
  469. if Assigned(IEntry^.iid) then { for Com interfaces }
  470. intf_incr_ref(pointer(obj));
  471. getinterfacebystr:=True;
  472. end
  473. else begin
  474. PDWORD(@Obj)^:=0;
  475. getinterfacebystr:=False;
  476. end;
  477. end;
  478. class function TObject.getinterfaceentry(const iid : tguid) : pinterfaceentry;
  479. var
  480. i: integer;
  481. intftable: pinterfacetable;
  482. Res: pinterfaceentry;
  483. begin
  484. getinterfaceentry:=nil;
  485. intftable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  486. if assigned(intftable) then begin
  487. i:=intftable^.EntryCount;
  488. Res:=@intftable^.Entries[0];
  489. while (i>0) and
  490. not (assigned(Res^.iid) and IsGUIDEqual(Res^.iid^,iid)) do begin
  491. inc(Res);
  492. dec(i);
  493. end;
  494. if (i>0) then
  495. getinterfaceentry:=Res;
  496. end;
  497. if (getinterfaceentry=nil)and not(classparent=nil) then
  498. getinterfaceentry:=classparent.getinterfaceentry(iid)
  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. if (getinterfaceentrybystr=nil)and not(classparent=nil) then
  519. getinterfaceentrybystr:=classparent.getinterfaceentrybystr(iidstr)
  520. end;
  521. class function TObject.getinterfacetable : pinterfacetable;
  522. begin
  523. getinterfacetable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  524. end;
  525. {****************************************************************************
  526. TINTERFACEDOBJECT
  527. ****************************************************************************}
  528. function TInterfacedObject.QueryInterface(
  529. const iid : tguid;out obj) : longint;stdcall;
  530. begin
  531. if getinterface(iid,obj) then
  532. result:=0
  533. else
  534. result:=longint($80004002);
  535. end;
  536. function TInterfacedObject._AddRef : longint;stdcall;
  537. begin
  538. inclocked(frefcount);
  539. _addref:=frefcount;
  540. end;
  541. function TInterfacedObject._Release : longint;stdcall;
  542. begin
  543. if declocked(frefcount) then
  544. begin
  545. destroy;
  546. _Release:=0;
  547. end
  548. else
  549. _Release:=frefcount;
  550. end;
  551. procedure TInterfacedObject.AfterConstruction;
  552. begin
  553. { we need to fix the refcount we forced in newinstance }
  554. { further, it must be done in a thread safe way }
  555. declocked(frefcount);
  556. end;
  557. procedure TInterfacedObject.BeforeDestruction;
  558. begin
  559. if frefcount<>0 then
  560. HandleError(204);
  561. end;
  562. class function TInterfacedObject.NewInstance : TObject;
  563. begin
  564. NewInstance:=inherited NewInstance;
  565. TInterfacedObject(NewInstance).frefcount:=1;
  566. end;
  567. {$endif HASINTF}
  568. {****************************************************************************
  569. Exception Support
  570. ****************************************************************************}
  571. {$i except.inc}
  572. {****************************************************************************
  573. Initialize
  574. ****************************************************************************}
  575. {
  576. $Log$
  577. Revision 1.33 2003-07-19 11:19:07 michael
  578. + fix from Ivan Shikhalev for QueryInterface to return ancestor methods
  579. Revision 1.32 2003/05/01 08:05:23 florian
  580. * started to make the rtl 64 bit save by introducing SizeInt and SizeUInt (similar to size_t of C)
  581. Revision 1.31 2003/03/17 20:55:58 peter
  582. * ClassType changed to class method
  583. Revision 1.30 2002/10/19 15:53:20 peter
  584. * 'inlined' some more calls
  585. Revision 1.29 2002/10/15 19:29:49 peter
  586. * manual inline classparent calls in the loops
  587. Revision 1.28 2002/10/11 14:05:21 florian
  588. * initinterfacepointers improved
  589. Revision 1.27 2002/09/07 15:07:46 peter
  590. * old logs removed and tabs fixed
  591. Revision 1.26 2002/09/07 11:08:58 carl
  592. - remove logs
  593. Revision 1.25 2002/08/31 13:11:11 florian
  594. * several fixes for Linux/PPC compilation
  595. }