* fixed memory leaks for do nothing source

* fixed unit interdependency
This commit is contained in:
peter 1998-10-08 13:48:40 +00:00
parent 075d0d16fc
commit 47c808f95a
6 changed files with 244 additions and 157 deletions

View File

@ -597,14 +597,14 @@ begin
begin
CGMessage(cg_d_stackframe_omited);
nostackframe:=true;
if (aktprocsym^.definition^.options and (pounitinit or poproginit)<>0) then
if (aktprocsym^.definition^.options and (pounitinit or poproginit or pounitfinalize)<>0) then
parasize:=0
else
parasize:=aktprocsym^.definition^.parast^.datasize+procinfo.call_offset;
end
else
begin
if (aktprocsym^.definition^.options and (pounitinit or poproginit)<>0) then
if (aktprocsym^.definition^.options and (pounitinit or poproginit or pounitfinalize)<>0) then
parasize:=0
else
parasize:=aktprocsym^.definition^.parast^.datasize+procinfo.call_offset-8;
@ -1345,7 +1345,11 @@ end;
end.
{
$Log$
Revision 1.18 1998-09-28 16:57:17 pierre
Revision 1.19 1998-10-08 13:48:40 peter
* fixed memory leaks for do nothing source
* fixed unit interdependency
Revision 1.18 1998/09/28 16:57:17 pierre
* changed all length(p^.value_str^) into str_length(p)
to get it work with and without ansistrings
* changed sourcefiles field of tmodule to a pointer

View File

@ -123,7 +123,8 @@ unit files;
map : punitmap; { mapping of all used units }
unitcount : word; { local unit counter }
unit_index : word; { global counter for browser }
symtable : pointer; { pointer to the psymtable of this unit }
globalsymtable, { pointer to the local/static symtable of this unit }
localsymtable : pointer; { pointer to the psymtable of this unit }
{$ifdef UseBrowser}
implsymtable : pointer;
{$endif UseBrowser}
@ -778,8 +779,32 @@ unit files;
procedure tmodule.reset;
begin
{$ifndef VER0_99_8}
if assigned(globalsymtable) then
begin
dispose(punitsymtable(globalsymtable),done);
globalsymtable:=nil;
end;
if assigned(localsymtable) then
begin
dispose(punitsymtable(localsymtable),done);
localsymtable:=nil;
end;
{$endif}
if assigned(map) then
begin
dispose(map);
map:=nil;
end;
if assigned(ppufile) then
begin
dispose(ppufile,done);
ppufile:=nil;
end;
sourcefiles^.done;
sourcefiles^.init;
imports^.done;
imports^.init;
used_units.done;
used_units.init;
linkofiles.done;
@ -788,6 +813,17 @@ unit files;
linkstaticlibs.init;
linksharedlibs.done;
linksharedlibs.init;
uses_imports:=false;
do_assemble:=false;
do_compile:=false;
sources_avail:=true;
compiled:=false;
in_implementation:=false;
in_global:=true;
loaded_from:=nil;
flags:=0;
crc:=0;
unitcount:=1;
end;
@ -830,7 +866,8 @@ unit files;
ppufile:=nil;
scanner:=nil;
map:=nil;
symtable:=nil;
globalsymtable:=nil;
localsymtable:=nil;
{$ifdef UseBrowser}
implsymtable:=nil;
{$endif UseBrowser}
@ -850,9 +887,6 @@ unit files;
is_unit:=_is_unit;
uses_imports:=false;
imports:=new(plinkedlist,init);
{ set smartlink flag }
if (cs_smartlink in aktmoduleswitches) then
flags:=flags or uf_smartlink;
{ search the PPU file if it is an unit }
if is_unit then
begin
@ -870,9 +904,9 @@ unit files;
dispose(ppufile,done);
if assigned(imports) then
dispose(imports,done);
used_units.done;
if assigned(sourcefiles) then
dispose(sourcefiles,done);
used_units.done;
linkofiles.done;
linkstaticlibs.done;
linksharedlibs.done;
@ -887,8 +921,10 @@ unit files;
stringdispose(mainsource);
stringdispose(asmprefix);
{$ifndef VER0_99_8}
if assigned(symtable) then
dispose(punitsymtable(symtable),done);
if assigned(globalsymtable) then
dispose(punitsymtable(globalsymtable),done);
if assigned(localsymtable) then
dispose(punitsymtable(localsymtable),done);
{$endif}
inherited done;
end;
@ -933,7 +969,11 @@ unit files;
end.
{
$Log$
Revision 1.52 1998-10-06 22:09:48 peter
Revision 1.53 1998-10-08 13:48:43 peter
* fixed memory leaks for do nothing source
* fixed unit interdependency
Revision 1.52 1998/10/06 22:09:48 peter
* fixed for compiling with 0.99.8 due circular units
Revision 1.51 1998/10/06 17:16:47 pierre

View File

@ -284,8 +284,15 @@ unit parser;
dispose(current_module^.ppufile,done);
current_module^.ppufile:=nil;
end;
{ free scanner }
{ free scanner, but it can already be freed due a 2nd compile }
if assigned(current_scanner) then
begin
dispose(current_scanner,done);
current_scanner:=nil;
end;
current_module^.scanner:=nil;
{ free macros }
{!!! No check for unused macros yet !!! }
dispose(macros,done);
@ -367,7 +374,11 @@ unit parser;
end.
{
$Log$
Revision 1.55 1998-10-06 17:16:53 pierre
Revision 1.56 1998-10-08 13:48:45 peter
* fixed memory leaks for do nothing source
* fixed unit interdependency
Revision 1.55 1998/10/06 17:16:53 pierre
* some memory leaks fixed (thanks to Peter for heaptrc !)
Revision 1.54 1998/10/05 21:33:23 peter

View File

@ -688,7 +688,7 @@ unit pdecl;
begin
consume(_CONSTRUCTOR);
{ must be at same level as in implementation }
_proc_head(poconstructor);
parse_proc_head(poconstructor);
if (cs_constructor_name in aktglobalswitches) and (aktprocsym^.name<>'INIT') then
Message(parser_e_constructorname_must_be_init);
@ -1023,7 +1023,7 @@ unit pdecl;
procedure destructor_head;
begin
consume(_DESTRUCTOR);
_proc_head(podestructor);
parse_proc_head(podestructor);
if (cs_constructor_name in aktglobalswitches) and (aktprocsym^.name<>'DONE') then
Message(parser_e_destructorname_must_be_done);
consume(SEMICOLON);
@ -1281,7 +1281,7 @@ unit pdecl;
_CLASS : begin
oldparse_only:=parse_only;
parse_only:=true;
proc_head;
parse_proc_dec;
parse_only:=oldparse_only;
case idtoken of
_DYNAMIC,
@ -2024,7 +2024,7 @@ unit pdecl;
_FUNCTION,_PROCEDURE,_OPERATOR,_CLASS:
begin
Not_supported_for_inline(token);
unter_dec;
read_proc;
end;
_EXPORTS:
begin
@ -2053,7 +2053,7 @@ unit pdecl;
_VAR : var_dec;
_FUNCTION,
_PROCEDURE,
_OPERATOR : unter_dec;
_OPERATOR : read_proc;
else
break;
end;
@ -2064,7 +2064,11 @@ unit pdecl;
end.
{
$Log$
Revision 1.66 1998-10-06 20:43:31 peter
Revision 1.67 1998-10-08 13:48:46 peter
* fixed memory leaks for do nothing source
* fixed unit interdependency
Revision 1.66 1998/10/06 20:43:31 peter
* fixed set of bugs. like set of false..true set of #1..#255 and
set of #1..true which was allowed

View File

@ -22,7 +22,7 @@
}
unit pmodules;
{define TEST_IMPL does not work well }
{.$define TEST_IMPL does not work well }
interface
@ -200,10 +200,13 @@ unit pmodules;
if loaded_unit^.crc<>pu^.checksum then
begin
current_module^.do_compile:=true;
dispose(current_module^.map);
current_module^.map:=nil;
Comment(V_Warning,'recompiling, interface of '+pu^.name^+' (intfc) is changed');
exit;
end;
{ setup the map entry for deref }
current_module^.map^[nextmapentry]:=loaded_unit^.symtable;
current_module^.map^[nextmapentry]:=loaded_unit^.globalsymtable;
inc(nextmapentry);
if nextmapentry>maxunits then
Message(unit_f_too_much_units);
@ -211,12 +214,12 @@ unit pmodules;
pu:=pused_unit(pu^.next);
end;
{ ok, now load the unit }
current_module^.symtable:=new(punitsymtable,loadasunit);
current_module^.globalsymtable:=new(punitsymtable,loadasunit);
{ if this is the system unit insert the intern symbols }
if compile_system then
begin
make_ref:=false;
insertinternsyms(psymtable(current_module^.symtable));
insertinternsyms(psymtable(current_module^.globalsymtable));
make_ref:=true;
end;
{ now only read the implementation part }
@ -238,11 +241,14 @@ unit pmodules;
if loaded_unit^.crc<>pu^.checksum then
begin
current_module^.do_compile:=true;
Comment(V_Warning,'recompiling, interface of '+pu^.name^+' (impl) is changed');
dispose(current_module^.map);
current_module^.map:=nil;
exit;
end;
{$endif TEST_IMPL}
{ setup the map entry for deref }
current_module^.map^[nextmapentry]:=loaded_unit^.symtable;
current_module^.map^[nextmapentry]:=loaded_unit^.globalsymtable;
inc(nextmapentry);
if nextmapentry>maxunits then
Message(unit_f_too_much_units);
@ -251,10 +257,7 @@ unit pmodules;
end;
{$ifdef UseBrowser}
if cs_browser in aktmoduleswitches then
begin
punitsymtable(current_module^.symtable)^.
load_symtable_refs;
end;
punitsymtable(current_module^.symtable)^.load_symtable_refs;
if ((current_module^.flags and uf_has_browser)<>0) and
(cs_local_browser in aktmoduleswitches) then
begin
@ -299,12 +302,22 @@ unit pmodules;
if not(current_module^.sources_avail) then
Message1(unit_f_cant_compile_unit,current_module^.modulename^)
else
begin
if assigned(old_current_module^.scanner) then
begin
current_scanner^.tempcloseinputfile;
current_scanner:=nil;
{ the current_scanner is always the same
as current_module^.scanner (PFV) }
end;
compile(current_module^.mainsource^,compile_system);
if (not old_current_module^.compiled) then
if (not old_current_module^.compiled) and
assigned(old_current_module^.scanner) then
begin
current_scanner:=old_current_module^.scanner;
current_scanner^.tempopeninputfile;
end;
end;
end
else
begin
@ -338,8 +351,8 @@ unit pmodules;
{ and this means that the unit }
{ is already compiled }
{ else there is a cyclic unit use }
if assigned(hp^.symtable) then
st:=punitsymtable(hp^.symtable)
if assigned(hp^.globalsymtable) then
st:=punitsymtable(hp^.globalsymtable)
else
begin
{ both units in interface ? }
@ -366,16 +379,17 @@ unit pmodules;
{ the unit is not in the symtable stack }
if (not assigned(st)) then
begin
{ if the unit is loaded remove it first }
{ if the unit is loaded remove it first, but hold the same
memory position, so no new/dispose }
{ this creates problem with the browser !! }
if assigned(hp) then
begin
{ remove the old unit }
loaded_units.remove(hp);
hp^.done;
hp^.init(s,true);
hp^.reset;
current_module:=hp;
current_module^.in_second_compile:=true;
current_module^.do_compile:=true;
end
else
{ generates a new unit info record }
@ -414,7 +428,7 @@ unit pmodules;
end;
{ insert the system unit, it is allways the first }
hp:=loadunit(upper(target_info.system_unit),true);
systemunit:=hp^.symtable;
systemunit:=hp^.globalsymtable;
{ it's always the first unit }
systemunit^.next:=nil;
symtablestack:=systemunit;
@ -433,7 +447,7 @@ unit pmodules;
if m_objpas in aktmodeswitches then
begin
hp:=loadunit('OBJPAS',false);
objpasunit:=hp^.symtable;
objpasunit:=hp^.globalsymtable;
{ insert in stack }
objpasunit^.next:=symtablestack;
symtablestack:=objpasunit;
@ -470,7 +484,7 @@ unit pmodules;
pused_unit(current_module^.used_units.last)^.in_uses:=true;
if current_module^.compiled then
exit;
refsymtable^.insert(new(punitsym,init(s,hp2^.symtable)));
refsymtable^.insert(new(punitsym,init(s,hp2^.globalsymtable)));
if token=COMMA then
begin
pattern:='';
@ -492,9 +506,9 @@ unit pmodules;
if (cs_debuginfo in aktmoduleswitches) and
not hp^.is_stab_written then
begin
punitsymtable(hp^.u^.symtable)^.concattypestabto(debuglist);
punitsymtable(hp^.u^.globalsymtable)^.concattypestabto(debuglist);
hp^.is_stab_written:=true;
hp^.unitid:=psymtable(hp^.u^.symtable)^.unitid;
hp^.unitid:=psymtable(hp^.u^.globalsymtable)^.unitid;
end;
{$EndIf GDB}
if hp^.in_uses then
@ -503,14 +517,14 @@ unit pmodules;
while assigned(hp3) do
begin
{ insert units only once ! }
if hp^.u^.symtable=hp3 then
if hp^.u^.globalsymtable=hp3 then
break;
hp3:=hp3^.next;
{ unit isn't inserted }
if hp3=nil then
begin
psymtable(hp^.u^.symtable)^.next:=symtablestack;
symtablestack:=psymtable(hp^.u^.symtable);
psymtable(hp^.u^.globalsymtable)^.next:=symtablestack;
symtablestack:=psymtable(hp^.u^.globalsymtable);
{$ifdef CHAINPROCSYMS}
symtablestack^.chainprocsyms;
{$endif CHAINPROCSYMS}
@ -540,13 +554,43 @@ unit pmodules;
end;
procedure gen_main_procsym(const name:string;options:longint;st:psymtable);
begin
{Generate a procsym for main}
make_ref:=false;
aktprocsym:=new(Pprocsym,init(name));
aktprocsym^.definition:=new(Pprocdef,init);
aktprocsym^.definition^.options:=aktprocsym^.definition^.options or options;
aktprocsym^.definition^.setmangledname(target_os.cprefix+name);
aktprocsym^.definition^.forwarddef:=false;
make_ref:=true;
{ The localst is a local symtable. Change it into the static
symtable }
dispose(aktprocsym^.definition^.localst,done);
aktprocsym^.definition^.localst:=st;
{ and insert the procsym in symtable }
st^.insert(aktprocsym);
{ set some informations about the main program }
with procinfo do
begin
retdef:=voiddef;
_class:=nil;
call_offset:=8;
framepointer:=frame_pointer;
flags:=0;
end;
end;
procedure proc_unit;
var
{ unitname : stringid; }
names : Tstringcontainer;
p : psymtable;
st : psymtable;
unitst : punitsymtable;
{$ifdef GDB}
pu : pused_unit;
{$endif GDB}
i : longint;
s1,s2 : ^string; {Saves stack space}
begin
@ -604,9 +648,11 @@ unit pmodules;
parse_only:=true;
{ generate now the global symboltable }
p:=new(punitsymtable,init(globalsymtable,current_module^.modulename^));
refsymtable:=p;
unitst:=punitsymtable(p);
st:=new(punitsymtable,init(globalsymtable,current_module^.modulename^));
refsymtable:=st;
unitst:=punitsymtable(st);
{ define first as local to overcome dependency conflicts }
current_module^.localsymtable:=st;
{ the unit name must be usable as a unit specifier }
{ inside the unit itself (PM) }
@ -638,21 +684,24 @@ unit pmodules;
unitst^.symtabletype:=globalsymtable;
end;
{ ... but insert the symbol table later }
p^.next:=symtablestack;
symtablestack:=p;
st^.next:=symtablestack;
symtablestack:=st;
end
else
{ while compiling a system unit, some types are directly inserted }
begin
p^.next:=symtablestack;
symtablestack:=p;
insert_intern_types(p);
st^.next:=symtablestack;
symtablestack:=st;
insert_intern_types(st);
end;
{ displaced for inter-dependency considerations }
current_module^.symtable:=psymtable(p);
{ now we know the place to insert the constants }
constsymtable:=symtablestack;
{ move the global symtab from the temporary local to global }
current_module^.globalsymtable:=current_module^.localsymtable;
current_module^.localsymtable:=nil;
{ ... parse the declarations }
read_interface_declarations;
@ -674,20 +723,8 @@ unit pmodules;
parse_only:=false;
{ generates static symbol table }
p:=new(punitsymtable,init(staticsymtable,current_module^.modulename^));
{Generate a procsym.}
make_ref:=false;
aktprocsym:=new(Pprocsym,init(current_module^.modulename^+'_init'));
aktprocsym^.definition:=new(Pprocdef,init);
aktprocsym^.definition^.options:=aktprocsym^.definition^.options or pounitinit;
aktprocsym^.definition^.setmangledname(current_module^.modulename^+'_init');
make_ref:=true;
{The generated procsym has a local symtable. Discard it and turn
it into the static one.}
dispose(aktprocsym^.definition^.localst,done);
aktprocsym^.definition^.localst:=p;
st:=new(punitsymtable,init(staticsymtable,current_module^.modulename^));
current_module^.localsymtable:=st;
{ remove the globalsymtable from the symtable stack }
{ to reinsert it after loading the implementation units }
@ -698,7 +735,7 @@ unit pmodules;
{$ifdef UseBrowser}
refsymtable^.number_symbols;
{ we don't want implementation units symbols in unitsymtable !! PM }
refsymtable:=p;
refsymtable:=st;
{$endif UseBrowser}
{ Read the implementation units }
parse_implementation_uses(unitst);
@ -707,7 +744,7 @@ unit pmodules;
numberunits;
{ now we can change refsymtable }
refsymtable:=p;
refsymtable:=st;
{ but reinsert the global symtable as lasts }
unitst^.next:=symtablestack;
@ -729,78 +766,81 @@ unit pmodules;
allow_special:=false;
{$endif Splitheap}
{ set some informations }
procinfo.retdef:=voiddef;
procinfo._class:=nil;
procinfo.call_offset:=8;
{ for temporary values }
procinfo.framepointer:=frame_pointer;
{ clear flags }
procinfo.flags:=0;
{ Create a new procedure }
codegen_newprocedure;
{ Generate a procsym }
gen_main_procsym(current_module^.modulename^+'_init',pounitinit,st);
{ Compile the unit }
names.init;
names.insert(current_module^.modulename^+'_init');
names.insert('INIT$$'+current_module^.modulename^);
compile_proc_body(names,true,false);
names.done;
{ Shutdown the codegen for this procedure }
codegen_doneprocedure;
{$ifdef dummy}
if token=_FINALIZATION then
begin
current_module^.flags:=current_module^.flags or uf_finalize;
{ clear flags }
procinfo.flags:=0;
{Reset the codegenerator.}
codegen_newprocedure;
names.init;
names.insert(current_module^.modulename^+'_finalize');
names.insert('FINALIZE$$'+current_module^.modulename^);
names.insert('INIT$$'+current_module^.modulename^);
names.insert(target_os.cprefix+current_module^.modulename^+'_init');
compile_proc_body(names,true,false);
names.done;
codegen_doneprocedure;
end;
{$endif dummy}
consume(POINT);
{ size of the static data }
datasize:=symtablestack^.datasize;
{ avoid self recursive destructor call !! PM }
aktprocsym^.definition^.localst:=nil;
{ unsed static symbols ? }
symtablestack^.allsymbolsused;
{ finalize? }
if token=_FINALIZATION then
begin
{ set module options }
current_module^.flags:=current_module^.flags or uf_finalize;
{ Generate a procsym }
gen_main_procsym(current_module^.modulename^+'_finalize',pounitfinalize,st);
{ Compile the finalize }
codegen_newprocedure;
names.init;
names.insert('FINALIZE$$'+current_module^.modulename^);
names.insert(target_os.cprefix+current_module^.modulename^+'_finalize');
compile_proc_body(names,true,false);
names.done;
codegen_doneprocedure;
{ avoid self recursive destructor call !! PM }
aktprocsym^.definition^.localst:=nil;
end;
{ the last char should always be a point }
consume(POINT);
{ test static symtable }
st^.allsymbolsused;
{ size of the static data }
datasize:=st^.datasize;
{$ifdef GDB}
{ add all used definitions even for implementation}
if (cs_debuginfo in aktmoduleswitches) then
begin
{ all types }
punitsymtable(symtablestack)^.concattypestabto(debuglist);
punitsymtable(st)^.concattypestabto(debuglist);
{ and all local symbols}
symtablestack^.concatstabto(debuglist);
st^.concatstabto(debuglist);
end;
{$endif GDB}
current_module^.in_implementation:=false;
{ deletes all symtables generated in the implementation part }
{ deletes all symtables generated in the implementation part
This could not ever happen, the static symtable is never
inserted in the symtablestack (PFV)
while symtablestack^.symtabletype<>globalsymtable do
if cs_local_browser in aktmoduleswitches then
symtablestack:=symtablestack^.next
else
dellexlevel;
dellexlevel; }
{ tests, if all forwards are resolved }
{ remove static symtable here to save some mem ;) }
dispose(st,done);
current_module^.localsymtable:=nil;
{ tests, if all (interface) forwards are resolved }
symtablestack^.check_forwards;
{ now we have a correct unit, change the symtable type }
current_module^.in_implementation:=false;
symtablestack^.symtabletype:=unitsymtable;
{$ifdef GDB}
punitsymtable(symtablestack)^.is_stab_written:=false;
@ -833,7 +873,7 @@ unit pmodules;
pu:=pused_unit(usedunits.first);
while assigned(pu) do
begin
punitsymtable(pu^.u^.symtable)^.is_stab_written:=false;
punitsymtable(pu^.u^.globalsymtable)^.is_stab_written:=false;
pu:=pused_unit(pu^.next);
end;
{$endif GDB}
@ -889,7 +929,7 @@ unit pmodules;
{ insert after the unit symbol tables the static symbol table }
{ of the program }
st:=new(punitsymtable,init(staticsymtable,current_module^.modulename^));
current_module^.symtable:=st;
current_module^.localsymtable:=st;
symtablestack:=st;
refsymtable:=st;
@ -899,19 +939,6 @@ unit pmodules;
{ load standard units (system,objpas unit) }
loaddefaultunits;
{Generate a procsym for main}
make_ref:=false;
aktprocsym:=new(Pprocsym,init('main'));
aktprocsym^.definition:=new(Pprocdef,init);
aktprocsym^.definition^.options:=aktprocsym^.definition^.options or poproginit;
aktprocsym^.definition^.setmangledname(target_os.Cprefix+'main');
make_ref:=true;
{The localst is a local symtable. Change it into the static
symtable.}
dispose(aktprocsym^.definition^.localst,done);
aktprocsym^.definition^.localst:=st;
{ reset }
lexlevel:=0;
@ -927,23 +954,16 @@ unit pmodules;
{ the elements of enumeration types are inserted }
constsymtable:=st;
{ set some informations about the main program }
with procinfo do
begin
retdef:=voiddef;
_class:=nil;
call_offset:=8;
framepointer:=frame_pointer;
flags:=0;
end;
{ Generate a procsym for main }
gen_main_procsym('main',poproginit,st);
{ reset }
procprefix:='';
in_except_block:=false;
codegen_newprocedure;
{The program intialization needs an alias, so it can be called
from the bootstrap code.}
codegen_newprocedure;
names.init;
names.insert('program_init');
names.insert('PASCALMAIN');
@ -954,12 +974,12 @@ unit pmodules;
{$endif}
compile_proc_body(names,true,false);
names.done;
codegen_doneprocedure;
{ avoid self recursive destructor call !! PM }
aktprocsym^.definition^.localst:=nil;
codegen_doneprocedure;
{ consume the last point }
consume(POINT);
{ leave when we got an error }
@ -1002,7 +1022,11 @@ unit pmodules;
end.
{
$Log$
Revision 1.60 1998-10-06 17:16:54 pierre
Revision 1.61 1998-10-08 13:48:47 peter
* fixed memory leaks for do nothing source
* fixed unit interdependency
Revision 1.60 1998/10/06 17:16:54 pierre
* some memory leaks fixed (thanks to Peter for heaptrc !)
Revision 1.59 1998/10/05 21:33:26 peter

View File

@ -321,7 +321,7 @@
begin
tsym.load;
typ:=unitsym;
unitsymtable:=punitsymtable(current_module^.symtable);
unitsymtable:=punitsymtable(current_module^.globalsymtable);
prevsym:=nil;
end;
@ -1719,7 +1719,11 @@
{
$Log$
Revision 1.50 1998-10-06 17:16:56 pierre
Revision 1.51 1998-10-08 13:48:50 peter
* fixed memory leaks for do nothing source
* fixed unit interdependency
Revision 1.50 1998/10/06 17:16:56 pierre
* some memory leaks fixed (thanks to Peter for heaptrc !)
Revision 1.49 1998/10/01 09:22:55 peter