nobj.pas 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342
  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])<>
  538. (hp.procoptions-[po_abstractmethod,po_overridingmethod,po_assembler])) 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) and not (sp_private in sym.symoptions) 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:=mappedname; { for error messages }
  920. if mappedname<>'' then
  921. implprocdef:=gintfgetcprocdef(proc,mappedname);
  922. until assigned(implprocdef) or not assigned(nextexist);
  923. if not assigned(implprocdef) then
  924. implprocdef:=gintfgetcprocdef(proc,proc.procsym.name);
  925. if procname='' then
  926. procname:=proc.procsym.name;
  927. if assigned(implprocdef) then
  928. _class.implementedinterfaces.addimplproc(intfindex,implprocdef)
  929. else
  930. Message1(sym_e_id_not_found,procname);
  931. end;
  932. end;
  933. end;
  934. procedure tclassheader.gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
  935. begin
  936. if assigned(intf.childof) then
  937. gintfwalkdowninterface(intf.childof,intfindex);
  938. gintfdoonintf(intf,intfindex);
  939. end;
  940. function tclassheader.genintftable: tasmlabel;
  941. var
  942. intfindex: longint;
  943. curintf: tobjectdef;
  944. intftable: tasmlabel;
  945. begin
  946. { 1. step collect implementor functions into the implementedinterfaces.implprocs }
  947. for intfindex:=1 to _class.implementedinterfaces.count do
  948. begin
  949. curintf:=_class.implementedinterfaces.interfaces(intfindex);
  950. gintfwalkdowninterface(curintf,intfindex);
  951. end;
  952. { 2. step calc required fieldcount and their offsets in the object memory map
  953. and write data }
  954. getdatalabel(intftable);
  955. dataSegment.concat(Tai_label.Create(intftable));
  956. gintfwritedata;
  957. _class.implementedinterfaces.clearimplprocs; { release temporary information }
  958. genintftable:=intftable;
  959. end;
  960. { Write interface identifiers to the data section }
  961. procedure tclassheader.writeinterfaceids;
  962. var
  963. i: longint;
  964. s1,s2 : string;
  965. begin
  966. if _class.owner.name=nil then
  967. s1:=''
  968. else
  969. s1:=upper(_class.owner.name^);
  970. if _class.objname=nil then
  971. s2:=''
  972. else
  973. s2:=upper(_class.objname^);
  974. s1:=s1+'$_'+s2;
  975. if _class.isiidguidvalid then
  976. begin
  977. if (cs_create_smart in aktmoduleswitches) then
  978. dataSegment.concat(Tai_cut.Create);
  979. dataSegment.concat(Tai_symbol.Createname_global('IID$_'+s1,0));
  980. dataSegment.concat(Tai_const.Create_32bit(longint(_class.iidguid.D1)));
  981. dataSegment.concat(Tai_const.Create_16bit(_class.iidguid.D2));
  982. dataSegment.concat(Tai_const.Create_16bit(_class.iidguid.D3));
  983. for i:=Low(_class.iidguid.D4) to High(_class.iidguid.D4) do
  984. dataSegment.concat(Tai_const.Create_8bit(_class.iidguid.D4[i]));
  985. end;
  986. if (cs_create_smart in aktmoduleswitches) then
  987. dataSegment.concat(Tai_cut.Create);
  988. dataSegment.concat(Tai_symbol.Createname_global('IIDSTR$_'+s1,0));
  989. dataSegment.concat(Tai_const.Create_8bit(length(_class.iidstr^)));
  990. dataSegment.concat(Tai_string.Create(_class.iidstr^));
  991. end;
  992. { generates the vmt for classes as well as for objects }
  993. procedure tclassheader.writevmt;
  994. var
  995. vmtlist : taasmoutput;
  996. methodnametable,intmessagetable,
  997. strmessagetable,classnamelabel,
  998. fieldtablelabel : tasmlabel;
  999. {$ifdef WITHDMT}
  1000. dmtlabel : tasmlabel;
  1001. {$endif WITHDMT}
  1002. interfacetable : tasmlabel;
  1003. begin
  1004. {$ifdef WITHDMT}
  1005. dmtlabel:=gendmt;
  1006. {$endif WITHDMT}
  1007. { this generates the entries }
  1008. vmtlist:=TAasmoutput.Create;
  1009. genvmt(vmtlist);
  1010. { write tables for classes, this must be done before the actual
  1011. class is written, because we need the labels defined }
  1012. if is_class(_class) then
  1013. begin
  1014. methodnametable:=genpublishedmethodstable;
  1015. fieldtablelabel:=_class.generate_field_table;
  1016. { rtti }
  1017. if (oo_can_have_published in _class.objectoptions) then
  1018. _class.generate_rtti;
  1019. { write class name }
  1020. getdatalabel(classnamelabel);
  1021. dataSegment.concat(Tai_label.Create(classnamelabel));
  1022. dataSegment.concat(Tai_const.Create_8bit(length(_class.objname^)));
  1023. dataSegment.concat(Tai_string.Create(_class.objname^));
  1024. { generate message and dynamic tables }
  1025. if (oo_has_msgstr in _class.objectoptions) then
  1026. strmessagetable:=genstrmsgtab;
  1027. if (oo_has_msgint in _class.objectoptions) then
  1028. intmessagetable:=genintmsgtab
  1029. else
  1030. dataSegment.concat(Tai_const.Create_32bit(0));
  1031. { interface table }
  1032. if _class.implementedinterfaces.count>0 then
  1033. interfacetable:=genintftable;
  1034. end;
  1035. { write debug info }
  1036. {$ifdef GDB}
  1037. if (cs_debuginfo in aktmoduleswitches) then
  1038. begin
  1039. do_count_dbx:=true;
  1040. if assigned(_class.owner) and assigned(_class.owner.name) then
  1041. dataSegment.concat(Tai_stabs.Create(strpnew('"vmt_'+_class.owner.name^+_class.name+':S'+
  1042. typeglobalnumber('__vtbl_ptr_type')+'",'+tostr(N_STSYM)+',0,0,'+_class.vmt_mangledname)));
  1043. end;
  1044. {$endif GDB}
  1045. dataSegment.concat(Tai_symbol.Createdataname_global(_class.vmt_mangledname,0));
  1046. { determine the size with symtable.datasize, because }
  1047. { size gives back 4 for classes }
  1048. dataSegment.concat(Tai_const.Create_32bit(_class.symtable.datasize));
  1049. dataSegment.concat(Tai_const.Create_32bit(-_class.symtable.datasize));
  1050. {$ifdef WITHDMT}
  1051. if _class.classtype=ct_object then
  1052. begin
  1053. if assigned(dmtlabel) then
  1054. dataSegment.concat(Tai_const_symbol.Create(dmtlabel)))
  1055. else
  1056. dataSegment.concat(Tai_const.Create_32bit(0));
  1057. end;
  1058. {$endif WITHDMT}
  1059. { write pointer to parent VMT, this isn't implemented in TP }
  1060. { but this is not used in FPC ? (PM) }
  1061. { it's not used yet, but the delphi-operators as and is need it (FK) }
  1062. { it is not written for parents that don't have any vmt !! }
  1063. if assigned(_class.childof) and
  1064. (oo_has_vmt in _class.childof.objectoptions) then
  1065. dataSegment.concat(Tai_const_symbol.Createname(_class.childof.vmt_mangledname))
  1066. else
  1067. dataSegment.concat(Tai_const.Create_32bit(0));
  1068. { write extended info for classes, for the order see rtl/inc/objpash.inc }
  1069. if is_class(_class) then
  1070. begin
  1071. { pointer to class name string }
  1072. dataSegment.concat(Tai_const_symbol.Create(classnamelabel));
  1073. { pointer to dynamic table }
  1074. if (oo_has_msgint in _class.objectoptions) then
  1075. dataSegment.concat(Tai_const_symbol.Create(intmessagetable))
  1076. else
  1077. dataSegment.concat(Tai_const.Create_32bit(0));
  1078. { pointer to method table }
  1079. if assigned(methodnametable) then
  1080. dataSegment.concat(Tai_const_symbol.Create(methodnametable))
  1081. else
  1082. dataSegment.concat(Tai_const.Create_32bit(0));
  1083. { pointer to field table }
  1084. dataSegment.concat(Tai_const_symbol.Create(fieldtablelabel));
  1085. { pointer to type info of published section }
  1086. if (oo_can_have_published in _class.objectoptions) then
  1087. dataSegment.concat(Tai_const_symbol.Createname(_class.rtti_name))
  1088. else
  1089. dataSegment.concat(Tai_const.Create_32bit(0));
  1090. { inittable for con-/destruction }
  1091. {
  1092. if _class.needs_inittable then
  1093. }
  1094. { we generate the init table for classes always, because needs_inittable }
  1095. { for classes is always false, it applies only for objects }
  1096. dataSegment.concat(Tai_const_symbol.Create(_class.get_inittable_label));
  1097. {
  1098. else
  1099. dataSegment.concat(Tai_const.Create_32bit(0));
  1100. }
  1101. { auto table }
  1102. dataSegment.concat(Tai_const.Create_32bit(0));
  1103. { interface table }
  1104. if _class.implementedinterfaces.count>0 then
  1105. dataSegment.concat(Tai_const_symbol.Create(interfacetable))
  1106. else
  1107. dataSegment.concat(Tai_const.Create_32bit(0));
  1108. { table for string messages }
  1109. if (oo_has_msgstr in _class.objectoptions) then
  1110. dataSegment.concat(Tai_const_symbol.Create(strmessagetable))
  1111. else
  1112. dataSegment.concat(Tai_const.Create_32bit(0));
  1113. end;
  1114. dataSegment.concatlist(vmtlist);
  1115. vmtlist.free;
  1116. { write the size of the VMT }
  1117. dataSegment.concat(Tai_symbol_end.Createname(_class.vmt_mangledname));
  1118. end;
  1119. initialization
  1120. cclassheader:=tclassheader;
  1121. end.
  1122. {
  1123. $Log$
  1124. Revision 1.1 2001-04-21 13:37:16 peter
  1125. * made tclassheader using class of to implement cpu dependent code
  1126. Revision 1.20 2001/04/18 22:01:54 peter
  1127. * registration of targets and assemblers
  1128. Revision 1.19 2001/04/13 01:22:07 peter
  1129. * symtable change to classes
  1130. * range check generation and errors fixed, make cycle DEBUG=1 works
  1131. * memory leaks fixed
  1132. Revision 1.18 2001/04/04 21:30:43 florian
  1133. * applied several fixes to get the DD8 Delphi Unit compiled
  1134. e.g. "forward"-interfaces are working now
  1135. Revision 1.17 2000/12/25 00:07:26 peter
  1136. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1137. tlinkedlist objects)
  1138. Revision 1.16 2000/11/29 00:30:30 florian
  1139. * unused units removed from uses clause
  1140. * some changes for widestrings
  1141. Revision 1.15 2000/11/19 16:23:35 florian
  1142. *** empty log message ***
  1143. Revision 1.14 2000/11/12 23:24:10 florian
  1144. * interfaces are basically running
  1145. Revision 1.13 2000/11/08 00:07:40 florian
  1146. * potential range check error fixed
  1147. Revision 1.12 2000/11/06 23:13:53 peter
  1148. * uppercase manglednames
  1149. Revision 1.11 2000/11/04 17:31:00 florian
  1150. * fixed some problems of previous commit
  1151. Revision 1.10 2000/11/04 14:25:19 florian
  1152. + merged Attila's changes for interfaces, not tested yet
  1153. Revision 1.9 2000/11/01 23:04:37 peter
  1154. * tprocdef.fullprocname added for better casesensitve writing of
  1155. procedures
  1156. Revision 1.8 2000/10/31 22:02:47 peter
  1157. * symtable splitted, no real code changes
  1158. Revision 1.7 2000/10/14 10:14:47 peter
  1159. * moehrendorf oct 2000 rewrite
  1160. Revision 1.6 2000/09/24 21:19:50 peter
  1161. * delphi compile fixes
  1162. Revision 1.5 2000/09/24 15:06:17 peter
  1163. * use defines.inc
  1164. Revision 1.4 2000/08/27 16:11:51 peter
  1165. * moved some util functions from globals,cobjects to cutils
  1166. * splitted files into finput,fmodule
  1167. Revision 1.3 2000/07/13 12:08:26 michael
  1168. + patched to 1.1.0 with former 1.09patch from peter
  1169. Revision 1.2 2000/07/13 11:32:41 michael
  1170. + removed logs
  1171. }