diff --git a/components/codetools/ccodeparsertool.pas b/components/codetools/ccodeparsertool.pas index c29b5386e0..150e240d16 100644 --- a/components/codetools/ccodeparsertool.pas +++ b/components/codetools/ccodeparsertool.pas @@ -183,6 +183,9 @@ type function ExtractFunctionResultType(FuncNode: TCodeTreeNode; WithDirectives: boolean = false): string; function IsPointerToFunction(FuncNode: TCodeTreeNode): boolean; + function ExtractParameterName(ParamNode: TCodeTreeNode): string; + function ExtractParameterType(ParamNode: TCodeTreeNode; + WithDirectives: boolean = false): string; function ExtractEnumBlockName(EnumBlockNode: TCodeTreeNode): string; function ExtractEnumIDName(EnumIDNode: TCodeTreeNode): string; function ExtractEnumIDValue(EnumIDNode: TCodeTreeNode; @@ -605,8 +608,9 @@ begin end; procedure TCCodeParserTool.ReadConstant; +// ends on last atom of constant begin - if AtomIsChar(',') or AtomIsChar(';') then + if AtomIsChar(',') or AtomIsChar(';') or AtomIsChar(')') then RaiseExpectedButAtomFound('identifier'); CreateChildNode(ccnConstant); repeat @@ -820,8 +824,8 @@ begin SrcPos:=AtomStart+1; RaiseException('closing bracket not found'); end; - if AtomIs(')') then break; - if AtomIs(',') then + if AtomIsChar(')') then break; + if AtomIsChar(',') then RaiseExpectedButAtomFound('parameter type'); // read parameter CreateChildNode(ccnFuncParameter); @@ -833,12 +837,12 @@ begin NamePos:=0; repeat if AtomStart>SrcLen then break; - if AtomIs(')') then begin + if AtomIsChar(')') then begin // end of parameter list break; end else if AtomIs('[') then ReadTilBracketClose(true) - else if AtomIs(',') then + else if AtomIsChar(',') then break else if IsIdentStartChar[Src[AtomStart]] then begin if NamePos>0 then @@ -869,12 +873,17 @@ begin EndChildNode; end; end; + end else if AtomIsChar('=') then begin + if TypePos<1 then + RaiseExpectedButAtomFound('type'); + ReadNextAtom; + ReadConstant; end; CurNode.EndPos:=SrcPos; ReadNextAtom; until false; EndChildNode; - until AtomIs(')'); + until AtomIsChar(')'); CurNode.EndPos:=SrcPos; EndChildNode; end; @@ -1320,7 +1329,7 @@ begin // a variable with an initial value // omit the constant s:=ExtractCode(NameNode.EndPos,NameNode.NextBrother.StartPos, - WithDirectives); + WithDirectives); s:=copy(s,1,length(s)-1); Result:=Result+s; end else begin @@ -1420,6 +1429,57 @@ begin Result:=false; end; +function TCCodeParserTool.ExtractParameterName(ParamNode: TCodeTreeNode + ): string; +var + NameNode: TCodeTreeNode; +begin + NameNode:=GetFirstNameNode(ParamNode); + if (NameNode=nil) then + Result:='' + else + Result:=copy(Src,NameNode.StartPos,NameNode.EndPos-NameNode.StartPos); +end; + +function TCCodeParserTool.ExtractParameterType(ParamNode: TCodeTreeNode; + WithDirectives: boolean): string; +var + NameNode: TCodeTreeNode; + s: String; + ConstantNode: TCodeTreeNode; +begin + NameNode:=GetFirstNameNode(ParamNode); + if (ParamNode.LastChild<>nil) + and (ParamNode.LastChild.Desc=ccnConstant) then + ConstantNode:=ParamNode.LastChild + else + ConstantNode:=nil; + if (NameNode=nil) then begin + if ConstantNode<>nil then begin + // a parameter with an initial value + // omit the constant + Result:=ExtractCode(ParamNode.StartPos,ConstantNode.StartPos,WithDirectives); + Result:=copy(Result,1,length(Result)-1); + end else begin + Result:=ExtractCode(ParamNode.StartPos,ParamNode.EndPos,WithDirectives); + end; + end else begin + Result:=ExtractCode(ParamNode.StartPos,NameNode.StartPos,WithDirectives); + if (NameNode.NextBrother<>nil) + and (NameNode.NextBrother.Desc=ccnConstant) then begin + // a parameter with an initial value + // omit the constant + s:=ExtractCode(NameNode.EndPos,NameNode.NextBrother.StartPos, + WithDirectives); + s:=copy(s,1,length(s)-1); + Result:=Result+s; + end else begin + Result:=Result+ExtractCode(NameNode.EndPos,ParamNode.EndPos, + WithDirectives); + end; + end; +end; + function TCCodeParserTool.ExtractEnumBlockName(EnumBlockNode: TCodeTreeNode ): string; var diff --git a/components/codetools/examples/scanexamples/test.h b/components/codetools/examples/scanexamples/test.h index 81504dbf9c..fa23bc6ab1 100644 --- a/components/codetools/examples/scanexamples/test.h +++ b/components/codetools/examples/scanexamples/test.h @@ -141,6 +141,7 @@ char ** ppc; // pointer to pointer to char int* ap[15]; // array of 15 pointers to ints int (*fp)(char*); // pointer to function taking a char* argument; returns an int int * f(char*); // function taking a char* argument; returns a pointer to int +int func2(int=3); // function taking an int argument or no argument; returns an int unsigned short unsigned_short; unsigned long long unsigned_long_long; diff --git a/components/codetools/h2pastool.pas b/components/codetools/h2pastool.pas index 1d8e0176fc..b0885161db 100644 --- a/components/codetools/h2pastool.pas +++ b/components/codetools/h2pastool.pas @@ -345,28 +345,38 @@ begin Ok:=false; end; - NextCNode:=CNode.NextSkipChilds; if Ok then begin H2PNode:=CreateH2PNode(CurName,CurName,CNode,ctnProcedure,SimpleType, ParentNode,ParentNode=nil); - DebugLn(['TH2PasTool.BuildH2PTree added: ',H2PNode.DescAsString]); - CNode:=CNode.FirstChild; - while (CNode<>nil) and (CNode.Desc<>ccnFuncParamList) do - CNode:=CNode.NextBrother; - if CNode<>nil then begin - CNode:=CNode.FirstChild; - while CNode<>nil do begin - if CNode.Desc=ccnFuncParameter then begin - CurType:=CTool.ExtractCode(CNode.StartPos,CNode.EndPos); - DebugLn(['TH2PasTool.BuildH2PTree Parameter="',CurType,'"']); - end; - CNode:=CNode.NextBrother; - end; - end; + DebugLn(['TH2PasTool.BuildH2PTree function added: ',H2PNode.DescAsString]); + // build recursively + BuildH2PTree(H2PNode); end else begin DebugLn(['TH2PasTool.BuildH2PTree SKIPPING Function Name="',CurName,'" Type="',CurType,'"']); end; end; + ccnFuncParamList: + NextCNode:=CNode.FirstChild; + ccnFuncParameter: + begin + CurName:=CTool.ExtractParameterName(CNode); + CurType:=CTool.ExtractParameterType(CNode); + SimpleType:=GetSimplePascalTypeOfCVar(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,'"']); + end; + end; ccnEnumBlock: begin CurName:=CTool.ExtractEnumBlockName(CNode); @@ -381,7 +391,7 @@ begin ParentNode,ParentNode=nil); end; DebugLn(['TH2PasTool.BuildH2PTree added: ',TypeH2PNode.DescAsString]); - NextCNode:=CNode.NextSkipChilds; + CNode:=CNode.FirstChild; while CNode<>nil do begin if CNode.Desc=ccnEnumID then begin @@ -560,10 +570,12 @@ begin CCode:=CTool.ExtractVariableType(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.GetTypeForVarType CCode="',CCode,'"']); + DebugLn(['TH2PasTool.GetH2PNodeForComplexType CCode="',CCode,'"']); { int[][3] -> array of array[0..2] of cint char** -> PPchar int *[15] -> array[0..14] of pcint @@ -584,15 +596,15 @@ begin break; until false; if BaseCType='' then begin - DebugLn(['TH2PasTool.GetTypeForVarType no base type in c declaration: CCode="',dbgstr(CCode),'"']); + DebugLn(['TH2PasTool.GetH2PNodeForComplexType no base type in c declaration: CCode="',dbgstr(CCode),'"']); exit; end; BasePascalType:=ConvertSimpleCTypeToPascalType(BaseCType,true); if (BasePascalType='') then begin - DebugLn(['TH2PasTool.GetTypeForVarType unknown c type: "',BaseCType,'"']); + DebugLn(['TH2PasTool.GetH2PNodeForComplexType unknown c type: "',BaseCType,'"']); exit; end; - DebugLn(['TH2PasTool.GetTypeForVarType BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']); + DebugLn(['TH2PasTool.GetH2PNodeForComplexType BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']); // read pointer(s) while (AtomStart<=length(CCode)) do begin @@ -607,11 +619,11 @@ begin NewBasePascalType:='P'+BasePascalType; SubH2PNode:=CreateAutoGeneratedH2PNode(NewBasePascalType,nil, ctnTypeDefinition,'^'+BasePascalType); - DebugLn(['TH2PasTool.GetTypeForVarType added new pointer type: ',SubH2PNode.DescAsString]); + DebugLn(['TH2PasTool.GetH2PNodeForComplexType added new pointer type: ',SubH2PNode.DescAsString]); NewBasePascalType:=SubH2PNode.PascalName; end; BasePascalType:=NewBasePascalType; - DebugLn(['TH2PasTool.GetTypeForVarType using pointer type: BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']); + DebugLn(['TH2PasTool.GetH2PNodeForComplexType using pointer type: BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']); end else if (CurAtom='const') then begin // skip 'const' end else begin @@ -632,7 +644,7 @@ begin BracketOpenPos:=AtomStart; ReadRawNextCAtom(CCode,p,AtomStart); if AtomStart>length(CCode) then begin - DebugLn(['TH2PasTool.GetTypeForVarType untranslatable (missing ]): CCode="',dbgstr(CCode),'"']); + DebugLn(['TH2PasTool.GetH2PNodeForComplexType untranslatable (missing ]): CCode="',dbgstr(CCode),'"']); exit; end; CurAtom:=copy(CCode,AtomStart,p-AtomStart);