nobj.pas 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Routines for the code generation of data structures
  5. like VMT, Messages, VTables, Interfaces descs
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit nobj;
  20. {$i defines.inc}
  21. interface
  22. uses
  23. cutils,cclasses,
  24. symdef,aasm;
  25. type
  26. pprocdeftree = ^tprocdeftree;
  27. tprocdeftree = record
  28. data : tprocdef;
  29. nl : tasmlabel;
  30. l,r : pprocdeftree;
  31. end;
  32. pprocdefcoll = ^tprocdefcoll;
  33. tprocdefcoll = record
  34. data : tprocdef;
  35. next : pprocdefcoll;
  36. end;
  37. psymcoll = ^tsymcoll;
  38. tsymcoll = record
  39. name : pstring;
  40. data : pprocdefcoll;
  41. next : psymcoll;
  42. end;
  43. tclassheader=class
  44. private
  45. _Class : tobjectdef;
  46. count : integer;
  47. private
  48. { message tables }
  49. root : pprocdeftree;
  50. procedure disposeprocdeftree(p : pprocdeftree);
  51. procedure insertmsgint(p : tnamedindexitem);
  52. procedure insertmsgstr(p : tnamedindexitem);
  53. procedure insertint(p : pprocdeftree;var at : pprocdeftree);
  54. procedure insertstr(p : pprocdeftree;var at : pprocdeftree);
  55. procedure writenames(p : pprocdeftree);
  56. procedure writeintentry(p : pprocdeftree);
  57. procedure writestrentry(p : pprocdeftree);
  58. {$ifdef WITHDMT}
  59. private
  60. { dmt }
  61. procedure insertdmtentry(p : tnamedindexitem);
  62. procedure writedmtindexentry(p : pprocdeftree);
  63. procedure writedmtaddressentry(p : pprocdeftree);
  64. {$endif}
  65. private
  66. { published methods }
  67. procedure do_count(p : tnamedindexitem);
  68. procedure genpubmethodtableentry(p : tnamedindexitem);
  69. private
  70. { vmt }
  71. wurzel : psymcoll;
  72. nextvirtnumber : integer;
  73. has_constructor,
  74. has_virtual_method : boolean;
  75. procedure eachsym(sym : tnamedindexitem);
  76. procedure disposevmttree;
  77. private
  78. { interface tables }
  79. function gintfgetvtbllabelname(intfindex: integer): string;
  80. procedure gintfcreatevtbl(intfindex: integer; rawdata,rawcode: TAAsmoutput);
  81. procedure gintfgenentry(intfindex, contintfindex: integer; rawdata: TAAsmoutput);
  82. procedure gintfoptimizevtbls(implvtbl : plongint);
  83. procedure gintfwritedata;
  84. function gintfgetcprocdef(proc: tprocdef;const name: string): tprocdef;
  85. procedure gintfdoonintf(intf: tobjectdef; intfindex: longint);
  86. procedure gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
  87. protected
  88. procedure cgintfwrapper(asmlist: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);virtual;abstract;
  89. public
  90. constructor create(c:tobjectdef);
  91. { generates the message tables for a class }
  92. function genstrmsgtab : tasmlabel;
  93. function genintmsgtab : tasmlabel;
  94. function genpublishedmethodstable : tasmlabel;
  95. {$ifdef WITHDMT}
  96. { generates a DMT for _class }
  97. function gendmt : tasmlabel;
  98. {$endif WITHDMT}
  99. { generates a VMT for _class }
  100. procedure genvmt(list : TAAsmoutput);
  101. { interfaces }
  102. function genintftable: tasmlabel;
  103. procedure writevmt;
  104. procedure writeinterfaceids;
  105. end;
  106. tclassheaderclass=class of tclassheader;
  107. var
  108. cclassheader : tclassheaderclass;
  109. implementation
  110. uses
  111. {$ifdef delphi}
  112. sysutils,
  113. {$else}
  114. strings,
  115. {$endif}
  116. globtype,globals,verbose,
  117. symtable,symconst,symtype,symsym,types,
  118. {$ifdef GDB}
  119. gdb,
  120. {$endif GDB}
  121. systems
  122. ;
  123. {*****************************************************************************
  124. TClassHeader
  125. *****************************************************************************}
  126. constructor tclassheader.create(c:tobjectdef);
  127. begin
  128. inherited Create;
  129. _Class:=c;
  130. end;
  131. {**************************************
  132. Message Tables
  133. **************************************}
  134. procedure tclassheader.disposeprocdeftree(p : pprocdeftree);
  135. begin
  136. if assigned(p^.l) then
  137. disposeprocdeftree(p^.l);
  138. if assigned(p^.r) then
  139. disposeprocdeftree(p^.r);
  140. dispose(p);
  141. end;
  142. procedure tclassheader.insertint(p : pprocdeftree;var at : pprocdeftree);
  143. begin
  144. if at=nil then
  145. begin
  146. at:=p;
  147. inc(count);
  148. end
  149. else
  150. begin
  151. if p^.data.messageinf.i<at^.data.messageinf.i then
  152. insertint(p,at^.l)
  153. else if p^.data.messageinf.i>at^.data.messageinf.i then
  154. insertint(p,at^.r)
  155. else
  156. Message1(parser_e_duplicate_message_label,tostr(p^.data.messageinf.i));
  157. end;
  158. end;
  159. procedure tclassheader.insertstr(p : pprocdeftree;var at : pprocdeftree);
  160. var
  161. i : integer;
  162. begin
  163. if at=nil then
  164. begin
  165. at:=p;
  166. inc(count);
  167. end
  168. else
  169. begin
  170. i:=strcomp(p^.data.messageinf.str,at^.data.messageinf.str);
  171. if i<0 then
  172. insertstr(p,at^.l)
  173. else if i>0 then
  174. insertstr(p,at^.r)
  175. else
  176. Message1(parser_e_duplicate_message_label,strpas(p^.data.messageinf.str));
  177. end;
  178. end;
  179. procedure tclassheader.insertmsgint(p : tnamedindexitem);
  180. var
  181. hp : tprocdef;
  182. pt : pprocdeftree;
  183. begin
  184. if tsym(p).typ=procsym then
  185. begin
  186. hp:=tprocsym(p).definition;
  187. while assigned(hp) do
  188. begin
  189. if (po_msgint in hp.procoptions) then
  190. begin
  191. new(pt);
  192. pt^.data:=hp;
  193. pt^.l:=nil;
  194. pt^.r:=nil;
  195. insertint(pt,root);
  196. end;
  197. hp:=hp.nextoverloaded;
  198. end;
  199. end;
  200. end;
  201. procedure tclassheader.insertmsgstr(p : tnamedindexitem);
  202. var
  203. hp : tprocdef;
  204. pt : pprocdeftree;
  205. begin
  206. if tsym(p).typ=procsym then
  207. begin
  208. hp:=tprocsym(p).definition;
  209. while assigned(hp) do
  210. begin
  211. if (po_msgstr in hp.procoptions) then
  212. begin
  213. new(pt);
  214. pt^.data:=hp;
  215. pt^.l:=nil;
  216. pt^.r:=nil;
  217. insertstr(pt,root);
  218. end;
  219. hp:=hp.nextoverloaded;
  220. end;
  221. end;
  222. end;
  223. procedure tclassheader.writenames(p : pprocdeftree);
  224. begin
  225. getdatalabel(p^.nl);
  226. if assigned(p^.l) then
  227. writenames(p^.l);
  228. dataSegment.concat(Tai_label.Create(p^.nl));
  229. dataSegment.concat(Tai_const.Create_8bit(strlen(p^.data.messageinf.str)));
  230. dataSegment.concat(Tai_string.Create_pchar(p^.data.messageinf.str));
  231. if assigned(p^.r) then
  232. writenames(p^.r);
  233. end;
  234. procedure tclassheader.writestrentry(p : pprocdeftree);
  235. begin
  236. if assigned(p^.l) then
  237. writestrentry(p^.l);
  238. { write name label }
  239. dataSegment.concat(Tai_const_symbol.Create(p^.nl));
  240. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  241. if assigned(p^.r) then
  242. writestrentry(p^.r);
  243. end;
  244. function tclassheader.genstrmsgtab : tasmlabel;
  245. var
  246. r : tasmlabel;
  247. begin
  248. root:=nil;
  249. count:=0;
  250. { insert all message handlers into a tree, sorted by name }
  251. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertmsgstr);
  252. { write all names }
  253. if assigned(root) then
  254. writenames(root);
  255. { now start writing of the message string table }
  256. getdatalabel(r);
  257. dataSegment.concat(Tai_label.Create(r));
  258. genstrmsgtab:=r;
  259. dataSegment.concat(Tai_const.Create_32bit(count));
  260. if assigned(root) then
  261. begin
  262. writestrentry(root);
  263. disposeprocdeftree(root);
  264. end;
  265. end;
  266. procedure tclassheader.writeintentry(p : pprocdeftree);
  267. begin
  268. if assigned(p^.l) then
  269. writeintentry(p^.l);
  270. { write name label }
  271. dataSegment.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  272. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  273. if assigned(p^.r) then
  274. writeintentry(p^.r);
  275. end;
  276. function tclassheader.genintmsgtab : tasmlabel;
  277. var
  278. r : tasmlabel;
  279. begin
  280. root:=nil;
  281. count:=0;
  282. { insert all message handlers into a tree, sorted by name }
  283. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertmsgint);
  284. { now start writing of the message string table }
  285. getdatalabel(r);
  286. dataSegment.concat(Tai_label.Create(r));
  287. genintmsgtab:=r;
  288. dataSegment.concat(Tai_const.Create_32bit(count));
  289. if assigned(root) then
  290. begin
  291. writeintentry(root);
  292. disposeprocdeftree(root);
  293. end;
  294. end;
  295. {$ifdef WITHDMT}
  296. {**************************************
  297. DMT
  298. **************************************}
  299. procedure tclassheader.insertdmtentry(p : tnamedindexitem);
  300. var
  301. hp : tprocdef;
  302. pt : pprocdeftree;
  303. begin
  304. if tsym(p).typ=procsym then
  305. begin
  306. hp:=tprocsym(p).definition;
  307. while assigned(hp) do
  308. begin
  309. if (po_msgint in hp.procoptions) then
  310. begin
  311. new(pt);
  312. pt^.p:=hp;
  313. pt^.l:=nil;
  314. pt^.r:=nil;
  315. insertint(pt,root);
  316. end;
  317. hp:=hp.nextoverloaded;
  318. end;
  319. end;
  320. end;
  321. procedure tclassheader.writedmtindexentry(p : pprocdeftree);
  322. begin
  323. if assigned(p^.l) then
  324. writedmtindexentry(p^.l);
  325. dataSegment.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  326. if assigned(p^.r) then
  327. writedmtindexentry(p^.r);
  328. end;
  329. procedure tclassheader.writedmtaddressentry(p : pprocdeftree);
  330. begin
  331. if assigned(p^.l) then
  332. writedmtaddressentry(p^.l);
  333. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  334. if assigned(p^.r) then
  335. writedmtaddressentry(p^.r);
  336. end;
  337. function tclassheader.gendmt : tasmlabel;
  338. var
  339. r : tasmlabel;
  340. begin
  341. root:=nil;
  342. count:=0;
  343. gendmt:=nil;
  344. { insert all message handlers into a tree, sorted by number }
  345. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertdmtentry);
  346. if count>0 then
  347. begin
  348. getdatalabel(r);
  349. gendmt:=r;
  350. dataSegment.concat(Tai_label.Create(r));
  351. { entries for caching }
  352. dataSegment.concat(Tai_const.Create_32bit(0));
  353. dataSegment.concat(Tai_const.Create_32bit(0));
  354. dataSegment.concat(Tai_const.Create_32bit(count));
  355. if assigned(root) then
  356. begin
  357. writedmtindexentry(root);
  358. writedmtaddressentry(root);
  359. disposeprocdeftree(root);
  360. end;
  361. end;
  362. end;
  363. {$endif WITHDMT}
  364. {**************************************
  365. Published Methods
  366. **************************************}
  367. procedure tclassheader.do_count(p : tnamedindexitem);
  368. begin
  369. if (tsym(p).typ=procsym) and (sp_published in tsym(p).symoptions) then
  370. inc(count);
  371. end;
  372. procedure tclassheader.genpubmethodtableentry(p : tnamedindexitem);
  373. var
  374. hp : tprocdef;
  375. l : tasmlabel;
  376. begin
  377. if (tsym(p).typ=procsym) and (sp_published in tsym(p).symoptions) then
  378. begin
  379. hp:=tprocsym(p).definition;
  380. if assigned(hp.nextoverloaded) then
  381. internalerror(1209992);
  382. getdatalabel(l);
  383. Consts.concat(Tai_label.Create(l));
  384. Consts.concat(Tai_const.Create_8bit(length(p.name)));
  385. Consts.concat(Tai_string.Create(p.name));
  386. dataSegment.concat(Tai_const_symbol.Create(l));
  387. dataSegment.concat(Tai_const_symbol.Createname(hp.mangledname));
  388. end;
  389. end;
  390. function tclassheader.genpublishedmethodstable : tasmlabel;
  391. var
  392. l : tasmlabel;
  393. begin
  394. count:=0;
  395. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}do_count);
  396. if count>0 then
  397. begin
  398. getdatalabel(l);
  399. dataSegment.concat(Tai_label.Create(l));
  400. dataSegment.concat(Tai_const.Create_32bit(count));
  401. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}genpubmethodtableentry);
  402. genpublishedmethodstable:=l;
  403. end
  404. else
  405. genpublishedmethodstable:=nil;
  406. end;
  407. {**************************************
  408. VMT
  409. **************************************}
  410. procedure tclassheader.eachsym(sym : tnamedindexitem);
  411. var
  412. procdefcoll : pprocdefcoll;
  413. hp : tprocdef;
  414. symcoll : psymcoll;
  415. _name : string;
  416. stored : boolean;
  417. { creates a new entry in the procsym list }
  418. procedure newentry;
  419. begin
  420. { if not, generate a new symbol item }
  421. new(symcoll);
  422. symcoll^.name:=stringdup(sym.name);
  423. symcoll^.next:=wurzel;
  424. symcoll^.data:=nil;
  425. wurzel:=symcoll;
  426. hp:=tprocsym(sym).definition;
  427. { inserts all definitions }
  428. while assigned(hp) do
  429. begin
  430. new(procdefcoll);
  431. procdefcoll^.data:=hp;
  432. procdefcoll^.next:=symcoll^.data;
  433. symcoll^.data:=procdefcoll;
  434. { if it's a virtual method }
  435. if (po_virtualmethod in hp.procoptions) then
  436. begin
  437. { then it gets a number ... }
  438. hp.extnumber:=nextvirtnumber;
  439. { and we inc the number }
  440. inc(nextvirtnumber);
  441. has_virtual_method:=true;
  442. end;
  443. if (hp.proctypeoption=potype_constructor) then
  444. has_constructor:=true;
  445. { check, if a method should be overridden }
  446. if (po_overridingmethod in hp.procoptions) then
  447. MessagePos1(hp.fileinfo,parser_e_nothing_to_be_overridden,_class.objname^+'.'+_name+hp.demangled_paras);
  448. { next overloaded method }
  449. hp:=hp.nextoverloaded;
  450. end;
  451. end;
  452. procedure newdefentry;
  453. begin
  454. new(procdefcoll);
  455. procdefcoll^.data:=hp;
  456. procdefcoll^.next:=symcoll^.data;
  457. symcoll^.data:=procdefcoll;
  458. { if it's a virtual method }
  459. if (po_virtualmethod in hp.procoptions) then
  460. begin
  461. { then it gets a number ... }
  462. hp.extnumber:=nextvirtnumber;
  463. { and we inc the number }
  464. inc(nextvirtnumber);
  465. has_virtual_method:=true;
  466. end;
  467. if (hp.proctypeoption=potype_constructor) then
  468. has_constructor:=true;
  469. { check, if a method should be overridden }
  470. if (po_overridingmethod in hp.procoptions) then
  471. MessagePos1(hp.fileinfo,parser_e_nothing_to_be_overridden,_class.objname^+'.'+_name+hp.demangled_paras);
  472. end;
  473. label
  474. handlenextdef;
  475. begin
  476. { put only sub routines into the VMT }
  477. if tsym(sym).typ=procsym then
  478. begin
  479. _name:=sym.name;
  480. symcoll:=wurzel;
  481. while assigned(symcoll) do
  482. begin
  483. { does the symbol already exist in the list ? }
  484. if _name=symcoll^.name^ then
  485. begin
  486. { walk through all defs of the symbol }
  487. hp:=tprocsym(sym).definition;
  488. while assigned(hp) do
  489. begin
  490. { compare with all stored definitions }
  491. procdefcoll:=symcoll^.data;
  492. stored:=false;
  493. while assigned(procdefcoll) do
  494. begin
  495. { compare parameters }
  496. if equal_paras(procdefcoll^.data.para,hp.para,cp_all) and
  497. (
  498. (po_virtualmethod in procdefcoll^.data.procoptions) or
  499. (po_virtualmethod in hp.procoptions)
  500. ) then
  501. begin { same parameters }
  502. { wenn sie gleich sind }
  503. { und eine davon virtual deklariert ist }
  504. { Fehler falls nur eine VIRTUAL }
  505. if (po_virtualmethod in procdefcoll^.data.procoptions)<>
  506. (po_virtualmethod in hp.procoptions) then
  507. begin
  508. { in classes, we hide the old method }
  509. if is_class(_class) then
  510. begin
  511. { warn only if it is the first time,
  512. we hide the method }
  513. if _class=hp._class then
  514. Message1(parser_w_should_use_override,hp.fullprocname);
  515. end
  516. else
  517. if _class=hp._class then
  518. begin
  519. if (po_virtualmethod in procdefcoll^.data.procoptions) then
  520. Message1(parser_w_overloaded_are_not_both_virtual,
  521. hp.fullprocname)
  522. else
  523. Message1(parser_w_overloaded_are_not_both_non_virtual,
  524. hp.fullprocname);
  525. end;
  526. { was newentry; exit; (FK) }
  527. newdefentry;
  528. goto handlenextdef;
  529. end
  530. else
  531. { the flags have to match }
  532. { except abstract and override }
  533. { only if both are virtual !! }
  534. if (procdefcoll^.data.proccalloptions<>hp.proccalloptions) or
  535. (procdefcoll^.data.proctypeoption<>hp.proctypeoption) or
  536. ((procdefcoll^.data.procoptions-
  537. [po_abstractmethod,po_overridingmethod,po_assembler,po_overload])<>
  538. (hp.procoptions-[po_abstractmethod,po_overridingmethod,po_assembler,po_overload])) then
  539. Message1(parser_e_header_dont_match_forward,hp.fullprocname);
  540. { check, if the overridden directive is set }
  541. { (povirtualmethod is set! }
  542. { class ? }
  543. if is_class(_class) and
  544. not(po_overridingmethod in hp.procoptions) then
  545. begin
  546. { warn only if it is the first time,
  547. we hide the method }
  548. if _class=hp._class then
  549. Message1(parser_w_should_use_override,hp.fullprocname);
  550. { was newentry; (FK) }
  551. newdefentry;
  552. exit;
  553. end;
  554. { error, if the return types aren't equal }
  555. if not(is_equal(procdefcoll^.data.rettype.def,hp.rettype.def)) and
  556. not((procdefcoll^.data.rettype.def.deftype=objectdef) and
  557. (hp.rettype.def.deftype=objectdef) and
  558. is_class(procdefcoll^.data.rettype.def) and
  559. is_class(hp.rettype.def) and
  560. (tobjectdef(hp.rettype.def).is_related(
  561. tobjectdef(procdefcoll^.data.rettype.def)))) then
  562. Message2(parser_e_overridden_methods_not_same_ret,hp.fullprocnamewithret,
  563. procdefcoll^.data.fullprocnamewithret);
  564. { now set the number }
  565. hp.extnumber:=procdefcoll^.data.extnumber;
  566. { and exchange }
  567. procdefcoll^.data:=hp;
  568. stored:=true;
  569. goto handlenextdef;
  570. end; { same parameters }
  571. procdefcoll:=procdefcoll^.next;
  572. end;
  573. { if it isn't saved in the list }
  574. { we create a new entry }
  575. if not(stored) then
  576. begin
  577. new(procdefcoll);
  578. procdefcoll^.data:=hp;
  579. procdefcoll^.next:=symcoll^.data;
  580. symcoll^.data:=procdefcoll;
  581. { if the method is virtual ... }
  582. if (po_virtualmethod in hp.procoptions) then
  583. begin
  584. { ... it will get a number }
  585. hp.extnumber:=nextvirtnumber;
  586. inc(nextvirtnumber);
  587. end;
  588. { check, if a method should be overridden }
  589. if (po_overridingmethod in hp.procoptions) then
  590. MessagePos1(hp.fileinfo,parser_e_nothing_to_be_overridden,
  591. hp.fullprocname);
  592. end;
  593. handlenextdef:
  594. hp:=hp.nextoverloaded;
  595. end;
  596. exit;
  597. end;
  598. symcoll:=symcoll^.next;
  599. end;
  600. newentry;
  601. end;
  602. end;
  603. procedure tclassheader.disposevmttree;
  604. var
  605. symcoll : psymcoll;
  606. procdefcoll : pprocdefcoll;
  607. begin
  608. { disposes the above generated tree }
  609. symcoll:=wurzel;
  610. while assigned(symcoll) do
  611. begin
  612. wurzel:=symcoll^.next;
  613. stringdispose(symcoll^.name);
  614. procdefcoll:=symcoll^.data;
  615. while assigned(procdefcoll) do
  616. begin
  617. symcoll^.data:=procdefcoll^.next;
  618. dispose(procdefcoll);
  619. procdefcoll:=symcoll^.data;
  620. end;
  621. dispose(symcoll);
  622. symcoll:=wurzel;
  623. end;
  624. end;
  625. procedure tclassheader.genvmt(list : TAAsmoutput);
  626. procedure do_genvmt(p : tobjectdef);
  627. begin
  628. { start with the base class }
  629. if assigned(p.childof) then
  630. do_genvmt(p.childof);
  631. { walk through all public syms }
  632. p.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}eachsym);
  633. end;
  634. var
  635. symcoll : psymcoll;
  636. procdefcoll : pprocdefcoll;
  637. i : longint;
  638. begin
  639. wurzel:=nil;
  640. nextvirtnumber:=0;
  641. has_constructor:=false;
  642. has_virtual_method:=false;
  643. { generates a tree of all used methods }
  644. do_genvmt(_class);
  645. if has_virtual_method and not(has_constructor) then
  646. Message1(parser_w_virtual_without_constructor,_class.objname^);
  647. { generates the VMT }
  648. { walk trough all numbers for virtual methods and search }
  649. { the method }
  650. for i:=0 to nextvirtnumber-1 do
  651. begin
  652. symcoll:=wurzel;
  653. { walk trough all symbols }
  654. while assigned(symcoll) do
  655. begin
  656. { walk trough all methods }
  657. procdefcoll:=symcoll^.data;
  658. while assigned(procdefcoll) do
  659. begin
  660. { writes the addresses to the VMT }
  661. { but only this which are declared as virtual }
  662. if procdefcoll^.data.extnumber=i then
  663. begin
  664. if (po_virtualmethod in procdefcoll^.data.procoptions) then
  665. begin
  666. { if a method is abstract, then is also the }
  667. { class abstract and it's not allow to }
  668. { generates an instance }
  669. if (po_abstractmethod in procdefcoll^.data.procoptions) then
  670. begin
  671. include(_class.objectoptions,oo_has_abstract);
  672. List.concat(Tai_const_symbol.Createname('FPC_ABSTRACTERROR'));
  673. end
  674. else
  675. begin
  676. List.concat(Tai_const_symbol.createname(procdefcoll^.data.mangledname));
  677. end;
  678. end;
  679. end;
  680. procdefcoll:=procdefcoll^.next;
  681. end;
  682. symcoll:=symcoll^.next;
  683. end;
  684. end;
  685. disposevmttree;
  686. end;
  687. {**************************************
  688. Interface tables
  689. **************************************}
  690. function tclassheader.gintfgetvtbllabelname(intfindex: integer): string;
  691. begin
  692. gintfgetvtbllabelname:='_$$_'+upper(_class.objname^)+'_$$_'+
  693. upper(_class.implementedinterfaces.interfaces(intfindex).objname^)+'_$$_VTBL';
  694. end;
  695. procedure tclassheader.gintfcreatevtbl(intfindex: integer; rawdata,rawcode: TAAsmoutput);
  696. var
  697. implintf: timplementedinterfaces;
  698. curintf: tobjectdef;
  699. proccount: integer;
  700. tmps: string;
  701. i: longint;
  702. begin
  703. implintf:=_class.implementedinterfaces;
  704. curintf:=implintf.interfaces(intfindex);
  705. rawdata.concat(Tai_symbol.Createname(gintfgetvtbllabelname(intfindex),0));
  706. proccount:=implintf.implproccount(intfindex);
  707. for i:=1 to proccount do
  708. begin
  709. tmps:=implintf.implprocs(intfindex,i).mangledname+'_$$_'+upper(curintf.objname^);
  710. { create wrapper code }
  711. cgintfwrapper(rawcode,implintf.implprocs(intfindex,i),tmps,implintf.ioffsets(intfindex)^);
  712. { create reference }
  713. rawdata.concat(Tai_const_symbol.Createname(tmps));
  714. end;
  715. end;
  716. procedure tclassheader.gintfgenentry(intfindex, contintfindex: integer; rawdata: TAAsmoutput);
  717. var
  718. implintf: timplementedinterfaces;
  719. curintf: tobjectdef;
  720. tmplabel: tasmlabel;
  721. i: longint;
  722. begin
  723. implintf:=_class.implementedinterfaces;
  724. curintf:=implintf.interfaces(intfindex);
  725. { GUID }
  726. if curintf.objecttype in [odt_interfacecom] then
  727. begin
  728. { label for GUID }
  729. getdatalabel(tmplabel);
  730. rawdata.concat(Tai_label.Create(tmplabel));
  731. rawdata.concat(Tai_const.Create_32bit(curintf.iidguid.D1));
  732. rawdata.concat(Tai_const.Create_16bit(curintf.iidguid.D2));
  733. rawdata.concat(Tai_const.Create_16bit(curintf.iidguid.D3));
  734. for i:=Low(curintf.iidguid.D4) to High(curintf.iidguid.D4) do
  735. rawdata.concat(Tai_const.Create_8bit(curintf.iidguid.D4[i]));
  736. dataSegment.concat(Tai_const_symbol.Create(tmplabel));
  737. end
  738. else
  739. begin
  740. { nil for Corba interfaces }
  741. dataSegment.concat(Tai_const.Create_32bit(0)); { nil }
  742. end;
  743. { VTable }
  744. dataSegment.concat(Tai_const_symbol.Createname(gintfgetvtbllabelname(contintfindex)));
  745. { IOffset field }
  746. dataSegment.concat(Tai_const.Create_32bit(implintf.ioffsets(contintfindex)^));
  747. { IIDStr }
  748. getdatalabel(tmplabel);
  749. rawdata.concat(Tai_label.Create(tmplabel));
  750. rawdata.concat(Tai_const.Create_8bit(length(curintf.iidstr^)));
  751. if curintf.objecttype=odt_interfacecom then
  752. rawdata.concat(Tai_string.Create(upper(curintf.iidstr^)))
  753. else
  754. rawdata.concat(Tai_string.Create(curintf.iidstr^));
  755. dataSegment.concat(Tai_const_symbol.Create(tmplabel));
  756. end;
  757. procedure tclassheader.gintfoptimizevtbls(implvtbl : plongint);
  758. type
  759. tcompintfentry = record
  760. weight: longint;
  761. compintf: longint;
  762. end;
  763. { Max 1000 interface in the class header interfaces it's enough imho }
  764. tcompintfs = packed array[1..1000] of tcompintfentry;
  765. pcompintfs = ^tcompintfs;
  766. tequals = packed array[1..1000] of longint;
  767. pequals = ^tequals;
  768. var
  769. max: longint;
  770. equals: pequals;
  771. compats: pcompintfs;
  772. i: longint;
  773. j: longint;
  774. w: longint;
  775. cij: boolean;
  776. cji: boolean;
  777. begin
  778. max:=_class.implementedinterfaces.count;
  779. if max>High(tequals) then
  780. Internalerror(200006135);
  781. getmem(compats,sizeof(tcompintfentry)*max);
  782. getmem(equals,sizeof(longint)*max);
  783. fillchar(compats^,sizeof(tcompintfentry)*max,0);
  784. fillchar(equals^,sizeof(longint)*max,0);
  785. { ismergepossible is a containing relation
  786. meaning of ismergepossible(a,b,w) =
  787. if implementorfunction map of a is contained implementorfunction map of b
  788. imp(a,b) and imp(b,c) => imp(a,c) ; imp(a,b) and imp(b,a) => a == b
  789. }
  790. { the order is very important for correct allocation }
  791. for i:=1 to max do
  792. begin
  793. for j:=i+1 to max do
  794. begin
  795. cij:=_class.implementedinterfaces.isimplmergepossible(i,j,w);
  796. cji:=_class.implementedinterfaces.isimplmergepossible(j,i,w);
  797. if cij and cji then { i equal j }
  798. begin
  799. { get minimum index of equal }
  800. if equals^[j]=0 then
  801. equals^[j]:=i;
  802. end
  803. else if cij then
  804. begin
  805. { get minimum index of maximum weight }
  806. if compats^[i].weight<w then
  807. begin
  808. compats^[i].weight:=w;
  809. compats^[i].compintf:=j;
  810. end;
  811. end
  812. else if cji then
  813. begin
  814. { get minimum index of maximum weight }
  815. if (compats^[j].weight<w) then
  816. begin
  817. compats^[j].weight:=w;
  818. compats^[j].compintf:=i;
  819. end;
  820. end;
  821. end;
  822. end;
  823. for i:=1 to max do
  824. begin
  825. if compats^[i].compintf<>0 then
  826. implvtbl[i]:=compats^[i].compintf
  827. else if equals^[i]<>0 then
  828. implvtbl[i]:=equals^[i]
  829. else
  830. implvtbl[i]:=i;
  831. end;
  832. freemem(compats,sizeof(tcompintfentry)*max);
  833. freemem(equals,sizeof(longint)*max);
  834. end;
  835. procedure tclassheader.gintfwritedata;
  836. var
  837. rawdata,rawcode: taasmoutput;
  838. impintfindexes: plongint;
  839. max: longint;
  840. i: longint;
  841. begin
  842. max:=_class.implementedinterfaces.count;
  843. getmem(impintfindexes,(max+1)*sizeof(longint));
  844. gintfoptimizevtbls(impintfindexes);
  845. rawdata:=TAAsmOutput.Create;
  846. rawcode:=TAAsmOutput.Create;
  847. dataSegment.concat(Tai_const.Create_16bit(max));
  848. { Two pass, one for allocation and vtbl creation }
  849. for i:=1 to max do
  850. begin
  851. if impintfindexes[i]=i then { if implement itself }
  852. begin
  853. { allocate a pointer in the object memory }
  854. with tstoredsymtable(_class.symtable) do
  855. begin
  856. if (dataalignment>=target_info.size_of_pointer) then
  857. datasize:=align(datasize,dataalignment)
  858. else
  859. datasize:=align(datasize,target_info.size_of_pointer);
  860. _class.implementedinterfaces.ioffsets(i)^:=datasize;
  861. datasize:=datasize+target_info.size_of_pointer;
  862. end;
  863. { write vtbl }
  864. gintfcreatevtbl(i,rawdata,rawcode);
  865. end;
  866. end;
  867. { second pass: for fill interfacetable and remained ioffsets }
  868. for i:=1 to max do
  869. begin
  870. if i<>impintfindexes[i] then { why execute x:=x ? }
  871. with _class.implementedinterfaces do
  872. ioffsets(i)^:=ioffsets(impintfindexes[i])^;
  873. gintfgenentry(i,impintfindexes[i],rawdata);
  874. end;
  875. dataSegment.insertlist(rawdata);
  876. rawdata.free;
  877. if (cs_create_smart in aktmoduleswitches) then
  878. rawcode.insert(Tai_cut.Create);
  879. codeSegment.insertlist(rawcode);
  880. rawcode.free;
  881. freemem(impintfindexes,(max+1)*sizeof(longint));
  882. end;
  883. function tclassheader.gintfgetcprocdef(proc: tprocdef;const name: string): tprocdef;
  884. var
  885. sym: tprocsym;
  886. implprocdef: tprocdef;
  887. begin
  888. implprocdef:=nil;
  889. sym:=tprocsym(search_class_member(_class,name));
  890. if assigned(sym) and (sym.typ=procsym) then
  891. begin
  892. implprocdef:=sym.definition;
  893. while assigned(implprocdef) and not equal_paras(proc.para,implprocdef.para,cp_none) and
  894. (proc.proccalloptions<>implprocdef.proccalloptions) do
  895. implprocdef:=implprocdef.nextoverloaded;
  896. end;
  897. gintfgetcprocdef:=implprocdef;
  898. end;
  899. procedure tclassheader.gintfdoonintf(intf: tobjectdef; intfindex: longint);
  900. var
  901. i: longint;
  902. proc: tprocdef;
  903. procname: string; { for error }
  904. mappedname: string;
  905. nextexist: pointer;
  906. implprocdef: tprocdef;
  907. begin
  908. for i:=1 to intf.symtable.defindex.count do
  909. begin
  910. proc:=tprocdef(intf.symtable.defindex.search(i));
  911. if proc.deftype=procdef then
  912. begin
  913. procname:='';
  914. implprocdef:=nil;
  915. nextexist:=nil;
  916. repeat
  917. mappedname:=_class.implementedinterfaces.getmappings(intfindex,proc.procsym.name,nextexist);
  918. if procname='' then
  919. procname:=proc.procsym.name;
  920. //mappedname; { for error messages }
  921. if mappedname<>'' then
  922. implprocdef:=gintfgetcprocdef(proc,mappedname);
  923. until assigned(implprocdef) or not assigned(nextexist);
  924. if not assigned(implprocdef) then
  925. implprocdef:=gintfgetcprocdef(proc,proc.procsym.name);
  926. if procname='' then
  927. procname:=proc.procsym.name;
  928. if assigned(implprocdef) then
  929. _class.implementedinterfaces.addimplproc(intfindex,implprocdef)
  930. else
  931. Message1(sym_e_id_not_found,procname);
  932. end;
  933. end;
  934. end;
  935. procedure tclassheader.gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
  936. begin
  937. if assigned(intf.childof) then
  938. gintfwalkdowninterface(intf.childof,intfindex);
  939. gintfdoonintf(intf,intfindex);
  940. end;
  941. function tclassheader.genintftable: tasmlabel;
  942. var
  943. intfindex: longint;
  944. curintf: tobjectdef;
  945. intftable: tasmlabel;
  946. begin
  947. { 1. step collect implementor functions into the implementedinterfaces.implprocs }
  948. for intfindex:=1 to _class.implementedinterfaces.count do
  949. begin
  950. curintf:=_class.implementedinterfaces.interfaces(intfindex);
  951. gintfwalkdowninterface(curintf,intfindex);
  952. end;
  953. { 2. step calc required fieldcount and their offsets in the object memory map
  954. and write data }
  955. getdatalabel(intftable);
  956. dataSegment.concat(Tai_label.Create(intftable));
  957. gintfwritedata;
  958. _class.implementedinterfaces.clearimplprocs; { release temporary information }
  959. genintftable:=intftable;
  960. end;
  961. { Write interface identifiers to the data section }
  962. procedure tclassheader.writeinterfaceids;
  963. var
  964. i: longint;
  965. s1,s2 : string;
  966. begin
  967. if _class.owner.name=nil then
  968. s1:=''
  969. else
  970. s1:=upper(_class.owner.name^);
  971. if _class.objname=nil then
  972. s2:=''
  973. else
  974. s2:=upper(_class.objname^);
  975. s1:=s1+'$_'+s2;
  976. if _class.isiidguidvalid then
  977. begin
  978. if (cs_create_smart in aktmoduleswitches) then
  979. dataSegment.concat(Tai_cut.Create);
  980. dataSegment.concat(Tai_symbol.Createname_global('IID$_'+s1,0));
  981. dataSegment.concat(Tai_const.Create_32bit(longint(_class.iidguid.D1)));
  982. dataSegment.concat(Tai_const.Create_16bit(_class.iidguid.D2));
  983. dataSegment.concat(Tai_const.Create_16bit(_class.iidguid.D3));
  984. for i:=Low(_class.iidguid.D4) to High(_class.iidguid.D4) do
  985. dataSegment.concat(Tai_const.Create_8bit(_class.iidguid.D4[i]));
  986. end;
  987. if (cs_create_smart in aktmoduleswitches) then
  988. dataSegment.concat(Tai_cut.Create);
  989. dataSegment.concat(Tai_symbol.Createname_global('IIDSTR$_'+s1,0));
  990. dataSegment.concat(Tai_const.Create_8bit(length(_class.iidstr^)));
  991. dataSegment.concat(Tai_string.Create(_class.iidstr^));
  992. end;
  993. { generates the vmt for classes as well as for objects }
  994. procedure tclassheader.writevmt;
  995. var
  996. vmtlist : taasmoutput;
  997. methodnametable,intmessagetable,
  998. strmessagetable,classnamelabel,
  999. fieldtablelabel : tasmlabel;
  1000. {$ifdef WITHDMT}
  1001. dmtlabel : tasmlabel;
  1002. {$endif WITHDMT}
  1003. interfacetable : tasmlabel;
  1004. begin
  1005. {$ifdef WITHDMT}
  1006. dmtlabel:=gendmt;
  1007. {$endif WITHDMT}
  1008. { this generates the entries }
  1009. vmtlist:=TAasmoutput.Create;
  1010. genvmt(vmtlist);
  1011. { write tables for classes, this must be done before the actual
  1012. class is written, because we need the labels defined }
  1013. if is_class(_class) then
  1014. begin
  1015. methodnametable:=genpublishedmethodstable;
  1016. fieldtablelabel:=_class.generate_field_table;
  1017. { rtti }
  1018. if (oo_can_have_published in _class.objectoptions) then
  1019. _class.generate_rtti;
  1020. { write class name }
  1021. getdatalabel(classnamelabel);
  1022. dataSegment.concat(Tai_label.Create(classnamelabel));
  1023. dataSegment.concat(Tai_const.Create_8bit(length(_class.objname^)));
  1024. dataSegment.concat(Tai_string.Create(_class.objname^));
  1025. { generate message and dynamic tables }
  1026. if (oo_has_msgstr in _class.objectoptions) then
  1027. strmessagetable:=genstrmsgtab;
  1028. if (oo_has_msgint in _class.objectoptions) then
  1029. intmessagetable:=genintmsgtab
  1030. else
  1031. dataSegment.concat(Tai_const.Create_32bit(0));
  1032. { interface table }
  1033. if _class.implementedinterfaces.count>0 then
  1034. interfacetable:=genintftable;
  1035. end;
  1036. { write debug info }
  1037. {$ifdef GDB}
  1038. if (cs_debuginfo in aktmoduleswitches) then
  1039. begin
  1040. do_count_dbx:=true;
  1041. if assigned(_class.owner) and assigned(_class.owner.name) then
  1042. dataSegment.concat(Tai_stabs.Create(strpnew('"vmt_'+_class.owner.name^+_class.name+':S'+
  1043. typeglobalnumber('__vtbl_ptr_type')+'",'+tostr(N_STSYM)+',0,0,'+_class.vmt_mangledname)));
  1044. end;
  1045. {$endif GDB}
  1046. dataSegment.concat(Tai_symbol.Createdataname_global(_class.vmt_mangledname,0));
  1047. { determine the size with symtable.datasize, because }
  1048. { size gives back 4 for classes }
  1049. dataSegment.concat(Tai_const.Create_32bit(_class.symtable.datasize));
  1050. dataSegment.concat(Tai_const.Create_32bit(-_class.symtable.datasize));
  1051. {$ifdef WITHDMT}
  1052. if _class.classtype=ct_object then
  1053. begin
  1054. if assigned(dmtlabel) then
  1055. dataSegment.concat(Tai_const_symbol.Create(dmtlabel)))
  1056. else
  1057. dataSegment.concat(Tai_const.Create_32bit(0));
  1058. end;
  1059. {$endif WITHDMT}
  1060. { write pointer to parent VMT, this isn't implemented in TP }
  1061. { but this is not used in FPC ? (PM) }
  1062. { it's not used yet, but the delphi-operators as and is need it (FK) }
  1063. { it is not written for parents that don't have any vmt !! }
  1064. if assigned(_class.childof) and
  1065. (oo_has_vmt in _class.childof.objectoptions) then
  1066. dataSegment.concat(Tai_const_symbol.Createname(_class.childof.vmt_mangledname))
  1067. else
  1068. dataSegment.concat(Tai_const.Create_32bit(0));
  1069. { write extended info for classes, for the order see rtl/inc/objpash.inc }
  1070. if is_class(_class) then
  1071. begin
  1072. { pointer to class name string }
  1073. dataSegment.concat(Tai_const_symbol.Create(classnamelabel));
  1074. { pointer to dynamic table }
  1075. if (oo_has_msgint in _class.objectoptions) then
  1076. dataSegment.concat(Tai_const_symbol.Create(intmessagetable))
  1077. else
  1078. dataSegment.concat(Tai_const.Create_32bit(0));
  1079. { pointer to method table }
  1080. if assigned(methodnametable) then
  1081. dataSegment.concat(Tai_const_symbol.Create(methodnametable))
  1082. else
  1083. dataSegment.concat(Tai_const.Create_32bit(0));
  1084. { pointer to field table }
  1085. dataSegment.concat(Tai_const_symbol.Create(fieldtablelabel));
  1086. { pointer to type info of published section }
  1087. if (oo_can_have_published in _class.objectoptions) then
  1088. dataSegment.concat(Tai_const_symbol.Createname(_class.rtti_name))
  1089. else
  1090. dataSegment.concat(Tai_const.Create_32bit(0));
  1091. { inittable for con-/destruction }
  1092. {
  1093. if _class.needs_inittable then
  1094. }
  1095. { we generate the init table for classes always, because needs_inittable }
  1096. { for classes is always false, it applies only for objects }
  1097. dataSegment.concat(Tai_const_symbol.Create(_class.get_inittable_label));
  1098. {
  1099. else
  1100. dataSegment.concat(Tai_const.Create_32bit(0));
  1101. }
  1102. { auto table }
  1103. dataSegment.concat(Tai_const.Create_32bit(0));
  1104. { interface table }
  1105. if _class.implementedinterfaces.count>0 then
  1106. dataSegment.concat(Tai_const_symbol.Create(interfacetable))
  1107. else
  1108. dataSegment.concat(Tai_const.Create_32bit(0));
  1109. { table for string messages }
  1110. if (oo_has_msgstr in _class.objectoptions) then
  1111. dataSegment.concat(Tai_const_symbol.Create(strmessagetable))
  1112. else
  1113. dataSegment.concat(Tai_const.Create_32bit(0));
  1114. end;
  1115. dataSegment.concatlist(vmtlist);
  1116. vmtlist.free;
  1117. { write the size of the VMT }
  1118. dataSegment.concat(Tai_symbol_end.Createname(_class.vmt_mangledname));
  1119. end;
  1120. initialization
  1121. cclassheader:=tclassheader;
  1122. end.
  1123. {
  1124. $Log$
  1125. Revision 1.2 2001-08-22 21:16:20 florian
  1126. * some interfaces related problems regarding
  1127. mapping of interface implementions fixed
  1128. Revision 1.1 2001/04/21 13:37:16 peter
  1129. * made tclassheader using class of to implement cpu dependent code
  1130. Revision 1.20 2001/04/18 22:01:54 peter
  1131. * registration of targets and assemblers
  1132. Revision 1.19 2001/04/13 01:22:07 peter
  1133. * symtable change to classes
  1134. * range check generation and errors fixed, make cycle DEBUG=1 works
  1135. * memory leaks fixed
  1136. Revision 1.18 2001/04/04 21:30:43 florian
  1137. * applied several fixes to get the DD8 Delphi Unit compiled
  1138. e.g. "forward"-interfaces are working now
  1139. Revision 1.17 2000/12/25 00:07:26 peter
  1140. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1141. tlinkedlist objects)
  1142. Revision 1.16 2000/11/29 00:30:30 florian
  1143. * unused units removed from uses clause
  1144. * some changes for widestrings
  1145. Revision 1.15 2000/11/19 16:23:35 florian
  1146. *** empty log message ***
  1147. Revision 1.14 2000/11/12 23:24:10 florian
  1148. * interfaces are basically running
  1149. Revision 1.13 2000/11/08 00:07:40 florian
  1150. * potential range check error fixed
  1151. Revision 1.12 2000/11/06 23:13:53 peter
  1152. * uppercase manglednames
  1153. Revision 1.11 2000/11/04 17:31:00 florian
  1154. * fixed some problems of previous commit
  1155. Revision 1.10 2000/11/04 14:25:19 florian
  1156. + merged Attila's changes for interfaces, not tested yet
  1157. Revision 1.9 2000/11/01 23:04:37 peter
  1158. * tprocdef.fullprocname added for better casesensitve writing of
  1159. procedures
  1160. Revision 1.8 2000/10/31 22:02:47 peter
  1161. * symtable splitted, no real code changes
  1162. Revision 1.7 2000/10/14 10:14:47 peter
  1163. * moehrendorf oct 2000 rewrite
  1164. Revision 1.6 2000/09/24 21:19:50 peter
  1165. * delphi compile fixes
  1166. Revision 1.5 2000/09/24 15:06:17 peter
  1167. * use defines.inc
  1168. Revision 1.4 2000/08/27 16:11:51 peter
  1169. * moved some util functions from globals,cobjects to cutils
  1170. * splitted files into finput,fmodule
  1171. Revision 1.3 2000/07/13 12:08:26 michael
  1172. + patched to 1.1.0 with former 1.09patch from peter
  1173. Revision 1.2 2000/07/13 11:32:41 michael
  1174. + removed logs
  1175. }