mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-02 18:37:38 +01:00
codetools: h2p: implemented #endif
git-svn-id: trunk@14580 -
This commit is contained in:
parent
c305d6c5d1
commit
46bfc75db8
@ -22,6 +22,24 @@
|
||||
|
||||
Abstract:
|
||||
A simple C parser.
|
||||
|
||||
Predefined C macros:
|
||||
__LINE__ current source file line number as decimal
|
||||
__FILE__ current source filename
|
||||
__DATE__ current date: Apr 21 1990 or Jan 1 2008 (note the space in front of the 1)
|
||||
__TIME__ current time "hh:mm:ss"
|
||||
__STDC__ 1
|
||||
|
||||
Predefined gcc macros:
|
||||
__attribute__((packed))
|
||||
Examples:
|
||||
typedef struct {
|
||||
uint8_t b[6];
|
||||
} __attribute__((packed)) bdaddr_t;
|
||||
struct __attribute__((packed)) {
|
||||
typeof(*(ptr)) __v;
|
||||
} *__p = (void *) (ptr);
|
||||
|
||||
}
|
||||
unit CCodeParserTool;
|
||||
|
||||
@ -50,7 +68,7 @@ const
|
||||
ccnNone = 0+ccnBase;
|
||||
|
||||
ccnRoot = 1+ccnBase;
|
||||
ccnDirective = 2+ccnBase;// e.g. "#define a" ,can be multiple lines, without line end
|
||||
ccnDirective = 2+ccnBase;// e.g. "#define a" ,can be multiple lines, EndPos at line end
|
||||
ccnExtern = 3+ccnBase;// e.g. extern "C" {}
|
||||
ccnEnumBlock = 4+ccnBase;// e.g. enum {};
|
||||
ccnEnumID = 5+ccnBase;// e.g. name = value;
|
||||
@ -195,6 +213,7 @@ type
|
||||
function ExtractStructName(StructNode: TCodeTreeNode): string;
|
||||
function ExtractUnionName(UnionNode: TCodeTreeNode): string;
|
||||
function ExtractTypedefName(TypedefNode: TCodeTreeNode): string;
|
||||
function ExtractDirectiveAction(DirectiveNode: TCodeTreeNode): string;
|
||||
|
||||
procedure Replace(FromPos, ToPos: integer; const NewSrc: string);
|
||||
|
||||
@ -412,6 +431,11 @@ procedure TCCodeParserTool.ReadStruct;
|
||||
As variable:
|
||||
struct hidp_conninfo *ci;
|
||||
|
||||
As typecast in macros:
|
||||
struct __attribute__((packed)) {
|
||||
typeof(*(ptr)) __v;
|
||||
} *__p = (void *) (ptr);
|
||||
|
||||
*)
|
||||
begin
|
||||
CreateChildNode(ccnStruct);
|
||||
@ -426,6 +450,14 @@ begin
|
||||
ReadNextAtom;
|
||||
end;
|
||||
|
||||
// read front attributes
|
||||
if AtomIs('__attribute__') then begin
|
||||
ReadNextAtom;
|
||||
if not AtomIsChar('(') then
|
||||
RaiseExpectedButAtomFound('(');
|
||||
ReadTilBracketClose(true);
|
||||
ReadNextAtom;
|
||||
end;
|
||||
if AtomIsChar('{') then begin
|
||||
// read block {}
|
||||
repeat
|
||||
@ -445,7 +477,7 @@ begin
|
||||
else
|
||||
RaiseExpectedButAtomFound('identifier');
|
||||
until false;
|
||||
// read attributes
|
||||
// read after attributes
|
||||
ReadNextAtom;
|
||||
if AtomIs('__attribute__') then begin
|
||||
ReadNextAtom;
|
||||
@ -1582,6 +1614,15 @@ begin
|
||||
Result:=GetIdentifier(@Src[Node.StartPos]);
|
||||
end;
|
||||
|
||||
function TCCodeParserTool.ExtractDirectiveAction(DirectiveNode: TCodeTreeNode
|
||||
): string;
|
||||
begin
|
||||
if DirectiveNode.StartPos<SrcLen then
|
||||
Result:=GetIdentifier(@Src[DirectiveNode.StartPos+1])
|
||||
else
|
||||
Result:='';
|
||||
end;
|
||||
|
||||
function TCCodeParserTool.GetAtom: string;
|
||||
begin
|
||||
Result:=copy(Src,AtomStart,SrcPos-AtomStart);
|
||||
|
||||
@ -91,13 +91,27 @@ type
|
||||
procedure WriteDebugReport(WithChilds: boolean);
|
||||
end;
|
||||
|
||||
TIgnoreCSourcePart = (
|
||||
icspInclude
|
||||
);
|
||||
TIgnoreCSourceParts = set of TIgnoreCSourcePart;
|
||||
|
||||
{ TH2PasTool }
|
||||
|
||||
TH2PasTool = class
|
||||
private
|
||||
FIgnoreCParts: TIgnoreCSourceParts;
|
||||
FPredefinedCTypes: TFPStringHashTable;
|
||||
FPascalNames: TAVLTree;// tree of TH2PNode sorted for PascalName
|
||||
FCNames: TAVLTree;// tree of TH2PNode sorted for CName
|
||||
procedure ConvertStruct(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
procedure ConvertVariable(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
procedure ConvertEnumBlock(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
procedure ConvertFunction(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
procedure ConvertFuncParameter(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
procedure ConvertTypedef(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
procedure ConvertDirective(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
procedure SetIgnoreCParts(const AValue: TIgnoreCSourceParts);
|
||||
public
|
||||
Tree: TH2PTree;
|
||||
CTool: TCCodeParserTool;
|
||||
@ -129,6 +143,7 @@ type
|
||||
destructor Destroy; override;
|
||||
procedure Clear;
|
||||
property PredefinedCTypes: TFPStringHashTable read FPredefinedCTypes;
|
||||
property IgnoreCParts: TIgnoreCSourceParts read FIgnoreCParts write SetIgnoreCParts;
|
||||
end;
|
||||
|
||||
|
||||
@ -259,6 +274,324 @@ end;
|
||||
|
||||
{ TH2PasTool }
|
||||
|
||||
procedure TH2PasTool.ConvertStruct(CNode: TCodeTreeNode; ParentNode: TH2PNode);
|
||||
var
|
||||
CurName: String;
|
||||
TypeH2PNode: TH2PNode;
|
||||
begin
|
||||
CurName:=CTool.ExtractStructName(CNode);
|
||||
if CurName='' then begin
|
||||
// this is an anonymous struct -> ignore
|
||||
DebugLn(['TH2PasTool.ConvertStruct SKIPPING anonymous struct at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end else begin
|
||||
// this struct has a name
|
||||
// create a type
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnRecordType,'',
|
||||
nil,ParentNode=nil);
|
||||
// build recursively
|
||||
BuildH2PTree(TypeH2PNode);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TH2PasTool.ConvertVariable(CNode: TCodeTreeNode; ParentNode: TH2PNode
|
||||
);
|
||||
var
|
||||
CurName: String;
|
||||
TypeH2PNode: TH2PNode;
|
||||
CurType: String;
|
||||
SimpleType: String;
|
||||
H2PNode: TH2PNode;
|
||||
begin
|
||||
if (CNode.FirstChild<>nil) and (CNode.FirstChild.Desc=ccnUnion)
|
||||
then begin
|
||||
CurName:=CTool.ExtractVariableName(CNode);
|
||||
if (ParentNode<>nil) and (ParentNode.PascalDesc=ctnRecordType)
|
||||
then begin
|
||||
// create a pascal 'record case'
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnRecordCase,'',
|
||||
ParentNode,false);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added record case for nested union']);
|
||||
// build recursively the record cases
|
||||
if CNode.FirstChild.FirstChild<>nil then
|
||||
BuildH2PTree(TypeH2PNode,CNode.FirstChild.FirstChild);
|
||||
end else if (CurName<>'') and (ParentNode=nil) then begin
|
||||
// this union has a name
|
||||
// create a record type
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnRecordCase,'',
|
||||
nil,true);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added record type for union: ',TypeH2PNode.DescAsString]);
|
||||
// build recursively
|
||||
if CNode.FirstChild.FirstChild<>nil then
|
||||
BuildH2PTree(TypeH2PNode,CNode.FirstChild.FirstChild);
|
||||
// create variable
|
||||
CurName:=CTool.ExtractUnionName(CNode);
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnVarDefinition,
|
||||
TypeH2PNode.PascalName,
|
||||
nil,ParentNode=nil);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added variable for union: ',H2PNode.DescAsString]);
|
||||
end else begin
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING union variable at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end;
|
||||
end else begin
|
||||
CurName:=CTool.ExtractVariableName(CNode);
|
||||
CurType:=CTool.ExtractVariableType(CNode);
|
||||
SimpleType:=GetSimplePascalTypeOfCVar(CNode);
|
||||
if SimpleType='' then begin
|
||||
// this variable has a complex type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode);
|
||||
if TypeH2PNode<>nil then
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end;
|
||||
if SimpleType<>'' then begin
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnVarDefinition,SimpleType,
|
||||
ParentNode,ParentNode=nil);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added: ',H2PNode.DescAsString]);
|
||||
end else begin
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING Variable Name="',CurName,'" Type="',CurType,'"']);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TH2PasTool.ConvertEnumBlock(CNode: TCodeTreeNode;
|
||||
ParentNode: TH2PNode);
|
||||
var
|
||||
CurName: String;
|
||||
TypeH2PNode: TH2PNode;
|
||||
CurValue: String;
|
||||
H2PNode: TH2PNode;
|
||||
begin
|
||||
CurName:=CTool.ExtractEnumBlockName(CNode);
|
||||
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,'',
|
||||
nil,ParentNode=nil);
|
||||
end else begin
|
||||
// this enum block has a name
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnEnumerationType,'',
|
||||
nil,ParentNode=nil);
|
||||
end;
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added: ',TypeH2PNode.DescAsString]);
|
||||
|
||||
CNode:=CNode.FirstChild;
|
||||
while CNode<>nil do begin
|
||||
if CNode.Desc=ccnEnumID then begin
|
||||
CurName:=CTool.ExtractEnumIDName(CNode);
|
||||
CurValue:=CTool.ExtractEnumIDValue(CNode);
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnEnumIdentifier,CurValue,
|
||||
TypeH2PNode,ParentNode=nil);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added: ',H2PNode.DescAsString]);
|
||||
end;
|
||||
CNode:=CNode.NextBrother;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TH2PasTool.ConvertFunction(CNode: TCodeTreeNode; ParentNode: TH2PNode
|
||||
);
|
||||
var
|
||||
CurName: String;
|
||||
CurType: String;
|
||||
SimpleType: String;
|
||||
IsPointerToFunction: Boolean;
|
||||
Ok: Boolean;
|
||||
StatementNode: TCodeTreeNode;
|
||||
TypeH2PNode: TH2PNode;
|
||||
H2PNode: TH2PNode;
|
||||
begin
|
||||
CurName:=CTool.ExtractFunctionName(CNode);
|
||||
CurType:=CTool.ExtractFunctionResultType(CNode);
|
||||
SimpleType:=GetSimplePascalResultTypeOfCFunction(CNode);
|
||||
IsPointerToFunction:=CTool.IsPointerToFunction(CNode);
|
||||
StatementNode:=nil;
|
||||
Ok:=true;
|
||||
if (CNode.LastChild<>nil) and (CNode.LastChild.Desc=ccnStatementBlock) then
|
||||
StatementNode:=CNode.LastChild;
|
||||
DebugLn(['TH2PasTool.BuildH2PTree Function Name="',CurName,'" ResultType="',CurType,'" SimpleType=',SimpleType,' HasStatements=',StatementNode<>nil,' IsPointer=',IsPointerToFunction]);
|
||||
if StatementNode<>nil then begin
|
||||
// this function has a body
|
||||
Ok:=false;
|
||||
end;
|
||||
if Ok and (SimpleType='') then begin
|
||||
// this function has a complex result type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode);
|
||||
if TypeH2PNode<>nil then begin
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end else
|
||||
Ok:=false;
|
||||
end;
|
||||
|
||||
if Ok then begin
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnProcedure,SimpleType,
|
||||
nil,false);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree function added: ',H2PNode.DescAsString]);
|
||||
// build recursively
|
||||
BuildH2PTree(H2PNode);
|
||||
end else begin
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING Function Name="',CurName,'" Type="',CurType,'" at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TH2PasTool.ConvertFuncParameter(CNode: TCodeTreeNode;
|
||||
ParentNode: TH2PNode);
|
||||
var
|
||||
CurName: String;
|
||||
CurType: String;
|
||||
SimpleType: String;
|
||||
TypeH2PNode: TH2PNode;
|
||||
H2PNode: TH2PNode;
|
||||
begin
|
||||
CurName:=CTool.ExtractParameterName(CNode);
|
||||
CurType:=CTool.ExtractParameterType(CNode);
|
||||
SimpleType:=GetSimplePascalTypeOfCParameter(CNode);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree Parameter: Name="',CurName,'" Type="',CurType,'" SimpleType="',SimpleType,'"']);
|
||||
if SimpleType='' then begin
|
||||
// this variable has a complex type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode);
|
||||
if TypeH2PNode<>nil then
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end;
|
||||
if SimpleType<>'' then begin
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnVarDefinition,SimpleType,
|
||||
ParentNode,false);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added: ',H2PNode.DescAsString]);
|
||||
end else begin
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING parameter Name="',CurName,'" Type="',CurType,'" at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TH2PasTool.ConvertTypedef(CNode: TCodeTreeNode; ParentNode: TH2PNode
|
||||
);
|
||||
var
|
||||
CurName: String;
|
||||
ChildNode: TCodeTreeNode;
|
||||
CurType: String;
|
||||
TypeH2PNode: TH2PNode;
|
||||
IsPointerToFunction: Boolean;
|
||||
SimpleType: String;
|
||||
H2PNode: TH2PNode;
|
||||
begin
|
||||
if CNode.FirstChild=nil then begin
|
||||
exit;
|
||||
end;
|
||||
CurName:=CTool.ExtractTypedefName(CNode);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree Typedef name="',CurName,'"']);
|
||||
ChildNode:=CNode.FirstChild;
|
||||
case ChildNode.Desc of
|
||||
|
||||
ccnStruct: // typedef struct
|
||||
begin
|
||||
ChildNode:=CNode.FirstChild.FirstChild;
|
||||
if (ChildNode<>nil)
|
||||
and (ChildNode.Desc=ccnStructAlias) then begin
|
||||
// this is a struct alias
|
||||
CurType:=GetIdentifier(@CTool.Src[ChildNode.StartPos]);
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,
|
||||
ctnTypeDefinition,CurType);
|
||||
end else begin
|
||||
// this is a new struct
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnRecordType,'');
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added record: ',TypeH2PNode.DescAsString]);
|
||||
// build recursively
|
||||
if ChildNode<>nil then
|
||||
BuildH2PTree(TypeH2PNode,ChildNode);
|
||||
end;
|
||||
end;
|
||||
|
||||
ccnFunction: // typedef function
|
||||
begin
|
||||
CurName:=CTool.ExtractFunctionName(ChildNode);
|
||||
CurType:=CTool.ExtractFunctionResultType(ChildNode,false,false);
|
||||
IsPointerToFunction:=CTool.IsPointerToFunction(ChildNode);
|
||||
SimpleType:=GetSimplePascalResultTypeOfCFunction(ChildNode);
|
||||
if IsPointerToFunction and (SimpleType='') then begin
|
||||
// this function has a complex result type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(ChildNode);
|
||||
if TypeH2PNode<>nil then
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end;
|
||||
if IsPointerToFunction and (SimpleType<>'') then begin
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnProcedureType,SimpleType,
|
||||
nil,true);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree function type added: ',H2PNode.DescAsString]);
|
||||
// build recursively
|
||||
if ChildNode.FirstChild<>nil then
|
||||
BuildH2PTree(H2PNode,ChildNode.FirstChild);
|
||||
end else begin
|
||||
DebugLn(['TH2PasTool.BuildH2PTree typdef function CurName=',CurName,' CurType=',CTool.ExtractFunctionResultType(ChildNode),' SimpleType=',SimpleType]);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING typedef ',CCNodeDescAsString(ChildNode.Desc),' at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end;
|
||||
end;
|
||||
|
||||
else // typedef
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING typedef ',CCNodeDescAsString(CNode.FirstChild.Desc),' at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TH2PasTool.ConvertDirective(CNode: TCodeTreeNode; ParentNode: TH2PNode
|
||||
);
|
||||
var
|
||||
Directive: String;
|
||||
PascalCode: String;
|
||||
H2PNode: TH2PNode;
|
||||
begin
|
||||
Directive:=CTool.ExtractDirectiveAction(CNode);
|
||||
if Directive='include' then begin
|
||||
// #include <filename> // search independent of source position
|
||||
// #include "filename" // search dependent on source position
|
||||
if icspInclude in IgnoreCParts then
|
||||
exit;
|
||||
end else if Directive='define' then begin
|
||||
// #define FMAC(a,b) a here, then b
|
||||
// #define NONFMAC some text here
|
||||
end else if Directive='undef' then begin
|
||||
// #undef NAME
|
||||
end else if Directive='if' then begin
|
||||
// #if EXPRESSION
|
||||
end else if Directive='ifdef' then begin
|
||||
// #ifdef NAME
|
||||
end else if Directive='ifndef' then begin
|
||||
// #ifndef NAME
|
||||
end else if Directive='elif' then begin
|
||||
// #elif EXPRESSION
|
||||
end else if Directive='else' then begin
|
||||
// #else
|
||||
H2PNode:=CreateH2PNode('#else','#else',CNode,ctnNone,
|
||||
'',ParentNode,false);
|
||||
DebugLn(['TH2PasTool.ConvertDirective added $else: ',H2PNode.DescAsString]);
|
||||
exit;
|
||||
end else if Directive='endif' then begin
|
||||
// #endif
|
||||
H2PNode:=CreateH2PNode('#endif','#endif',CNode,ctnNone,
|
||||
'',ParentNode,false);
|
||||
DebugLn(['TH2PasTool.ConvertDirective added $endif: ',H2PNode.DescAsString]);
|
||||
exit;
|
||||
end else if Directive='line' then begin
|
||||
// #line: set the current line number -> ignore
|
||||
exit;
|
||||
end else if Directive='error' then begin
|
||||
// #error
|
||||
PascalCode:=CTool.ExtractCode(CNode.StartPos+length('#error'),
|
||||
CNode.EndPos);
|
||||
H2PNode:=CreateH2PNode('#error','#error',CNode,ctnNone,
|
||||
PascalCode,ParentNode,false);
|
||||
DebugLn(['TH2PasTool.ConvertDirective added $error: ',H2PNode.DescAsString]);
|
||||
exit;
|
||||
end else if Directive='pragma' then begin
|
||||
// #pragma: implementation specifics
|
||||
exit;
|
||||
end else if Directive='' then begin
|
||||
// # : null
|
||||
exit;
|
||||
end;
|
||||
DebugLn(['TH2PasTool.ConvertDirective SKIPPING directive at ',CTool.CleanPosToStr(CNode.StartPos),' Code="',dbgstr(CTool.ExtractCode(CNode.StartPos,CNode.EndPos)),'"']);
|
||||
end;
|
||||
|
||||
procedure TH2PasTool.SetIgnoreCParts(const AValue: TIgnoreCSourceParts);
|
||||
begin
|
||||
if FIgnoreCParts=AValue then exit;
|
||||
FIgnoreCParts:=AValue;
|
||||
end;
|
||||
|
||||
function TH2PasTool.Convert(CCode, PascalCode: TCodeBuffer): boolean;
|
||||
begin
|
||||
Result:=false;
|
||||
@ -278,17 +611,7 @@ procedure TH2PasTool.BuildH2PTree(ParentNode: TH2PNode;
|
||||
StartNode: TCodeTreeNode);
|
||||
var
|
||||
CNode: TCodeTreeNode;
|
||||
CurName: String;
|
||||
CurType: String;
|
||||
SimpleType: String;
|
||||
H2PNode: TH2PNode;
|
||||
NextCNode: TCodeTreeNode;
|
||||
TypeH2PNode: TH2PNode;
|
||||
CurValue: String;
|
||||
StatementNode: TCodeTreeNode;
|
||||
Ok: Boolean;
|
||||
IsPointerToFunction: Boolean;
|
||||
ChildNode: TCodeTreeNode;
|
||||
begin
|
||||
//DebugLn(['TH2PasTool.BuildH2PTree ParentNode=',ParentNode.DescAsString]);
|
||||
if ParentNode<>nil then begin
|
||||
@ -307,220 +630,31 @@ begin
|
||||
ccnRoot, ccnExtern:
|
||||
NextCNode:=CNode.Next;
|
||||
|
||||
ccnDirective:
|
||||
NextCNode:=CNode.Next;
|
||||
|
||||
ccnTypedef:
|
||||
if CNode.FirstChild<>nil then begin
|
||||
CurName:=CTool.ExtractTypedefName(CNode);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree Typedef name="',CurName,'"']);
|
||||
ChildNode:=CNode.FirstChild;
|
||||
case ChildNode.Desc of
|
||||
|
||||
ccnStruct: // typedef struct
|
||||
begin
|
||||
ChildNode:=CNode.FirstChild.FirstChild;
|
||||
if (ChildNode<>nil)
|
||||
and (ChildNode.Desc=ccnStructAlias) then begin
|
||||
// this is a struct alias
|
||||
CurType:=GetIdentifier(@CTool.Src[ChildNode.StartPos]);
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,
|
||||
ctnTypeDefinition,CurType);
|
||||
end else begin
|
||||
// this is a new struct
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnRecordType,'');
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added record: ',TypeH2PNode.DescAsString]);
|
||||
// build recursively
|
||||
if ChildNode<>nil then
|
||||
BuildH2PTree(TypeH2PNode,ChildNode);
|
||||
end;
|
||||
end;
|
||||
|
||||
ccnFunction: // typedef function
|
||||
begin
|
||||
CurName:=CTool.ExtractFunctionName(ChildNode);
|
||||
CurType:=CTool.ExtractFunctionResultType(ChildNode,false,false);
|
||||
IsPointerToFunction:=CTool.IsPointerToFunction(ChildNode);
|
||||
SimpleType:=GetSimplePascalResultTypeOfCFunction(ChildNode);
|
||||
if IsPointerToFunction and (SimpleType='') then begin
|
||||
// this function has a complex result type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(ChildNode);
|
||||
if TypeH2PNode<>nil then
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end;
|
||||
if IsPointerToFunction and (SimpleType<>'') then begin
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnProcedureType,SimpleType,
|
||||
nil,true);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree function type added: ',H2PNode.DescAsString]);
|
||||
// build recursively
|
||||
if ChildNode.FirstChild<>nil then
|
||||
BuildH2PTree(H2PNode,ChildNode.FirstChild);
|
||||
end else begin
|
||||
DebugLn(['TH2PasTool.BuildH2PTree typdef function CurName=',CurName,' CurType=',CTool.ExtractFunctionResultType(ChildNode),' SimpleType=',SimpleType]);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING typedef ',CCNodeDescAsString(ChildNode.Desc),' at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end;
|
||||
end;
|
||||
|
||||
else // typedef
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING typedef ',CCNodeDescAsString(CNode.FirstChild.Desc),' at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end;
|
||||
end;
|
||||
|
||||
ConvertTypedef(CNode,ParentNode);
|
||||
|
||||
ccnVariable:
|
||||
if (CNode.FirstChild<>nil) and (CNode.FirstChild.Desc=ccnUnion)
|
||||
then begin
|
||||
CurName:=CTool.ExtractVariableName(CNode);
|
||||
if (ParentNode<>nil) and (ParentNode.PascalDesc=ctnRecordType)
|
||||
then begin
|
||||
// create a pascal 'record case'
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnRecordCase,'',
|
||||
ParentNode,false);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added record case for nested union']);
|
||||
// build recursively the record cases
|
||||
if CNode.FirstChild.FirstChild<>nil then
|
||||
BuildH2PTree(TypeH2PNode,CNode.FirstChild.FirstChild);
|
||||
end else if (CurName<>'') and (ParentNode=nil) then begin
|
||||
// this union has a name
|
||||
// create a record type
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnRecordCase,'',
|
||||
nil,true);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added record type for union: ',TypeH2PNode.DescAsString]);
|
||||
// build recursively
|
||||
if CNode.FirstChild.FirstChild<>nil then
|
||||
BuildH2PTree(TypeH2PNode,CNode.FirstChild.FirstChild);
|
||||
// create variable
|
||||
CurName:=CTool.ExtractUnionName(CNode);
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnVarDefinition,
|
||||
TypeH2PNode.PascalName,
|
||||
nil,ParentNode=nil);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added variable for union: ',H2PNode.DescAsString]);
|
||||
end else begin
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING union variable at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end;
|
||||
end else begin
|
||||
CurName:=CTool.ExtractVariableName(CNode);
|
||||
CurType:=CTool.ExtractVariableType(CNode);
|
||||
SimpleType:=GetSimplePascalTypeOfCVar(CNode);
|
||||
if SimpleType='' then begin
|
||||
// this variable has a complex type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode);
|
||||
if TypeH2PNode<>nil then
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end;
|
||||
if SimpleType<>'' then begin
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnVarDefinition,SimpleType,
|
||||
ParentNode,ParentNode=nil);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added: ',H2PNode.DescAsString]);
|
||||
end else begin
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING Variable Name="',CurName,'" Type="',CurType,'"']);
|
||||
end;
|
||||
end;
|
||||
|
||||
ConvertVariable(CNode,ParentNode);
|
||||
|
||||
ccnFunction:
|
||||
begin
|
||||
CurName:=CTool.ExtractFunctionName(CNode);
|
||||
CurType:=CTool.ExtractFunctionResultType(CNode);
|
||||
SimpleType:=GetSimplePascalResultTypeOfCFunction(CNode);
|
||||
IsPointerToFunction:=CTool.IsPointerToFunction(CNode);
|
||||
StatementNode:=nil;
|
||||
Ok:=true;
|
||||
if (CNode.LastChild<>nil) and (CNode.LastChild.Desc=ccnStatementBlock) then
|
||||
StatementNode:=CNode.LastChild;
|
||||
DebugLn(['TH2PasTool.BuildH2PTree Function Name="',CurName,'" ResultType="',CurType,'" SimpleType=',SimpleType,' HasStatements=',StatementNode<>nil,' IsPointer=',IsPointerToFunction]);
|
||||
if StatementNode<>nil then begin
|
||||
// this function has a body
|
||||
Ok:=false;
|
||||
end;
|
||||
if Ok and (SimpleType='') then begin
|
||||
// this function has a complex result type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode);
|
||||
if TypeH2PNode<>nil then begin
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end else
|
||||
Ok:=false;
|
||||
end;
|
||||
|
||||
if Ok then begin
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnProcedure,SimpleType,
|
||||
nil,false);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree function added: ',H2PNode.DescAsString]);
|
||||
// build recursively
|
||||
BuildH2PTree(H2PNode);
|
||||
end else begin
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING Function Name="',CurName,'" Type="',CurType,'" at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end;
|
||||
end;
|
||||
|
||||
ConvertFunction(CNode,ParentNode);
|
||||
|
||||
ccnFuncParamList:
|
||||
NextCNode:=CNode.FirstChild;
|
||||
|
||||
ccnFuncParameter:
|
||||
begin
|
||||
CurName:=CTool.ExtractParameterName(CNode);
|
||||
CurType:=CTool.ExtractParameterType(CNode);
|
||||
SimpleType:=GetSimplePascalTypeOfCParameter(CNode);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree Parameter: Name="',CurName,'" Type="',CurType,'" SimpleType="',SimpleType,'"']);
|
||||
if SimpleType='' then begin
|
||||
// this variable has a complex type
|
||||
TypeH2PNode:=GetH2PNodeForComplexType(CNode);
|
||||
if TypeH2PNode<>nil then
|
||||
SimpleType:=TypeH2PNode.PascalName;
|
||||
end;
|
||||
if SimpleType<>'' then begin
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnVarDefinition,SimpleType,
|
||||
ParentNode,false);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added: ',H2PNode.DescAsString]);
|
||||
end else begin
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING parameter Name="',CurName,'" Type="',CurType,'" at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end;
|
||||
end;
|
||||
|
||||
ccnEnumBlock:
|
||||
begin
|
||||
CurName:=CTool.ExtractEnumBlockName(CNode);
|
||||
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,'',
|
||||
nil,ParentNode=nil);
|
||||
end else begin
|
||||
// this enum block has a name
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnEnumerationType,'',
|
||||
nil,ParentNode=nil);
|
||||
end;
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added: ',TypeH2PNode.DescAsString]);
|
||||
ConvertFuncParameter(CNode,ParentNode);
|
||||
|
||||
ccnEnumBlock:
|
||||
ConvertEnumBlock(CNode,ParentNode);
|
||||
|
||||
CNode:=CNode.FirstChild;
|
||||
while CNode<>nil do begin
|
||||
if CNode.Desc=ccnEnumID then begin
|
||||
CurName:=CTool.ExtractEnumIDName(CNode);
|
||||
CurValue:=CTool.ExtractEnumIDValue(CNode);
|
||||
H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnEnumIdentifier,CurValue,
|
||||
TypeH2PNode,ParentNode=nil);
|
||||
DebugLn(['TH2PasTool.BuildH2PTree added: ',H2PNode.DescAsString]);
|
||||
end;
|
||||
CNode:=CNode.NextBrother;
|
||||
end;
|
||||
end;
|
||||
|
||||
ccnStruct:
|
||||
begin
|
||||
CurName:=CTool.ExtractStructName(CNode);
|
||||
if CurName='' then begin
|
||||
// this is an anonymous struct -> ignore
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING anonymous struct at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end else begin
|
||||
// this struct has a name
|
||||
// create a type
|
||||
TypeH2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnRecordType,'',
|
||||
nil,ParentNode=nil);
|
||||
// build recursively
|
||||
BuildH2PTree(TypeH2PNode);
|
||||
end;
|
||||
end;
|
||||
ConvertStruct(CNode,ParentNode);
|
||||
|
||||
ccnName: ;
|
||||
|
||||
ccnDirective:
|
||||
ConvertDirective(CNode,ParentNode);
|
||||
else
|
||||
DebugLn(['TH2PasTool.BuildH2PTree SKIPPING ',CCNodeDescAsString(CNode.Desc),' at ',CTool.CleanPosToStr(CNode.StartPos)]);
|
||||
end;
|
||||
@ -902,6 +1036,7 @@ begin
|
||||
Tree:=TH2PTree.Create;
|
||||
FPascalNames:=TAVLTree.Create(@CompareH2PNodePascalNames);
|
||||
FCNames:=TAVLTree.Create(@CompareH2PNodeCNames);
|
||||
FIgnoreCParts:=[icspInclude];
|
||||
end;
|
||||
|
||||
destructor TH2PasTool.Destroy;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user