objpas.pp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1998 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. unit objpas;
  13. {$I-,S-}
  14. interface
  15. {*****************************************************************************
  16. Basic Types/constants
  17. *****************************************************************************}
  18. const
  19. // vmtSelfPtr = -36; { not implemented yet }
  20. vmtMsgStrPtr = -36;
  21. vmtIntfTable = -32;
  22. vmtAutoTable = -28;
  23. vmtInitTable = -24;
  24. vmtTypeInfo = -20;
  25. vmtFieldTable = -16;
  26. vmtMethodTable = -12;
  27. vmtDynamicTable = -8;
  28. vmtClassName = -4;
  29. vmtInstanceSize = 0;
  30. vmtParent = 8;
  31. vmtDestroy = 12;
  32. vmtNewInstance = 16;
  33. vmtFreeInstance = 20;
  34. vmtSafeCallException = 24;
  35. vmtDefaultHandler = 28;
  36. vmtAfterConstruction = 32;
  37. vmtBeforeDestruction = 36;
  38. vmtDefaultHandlerStr = 40;
  39. type
  40. { first, in object pascal, the types must be redefined }
  41. smallint = system.integer;
  42. integer = system.longint;
  43. { some pointer definitions }
  44. pshortstring = ^shortstring;
  45. plongstring = ^longstring;
  46. pansistring = ^ansistring;
  47. pwidestring = ^widestring;
  48. // pstring = pansistring;
  49. pextended = ^extended;
  50. ppointer = ^pointer;
  51. { now the let's declare the base classes for the class object }
  52. { model }
  53. tobject = class;
  54. tclass = class of tobject;
  55. pclass = ^tclass;
  56. { to access the message table from outside }
  57. tmsgstrtable = record
  58. name : pshortstring;
  59. method : pointer;
  60. end;
  61. pmsgstrtable = ^tmsgstrtable;
  62. tstringmessagetable = record
  63. count : dword;
  64. msgstrtable : array[0..0] of tmsgstrtable;
  65. end;
  66. pstringmessagetable = ^tstringmessagetable;
  67. tobject = class
  68. { please don't change the order of virtual methods, because }
  69. { their vmt offsets are used by some assembler code which uses }
  70. { hard coded addresses (FK) }
  71. constructor create;
  72. { the virtual procedures must be in THAT order }
  73. destructor destroy;virtual;
  74. class function newinstance : tobject;virtual;
  75. procedure freeinstance;virtual;
  76. function safecallexception(exceptobject : tobject;
  77. exceptaddr : pointer) : integer;virtual;
  78. procedure defaulthandler(var message);virtual;
  79. procedure free;
  80. class function initinstance(instance : pointer) : tobject;
  81. procedure cleanupinstance;
  82. function classtype : tclass;
  83. class function classinfo : pointer;
  84. class function classname : shortstring;
  85. class function classnameis(const name : string) : boolean;
  86. class function classparent : tclass;
  87. class function instancesize : longint;
  88. class function inheritsfrom(aclass : tclass) : boolean;
  89. class function stringmessagetable : pstringmessagetable;
  90. { message handling routines }
  91. procedure dispatch(var message);
  92. procedure dispatchstr(var message);
  93. class function methodaddress(const name : shortstring) : pointer;
  94. class function methodname(address : pointer) : shortstring;
  95. function fieldaddress(const name : shortstring) : pointer;
  96. { new since Delphi 4 }
  97. procedure AfterConstruction;virtual;
  98. procedure BeforeDestruction;virtual;
  99. { new for gtk, default handler for text based messages }
  100. procedure DefaultHandlerStr(var message);virtual;
  101. { interface functions, I don't know if we need this }
  102. {
  103. function getinterface(const iid : tguid;out obj) : boolean;
  104. class function getinterfaceentry(const iid : tguid) : pinterfaceentry;
  105. class function getinterfacetable : pinterfacetable;
  106. }
  107. end;
  108. TExceptProc = Procedure (Obj : TObject; Addr: Pointer);
  109. Const
  110. ExceptProc : Pointer {TExceptProc} = Nil;
  111. {*****************************************************************************
  112. Variant Type
  113. *****************************************************************************}
  114. Const
  115. varEmpty = $0000;
  116. varNull = $0001;
  117. varSmallint = $0002;
  118. varInteger = $0003;
  119. varSingle = $0004;
  120. varDouble = $0005;
  121. varCurrency = $0006;
  122. varDate = $0007;
  123. varOleStr = $0008;
  124. varDispatch = $0009;
  125. varError = $000A;
  126. varBoolean = $000B;
  127. varVariant = $000C;
  128. varUnknown = $000D;
  129. varByte = $0011;
  130. varString = $0100;
  131. varAny = $0101;
  132. varTypeMask = $0FFF;
  133. varArray = $2000;
  134. varByRef = $4000;
  135. vtInteger = 0;
  136. vtBoolean = 1;
  137. vtChar = 2;
  138. vtExtended = 3;
  139. vtString = 4;
  140. vtPointer = 5;
  141. vtPChar = 6;
  142. vtObject = 7;
  143. vtClass = 8;
  144. vtWideChar = 9;
  145. vtPWideChar = 10;
  146. vtAnsiString = 11;
  147. vtCurrency = 12;
  148. vtVariant = 13;
  149. vtInterface = 14;
  150. vtWideString = 15;
  151. vtInt64 = 16;
  152. Type
  153. PVarRec = ^TVarRec;
  154. TVarRec = record
  155. case VType : Longint of
  156. vtInteger : (VInteger: Integer);
  157. vtBoolean : (VBoolean: Boolean);
  158. vtChar : (VChar: Char);
  159. vtExtended : (VExtended: PExtended);
  160. vtString : (VString: PShortString);
  161. vtPointer : (VPointer: Pointer);
  162. vtPChar : (VPChar: PChar);
  163. vtObject : (VObject: TObject);
  164. vtClass : (VClass: TClass);
  165. // vtWideChar : (VWideChar: WideChar);
  166. // vtPWideChar : (VPWideChar: PWideChar);
  167. vtAnsiString : (VAnsiString: Pointer);
  168. // vtCurrency : (VCurrency: PCurrency);
  169. // vtVariant : (VVariant: PVariant);
  170. // vtInterface : (VInterface: Pointer);
  171. vtWideString : (VWideString: Pointer);
  172. // vtInt64 : (VInt64: PInt64);
  173. end;
  174. {****************************************************************************
  175. Compatibiity routines.
  176. ****************************************************************************}
  177. { Untyped file support }
  178. Procedure AssignFile(Var f:File;const Name:string);
  179. Procedure AssignFile(Var f:File;p:pchar);
  180. Procedure AssignFile(Var f:File;c:char);
  181. Procedure CloseFile(Var f:File);
  182. { Text file support }
  183. Procedure AssignFile(Var t:Text;const s:string);
  184. Procedure AssignFile(Var t:Text;p:pchar);
  185. Procedure AssignFile(Var t:Text;c:char);
  186. Procedure CloseFile(Var t:Text);
  187. { Typed file supoort }
  188. Procedure AssignFile(Var f:TypedFile;const Name:string);
  189. Procedure AssignFile(Var f:TypedFile;p:pchar);
  190. Procedure AssignFile(Var f:TypedFile;c:char);
  191. implementation
  192. Procedure HandleError (Errno : longint);external name 'FPC_HANDLEERROR';
  193. {****************************************************************************
  194. Internal Routines called from the Compiler
  195. ****************************************************************************}
  196. procedure finalize(data,typeinfo : pointer);external name 'FPC_FINALIZE';
  197. { the reverse order of the parameters make code generation easier }
  198. function int_do_is(aclass : tclass;aobject : tobject) : boolean;[public,alias: 'FPC_DO_IS'];
  199. begin
  200. int_do_is:=aobject.inheritsfrom(aclass);
  201. end;
  202. { the reverse order of the parameters make code generation easier }
  203. procedure int_do_as(aclass : tclass;aobject : tobject);[public,alias: 'FPC_DO_AS'];
  204. begin
  205. if assigned(aobject) and not(aobject.inheritsfrom(aclass)) then
  206. handleerror(219);
  207. end;
  208. {****************************************************************************
  209. TOBJECT
  210. ****************************************************************************}
  211. constructor TObject.Create;
  212. begin
  213. end;
  214. destructor TObject.Destroy;
  215. begin
  216. end;
  217. procedure TObject.Free;
  218. begin
  219. // the call via self avoids a warning
  220. if self<>nil then
  221. self.destroy;
  222. end;
  223. class function TObject.InstanceSize : LongInt;
  224. type
  225. plongint = ^longint;
  226. begin
  227. { type of self is class of tobject => it points to the vmt }
  228. { the size is saved at offset 0 }
  229. InstanceSize:=plongint(self)^;
  230. end;
  231. class function TObject.InitInstance(instance : pointer) : tobject;
  232. begin
  233. fillchar(instance^,self.instancesize,0);
  234. { insert VMT pointer into the new created memory area }
  235. { (in class methods self contains the VMT!) }
  236. ppointer(instance)^:=pointer(self);
  237. InitInstance:=TObject(Instance);
  238. end;
  239. class function TObject.ClassParent : tclass;
  240. begin
  241. { type of self is class of tobject => it points to the vmt }
  242. { the parent vmt is saved at offset vmtParent }
  243. classparent:=(pclass(self)+vmtParent)^;
  244. end;
  245. class function TObject.NewInstance : tobject;
  246. var
  247. p : pointer;
  248. begin
  249. getmem(p,instancesize);
  250. InitInstance(p);
  251. NewInstance:=TObject(p);
  252. end;
  253. procedure TObject.FreeInstance;
  254. var
  255. p : Pointer;
  256. begin
  257. CleanupInstance;
  258. { self is a register, so we can't pass it call by reference }
  259. p:=Pointer(Self);
  260. FreeMem(p,InstanceSize);
  261. end;
  262. function TObject.ClassType : TClass;
  263. begin
  264. ClassType:=TClass(Pointer(Self)^)
  265. end;
  266. class function TObject.MethodAddress(const name : shortstring) : pointer;
  267. begin
  268. methodaddress:=nil;
  269. end;
  270. class function TObject.MethodName(address : pointer) : shortstring;
  271. begin
  272. methodname:='';
  273. end;
  274. function TObject.FieldAddress(const name : shortstring) : pointer;
  275. begin
  276. fieldaddress:=nil;
  277. end;
  278. function TObject.SafeCallException(exceptobject : tobject;
  279. exceptaddr : pointer) : integer;
  280. begin
  281. safecallexception:=0;
  282. end;
  283. class function TObject.ClassInfo : pointer;
  284. begin
  285. ClassInfo:=(PPointer(self)+vmtTypeInfo)^;
  286. end;
  287. class function TObject.ClassName : ShortString;
  288. begin
  289. ClassName:=PShortString((PPointer(Self)+vmtClassName)^)^;
  290. end;
  291. class function TObject.ClassNameIs(const name : string) : boolean;
  292. begin
  293. ClassNameIs:=ClassName=name;
  294. end;
  295. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  296. var
  297. c : tclass;
  298. begin
  299. c:=self;
  300. while assigned(c) do
  301. begin
  302. if c=aclass then
  303. begin
  304. InheritsFrom:=true;
  305. exit;
  306. end;
  307. c:=c.ClassParent;
  308. end;
  309. InheritsFrom:=false;
  310. end;
  311. class function TObject.stringmessagetable : pstringmessagetable;
  312. type
  313. pdword = ^dword;
  314. begin
  315. stringmessagetable:=pstringmessagetable((pdword(Self)+vmtMsgStrPtr)^);
  316. end;
  317. procedure TObject.Dispatch(var message);
  318. type
  319. tmsgtable = record
  320. index : dword;
  321. method : pointer;
  322. end;
  323. pmsgtable = ^tmsgtable;
  324. pdword = ^dword;
  325. var
  326. index : dword;
  327. count,i : longint;
  328. msgtable : pmsgtable;
  329. p : pointer;
  330. vmt : tclass;
  331. begin
  332. index:=dword(message);
  333. vmt:=ClassType;
  334. while assigned(vmt) do
  335. begin
  336. msgtable:=pmsgtable((pdword(vmt)+vmtDynamicTable)^+4);
  337. count:=pdword((pdword(vmt)+vmtDynamicTable)^)^;
  338. { later, we can implement a binary search here }
  339. for i:=0 to count-1 do
  340. begin
  341. if index=msgtable[i].index then
  342. begin
  343. p:=msgtable[i].method;
  344. asm
  345. pushl message
  346. pushl %esi
  347. movl p,%edi
  348. call *%edi
  349. end;
  350. exit;
  351. end;
  352. end;
  353. vmt:=vmt.ClassParent;
  354. end;
  355. DefaultHandler(message);
  356. end;
  357. procedure TObject.DispatchStr(var message);
  358. type
  359. pdword = ^dword;
  360. var
  361. name : shortstring;
  362. count,i : longint;
  363. msgstrtable : pmsgstrtable;
  364. p : pointer;
  365. vmt : tclass;
  366. begin
  367. name:=pshortstring(message)^;
  368. vmt:=ClassType;
  369. while assigned(vmt) do
  370. begin
  371. count:=pdword((pdword(vmt)+vmtMsgStrPtr)^)^;
  372. msgstrtable:=pmsgstrtable((pdword(vmt)+vmtMsgStrPtr)^+4);
  373. { later, we can implement a binary search here }
  374. for i:=0 to count-1 do
  375. begin
  376. if name=msgstrtable[i].name^ then
  377. begin
  378. p:=msgstrtable[i].method;
  379. asm
  380. pushl message
  381. pushl %esi
  382. movl p,%edi
  383. call *%edi
  384. end;
  385. exit;
  386. end;
  387. end;
  388. vmt:=vmt.ClassParent;
  389. end;
  390. DefaultHandlerStr(message);
  391. end;
  392. procedure TObject.DefaultHandler(var message);
  393. begin
  394. end;
  395. procedure TObject.DefaultHandlerStr(var message);
  396. begin
  397. end;
  398. procedure TObject.CleanupInstance;
  399. var
  400. vmt : tclass;
  401. begin
  402. vmt:=ClassType;
  403. while vmt<>nil do
  404. begin
  405. if Assigned(Pointer((Pointer(vmt)+vmtInitTable)^)) then
  406. Finalize(Pointer(Self),Pointer((Pointer(vmt)+vmtInitTable)^));
  407. vmt:=vmt.ClassParent;
  408. end;
  409. end;
  410. procedure TObject.AfterConstruction;
  411. begin
  412. end;
  413. procedure TObject.BeforeDestruction;
  414. begin
  415. end;
  416. {****************************************************************************
  417. Compatibiity routines.
  418. ****************************************************************************}
  419. { Untyped file support }
  420. Procedure AssignFile(Var f:File;const Name:string);
  421. begin
  422. System.Assign (F,Name);
  423. end;
  424. Procedure AssignFile(Var f:File;p:pchar);
  425. begin
  426. System.Assign (F,P);
  427. end;
  428. Procedure AssignFile(Var f:File;c:char);
  429. begin
  430. System.Assign (F,C);
  431. end;
  432. Procedure CloseFile(Var f:File);
  433. begin
  434. System.Close(f);
  435. end;
  436. { Text file support }
  437. Procedure AssignFile(Var t:Text;const s:string);
  438. begin
  439. System.Assign (T,S);
  440. end;
  441. Procedure AssignFile(Var t:Text;p:pchar);
  442. begin
  443. System.Assign (T,P);
  444. end;
  445. Procedure AssignFile(Var t:Text;c:char);
  446. begin
  447. System.Assign (T,C);
  448. end;
  449. Procedure CloseFile(Var t:Text);
  450. begin
  451. Close(T);
  452. end;
  453. { Typed file supoort }
  454. Procedure AssignFile(Var f:TypedFile;const Name:string);
  455. begin
  456. system.Assign(F,Name);
  457. end;
  458. Procedure AssignFile(Var f:TypedFile;p:pchar);
  459. begin
  460. system.Assign (F,p);
  461. end;
  462. Procedure AssignFile(Var f:TypedFile;c:char);
  463. begin
  464. system.Assign (F,C);
  465. end;
  466. {****************************************************************************
  467. Exception Support
  468. ****************************************************************************}
  469. {$i except.inc}
  470. {****************************************************************************
  471. Initialize
  472. ****************************************************************************}
  473. begin
  474. InitExceptions;
  475. end.
  476. {
  477. $Log$
  478. Revision 1.22 1999-04-16 20:47:20 florian
  479. + tobject.messagestringtable function for Megido/GTK support
  480. added
  481. Revision 1.21 1999/02/23 14:04:36 pierre
  482. * call %edi => call *%edi
  483. Revision 1.20 1999/02/22 23:30:54 florian
  484. + TObject.Dispatch and TObject.DispatchStr added, working
  485. Revision 1.19 1998/12/24 10:12:03 michael
  486. Implemented AssignFile and CloseFile compatibility
  487. Revision 1.18 1998/10/12 12:42:58 florian
  488. * as operator runtime error can be now caught by an errorproc
  489. Revision 1.17 1998/10/05 12:32:53 peter
  490. + assert() support
  491. Revision 1.16 1998/10/03 15:07:16 florian
  492. + TObject.AfterConstruction and TObject.BeforeDestruction of Delphi 4
  493. Revision 1.15 1998/09/24 16:13:48 michael
  494. Changes in exception and open array handling
  495. Revision 1.14 1998/09/23 12:40:43 michael
  496. Fixed TVarRec again. Should be OK now
  497. Revision 1.13 1998/09/23 12:18:32 michael
  498. + added VType in TVArRec
  499. Revision 1.12 1998/09/23 10:00:47 peter
  500. * tvarrec should be 8 bytes
  501. Revision 1.11 1998/09/22 15:30:07 peter
  502. * array of const update
  503. Revision 1.9 1998/09/16 13:08:19 michael
  504. Added AbstractErrorHandler
  505. Revision 1.8 1998/09/06 21:27:31 florian
  506. + method tobject.classinfo added
  507. Revision 1.7 1998/09/04 08:49:06 peter
  508. * 0.99.5 doesn't compile a whole objpas anymore to overcome crashes
  509. Revision 1.6 1998/08/23 20:58:52 florian
  510. + rtti for objects and classes
  511. + TObject.GetClassName implemented
  512. Revision 1.5 1998/07/30 16:10:11 michael
  513. + Added support for ExceptProc+
  514. Revision 1.4 1998/07/29 15:44:33 michael
  515. included sysutils and math.pp as target. They compile now.
  516. Revision 1.3 1998/07/29 10:09:28 michael
  517. + put in exception support
  518. Revision 1.2 1998/03/25 23:40:24 florian
  519. + stuff from old objpash.inc and objpas.inc merged in
  520. }