pdecvar.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Parses variable declarations. Used for var statement and record
  5. definitions
  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 pdecvar;
  20. {$i defines.inc}
  21. interface
  22. procedure read_var_decs(is_record,is_object,is_threadvar:boolean);
  23. implementation
  24. uses
  25. { common }
  26. cutils,
  27. { global }
  28. globtype,globals,tokens,verbose,
  29. systems,
  30. { symtable }
  31. symconst,symbase,symtype,symdef,symsym,symtable,types,fmodule,
  32. { pass 1 }
  33. node,
  34. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
  35. { parser }
  36. scanner,
  37. pbase,pexpr,ptype,ptconst,pdecsub,
  38. { link }
  39. import;
  40. const
  41. variantrecordlevel : longint = 0;
  42. procedure read_var_decs(is_record,is_object,is_threadvar:boolean);
  43. { reads the filed of a record into a }
  44. { symtablestack, if record=false }
  45. { variants are forbidden, so this procedure }
  46. { can be used to read object fields }
  47. { if absolute is true, ABSOLUTE and file }
  48. { types are allowed }
  49. { => the procedure is also used to read }
  50. { a sequence of variable declaration }
  51. procedure insert_syms(st : tsymtable;sc : tidstringlist;tt : ttype;is_threadvar : boolean);
  52. { inserts the symbols of sc in st with def as definition or sym as ttypesym, sc is disposed }
  53. var
  54. s : string;
  55. filepos : tfileposinfo;
  56. ss : tvarsym;
  57. begin
  58. filepos:=akttokenpos;
  59. while not sc.empty do
  60. begin
  61. s:=sc.get(akttokenpos);
  62. ss:=tvarsym.Create(s,tt);
  63. if is_threadvar then
  64. include(ss.varoptions,vo_is_thread_var);
  65. st.insert(ss);
  66. { static data fields are inserted in the globalsymtable }
  67. if (st.symtabletype=objectsymtable) and
  68. (sp_static in current_object_option) then
  69. begin
  70. s:='$'+lower(st.name^)+'_'+upper(s);
  71. st.defowner.owner.insert(tvarsym.create(s,tt));
  72. end;
  73. end;
  74. {$ifdef fixLeaksOnError}
  75. if strContStack.pop <> sc then
  76. writeln('problem with strContStack in pdecl (2)');
  77. {$endif fixLeaksOnError}
  78. sc.free;
  79. akttokenpos:=filepos;
  80. end;
  81. var
  82. sc : tidstringList;
  83. s : stringid;
  84. old_block_type : tblock_type;
  85. declarepos,storetokenpos : tfileposinfo;
  86. oldsymtablestack : tsymtable;
  87. symdone : boolean;
  88. { to handle absolute }
  89. abssym : tabsolutesym;
  90. { c var }
  91. newtype : ttypesym;
  92. is_dll,
  93. is_gpc_name,is_cdecl,
  94. extern_aktvarsym,export_aktvarsym : boolean;
  95. old_current_object_option : tsymoptions;
  96. dll_name,
  97. C_name : string;
  98. tt,casetype : ttype;
  99. { Delphi initialized vars }
  100. tconstsym : ttypedconstsym;
  101. { maxsize contains the max. size of a variant }
  102. { startvarrec contains the start of the variant part of a record }
  103. usedalign,
  104. maxsize,minalignment,maxalignment,startvarrecalign,startvarrecsize : longint;
  105. pt : tnode;
  106. srsym : tsym;
  107. srsymtable : tsymtable;
  108. unionsymtable : tsymtable;
  109. offset : longint;
  110. uniondef : trecorddef;
  111. unionsym : tvarsym;
  112. uniontype : ttype;
  113. dummysymoptions : tsymoptions;
  114. begin
  115. old_current_object_option:=current_object_option;
  116. { all variables are public if not in a object declaration }
  117. if not is_object then
  118. current_object_option:=[sp_public];
  119. old_block_type:=block_type;
  120. block_type:=bt_type;
  121. is_gpc_name:=false;
  122. { Force an expected ID error message }
  123. if not (token in [_ID,_CASE,_END]) then
  124. consume(_ID);
  125. { read vars }
  126. while (token=_ID) and
  127. not(is_object and (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED])) do
  128. begin
  129. C_name:=orgpattern;
  130. sc:=consume_idlist;
  131. {$ifdef fixLeaksOnError}
  132. strContStack.push(sc);
  133. {$endif fixLeaksOnError}
  134. consume(_COLON);
  135. if (m_gpc in aktmodeswitches) and
  136. not(is_record or is_object or is_threadvar) and
  137. (token=_ID) and (orgpattern='__asmname__') then
  138. begin
  139. consume(_ID);
  140. C_name:=get_stringconst;
  141. Is_gpc_name:=true;
  142. end;
  143. { this is needed for Delphi mode at least
  144. but should be OK for all modes !! (PM) }
  145. ignore_equal:=true;
  146. if is_record then
  147. begin
  148. { for records, don't search the recordsymtable for
  149. the symbols of the types }
  150. oldsymtablestack:=symtablestack;
  151. symtablestack:=symtablestack.next;
  152. read_type(tt,'');
  153. symtablestack:=oldsymtablestack;
  154. end
  155. else
  156. read_type(tt,'');
  157. { types that use init/final are not allowed in variant parts, but
  158. classes are allowed }
  159. if (variantrecordlevel>0) and
  160. (tt.def.needs_inittable and not is_class(tt.def)) then
  161. Message(parser_e_cant_use_inittable_here);
  162. ignore_equal:=false;
  163. symdone:=false;
  164. if is_gpc_name then
  165. begin
  166. storetokenpos:=akttokenpos;
  167. s:=sc.get(akttokenpos);
  168. if not sc.empty then
  169. Message(parser_e_absolute_only_one_var);
  170. {$ifdef fixLeaksOnError}
  171. if strContStack.pop <> sc then
  172. writeln('problem with strContStack in pdecl (3)');
  173. {$endif fixLeaksOnError}
  174. sc.free;
  175. aktvarsym:=tvarsym.create_C(s,target_info.Cprefix+C_name,tt);
  176. include(aktvarsym.varoptions,vo_is_external);
  177. symtablestack.insert(aktvarsym);
  178. akttokenpos:=storetokenpos;
  179. symdone:=true;
  180. end;
  181. { check for absolute }
  182. if not symdone and
  183. (idtoken=_ABSOLUTE) and not(is_record or is_object or is_threadvar) then
  184. begin
  185. consume(_ABSOLUTE);
  186. { only allowed for one var }
  187. s:=sc.get(declarepos);
  188. if not sc.empty then
  189. Message(parser_e_absolute_only_one_var);
  190. {$ifdef fixLeaksOnError}
  191. if strContStack.pop <> sc then
  192. writeln('problem with strContStack in pdecl (4)');
  193. {$endif fixLeaksOnError}
  194. sc.free;
  195. { parse the rest }
  196. pt:=expr;
  197. if (pt.nodetype=stringconstn) or (is_constcharnode(pt)) then
  198. begin
  199. storetokenpos:=akttokenpos;
  200. akttokenpos:=declarepos;
  201. abssym:=tabsolutesym.create(s,tt);
  202. if pt.nodetype=stringconstn then
  203. s:=strpas(tstringconstnode(pt).value_str)
  204. else
  205. s:=chr(tordconstnode(pt).value);
  206. consume(token);
  207. abssym.abstyp:=toasm;
  208. abssym.asmname:=stringdup(s);
  209. symtablestack.insert(abssym);
  210. akttokenpos:=storetokenpos;
  211. symdone:=true;
  212. end;
  213. if not symdone then
  214. begin
  215. { variable }
  216. if (pt.nodetype=loadn) then
  217. begin
  218. { we should check the result type of srsym }
  219. if not (tloadnode(pt).symtableentry.typ in [varsym,typedconstsym,funcretsym]) then
  220. Message(parser_e_absolute_only_to_var_or_const);
  221. storetokenpos:=akttokenpos;
  222. akttokenpos:=declarepos;
  223. abssym:=tabsolutesym.create(s,tt);
  224. abssym.abstyp:=tovar;
  225. abssym.ref:=tstoredsym(tloadnode(pt).symtableentry);
  226. symtablestack.insert(abssym);
  227. akttokenpos:=storetokenpos;
  228. symdone:=true;
  229. end
  230. { funcret }
  231. else if (pt.nodetype=funcretn) then
  232. begin
  233. storetokenpos:=akttokenpos;
  234. akttokenpos:=declarepos;
  235. abssym:=tabsolutesym.create(s,tt);
  236. abssym.abstyp:=tovar;
  237. abssym.ref:=tstoredsym(tfuncretnode(pt).funcretsym);
  238. symtablestack.insert(abssym);
  239. akttokenpos:=storetokenpos;
  240. symdone:=true;
  241. end;
  242. { address }
  243. if (not symdone) and
  244. ((target_info.target=target_i386_go32v2) or
  245. (m_objfpc in aktmodeswitches) or
  246. (m_delphi in aktmodeswitches)) then
  247. begin
  248. if is_constintnode(pt) then
  249. begin
  250. storetokenpos:=akttokenpos;
  251. akttokenpos:=declarepos;
  252. abssym:=tabsolutesym.create(s,tt);
  253. abssym.abstyp:=toaddr;
  254. abssym.absseg:=false;
  255. abssym.address:=tordconstnode(pt).value;
  256. if (token=_COLON) and
  257. (target_info.target=target_i386_go32v2) then
  258. begin
  259. consume(token);
  260. pt:=expr;
  261. if is_constintnode(pt) then
  262. begin
  263. abssym.address:=abssym.address shl 4+tordconstnode(pt).value;
  264. abssym.absseg:=true;
  265. end
  266. else
  267. Message(parser_e_absolute_only_to_var_or_const);
  268. end;
  269. symtablestack.insert(abssym);
  270. akttokenpos:=storetokenpos;
  271. end
  272. else
  273. Message(parser_e_absolute_only_to_var_or_const);
  274. end;
  275. end
  276. else
  277. Message(parser_e_absolute_only_to_var_or_const);
  278. symdone:=true;
  279. end;
  280. { Handling of Delphi typed const = initialized vars ! }
  281. { When should this be rejected ?
  282. - in parasymtable
  283. - in record or object
  284. - ... (PM) }
  285. if (token=_EQUAL) and
  286. not(m_tp7 in aktmodeswitches) and
  287. not(symtablestack.symtabletype in [parasymtable]) and
  288. not is_record and
  289. not is_object then
  290. begin
  291. storetokenpos:=akttokenpos;
  292. s:=sc.get(akttokenpos);
  293. if not sc.empty then
  294. Message(parser_e_initialized_only_one_var);
  295. tconstsym:=ttypedconstsym.createtype(s,tt,false);
  296. symtablestack.insert(tconstsym);
  297. akttokenpos:=storetokenpos;
  298. consume(_EQUAL);
  299. readtypedconst(tt,tconstsym,true);
  300. symdone:=true;
  301. end;
  302. { hint directive }
  303. {$warning hintdirective not stored in syms}
  304. dummysymoptions:=[];
  305. try_consume_hintdirective(dummysymoptions);
  306. { for a record there doesn't need to be a ; before the END or ) }
  307. if not((is_record or is_object) and (token in [_END,_RKLAMMER])) then
  308. consume(_SEMICOLON);
  309. { procvar handling }
  310. if (tt.def.deftype=procvardef) and (tt.def.typesym=nil) then
  311. begin
  312. newtype:=ttypesym.create('unnamed',tt);
  313. parse_var_proc_directives(tsym(newtype));
  314. newtype.restype.def:=nil;
  315. tt.def.typesym:=nil;
  316. newtype.free;
  317. end;
  318. { Check for variable directives }
  319. if not symdone and (token=_ID) then
  320. begin
  321. { Check for C Variable declarations }
  322. if (m_cvar_support in aktmodeswitches) and
  323. not(is_record or is_object or is_threadvar) and
  324. (idtoken in [_EXPORT,_EXTERNAL,_PUBLIC,_CVAR]) then
  325. begin
  326. { only allowed for one var }
  327. s:=sc.get(declarepos);
  328. if not sc.empty then
  329. Message(parser_e_absolute_only_one_var);
  330. {$ifdef fixLeaksOnError}
  331. if strContStack.pop <> sc then
  332. writeln('problem with strContStack in pdecl (5)');
  333. {$endif fixLeaksOnError}
  334. sc.free;
  335. { defaults }
  336. is_dll:=false;
  337. is_cdecl:=false;
  338. extern_aktvarsym:=false;
  339. export_aktvarsym:=false;
  340. { cdecl }
  341. if idtoken=_CVAR then
  342. begin
  343. consume(_CVAR);
  344. consume(_SEMICOLON);
  345. is_cdecl:=true;
  346. C_name:=target_info.Cprefix+C_name;
  347. end;
  348. { external }
  349. if idtoken=_EXTERNAL then
  350. begin
  351. consume(_EXTERNAL);
  352. extern_aktvarsym:=true;
  353. end;
  354. { export }
  355. if idtoken in [_EXPORT,_PUBLIC] then
  356. begin
  357. consume(_ID);
  358. if extern_aktvarsym or
  359. (symtablestack.symtabletype in [parasymtable,localsymtable]) then
  360. Message(parser_e_not_external_and_export)
  361. else
  362. export_aktvarsym:=true;
  363. end;
  364. { external and export need a name after when no cdecl is used }
  365. if not is_cdecl then
  366. begin
  367. { dll name ? }
  368. if (extern_aktvarsym) and (idtoken<>_NAME) then
  369. begin
  370. is_dll:=true;
  371. dll_name:=get_stringconst;
  372. end;
  373. consume(_NAME);
  374. C_name:=get_stringconst;
  375. end;
  376. { consume the ; when export or external is used }
  377. if extern_aktvarsym or export_aktvarsym then
  378. consume(_SEMICOLON);
  379. { insert in the symtable }
  380. storetokenpos:=akttokenpos;
  381. akttokenpos:=declarepos;
  382. if is_dll then
  383. aktvarsym:=tvarsym.create_dll(s,tt)
  384. else
  385. aktvarsym:=tvarsym.create_C(s,C_name,tt);
  386. { set some vars options }
  387. if export_aktvarsym then
  388. begin
  389. inc(aktvarsym.refs);
  390. include(aktvarsym.varoptions,vo_is_exported);
  391. end;
  392. if extern_aktvarsym then
  393. include(aktvarsym.varoptions,vo_is_external);
  394. { insert in the stack/datasegment }
  395. symtablestack.insert(aktvarsym);
  396. akttokenpos:=storetokenpos;
  397. { now we can insert it in the import lib if its a dll, or
  398. add it to the externals }
  399. if extern_aktvarsym then
  400. begin
  401. if is_dll then
  402. begin
  403. if not(current_module.uses_imports) then
  404. begin
  405. current_module.uses_imports:=true;
  406. importlib.preparelib(current_module.modulename^);
  407. end;
  408. importlib.importvariable(aktvarsym.mangledname,dll_name,C_name)
  409. end
  410. else
  411. if target_info.DllScanSupported then
  412. current_module.Externals.insert(tExternalsItem.create(aktvarsym.mangledname));
  413. end;
  414. symdone:=true;
  415. end
  416. else
  417. if (is_object) and (cs_static_keyword in aktmoduleswitches) and (idtoken=_STATIC) then
  418. begin
  419. include(current_object_option,sp_static);
  420. insert_syms(symtablestack,sc,tt,false);
  421. exclude(current_object_option,sp_static);
  422. consume(_STATIC);
  423. consume(_SEMICOLON);
  424. symdone:=true;
  425. end;
  426. end;
  427. { insert it in the symtable, if not done yet }
  428. if not symdone then
  429. begin
  430. { save object option, because we can turn of the sp_published }
  431. if (sp_published in current_object_option) and
  432. not(is_class(tt.def)) then
  433. begin
  434. Message(parser_e_cant_publish_that);
  435. exclude(current_object_option,sp_published);
  436. end
  437. else
  438. if (sp_published in current_object_option) and
  439. not(oo_can_have_published in tobjectdef(tt.def).objectoptions) then
  440. begin
  441. Message(parser_e_only_publishable_classes_can__be_published);
  442. exclude(current_object_option,sp_published);
  443. end;
  444. insert_syms(symtablestack,sc,tt,is_threadvar);
  445. current_object_option:=old_current_object_option;
  446. end;
  447. end;
  448. { Check for Case }
  449. if is_record and (token=_CASE) then
  450. begin
  451. maxsize:=0;
  452. maxalignment:=0;
  453. consume(_CASE);
  454. s:=pattern;
  455. searchsym(s,srsym,srsymtable);
  456. { may be only a type: }
  457. if assigned(srsym) and (srsym.typ in [typesym,unitsym]) then
  458. begin
  459. { for records, don't search the recordsymtable for
  460. the symbols of the types }
  461. oldsymtablestack:=symtablestack;
  462. symtablestack:=symtablestack.next;
  463. read_type(casetype,'');
  464. symtablestack:=oldsymtablestack;
  465. end
  466. else
  467. begin
  468. consume(_ID);
  469. consume(_COLON);
  470. { for records, don't search the recordsymtable for
  471. the symbols of the types }
  472. oldsymtablestack:=symtablestack;
  473. symtablestack:=symtablestack.next;
  474. read_type(casetype,'');
  475. symtablestack:=oldsymtablestack;
  476. symtablestack.insert(tvarsym.create(s,casetype));
  477. end;
  478. if not(is_ordinal(casetype.def)) or is_64bitint(casetype.def) then
  479. Message(type_e_ordinal_expr_expected);
  480. consume(_OF);
  481. UnionSymtable:=trecordsymtable.create;
  482. Unionsymtable.next:=symtablestack;
  483. registerdef:=false;
  484. UnionDef:=trecorddef.create(unionsymtable);
  485. registerdef:=true;
  486. symtablestack:=UnionSymtable;
  487. startvarrecsize:=symtablestack.datasize;
  488. startvarrecalign:=symtablestack.dataalignment;
  489. repeat
  490. repeat
  491. pt:=comp_expr(true);
  492. if not(pt.nodetype=ordconstn) then
  493. Message(cg_e_illegal_expression);
  494. pt.free;
  495. if token=_COMMA then
  496. consume(_COMMA)
  497. else
  498. break;
  499. until false;
  500. consume(_COLON);
  501. { read the vars }
  502. consume(_LKLAMMER);
  503. inc(variantrecordlevel);
  504. if token<>_RKLAMMER then
  505. read_var_decs(true,false,false);
  506. dec(variantrecordlevel);
  507. consume(_RKLAMMER);
  508. { calculates maximal variant size }
  509. maxsize:=max(maxsize,symtablestack.datasize);
  510. maxalignment:=max(maxalignment,symtablestack.dataalignment);
  511. { the items of the next variant are overlayed }
  512. symtablestack.datasize:=startvarrecsize;
  513. symtablestack.dataalignment:=startvarrecalign;
  514. if (token<>_END) and (token<>_RKLAMMER) then
  515. consume(_SEMICOLON)
  516. else
  517. break;
  518. until (token=_END) or (token=_RKLAMMER);
  519. { at last set the record size to that of the biggest variant }
  520. symtablestack.datasize:=maxsize;
  521. symtablestack.dataalignment:=maxalignment;
  522. uniontype.def:=uniondef;
  523. uniontype.sym:=nil;
  524. UnionSym:=tvarsym.create('case',uniontype);
  525. symtablestack:=symtablestack.next;
  526. { we do NOT call symtablestack.insert
  527. on purpose PM }
  528. if aktalignment.recordalignmax=-1 then
  529. begin
  530. {$ifdef i386}
  531. if maxalignment>2 then
  532. minalignment:=4
  533. else if maxalignment>1 then
  534. minalignment:=2
  535. else
  536. minalignment:=1;
  537. {$else}
  538. {$ifdef m68k}
  539. minalignment:=2;
  540. {$endif}
  541. minalignment:=1;
  542. {$endif}
  543. end
  544. else
  545. minalignment:=maxalignment;
  546. usedalign:=used_align(maxalignment,minalignment,maxalignment);
  547. offset:=align(symtablestack.datasize,usedalign);
  548. symtablestack.datasize:=offset+unionsymtable.datasize;
  549. if maxalignment>symtablestack.dataalignment then
  550. symtablestack.dataalignment:=maxalignment;
  551. trecordsymtable(Unionsymtable).Insert_in(symtablestack,offset);
  552. Unionsym.owner:=nil;
  553. unionsym.free;
  554. uniondef.free;
  555. end;
  556. block_type:=old_block_type;
  557. current_object_option:=old_current_object_option;
  558. end;
  559. end.
  560. {
  561. $Log$
  562. Revision 1.21 2001-10-23 21:49:42 peter
  563. * $calling directive and -Cc commandline patch added
  564. from Pavel Ozerski
  565. Revision 1.20 2001/09/30 21:15:48 peter
  566. * merged absolute support for constants
  567. Revision 1.19 2001/08/30 20:13:53 peter
  568. * rtti/init table updates
  569. * rttisym for reusable global rtti/init info
  570. * support published for interfaces
  571. Revision 1.18 2001/07/01 20:16:16 peter
  572. * alignmentinfo record added
  573. * -Oa argument supports more alignment settings that can be specified
  574. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  575. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  576. required alignment and the maximum usefull alignment. The final
  577. alignment will be choosen per variable size dependent on these
  578. settings
  579. Revision 1.17 2001/06/03 21:57:36 peter
  580. + hint directive parsing support
  581. Revision 1.16 2001/04/18 22:01:57 peter
  582. * registration of targets and assemblers
  583. Revision 1.15 2001/04/13 01:22:12 peter
  584. * symtable change to classes
  585. * range check generation and errors fixed, make cycle DEBUG=1 works
  586. * memory leaks fixed
  587. Revision 1.14 2001/04/04 22:43:52 peter
  588. * remove unnecessary calls to firstpass
  589. Revision 1.13 2001/04/04 21:30:45 florian
  590. * applied several fixes to get the DD8 Delphi Unit compiled
  591. e.g. "forward"-interfaces are working now
  592. Revision 1.12 2001/04/02 21:20:33 peter
  593. * resulttype rewrite
  594. Revision 1.11 2001/03/11 22:58:50 peter
  595. * getsym redesign, removed the globals srsym,srsymtable
  596. Revision 1.10 2001/03/06 18:28:02 peter
  597. * patch from Pavel with a new and much faster DLL Scanner for
  598. automatic importing so $linklib works for DLLs. Thanks Pavel!
  599. Revision 1.9 2001/02/20 21:42:54 peter
  600. * record and object declaration with same field as type fixed
  601. Revision 1.7 2001/02/20 11:19:45 marco
  602. * Fix passing tvarrec to array of const
  603. Revision 1.6 2000/12/25 00:07:27 peter
  604. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  605. tlinkedlist objects)
  606. Revision 1.5 2000/12/17 14:00:18 peter
  607. * fixed static variables
  608. Revision 1.4 2000/11/29 00:30:36 florian
  609. * unused units removed from uses clause
  610. * some changes for widestrings
  611. Revision 1.3 2000/11/04 14:25:20 florian
  612. + merged Attila's changes for interfaces, not tested yet
  613. Revision 1.2 2000/10/31 22:02:49 peter
  614. * symtable splitted, no real code changes
  615. Revision 1.1 2000/10/14 10:14:51 peter
  616. * moehrendorf oct 2000 rewrite
  617. }