hcgdata.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Routines for the code generation of data structures
  5. like VMT,Messages
  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 hcgdata;
  20. interface
  21. uses
  22. symtable,aasm;
  23. { generates the message tables for a class }
  24. function genstrmsgtab(_class : pobjectdef) : pasmlabel;
  25. function genintmsgtab(_class : pobjectdef) : pasmlabel;
  26. { generates the method name table }
  27. function genpublishedmethodstable(_class : pobjectdef) : pasmlabel;
  28. { generates a VMT for _class }
  29. procedure genvmt(list : paasmoutput;_class : pobjectdef);
  30. {$ifdef WITHDMT}
  31. { generates a DMT for _class }
  32. function gendmt(_class : pobjectdef) : pasmlabel;
  33. {$endif WITHDMT}
  34. implementation
  35. uses
  36. strings,cobjects,
  37. globtype,globals,verbose,
  38. symconst,types,
  39. hcodegen;
  40. {*****************************************************************************
  41. Message
  42. *****************************************************************************}
  43. type
  44. pprocdeftree = ^tprocdeftree;
  45. tprocdeftree = record
  46. p : pprocdef;
  47. nl : pasmlabel;
  48. l,r : pprocdeftree;
  49. end;
  50. var
  51. root : pprocdeftree;
  52. count : longint;
  53. procedure insertstr(p : pprocdeftree;var at : pprocdeftree);
  54. var
  55. i : longint;
  56. begin
  57. if at=nil then
  58. begin
  59. at:=p;
  60. inc(count);
  61. end
  62. else
  63. begin
  64. i:=strcomp(p^.p^.messageinf.str,at^.p^.messageinf.str);
  65. if i<0 then
  66. insertstr(p,at^.l)
  67. else if i>0 then
  68. insertstr(p,at^.r)
  69. else
  70. Message1(parser_e_duplicate_message_label,strpas(p^.p^.messageinf.str));
  71. end;
  72. end;
  73. procedure disposeprocdeftree(p : pprocdeftree);
  74. begin
  75. if assigned(p^.l) then
  76. disposeprocdeftree(p^.l);
  77. if assigned(p^.r) then
  78. disposeprocdeftree(p^.r);
  79. dispose(p);
  80. end;
  81. procedure insertmsgstr(p : pnamedindexobject);{$ifndef FPC}far;{$endif FPC}
  82. var
  83. hp : pprocdef;
  84. pt : pprocdeftree;
  85. begin
  86. if psym(p)^.typ=procsym then
  87. begin
  88. hp:=pprocsym(p)^.definition;
  89. while assigned(hp) do
  90. begin
  91. if (po_msgstr in hp^.procoptions) then
  92. begin
  93. new(pt);
  94. pt^.p:=hp;
  95. pt^.l:=nil;
  96. pt^.r:=nil;
  97. insertstr(pt,root);
  98. end;
  99. hp:=hp^.nextoverloaded;
  100. end;
  101. end;
  102. end;
  103. procedure insertint(p : pprocdeftree;var at : pprocdeftree);
  104. begin
  105. if at=nil then
  106. begin
  107. at:=p;
  108. inc(count);
  109. end
  110. else
  111. begin
  112. if p^.p^.messageinf.i<at^.p^.messageinf.i then
  113. insertint(p,at^.l)
  114. else if p^.p^.messageinf.i>at^.p^.messageinf.i then
  115. insertint(p,at^.r)
  116. else
  117. Message1(parser_e_duplicate_message_label,tostr(p^.p^.messageinf.i));
  118. end;
  119. end;
  120. procedure insertmsgint(p : pnamedindexobject);{$ifndef FPC}far;{$endif FPC}
  121. var
  122. hp : pprocdef;
  123. pt : pprocdeftree;
  124. begin
  125. if psym(p)^.typ=procsym then
  126. begin
  127. hp:=pprocsym(p)^.definition;
  128. while assigned(hp) do
  129. begin
  130. if (po_msgint in hp^.procoptions) then
  131. begin
  132. new(pt);
  133. pt^.p:=hp;
  134. pt^.l:=nil;
  135. pt^.r:=nil;
  136. insertint(pt,root);
  137. end;
  138. hp:=hp^.nextoverloaded;
  139. end;
  140. end;
  141. end;
  142. procedure writenames(p : pprocdeftree);
  143. begin
  144. getdatalabel(p^.nl);
  145. if assigned(p^.l) then
  146. writenames(p^.l);
  147. datasegment^.concat(new(pai_label,init(p^.nl)));
  148. datasegment^.concat(new(pai_const,init_8bit(strlen(p^.p^.messageinf.str))));
  149. datasegment^.concat(new(pai_string,init_pchar(p^.p^.messageinf.str)));
  150. if assigned(p^.r) then
  151. writenames(p^.r);
  152. end;
  153. procedure writestrentry(p : pprocdeftree);
  154. begin
  155. if assigned(p^.l) then
  156. writestrentry(p^.l);
  157. { write name label }
  158. datasegment^.concat(new(pai_const_symbol,init(p^.nl)));
  159. datasegment^.concat(new(pai_const_symbol,initname(p^.p^.mangledname)));
  160. if assigned(p^.r) then
  161. writestrentry(p^.r);
  162. end;
  163. function genstrmsgtab(_class : pobjectdef) : pasmlabel;
  164. var
  165. r : pasmlabel;
  166. begin
  167. root:=nil;
  168. count:=0;
  169. { insert all message handlers into a tree, sorted by name }
  170. _class^.symtable^.foreach({$ifndef TP}@{$endif}insertmsgstr);
  171. { write all names }
  172. if assigned(root) then
  173. writenames(root);
  174. { now start writing of the message string table }
  175. getdatalabel(r);
  176. datasegment^.concat(new(pai_label,init(r)));
  177. genstrmsgtab:=r;
  178. datasegment^.concat(new(pai_const,init_32bit(count)));
  179. if assigned(root) then
  180. begin
  181. writestrentry(root);
  182. disposeprocdeftree(root);
  183. end;
  184. end;
  185. procedure writeintentry(p : pprocdeftree);
  186. begin
  187. if assigned(p^.l) then
  188. writeintentry(p^.l);
  189. { write name label }
  190. datasegment^.concat(new(pai_const,init_32bit(p^.p^.messageinf.i)));
  191. datasegment^.concat(new(pai_const_symbol,initname(p^.p^.mangledname)));
  192. if assigned(p^.r) then
  193. writeintentry(p^.r);
  194. end;
  195. function genintmsgtab(_class : pobjectdef) : pasmlabel;
  196. var
  197. r : pasmlabel;
  198. begin
  199. root:=nil;
  200. count:=0;
  201. { insert all message handlers into a tree, sorted by name }
  202. _class^.symtable^.foreach({$ifndef TP}@{$endif}insertmsgint);
  203. { now start writing of the message string table }
  204. getdatalabel(r);
  205. datasegment^.concat(new(pai_label,init(r)));
  206. genintmsgtab:=r;
  207. datasegment^.concat(new(pai_const,init_32bit(count)));
  208. if assigned(root) then
  209. begin
  210. writeintentry(root);
  211. disposeprocdeftree(root);
  212. end;
  213. end;
  214. {$ifdef WITHDMT}
  215. procedure insertdmtentry(p : pnamedindexobject);{$ifndef FPC}far;{$endif FPC}
  216. var
  217. hp : pprocdef;
  218. pt : pprocdeftree;
  219. begin
  220. if psym(p)^.typ=procsym then
  221. begin
  222. hp:=pprocsym(p)^.definition;
  223. while assigned(hp) do
  224. begin
  225. if (po_msgint in hp^.procoptions) then
  226. begin
  227. new(pt);
  228. pt^.p:=hp;
  229. pt^.l:=nil;
  230. pt^.r:=nil;
  231. insertint(pt,root);
  232. end;
  233. hp:=hp^.nextoverloaded;
  234. end;
  235. end;
  236. end;
  237. procedure writedmtindexentry(p : pprocdeftree);
  238. begin
  239. if assigned(p^.l) then
  240. writedmtindexentry(p^.l);
  241. datasegment^.concat(new(pai_const,init_32bit(p^.p^.messageinf.i)));
  242. if assigned(p^.r) then
  243. writedmtindexentry(p^.r);
  244. end;
  245. procedure writedmtaddressentry(p : pprocdeftree);
  246. begin
  247. if assigned(p^.l) then
  248. writedmtaddressentry(p^.l);
  249. datasegment^.concat(new(pai_const_symbol,initname(p^.p^.mangledname)));
  250. if assigned(p^.r) then
  251. writedmtaddressentry(p^.r);
  252. end;
  253. function gendmt(_class : pobjectdef) : pasmlabel;
  254. var
  255. r : pasmlabel;
  256. begin
  257. root:=nil;
  258. count:=0;
  259. gendmt:=nil;
  260. { insert all message handlers into a tree, sorted by number }
  261. _class^.symtable^.foreach({$ifndef TP}@{$endif}insertdmtentry);
  262. if count>0 then
  263. begin
  264. getdatalabel(r);
  265. gendmt:=r;
  266. datasegment^.concat(new(pai_label,init(r)));
  267. { entries for caching }
  268. datasegment^.concat(new(pai_const,init_32bit(0)));
  269. datasegment^.concat(new(pai_const,init_32bit(0)));
  270. datasegment^.concat(new(pai_const,init_32bit(count)));
  271. if assigned(root) then
  272. begin
  273. writedmtindexentry(root);
  274. writedmtaddressentry(root);
  275. disposeprocdeftree(root);
  276. end;
  277. end;
  278. end;
  279. {$endif WITHDMT}
  280. procedure do_count(p : pnamedindexobject);{$ifndef FPC}far;{$endif FPC}
  281. begin
  282. if (psym(p)^.typ=procsym) and (sp_published in psym(p)^.symoptions) then
  283. inc(count);
  284. end;
  285. procedure genpubmethodtableentry(p : pnamedindexobject);{$ifndef FPC}far;{$endif FPC}
  286. var
  287. hp : pprocdef;
  288. l : pasmlabel;
  289. begin
  290. if (psym(p)^.typ=procsym) and (sp_published in psym(p)^.symoptions) then
  291. begin
  292. hp:=pprocsym(p)^.definition;
  293. if assigned(hp^.nextoverloaded) then
  294. internalerror(1209992);
  295. getdatalabel(l);
  296. consts^.concat(new(pai_label,init(l)));
  297. consts^.concat(new(pai_const,init_8bit(length(p^.name))));
  298. consts^.concat(new(pai_string,init(p^.name)));
  299. datasegment^.concat(new(pai_const_symbol,init(l)));
  300. datasegment^.concat(new(pai_const_symbol,initname(hp^.mangledname)));
  301. end;
  302. end;
  303. function genpublishedmethodstable(_class : pobjectdef) : pasmlabel;
  304. var
  305. l : pasmlabel;
  306. begin
  307. count:=0;
  308. _class^.symtable^.foreach({$ifndef TP}@{$endif}do_count);
  309. if count>0 then
  310. begin
  311. getdatalabel(l);
  312. datasegment^.concat(new(pai_label,init(l)));
  313. datasegment^.concat(new(pai_const,init_32bit(count)));
  314. _class^.symtable^.foreach({$ifndef TP}@{$endif}genpubmethodtableentry);
  315. genpublishedmethodstable:=l;
  316. end
  317. else
  318. genpublishedmethodstable:=nil;
  319. end;
  320. {*****************************************************************************
  321. VMT
  322. *****************************************************************************}
  323. type
  324. pprocdefcoll = ^tprocdefcoll;
  325. tprocdefcoll = record
  326. next : pprocdefcoll;
  327. data : pprocdef;
  328. end;
  329. psymcoll = ^tsymcoll;
  330. tsymcoll = record
  331. next : psymcoll;
  332. name : pstring;
  333. data : pprocdefcoll;
  334. end;
  335. var
  336. wurzel : psymcoll;
  337. nextvirtnumber : longint;
  338. _c : pobjectdef;
  339. has_constructor,has_virtual_method : boolean;
  340. procedure eachsym(sym : pnamedindexobject);{$ifndef FPC}far;{$endif FPC}
  341. var
  342. procdefcoll : pprocdefcoll;
  343. hp : pprocdef;
  344. symcoll : psymcoll;
  345. _name : string;
  346. stored : boolean;
  347. { creates a new entry in the procsym list }
  348. procedure newentry;
  349. begin
  350. { if not, generate a new symbol item }
  351. new(symcoll);
  352. symcoll^.name:=stringdup(sym^.name);
  353. symcoll^.next:=wurzel;
  354. symcoll^.data:=nil;
  355. wurzel:=symcoll;
  356. hp:=pprocsym(sym)^.definition;
  357. { inserts all definitions }
  358. while assigned(hp) do
  359. begin
  360. new(procdefcoll);
  361. procdefcoll^.data:=hp;
  362. procdefcoll^.next:=symcoll^.data;
  363. symcoll^.data:=procdefcoll;
  364. { if it's a virtual method }
  365. if (po_virtualmethod in hp^.procoptions) then
  366. begin
  367. { then it gets a number ... }
  368. hp^.extnumber:=nextvirtnumber;
  369. { and we inc the number }
  370. inc(nextvirtnumber);
  371. has_virtual_method:=true;
  372. end;
  373. if (hp^.proctypeoption=potype_constructor) then
  374. has_constructor:=true;
  375. { check, if a method should be overridden }
  376. if (po_overridingmethod in hp^.procoptions) then
  377. MessagePos1(hp^.fileinfo,parser_e_nothing_to_be_overridden,_c^.objname^+'.'+_name+hp^.demangled_paras);
  378. { next overloaded method }
  379. hp:=hp^.nextoverloaded;
  380. end;
  381. end;
  382. procedure newdefentry;
  383. begin
  384. new(procdefcoll);
  385. procdefcoll^.data:=hp;
  386. procdefcoll^.next:=symcoll^.data;
  387. symcoll^.data:=procdefcoll;
  388. { if it's a virtual method }
  389. if (po_virtualmethod in hp^.procoptions) then
  390. begin
  391. { then it gets a number ... }
  392. hp^.extnumber:=nextvirtnumber;
  393. { and we inc the number }
  394. inc(nextvirtnumber);
  395. has_virtual_method:=true;
  396. end;
  397. if (hp^.proctypeoption=potype_constructor) then
  398. has_constructor:=true;
  399. { check, if a method should be overridden }
  400. if (po_overridingmethod in hp^.procoptions) then
  401. MessagePos1(hp^.fileinfo,parser_e_nothing_to_be_overridden,_c^.objname^+'.'+_name+hp^.demangled_paras);
  402. end;
  403. label
  404. handlenextdef;
  405. begin
  406. { put only sub routines into the VMT }
  407. if psym(sym)^.typ=procsym then
  408. begin
  409. _name:=sym^.name;
  410. symcoll:=wurzel;
  411. while assigned(symcoll) do
  412. begin
  413. { does the symbol already exist in the list ? }
  414. if _name=symcoll^.name^ then
  415. begin
  416. { walk through all defs of the symbol }
  417. hp:=pprocsym(sym)^.definition;
  418. while assigned(hp) do
  419. begin
  420. { compare with all stored definitions }
  421. procdefcoll:=symcoll^.data;
  422. stored:=false;
  423. while assigned(procdefcoll) do
  424. begin
  425. { compare parameters }
  426. if equal_paras(procdefcoll^.data^.para,hp^.para,cp_all) and
  427. (
  428. (po_virtualmethod in procdefcoll^.data^.procoptions) or
  429. (po_virtualmethod in hp^.procoptions)
  430. ) then
  431. begin { same parameters }
  432. { wenn sie gleich sind }
  433. { und eine davon virtual deklariert ist }
  434. { Fehler falls nur eine VIRTUAL }
  435. if (po_virtualmethod in procdefcoll^.data^.procoptions)<>
  436. (po_virtualmethod in hp^.procoptions) then
  437. begin
  438. { in classes, we hide the old method }
  439. if _c^.is_class then
  440. begin
  441. { warn only if it is the first time,
  442. we hide the method }
  443. if _c=hp^._class then
  444. Message1(parser_w_should_use_override,_c^.objname^+'.'+_name);
  445. end
  446. else
  447. if _c=hp^._class then
  448. begin
  449. if (po_virtualmethod in procdefcoll^.data^.procoptions) then
  450. Message1(parser_w_overloaded_are_not_both_virtual,_c^.objname^+'.'+_name)
  451. else
  452. Message1(parser_w_overloaded_are_not_both_non_virtual,
  453. _c^.objname^+'.'+_name);
  454. end;
  455. { was newentry; exit; (FK) }
  456. newdefentry;
  457. goto handlenextdef;
  458. end
  459. else
  460. { the flags have to match }
  461. { except abstract and override }
  462. { only if both are virtual !! }
  463. if (procdefcoll^.data^.proccalloptions<>hp^.proccalloptions) or
  464. (procdefcoll^.data^.proctypeoption<>hp^.proctypeoption) or
  465. ((procdefcoll^.data^.procoptions-
  466. [po_abstractmethod,po_overridingmethod,po_assembler])<>
  467. (hp^.procoptions-[po_abstractmethod,po_overridingmethod,po_assembler])) then
  468. Message1(parser_e_header_dont_match_forward,_c^.objname^+'.'+_name);
  469. { check, if the overridden directive is set }
  470. { (povirtualmethod is set! }
  471. { class ? }
  472. if _c^.is_class and
  473. not(po_overridingmethod in hp^.procoptions) then
  474. begin
  475. { warn only if it is the first time,
  476. we hide the method }
  477. if _c=hp^._class then
  478. Message1(parser_w_should_use_override,_c^.objname^+'.'+_name);
  479. { was newentry; (FK) }
  480. newdefentry;
  481. exit;
  482. end;
  483. { error, if the return types aren't equal }
  484. if not(is_equal(procdefcoll^.data^.rettype.def,hp^.rettype.def)) and
  485. not((procdefcoll^.data^.rettype.def^.deftype=objectdef) and
  486. (hp^.rettype.def^.deftype=objectdef) and
  487. (pobjectdef(procdefcoll^.data^.rettype.def)^.is_class) and
  488. (pobjectdef(hp^.rettype.def)^.is_class) and
  489. (pobjectdef(hp^.rettype.def)^.is_related(
  490. pobjectdef(procdefcoll^.data^.rettype.def)))) then
  491. Message1(parser_e_overloaded_methodes_not_same_ret,_c^.objname^+'.'+_name);
  492. { now set the number }
  493. hp^.extnumber:=procdefcoll^.data^.extnumber;
  494. { and exchange }
  495. procdefcoll^.data:=hp;
  496. stored:=true;
  497. goto handlenextdef;
  498. end; { same parameters }
  499. procdefcoll:=procdefcoll^.next;
  500. end;
  501. { if it isn't saved in the list }
  502. { we create a new entry }
  503. if not(stored) then
  504. begin
  505. new(procdefcoll);
  506. procdefcoll^.data:=hp;
  507. procdefcoll^.next:=symcoll^.data;
  508. symcoll^.data:=procdefcoll;
  509. { if the method is virtual ... }
  510. if (po_virtualmethod in hp^.procoptions) then
  511. begin
  512. { ... it will get a number }
  513. hp^.extnumber:=nextvirtnumber;
  514. inc(nextvirtnumber);
  515. end;
  516. { check, if a method should be overridden }
  517. if (po_overridingmethod in hp^.procoptions) then
  518. MessagePos1(hp^.fileinfo,parser_e_nothing_to_be_overridden,
  519. _c^.objname^+'.'+_name+hp^.demangled_paras);
  520. end;
  521. handlenextdef:
  522. hp:=hp^.nextoverloaded;
  523. end;
  524. exit;
  525. end;
  526. symcoll:=symcoll^.next;
  527. end;
  528. newentry;
  529. end;
  530. end;
  531. procedure genvmt(list : paasmoutput;_class : pobjectdef);
  532. procedure do_genvmt(p : pobjectdef);
  533. begin
  534. { start with the base class }
  535. if assigned(p^.childof) then
  536. do_genvmt(p^.childof);
  537. { walk through all public syms }
  538. { I had to change that to solve bug0260 (PM)}
  539. { _c:=p; }
  540. _c:=_class;
  541. { Florian, please check if you agree (PM) }
  542. { no it wasn't correct, but I fixed it at }
  543. { another place: your fix hides only a bug }
  544. { _c is only used to give correct warnings }
  545. p^.symtable^.foreach({$ifndef TP}@{$endif}eachsym);
  546. end;
  547. var
  548. symcoll : psymcoll;
  549. procdefcoll : pprocdefcoll;
  550. i : longint;
  551. begin
  552. wurzel:=nil;
  553. nextvirtnumber:=0;
  554. has_constructor:=false;
  555. has_virtual_method:=false;
  556. { generates a tree of all used methods }
  557. do_genvmt(_class);
  558. if has_virtual_method and not(has_constructor) then
  559. Message1(parser_w_virtual_without_constructor,_class^.objname^);
  560. { generates the VMT }
  561. { walk trough all numbers for virtual methods and search }
  562. { the method }
  563. for i:=0 to nextvirtnumber-1 do
  564. begin
  565. symcoll:=wurzel;
  566. { walk trough all symbols }
  567. while assigned(symcoll) do
  568. begin
  569. { walk trough all methods }
  570. procdefcoll:=symcoll^.data;
  571. while assigned(procdefcoll) do
  572. begin
  573. { writes the addresses to the VMT }
  574. { but only this which are declared as virtual }
  575. if procdefcoll^.data^.extnumber=i then
  576. begin
  577. if (po_virtualmethod in procdefcoll^.data^.procoptions) then
  578. begin
  579. { if a method is abstract, then is also the }
  580. { class abstract and it's not allow to }
  581. { generates an instance }
  582. if (po_abstractmethod in procdefcoll^.data^.procoptions) then
  583. begin
  584. include(_class^.objectoptions,oo_has_abstract);
  585. list^.concat(new(pai_const_symbol,initname('FPC_ABSTRACTERROR')));
  586. end
  587. else
  588. begin
  589. list^.concat(new(pai_const_symbol,
  590. initname(procdefcoll^.data^.mangledname)));
  591. end;
  592. end;
  593. end;
  594. procdefcoll:=procdefcoll^.next;
  595. end;
  596. symcoll:=symcoll^.next;
  597. end;
  598. end;
  599. { disposes the above generated tree }
  600. symcoll:=wurzel;
  601. while assigned(symcoll) do
  602. begin
  603. wurzel:=symcoll^.next;
  604. stringdispose(symcoll^.name);
  605. procdefcoll:=symcoll^.data;
  606. while assigned(procdefcoll) do
  607. begin
  608. symcoll^.data:=procdefcoll^.next;
  609. dispose(procdefcoll);
  610. procdefcoll:=symcoll^.data;
  611. end;
  612. dispose(symcoll);
  613. symcoll:=wurzel;
  614. end;
  615. end;
  616. end.
  617. {
  618. $Log$
  619. Revision 1.2 2000-07-13 11:32:41 michael
  620. + removed logs
  621. }