codetools: c file merger: options to merge all

git-svn-id: trunk@29559 -
This commit is contained in:
mattias 2011-02-15 12:27:49 +00:00
parent d4ab1e76ea
commit 4f644760d6
2 changed files with 73 additions and 63 deletions

View File

@ -320,6 +320,12 @@ type
end;
PCHFileLink = ^TCHFileLink;
TCHFileMergeFlag = (
chfmfIgnoreIncludes, // do not merge at includes, but simply append
chfmfAll // merge all files, otherwise merge only the first
);
TCHFileMergeFlags = set of TCHFileMergeFlag;
TCHeaderFileMerger = class
private
procedure AddLink(aMergedPos: integer; aCode: TCodeBuffer; aSrcPos: integer);
@ -331,8 +337,10 @@ type
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure Merge(SourceFiles: TStrings; CodeCache: TCodeCache);
procedure Merge(SourceBuffers: TFPList { list of TCodeBuffer });
procedure Merge(SourceFiles: TStrings; CodeCache: TCodeCache;
const Flags: TCHFileMergeFlags);
procedure Merge(SourceBuffers: TFPList { list of TCodeBuffer };
const Flags: TCHFileMergeFlags);
function MergedPosToOriginal(MergedPos: integer;
out Code: TCodeBuffer; out CodePos: integer): boolean;
function MergedPosToOriginal(MergedX, MergedY: integer;
@ -471,7 +479,7 @@ begin
end;
procedure TCHeaderFileMerger.Merge(SourceFiles: TStrings;
CodeCache: TCodeCache);
CodeCache: TCodeCache; const Flags: TCHFileMergeFlags);
var
SourceBuffers: TFPList;
i: Integer;
@ -486,13 +494,14 @@ begin
raise Exception.Create('TCHeaderFileCombine.Combine: ERROR loading file '+SourceFiles[i]);
SourceBuffers.Add(Buf);
end;
Merge(SourceBuffers);
Merge(SourceBuffers,Flags);
finally
SourceBuffers.Free;
end;
end;
procedure TCHeaderFileMerger.Merge(SourceBuffers: TFPList);
procedure TCHeaderFileMerger.Merge(SourceBuffers: TFPList;
const Flags: TCHFileMergeFlags);
var
MergedBuffers: TFPList; // list of TCodeBuffer
StrStream: TStringStream;
@ -523,34 +532,36 @@ var
begin
MergedBuffers.Add(Code);
MergePos:=1;
for i:=0 to Code.LineCount-1 do begin
Line:=Code.GetLine(i);
if length(Line)<length('#include')+2 then continue;
if copy(Line,1,length('#include'))<>'#include' then continue;
if not (Line[length('#include')+1] in [' ',#9]) then continue;
IncludeParam:=Trim(copy(Line,length('#include')+1,length(Line)));
if (IncludeParam<>'') and (IncludeParam[1] in ['<','"']) then
IncludeParam:=copy(IncludeParam,2,length(IncludeParam)-2);
if IncludeParam<>'' then begin
// for example: glib/gutils.h
//debugln(['TCHeaderFileMerger.Merge Param=',IncludeParam]);
// search file in list
for j:=1 to SourceBuffers.Count-1 do begin
IncCode:=TCodeBuffer(SourceBuffers[j]);
IncFilename:=IncCode.Filename;
if CompareFilenames(IncludeParam,
RightStr(IncFilename,length(IncludeParam)))<>0 then continue;
if (length(IncFilename)=length(IncludeParam))
or (IncFilename[length(IncFilename)-length(IncludeParam)]=PathDelim)
then begin
// include file found
if MergedBuffers.IndexOf(IncCode)<0 then begin
debugln(['TCHeaderFileMerger.Merge file '+IncFilename+' into '+Code.Filename]);
Append('/* h2pas: merged '+IncludeParam+' into '+ExtractFileName(Code.Filename)+' */'+LineEnding);
Append(Code,MergePos,Code.GetLineStart(i));
MergePos:=Code.GetLineStart(i+1);
Parse(IncCode);
Append('/* h2pas: end of merged '+IncludeParam+' into '+ExtractFileName(Code.Filename)+' */'+LineEnding);
if not (chfmfIgnoreIncludes in Flags) then begin
for i:=0 to Code.LineCount-1 do begin
Line:=Code.GetLine(i);
if length(Line)<length('#include')+2 then continue;
if copy(Line,1,length('#include'))<>'#include' then continue;
if not (Line[length('#include')+1] in [' ',#9]) then continue;
IncludeParam:=Trim(copy(Line,length('#include')+1,length(Line)));
if (IncludeParam<>'') and (IncludeParam[1] in ['<','"']) then
IncludeParam:=copy(IncludeParam,2,length(IncludeParam)-2);
if IncludeParam<>'' then begin
// for example: glib/gutils.h
//debugln(['TCHeaderFileMerger.Merge Param=',IncludeParam]);
// search file in list
for j:=1 to SourceBuffers.Count-1 do begin
IncCode:=TCodeBuffer(SourceBuffers[j]);
IncFilename:=IncCode.Filename;
if CompareFilenames(IncludeParam,
RightStr(IncFilename,length(IncludeParam)))<>0 then continue;
if (length(IncFilename)=length(IncludeParam))
or (IncFilename[length(IncFilename)-length(IncludeParam)]=PathDelim)
then begin
// include file found
if MergedBuffers.IndexOf(IncCode)<0 then begin
debugln(['TCHeaderFileMerger.Merge file '+IncFilename+' into '+Code.Filename]);
Append('/* h2pas: merged '+IncludeParam+' into '+ExtractFileName(Code.Filename)+' */'+LineEnding);
Append(Code,MergePos,Code.GetLineStart(i));
MergePos:=Code.GetLineStart(i+1);
Parse(IncCode);
Append('/* h2pas: end of merged '+IncludeParam+' into '+ExtractFileName(Code.Filename)+' */'+LineEnding);
end;
end;
end;
end;
@ -561,12 +572,17 @@ var
Append(LineEnding);
end;
var
i: Integer;
begin
Clear;
MergedBuffers:=TFPList.Create;
StrStream:=TStringStream.Create('');
try
Parse(TCodeBuffer(SourceBuffers[0]));
for i:=0 to SourceBuffers.Count-1 do begin
Parse(TCodeBuffer(SourceBuffers[i]));
if not (chfmfAll in Flags) then break;
end;
finally
CombinedSource:=TCodeBuffer.Create;
CombinedSource.Source:=StrStream.DataString;

View File

@ -49,14 +49,15 @@ var
Filenames: TStringList;
Src: String;
Merger: TCHeaderFileMerger;
MergeFiles: Boolean;
MergeAll: Boolean;
MergeFlags: TCHFileMergeFlags;
begin
Merger:=nil;
try
Tool:=TH2PasTool.Create;
Filenames:=TStringList.Create;
OutputFilename:=CleanAndExpandFilename(AppendPathDelim(GetCurrentDir)+'h2pasoutput.pas');
MergeFiles:=false;
MergeAll:=false;
for i:=1 to Paramcount do begin
Param:=ParamStr(i);
if copy(Param,1,2)='-d' then
@ -65,13 +66,15 @@ begin
Tool.Undefines.Add(copy(Param,3,255),'')
else if copy(Param,1,2)='-o' then
OutputFilename:=CleanAndExpandFilename(Param)
else if Param='--merge' then
MergeFiles:=true
else if Param='--merge-all' then
MergeAll:=true
else if copy(Param,1,1)='-' then begin
writeln('Usage: ',ParamStr(0),' [--merge] [-d<definesymbol>]... [-u<undefinesymbol>]... <main header filename> <sub header file> ... -o<Outputfilename>');
writeln('Usage: ',ParamStr(0),' [--merge-all] [-d<definesymbol>]... [-u<undefinesymbol>]... <main header filename> <sub header file> ... -o<Outputfilename>');
writeln();
writeln(' Note: if --merge is given the sub header files are merged recursively into the main header at the #include directives.');
writeln(' Sub header files which are not used by any #include directive are not merged.');
writeln(' Scans for include directives and inserts given sub include files.');
writeln('');
writeln(' --merge-all');
writeln(' Merge all given files. Normally only files needed by the main header files are merged.');
Halt;
end else begin
Filename:=CleanAndExpandFilename(Param);
@ -86,28 +89,19 @@ begin
Filenames.Add(CleanAndExpandFilename(GetCurrentDir+'/scanexamples/test.h'));
// Step 1: load all input files
if MergeFiles then begin
Merger:=TCHeaderFileMerger.Create;
Merger.Merge(Filenames,CodeToolBoss.SourceCache);
//Merger.WriteDebugReport;
Src:=Merger.CombinedSource.Source;
{writeln;
writeln('======Combined c header files================');
writeln(Src);
writeln('=============================================');}
end else begin
Src:='';
for i:=0 to Filenames.Count-1 do begin
Filename:=Filenames[i];
CCode:=CodeToolBoss.LoadFile(Filename,false,false);
if CCode=nil then
raise Exception.Create('loading failed '+Filename);
Tool.UndefineEnclosingIFNDEF(CCode);
if Src<>'' then
Src:=Src+LineEnding;
Src:=Src+CCode.Source;
end;
end;
Merger:=TCHeaderFileMerger.Create;
MergeFlags:=[];
if MergeAll then Include(MergeFlags,chfmfAll);
Merger.Merge(Filenames,CodeToolBoss.SourceCache,MergeFlags);
//Merger.WriteDebugReport;
Src:=Merger.CombinedSource.Source;
{writeln;
writeln('======Combined c header files================');
writeln(Src);
writeln('=============================================');}
// ToDo:
// Tool.UndefineEnclosingIFNDEF(CCode);
// Step 2: create a temporary file
Filename:='h2pasoutput.pas';