fpc/compiler/symppu.inc

543 lines
14 KiB
PHP

{
$Id$
Copyright (c) 1993-98 by Florian Klaempfl, Pierre Muller
Implementation of the reading of PPU Files for the symtable
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.
****************************************************************************
}
const
{$ifdef FPC}
ppubufsize=32768;
{$ELSE}
{$IFDEF USEOVERLAY}
ppubufsize=512;
{$ELSE}
ppubufsize=4096;
{$ENDIF}
{$ENDIF}
{*****************************************************************************
PPU Writing
*****************************************************************************}
{$ifdef NEWPPU}
procedure writebyte(b:byte);
begin
ppufile^.putbyte(b);
end;
procedure writeword(w:word);
begin
ppufile^.putword(w);
end;
procedure writelong(l:longint);
begin
ppufile^.putlongint(l);
end;
procedure writedouble(d:double);
begin
ppufile^.putdata(d,sizeof(double));
end;
procedure writestring(const s:string);
begin
ppufile^.putstring(s);
end;
procedure writeset(var s); {You cannot pass an array[0..31] of byte!}
begin
ppufile^.putdata(s,32);
end;
procedure writecontainer(var p:tstringcontainer;id:byte;hold:boolean);
var
hcontainer : tstringcontainer;
s : string;
begin
if hold then
hcontainer.init;
while not p.empty do
begin
s:=p.get;
ppufile^.putstring(s);
if hold then
hcontainer.insert(s);
end;
ppufile^.writeentry(id);
if hold then
p:=hcontainer;
end;
procedure writeposinfo(const p:tfileposinfo);
begin
writeword(p.fileindex);
writelong(p.line);
writeword(p.column);
end;
procedure writedefref(p : pdef);
begin
if p=nil then
ppufile^.putlongint($ffffffff)
else
begin
if (p^.owner^.symtabletype in [recordsymtable,objectsymtable]) then
ppufile^.putword($ffff)
else
ppufile^.putword(p^.owner^.unitid);
ppufile^.putword(p^.number);
end;
end;
{$ifdef UseBrowser}
procedure writesymref(p : psym);
begin
if p=nil then
writelong($ffffffff)
else
begin
if (p^.owner^.symtabletype in [recordsymtable,objectsymtable]) then
writeword($ffff)
else
writeword(p^.owner^.unitid);
writeword(p^.indexnb);
end;
end;
{$endif UseBrowser}
procedure writeunitas(const s : string;unit_symtable : punitsymtable);
{$ifdef UseBrowser}
var
pus : punitsymtable;
{$endif UseBrowser}
begin
Message1(unit_u_ppu_write,s);
{ create unit flags }
with Current_Module^ do
begin
if cs_smartlink in aktswitches then
begin
flags:=flags or uf_smartlink;
if SplitName(ppufilename^)<>SplitName(libfilename^) then
flags:=flags or uf_in_library;
end;
if use_dbx then
flags:=flags or uf_uses_dbx;
if target_os.endian=en_big_endian then
flags:=flags or uf_big_endian;
{$ifdef UseBrowser}
if use_browser then
flags:=flags or uf_uses_browser;
{$endif UseBrowser}
end;
ppufile:=new(pppufile,init(s));
ppufile^.change_endian:=source_os.endian<>target_os.endian;
if not ppufile^.create then
Message(unit_f_ppu_cannot_write);
unit_symtable^.writeasunit;
{$ifdef UseBrowser}
{ write all new references to old unit elements }
pus:=punitsymtable(unit_symtable^.next);
if use_browser then
while assigned(pus) do
begin
if pus^.symtabletype = unitsymtable then
pus^.write_external_references;
pus:=punitsymtable(pus^.next);
end;
{$endif UseBrowser}
ppufile^.flush;
{ create and write header }
ppufile^.header.size:=ppufile^.size;
ppufile^.header.checksum:=ppufile^.crc;
ppufile^.header.compiler:=wordversion;
ppufile^.header.target:=word(target_info.target);
ppufile^.header.flags:=current_module^.flags;
ppufile^.writeheader;
{ save crc in current_module also }
current_module^.crc:=ppufile^.crc;
{ close }
ppufile^.close;
dispose(ppufile,done);
end;
{$else NEWPPU}
procedure writebyte(b:byte);
begin
ppufile.write_data(b,1);
end;
procedure writeword(w:word);
begin
ppufile.write_data(w,2);
end;
procedure writelong(l:longint);
begin
ppufile.write_data(l,4);
end;
procedure writedouble(d:double);
begin
ppufile.write_data(d,sizeof(double));
end;
procedure writestring(s : string);
begin
ppufile.write_data(s,length(s)+1);
end;
procedure writeset(var s); {You cannot pass an array[0..31] of byte!}
begin
ppufile.write_data(s,32);
end;
procedure writecontainer(var p:tstringcontainer;id:byte;hold:boolean);
var
hcontainer : tstringcontainer;
s : string;
begin
if hold then
hcontainer.init;
while not p.empty do
begin
writebyte(id);
s:=p.get;
writestring(s);
if hold then
hcontainer.insert(s);
end;
if hold then
p:=hcontainer;
end;
procedure writeposinfo(const p:tfileposinfo);
begin
writeword(p.fileindex);
writelong(p.line);
writeword(p.column);
end;
procedure writedefref(p : pdef);
begin
if p=nil then
writelong($ffffffff)
else
begin
if (p^.owner^.symtabletype in [recordsymtable,objectsymtable]) then
writeword($ffff)
else
writeword(p^.owner^.unitid);
writeword(p^.number);
end;
end;
{$ifdef UseBrowser}
procedure writesymref(p : psym);
begin
if p=nil then
writelong($ffffffff)
else
begin
if (p^.owner^.symtabletype in [recordsymtable,objectsymtable]) then
writeword($ffff)
else
writeword(p^.owner^.unitid);
writeword(p^.indexnb);
end;
end;
{$endif UseBrowser}
procedure writeunitas(const s : string;unit_symtable : punitsymtable);
{$ifdef UseBrowser}
var
pus : punitsymtable;
{$endif UseBrowser}
begin
Message1(unit_u_ppu_write,s);
{ create unit flags }
with Current_Module^ do
begin
if cs_smartlink in aktswitches then
begin
flags:=flags or uf_smartlink;
if SplitName(ppufilename^)<>SplitName(libfilename^) then
flags:=flags or uf_in_library;
end;
if use_dbx then
flags:=flags or uf_uses_dbx;
if target_os.endian=en_big_endian then
flags:=flags or uf_big_endian;
{$ifdef UseBrowser}
if use_browser then
flags:=flags or uf_uses_browser;
{$endif UseBrowser}
end;
{ open en init ppufile }
ppufile.init(s,ppubufsize);
ppufile.change_endian:=source_os.endian<>target_os.endian;
ppufile.rewrite;
if ioresult<>0 then
Message(unit_f_ppu_cannot_write);
{ create and write header }
unitheader[8]:=char(byte(target_info.target));
unitheader[9]:=char(current_module^.flags);
ppufile.write_data(unitheader,sizeof(unitheader));
ppufile.clear_crc;
ppufile.do_crc:=true;
unit_symtable^.writeasunit;
ppufile.flush;
ppufile.do_crc:=false;
{$ifdef UseBrowser}
{ write all new references to old unit elements }
pus:=punitsymtable(unit_symtable^.next);
if use_browser then
while assigned(pus) do
begin
if pus^.symtabletype = unitsymtable then
pus^.write_external_references;
pus:=punitsymtable(pus^.next);
end;
{$endif UseBrowser}
{ writes the checksum }
ppufile.seek(10);
current_module^.crc:=ppufile.getcrc;
ppufile.write_data(current_module^.crc,4);
ppufile.flush;
ppufile.done;
end;
{$endif NEWPPU}
{*****************************************************************************
PPU Reading
*****************************************************************************}
{$ifdef NEWPPU}
function readbyte:byte;
begin
readbyte:=ppufile^.getbyte;
if ppufile^.error then
Message(unit_f_ppu_read_error);
end;
function readword:word;
begin
readword:=ppufile^.getword;
if ppufile^.error then
Message(unit_f_ppu_read_error);
end;
function readlong:longint;
begin
readlong:=ppufile^.getlongint;
if ppufile^.error then
Message(unit_f_ppu_read_error);
end;
function readdouble : double;
var
d : double;
begin
ppufile^.getdata(d,sizeof(double));
if ppufile^.error then
Message(unit_f_ppu_read_error);
readdouble:=d;
end;
function readstring : string;
begin
readstring:=ppufile^.getstring;
if ppufile^.error then
Message(unit_f_ppu_read_error);
end;
procedure readset(var s); {You cannot pass an array [0..31] of byte.}
begin
ppufile^.getdata(s,32);
if ppufile^.error then
Message(unit_f_ppu_read_error);
end;
procedure readcontainer(var p:tstringcontainer);
begin
while not current_module^.ppufile^.endofentry do
p.insert(current_module^.ppufile^.getstring);
end;
procedure readposinfo(var p:tfileposinfo);
begin
p.fileindex:=readword;
p.line:=readlong;
p.column:=readword;
end;
function readdefref : pdef;
var
hd : pdef;
begin
longint(hd):=readword;
longint(hd):=longint(hd) or (longint(readword) shl 16);
readdefref:=hd;
end;
{$ifdef UseBrowser}
function readsymref : psym;
var
hd : psym;
begin
longint(hd):=readword;
longint(hd):=longint(hd) or (longint(readword) shl 16);
readsymref:=hd;
end;
{$endif}
{$else NEWPPU}
function readbyte : byte;
var
count : longint;
b : byte;
begin
current_module^.ppufile^.read_data(b,sizeof(byte),count);
readbyte:=b;
if count<>1 then
Message(unit_f_ppu_read_error);
end;
function readword : word;
var
count : longint;
w : word;
begin
current_module^.ppufile^.read_data(w,sizeof(word),count);
readword:=w;
if count<>sizeof(word) then
Message(unit_f_ppu_read_error);
end;
function readlong : longint;
var
count,l : longint;
begin
current_module^.ppufile^.read_data(l,sizeof(longint),count);
readlong:=l;
if count<>sizeof(longint) then
Message(unit_f_ppu_read_error);
end;
function readdouble : double;
var
count : longint;
d : double;
begin
current_module^.ppufile^.read_data(d,sizeof(double),count);
readdouble:=d;
if count<>sizeof(double) then
Message(unit_f_ppu_read_error);
end;
function readstring : string;
var
s : string;
count : longint;
begin
s[0]:=char(readbyte);
current_module^.ppufile^.read_data(s[1],ord(s[0]),count);
if count<>ord(s[0]) then
Message(unit_f_ppu_read_error);
readstring:=s;
end;
{***SETCONST}
procedure readset(var s); {You cannot pass an array [0..31] of byte.}
var count:longint;
begin
current_module^.ppufile^.read_data(s,32,count);
if count<>32 then
Message(unit_f_ppu_read_error);
end;
{***}
procedure readposinfo(var p:tfileposinfo);
begin
p.fileindex:=readword;
p.line:=readlong;
p.column:=readword;
end;
function readdefref : pdef;
var
hd : pdef;
begin
longint(hd):=readword;
longint(hd):=longint(hd) or (longint(readword) shl 16);
readdefref:=hd;
end;
{$ifdef UseBrowser}
function readsymref : psym;
var
hd : psym;
begin
longint(hd):=readword;
longint(hd):=longint(hd) or (longint(readword) shl 16);
readsymref:=hd;
end;
{$endif UseBrowser}
{$endif NEWPPU}
{
$Log$
Revision 1.2 1998-05-28 14:40:28 peter
* fixes for newppu, remake3 works now with it
Revision 1.1 1998/05/27 19:45:09 peter
* symtable.pas splitted into includefiles
* symtable adapted for $ifdef NEWPPU
}