fpc/compiler/pmodules.pas
2000-01-16 22:17:11 +00:00

1774 lines
62 KiB
ObjectPascal

{
$Id$
Copyright (c) 1998-2000 by Florian Klaempfl
Handles the parsing and loading of the modules (ppufiles)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
unit pmodules;
{ close old_current_ppu on system that are
short on file handles like DOS system PM }
{$ifdef GO32V1}
{$define SHORT_ON_FILE_HANDLES}
{$endif GO32V1}
{$ifdef GO32V2}
{$define SHORT_ON_FILE_HANDLES}
{$endif GO32V2}
{$define New_GDB}
interface
procedure proc_unit;
procedure proc_program(islibrary : boolean);
implementation
uses
globtype,version,systems,tokens,
cobjects,comphook,compiler,
globals,verbose,files,
symconst,symtable,aasm,
{$ifdef newcg}
cgbase,
{$else newcg}
hcodegen,
{$endif newcg}
link,assemble,import,export,gendef,ppu,comprsrc,
cresstr,cpubase,cpuasm,
{$ifdef GDB}
gdb,
{$endif GDB}
scanner,pbase,psystem,pdecl,psub,parser;
procedure create_objectfile;
begin
{ create the .s file and assemble it }
GenerateAsm(false);
{ Also create a smartlinked version ? }
if (cs_create_smart in aktmoduleswitches) then
begin
{ regenerate the importssection for win32 }
if assigned(importssection) and
(target_info.target=target_i386_win32) then
begin
importssection^.clear;
importlib^.generatesmartlib;
end;
GenerateAsm(true);
if target_asm.needar then
Linker^.MakeStaticLibrary;
end;
{ resource files }
CompileResourceFiles;
end;
procedure insertobjectfile;
{ Insert the used object file for this unit in the used list for this unit }
begin
current_module^.linkunitofiles.insert(current_module^.objfilename^,link_static);
current_module^.flags:=current_module^.flags or uf_static_linked;
if (cs_create_smart in aktmoduleswitches) then
begin
current_module^.linkunitstaticlibs.insert(current_module^.staticlibfilename^,link_smart);
current_module^.flags:=current_module^.flags or uf_smart_linked;
end;
end;
procedure insertsegment;
procedure fixseg(p:paasmoutput;sec:tsection);
begin
p^.insert(new(pai_section,init(sec)));
if (cs_create_smart in aktmoduleswitches) then
p^.insert(new(pai_cut,init));
p^.concat(new(pai_section,init(sec_none)));
end;
begin
{ Insert Ident of the compiler }
if (not (cs_create_smart in aktmoduleswitches))
{$ifndef EXTDEBUG}
and (not current_module^.is_unit)
{$endif}
then
begin
datasegment^.insert(new(pai_align,init(4)));
datasegment^.insert(new(pai_string,init('FPC '+full_version_string+
' ['+date_string+'] for '+target_cpu_string+' - '+target_info.short_name)));
end;
{ finish codesegment }
codesegment^.concat(new(pai_align,init(16)));
{ Insert start and end of sections }
fixseg(codesegment,sec_code);
fixseg(datasegment,sec_data);
fixseg(bsssegment,sec_bss);
{ we should use .rdata section for these two no ? }
{ .rdata is a read only data section (PM) }
fixseg(rttilist,sec_data);
fixseg(consts,sec_data);
if assigned(resourcestringlist) then
fixseg(resourcestringlist,sec_data);
{$ifdef GDB}
if assigned(debuglist) then
begin
debuglist^.insert(new(pai_symbol,initname('gcc2_compiled',0)));
fixseg(debuglist,sec_code);
end;
{$endif GDB}
end;
Procedure InsertResourceTablesTable;
var
hp : pused_unit;
ResourceStringTables : taasmoutput;
count : longint;
begin
ResourceStringTables.init;
count:=0;
hp:=pused_unit(usedunits.first);
while assigned(hp) do
begin
If (hp^.u^.flags and uf_has_resources)=uf_has_resources then
begin
ResourceStringTables.concat(new(pai_const_symbol,initname(hp^.u^.modulename^+'_RESOURCESTRINGLIST')));
inc(count);
end;
hp:=Pused_unit(hp^.next);
end;
{ Add program resources, if any }
If ResourceStringList<>Nil then
begin
ResourceStringTables.concat(new(pai_const_symbol,initname(Current_Module^.modulename^+'_RESOURCESTRINGLIST')));
Inc(Count);
end;
{ TableCount }
{ doesn't work because of bug in the compiler !! (JM)
With ResourceStringTables do}
begin
ResourceStringTables.insert(new(pai_const,init_32bit(count)));
ResourceStringTables.insert(new(pai_symbol,initname_global('FPC_RESOURCESTRINGTABLES',0)));
ResourceStringTables.concat(new(pai_symbol_end,initname('FPC_RESOURCESTRINGTABLES')));
end;
{ insert in data segment }
if (cs_create_smart in aktmoduleswitches) then
datasegment^.concat(new(pai_cut,init));
datasegment^.concatlist(@ResourceStringTables);
ResourceStringTables.done;
end;
procedure InsertInitFinalTable;
var
hp : pused_unit;
unitinits : taasmoutput;
count : longint;
begin
unitinits.init;
count:=0;
hp:=pused_unit(usedunits.first);
while assigned(hp) do
begin
{ call the unit init code and make it external }
if (hp^.u^.flags and (uf_init or uf_finalize))<>0 then
begin
if (hp^.u^.flags and uf_init)<>0 then
begin
unitinits.concat(new(pai_const_symbol,initname('INIT$$'+hp^.u^.modulename^)));
end
else
unitinits.concat(new(pai_const,init_32bit(0)));
if (hp^.u^.flags and uf_finalize)<>0 then
begin
unitinits.concat(new(pai_const_symbol,initname('FINALIZE$$'+hp^.u^.modulename^)));
end
else
unitinits.concat(new(pai_const,init_32bit(0)));
inc(count);
end;
hp:=Pused_unit(hp^.next);
end;
if current_module^.islibrary then
if (current_module^.flags and uf_finalize)<>0 then
begin
{ INIT code is done by PASCALMAIN calling }
unitinits.concat(new(pai_const,init_32bit(0)));
unitinits.concat(new(pai_const_symbol,initname('FINALIZE$$'+current_module^.modulename^)));
inc(count);
end;
{ TableCount,InitCount }
unitinits.insert(new(pai_const,init_32bit(0)));
unitinits.insert(new(pai_const,init_32bit(count)));
unitinits.insert(new(pai_symbol,initname_global('INITFINAL',0)));
unitinits.concat(new(pai_symbol_end,initname('INITFINAL')));
{ insert in data segment }
if (cs_create_smart in aktmoduleswitches) then
datasegment^.concat(new(pai_cut,init));
datasegment^.concatlist(@unitinits);
unitinits.done;
end;
procedure insertheap;
begin
if (cs_create_smart in aktmoduleswitches) then
begin
bsssegment^.concat(new(pai_cut,init));
datasegment^.concat(new(pai_cut,init));
end;
{ On the Macintosh Classic M68k Architecture
The Heap variable is simply a POINTER to the
real HEAP. The HEAP must be set up by the RTL
and must store the pointer in this value.
On OS/2 the heap is also intialized by the RTL. We do
not output a pointer }
case target_info.target of
{$ifdef i386}
target_i386_OS2:
;
{$endif i386}
{$ifdef alpha}
target_alpha_linux:
;
{$endif alpha}
{$ifdef powerpc}
target_powerpc_linux:
;
{$endif powerpc}
{$ifdef m68k}
target_m68k_Mac:
bsssegment^.concat(new(pai_datablock,init_global('HEAP',4)));
target_m68k_PalmOS:
;
{$endif m68k}
else
bsssegment^.concat(new(pai_datablock,init_global('HEAP',heapsize)));
end;
{$ifdef m68k}
if target_info.target<>target_m68k_PalmOS then
begin
datasegment^.concat(new(pai_symbol,initname_global('HEAP_SIZE',0)));
datasegment^.concat(new(pai_const,init_32bit(heapsize)));
end;
{$else m68k}
datasegment^.concat(new(pai_symbol,initname_global('HEAPSIZE',4)));
datasegment^.concat(new(pai_const,init_32bit(heapsize)));
{$endif m68k}
end;
procedure inserttargetspecific;
begin
case target_info.target of
{$ifdef alpha}
target_alpha_linux:
;
{$endif alpha}
{$ifdef powerpc}
target_powerpc_linux:
;
{$endif powerpc}
{$ifdef i386}
target_i386_GO32V2 :
begin
{ stacksize can be specified }
datasegment^.concat(new(pai_symbol,initname_global('__stklen',4)));
datasegment^.concat(new(pai_const,init_32bit(stacksize)));
end;
{$endif i386}
{$ifdef m68k}
target_m68k_Atari :
begin
{ stacksize can be specified }
datasegment^.concat(new(pai_symbol,initname_global('__stklen',4)));
datasegment^.concat(new(pai_const,init_32bit(stacksize)));
end;
{$endif m68k}
end;
end;
function loadunit(const s : string;compile_system:boolean) : pmodule;forward;
procedure load_usedunits(compile_system:boolean);
var
pu : pused_unit;
loaded_unit : pmodule;
load_refs : boolean;
nextmapentry : longint;
begin
load_refs:=true;
{ init the map }
new(current_module^.map);
fillchar(current_module^.map^,sizeof(tunitmap),#0);
{$ifdef NEWMAP}
current_module^.map^[0]:=current_module;
{$endif NEWMAP}
nextmapentry:=1;
{ load the used units from interface }
current_module^.in_implementation:=false;
pu:=pused_unit(current_module^.used_units.first);
while assigned(pu) do
begin
if (not pu^.loaded) and (pu^.in_interface) then
begin
loaded_unit:=loadunit(pu^.name^,false);
if current_module^.compiled then
exit;
{ register unit in used units }
pu^.u:=loaded_unit;
pu^.loaded:=true;
{ doubles are not important for that list PM }
pu^.u^.dependent_units.concat(new(pdependent_unit,init(current_module)));
{ need to recompile the current unit ? }
if loaded_unit^.crc<>pu^.checksum then
begin
Message2(unit_u_recompile_crc_change,current_module^.modulename^,pu^.name^);
current_module^.recompile_reason:=rr_crcchanged;
current_module^.do_compile:=true;
dispose(current_module^.map);
current_module^.map:=nil;
exit;
end;
{ setup the map entry for deref }
{$ifndef NEWMAP}
current_module^.map^[nextmapentry]:=loaded_unit^.globalsymtable;
{$else NEWMAP}
current_module^.map^[nextmapentry]:=loaded_unit;
{$endif NEWMAP}
inc(nextmapentry);
if nextmapentry>maxunits then
Message(unit_f_too_much_units);
end;
pu:=pused_unit(pu^.next);
end;
{ ok, now load the unit }
current_module^.globalsymtable:=new(punitsymtable,loadasunit);
{ now only read the implementation part }
current_module^.in_implementation:=true;
{ load the used units from implementation }
pu:=pused_unit(current_module^.used_units.first);
while assigned(pu) do
begin
if (not pu^.loaded) and (not pu^.in_interface) then
begin
loaded_unit:=loadunit(pu^.name^,false);
if current_module^.compiled then
exit;
{ register unit in used units }
pu^.u:=loaded_unit;
pu^.loaded:=true;
{ need to recompile the current unit ? }
if (loaded_unit^.interface_crc<>pu^.interface_checksum) {and
not(current_module^.in_second_compile) } then
begin
Message2(unit_u_recompile_crc_change,current_module^.modulename^,pu^.name^+' {impl}');
current_module^.recompile_reason:=rr_crcchanged;
current_module^.do_compile:=true;
dispose(current_module^.map);
current_module^.map:=nil;
exit;
end;
{ setup the map entry for deref }
{$ifndef NEWMAP}
current_module^.map^[nextmapentry]:=loaded_unit^.globalsymtable;
{$else NEWMAP}
current_module^.map^[nextmapentry]:=loaded_unit;
{$endif NEWMAP}
inc(nextmapentry);
if nextmapentry>maxunits then
Message(unit_f_too_much_units);
end;
pu:=pused_unit(pu^.next);
end;
{ load browser info if stored }
if ((current_module^.flags and uf_has_browser)<>0) and load_refs then
punitsymtable(current_module^.globalsymtable)^.load_symtable_refs;
{ remove the map, it's not needed anymore }
dispose(current_module^.map);
current_module^.map:=nil;
end;
function loadunit(const s : string;compile_system:boolean) : pmodule;
const
ImplIntf : array[boolean] of string[15]=('interface','implementation');
var
st : punitsymtable;
second_time : boolean;
old_current_ppu : pppufile;
old_current_module,hp,hp2 : pmodule;
name : string;{ necessary because current_module^.mainsource^ is reset in compile !! }
scanner : pscannerfile;
procedure loadppufile;
begin
{ load interface section }
if not current_module^.do_compile then
load_interface;
{ only load units when we don't recompile }
if not current_module^.do_compile then
load_usedunits(compile_system);
{ recompile if set }
if current_module^.do_compile then
begin
{ we don't need the ppufile anymore }
if assigned(current_module^.ppufile) then
begin
dispose(current_module^.ppufile,done);
current_module^.ppufile:=nil;
current_ppu:=nil;
end;
{ recompile the unit or give a fatal error if sources not available }
if not(current_module^.sources_avail) then
if (not current_module^.search_unit(current_module^.modulename^,true))
and (length(current_module^.modulename^)>8) then
current_module^.search_unit(copy(current_module^.modulename^,1,8),true);
if not(current_module^.sources_avail) then
begin
if current_module^.recompile_reason=rr_noppu then
Message1(unit_f_cant_find_ppu,current_module^.modulename^)
else
Message1(unit_f_cant_compile_unit,current_module^.modulename^);
end
else
begin
if current_module^.in_compile then
begin
current_module^.in_second_compile:=true;
Message1(parser_d_compiling_second_time,current_module^.modulename^);
end;
current_scanner^.tempcloseinputfile;
name:=current_module^.mainsource^;
if assigned(scanner) then
scanner^.invalid:=true;
compile(name,compile_system);
current_module^.in_second_compile:=false;
if (not current_scanner^.invalid) then
current_scanner^.tempopeninputfile;
end;
end
else
begin
{ only reassemble ? }
if (current_module^.do_assemble) then
OnlyAsm;
end;
if assigned(current_module^.ppufile) then
begin
dispose(current_module^.ppufile,done);
current_module^.ppufile:=nil;
current_ppu:=nil;
end;
end;
var
dummy : pmodule;
begin
old_current_module:=current_module;
old_current_ppu:=current_ppu;
{ Info }
Message3(unit_u_load_unit,current_module^.modulename^,ImplIntf[current_module^.in_implementation],s);
{ unit not found }
st:=nil;
dummy:=nil;
{ search all loaded units }
hp:=pmodule(loaded_units.first);
while assigned(hp) do
begin
if hp^.modulename^=s then
begin
{ forced to reload ? }
if hp^.do_reload then
begin
hp^.do_reload:=false;
break;
end;
{ the unit is already registered }
{ and this means that the unit }
{ is already compiled }
{ else there is a cyclic unit use }
if assigned(hp^.globalsymtable) then
st:=punitsymtable(hp^.globalsymtable)
else
begin
{ both units in interface ? }
if (not current_module^.in_implementation) and (not hp^.in_implementation) then
begin
{ check for a cycle }
hp2:=current_module^.loaded_from;
while assigned(hp2) and (hp2<>hp) do
begin
if hp2^.in_implementation then
hp2:=nil
else
hp2:=hp2^.loaded_from;
end;
if assigned(hp2) then
Message2(unit_f_circular_unit_reference,current_module^.modulename^,hp^.modulename^);
end;
end;
break;
end
else if copy(hp^.modulename^,1,8)=s then
dummy:=hp;
{ the next unit }
hp:=pmodule(hp^.next);
end;
if assigned(dummy) and not assigned(hp) then
Message2(unit_w_unit_name_error,s,dummy^.modulename^);
{ the unit is not in the symtable stack }
if (not assigned(st)) then
begin
if assigned(hp) then
begin
{ remove the old unit }
loaded_units.remove(hp);
scanner:=hp^.scanner;
hp^.reset;
hp^.scanner:=scanner;
{ try to reopen ppu }
hp^.search_unit(s,false);
{ try to load the unit a second time first }
current_module:=hp;
current_module^.in_second_load:=true;
Message1(unit_u_second_load_unit,current_module^.modulename^);
second_time:=true;
end
else
{ generates a new unit info record }
begin
current_module:=new(pmodule,init(s,true));
scanner:=nil;
second_time:=false;
end;
current_ppu:=current_module^.ppufile;
{ close old_current_ppu on system that are
short on file handles like DOS PM }
{$ifdef SHORT_ON_FILE_HANDLES}
if assigned(old_current_ppu) then
old_current_ppu^.tempclose;
{$endif SHORT_ON_FILE_HANDLES}
{ now we can register the unit }
current_module^.loaded_from:=old_current_module;
loaded_units.insert(current_module);
{ now realy load the ppu }
loadppufile;
{ set compiled flag }
current_module^.compiled:=true;
{ load return pointer }
hp:=current_module;
{ for a second_time recompile reload all dependent units,
for a first time compile register the unit _once_ }
if second_time then
begin
{ now reload all dependent units }
hp2:=pmodule(loaded_units.first);
while assigned(hp2) do
begin
if hp2^.do_reload then
dummy:=loadunit(hp2^.modulename^,false);
hp2:=pmodule(hp2^.next);
end;
end
else
usedunits.concat(new(pused_unit,init(current_module,true)));
end;
{ set the old module }
{$ifdef SHORT_ON_FILE_HANDLES}
if assigned(old_current_ppu) then
old_current_ppu^.tempopen;
{$endif SHORT_ON_FILE_HANDLES}
current_ppu:=old_current_ppu;
current_module:=old_current_module;
loadunit:=hp;
end;
procedure loaddefaultunits;
var
hp : pmodule;
begin
{ are we compiling the system unit? }
if (cs_compilesystem in aktmoduleswitches) then
begin
{ create system defines }
createconstdefs;
{ we don't need to reset anything, it's already done in parser.pas }
exit;
end;
{ insert the system unit, it is allways the first }
hp:=loadunit(upper(target_info.system_unit),true);
systemunit:=hp^.globalsymtable;
{ it's always the first unit }
systemunit^.next:=nil;
symtablestack:=systemunit;
{ add to the used units }
current_module^.used_units.concat(new(pused_unit,init(hp,true)));
refsymtable^.insert(new(punitsym,init('SYSTEM',systemunit)));
{ read default constant definitions }
make_ref:=false;
readconstdefs;
{ if POWER is defined in the RTL then use it for starstar overloading }
getsym('POWER',false);
make_ref:=true;
if assigned(srsym) and (srsym^.typ=procsym) and (overloaded_operators[_STARSTAR]=nil) then
overloaded_operators[_STARSTAR]:=pprocsym(srsym);
{ Objpas unit? }
if m_objpas in aktmodeswitches then
begin
hp:=loadunit('OBJPAS',false);
psymtable(hp^.globalsymtable)^.next:=symtablestack;
symtablestack:=hp^.globalsymtable;
{ add to the used units }
current_module^.used_units.concat(new(pused_unit,init(hp,true)));
refsymtable^.insert(new(punitsym,init('OBJPAS',hp^.globalsymtable)));
end;
{ Profile unit? Needed for go32v2 only }
if (cs_profile in aktmoduleswitches) and (target_info.target=target_i386_go32v2) then
begin
hp:=loadunit('PROFILE',false);
psymtable(hp^.globalsymtable)^.next:=symtablestack;
symtablestack:=hp^.globalsymtable;
{ add to the used units }
current_module^.used_units.concat(new(pused_unit,init(hp,true)));
refsymtable^.insert(new(punitsym,init('PROFILE',hp^.globalsymtable)));
end;
{ Heaptrc unit? (not needed for units), this is here to be sure that it is really
loaded as first unit }
if (cs_gdb_heaptrc in aktglobalswitches) and not(current_module^.is_unit)then
begin
hp:=loadunit('HEAPTRC',false);
psymtable(hp^.globalsymtable)^.next:=symtablestack;
symtablestack:=hp^.globalsymtable;
{ add to the used units }
current_module^.used_units.concat(new(pused_unit,init(hp,true)));
refsymtable^.insert(new(punitsym,init('HEAPTRC',hp^.globalsymtable)));
end;
{ save default symtablestack }
defaultsymtablestack:=symtablestack;
end;
procedure loadunits;
var
s : stringid;
pu,
hp : pused_unit;
hp2 : pmodule;
hp3 : psymtable;
oldprocsym:Pprocsym;
begin
oldprocsym:=aktprocsym;
consume(_USES);
{$ifdef DEBUG}
test_symtablestack;
{$endif DEBUG}
repeat
s:=pattern;
consume(_ID);
{ Give a warning if objpas is loaded }
if s='OBJPAS' then
Message(parser_w_no_objpas_use_mode);
{ check if the unit is already used }
pu:=pused_unit(current_module^.used_units.first);
while assigned(pu) do
begin
if (pu^.name^=s) then
break;
pu:=pused_unit(pu^.next);
end;
{ avoid uses of itself }
if not assigned(pu) and (s<>current_module^.modulename^) then
begin
{ load the unit }
hp2:=loadunit(s,false);
{ the current module uses the unit hp2 }
current_module^.used_units.concat(new(pused_unit,init(hp2,not current_module^.in_implementation)));
pused_unit(current_module^.used_units.last)^.in_uses:=true;
if current_module^.compiled then
exit;
refsymtable^.insert(new(punitsym,init(s,hp2^.globalsymtable)));
end
else
Message1(sym_e_duplicate_id,s);
if token=_COMMA then
begin
pattern:='';
consume(_COMMA);
end
else
break;
until false;
consume(_SEMICOLON);
{ set the symtable to systemunit so it gets reorderd correctly }
symtablestack:=defaultsymtablestack;
{ now insert the units in the symtablestack }
hp:=pused_unit(current_module^.used_units.first);
while assigned(hp) do
begin
{$IfDef GDB}
if (cs_debuginfo in aktmoduleswitches) and
(cs_gdb_dbx in aktglobalswitches) and
not hp^.is_stab_written then
begin
punitsymtable(hp^.u^.globalsymtable)^.concattypestabto(debuglist);
hp^.is_stab_written:=true;
hp^.unitid:=psymtable(hp^.u^.globalsymtable)^.unitid;
end;
{$EndIf GDB}
if hp^.in_uses then
begin
hp3:=symtablestack;
while assigned(hp3) do
begin
{ insert units only once ! }
if hp^.u^.globalsymtable=hp3 then
break;
hp3:=hp3^.next;
{ unit isn't inserted }
if hp3=nil then
begin
psymtable(hp^.u^.globalsymtable)^.next:=symtablestack;
symtablestack:=psymtable(hp^.u^.globalsymtable);
{$ifdef CHAINPROCSYMS}
symtablestack^.chainprocsyms;
{$endif CHAINPROCSYMS}
{$ifdef DEBUG}
test_symtablestack;
{$endif DEBUG}
end;
end;
end;
hp:=pused_unit(hp^.next);
end;
aktprocsym:=oldprocsym;
end;
procedure write_gdb_info;
{$IfDef GDB}
var
hp : pused_unit;
begin
if not (cs_debuginfo in aktmoduleswitches) then
exit;
if (cs_gdb_dbx in aktglobalswitches) then
begin
debuglist^.concat(new(pai_asm_comment,init(strpnew('EINCL of global '+
punitsymtable(current_module^.globalsymtable)^.name^+' has index '+
tostr(punitsymtable(current_module^.globalsymtable)^.unitid)))));
debuglist^.concat(new(pai_stabs,init(strpnew('"'+
punitsymtable(current_module^.globalsymtable)^.name^+'",'+
tostr(N_EINCL)+',0,0,0'))));
punitsymtable(current_module^.globalsymtable)^.dbx_count_ok:=true;
dbx_counter:=punitsymtable(current_module^.globalsymtable)^.prev_dbx_counter;
do_count_dbx:=false;
end;
{ now insert the units in the symtablestack }
hp:=pused_unit(current_module^.used_units.first);
while assigned(hp) do
begin
if (cs_debuginfo in aktmoduleswitches) and
not hp^.is_stab_written then
begin
punitsymtable(hp^.u^.globalsymtable)^.concattypestabto(debuglist);
hp^.is_stab_written:=true;
hp^.unitid:=psymtable(hp^.u^.globalsymtable)^.unitid;
end;
hp:=pused_unit(hp^.next);
end;
if current_module^.in_implementation then
begin
if assigned(current_module^.localsymtable) then
begin
{ all types }
punitsymtable(current_module^.localsymtable)^.concattypestabto(debuglist);
{ and all local symbols}
punitsymtable(current_module^.localsymtable)^.concatstabto(debuglist);
end;
end
else
begin
if assigned(current_module^.globalsymtable) then
begin
{ all types }
punitsymtable(current_module^.globalsymtable)^.concattypestabto(debuglist);
{ and all local symbols}
punitsymtable(current_module^.globalsymtable)^.concatstabto(debuglist);
end;
end;
end;
{$Else GDB}
begin
end;
{$EndIf GDB}
procedure parse_implementation_uses(symt:Psymtable);
begin
if token=_USES then
begin
symt^.symtabletype:=unitsymtable;
loadunits;
symt^.symtabletype:=globalsymtable;
{$ifdef DEBUG}
test_symtablestack;
{$endif DEBUG}
end;
end;
procedure setupglobalswitches;
procedure def_symbol(const s:string);
var
mac : pmacrosym;
begin
mac:=new(pmacrosym,init(s));
mac^.defined:=true;
Message1(parser_m_macro_defined,mac^.name);
macros^.insert(mac);
end;
begin
{ can't have local browser when no global browser }
if (cs_local_browser in aktmoduleswitches) and
not(cs_browser in aktmoduleswitches) then
aktmoduleswitches:=aktmoduleswitches-[cs_local_browser];
{ define a symbol in delphi,objfpc,tp,gpc mode }
if (m_delphi in aktmodeswitches) then
def_symbol('FPC_DELPHI')
else
if (m_tp in aktmodeswitches) then
def_symbol('FPC_TP')
else
if (m_objfpc in aktmodeswitches) then
def_symbol('FPC_OBJFPC')
else
if (m_gpc in aktmodeswitches) then
def_symbol('FPC_GPC');
{ turn ansistrings on by default ? }
if (m_default_ansistring in aktmodeswitches) then
aktlocalswitches:=aktlocalswitches+[cs_ansistrings];
end;
procedure gen_main_procsym(const name:string;options:tproctypeoption;st:psymtable);
var
stt : psymtable;
begin
{Generate a procsym for main}
make_ref:=false;
aktprocsym:=new(Pprocsym,init(name));
{ main are allways used }
inc(aktprocsym^.refs);
{Try to insert in in static symtable ! }
stt:=symtablestack;
symtablestack:=st;
aktprocsym^.definition:=new(Pprocdef,init);
symtablestack:=stt;
aktprocsym^.definition^.proctypeoption:=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
returntype.setdef(voiddef);
_class:=nil;
para_offset:=8;
framepointer:=frame_pointer;
flags:=0;
end;
end;
procedure proc_unit;
function is_assembler_generated:boolean;
begin
is_assembler_generated:=(Errorcount=0) and
not(
codesegment^.empty and
datasegment^.empty and
bsssegment^.empty and
((importssection=nil) or importssection^.empty) and
((resourcesection=nil) or resourcesection^.empty) and
((resourcestringlist=nil) or resourcestringlist^.empty)
);
end;
var
{$ifdef fixLeaksOnError}
names : Pstringcontainer;
{$else fixLeaksOnError}
names : Tstringcontainer;
{$endif fixLeaksOnError}
st : psymtable;
unitst : punitsymtable;
{$ifdef GDB}
pu : pused_unit;
{$endif GDB}
{$ifndef Dont_use_double_checksum}
store_crc,store_interface_crc : longint;
{$endif}
s1,s2 : ^string; {Saves stack space}
begin
consume(_UNIT);
if Compile_Level=1 then
IsExe:=false;
if token=_ID then
begin
{ create filenames and unit name }
current_module^.SetFileName(current_scanner^.inputfile^.path^+current_scanner^.inputfile^.name^,true);
stringdispose(current_module^.modulename);
current_module^.modulename:=stringdup(upper(pattern));
{ check for system unit }
new(s1);
new(s2);
s1^:=upper(target_info.system_unit);
s2^:=upper(SplitName(current_scanner^.inputfile^.name^));
if (cs_compilesystem in aktmoduleswitches) then
begin
if ((length(current_module^.modulename^)>8) or
(current_module^.modulename^<>s1^) or
(current_module^.modulename^<>s2^)) then
Message1(unit_e_illegal_unit_name,current_module^.modulename^);
end
else
begin
if (cs_check_unit_name in aktglobalswitches) and
not((current_module^.modulename^=s2^) or
((length(current_module^.modulename^)>8) and
(copy(current_module^.modulename^,1,8)=s2^))) then
Message1(unit_e_illegal_unit_name,current_module^.modulename^);
if (current_module^.modulename^=s1^) then
Message(unit_w_switch_us_missed);
end;
dispose(s2);
dispose(s1);
end;
consume(_ID);
consume(_SEMICOLON);
consume(_INTERFACE);
{ global switches are read, so further changes aren't allowed }
current_module^.in_global:=false;
{ handle the global switches }
setupglobalswitches;
Message1(unit_u_start_parse_interface,current_module^.modulename^);
{ update status }
status.currentmodule:=current_module^.modulename^;
{ maybe turn off m_objpas if we are compiling objpas }
if (current_module^.modulename^='OBJPAS') then
aktmodeswitches:=aktmodeswitches-[m_objpas];
{ this should be placed after uses !!}
{$ifndef UseNiceNames}
procprefix:='_'+current_module^.modulename^+'$$';
{$else UseNiceNames}
procprefix:='_'+tostr(length(current_module^.modulename^))+lowercase(current_module^.modulename^)+'_';
{$endif UseNiceNames}
parse_only:=true;
{ generate now the global symboltable }
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) }
{ this also forbids to have another symbol }
{ with the same name as the unit }
refsymtable^.insert(new(punitsym,init(current_module^.modulename^,unitst)));
{ a unit compiled at command line must be inside the loaded_unit list }
if (compile_level=1) then
loaded_units.insert(current_module);
{ load default units, like the system unit }
loaddefaultunits;
{ reset }
make_ref:=true;
lexlevel:=0;
{ insert qualifier for the system unit (allows system.writeln) }
if not(cs_compilesystem in aktmoduleswitches) then
begin
if token=_USES then
begin
unitst^.symtabletype:=unitsymtable;
loadunits;
{ has it been compiled at a higher level ?}
if current_module^.compiled then
begin
{ this unit symtable is obsolete }
{ dispose(unitst,done);
disposed as localsymtable !! }
exit;
end;
unitst^.symtabletype:=globalsymtable;
end;
{ ... but insert the symbol table later }
st^.next:=symtablestack;
symtablestack:=st;
end
else
{ while compiling a system unit, some types are directly inserted }
begin
st^.next:=symtablestack;
symtablestack:=st;
insert_intern_types(st);
end;
{ 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;
reset_global_defs;
{ number all units, so we know if a unit is used by this unit or
needs to be added implicitly }
numberunits;
{ ... parse the declarations }
Message1(parser_u_parsing_interface,current_module^.modulename^);
read_interface_declarations;
{ leave when we got an error }
if (Errorcount>0) and not status.skip_error then
begin
Message1(unit_f_errors_in_unit,tostr(Errorcount));
status.skip_error:=true;
exit;
end;
{$ifdef New_GDB}
write_gdb_info;
{$endIf Def New_GDB}
{$ifndef Dont_use_double_checksum}
if not(cs_compilesystem in aktmoduleswitches) then
if (Errorcount=0) then
writeunitas(current_module^.ppufilename^,punitsymtable(symtablestack),true);
{$endif Test_Double_checksum}
{ Parse the implementation section }
consume(_IMPLEMENTATION);
current_module^.in_implementation:=true;
Message1(unit_u_start_parse_implementation,current_module^.modulename^);
parse_only:=false;
{ generates static symbol table }
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 }
symtablestack:=unitst^.next;
{ we don't want implementation units symbols in unitsymtable !! PM }
refsymtable:=st;
{ Read the implementation units }
parse_implementation_uses(unitst);
if current_module^.compiled then
begin
exit;
end;
{ reset ranges/stabs in exported definitions }
reset_global_defs;
{ All units are read, now give them a number }
numberunits;
{ now we can change refsymtable }
refsymtable:=st;
{ but reinsert the global symtable as lasts }
unitst^.next:=symtablestack;
symtablestack:=unitst;
{$ifdef DEBUG}
test_symtablestack;
{$endif DEBUG}
constsymtable:=symtablestack;
{$ifdef Splitheap}
if testsplit then
begin
Split_Heap;
allow_special:=true;
Switch_to_temp_heap;
end;
{ it will report all crossings }
allow_special:=false;
{$endif Splitheap}
Message1(parser_u_parsing_implementation,current_module^.modulename^);
{ Compile the unit }
codegen_newprocedure;
gen_main_procsym(current_module^.modulename^+'_init',potype_unitinit,st);
{$ifdef fixLeaksOnError}
new(names,init);
strContStack.push(names);
names^.insert('INIT$$'+current_module^.modulename^);
names^.insert(target_os.cprefix+current_module^.modulename^+'_init');
compile_proc_body(names^,true,false);
if names <> PstringContainer(strContStack.pop) then
writeln('Problem with strContStack in pmodules (1)');
dispose(names,done);
{$else fixLeaksOnError}
names.init;
names.insert('INIT$$'+current_module^.modulename^);
names.insert(target_os.cprefix+current_module^.modulename^+'_init');
compile_proc_body(names,true,false);
names.done;
{$endif fixLeaksOnError}
codegen_doneprocedure;
{ avoid self recursive destructor call !! PM }
aktprocsym^.definition^.localst:=nil;
{ finalize? }
if token=_FINALIZATION then
begin
{ set module options }
current_module^.flags:=current_module^.flags or uf_finalize;
{ Compile the finalize }
codegen_newprocedure;
gen_main_procsym(current_module^.modulename^+'_finalize',potype_unitfinalize,st);
{$ifdef fixLeaksOnError}
new(names,init);
strContStack.push(names);
names^.insert('FINALIZE$$'+current_module^.modulename^);
names^.insert(target_os.cprefix+current_module^.modulename^+'_finalize');
compile_proc_body(names^,true,false);
if names <> PstringContainer(strContStack.pop) then
writeln('Problem with strContStack in pmodules (2)');
dispose(names,done);
{$else fixLeaksOnError}
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;
{$endif fixLeaksOnError}
codegen_doneprocedure;
end;
{ the last char should always be a point }
consume(_POINT);
If ResourceStringList<>Nil then
begin
insertresourcestrings;
current_module^.flags:=current_module^.flags or uf_has_resources;
WriteResourceFile(Current_module^.ModuleName^);
end;
{ avoid self recursive destructor call !! PM }
aktprocsym^.definition^.localst:=nil;
{ absence does not matter here !! }
aktprocsym^.definition^.forwarddef:=false;
{ test static symtable }
if (Errorcount=0) then
begin
st^.allsymbolsused;
st^.allprivatesused;
end;
{ size of the static data }
datasize:=st^.datasize;
{$ifdef GDB}
{ add all used definitions even for implementation}
if (cs_debuginfo in aktmoduleswitches) then
begin
{$IfnDef New_GDB}
if assigned(current_module^.globalsymtable) then
begin
{ all types }
punitsymtable(current_module^.globalsymtable)^.concattypestabto(debuglist);
{ and all local symbols}
punitsymtable(current_module^.globalsymtable)^.concatstabto(debuglist);
end;
{ all local types }
punitsymtable(st)^.concattypestabto(debuglist);
{ and all local symbols}
st^.concatstabto(debuglist);
{$else New_GDB}
write_gdb_info;
{$endIf Def New_GDB}
end;
{$endif GDB}
reset_global_defs;
{ tests, if all (interface) forwards are resolved }
if (Errorcount=0) then
begin
symtablestack^.check_forwards;
symtablestack^.allprivatesused;
end;
{ 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;
{$endif GDB}
{ leave when we got an error }
if (Errorcount>0) and not status.skip_error then
begin
Message1(unit_f_errors_in_unit,tostr(Errorcount));
status.skip_error:=true;
exit;
end;
{ generate imports }
if current_module^.uses_imports then
importlib^.generatelib;
{ insert own objectfile, or say that it's in a library
(no check for an .o when loading) }
if is_assembler_generated then
insertobjectfile
else
current_module^.flags:=current_module^.flags or uf_no_link;
if cs_local_browser in aktmoduleswitches then
current_module^.localsymtable:=refsymtable;
{ Write out the ppufile }
{$ifndef Dont_use_double_checksum}
store_interface_crc:=current_module^.interface_crc;
store_crc:=current_module^.crc;
{$endif Test_Double_checksum}
if (Errorcount=0) then
writeunitas(current_module^.ppufilename^,punitsymtable(symtablestack),false);
{$ifndef Dont_use_double_checksum}
if not(cs_compilesystem in aktmoduleswitches) then
if store_interface_crc<>current_module^.interface_crc then
Do_comment(V_Warning,current_module^.ppufilename^+' Interface CRC changed '+
tostr(store_crc)+'<>'+tostr(current_module^.interface_crc));
{$ifdef EXTDEBUG}
if not(cs_compilesystem in aktmoduleswitches) then
if (store_crc<>current_module^.crc) and simplify_ppu then
Do_comment(V_Warning,current_module^.ppufilename^+' implementation CRC changed '+
tostr(store_crc)+'<>'+tostr(current_module^.interface_crc));
{$endif EXTDEBUG}
{$endif ndef Dont_use_Double_checksum}
{ must be done only after local symtable ref stores !! }
closecurrentppu;
{$ifdef GDB}
pu:=pused_unit(usedunits.first);
while assigned(pu) do
begin
if assigned(pu^.u^.globalsymtable) then
punitsymtable(pu^.u^.globalsymtable)^.is_stab_written:=false;
pu:=pused_unit(pu^.next);
end;
{$endif GDB}
{ remove static symtable (=refsymtable) here to save some mem }
if not (cs_local_browser in aktmoduleswitches) then
begin
dispose(st,done);
current_module^.localsymtable:=nil;
end;
if is_assembler_generated then
begin
{ finish asmlist by adding segment starts }
insertsegment;
{ assemble }
create_objectfile;
end;
{ leave when we got an error }
if (Errorcount>0) and not status.skip_error then
begin
Message1(unit_f_errors_in_unit,tostr(Errorcount));
status.skip_error:=true;
exit;
end;
end;
procedure proc_program(islibrary : boolean);
var
st : psymtable;
hp : pmodule;
{$ifdef fixLeaksOnError}
names : Pstringcontainer;
{$else fixLeaksOnError}
names : Tstringcontainer;
{$endif fixLeaksOnError}
begin
DLLsource:=islibrary;
IsExe:=true;
parse_only:=false;
{ relocation works only without stabs under win32 !! PM }
{ internal assembler uses rva for stabs info
so it should work with relocated DLLs }
if RelocSection and
(target_info.target=target_i386_win32) and
(target_info.assem<>as_i386_pecoff) then
begin
aktglobalswitches:=aktglobalswitches+[cs_link_strip];
{ Warning stabs info does not work with reloc section !! }
if cs_debuginfo in aktmoduleswitches then
begin
Message1(parser_w_parser_reloc_no_debug,current_module^.mainsource^);
Message(parser_w_parser_win32_debug_needs_WN);
aktmoduleswitches:=aktmoduleswitches-[cs_debuginfo];
end;
end;
if islibrary then
begin
consume(_LIBRARY);
stringdispose(current_module^.modulename);
current_module^.modulename:=stringdup(pattern);
current_module^.islibrary:=true;
exportlib^.preparelib(pattern);
consume(_ID);
consume(_SEMICOLON);
end
else
{ is there an program head ? }
if token=_PROGRAM then
begin
consume(_PROGRAM);
stringdispose(current_module^.modulename);
current_module^.modulename:=stringdup(pattern);
if (target_info.target=target_i386_WIN32) then
exportlib^.preparelib(pattern);
consume(_ID);
if token=_LKLAMMER then
begin
consume(_LKLAMMER);
idlist;
consume(_RKLAMMER);
end;
consume(_SEMICOLON);
end
else if (target_info.target=target_i386_WIN32) then
exportlib^.preparelib(current_module^.modulename^);
{ global switches are read, so further changes aren't allowed }
current_module^.in_global:=false;
{ get correct output names }
current_module^.SetFileName(current_scanner^.inputfile^.path^+current_scanner^.inputfile^.name^,true);
{ setup things using the global switches }
setupglobalswitches;
{ set implementation flag }
current_module^.in_implementation:=true;
{ insert after the unit symbol tables the static symbol table }
{ of the program }
st:=new(punitsymtable,init(staticsymtable,current_module^.modulename^));
current_module^.localsymtable:=st;
symtablestack:=st;
refsymtable:=st;
{ necessary for browser }
loaded_units.insert(current_module);
{ load standard units (system,objpas,profile unit) }
loaddefaultunits;
{ reset }
lexlevel:=0;
{Load the units used by the program we compile.}
if token=_USES then
loadunits;
{ reset ranges/stabs in exported definitions }
reset_global_defs;
{ All units are read, now give them a number }
numberunits;
{Insert the name of the main program into the symbol table.}
if current_module^.modulename^<>'' then
{st^.insert(new(pprogramsym,init(current_module^.modulename^)));}
st^.insert(new(punitsym,init(current_module^.modulename^,punitsymtable(st))));
{ ...is also constsymtable, this is the symtable where }
{ the elements of enumeration types are inserted }
constsymtable:=st;
Message1(parser_u_parsing_implementation,current_module^.mainsource^);
{ reset }
procprefix:='';
{The program intialization needs an alias, so it can be called
from the bootstrap code.}
codegen_newprocedure;
gen_main_procsym('main',potype_proginit,st);
{$ifdef fixLeaksOnError}
new(names,init);
strContStack.push(names);
names^.insert('program_init');
names^.insert('PASCALMAIN');
names^.insert(target_os.cprefix+'main');
{$ifdef m68k}
if target_info.target=target_m68k_PalmOS then
names^.insert('PilotMain');
{$endif m68k}
compile_proc_body(names^,true,false);
if names <> PstringContainer(strContStack.pop) then
writeln('Problem with strContStack in pmodules (1)');
dispose(names,done);
{$else fixLeaksOnError}
names.init;
names.insert('program_init');
names.insert('PASCALMAIN');
names.insert(target_os.cprefix+'main');
{$ifdef m68k}
if target_info.target=target_m68k_PalmOS then
names.insert('PilotMain');
{$endif m68k}
compile_proc_body(names,true,false);
names.done;
{$endif fixLeaksOnError}
{ avoid self recursive destructor call !! PM }
aktprocsym^.definition^.localst:=nil;
{ consider these symbols as global ones }
{ for browser }
current_module^.globalsymtable:=current_module^.localsymtable;
current_module^.localsymtable:=nil;
If ResourceStringList<>Nil then
begin
insertresourcestrings;
WriteResourceFile(Current_module^.ModuleName^);
end;
codegen_doneprocedure;
{ finalize? }
if token=_FINALIZATION then
begin
{ set module options }
current_module^.flags:=current_module^.flags or uf_finalize;
{ Compile the finalize }
codegen_newprocedure;
gen_main_procsym(current_module^.modulename^+'_finalize',potype_unitfinalize,st);
{$ifdef fixLeaksOnError}
new(names,init);
strContStack.push(names);
names^.insert('FINALIZE$$'+current_module^.modulename^);
names^.insert(target_os.cprefix+current_module^.modulename^+'_finalize');
compile_proc_body(names^,true,false);
if names <> PstringContainer(strContStack.pop) then
writeln('Problem with strContStack in pmodules (1)');
dispose(names,done);
{$else fixLeaksOnError}
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;
{$endif fixLeaksOnError}
codegen_doneprocedure;
end;
{ consume the last point }
consume(_POINT);
{$ifdef New_GDB}
write_gdb_info;
{$endIf Def New_GDB}
{ leave when we got an error }
if (Errorcount>0) and not status.skip_error then
begin
Message1(unit_f_errors_in_unit,tostr(Errorcount));
status.skip_error:=true;
exit;
end;
{ test static symtable }
if (Errorcount=0) then
begin
st^.allsymbolsused;
st^.allprivatesused;
end;
{ generate imports }
if current_module^.uses_imports then
importlib^.generatelib;
if islibrary or
(target_info.target=target_i386_WIN32) then
exportlib^.generatelib;
{ insert heap }
insertResourceTablesTable;
insertinitfinaltable;
insertheap;
inserttargetspecific;
datasize:=symtablestack^.datasize;
{ finish asmlist by adding segment starts }
insertsegment;
{ insert own objectfile }
insertobjectfile;
{ assemble and link }
create_objectfile;
{ leave when we got an error }
if (Errorcount>0) and not status.skip_error then
begin
Message1(unit_f_errors_in_unit,tostr(Errorcount));
status.skip_error:=true;
exit;
end;
{ create the executable when we are at level 1 }
if (compile_level=1) then
begin
{ insert all .o files from all loaded units }
hp:=pmodule(loaded_units.first);
while assigned(hp) do
begin
Linker^.AddModuleFiles(hp);
hp:=pmodule(hp^.next);
end;
{ write .def file }
if (cs_link_deffile in aktglobalswitches) then
deffile.writefile;
{ finally we can create a executable }
if (not current_module^.is_unit) then
begin
if DLLSource then
Linker^.MakeSharedLibrary
else
Linker^.MakeExecutable;
end;
end;
end;
end.
{
$Log$
Revision 1.183 2000-01-16 22:17:12 peter
* renamed call_offset to para_offset
Revision 1.182 2000/01/16 14:15:33 jonas
* changed "with object_type" construct because of bug in the
compiler
Revision 1.181 2000/01/12 10:30:15 peter
* align codesegment at the end after main proc
Revision 1.180 2000/01/11 17:16:05 jonas
* removed a lot of memory leaks when an error is encountered (caused by
procinfo and pstringcontainers). There are still plenty left though :)
Revision 1.179 2000/01/11 09:52:07 peter
* fixed placing of .sl directories
* use -b again for base-file selection
* fixed group writing for linux with smartlinking
Revision 1.178 2000/01/07 01:14:29 peter
* updated copyright to 2000
Revision 1.177 1999/12/20 22:29:26 pierre
* relocation with debug info in rva (only with internal compiler)
Revision 1.176 1999/12/10 10:02:53 peter
* only check relocsection for win32
Revision 1.175 1999/11/30 10:40:44 peter
+ ttype, tsymlist
Revision 1.174 1999/11/29 16:24:52 pierre
* bug in previous commit corrected
Revision 1.173 1999/11/29 15:18:27 pierre
+ allow exports in win32 executables
Revision 1.172 1999/11/24 11:41:05 pierre
* defaultsymtablestack is now restored after parser.compile
Revision 1.171 1999/11/22 22:21:46 pierre
* Compute correct Exe Filenam
Revision 1.170 1999/11/22 00:23:09 pierre
* also complain about unused functions in program
Revision 1.169 1999/11/20 01:19:10 pierre
* DLL index used for win32 target with DEF file
+ DLL initialization/finalization support
Revision 1.168 1999/11/18 23:35:40 pierre
* avoid double warnings
Revision 1.167 1999/11/18 15:34:47 pierre
* Notes/Hints for local syms changed to
Set_varstate function
Revision 1.166 1999/11/17 17:05:02 pierre
* Notes/hints changes
Revision 1.165 1999/11/15 15:03:47 pierre
* Pavel's changes for reloc section in executable
+ warning that -g needs -WN under win32
Revision 1.164 1999/11/09 23:46:00 pierre
* power search for ** operator not in browser
* DBX support work, still does not work !
Revision 1.163 1999/11/09 13:00:37 peter
* define FPC_DELPHI,FPC_OBJFPC,FPC_TP,FPC_GPC
* initial support for ansistring default with modes
Revision 1.162 1999/11/06 14:34:22 peter
* truncated log to 20 revs
Revision 1.161 1999/11/02 15:06:57 peter
* import library fixes for win32
* alignment works again
Revision 1.160 1999/10/21 14:29:37 peter
* redesigned linker object
+ library support for linux (only procedures can be exported)
Revision 1.159 1999/10/12 21:20:45 florian
* new codegenerator compiles again
Revision 1.158 1999/10/03 19:44:42 peter
* removed objpasunit reference, tvarrec is now searched in systemunit
where it already was located
Revision 1.157 1999/09/27 23:44:54 peter
* procinfo is now a pointer
* support for result setting in sub procedure
Revision 1.156 1999/09/20 16:39:00 peter
* cs_create_smart instead of cs_smartlink
* -CX is create smartlink
* -CD is create dynamic, but does nothing atm.
Revision 1.155 1999/09/16 23:05:54 florian
* m68k compiler is again compilable (only gas writer, no assembler reader)
Revision 1.154 1999/09/16 14:18:12 pierre
+ warning if truncate unit name found
Revision 1.153 1999/09/13 22:56:17 peter
* fixed crashes under plain dos
Revision 1.152 1999/09/01 22:18:42 peter
* moved parsing interface/implementation to -vu
Revision 1.151 1999/08/31 15:51:10 pierre
* in_second_compile cleaned up, in_compile and in_second_load added
Revision 1.150 1999/08/30 16:21:40 pierre
* tempclosing of ppufiles under dos was wrong
Revision 1.149 1999/08/28 15:34:19 florian
* bug 519 fixed
Revision 1.148 1999/08/27 14:53:00 pierre
* double checksum problem solved
Revision 1.147 1999/08/27 10:57:56 pierre
+ define SHORT_ON_FILE_HANDLES for DOS targets
causes tempclose of ppufiles
+ double_checksum code released
(you can try with -dDONT_USE_DOUBLE_CHECKSUM to see the difference)
this allow second compilation of compiler without any
unit recompilation !!!!
Revision 1.146 1999/08/26 21:16:21 peter
* write date of the compiler into the executable
Revision 1.145 1999/08/26 20:24:44 michael
+ Hopefuly last fixes for resourcestrings
Revision 1.144 1999/08/24 22:38:53 michael
* more resourcestring changes
Revision 1.143 1999/08/24 12:01:34 michael
+ changes for resourcestrings
Revision 1.142 1999/08/16 15:35:27 pierre
* fix for DLL relocation problems
* external bss vars had wrong stabs for pecoff
+ -WB11000000 to specify default image base, allows to
load several DLLs with debugging info included
(relocatable DLL are stripped because the relocation
of the .Stab section is misplaced by ldw)
}