objpas.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  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. UName := UpCase(name);
  162. CurClassType := ClassType;
  163. while CurClassType <> nil do
  164. begin
  165. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  166. if FieldTable <> nil then
  167. begin
  168. FieldInfo := PFieldInfo(Pointer(FieldTable) + 6);
  169. for i := 0 to FieldTable^.FieldCount - 1 do
  170. begin
  171. if UpCase(FieldInfo^.Name) = UName then
  172. begin
  173. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  174. exit;
  175. end;
  176. Inc(FieldInfo, 7 + Length(FieldInfo^.Name));
  177. end;
  178. end;
  179. { Try again with the parent class type }
  180. CurClassType := CurClassType.ClassParent;
  181. end;
  182. fieldaddress:=nil;
  183. end;
  184. function TObject.SafeCallException(exceptobject : tobject;
  185. exceptaddr : pointer) : longint;
  186. begin
  187. safecallexception:=0;
  188. end;
  189. class function TObject.ClassInfo : pointer;
  190. begin
  191. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  192. end;
  193. class function TObject.ClassName : ShortString;
  194. begin
  195. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  196. end;
  197. class function TObject.ClassNameIs(const name : string) : boolean;
  198. begin
  199. ClassNameIs:=Upcase(ClassName)=Upcase(name);
  200. end;
  201. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  202. var
  203. c : tclass;
  204. begin
  205. c:=self;
  206. while assigned(c) do
  207. begin
  208. if c=aclass then
  209. begin
  210. InheritsFrom:=true;
  211. exit;
  212. end;
  213. c:=c.ClassParent;
  214. end;
  215. InheritsFrom:=false;
  216. end;
  217. class function TObject.stringmessagetable : pstringmessagetable;
  218. type
  219. pdword = ^dword;
  220. begin
  221. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  222. end;
  223. type
  224. tmessagehandler = procedure(var msg) of object;
  225. tmessagehandlerrec = packed record
  226. proc : pointer;
  227. obj : pointer;
  228. end;
  229. procedure TObject.Dispatch(var message);
  230. type
  231. tmsgtable = record
  232. index : dword;
  233. method : pointer;
  234. end;
  235. pmsgtable = ^tmsgtable;
  236. pdword = ^dword;
  237. var
  238. index : dword;
  239. count,i : longint;
  240. msgtable : pmsgtable;
  241. p : pointer;
  242. vmt : tclass;
  243. msghandler : tmessagehandler;
  244. begin
  245. index:=dword(message);
  246. vmt:=ClassType;
  247. while assigned(vmt) do
  248. begin
  249. // See if we have messages at all in this class.
  250. p:=pointer(vmt)+vmtDynamicTable;
  251. If Assigned(p) and (Pdword(p)^<>0) then
  252. begin
  253. msgtable:=pmsgtable(pdword(P)^+4);
  254. count:=pdword(pdword(P)^)^;
  255. end
  256. else
  257. Count:=0;
  258. { later, we can implement a binary search here }
  259. for i:=0 to count-1 do
  260. begin
  261. if index=msgtable[i].index then
  262. begin
  263. p:=msgtable[i].method;
  264. tmessagehandlerrec(msghandler).proc:=p;
  265. tmessagehandlerrec(msghandler).obj:=self;
  266. msghandler(message);
  267. { we don't need any longer the assembler
  268. solution
  269. asm
  270. pushl message
  271. pushl %esi
  272. movl p,%edi
  273. call *%edi
  274. end;
  275. }
  276. exit;
  277. end;
  278. end;
  279. vmt:=vmt.ClassParent;
  280. end;
  281. DefaultHandler(message);
  282. end;
  283. procedure TObject.DispatchStr(var message);
  284. type
  285. pdword = ^dword;
  286. var
  287. name : shortstring;
  288. count,i : longint;
  289. msgstrtable : pmsgstrtable;
  290. p : pointer;
  291. vmt : tclass;
  292. msghandler : tmessagehandler;
  293. begin
  294. name:=pshortstring(@message)^;
  295. vmt:=ClassType;
  296. while assigned(vmt) do
  297. begin
  298. p:=(pointer(vmt)+vmtMsgStrPtr);
  299. If (P<>Nil) and (PDWord(P)^<>0) then
  300. begin
  301. count:=pdword(pdword(p)^)^;
  302. msgstrtable:=pmsgstrtable(pdword(P)^+4);
  303. end
  304. else
  305. Count:=0;
  306. { later, we can implement a binary search here }
  307. for i:=0 to count-1 do
  308. begin
  309. if name=msgstrtable[i].name^ then
  310. begin
  311. p:=msgstrtable[i].method;
  312. tmessagehandlerrec(msghandler).proc:=p;
  313. tmessagehandlerrec(msghandler).obj:=self;
  314. msghandler(message);
  315. { we don't need any longer the assembler
  316. solution
  317. asm
  318. pushl message
  319. pushl %esi
  320. movl p,%edi
  321. call *%edi
  322. end;
  323. }
  324. exit;
  325. end;
  326. end;
  327. vmt:=vmt.ClassParent;
  328. end;
  329. DefaultHandlerStr(message);
  330. end;
  331. procedure TObject.DefaultHandler(var message);
  332. begin
  333. end;
  334. procedure TObject.DefaultHandlerStr(var message);
  335. begin
  336. end;
  337. procedure TObject.CleanupInstance;
  338. var
  339. vmt : tclass;
  340. begin
  341. vmt:=ClassType;
  342. while vmt<>nil do
  343. begin
  344. if Assigned(Pointer((Pointer(vmt)+vmtInitTable)^)) then
  345. Finalize(Pointer(Self),Pointer((Pointer(vmt)+vmtInitTable)^));
  346. vmt:=vmt.ClassParent;
  347. end;
  348. end;
  349. procedure TObject.AfterConstruction;
  350. begin
  351. end;
  352. procedure TObject.BeforeDestruction;
  353. begin
  354. end;
  355. {****************************************************************************
  356. Exception Support
  357. ****************************************************************************}
  358. {$i except.inc}
  359. {****************************************************************************
  360. Initialize
  361. ****************************************************************************}
  362. {
  363. $Log$
  364. Revision 1.16 2000-06-29 16:32:50 sg
  365. * Implemented TObject.FieldAddress
  366. Revision 1.15 2000/05/16 08:06:14 michael
  367. + Fixed ClassNameIs so it is case insensitive
  368. Revision 1.14 2000/02/09 16:59:31 peter
  369. * truncated log
  370. Revision 1.13 2000/01/07 16:41:36 daniel
  371. * copyright 2000
  372. Revision 1.12 2000/01/07 16:32:25 daniel
  373. * copyright 2000 added
  374. Revision 1.11 1999/09/15 20:28:35 florian
  375. * fixed methodname/address: the loops must go from 0 to ...^.count-1
  376. Revision 1.10 1999/09/12 14:53:26 florian
  377. + tobject.methodaddress und tobject.methodname durchsucht nun auch
  378. die Elternklassen
  379. Revision 1.9 1999/09/12 08:01:00 florian
  380. + implementation of TObject.MethodName and TObject.MethodAddress (not
  381. in the compiler yet)
  382. Revision 1.8 1999/09/08 16:14:41 peter
  383. * pointer fixes
  384. }