objpas.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  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 int_do_is(aclass : tclass;aobject : tobject) : boolean;[public,alias: 'FPC_DO_IS'];
  17. begin
  18. int_do_is:=aobject.inheritsfrom(aclass);
  19. end;
  20. { the reverse order of the parameters make code generation easier }
  21. procedure int_do_as(aclass : tclass;aobject : tobject);[public,alias: 'FPC_DO_AS'];
  22. begin
  23. if assigned(aobject) and not(aobject.inheritsfrom(aclass)) then
  24. handleerror(219);
  25. end;
  26. {****************************************************************************
  27. TOBJECT
  28. ****************************************************************************}
  29. constructor TObject.Create;
  30. begin
  31. end;
  32. destructor TObject.Destroy;
  33. begin
  34. end;
  35. procedure TObject.Free;
  36. begin
  37. // the call via self avoids a warning
  38. if self<>nil then
  39. self.destroy;
  40. end;
  41. class function TObject.InstanceSize : LongInt;
  42. type
  43. plongint = ^longint;
  44. begin
  45. { type of self is class of tobject => it points to the vmt }
  46. { the size is saved at offset 0 }
  47. InstanceSize:=plongint(self)^;
  48. end;
  49. class function TObject.InitInstance(instance : pointer) : tobject;
  50. begin
  51. fillchar(instance^,self.instancesize,0);
  52. { insert VMT pointer into the new created memory area }
  53. { (in class methods self contains the VMT!) }
  54. ppointer(instance)^:=pointer(self);
  55. InitInstance:=TObject(Instance);
  56. end;
  57. class function TObject.ClassParent : tclass;
  58. begin
  59. { type of self is class of tobject => it points to the vmt }
  60. { the parent vmt is saved at offset vmtParent }
  61. classparent:=pclass(pointer(self)+vmtParent)^;
  62. end;
  63. class function TObject.NewInstance : tobject;
  64. var
  65. p : pointer;
  66. begin
  67. getmem(p,instancesize);
  68. InitInstance(p);
  69. NewInstance:=TObject(p);
  70. end;
  71. procedure TObject.FreeInstance;
  72. var
  73. p : Pointer;
  74. begin
  75. CleanupInstance;
  76. { self is a register, so we can't pass it call by reference }
  77. p:=Pointer(Self);
  78. FreeMem(p,InstanceSize);
  79. end;
  80. function TObject.ClassType : TClass;
  81. begin
  82. ClassType:=TClass(Pointer(Self)^)
  83. end;
  84. type
  85. tmethodnamerec = packed record
  86. name : pshortstring;
  87. addr : pointer;
  88. end;
  89. tmethodnametable = packed record
  90. count : dword;
  91. entries : packed array[0..0] of tmethodnamerec;
  92. end;
  93. pmethodnametable = ^tmethodnametable;
  94. class function TObject.MethodAddress(const name : shortstring) : pointer;
  95. var
  96. methodtable : pmethodnametable;
  97. i : dword;
  98. c : tclass;
  99. begin
  100. c:=self;
  101. while assigned(c) do
  102. begin
  103. methodtable:=pmethodnametable((Pointer(c)+vmtMethodTable)^);
  104. if assigned(methodtable) then
  105. begin
  106. for i:=0 to methodtable^.count-1 do
  107. if methodtable^.entries[i].name^=name then
  108. begin
  109. MethodAddress:=methodtable^.entries[i].addr;
  110. exit;
  111. end;
  112. end;
  113. c:=c.ClassParent;
  114. end;
  115. MethodAddress:=nil;
  116. end;
  117. class function TObject.MethodName(address : pointer) : shortstring;
  118. var
  119. methodtable : pmethodnametable;
  120. i : dword;
  121. c : tclass;
  122. begin
  123. c:=self;
  124. while assigned(c) do
  125. begin
  126. methodtable:=pmethodnametable((Pointer(c)+vmtMethodTable)^);
  127. if assigned(methodtable) then
  128. begin
  129. for i:=0 to methodtable^.count-1 do
  130. if methodtable^.entries[i].addr=address then
  131. begin
  132. MethodName:=methodtable^.entries[i].name^;
  133. exit;
  134. end;
  135. end;
  136. c:=c.ClassParent;
  137. end;
  138. MethodName:='';
  139. end;
  140. function TObject.FieldAddress(const name : shortstring) : pointer;
  141. type
  142. PFieldInfo = ^TFieldInfo;
  143. TFieldInfo = packed record
  144. FieldOffset: LongWord;
  145. ClassTypeIndex: Word;
  146. Name: ShortString;
  147. end;
  148. PFieldTable = ^TFieldTable;
  149. TFieldTable = packed record
  150. FieldCount: Word;
  151. ClassTable: Pointer;
  152. { Fields: array[Word] of TFieldInfo; Elements have variant size! }
  153. end;
  154. var
  155. UName: ShortString;
  156. CurClassType: TClass;
  157. FieldTable: PFieldTable;
  158. FieldInfo: PFieldInfo;
  159. i: Integer;
  160. begin
  161. if Length(name) > 0 then
  162. begin
  163. UName := UpCase(name);
  164. CurClassType := ClassType;
  165. while CurClassType <> nil do
  166. begin
  167. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  168. if FieldTable <> nil then
  169. begin
  170. FieldInfo := PFieldInfo(Pointer(FieldTable) + 6);
  171. for i := 0 to FieldTable^.FieldCount - 1 do
  172. begin
  173. if UpCase(FieldInfo^.Name) = UName then
  174. begin
  175. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  176. exit;
  177. end;
  178. Inc(Pointer(FieldInfo), 7 + Length(FieldInfo^.Name));
  179. end;
  180. end;
  181. { Try again with the parent class type }
  182. CurClassType := CurClassType.ClassParent;
  183. end;
  184. end;
  185. fieldaddress:=nil;
  186. end;
  187. function TObject.SafeCallException(exceptobject : tobject;
  188. exceptaddr : pointer) : longint;
  189. begin
  190. safecallexception:=0;
  191. end;
  192. class function TObject.ClassInfo : pointer;
  193. begin
  194. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  195. end;
  196. class function TObject.ClassName : ShortString;
  197. begin
  198. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  199. end;
  200. class function TObject.ClassNameIs(const name : string) : boolean;
  201. begin
  202. ClassNameIs:=Upcase(ClassName)=Upcase(name);
  203. end;
  204. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  205. var
  206. c : tclass;
  207. begin
  208. c:=self;
  209. while assigned(c) do
  210. begin
  211. if c=aclass then
  212. begin
  213. InheritsFrom:=true;
  214. exit;
  215. end;
  216. c:=c.ClassParent;
  217. end;
  218. InheritsFrom:=false;
  219. end;
  220. class function TObject.stringmessagetable : pstringmessagetable;
  221. type
  222. pdword = ^dword;
  223. begin
  224. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  225. end;
  226. type
  227. tmessagehandler = procedure(var msg) of object;
  228. tmessagehandlerrec = packed record
  229. proc : pointer;
  230. obj : pointer;
  231. end;
  232. procedure TObject.Dispatch(var message);
  233. type
  234. tmsgtable = record
  235. index : dword;
  236. method : pointer;
  237. end;
  238. pmsgtable = ^tmsgtable;
  239. pdword = ^dword;
  240. var
  241. index : dword;
  242. count,i : longint;
  243. msgtable : pmsgtable;
  244. p : pointer;
  245. vmt : tclass;
  246. msghandler : tmessagehandler;
  247. begin
  248. index:=dword(message);
  249. vmt:=ClassType;
  250. while assigned(vmt) do
  251. begin
  252. // See if we have messages at all in this class.
  253. p:=pointer(vmt)+vmtDynamicTable;
  254. If Assigned(p) and (Pdword(p)^<>0) then
  255. begin
  256. msgtable:=pmsgtable(pdword(P)^+4);
  257. count:=pdword(pdword(P)^)^;
  258. end
  259. else
  260. Count:=0;
  261. { later, we can implement a binary search here }
  262. for i:=0 to count-1 do
  263. begin
  264. if index=msgtable[i].index then
  265. begin
  266. p:=msgtable[i].method;
  267. tmessagehandlerrec(msghandler).proc:=p;
  268. tmessagehandlerrec(msghandler).obj:=self;
  269. msghandler(message);
  270. { we don't need any longer the assembler
  271. solution
  272. asm
  273. pushl message
  274. pushl %esi
  275. movl p,%edi
  276. call *%edi
  277. end;
  278. }
  279. exit;
  280. end;
  281. end;
  282. vmt:=vmt.ClassParent;
  283. end;
  284. DefaultHandler(message);
  285. end;
  286. procedure TObject.DispatchStr(var message);
  287. type
  288. pdword = ^dword;
  289. var
  290. name : shortstring;
  291. count,i : longint;
  292. msgstrtable : pmsgstrtable;
  293. p : pointer;
  294. vmt : tclass;
  295. msghandler : tmessagehandler;
  296. begin
  297. name:=pshortstring(@message)^;
  298. vmt:=ClassType;
  299. while assigned(vmt) do
  300. begin
  301. p:=(pointer(vmt)+vmtMsgStrPtr);
  302. If (P<>Nil) and (PDWord(P)^<>0) then
  303. begin
  304. count:=pdword(pdword(p)^)^;
  305. msgstrtable:=pmsgstrtable(pdword(P)^+4);
  306. end
  307. else
  308. Count:=0;
  309. { later, we can implement a binary search here }
  310. for i:=0 to count-1 do
  311. begin
  312. if name=msgstrtable[i].name^ then
  313. begin
  314. p:=msgstrtable[i].method;
  315. tmessagehandlerrec(msghandler).proc:=p;
  316. tmessagehandlerrec(msghandler).obj:=self;
  317. msghandler(message);
  318. { we don't need any longer the assembler
  319. solution
  320. asm
  321. pushl message
  322. pushl %esi
  323. movl p,%edi
  324. call *%edi
  325. end;
  326. }
  327. exit;
  328. end;
  329. end;
  330. vmt:=vmt.ClassParent;
  331. end;
  332. DefaultHandlerStr(message);
  333. end;
  334. procedure TObject.DefaultHandler(var message);
  335. begin
  336. end;
  337. procedure TObject.DefaultHandlerStr(var message);
  338. begin
  339. end;
  340. procedure TObject.CleanupInstance;
  341. var
  342. vmt : tclass;
  343. begin
  344. vmt:=ClassType;
  345. while vmt<>nil do
  346. begin
  347. if Assigned(Pointer((Pointer(vmt)+vmtInitTable)^)) then
  348. Finalize(Pointer(Self),Pointer((Pointer(vmt)+vmtInitTable)^));
  349. vmt:=vmt.ClassParent;
  350. end;
  351. end;
  352. procedure TObject.AfterConstruction;
  353. begin
  354. end;
  355. procedure TObject.BeforeDestruction;
  356. begin
  357. end;
  358. {****************************************************************************
  359. Exception Support
  360. ****************************************************************************}
  361. {$i except.inc}
  362. {****************************************************************************
  363. Initialize
  364. ****************************************************************************}
  365. {
  366. $Log$
  367. Revision 1.1 2000-07-13 06:30:48 michael
  368. + Initial import
  369. Revision 1.18 2000/07/08 21:27:42 sg
  370. * Fixed TObject.FieldAddress
  371. Revision 1.17 2000/07/08 07:24:24 sg
  372. * FieldAddress now returns immediately if name=''
  373. Revision 1.16 2000/06/29 16:32:50 sg
  374. * Implemented TObject.FieldAddress
  375. Revision 1.15 2000/05/16 08:06:14 michael
  376. + Fixed ClassNameIs so it is case insensitive
  377. Revision 1.14 2000/02/09 16:59:31 peter
  378. * truncated log
  379. Revision 1.13 2000/01/07 16:41:36 daniel
  380. * copyright 2000
  381. Revision 1.12 2000/01/07 16:32:25 daniel
  382. * copyright 2000 added
  383. Revision 1.11 1999/09/15 20:28:35 florian
  384. * fixed methodname/address: the loops must go from 0 to ...^.count-1
  385. Revision 1.10 1999/09/12 14:53:26 florian
  386. + tobject.methodaddress und tobject.methodname durchsucht nun auch
  387. die Elternklassen
  388. Revision 1.9 1999/09/12 08:01:00 florian
  389. + implementation of TObject.MethodName and TObject.MethodAddress (not
  390. in the compiler yet)
  391. Revision 1.8 1999/09/08 16:14:41 peter
  392. * pointer fixes
  393. }