mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-16 18:49:19 +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
|
var
|
||||||
NameNode: TCodeTreeNode;
|
NameNode: TCodeTreeNode;
|
||||||
s: String;
|
s: String;
|
||||||
|
AfterNameNode: TCodeTreeNode;
|
||||||
|
StartPos: Integer;
|
||||||
begin
|
begin
|
||||||
|
Result:='';
|
||||||
NameNode:=GetFirstNameNode(VarNode);
|
NameNode:=GetFirstNameNode(VarNode);
|
||||||
if (NameNode=nil) then
|
if (NameNode<>nil) then begin
|
||||||
Result:=''
|
|
||||||
else begin
|
|
||||||
Result:=ExtractCode(VarNode.StartPos,NameNode.StartPos,WithDirectives);
|
Result:=ExtractCode(VarNode.StartPos,NameNode.StartPos,WithDirectives);
|
||||||
if (NameNode.NextBrother<>nil)
|
AfterNameNode:=NameNode.NextBrother;
|
||||||
and (NameNode.NextBrother.Desc=ccnConstant) then begin
|
StartPos:=NameNode.EndPos;
|
||||||
// a variable with an initial value
|
end else begin
|
||||||
// omit the constant
|
AfterNameNode:=VarNode.FirstChild;
|
||||||
s:=ExtractCode(NameNode.EndPos,NameNode.NextBrother.StartPos,
|
StartPos:=VarNode.StartPos;
|
||||||
WithDirectives);
|
end;
|
||||||
s:=copy(s,1,length(s)-1);
|
if (AfterNameNode<>nil)
|
||||||
Result:=Result+s;
|
and (AfterNameNode.Desc=ccnConstant) then begin
|
||||||
end else begin
|
// omit constant
|
||||||
Result:=Result+ExtractCode(NameNode.EndPos,VarNode.EndPos,
|
s:=ExtractCode(StartPos,AfterNameNode.StartPos,WithDirectives);
|
||||||
WithDirectives);
|
if (s<>'') and (s[length(s)]='=') then
|
||||||
end;
|
s:=Trim(copy(s,1,length(s)-1));
|
||||||
|
Result:=Result+s;
|
||||||
|
end else begin
|
||||||
|
Result:=Result+ExtractCode(StartPos,VarNode.EndPos,WithDirectives);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2544,7 +2548,7 @@ begin
|
|||||||
if Tree<>nil then begin
|
if Tree<>nil then begin
|
||||||
Node:=Tree.Root;
|
Node:=Tree.Root;
|
||||||
while Node<>nil do begin
|
while Node<>nil do begin
|
||||||
DebugLn([GetNodeIndent(CurNode)+NodeAsString(Node)]);
|
DebugLn([GetNodeIndent(Node)+NodeAsString(Node)]);
|
||||||
Node:=Node.Next;
|
Node:=Node.Next;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -194,7 +194,7 @@ type
|
|||||||
// converting C nodes to H2P nodes
|
// converting C nodes to H2P nodes
|
||||||
procedure ConvertStruct(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
procedure ConvertStruct(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||||
procedure ConvertVariable(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 ConvertFunction(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||||
procedure ConvertFuncParameter(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
procedure ConvertFuncParameter(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||||
procedure ConvertTypedef(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
procedure ConvertTypedef(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||||
@ -268,7 +268,7 @@ type
|
|||||||
PascalDesc: TCodeTreeNodeDesc; const PascalCode: string;
|
PascalDesc: TCodeTreeNodeDesc; const PascalCode: string;
|
||||||
ParentNode: TH2PNode; IsGlobal: boolean;
|
ParentNode: TH2PNode; IsGlobal: boolean;
|
||||||
InsertAsPreLast: boolean): TH2PNode;
|
InsertAsPreLast: boolean): TH2PNode;
|
||||||
function GetH2PNodeForComplexType(CNode: TCodeTreeNode;
|
function CreateH2PNodeForComplexType(CNode: TCodeTreeNode;
|
||||||
CreateIfNotExists: boolean;
|
CreateIfNotExists: boolean;
|
||||||
InsertAsPreLast: boolean): TH2PNode;
|
InsertAsPreLast: boolean): TH2PNode;
|
||||||
function CreatePascalNameFromCCode(const CCode: string;
|
function CreatePascalNameFromCCode(const CCode: string;
|
||||||
@ -580,31 +580,32 @@ begin
|
|||||||
end;
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
CurName:=CTool.ExtractDefinitionName(CNode);
|
CurName:=CTool.ExtractDefinitionName(CNode);
|
||||||
CurType:=CTool.ExtractDefinitionType(CNode);
|
|
||||||
SimpleType:=GetSimplePascalTypeOfCVar(CNode);
|
SimpleType:=GetSimplePascalTypeOfCVar(CNode);
|
||||||
if SimpleType='' then begin
|
if SimpleType='' then begin
|
||||||
// this variable has a complex type
|
// this variable has a complex type
|
||||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode,true,ParentNode<>nil);
|
TypeH2PNode:=CreateH2PNodeForComplexType(CNode,true,ParentNode<>nil);
|
||||||
if TypeH2PNode<>nil then
|
if TypeH2PNode<>nil then
|
||||||
SimpleType:=TypeH2PNode.PascalName;
|
SimpleType:=TypeH2PNode.PascalName;
|
||||||
end;
|
end;
|
||||||
if SimpleType<>'' then begin
|
if CurName<>'' then begin
|
||||||
CurCName:=CurName;
|
if SimpleType<>'' then begin
|
||||||
H2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnVarDefinition,SimpleType,
|
CurCName:=CurName;
|
||||||
ParentNode,ParentNode=nil);
|
H2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnVarDefinition,SimpleType,
|
||||||
DebugLn(['TH2PasTool.ConvertVariable CurName=',CurName,' ',H2PNode.PascalName]);
|
ParentNode,ParentNode=nil);
|
||||||
DebugLn(['TH2PasTool.ConvertVariable added: ',H2PNode.DescAsString(CTool)]);
|
DebugLn(['TH2PasTool.ConvertVariable CurName=',CurName,' ',H2PNode.PascalName]);
|
||||||
end else begin
|
DebugLn(['TH2PasTool.ConvertVariable added: ',H2PNode.DescAsString(CTool)]);
|
||||||
DebugLn(['TH2PasTool.ConvertVariable SKIPPING Variable Name="',CurName,'" Type="',CurType,'"']);
|
end else begin
|
||||||
|
CurType:=CTool.ExtractDefinitionType(CNode);
|
||||||
|
DebugLn(['TH2PasTool.ConvertVariable SKIPPING Variable Name="',CurName,'" Type="',CurType,'"']);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TH2PasTool.ConvertEnumBlock(CNode: TCodeTreeNode;
|
function TH2PasTool.ConvertEnumBlock(CNode: TCodeTreeNode; ParentNode: TH2PNode
|
||||||
ParentNode: TH2PNode);
|
): TH2PNode;
|
||||||
var
|
var
|
||||||
CurName: String;
|
CurName: String;
|
||||||
TypeH2PNode: TH2PNode;
|
|
||||||
CurValue: String;
|
CurValue: String;
|
||||||
H2PNode: TH2PNode;
|
H2PNode: TH2PNode;
|
||||||
CurCName: String;
|
CurCName: String;
|
||||||
@ -613,15 +614,15 @@ begin
|
|||||||
if CurName='' then begin
|
if CurName='' then begin
|
||||||
// this is an anonymous enum block => auto generate a name
|
// this is an anonymous enum block => auto generate a name
|
||||||
CurName:=CreatePascalNameFromCCode(CTool.Src,CNode.StartPos,CNode.EndPos);
|
CurName:=CreatePascalNameFromCCode(CTool.Src,CNode.StartPos,CNode.EndPos);
|
||||||
TypeH2PNode:=CreateAutoGeneratedH2PNode(CurName,CNode,ctnEnumerationType,'',
|
Result:=CreateAutoGeneratedH2PNode(CurName,CNode,ctnEnumerationType,'',
|
||||||
nil,true,ParentNode<>nil);
|
nil,true,ParentNode<>nil);
|
||||||
end else begin
|
end else begin
|
||||||
// this enum block has a name
|
// this enum block has a name
|
||||||
CurCName:=CurName;
|
CurCName:=CurName;
|
||||||
TypeH2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnEnumerationType,'',
|
Result:=CreateH2PNode(CurName,CurCName,CNode,ctnEnumerationType,'',
|
||||||
nil,true);
|
nil,true);
|
||||||
end;
|
end;
|
||||||
DebugLn(['TH2PasTool.ConvertEnumBlock added: ',TypeH2PNode.DescAsString(CTool)]);
|
DebugLn(['TH2PasTool.ConvertEnumBlock added: ',Result.DescAsString(CTool)]);
|
||||||
|
|
||||||
CNode:=CNode.FirstChild;
|
CNode:=CNode.FirstChild;
|
||||||
while CNode<>nil do begin
|
while CNode<>nil do begin
|
||||||
@ -630,7 +631,7 @@ begin
|
|||||||
CurValue:=CTool.ExtractEnumIDValue(CNode);
|
CurValue:=CTool.ExtractEnumIDValue(CNode);
|
||||||
CurCName:=CurName;
|
CurCName:=CurName;
|
||||||
H2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnEnumIdentifier,CurValue,
|
H2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnEnumIdentifier,CurValue,
|
||||||
TypeH2PNode,true);
|
Result,true);
|
||||||
DebugLn(['TH2PasTool.ConvertEnumBlock added: ',H2PNode.DescAsString(CTool)]);
|
DebugLn(['TH2PasTool.ConvertEnumBlock added: ',H2PNode.DescAsString(CTool)]);
|
||||||
end;
|
end;
|
||||||
CNode:=CNode.NextBrother;
|
CNode:=CNode.NextBrother;
|
||||||
@ -666,7 +667,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
if Ok and (SimpleType='') then begin
|
if Ok and (SimpleType='') then begin
|
||||||
// this function has a complex result type
|
// this function has a complex result type
|
||||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode,true,ParentNode<>nil);
|
TypeH2PNode:=CreateH2PNodeForComplexType(CNode,true,ParentNode<>nil);
|
||||||
if TypeH2PNode<>nil then begin
|
if TypeH2PNode<>nil then begin
|
||||||
SimpleType:=TypeH2PNode.PascalName;
|
SimpleType:=TypeH2PNode.PascalName;
|
||||||
end else
|
end else
|
||||||
@ -724,7 +725,7 @@ begin
|
|||||||
DebugLn(['TH2PasTool.ConvertFuncParameter Parameter: Name="',CurName,'" Type="',CurType,'" SimpleType="',SimpleType,'"']);
|
DebugLn(['TH2PasTool.ConvertFuncParameter Parameter: Name="',CurName,'" Type="',CurType,'" SimpleType="',SimpleType,'"']);
|
||||||
if SimpleType='' then begin
|
if SimpleType='' then begin
|
||||||
// this variable has a complex type
|
// this variable has a complex type
|
||||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode,true,true);
|
TypeH2PNode:=CreateH2PNodeForComplexType(CNode,true,true);
|
||||||
if TypeH2PNode<>nil then
|
if TypeH2PNode<>nil then
|
||||||
SimpleType:=TypeH2PNode.PascalName;
|
SimpleType:=TypeH2PNode.PascalName;
|
||||||
end;
|
end;
|
||||||
@ -768,7 +769,7 @@ begin
|
|||||||
SimpleType:=GetSimplePascalTypeOfCVar(ChildNode);
|
SimpleType:=GetSimplePascalTypeOfCVar(ChildNode);
|
||||||
if SimpleType='' then begin
|
if SimpleType='' then begin
|
||||||
// this variable has a complex type
|
// this variable has a complex type
|
||||||
TypeH2PNode:=GetH2PNodeForComplexType(ChildNode,true,ParentNode<>nil);
|
TypeH2PNode:=CreateH2PNodeForComplexType(ChildNode,true,ParentNode<>nil);
|
||||||
if TypeH2PNode<>nil then
|
if TypeH2PNode<>nil then
|
||||||
SimpleType:=TypeH2PNode.PascalName;
|
SimpleType:=TypeH2PNode.PascalName;
|
||||||
end;
|
end;
|
||||||
@ -838,7 +839,7 @@ begin
|
|||||||
SimpleType:=GetSimplePascalResultTypeOfCFunction(ChildNode);
|
SimpleType:=GetSimplePascalResultTypeOfCFunction(ChildNode);
|
||||||
if IsPointerToFunction and (SimpleType='') then begin
|
if IsPointerToFunction and (SimpleType='') then begin
|
||||||
// this function has a complex result type
|
// this function has a complex result type
|
||||||
TypeH2PNode:=GetH2PNodeForComplexType(ChildNode,true,ParentNode<>nil);
|
TypeH2PNode:=CreateH2PNodeForComplexType(ChildNode,true,ParentNode<>nil);
|
||||||
if TypeH2PNode<>nil then
|
if TypeH2PNode<>nil then
|
||||||
SimpleType:=TypeH2PNode.PascalName;
|
SimpleType:=TypeH2PNode.PascalName;
|
||||||
end;
|
end;
|
||||||
@ -2395,7 +2396,7 @@ begin
|
|||||||
inc(i);
|
inc(i);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TH2PasTool.GetH2PNodeForComplexType(CNode: TCodeTreeNode;
|
function TH2PasTool.CreateH2PNodeForComplexType(CNode: TCodeTreeNode;
|
||||||
CreateIfNotExists: boolean; InsertAsPreLast: boolean): TH2PNode;
|
CreateIfNotExists: boolean; InsertAsPreLast: boolean): TH2PNode;
|
||||||
var
|
var
|
||||||
CCode: String;
|
CCode: String;
|
||||||
@ -2414,144 +2415,156 @@ var
|
|||||||
ConstantNumber: int64;
|
ConstantNumber: int64;
|
||||||
BracketOpenPos: LongInt;
|
BracketOpenPos: LongInt;
|
||||||
NeedH2PNode: Boolean;
|
NeedH2PNode: Boolean;
|
||||||
|
SubCNode: TCodeTreeNode;
|
||||||
begin
|
begin
|
||||||
Result:=nil;
|
Result:=nil;
|
||||||
if (CNode.Desc=ccnDefinition)
|
if (CNode.Desc=ccnDefinition) and (CNode.FirstChild<>nil) then begin
|
||||||
and (CNode.FirstChild<>nil)
|
SubCNode:=CNode.FirstChild;
|
||||||
and (CNode.FirstChild.Desc=ccnUnion) then begin
|
if SubCNode.Desc=ccnName then
|
||||||
// ToDo: union
|
SubCNode:=SubCNode.NextBrother;
|
||||||
end else begin
|
if (SubCNode<>nil) then begin
|
||||||
SubH2PNode:=nil;
|
if (SubCNode.Desc=ccnEnumBlock) then begin
|
||||||
if CNode.Desc=ccnDefinition then
|
Result:=ConvertEnumBlock(SubCNode,nil);
|
||||||
CCode:=CTool.ExtractDefinitionType(CNode)
|
exit;
|
||||||
else if CNode.Desc=ccnFunction then
|
end;
|
||||||
CCode:=CTool.ExtractFunctionResultType(CNode)
|
if SubCNode.Desc<>ccnConstant then begin
|
||||||
else if CNode.Desc=ccnFuncParameter then
|
debugln(['TH2PasTool.GetH2PNodeForComplexType TODO: ',CCNodeDescAsString(CNode.Desc),' of ',CCNodeDescAsString(SubCNode.Desc)]);
|
||||||
CCode:=CTool.ExtractParameterType(CNode)
|
exit;
|
||||||
else
|
|
||||||
exit;
|
|
||||||
|
|
||||||
DebugLn(['TH2PasTool.GetH2PNodeForComplexType CCode="',CCode,'"']);
|
|
||||||
{ int[][3] -> array of array[0..2] of cint
|
|
||||||
char** -> PPchar
|
|
||||||
int *[15] -> array[0..14] of pcint
|
|
||||||
|
|
||||||
}
|
|
||||||
// read identifiers
|
|
||||||
p:=1;
|
|
||||||
BaseCType:='';
|
|
||||||
repeat
|
|
||||||
ReadRawNextCAtom(CCode,p,AtomStart);
|
|
||||||
if AtomStart>length(CCode) then break;
|
|
||||||
if IsIdentStartChar[CCode[AtomStart]] then begin
|
|
||||||
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
|
|
||||||
if BaseCType<>'' then
|
|
||||||
BaseCType:=BaseCType+' ';
|
|
||||||
BaseCType:=BaseCType+CurAtom;
|
|
||||||
end else
|
|
||||||
break;
|
|
||||||
until false;
|
|
||||||
if BaseCType='' then begin
|
|
||||||
DebugLn(['TH2PasTool.GetH2PNodeForComplexType no base type in c declaration: CCode="',dbgstr(CCode),'"']);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
BasePascalType:=ConvertSimpleCTypeToPascalType(BaseCType,true);
|
|
||||||
if (BasePascalType='') then begin
|
|
||||||
DebugLn(['TH2PasTool.GetH2PNodeForComplexType unknown c type: "',BaseCType,'"']);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
DebugLn(['TH2PasTool.GetH2PNodeForComplexType BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
|
|
||||||
|
|
||||||
// read pointer(s)
|
|
||||||
while (AtomStart<=length(CCode)) do begin
|
|
||||||
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
|
|
||||||
if (CurAtom='*') then begin
|
|
||||||
BaseCType:=BaseCType+'*';
|
|
||||||
NewBasePascalType:=ConvertSimpleCTypeToPascalType(BaseCType,true);
|
|
||||||
if NewBasePascalType<>'' then begin
|
|
||||||
// for this pointer type exists already a predefined simple type
|
|
||||||
end else begin
|
|
||||||
// a new pointer type is needed
|
|
||||||
NewBasePascalType:='P'+BasePascalType;
|
|
||||||
SubH2PNode:=CreateAutoGeneratedH2PNode(NewBasePascalType,nil,
|
|
||||||
ctnTypeDefinition,'^'+BasePascalType,
|
|
||||||
nil,true,InsertAsPreLast);
|
|
||||||
DebugLn(['TH2PasTool.GetH2PNodeForComplexType added new pointer type: ',SubH2PNode.DescAsString(CTool)]);
|
|
||||||
NewBasePascalType:=SubH2PNode.PascalName;
|
|
||||||
end;
|
|
||||||
BasePascalType:=NewBasePascalType;
|
|
||||||
DebugLn(['TH2PasTool.GetH2PNodeForComplexType using pointer type: BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
|
|
||||||
end else if (CurAtom='const') then begin
|
|
||||||
// skip 'const'
|
|
||||||
end else begin
|
|
||||||
break;
|
|
||||||
end;
|
end;
|
||||||
ReadRawNextCAtom(CCode,p,AtomStart);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PascalName:=BasePascalType;
|
|
||||||
PascalCode:=PascalName;
|
|
||||||
|
|
||||||
// read arrays
|
|
||||||
NeedH2PNode:=false;
|
|
||||||
while (AtomStart<=length(CCode)) do begin
|
|
||||||
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
|
|
||||||
if CurAtom='[' then begin
|
|
||||||
NeedH2PNode:=true;
|
|
||||||
BracketOpenPos:=AtomStart;
|
|
||||||
ReadRawNextCAtom(CCode,p,AtomStart);
|
|
||||||
if AtomStart>length(CCode) then begin
|
|
||||||
DebugLn(['TH2PasTool.GetH2PNodeForComplexType untranslatable (missing ]): CCode="',dbgstr(CCode),'"']);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
|
|
||||||
if CurAtom=']' then begin
|
|
||||||
// [] -> open array
|
|
||||||
PascalCode:='array of '+PascalCode;
|
|
||||||
PascalName:='ArrayOf'+PascalName;
|
|
||||||
//DebugLn(['TH2PasTool.GetTypeForVarType open array: ',PascalCode]);
|
|
||||||
end else begin
|
|
||||||
// [constant] -> array[0..constant-1]
|
|
||||||
ConstantStartPos:=AtomStart;
|
|
||||||
p:=BracketOpenPos;
|
|
||||||
ReadTilCBracketClose(CCode,p);
|
|
||||||
ConstantEndPos:=p-1;
|
|
||||||
ConstantCode:=copy(CCode,ConstantStartPos,ConstantEndPos-ConstantStartPos);
|
|
||||||
//DebugLn(['TH2PasTool.GetTypeForVarType ConstantCode="',ConstantCode,'"']);
|
|
||||||
if CConstantToInt64(ConstantCode,ConstantNumber) then begin
|
|
||||||
if ConstantNumber>0 then
|
|
||||||
dec(ConstantNumber)
|
|
||||||
else
|
|
||||||
ConstantNumber:=0;
|
|
||||||
ConstantCode:=IntToStr(ConstantNumber);
|
|
||||||
end else begin
|
|
||||||
ConstantCode:=ConstantCode+'-1';
|
|
||||||
end;
|
|
||||||
PascalCode:='array[0..'+ConstantCode+'] of '+PascalCode;
|
|
||||||
PascalName:='Array0to'+CreatePascalNameFromCCode(ConstantCode)+'Of'+PascalName;
|
|
||||||
//DebugLn(['TH2PasTool.GetTypeForVarType fixed array: ',PascalCode]);
|
|
||||||
end;
|
|
||||||
end else
|
|
||||||
break;
|
|
||||||
ReadRawNextCAtom(CCode,p,AtomStart);
|
|
||||||
end;
|
|
||||||
if NeedH2PNode then begin
|
|
||||||
PascalName:='T'+PascalName;
|
|
||||||
PascalName:=copy(PascalName,1,DefaultMaxPascalIdentLen);
|
|
||||||
SubH2PNode:=CreateAutoGeneratedH2PNode(PascalName,nil,ctnTypeDefinition,
|
|
||||||
PascalCode,nil,true,InsertAsPreLast);
|
|
||||||
end;
|
|
||||||
|
|
||||||
// check if the whole declaration was translated
|
|
||||||
if AtomStart<=length(CCode) then begin
|
|
||||||
// unknown C type
|
|
||||||
DebugLn(['TH2PasTool.GetTypeForVarType untranslatable: CCode="',dbgstr(CCode),'"']);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
DebugLn(['TH2PasTool.GetTypeForVarType CCode="',dbgstr(CCode),'" PascalName="',PascalName,'"']);
|
|
||||||
Result:=SubH2PNode;
|
|
||||||
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
|
||||||
|
CCode:=CTool.ExtractFunctionResultType(CNode)
|
||||||
|
else if CNode.Desc=ccnFuncParameter then
|
||||||
|
CCode:=CTool.ExtractParameterType(CNode)
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
|
||||||
|
DebugLn(['TH2PasTool.GetH2PNodeForComplexType CCode="',CCode,'"']);
|
||||||
|
{ int[][3] -> array of array[0..2] of cint
|
||||||
|
char** -> PPchar
|
||||||
|
int *[15] -> array[0..14] of pcint
|
||||||
|
|
||||||
|
}
|
||||||
|
// read identifiers
|
||||||
|
p:=1;
|
||||||
|
BaseCType:='';
|
||||||
|
repeat
|
||||||
|
ReadRawNextCAtom(CCode,p,AtomStart);
|
||||||
|
if AtomStart>length(CCode) then break;
|
||||||
|
if IsIdentStartChar[CCode[AtomStart]] then begin
|
||||||
|
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
|
||||||
|
if BaseCType<>'' then
|
||||||
|
BaseCType:=BaseCType+' ';
|
||||||
|
BaseCType:=BaseCType+CurAtom;
|
||||||
|
end else
|
||||||
|
break;
|
||||||
|
until false;
|
||||||
|
if BaseCType='' then begin
|
||||||
|
DebugLn(['TH2PasTool.GetH2PNodeForComplexType no base type in c declaration: CCode="',dbgstr(CCode),'"']);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
BasePascalType:=ConvertSimpleCTypeToPascalType(BaseCType,true);
|
||||||
|
if (BasePascalType='') then begin
|
||||||
|
DebugLn(['TH2PasTool.GetH2PNodeForComplexType unknown c type: "',BaseCType,'"']);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
DebugLn(['TH2PasTool.GetH2PNodeForComplexType BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
|
||||||
|
|
||||||
|
// read pointer(s)
|
||||||
|
while (AtomStart<=length(CCode)) do begin
|
||||||
|
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
|
||||||
|
if (CurAtom='*') then begin
|
||||||
|
BaseCType:=BaseCType+'*';
|
||||||
|
NewBasePascalType:=ConvertSimpleCTypeToPascalType(BaseCType,true);
|
||||||
|
if NewBasePascalType<>'' then begin
|
||||||
|
// for this pointer type exists already a predefined simple type
|
||||||
|
end else begin
|
||||||
|
// a new pointer type is needed
|
||||||
|
NewBasePascalType:='P'+BasePascalType;
|
||||||
|
SubH2PNode:=CreateAutoGeneratedH2PNode(NewBasePascalType,nil,
|
||||||
|
ctnTypeDefinition,'^'+BasePascalType,
|
||||||
|
nil,true,InsertAsPreLast);
|
||||||
|
DebugLn(['TH2PasTool.GetH2PNodeForComplexType added new pointer type: ',SubH2PNode.DescAsString(CTool)]);
|
||||||
|
NewBasePascalType:=SubH2PNode.PascalName;
|
||||||
|
end;
|
||||||
|
BasePascalType:=NewBasePascalType;
|
||||||
|
DebugLn(['TH2PasTool.GetH2PNodeForComplexType using pointer type: BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
|
||||||
|
end else if (CurAtom='const') then begin
|
||||||
|
// skip 'const'
|
||||||
|
end else begin
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
ReadRawNextCAtom(CCode,p,AtomStart);
|
||||||
|
end;
|
||||||
|
|
||||||
|
PascalName:=BasePascalType;
|
||||||
|
PascalCode:=PascalName;
|
||||||
|
|
||||||
|
// read arrays
|
||||||
|
NeedH2PNode:=false;
|
||||||
|
while (AtomStart<=length(CCode)) do begin
|
||||||
|
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
|
||||||
|
if CurAtom='[' then begin
|
||||||
|
NeedH2PNode:=true;
|
||||||
|
BracketOpenPos:=AtomStart;
|
||||||
|
ReadRawNextCAtom(CCode,p,AtomStart);
|
||||||
|
if AtomStart>length(CCode) then begin
|
||||||
|
DebugLn(['TH2PasTool.GetH2PNodeForComplexType untranslatable (missing ]): CCode="',dbgstr(CCode),'"']);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
|
||||||
|
if CurAtom=']' then begin
|
||||||
|
// [] -> open array
|
||||||
|
PascalCode:='array of '+PascalCode;
|
||||||
|
PascalName:='ArrayOf'+PascalName;
|
||||||
|
//DebugLn(['TH2PasTool.GetTypeForVarType open array: ',PascalCode]);
|
||||||
|
end else begin
|
||||||
|
// [constant] -> array[0..constant-1]
|
||||||
|
ConstantStartPos:=AtomStart;
|
||||||
|
p:=BracketOpenPos;
|
||||||
|
ReadTilCBracketClose(CCode,p);
|
||||||
|
ConstantEndPos:=p-1;
|
||||||
|
ConstantCode:=copy(CCode,ConstantStartPos,ConstantEndPos-ConstantStartPos);
|
||||||
|
//DebugLn(['TH2PasTool.GetTypeForVarType ConstantCode="',ConstantCode,'"']);
|
||||||
|
if CConstantToInt64(ConstantCode,ConstantNumber) then begin
|
||||||
|
if ConstantNumber>0 then
|
||||||
|
dec(ConstantNumber)
|
||||||
|
else
|
||||||
|
ConstantNumber:=0;
|
||||||
|
ConstantCode:=IntToStr(ConstantNumber);
|
||||||
|
end else begin
|
||||||
|
ConstantCode:=ConstantCode+'-1';
|
||||||
|
end;
|
||||||
|
PascalCode:='array[0..'+ConstantCode+'] of '+PascalCode;
|
||||||
|
PascalName:='Array0to'+CreatePascalNameFromCCode(ConstantCode)+'Of'+PascalName;
|
||||||
|
//DebugLn(['TH2PasTool.GetTypeForVarType fixed array: ',PascalCode]);
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
break;
|
||||||
|
ReadRawNextCAtom(CCode,p,AtomStart);
|
||||||
|
end;
|
||||||
|
if NeedH2PNode then begin
|
||||||
|
PascalName:='T'+PascalName;
|
||||||
|
PascalName:=copy(PascalName,1,DefaultMaxPascalIdentLen);
|
||||||
|
SubH2PNode:=CreateAutoGeneratedH2PNode(PascalName,nil,ctnTypeDefinition,
|
||||||
|
PascalCode,nil,true,InsertAsPreLast);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// check if the whole declaration was translated
|
||||||
|
if AtomStart<=length(CCode) then begin
|
||||||
|
// unknown C type
|
||||||
|
DebugLn(['TH2PasTool.GetTypeForVarType untranslatable: CCode="',dbgstr(CCode),'"']);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
DebugLn(['TH2PasTool.GetTypeForVarType CCode="',dbgstr(CCode),'" PascalName="',PascalName,'"']);
|
||||||
|
Result:=SubH2PNode;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TH2PasTool.CreatePascalNameFromCCode(const CCode: string;
|
function TH2PasTool.CreatePascalNameFromCCode(const CCode: string;
|
||||||
@ -2670,6 +2683,7 @@ begin
|
|||||||
end else if (Tree.Root=nil) then begin
|
end else if (Tree.Root=nil) then begin
|
||||||
DebugLn(['TH2PasTool.WriteH2PNodeReport Tree.Root=nil']);
|
DebugLn(['TH2PasTool.WriteH2PNodeReport Tree.Root=nil']);
|
||||||
end else begin
|
end else begin
|
||||||
|
//debugln(['TH2PasTool.WriteH2PNodeReport ']);
|
||||||
Node:=Tree.Root;
|
Node:=Tree.Root;
|
||||||
while Node<>nil do begin
|
while Node<>nil do begin
|
||||||
DebugLn([GetIndentStr(Node.GetLevel*2),Node.DescAsString(CTool)]);
|
DebugLn([GetIndentStr(Node.GetLevel*2),Node.DescAsString(CTool)]);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
./runtests --format=plain --suite=TestCTH2PMergeHeaderFiles
|
./runtests --format=plain --suite=TestCTH2PMergeHeaderFiles
|
||||||
./runtests --format=plain --suite=TestCTH2PReplaceMacros
|
./runtests --format=plain --suite=TestCTH2PReplaceMacros
|
||||||
./runtests --format=plain --suite=TestCTH2PConvertSimpleTypes
|
./runtests --format=plain --suite=TestCTH2PConvertSimpleTypes
|
||||||
|
./runtests --format=plain --suite=TestCTH2PConvertEnumsTypes
|
||||||
}
|
}
|
||||||
unit TestCTH2Pas;
|
unit TestCTH2Pas;
|
||||||
|
|
||||||
@ -23,16 +24,50 @@ type
|
|||||||
|
|
||||||
TTestCodetoolsH2Pas = class(TTestCase)
|
TTestCodetoolsH2Pas = class(TTestCase)
|
||||||
protected
|
protected
|
||||||
|
procedure Test(Title, CHeaderSrc, ExpectedPasSrc: string);
|
||||||
published
|
published
|
||||||
procedure TestCTH2PMergeHeaderFiles;
|
procedure TestCTH2PMergeHeaderFiles;
|
||||||
procedure TestCTH2PReplaceMacros;
|
procedure TestCTH2PReplaceMacros;
|
||||||
procedure TestCTH2PConvertSimpleTypes;
|
procedure TestCTH2PConvertSimpleTypes;
|
||||||
|
procedure TestCTH2PConvertEnumsTypes;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
{ TTestCodetoolsH2Pas }
|
{ 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;
|
procedure TTestCodetoolsH2Pas.TestCTH2PMergeHeaderFiles;
|
||||||
var
|
var
|
||||||
Header1, Header2: TCodeBuffer;
|
Header1, Header2: TCodeBuffer;
|
||||||
@ -116,41 +151,26 @@ end;
|
|||||||
|
|
||||||
procedure TTestCodetoolsH2Pas.TestCTH2PConvertSimpleTypes;
|
procedure TTestCodetoolsH2Pas.TestCTH2PConvertSimpleTypes;
|
||||||
var
|
var
|
||||||
Tool: TH2PasTool;
|
UsesCTypes: String;
|
||||||
Header1: TCodeBuffer;
|
EmpytImplementation: String;
|
||||||
PasCode: TCodeBuffer;
|
|
||||||
ExpectedSrc: String;
|
|
||||||
begin
|
begin
|
||||||
Tool:=TH2PasTool.Create;
|
UsesCTypes:='uses ctypes;'+LineEnding;
|
||||||
Header1:=nil;
|
EmpytImplementation:=LineEnding+'implementation'+LineEnding+'end.';
|
||||||
PasCode:=nil;
|
Test('convert int i;',
|
||||||
try
|
'int i;',
|
||||||
Header1:=CodeToolBoss.CreateFile('header1.h');
|
UsesCTypes+'var i: cint; cvar; external;'+EmpytImplementation);
|
||||||
PasCode:=CodeToolBoss.CreateFile('header1.pas');
|
end;
|
||||||
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);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{Tool.WriteH2PNodeReport;
|
procedure TTestCodetoolsH2Pas.TestCTH2PConvertEnumsTypes;
|
||||||
Tool.WriteH2PDirectivesNodeReport;
|
var
|
||||||
writeln;
|
UsesCTypes: String;
|
||||||
writeln('=============================================');
|
EmpytImplementation: String;
|
||||||
writeln(PasCode.Source);}
|
begin
|
||||||
finally
|
UsesCTypes:='uses ctypes;'+LineEnding;
|
||||||
if Header1<>nil then Header1.IsDeleted:=true;
|
EmpytImplementation:=LineEnding+'implementation'+LineEnding+'end.';
|
||||||
if PasCode<>nil then PasCode.IsDeleted:=true;
|
Test('convert anonymous enum{ENUM1};',
|
||||||
Tool.Free;
|
'enum{ENUM1};',
|
||||||
end;
|
UsesCTypes+'type enumENUM1 = (ENUM1);'+EmpytImplementation);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
|
Loading…
Reference in New Issue
Block a user