mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-02 19:24:46 +01:00
codetools: c file merger: translate source position back to original file position
git-svn-id: trunk@29549 -
This commit is contained in:
parent
de531a2af0
commit
26709e8c25
@ -313,16 +313,33 @@ type
|
||||
|
||||
{ TCHeaderFileMerger }
|
||||
|
||||
TCHFileLink = record
|
||||
MergedPos: integer;
|
||||
Code: TCodeBuffer; // can be nil
|
||||
SrcPos: integer;
|
||||
end;
|
||||
PCHFileLink = ^TCHFileLink;
|
||||
|
||||
TCHeaderFileMerger = class
|
||||
private
|
||||
procedure AddLink(aMergedPos: integer; aCode: TCodeBuffer; aSrcPos: integer);
|
||||
public
|
||||
CombinedSource: TCodeBuffer;
|
||||
LinkCount: integer;
|
||||
Links: PCHFileLink;
|
||||
LinksCapacity: integer;
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure Merge(SourceFiles: TStrings;
|
||||
CodeCache: TCodeCache; out CombinedSource: string);
|
||||
procedure Merge(SourceBuffers: TFPList; // list of TCodeBuffer
|
||||
out CombinedSource: string);
|
||||
procedure Clear;
|
||||
procedure Merge(SourceFiles: TStrings; CodeCache: TCodeCache);
|
||||
procedure Merge(SourceBuffers: TFPList { list of TCodeBuffer });
|
||||
function MergedPosToOriginal(MergedPos: integer;
|
||||
out Code: TCodeBuffer; out CodePos: integer): boolean;
|
||||
function MergedPosToOriginal(MergedX, MergedY: integer;
|
||||
out Code: TCodeBuffer; out X, Y: integer): boolean;
|
||||
function LinkIndexOfMergedPos(MergedPos: integer): integer;
|
||||
end;
|
||||
|
||||
|
||||
function CCNodeDescAsString(Desc: TCCodeNodeDesc; SubDesc: TCCodeNodeDesc = 0): string;
|
||||
procedure InitCCodeKeyWordLists;
|
||||
|
||||
@ -413,6 +430,24 @@ end;
|
||||
|
||||
{ TCHeaderFileMerger }
|
||||
|
||||
procedure TCHeaderFileMerger.AddLink(aMergedPos: integer; aCode: TCodeBuffer;
|
||||
aSrcPos: integer);
|
||||
begin
|
||||
if LinkCount=LinksCapacity then begin
|
||||
if LinksCapacity<4 then
|
||||
LinksCapacity:=4
|
||||
else
|
||||
LinksCapacity:=LinksCapacity*2;
|
||||
ReAllocMem(Links,LinksCapacity*SizeOf(TCHFileLink));
|
||||
end;
|
||||
with Links[LinkCount] do begin
|
||||
MergedPos:=aMergedPos;
|
||||
Code:=aCode;
|
||||
SrcPos:=aSrcPos;
|
||||
end;
|
||||
inc(LinkCount);
|
||||
end;
|
||||
|
||||
constructor TCHeaderFileMerger.Create;
|
||||
begin
|
||||
|
||||
@ -420,17 +455,26 @@ end;
|
||||
|
||||
destructor TCHeaderFileMerger.Destroy;
|
||||
begin
|
||||
Clear;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TCHeaderFileMerger.Clear;
|
||||
begin
|
||||
FreeAndNil(CombinedSource);
|
||||
ReAllocMem(Links,0);
|
||||
LinkCount:=0;
|
||||
LinksCapacity:=0;
|
||||
end;
|
||||
|
||||
procedure TCHeaderFileMerger.Merge(SourceFiles: TStrings;
|
||||
CodeCache: TCodeCache; out CombinedSource: string);
|
||||
CodeCache: TCodeCache);
|
||||
var
|
||||
SourceBuffers: TFPList;
|
||||
i: Integer;
|
||||
Buf: TCodeBuffer;
|
||||
begin
|
||||
CombinedSource:='';
|
||||
Clear;
|
||||
SourceBuffers:=TFPList.Create;
|
||||
try
|
||||
for i:=0 to SourceFiles.Count-1 do begin
|
||||
@ -439,22 +483,22 @@ begin
|
||||
raise Exception.Create('TCHeaderFileCombine.Combine: ERROR loading file '+SourceFiles[i]);
|
||||
SourceBuffers.Add(Buf);
|
||||
end;
|
||||
Merge(SourceBuffers,CombinedSource);
|
||||
Merge(SourceBuffers);
|
||||
finally
|
||||
SourceBuffers.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCHeaderFileMerger.Merge(SourceBuffers: TFPList;
|
||||
out CombinedSource: string);
|
||||
procedure TCHeaderFileMerger.Merge(SourceBuffers: TFPList);
|
||||
var
|
||||
MergedBuffers: TFPList; // list of TCodeBuffer
|
||||
StrStream: TStringStream;
|
||||
|
||||
procedure Append(const Source: string; FromPos, EndPos: integer);
|
||||
procedure Append(Code: TCodeBuffer; FromPos, EndPos: integer);
|
||||
begin
|
||||
if EndPos<FromPos then exit;
|
||||
StrStream.Write(Source[FromPos],EndPos-FromPos);
|
||||
AddLink(StrStream.Position+1,Code,FromPos);
|
||||
StrStream.Write(Code.Source[FromPos],EndPos-FromPos);
|
||||
end;
|
||||
|
||||
procedure Parse(Code: TCodeBuffer);
|
||||
@ -492,32 +536,91 @@ var
|
||||
// include file found
|
||||
if MergedBuffers.IndexOf(IncCode)<0 then begin
|
||||
debugln(['TCHeaderFileMerger.Merge file '+IncFilename+' into '+Code.Filename]);
|
||||
Append(Code.Source,MergePos,Code.GetLineStart(i));
|
||||
StrStream.WriteString('/* h2pas: merged '+IncludeParam+' into '+ExtractFileName(Code.Filename)+' */'+LineEnding);
|
||||
Append(Code,MergePos,Code.GetLineStart(i));
|
||||
MergePos:=Code.GetLineStart(i+1);
|
||||
Parse(IncCode);
|
||||
StrStream.WriteString('/* h2pas: end of merged '+IncludeParam+' into '+ExtractFileName(Code.Filename)+' */'+LineEnding);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if MergePos<Code.SourceLength then
|
||||
Append(Code.Source,MergePos,Code.SourceLength);
|
||||
Append(Code,MergePos,Code.SourceLength);
|
||||
StrStream.WriteString(LineEnding);
|
||||
end;
|
||||
|
||||
begin
|
||||
CombinedSource:='';
|
||||
Clear;
|
||||
MergedBuffers:=TFPList.Create;
|
||||
StrStream:=TStringStream.Create('');
|
||||
try
|
||||
Parse(TCodeBuffer(SourceBuffers[0]));
|
||||
finally
|
||||
CombinedSource:=StrStream.DataString;
|
||||
CombinedSource:=TCodeBuffer.Create;
|
||||
CombinedSource.Source:=StrStream.DataString;
|
||||
StrStream.Free;
|
||||
MergedBuffers.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCHeaderFileMerger.MergedPosToOriginal(MergedPos: integer;
|
||||
out Code: TCodeBuffer; out CodePos: integer): boolean;
|
||||
var
|
||||
Link: PCHFileLink;
|
||||
LinkIndex: LongInt;
|
||||
begin
|
||||
Code:=nil;
|
||||
CodePos:=0;
|
||||
LinkIndex:=LinkIndexOfMergedPos(MergedPos);
|
||||
if LinkIndex<0 then exit(false);
|
||||
Link:=@Links[LinkIndex];
|
||||
Code:=Link^.Code;
|
||||
CodePos:=MergedPos-Link^.MergedPos;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function TCHeaderFileMerger.MergedPosToOriginal(MergedX, MergedY: integer;
|
||||
out Code: TCodeBuffer; out X, Y: integer): boolean;
|
||||
var
|
||||
MergedPos: integer;
|
||||
CodePos: integer;
|
||||
begin
|
||||
Result:=false;
|
||||
CombinedSource.LineColToPosition(MergedY,MergedX,MergedPos);
|
||||
if not MergedPosToOriginal(MergedPos,Code,CodePos) then exit;
|
||||
Code.AbsoluteToLineCol(CodePos,Y,X);
|
||||
Result:=Y>=1;
|
||||
end;
|
||||
|
||||
function TCHeaderFileMerger.LinkIndexOfMergedPos(MergedPos: integer): integer;
|
||||
var
|
||||
l: Integer;
|
||||
r: Integer;
|
||||
begin
|
||||
Result:=-1;
|
||||
if LinkCount=0 then exit;
|
||||
if (MergedPos<1) then exit;
|
||||
if MergedPos>CombinedSource.SourceLength+1 then
|
||||
exit;
|
||||
// MergedPos is in source
|
||||
if MergedPos>=Links[LinkCount-1].MergedPos then
|
||||
exit(LinkCount-1);
|
||||
// MergedPos is in one of the regular links (that have a successor)
|
||||
l:=0;
|
||||
r:=LinkCount-2;
|
||||
while (l<=r) do begin
|
||||
Result:=(l+r) div 2;
|
||||
if MergedPos<Links[Result].MergedPos then
|
||||
r:=Result-1
|
||||
else if MergedPos<Links[Result+1].MergedPos then
|
||||
exit
|
||||
else
|
||||
l:=Result+1;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ECCodeParserException }
|
||||
|
||||
constructor ECCodeParserException.Create(ASender: TCCodeParserTool;
|
||||
|
||||
@ -51,6 +51,7 @@ var
|
||||
Merger: TCHeaderFileMerger;
|
||||
MergeFiles: Boolean;
|
||||
begin
|
||||
Merger:=nil;
|
||||
try
|
||||
Tool:=TH2PasTool.Create;
|
||||
Filenames:=TStringList.Create;
|
||||
@ -87,13 +88,12 @@ begin
|
||||
// Step 1: load all input files
|
||||
if MergeFiles then begin
|
||||
Merger:=TCHeaderFileMerger.Create;
|
||||
Merger.Merge(Filenames,CodeToolBoss.SourceCache,Src);
|
||||
writeln;
|
||||
Merger.Merge(Filenames,CodeToolBoss.SourceCache);
|
||||
Src:=Merger.CombinedSource.Source;
|
||||
{writeln;
|
||||
writeln('======Combined c header files================');
|
||||
writeln(Src);
|
||||
writeln('=============================================');
|
||||
Merger.Free;
|
||||
Halt;
|
||||
writeln('=============================================');}
|
||||
end else begin
|
||||
Src:='';
|
||||
for i:=0 to Filenames.Count-1 do begin
|
||||
@ -139,10 +139,15 @@ begin
|
||||
writeln('Wrote ',PasCode.Filename)
|
||||
else
|
||||
writeln('Failed writing ',PasCode.Filename);
|
||||
|
||||
FreeAndNil(Merger);
|
||||
except
|
||||
on E: ECCodeParserException do begin
|
||||
CCodeTool:=ECCodeParserException(E).Sender;
|
||||
CCodeTool.CleanPosToCaret(CCodeTool.LastErrorReportPos,Caret);
|
||||
if Merger<>nil then begin
|
||||
Merger.MergedPosToOriginal(Caret.Y,Caret.X,Caret.Code,Caret.X,Caret.Y);
|
||||
end;
|
||||
writeln(Caret.Code.Filename+'('+IntToStr(Caret.Y)+','+IntToStr(Caret.X)+')'+' Error: '+E.Message);
|
||||
end;
|
||||
on E: Exception do begin
|
||||
|
||||
Loading…
Reference in New Issue
Block a user