mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-24 12:19:28 +02:00
codetools: h2pas: convert anonymous enum
git-svn-id: trunk@31304 -
This commit is contained in:
parent
3abbb28e51
commit
357f42936c
@ -2022,24 +2022,28 @@ function TCCodeParserTool.ExtractDefinitionType(VarNode: TCodeTreeNode;
|
||||
var
|
||||
NameNode: TCodeTreeNode;
|
||||
s: String;
|
||||
AfterNameNode: TCodeTreeNode;
|
||||
StartPos: Integer;
|
||||
begin
|
||||
Result:='';
|
||||
NameNode:=GetFirstNameNode(VarNode);
|
||||
if (NameNode=nil) then
|
||||
Result:=''
|
||||
else begin
|
||||
if (NameNode<>nil) then begin
|
||||
Result:=ExtractCode(VarNode.StartPos,NameNode.StartPos,WithDirectives);
|
||||
if (NameNode.NextBrother<>nil)
|
||||
and (NameNode.NextBrother.Desc=ccnConstant) then begin
|
||||
// a variable with an initial value
|
||||
// omit the constant
|
||||
s:=ExtractCode(NameNode.EndPos,NameNode.NextBrother.StartPos,
|
||||
WithDirectives);
|
||||
s:=copy(s,1,length(s)-1);
|
||||
AfterNameNode:=NameNode.NextBrother;
|
||||
StartPos:=NameNode.EndPos;
|
||||
end else begin
|
||||
AfterNameNode:=VarNode.FirstChild;
|
||||
StartPos:=VarNode.StartPos;
|
||||
end;
|
||||
if (AfterNameNode<>nil)
|
||||
and (AfterNameNode.Desc=ccnConstant) then begin
|
||||
// omit constant
|
||||
s:=ExtractCode(StartPos,AfterNameNode.StartPos,WithDirectives);
|
||||
if (s<>'') and (s[length(s)]='=') then
|
||||
s:=Trim(copy(s,1,length(s)-1));
|
||||
Result:=Result+s;
|
||||
end else begin
|
||||
Result:=Result+ExtractCode(NameNode.EndPos,VarNode.EndPos,
|
||||
WithDirectives);
|
||||
end;
|
||||
Result:=Result+ExtractCode(StartPos,VarNode.EndPos,WithDirectives);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -2544,7 +2548,7 @@ begin
|
||||
if Tree<>nil then begin
|
||||
Node:=Tree.Root;
|
||||
while Node<>nil do begin
|
||||
DebugLn([GetNodeIndent(CurNode)+NodeAsString(Node)]);
|
||||
DebugLn([GetNodeIndent(Node)+NodeAsString(Node)]);
|
||||
Node:=Node.Next;
|
||||
end;
|
||||
end;
|
||||
|
@ -194,7 +194,7 @@ type
|
||||
// converting C nodes to H2P nodes
|
||||
procedure ConvertStruct(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
procedure ConvertVariable(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
procedure ConvertEnumBlock(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
function ConvertEnumBlock(CNode: TCodeTreeNode; ParentNode: TH2PNode): TH2PNode;
|
||||
procedure ConvertFunction(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
procedure ConvertFuncParameter(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
procedure ConvertTypedef(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
@ -268,7 +268,7 @@ type
|
||||
PascalDesc: TCodeTreeNodeDesc; const PascalCode: string;
|
||||
ParentNode: TH2PNode; IsGlobal: boolean;
|
||||
InsertAsPreLast: boolean): TH2PNode;
|
||||
function GetH2PNodeForComplexType(CNode: TCodeTreeNode;
|
||||
function CreateH2PNodeForComplexType(CNode: TCodeTreeNode;
|
||||
CreateIfNotExists: boolean;
|
||||
InsertAsPreLast: boolean): TH2PNode;
|
||||
function CreatePascalNameFromCCode(const CCode: string;
|
||||
@ -580,14 +580,14 @@ begin
|
||||
end;
|
||||
end else begin
|
||||
CurName:=CTool.ExtractDefinitionName(CNode);
|
||||
CurType:=CTool.ExtractDefinitionType(CNode);
|
||||
SimpleType:=GetSimplePascalTypeOfCVar(CNode);
|
||||
if SimpleType='' then begin
|
||||
// this variable has a complex type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode,true,ParentNode<>nil);
|
||||
TypeH2PNode:=CreateH2PNodeForComplexType(CNode,true,ParentNode<>nil);
|
||||
if TypeH2PNode<>nil then
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end;
|
||||
if CurName<>'' then begin
|
||||
if SimpleType<>'' then begin
|
||||
CurCName:=CurName;
|
||||
H2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnVarDefinition,SimpleType,
|
||||
@ -595,16 +595,17 @@ begin
|
||||
DebugLn(['TH2PasTool.ConvertVariable CurName=',CurName,' ',H2PNode.PascalName]);
|
||||
DebugLn(['TH2PasTool.ConvertVariable added: ',H2PNode.DescAsString(CTool)]);
|
||||
end else begin
|
||||
CurType:=CTool.ExtractDefinitionType(CNode);
|
||||
DebugLn(['TH2PasTool.ConvertVariable SKIPPING Variable Name="',CurName,'" Type="',CurType,'"']);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TH2PasTool.ConvertEnumBlock(CNode: TCodeTreeNode;
|
||||
ParentNode: TH2PNode);
|
||||
function TH2PasTool.ConvertEnumBlock(CNode: TCodeTreeNode; ParentNode: TH2PNode
|
||||
): TH2PNode;
|
||||
var
|
||||
CurName: String;
|
||||
TypeH2PNode: TH2PNode;
|
||||
CurValue: String;
|
||||
H2PNode: TH2PNode;
|
||||
CurCName: String;
|
||||
@ -613,15 +614,15 @@ begin
|
||||
if CurName='' then begin
|
||||
// this is an anonymous enum block => auto generate a name
|
||||
CurName:=CreatePascalNameFromCCode(CTool.Src,CNode.StartPos,CNode.EndPos);
|
||||
TypeH2PNode:=CreateAutoGeneratedH2PNode(CurName,CNode,ctnEnumerationType,'',
|
||||
Result:=CreateAutoGeneratedH2PNode(CurName,CNode,ctnEnumerationType,'',
|
||||
nil,true,ParentNode<>nil);
|
||||
end else begin
|
||||
// this enum block has a name
|
||||
CurCName:=CurName;
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnEnumerationType,'',
|
||||
Result:=CreateH2PNode(CurName,CurCName,CNode,ctnEnumerationType,'',
|
||||
nil,true);
|
||||
end;
|
||||
DebugLn(['TH2PasTool.ConvertEnumBlock added: ',TypeH2PNode.DescAsString(CTool)]);
|
||||
DebugLn(['TH2PasTool.ConvertEnumBlock added: ',Result.DescAsString(CTool)]);
|
||||
|
||||
CNode:=CNode.FirstChild;
|
||||
while CNode<>nil do begin
|
||||
@ -630,7 +631,7 @@ begin
|
||||
CurValue:=CTool.ExtractEnumIDValue(CNode);
|
||||
CurCName:=CurName;
|
||||
H2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnEnumIdentifier,CurValue,
|
||||
TypeH2PNode,true);
|
||||
Result,true);
|
||||
DebugLn(['TH2PasTool.ConvertEnumBlock added: ',H2PNode.DescAsString(CTool)]);
|
||||
end;
|
||||
CNode:=CNode.NextBrother;
|
||||
@ -666,7 +667,7 @@ begin
|
||||
end;
|
||||
if Ok and (SimpleType='') then begin
|
||||
// this function has a complex result type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode,true,ParentNode<>nil);
|
||||
TypeH2PNode:=CreateH2PNodeForComplexType(CNode,true,ParentNode<>nil);
|
||||
if TypeH2PNode<>nil then begin
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end else
|
||||
@ -724,7 +725,7 @@ begin
|
||||
DebugLn(['TH2PasTool.ConvertFuncParameter Parameter: Name="',CurName,'" Type="',CurType,'" SimpleType="',SimpleType,'"']);
|
||||
if SimpleType='' then begin
|
||||
// this variable has a complex type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode,true,true);
|
||||
TypeH2PNode:=CreateH2PNodeForComplexType(CNode,true,true);
|
||||
if TypeH2PNode<>nil then
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end;
|
||||
@ -768,7 +769,7 @@ begin
|
||||
SimpleType:=GetSimplePascalTypeOfCVar(ChildNode);
|
||||
if SimpleType='' then begin
|
||||
// this variable has a complex type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(ChildNode,true,ParentNode<>nil);
|
||||
TypeH2PNode:=CreateH2PNodeForComplexType(ChildNode,true,ParentNode<>nil);
|
||||
if TypeH2PNode<>nil then
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end;
|
||||
@ -838,7 +839,7 @@ begin
|
||||
SimpleType:=GetSimplePascalResultTypeOfCFunction(ChildNode);
|
||||
if IsPointerToFunction and (SimpleType='') then begin
|
||||
// this function has a complex result type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(ChildNode,true,ParentNode<>nil);
|
||||
TypeH2PNode:=CreateH2PNodeForComplexType(ChildNode,true,ParentNode<>nil);
|
||||
if TypeH2PNode<>nil then
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end;
|
||||
@ -2395,7 +2396,7 @@ begin
|
||||
inc(i);
|
||||
end;
|
||||
|
||||
function TH2PasTool.GetH2PNodeForComplexType(CNode: TCodeTreeNode;
|
||||
function TH2PasTool.CreateH2PNodeForComplexType(CNode: TCodeTreeNode;
|
||||
CreateIfNotExists: boolean; InsertAsPreLast: boolean): TH2PNode;
|
||||
var
|
||||
CCode: String;
|
||||
@ -2414,14 +2415,27 @@ var
|
||||
ConstantNumber: int64;
|
||||
BracketOpenPos: LongInt;
|
||||
NeedH2PNode: Boolean;
|
||||
SubCNode: TCodeTreeNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (CNode.Desc=ccnDefinition)
|
||||
and (CNode.FirstChild<>nil)
|
||||
and (CNode.FirstChild.Desc=ccnUnion) then begin
|
||||
// ToDo: union
|
||||
end else begin
|
||||
if (CNode.Desc=ccnDefinition) and (CNode.FirstChild<>nil) then begin
|
||||
SubCNode:=CNode.FirstChild;
|
||||
if SubCNode.Desc=ccnName then
|
||||
SubCNode:=SubCNode.NextBrother;
|
||||
if (SubCNode<>nil) then begin
|
||||
if (SubCNode.Desc=ccnEnumBlock) then begin
|
||||
Result:=ConvertEnumBlock(SubCNode,nil);
|
||||
exit;
|
||||
end;
|
||||
if SubCNode.Desc<>ccnConstant then begin
|
||||
debugln(['TH2PasTool.GetH2PNodeForComplexType TODO: ',CCNodeDescAsString(CNode.Desc),' of ',CCNodeDescAsString(SubCNode.Desc)]);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
SubH2PNode:=nil;
|
||||
debugln(['TH2PasTool.GetH2PNodeForComplexType CNode=',CCNodeDescAsString(CNode.Desc)]);
|
||||
if CNode.Desc=ccnDefinition then
|
||||
CCode:=CTool.ExtractDefinitionType(CNode)
|
||||
else if CNode.Desc=ccnFunction then
|
||||
@ -2552,7 +2566,6 @@ begin
|
||||
DebugLn(['TH2PasTool.GetTypeForVarType CCode="',dbgstr(CCode),'" PascalName="',PascalName,'"']);
|
||||
Result:=SubH2PNode;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TH2PasTool.CreatePascalNameFromCCode(const CCode: string;
|
||||
StartPos: integer; EndPos: integer): string;
|
||||
@ -2670,6 +2683,7 @@ begin
|
||||
end else if (Tree.Root=nil) then begin
|
||||
DebugLn(['TH2PasTool.WriteH2PNodeReport Tree.Root=nil']);
|
||||
end else begin
|
||||
//debugln(['TH2PasTool.WriteH2PNodeReport ']);
|
||||
Node:=Tree.Root;
|
||||
while Node<>nil do begin
|
||||
DebugLn([GetIndentStr(Node.GetLevel*2),Node.DescAsString(CTool)]);
|
||||
|
@ -4,6 +4,7 @@
|
||||
./runtests --format=plain --suite=TestCTH2PMergeHeaderFiles
|
||||
./runtests --format=plain --suite=TestCTH2PReplaceMacros
|
||||
./runtests --format=plain --suite=TestCTH2PConvertSimpleTypes
|
||||
./runtests --format=plain --suite=TestCTH2PConvertEnumsTypes
|
||||
}
|
||||
unit TestCTH2Pas;
|
||||
|
||||
@ -23,16 +24,50 @@ type
|
||||
|
||||
TTestCodetoolsH2Pas = class(TTestCase)
|
||||
protected
|
||||
procedure Test(Title, CHeaderSrc, ExpectedPasSrc: string);
|
||||
published
|
||||
procedure TestCTH2PMergeHeaderFiles;
|
||||
procedure TestCTH2PReplaceMacros;
|
||||
procedure TestCTH2PConvertSimpleTypes;
|
||||
procedure TestCTH2PConvertEnumsTypes;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TTestCodetoolsH2Pas }
|
||||
|
||||
procedure TTestCodetoolsH2Pas.Test(Title, CHeaderSrc, ExpectedPasSrc: string);
|
||||
var
|
||||
Tool: TH2PasTool;
|
||||
Header1: TCodeBuffer;
|
||||
PasCode: TCodeBuffer;
|
||||
begin
|
||||
Tool:=TH2PasTool.Create;
|
||||
Header1:=nil;
|
||||
PasCode:=nil;
|
||||
try
|
||||
Header1:=CodeToolBoss.CreateFile('header1.h');
|
||||
PasCode:=CodeToolBoss.CreateFile('header1.pas');
|
||||
Header1.Source:=CHeaderSrc;
|
||||
Tool.Convert(Header1,PasCode);
|
||||
if CompareTextIgnoringSpace(ExpectedPasSrc,PasCode.Source,true)<>0 then begin
|
||||
// failed
|
||||
debugln(['TTestCodetoolsH2Pas.Test C Source="',CHeaderSrc,'"']);
|
||||
debugln(['TTestCodetoolsH2Pas.Test Expected pas="',ExpectedPasSrc,'"']);
|
||||
debugln(['TTestCodetoolsH2Pas.Test Found pas="',PasCode.Source,'"']);
|
||||
Tool.WriteH2PNodeReport;
|
||||
Tool.WriteH2PDirectivesNodeReport;
|
||||
AssertEquals(Title,ExpectedPasSrc,PasCode.Source);
|
||||
end else begin
|
||||
AssertEquals(Title,true,true);
|
||||
end;
|
||||
finally
|
||||
if Header1<>nil then Header1.IsDeleted:=true;
|
||||
if PasCode<>nil then PasCode.IsDeleted:=true;
|
||||
Tool.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTestCodetoolsH2Pas.TestCTH2PMergeHeaderFiles;
|
||||
var
|
||||
Header1, Header2: TCodeBuffer;
|
||||
@ -116,41 +151,26 @@ end;
|
||||
|
||||
procedure TTestCodetoolsH2Pas.TestCTH2PConvertSimpleTypes;
|
||||
var
|
||||
Tool: TH2PasTool;
|
||||
Header1: TCodeBuffer;
|
||||
PasCode: TCodeBuffer;
|
||||
ExpectedSrc: String;
|
||||
UsesCTypes: String;
|
||||
EmpytImplementation: String;
|
||||
begin
|
||||
Tool:=TH2PasTool.Create;
|
||||
Header1:=nil;
|
||||
PasCode:=nil;
|
||||
try
|
||||
Header1:=CodeToolBoss.CreateFile('header1.h');
|
||||
PasCode:=CodeToolBoss.CreateFile('header1.pas');
|
||||
Header1.Source:='int i;';
|
||||
Tool.Convert(Header1,PasCode);
|
||||
ExpectedSrc:=
|
||||
'uses ctypes;'+LineEnding
|
||||
+'var'+LineEnding
|
||||
+' i: cint; cvar; external;'+LineEnding
|
||||
+'implementation'+LineEnding
|
||||
+'end.';
|
||||
if CompareTextIgnoringSpace(ExpectedSrc,PasCode.Source,true)<>0 then begin
|
||||
AssertEquals('convert int i;',ExpectedSrc,PasCode.Source);
|
||||
end else begin
|
||||
AssertEquals('convert int i;',true,true);
|
||||
UsesCTypes:='uses ctypes;'+LineEnding;
|
||||
EmpytImplementation:=LineEnding+'implementation'+LineEnding+'end.';
|
||||
Test('convert int i;',
|
||||
'int i;',
|
||||
UsesCTypes+'var i: cint; cvar; external;'+EmpytImplementation);
|
||||
end;
|
||||
|
||||
{Tool.WriteH2PNodeReport;
|
||||
Tool.WriteH2PDirectivesNodeReport;
|
||||
writeln;
|
||||
writeln('=============================================');
|
||||
writeln(PasCode.Source);}
|
||||
finally
|
||||
if Header1<>nil then Header1.IsDeleted:=true;
|
||||
if PasCode<>nil then PasCode.IsDeleted:=true;
|
||||
Tool.Free;
|
||||
end;
|
||||
procedure TTestCodetoolsH2Pas.TestCTH2PConvertEnumsTypes;
|
||||
var
|
||||
UsesCTypes: String;
|
||||
EmpytImplementation: String;
|
||||
begin
|
||||
UsesCTypes:='uses ctypes;'+LineEnding;
|
||||
EmpytImplementation:=LineEnding+'implementation'+LineEnding+'end.';
|
||||
Test('convert anonymous enum{ENUM1};',
|
||||
'enum{ENUM1};',
|
||||
UsesCTypes+'type enumENUM1 = (ENUM1);'+EmpytImplementation);
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
Loading…
Reference in New Issue
Block a user