ptype.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Does parsing types for Free Pascal
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ptype;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. globtype,symtype;
  23. const
  24. { forward types should only be possible inside a TYPE statement }
  25. typecanbeforward : boolean = false;
  26. var
  27. { hack, which allows to use the current parsed }
  28. { object type as function argument type }
  29. testcurobject : byte;
  30. curobjectname : stringid;
  31. { reads a string, file type or a type id and returns a name and }
  32. { tdef }
  33. procedure single_type(var tt:ttype;var s : string;isforwarddef:boolean);
  34. procedure read_type(var tt:ttype;const name : stringid);
  35. { reads a type definition }
  36. { to a appropriating tdef, s gets the name of }
  37. { the type to allow name mangling }
  38. procedure id_type(var tt : ttype;var s : string;isforwarddef:boolean);
  39. implementation
  40. uses
  41. { common }
  42. cutils,cpuinfo,
  43. { global }
  44. globals,tokens,verbose,
  45. systems,
  46. { symtable }
  47. symconst,symbase,symdef,symsym,symtable,types,
  48. { pass 1 }
  49. node,pass_1,
  50. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
  51. { parser }
  52. scanner,
  53. pbase,pexpr,pdecsub,pdecvar,pdecobj;
  54. procedure id_type(var tt : ttype;var s : string;isforwarddef:boolean);
  55. { reads a type definition }
  56. { to a appropriating tdef, s gets the name of }
  57. { the type to allow name mangling }
  58. var
  59. is_unit_specific : boolean;
  60. pos : tfileposinfo;
  61. srsym : tsym;
  62. srsymtable : tsymtable;
  63. sorg : stringid;
  64. begin
  65. s:=pattern;
  66. sorg:=orgpattern;
  67. pos:=akttokenpos;
  68. { classes can be used also in classes }
  69. if (curobjectname=pattern) and is_class_or_interface(aktobjectdef) then
  70. begin
  71. tt.setdef(aktobjectdef);
  72. consume(_ID);
  73. exit;
  74. end;
  75. { objects can be parameters }
  76. if (testcurobject=2) and (curobjectname=pattern) then
  77. begin
  78. tt.setdef(aktobjectdef);
  79. consume(_ID);
  80. exit;
  81. end;
  82. { try to load the symbol to see if it's a unitsym }
  83. is_unit_specific:=false;
  84. searchsym(s,srsym,srsymtable);
  85. consume(_ID);
  86. if assigned(srsym) and
  87. (srsym.typ=unitsym) then
  88. begin
  89. is_unit_specific:=true;
  90. consume(_POINT);
  91. if srsym.owner.unitid=0 then
  92. begin
  93. srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
  94. pos:=akttokenpos;
  95. s:=pattern;
  96. end
  97. else
  98. srsym:=nil;
  99. consume(_ID);
  100. end;
  101. { are we parsing a possible forward def ? }
  102. if isforwarddef and
  103. not(is_unit_specific) then
  104. begin
  105. tt.setdef(tforwarddef.create(s,pos));
  106. exit;
  107. end;
  108. { unknown sym ? }
  109. if not assigned(srsym) then
  110. begin
  111. Message1(sym_e_id_not_found,sorg);
  112. tt:=generrortype;
  113. exit;
  114. end;
  115. { type sym ? }
  116. if (srsym.typ<>typesym) then
  117. begin
  118. Message(type_e_type_id_expected);
  119. tt:=generrortype;
  120. exit;
  121. end;
  122. { Types are first defined with an error def before assigning
  123. the real type so check if it's an errordef. if so then
  124. give an error }
  125. if (ttypesym(srsym).restype.def.deftype=errordef) then
  126. begin
  127. Message(sym_e_error_in_type_def);
  128. tt:=generrortype;
  129. exit;
  130. end;
  131. { Only use the definitions for system/current unit, becuase
  132. they can be refered from the parameters and symbols are not
  133. loaded at that time. A symbol reference to an other unit
  134. is still possible, because it's already loaded (PFV)
  135. can't use in [] here, becuase unitid can be > 255 }
  136. if (ttypesym(srsym).owner.unitid=0) or
  137. (ttypesym(srsym).owner.unitid=1) then
  138. tt.setdef(ttypesym(srsym).restype.def)
  139. else
  140. tt.setsym(srsym);
  141. end;
  142. procedure single_type(var tt:ttype;var s : string;isforwarddef:boolean);
  143. { reads a string, file type or a type id and returns a name and }
  144. { tdef }
  145. var
  146. hs : string;
  147. t2 : ttype;
  148. begin
  149. case token of
  150. _STRING:
  151. begin
  152. string_dec(tt);
  153. s:='STRING';
  154. end;
  155. _FILE:
  156. begin
  157. consume(_FILE);
  158. if token=_OF then
  159. begin
  160. consume(_OF);
  161. single_type(t2,hs,false);
  162. tt.setdef(tfiledef.createtyped(t2));
  163. s:='FILE$OF$'+hs;
  164. end
  165. else
  166. begin
  167. tt:=cfiletype;
  168. s:='FILE';
  169. end;
  170. end;
  171. else
  172. begin
  173. id_type(tt,s,isforwarddef);
  174. end;
  175. end;
  176. end;
  177. { reads a record declaration }
  178. function record_dec : tdef;
  179. var
  180. symtable : tsymtable;
  181. storetypecanbeforward : boolean;
  182. begin
  183. { create recdef }
  184. symtable:=trecordsymtable.create;
  185. record_dec:=trecorddef.create(symtable);
  186. { update symtable stack }
  187. symtable.next:=symtablestack;
  188. symtablestack:=symtable;
  189. { parse record }
  190. consume(_RECORD);
  191. storetypecanbeforward:=typecanbeforward;
  192. { for tp mode don't allow forward types }
  193. if m_tp in aktmodeswitches then
  194. typecanbeforward:=false;
  195. read_var_decs(true,false,false);
  196. consume(_END);
  197. typecanbeforward:=storetypecanbeforward;
  198. { may be scale record size to a size of n*4 ? }
  199. symtablestack.datasize:=align(symtablestack.datasize,symtablestack.dataalignment);
  200. { restore symtable stack }
  201. symtablestack:=symtable.next;
  202. end;
  203. { reads a type definition and returns a pointer to it }
  204. procedure read_type(var tt : ttype;const name : stringid);
  205. var
  206. pt : tnode;
  207. tt2 : ttype;
  208. aktenumdef : tenumdef;
  209. ap : tarraydef;
  210. s : stringid;
  211. l,v : TConstExprInt;
  212. oldaktpackrecords : longint;
  213. hs : string;
  214. defpos,storepos : tfileposinfo;
  215. procedure expr_type;
  216. var
  217. pt1,pt2 : tnode;
  218. begin
  219. { use of current parsed object ? }
  220. if (token=_ID) and (testcurobject=2) and (curobjectname=pattern) then
  221. begin
  222. consume(_ID);
  223. tt.setdef(aktobjectdef);
  224. exit;
  225. end;
  226. { classes can be used also in classes }
  227. if (curobjectname=pattern) and is_class_or_interface(aktobjectdef) then
  228. begin
  229. tt.setdef(aktobjectdef);
  230. consume(_ID);
  231. exit;
  232. end;
  233. { we can't accept a equal in type }
  234. pt1:=comp_expr(not(ignore_equal));
  235. if (token=_POINTPOINT) then
  236. begin
  237. consume(_POINTPOINT);
  238. { get high value of range }
  239. pt2:=comp_expr(not(ignore_equal));
  240. { make both the same type }
  241. inserttypeconv(pt1,pt2.resulttype);
  242. { both must be evaluated to constants now }
  243. if (pt1.nodetype=ordconstn) and
  244. (pt2.nodetype=ordconstn) then
  245. begin
  246. { Check bounds }
  247. if tordconstnode(pt2).value<tordconstnode(pt1).value then
  248. Message(cg_e_upper_lower_than_lower)
  249. else
  250. begin
  251. { All checks passed, create the new def }
  252. case pt1.resulttype.def.deftype of
  253. enumdef :
  254. tt.setdef(tenumdef.create_subrange(tenumdef(pt1.resulttype.def),tordconstnode(pt1).value,tordconstnode(pt2).value));
  255. orddef :
  256. begin
  257. if is_char(pt1.resulttype.def) then
  258. tt.setdef(torddef.create(uchar,tordconstnode(pt1).value,tordconstnode(pt2).value))
  259. else
  260. if is_boolean(pt1.resulttype.def) then
  261. tt.setdef(torddef.create(bool8bit,tordconstnode(pt1).value,tordconstnode(pt2).value))
  262. else
  263. tt.setdef(torddef.create(uauto,tordconstnode(pt1).value,tordconstnode(pt2).value));
  264. end;
  265. end;
  266. end;
  267. end
  268. else
  269. Message(sym_e_error_in_type_def);
  270. pt2.free;
  271. end
  272. else
  273. begin
  274. { a simple type renaming }
  275. if (pt1.nodetype=typen) then
  276. tt:=ttypenode(pt1).resulttype
  277. else
  278. Message(sym_e_error_in_type_def);
  279. end;
  280. pt1.free;
  281. end;
  282. procedure array_dec;
  283. var
  284. lowval,
  285. highval : longint;
  286. arraytype : ttype;
  287. ht : ttype;
  288. procedure setdefdecl(const t:ttype);
  289. begin
  290. case t.def.deftype of
  291. enumdef :
  292. begin
  293. lowval:=tenumdef(t.def).min;
  294. highval:=tenumdef(t.def).max;
  295. arraytype:=t;
  296. end;
  297. orddef :
  298. begin
  299. if torddef(t.def).typ in [uchar,
  300. u8bit,u16bit,
  301. s8bit,s16bit,s32bit,
  302. bool8bit,bool16bit,bool32bit,
  303. uwidechar] then
  304. begin
  305. lowval:=torddef(t.def).low;
  306. highval:=torddef(t.def).high;
  307. arraytype:=t;
  308. end
  309. else
  310. Message1(parser_e_type_cant_be_used_in_array_index,t.def.gettypename);
  311. end;
  312. else
  313. Message(sym_e_error_in_type_def);
  314. end;
  315. end;
  316. begin
  317. consume(_ARRAY);
  318. { open array? }
  319. if token=_LECKKLAMMER then
  320. begin
  321. consume(_LECKKLAMMER);
  322. { defaults }
  323. arraytype:=generrortype;
  324. lowval:=longint($80000000);
  325. highval:=$7fffffff;
  326. tt.reset;
  327. repeat
  328. { read the expression and check it, check apart if the
  329. declaration is an enum declaration because that needs to
  330. be parsed by readtype (PFV) }
  331. if token=_LKLAMMER then
  332. begin
  333. read_type(ht,'');
  334. setdefdecl(ht);
  335. end
  336. else
  337. begin
  338. pt:=expr;
  339. if pt.nodetype=typen then
  340. setdefdecl(pt.resulttype)
  341. else
  342. begin
  343. if (pt.nodetype=rangen) then
  344. begin
  345. if (trangenode(pt).left.nodetype=ordconstn) and
  346. (trangenode(pt).right.nodetype=ordconstn) then
  347. begin
  348. lowval:=tordconstnode(trangenode(pt).left).value;
  349. highval:=tordconstnode(trangenode(pt).right).value;
  350. if highval<lowval then
  351. begin
  352. Message(parser_e_array_lower_less_than_upper_bound);
  353. highval:=lowval;
  354. end;
  355. arraytype:=trangenode(pt).right.resulttype;
  356. end
  357. else
  358. Message(type_e_cant_eval_constant_expr);
  359. end
  360. else
  361. Message(sym_e_error_in_type_def)
  362. end;
  363. pt.free;
  364. end;
  365. { create arraydef }
  366. if not assigned(tt.def) then
  367. begin
  368. ap:=tarraydef.create(lowval,highval,arraytype);
  369. tt.setdef(ap);
  370. end
  371. else
  372. begin
  373. ap.elementtype.setdef(tarraydef.create(lowval,highval,arraytype));
  374. ap:=tarraydef(ap.elementtype.def);
  375. end;
  376. if token=_COMMA then
  377. consume(_COMMA)
  378. else
  379. break;
  380. until false;
  381. consume(_RECKKLAMMER);
  382. end
  383. else
  384. begin
  385. ap:=tarraydef.create(0,-1,s32bittype);
  386. ap.IsDynamicArray:=true;
  387. tt.setdef(ap);
  388. end;
  389. consume(_OF);
  390. read_type(tt2,'');
  391. { if no error, set element type }
  392. if assigned(ap) then
  393. ap.elementtype:=tt2;
  394. end;
  395. var
  396. p : tnode;
  397. enumdupmsg : boolean;
  398. begin
  399. tt.reset;
  400. case token of
  401. _STRING,_FILE:
  402. begin
  403. single_type(tt,hs,false);
  404. end;
  405. _LKLAMMER:
  406. begin
  407. consume(_LKLAMMER);
  408. { allow negativ value_str }
  409. l:=-1;
  410. enumdupmsg:=false;
  411. aktenumdef:=tenumdef.create;
  412. repeat
  413. s:=orgpattern;
  414. defpos:=akttokenpos;
  415. consume(_ID);
  416. { only allow assigning of specific numbers under fpc mode }
  417. if (m_fpc in aktmodeswitches) and
  418. (token=_ASSIGNMENT) then
  419. begin
  420. consume(_ASSIGNMENT);
  421. v:=get_intconst;
  422. { please leave that a note, allows type save }
  423. { declarations in the win32 units ! }
  424. if (v<=l) and (not enumdupmsg) then
  425. begin
  426. Message(parser_n_duplicate_enum);
  427. enumdupmsg:=true;
  428. end;
  429. l:=v;
  430. end
  431. else if (m_delphi in aktmodeswitches) and
  432. (token=_EQUAL) then
  433. begin
  434. consume(_EQUAL);
  435. p:=comp_expr(true);
  436. if (p.nodetype=ordconstn) then
  437. begin
  438. { we expect an integer or an enum of the
  439. same type }
  440. if is_integer(p.resulttype.def) or
  441. is_equal(p.resulttype.def,aktenumdef) then
  442. l:=tordconstnode(p).value
  443. else
  444. Message2(type_e_incompatible_types,p.resulttype.def.typename,s32bittype.def.typename);
  445. end
  446. else
  447. Message(cg_e_illegal_expression);
  448. p.free;
  449. end
  450. else
  451. inc(l);
  452. storepos:=akttokenpos;
  453. akttokenpos:=defpos;
  454. constsymtable.insert(tenumsym.create(s,aktenumdef,l));
  455. akttokenpos:=storepos;
  456. until not try_to_consume(_COMMA);
  457. tt.setdef(aktenumdef);
  458. consume(_RKLAMMER);
  459. end;
  460. _ARRAY:
  461. begin
  462. array_dec;
  463. end;
  464. _SET:
  465. begin
  466. consume(_SET);
  467. consume(_OF);
  468. read_type(tt2,'');
  469. if assigned(tt2.def) then
  470. begin
  471. case tt2.def.deftype of
  472. { don't forget that min can be negativ PM }
  473. enumdef :
  474. if tenumdef(tt2.def).min>=0 then
  475. tt.setdef(tsetdef.create(tt2,tenumdef(tt2.def).max))
  476. else
  477. Message(sym_e_ill_type_decl_set);
  478. orddef :
  479. begin
  480. case torddef(tt2.def).typ of
  481. uchar :
  482. tt.setdef(tsetdef.create(tt2,255));
  483. u8bit,u16bit,u32bit,
  484. s8bit,s16bit,s32bit :
  485. begin
  486. if (torddef(tt2.def).low>=0) then
  487. tt.setdef(tsetdef.create(tt2,torddef(tt2.def).high))
  488. else
  489. Message(sym_e_ill_type_decl_set);
  490. end;
  491. else
  492. Message(sym_e_ill_type_decl_set);
  493. end;
  494. end;
  495. else
  496. Message(sym_e_ill_type_decl_set);
  497. end;
  498. end
  499. else
  500. tt:=generrortype;
  501. end;
  502. _CARET:
  503. begin
  504. consume(_CARET);
  505. single_type(tt2,hs,typecanbeforward);
  506. tt.setdef(tpointerdef.create(tt2));
  507. end;
  508. _RECORD:
  509. begin
  510. tt.setdef(record_dec);
  511. end;
  512. _PACKED:
  513. begin
  514. consume(_PACKED);
  515. if token=_ARRAY then
  516. array_dec
  517. else
  518. begin
  519. oldaktpackrecords:=aktalignment.recordalignmax;
  520. aktalignment.recordalignmax:=1;
  521. if token in [_CLASS,_OBJECT] then
  522. tt.setdef(object_dec(name,nil))
  523. else
  524. tt.setdef(record_dec);
  525. aktalignment.recordalignmax:=oldaktpackrecords;
  526. end;
  527. end;
  528. _CLASS,
  529. _CPPCLASS,
  530. _INTERFACE,
  531. _OBJECT:
  532. begin
  533. tt.setdef(object_dec(name,nil));
  534. end;
  535. _PROCEDURE:
  536. begin
  537. consume(_PROCEDURE);
  538. tt.setdef(tprocvardef.create);
  539. if token=_LKLAMMER then
  540. parameter_dec(tprocvardef(tt.def));
  541. if token=_OF then
  542. begin
  543. consume(_OF);
  544. consume(_OBJECT);
  545. include(tprocvardef(tt.def).procoptions,po_methodpointer);
  546. end;
  547. end;
  548. _FUNCTION:
  549. begin
  550. consume(_FUNCTION);
  551. tt.def:=tprocvardef.create;
  552. if token=_LKLAMMER then
  553. parameter_dec(tprocvardef(tt.def));
  554. consume(_COLON);
  555. single_type(tprocvardef(tt.def).rettype,hs,false);
  556. if token=_OF then
  557. begin
  558. consume(_OF);
  559. consume(_OBJECT);
  560. include(tprocvardef(tt.def).procoptions,po_methodpointer);
  561. end;
  562. end;
  563. else
  564. expr_type;
  565. end;
  566. if tt.def=nil then
  567. tt:=generrortype;
  568. end;
  569. end.
  570. {
  571. $Log$
  572. Revision 1.29 2001-08-12 22:10:16 peter
  573. * write name in original case when type not found
  574. Revision 1.28 2001/07/09 21:15:41 peter
  575. * Length made internal
  576. * Add array support for Length
  577. Revision 1.27 2001/07/01 20:16:16 peter
  578. * alignmentinfo record added
  579. * -Oa argument supports more alignment settings that can be specified
  580. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  581. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  582. required alignment and the maximum usefull alignment. The final
  583. alignment will be choosen per variable size dependent on these
  584. settings
  585. Revision 1.26 2001/06/04 18:06:38 peter
  586. * fix for enum with assignment
  587. Revision 1.25 2001/06/04 11:51:59 peter
  588. * enum type declarations assignments can also be of the same enum
  589. type
  590. Revision 1.24 2001/06/03 20:16:19 peter
  591. * allow int64 in range declaration for new types
  592. Revision 1.23 2001/04/13 01:22:13 peter
  593. * symtable change to classes
  594. * range check generation and errors fixed, make cycle DEBUG=1 works
  595. * memory leaks fixed
  596. Revision 1.22 2001/04/04 22:43:53 peter
  597. * remove unnecessary calls to firstpass
  598. Revision 1.21 2001/04/02 21:20:34 peter
  599. * resulttype rewrite
  600. Revision 1.20 2001/03/22 22:35:42 florian
  601. + support for type a = (a=1); in Delphi mode added
  602. + procedure p(); in Delphi mode supported
  603. + on isn't keyword anymore, it can be used as
  604. id etc. now
  605. Revision 1.19 2001/03/12 12:49:01 michael
  606. + Patches from peter
  607. Revision 1.18 2001/03/11 22:58:50 peter
  608. * getsym redesign, removed the globals srsym,srsymtable
  609. Revision 1.17 2000/12/07 17:19:43 jonas
  610. * new constant handling: from now on, hex constants >$7fffffff are
  611. parsed as unsigned constants (otherwise, $80000000 got sign extended
  612. and became $ffffffff80000000), all constants in the longint range
  613. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  614. are cardinals and the rest are int64's.
  615. * added lots of longint typecast to prevent range check errors in the
  616. compiler and rtl
  617. * type casts of symbolic ordinal constants are now preserved
  618. * fixed bug where the original resulttype.def wasn't restored correctly
  619. after doing a 64bit rangecheck
  620. Revision 1.16 2000/11/29 00:30:38 florian
  621. * unused units removed from uses clause
  622. * some changes for widestrings
  623. Revision 1.15 2000/11/14 23:43:38 florian
  624. * fixed 1238
  625. Revision 1.14 2000/11/04 14:25:21 florian
  626. + merged Attila's changes for interfaces, not tested yet
  627. Revision 1.13 2000/10/31 22:02:51 peter
  628. * symtable splitted, no real code changes
  629. Revision 1.12 2000/10/26 21:54:03 peter
  630. * fixed crash with error in child definition (merged)
  631. Revision 1.11 2000/10/21 18:16:12 florian
  632. * a lot of changes:
  633. - basic dyn. array support
  634. - basic C++ support
  635. - some work for interfaces done
  636. ....
  637. Revision 1.10 2000/10/14 10:14:52 peter
  638. * moehrendorf oct 2000 rewrite
  639. Revision 1.9 2000/09/24 15:06:25 peter
  640. * use defines.inc
  641. Revision 1.8 2000/08/27 20:19:39 peter
  642. * store strings with case in ppu, when an internal symbol is created
  643. a '$' is prefixed so it's not automatic uppercased
  644. Revision 1.7 2000/08/27 16:11:52 peter
  645. * moved some util functions from globals,cobjects to cutils
  646. * splitted files into finput,fmodule
  647. Revision 1.6 2000/08/16 18:33:54 peter
  648. * splitted namedobjectitem.next into indexnext and listnext so it
  649. can be used in both lists
  650. * don't allow "word = word" type definitions (merged)
  651. Revision 1.5 2000/08/06 14:17:15 peter
  652. * overload fixes (merged)
  653. Revision 1.4 2000/07/30 17:04:43 peter
  654. * merged fixes
  655. Revision 1.3 2000/07/13 12:08:27 michael
  656. + patched to 1.1.0 with former 1.09patch from peter
  657. Revision 1.2 2000/07/13 11:32:47 michael
  658. + removed logs
  659. }