mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-10 05:48:59 +02:00

Merged revision(s) 28796, 28837-28845, 28847-28850, 28852, 32135 from branches/svenbarth/packages: Provide possibility to pass packages and search paths for packages as parameters. fpkg.pas: + new unit which contains the base types related to package files (most importantly "tpackage") globals.pas: + new variable "packagesearchpath" which contains all paths in which package files should be looked for + new variable "packagelist" which contains a list of all packages that should be used in a program or library * InitGlobals & DoneGlobals: initialize/finalize "packagesearchpath" accordingly ("packagelist" is handled in unit fpkg using a init/done-callback) options.pas: + TOption: new fields "parapackagepath" and "parapackages" to keep track of package search paths and package files passed as parameters * TOption.interpret_option: use '-Fp' for package search paths and '-FP' for package files * read_arguments: apply the passed package search paths and packages to their respective containers ........ + add a new unit which will contain basic functions related to handling packages ........ Move package related functions from pmodules to pkgutil. pmodules.pas => pkgutil.pas: * createimportlibfromexports * varexport * procexport * insert_export * RewritePPU ........ * adjust indentation ........ Extract the code to export the symbols of a unit to its own function in pkgutil so that less functions need to be exported. pmodules.pas, proc_package: * move code to export the symbols of a unit to new function export_unit pkgutil.pas: + new function export_unit - remove exports of procexport, varexport and insert_export ........ Some small fixes for package parsing. pmodules.pas, proc_package: * use orgpattern instead of pattern to build the module name (like is done in uses sections) * ignore duplicates when generating exports - no need to generate an import library for the package; that is done by the program/library that uses the package ........ + new unit fpcp of which the class tpcppackage handles the reading and writing of package metadata from/to pcp files (equivalant to tppumodule). ........ + add unit which contains representation of a PCP file (tpcpfile) like tppufile is for units. ........ Improve export generation. pkgutil.pas: + new function exportprocsym to correctly export a procedure with all its aliases + new function exportabstractrecordsymproc to export the members of structured types * insert_export: handle also namespacesym and propertsym (by ignoring them) * insert_export: correctly export classes, record and objects * insert_export: use new exportprocsym function to export a procsym * insert_export: only export public variables of a static symtable ........ + add entry constants for the name of the package and the package file names, both used by a PCP file ........ * use messages to get rid of most writelns related to package loading ........ Add additional entry types for PCP files entfile.pas: + new entries ibstartrequireds and ibendrequireds to store the list of required packages + new entries ibstartcontained and ibendcontained to store the list of contained units + new entries ibstartppus and ibendppus to store the list of contained PPU files ........ Generate the PCP file once the package file and the used units were compiled correctly. pmodules.pas: * proc_package: generate the PCP file upon successful compilation ........ Add the possibility to load all packages supplied as parameters. pkgutil.pas: + new function load_packages to load all packages supplied as parameters pmodules.pas, proc_program: * use load_packages to load all packages before any unit is loaded ........ Add code which tries to load a unit from a package first and only then as usual. fppu.pas, tppumodule: + new method loadfrompackage which searches all available packages for the unit and loads it from there if found * loadppu: first try to load the unit from a package if any are available ........ Don't link objects files of a unit that is provided by a package. pmodules.pas, proc_program: * if a unit has uf_in_library set we must not include it in the units we link against ........ git-svn-id: trunk@33452 -
189 lines
5.8 KiB
ObjectPascal
189 lines
5.8 KiB
ObjectPascal
{
|
|
Copyright (c) 2013-2016 by Free Pascal development team
|
|
|
|
Routines to read/write pcp files
|
|
|
|
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 pcp;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
cstreams,entfile;
|
|
|
|
const
|
|
CurrentPCPVersion=1;
|
|
|
|
{ unit flags }
|
|
//uf_init = $000001; { unit has initialization section }
|
|
//uf_finalize = $000002; { unit has finalization section }
|
|
pf_big_endian = $000004;
|
|
//uf_has_browser = $000010;
|
|
//uf_in_library = $000020; { is the file in another file than <ppufile>.* ? }
|
|
//uf_smart_linked = $000040; { the ppu can be smartlinked }
|
|
//uf_static_linked = $000080; { the ppu can be linked static }
|
|
//uf_shared_linked = $000100; { the ppu can be linked shared }
|
|
//uf_local_browser = $000200;
|
|
//uf_no_link = $000400; { unit has no .o generated, but can still have external linking! }
|
|
//uf_has_resourcestrings = $000800; { unit has resource string section }
|
|
pf_little_endian = $001000;
|
|
|
|
|
|
type
|
|
tpcpheader=record
|
|
common : tentryheader;
|
|
checksum : cardinal; { checksum for this pcpfile }
|
|
requiredlistsize, { number of entries for required packages }
|
|
ppulistsize : longint; { number of entries for contained PPUs }
|
|
end;
|
|
|
|
tpcpfile=class(tentryfile)
|
|
public
|
|
header : tpcpheader;
|
|
{ crc for the entire package }
|
|
crc : cardinal;
|
|
protected
|
|
function getheadersize:longint;override;
|
|
function getheaderaddr:pentryheader;override;
|
|
procedure newheader;override;
|
|
function readheader:longint;override;
|
|
procedure resetfile;override;
|
|
public
|
|
procedure writeheader;override;
|
|
function checkpcpid:boolean;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ tpcpfile }
|
|
|
|
function tpcpfile.getheadersize: longint;
|
|
begin
|
|
result:=sizeof(tpcpheader);
|
|
end;
|
|
|
|
function tpcpfile.getheaderaddr: pentryheader;
|
|
begin
|
|
result:=@header;
|
|
end;
|
|
|
|
procedure tpcpfile.newheader;
|
|
var
|
|
s : string;
|
|
begin
|
|
fillchar(header,sizeof(tpcpheader),0);
|
|
str(CurrentPCPVersion,s);
|
|
while length(s)<3 do
|
|
s:='0'+s;
|
|
with header.common do
|
|
begin
|
|
id[1]:='P';
|
|
id[2]:='C';
|
|
id[3]:='P';
|
|
ver[1]:=s[1];
|
|
ver[2]:=s[2];
|
|
ver[3]:=s[3];
|
|
end;
|
|
end;
|
|
|
|
function tpcpfile.readheader: longint;
|
|
begin
|
|
if fsize<sizeof(tpcpheader) then
|
|
exit(0);
|
|
result:=f.Read(header,sizeof(tpcpheader));
|
|
{ The header is always stored in little endian order }
|
|
{ therefore swap if on a big endian machine }
|
|
{$IFDEF ENDIAN_BIG}
|
|
header.common.compiler := swapendian(header.common.compiler);
|
|
header.common.cpu := swapendian(header.common.cpu);
|
|
header.common.target := swapendian(header.common.target);
|
|
header.common.flags := swapendian(header.common.flags);
|
|
header.common.size := swapendian(header.common.size);
|
|
header.checksum := swapendian(header.checksum);
|
|
header.requiredlistsize:=swapendian(header.requiredlistsize);
|
|
header.ppulistsize:=swapendian(header.ppulistsize);
|
|
{$ENDIF}
|
|
{ the PPU DATA is stored in native order }
|
|
if (header.common.flags and pf_big_endian) = pf_big_endian then
|
|
Begin
|
|
{$IFDEF ENDIAN_LITTLE}
|
|
change_endian := TRUE;
|
|
{$ELSE}
|
|
change_endian := FALSE;
|
|
{$ENDIF}
|
|
End
|
|
else if (header.common.flags and pf_little_endian) = pf_little_endian then
|
|
Begin
|
|
{$IFDEF ENDIAN_BIG}
|
|
change_endian := TRUE;
|
|
{$ELSE}
|
|
change_endian := FALSE;
|
|
{$ENDIF}
|
|
End;
|
|
end;
|
|
|
|
procedure tpcpfile.resetfile;
|
|
begin
|
|
crc:=0;
|
|
end;
|
|
|
|
|
|
procedure tpcpfile.writeheader;
|
|
var
|
|
opos : integer;
|
|
begin
|
|
{ flush buffer }
|
|
writebuf;
|
|
{ update size (w/o header!) in the header }
|
|
header.common.size:=bufstart-sizeof(tpcpheader);
|
|
{ set the endian flag }
|
|
{$ifndef FPC_BIG_ENDIAN}
|
|
header.common.flags:=header.common.flags or pf_little_endian;
|
|
{$else not FPC_BIG_ENDIAN}
|
|
header.common.flags:=header.common.flags or pf_big_endian;
|
|
{ Now swap the header in the correct endian (always little endian) }
|
|
header.common.compiler:=swapendian(header.common.compiler);
|
|
header.common.cpu:=swapendian(header.common.cpu);
|
|
header.common.target:=swapendian(header.common.target);
|
|
header.common.flags:=swapendian(header.common.flags);
|
|
header.common.size:=swapendian(header.common.size);
|
|
header.checksum:=swapendian(header.checksum);
|
|
header.requiredlistsize:=swapendian(header.requiredlistsize);
|
|
header.ppulistsize:=swapendian(header.ppulistsize);
|
|
{$endif not FPC_BIG_ENDIAN}
|
|
{ write header and restore filepos after it }
|
|
opos:=f.Position;
|
|
f.Position:=0;
|
|
f.Write(header,sizeof(tpcpheader));
|
|
f.Position:=opos;
|
|
end;
|
|
|
|
|
|
function tpcpfile.checkpcpid:boolean;
|
|
begin
|
|
result:=((Header.common.Id[1]='P') and
|
|
(Header.common.Id[2]='C') and
|
|
(Header.common.Id[3]='P'));
|
|
end;
|
|
|
|
|
|
end.
|
|
|