objpas.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  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. begin
  142. fieldaddress:=nil;
  143. end;
  144. function TObject.SafeCallException(exceptobject : tobject;
  145. exceptaddr : pointer) : longint;
  146. begin
  147. safecallexception:=0;
  148. end;
  149. class function TObject.ClassInfo : pointer;
  150. begin
  151. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  152. end;
  153. class function TObject.ClassName : ShortString;
  154. begin
  155. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  156. end;
  157. class function TObject.ClassNameIs(const name : string) : boolean;
  158. begin
  159. ClassNameIs:=ClassName=name;
  160. end;
  161. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  162. var
  163. c : tclass;
  164. begin
  165. c:=self;
  166. while assigned(c) do
  167. begin
  168. if c=aclass then
  169. begin
  170. InheritsFrom:=true;
  171. exit;
  172. end;
  173. c:=c.ClassParent;
  174. end;
  175. InheritsFrom:=false;
  176. end;
  177. class function TObject.stringmessagetable : pstringmessagetable;
  178. type
  179. pdword = ^dword;
  180. begin
  181. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  182. end;
  183. type
  184. tmessagehandler = procedure(var msg) of object;
  185. tmessagehandlerrec = packed record
  186. proc : pointer;
  187. obj : pointer;
  188. end;
  189. procedure TObject.Dispatch(var message);
  190. type
  191. tmsgtable = record
  192. index : dword;
  193. method : pointer;
  194. end;
  195. pmsgtable = ^tmsgtable;
  196. pdword = ^dword;
  197. var
  198. index : dword;
  199. count,i : longint;
  200. msgtable : pmsgtable;
  201. p : pointer;
  202. vmt : tclass;
  203. msghandler : tmessagehandler;
  204. begin
  205. index:=dword(message);
  206. vmt:=ClassType;
  207. while assigned(vmt) do
  208. begin
  209. // See if we have messages at all in this class.
  210. p:=pointer(vmt)+vmtDynamicTable;
  211. If Assigned(p) and (Pdword(p)^<>0) then
  212. begin
  213. msgtable:=pmsgtable(pdword(P)^+4);
  214. count:=pdword(pdword(P)^)^;
  215. end
  216. else
  217. Count:=0;
  218. { later, we can implement a binary search here }
  219. for i:=0 to count-1 do
  220. begin
  221. if index=msgtable[i].index then
  222. begin
  223. p:=msgtable[i].method;
  224. tmessagehandlerrec(msghandler).proc:=p;
  225. tmessagehandlerrec(msghandler).obj:=self;
  226. msghandler(message);
  227. { we don't need any longer the assembler
  228. solution
  229. asm
  230. pushl message
  231. pushl %esi
  232. movl p,%edi
  233. call *%edi
  234. end;
  235. }
  236. exit;
  237. end;
  238. end;
  239. vmt:=vmt.ClassParent;
  240. end;
  241. DefaultHandler(message);
  242. end;
  243. procedure TObject.DispatchStr(var message);
  244. type
  245. pdword = ^dword;
  246. var
  247. name : shortstring;
  248. count,i : longint;
  249. msgstrtable : pmsgstrtable;
  250. p : pointer;
  251. vmt : tclass;
  252. msghandler : tmessagehandler;
  253. begin
  254. name:=pshortstring(@message)^;
  255. vmt:=ClassType;
  256. while assigned(vmt) do
  257. begin
  258. p:=(pointer(vmt)+vmtMsgStrPtr);
  259. If (P<>Nil) and (PDWord(P)^<>0) then
  260. begin
  261. count:=pdword(pdword(p)^)^;
  262. msgstrtable:=pmsgstrtable(pdword(P)^+4);
  263. end
  264. else
  265. Count:=0;
  266. { later, we can implement a binary search here }
  267. for i:=0 to count-1 do
  268. begin
  269. if name=msgstrtable[i].name^ then
  270. begin
  271. p:=msgstrtable[i].method;
  272. tmessagehandlerrec(msghandler).proc:=p;
  273. tmessagehandlerrec(msghandler).obj:=self;
  274. msghandler(message);
  275. { we don't need any longer the assembler
  276. solution
  277. asm
  278. pushl message
  279. pushl %esi
  280. movl p,%edi
  281. call *%edi
  282. end;
  283. }
  284. exit;
  285. end;
  286. end;
  287. vmt:=vmt.ClassParent;
  288. end;
  289. DefaultHandlerStr(message);
  290. end;
  291. procedure TObject.DefaultHandler(var message);
  292. begin
  293. end;
  294. procedure TObject.DefaultHandlerStr(var message);
  295. begin
  296. end;
  297. procedure TObject.CleanupInstance;
  298. var
  299. vmt : tclass;
  300. begin
  301. vmt:=ClassType;
  302. while vmt<>nil do
  303. begin
  304. if Assigned(Pointer((Pointer(vmt)+vmtInitTable)^)) then
  305. Finalize(Pointer(Self),Pointer((Pointer(vmt)+vmtInitTable)^));
  306. vmt:=vmt.ClassParent;
  307. end;
  308. end;
  309. procedure TObject.AfterConstruction;
  310. begin
  311. end;
  312. procedure TObject.BeforeDestruction;
  313. begin
  314. end;
  315. {****************************************************************************
  316. Exception Support
  317. ****************************************************************************}
  318. {$i except.inc}
  319. {****************************************************************************
  320. Initialize
  321. ****************************************************************************}
  322. {
  323. $Log$
  324. Revision 1.13 2000-01-07 16:41:36 daniel
  325. * copyright 2000
  326. Revision 1.12 2000/01/07 16:32:25 daniel
  327. * copyright 2000 added
  328. Revision 1.11 1999/09/15 20:28:35 florian
  329. * fixed methodname/address: the loops must go from 0 to ...^.count-1
  330. Revision 1.10 1999/09/12 14:53:26 florian
  331. + tobject.methodaddress und tobject.methodname durchsucht nun auch
  332. die Elternklassen
  333. Revision 1.9 1999/09/12 08:01:00 florian
  334. + implementation of TObject.MethodName and TObject.MethodAddress (not
  335. in the compiler yet)
  336. Revision 1.8 1999/09/08 16:14:41 peter
  337. * pointer fixes
  338. Revision 1.7 1999/07/11 14:10:48 michael
  339. + Adaptes Dispatch(STr) to cope with empty/non-existent message tables
  340. Revision 1.6 1999/07/11 14:05:50 michael
  341. + Added
  342. Revision 1.5 1999/07/05 20:04:24 peter
  343. * removed temp defines
  344. Revision 1.4 1999/05/19 13:20:09 peter
  345. * fixed dispatchstr
  346. Revision 1.3 1999/05/17 21:52:37 florian
  347. * most of the Object Pascal stuff moved to the system unit
  348. }