objpas.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  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. UName : ShortString;
  97. methodtable : pmethodnametable;
  98. i : dword;
  99. c : tclass;
  100. begin
  101. UName := UpCase(name);
  102. c:=self;
  103. while assigned(c) do
  104. begin
  105. methodtable:=pmethodnametable((Pointer(c)+vmtMethodTable)^);
  106. if assigned(methodtable) then
  107. begin
  108. for i:=0 to methodtable^.count-1 do
  109. if UpCase(methodtable^.entries[i].name^)=UName then
  110. begin
  111. MethodAddress:=methodtable^.entries[i].addr;
  112. exit;
  113. end;
  114. end;
  115. c:=c.ClassParent;
  116. end;
  117. MethodAddress:=nil;
  118. end;
  119. class function TObject.MethodName(address : pointer) : shortstring;
  120. var
  121. methodtable : pmethodnametable;
  122. i : dword;
  123. c : tclass;
  124. begin
  125. c:=self;
  126. while assigned(c) do
  127. begin
  128. methodtable:=pmethodnametable((Pointer(c)+vmtMethodTable)^);
  129. if assigned(methodtable) then
  130. begin
  131. for i:=0 to methodtable^.count-1 do
  132. if methodtable^.entries[i].addr=address then
  133. begin
  134. MethodName:=methodtable^.entries[i].name^;
  135. exit;
  136. end;
  137. end;
  138. c:=c.ClassParent;
  139. end;
  140. MethodName:='';
  141. end;
  142. function TObject.FieldAddress(const name : shortstring) : pointer;
  143. type
  144. PFieldInfo = ^TFieldInfo;
  145. TFieldInfo = packed record
  146. FieldOffset: LongWord;
  147. ClassTypeIndex: Word;
  148. Name: ShortString;
  149. end;
  150. PFieldTable = ^TFieldTable;
  151. TFieldTable = packed record
  152. FieldCount: Word;
  153. ClassTable: Pointer;
  154. { Fields: array[Word] of TFieldInfo; Elements have variant size! }
  155. end;
  156. var
  157. UName: ShortString;
  158. CurClassType: TClass;
  159. FieldTable: PFieldTable;
  160. FieldInfo: PFieldInfo;
  161. i: Integer;
  162. begin
  163. if Length(name) > 0 then
  164. begin
  165. UName := UpCase(name);
  166. CurClassType := ClassType;
  167. while CurClassType <> nil do
  168. begin
  169. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  170. if FieldTable <> nil then
  171. begin
  172. FieldInfo := PFieldInfo(Pointer(FieldTable) + 6);
  173. for i := 0 to FieldTable^.FieldCount - 1 do
  174. begin
  175. if UpCase(FieldInfo^.Name) = UName then
  176. begin
  177. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  178. exit;
  179. end;
  180. Inc(Pointer(FieldInfo), 7 + Length(FieldInfo^.Name));
  181. end;
  182. end;
  183. { Try again with the parent class type }
  184. CurClassType := CurClassType.ClassParent;
  185. end;
  186. end;
  187. fieldaddress:=nil;
  188. end;
  189. function TObject.SafeCallException(exceptobject : tobject;
  190. exceptaddr : pointer) : longint;
  191. begin
  192. safecallexception:=0;
  193. end;
  194. class function TObject.ClassInfo : pointer;
  195. begin
  196. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  197. end;
  198. class function TObject.ClassName : ShortString;
  199. begin
  200. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  201. end;
  202. class function TObject.ClassNameIs(const name : string) : boolean;
  203. begin
  204. ClassNameIs:=Upcase(ClassName)=Upcase(name);
  205. end;
  206. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  207. var
  208. c : tclass;
  209. begin
  210. c:=self;
  211. while assigned(c) do
  212. begin
  213. if c=aclass then
  214. begin
  215. InheritsFrom:=true;
  216. exit;
  217. end;
  218. c:=c.ClassParent;
  219. end;
  220. InheritsFrom:=false;
  221. end;
  222. class function TObject.stringmessagetable : pstringmessagetable;
  223. type
  224. pdword = ^dword;
  225. begin
  226. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  227. end;
  228. type
  229. tmessagehandler = procedure(var msg) of object;
  230. tmessagehandlerrec = packed record
  231. proc : pointer;
  232. obj : pointer;
  233. end;
  234. procedure TObject.Dispatch(var message);
  235. type
  236. tmsgtable = record
  237. index : dword;
  238. method : pointer;
  239. end;
  240. pmsgtable = ^tmsgtable;
  241. pdword = ^dword;
  242. var
  243. index : dword;
  244. count,i : longint;
  245. msgtable : pmsgtable;
  246. p : pointer;
  247. vmt : tclass;
  248. msghandler : tmessagehandler;
  249. begin
  250. index:=dword(message);
  251. vmt:=ClassType;
  252. while assigned(vmt) do
  253. begin
  254. // See if we have messages at all in this class.
  255. p:=pointer(vmt)+vmtDynamicTable;
  256. If Assigned(p) and (Pdword(p)^<>0) then
  257. begin
  258. msgtable:=pmsgtable(pdword(P)^+4);
  259. count:=pdword(pdword(P)^)^;
  260. end
  261. else
  262. Count:=0;
  263. { later, we can implement a binary search here }
  264. for i:=0 to count-1 do
  265. begin
  266. if index=msgtable[i].index then
  267. begin
  268. p:=msgtable[i].method;
  269. tmessagehandlerrec(msghandler).proc:=p;
  270. tmessagehandlerrec(msghandler).obj:=self;
  271. msghandler(message);
  272. { we don't need any longer the assembler
  273. solution
  274. asm
  275. pushl message
  276. pushl %esi
  277. movl p,%edi
  278. call *%edi
  279. end;
  280. }
  281. exit;
  282. end;
  283. end;
  284. vmt:=vmt.ClassParent;
  285. end;
  286. DefaultHandler(message);
  287. end;
  288. procedure TObject.DispatchStr(var message);
  289. type
  290. pdword = ^dword;
  291. var
  292. name : shortstring;
  293. count,i : longint;
  294. msgstrtable : pmsgstrtable;
  295. p : pointer;
  296. vmt : tclass;
  297. msghandler : tmessagehandler;
  298. begin
  299. name:=pshortstring(@message)^;
  300. vmt:=ClassType;
  301. while assigned(vmt) do
  302. begin
  303. p:=(pointer(vmt)+vmtMsgStrPtr);
  304. If (P<>Nil) and (PDWord(P)^<>0) then
  305. begin
  306. count:=pdword(pdword(p)^)^;
  307. msgstrtable:=pmsgstrtable(pdword(P)^+4);
  308. end
  309. else
  310. Count:=0;
  311. { later, we can implement a binary search here }
  312. for i:=0 to count-1 do
  313. begin
  314. if name=msgstrtable[i].name^ then
  315. begin
  316. p:=msgstrtable[i].method;
  317. tmessagehandlerrec(msghandler).proc:=p;
  318. tmessagehandlerrec(msghandler).obj:=self;
  319. msghandler(message);
  320. { we don't need any longer the assembler
  321. solution
  322. asm
  323. pushl message
  324. pushl %esi
  325. movl p,%edi
  326. call *%edi
  327. end;
  328. }
  329. exit;
  330. end;
  331. end;
  332. vmt:=vmt.ClassParent;
  333. end;
  334. DefaultHandlerStr(message);
  335. end;
  336. procedure TObject.DefaultHandler(var message);
  337. begin
  338. end;
  339. procedure TObject.DefaultHandlerStr(var message);
  340. begin
  341. end;
  342. procedure TObject.CleanupInstance;
  343. var
  344. vmt : tclass;
  345. begin
  346. vmt:=ClassType;
  347. while vmt<>nil do
  348. begin
  349. if Assigned(Pointer((Pointer(vmt)+vmtInitTable)^)) then
  350. Finalize(Pointer(Self),Pointer((Pointer(vmt)+vmtInitTable)^));
  351. vmt:=vmt.ClassParent;
  352. end;
  353. end;
  354. procedure TObject.AfterConstruction;
  355. begin
  356. end;
  357. procedure TObject.BeforeDestruction;
  358. begin
  359. end;
  360. {****************************************************************************
  361. Exception Support
  362. ****************************************************************************}
  363. {$i except.inc}
  364. {****************************************************************************
  365. Initialize
  366. ****************************************************************************}
  367. {
  368. $Log$
  369. Revision 1.3 2000-07-22 14:52:01 sg
  370. * Resolved CVS conflicts for TObject.MethodAddress patch
  371. Revision 1.1.2.1 2000/07/22 14:46:57 sg
  372. * Made TObject.MethodAddress case independent
  373. }