Python 使用PycParser解析c文件时提取输入参数及其标识符类型

Python 使用PycParser解析c文件时提取输入参数及其标识符类型,python,pycparser,Python,Pycparser,注意:熟悉pycparser的人会更好地理解这个问题 我正在使用v2.10和 我试图提取C文件中定义的所有函数,并在解析该C文件时提取其输入参数名称和标识符类型(使用pycparser) 代码示例 import sys sys.path.extend(['.', '..']) CPPPATH = '../utils/cpp.exe' if sys.platform == 'win32' else 'cpp' from pycparser import c_parser, c_ast, parse

注意:熟悉pycparser的人会更好地理解这个问题

我正在使用v2.10和 我试图提取C文件中定义的所有函数,并在解析该C文件时提取其输入参数名称和标识符类型(使用pycparser)

代码示例

import sys
sys.path.extend(['.', '..'])
CPPPATH = '../utils/cpp.exe' if sys.platform == 'win32' else 'cpp'
from pycparser import c_parser, c_ast, parse_file

class FunctionParameter(c_ast.NodeVisitor):

    def visit_FuncDef(self, node):
        #node.decl.type.args.params
        print "Function name is", node.decl.name, "at", node.decl.coord
        print "    It's parameters name  and type is (are)"
        for params in (node.decl.type.args.params):
            print "        ", params.name, params.type


def func_parameter(filename):
    ast = parse_file(filename, use_cpp=True, cpp_path=CPPPATH, cpp_args=r'-I../utils/fake_libc/include')

    vf = FunctionParameter()
    vf.visit(ast)

if __name__ == '__main__':
    if len(sys.argv) > 1:
        filename = sys.argv[1]
    else:
        filename = 'c_files/hash.c'
    func_parameter(filename)
在这里的visit_FuncDef中,我打印函数名,然后在for循环中打印它的参数

问题是,我能够使用for循环中的
params.name
获取传递给函数的输入参数的名称,但无法使用
params.type
获取其标识符类型

有人能告诉我如何提取参数的标识符吗

顺便说一句,输出如下:

Function name is hash_func at c_files/hash.c:32
    It's parameters name  and type is (are)
         str <pycparser.c_ast.PtrDecl object at 0x00000000024EFC88>
         table_size <pycparser.c_ast.TypeDecl object at 0x00000000024EFEF0>
Function name is HashCreate at c_files/hash.c:44
    It's parameters name  and type is (are)
         hash <pycparser.c_ast.PtrDecl object at 0x00000000024FABE0>
         table_size <pycparser.c_ast.TypeDecl object at 0x00000000024FAE48>
Function name is HashInsert at c_files/hash.c:77
    It's parameters name  and type is (are)
         hash <pycparser.c_ast.PtrDecl object at 0x00000000024F99E8>
         entry <pycparser.c_ast.PtrDecl object at 0x00000000024F9BE0>
Function name is HashFind at c_files/hash.c:100
    It's parameters name  and type is (are)
         hash <pycparser.c_ast.PtrDecl object at 0x00000000028C4160>
         key <pycparser.c_ast.PtrDecl object at 0x00000000028C4358>
Function name is HashRemove at c_files/hash.c:117
    It's parameters name  and type is (are)
         hash <pycparser.c_ast.PtrDecl object at 0x00000000028C5780>
         key <pycparser.c_ast.PtrDecl object at 0x00000000028C5978>
Function name is HashPrint at c_files/hash.c:149
    It's parameters name  and type is (are)
         hash <pycparser.c_ast.PtrDecl object at 0x00000000028E9438>
         PrintFunc <pycparser.c_ast.PtrDecl object at 0x00000000028E9668>
Function name is HashDestroy at c_files/hash.c:170
    It's parameters name  and type is (are)
         hash <pycparser.c_ast.PtrDecl object at 0x00000000028EF240>
函数名在c_文件/hash处为hash_func。c:32
它的参数名称和类型为(are)
str
表2尺寸
函数名为HashCreate at c_files/hash.c:44
它的参数名称和类型为(are)
搞砸
表2尺寸
函数名为HashInsert at c_files/hash.c:77
它的参数名称和类型为(are)
搞砸
进入
函数名为HashFind at c_files/hash.c:100
它的参数名称和类型为(are)
搞砸
钥匙
函数名为HashRemove at c_files/hash.c:117
它的参数名称和类型为(are)
搞砸
钥匙
函数名为HashPrint,位于c_files/hash.c:149
它的参数名称和类型为(are)
搞砸
PrintFunc
函数名为HashDestroy at c_files/hash.c:170
它的参数名称和类型为(are)
搞砸
如您所见,这里不是获取标识符类型,而是获取每行中的对象类型。e、 g

示例hash.c文件,我将其用作测试文件(无论如何,它都在pycparser中):

/*
**哈希表ADT的C实现
*/
typedef enum tagReturnCode{SUCCESS,FAIL}ReturnCode;
typedef结构标记项
{
字符*键;
字符*值;
}入境;
typedef结构标记节点
{
条目*条目;
结构标记节点*下一步;
}节点;
typedef结构标记哈希
{
无符号整数表的大小;
节点**头;
}散列;
静态无符号整数哈希函数(常量字符*str,无符号整数表大小)
{
无符号整数散列值;
无符号整数a=127;
对于(哈希值=0;*str!=0;++str)
哈希值=(a*哈希值+*str)%table\u size;
返回哈希值;
}
ReturnCode HashCreate(散列**散列,无符号整数表大小)
{
无符号整数i;
如果(表_尺寸<1)
返回失败;
//
//为哈希分配空间
//
if(((*hash)=malloc(sizeof(**hash))==NULL)
返回失败;
//
//为列表头数组分配空间
//
如果(((*hash)->heads=malloc(table_size*sizeof(*((*hash)->heads)))==NULL)
返回失败;
//
//初始化哈希信息
//
对于(i=0;iheads[i]=NULL;
}
(*散列)->表大小=表大小;
回归成功;
}
返回码哈希插入(哈希*哈希,常量条目*条目)
{
无符号整数索引=哈希函数(条目->键,哈希->表大小);
节点*temp=hash->heads[索引];
HashRemove(散列,条目->键);
if((散列->头[index]=malloc(sizeof(节点)))==NULL)
返回失败;
hash->heads[index]->entry=malloc(sizeof(entry));
hash->heads[index]->entry->key=malloc(strlen(entry->key)+1);
hash->heads[index]->entry->value=malloc(strlen(entry->value)+1);
strcpy(hash->heads[index]->entry->key,entry->key);
strcpy(hash->heads[index]->entry->value,entry->value);
hash->heads[index]->next=temp;
回归成功;
}
常量项*哈希查找(常量哈希*哈希,常量字符*键)
{
无符号整数索引=哈希函数(键,哈希->表大小);
节点*temp=hash->heads[索引];
while(temp!=NULL)
{
如果(!strcmp(键,临时->输入->键))
返回温度->输入;
温度=温度->下一步;
}
返回NULL;
}
ReturnCode HashRemove(散列*散列,常量字符*键)
{
无符号整数索引=哈希函数(键,哈希->表大小);
节点*temp1=hash->heads[索引];
节点*temp2=temp1;
while(temp1!=NULL)
{
如果(!strcmp(键,temp1->entry->key))
{
if(temp1==hash->heads[索引])
哈希->头[索引]=哈希->头[索引]->下一步;
其他的
temp2->next=temp1->next;
自由(temp1->entry->key);
自由(temp1->entry->value);
免费(temp1->entry);
免费(temp1);
temp1=NULL;
回归成功;
}
temp2=temp1;
temp1=temp1->next;
}
返回失败;
}
void HashPrint(Hash*Hash,void(*PrintFunc)(char*,char*))
{
无符号整数i;
if(hash==NULL | | hash->heads==NULL)
返回;
对于(i=0;itable_size;++i)
{
节点*temp=hash->heads[i];
while(temp!=NULL)
{
PrintFunc(临时->输入->键,临时->输入->值);
温度=温度->下一步;
}
}
}
void HashDestroy(散列*散列)
{
无符号整数i;
if(hash==NULL)
返回;
对于(i=0;itable_size;++i)
{
节点*temp=hash->heads[i];
while(temp!=NULL)
{
节点*temp2=temp;
自由(临时->输入->键);
自由(临时->输入->值);
免费(临时->输入);
温度=温度->下一步;
免费(临时2);
}
}    
免费(散列->头);
hash->heads=NULL;
免费(散列);
}

是什么让你认为你没有提取类型

Function name is HashCreate at c_files/hash.c:44
    It's parameters name  and type is (are)
         hash <pycparser.c_ast.PtrDecl object at 0x00000000024FABE0>
         table_size <pycparser.c_ast.TypeDecl object at 0x00000000024FAE48>
函数名是HashCreate at c_files/hash.c:44
它的参数名称和类型为(are)
搞砸
表2尺寸
名称为
table\u size
,类型为
TypeDecl
。类型的简单名称是不支持的
Function name is HashCreate at c_files/hash.c:44
    It's parameters name  and type is (are)
         hash <pycparser.c_ast.PtrDecl object at 0x00000000024FABE0>
         table_size <pycparser.c_ast.TypeDecl object at 0x00000000024FAE48>
def visit_FuncDef(self, node):
    #node.decl.type.args.params
    print "Function name is", node.decl.name, "at", node.decl.coord
    print "    It's parameters name  and type is (are)"
    for params in (node.decl.type.args.params): ###FuncDef/Decl/FuncDecl/ParamList
        # Assign parameter name
        pname = params.name ###ParamList/Decl

        # Parameter is a pointer type of some kind
        if type(params.type) is c_ast.PtrDecl:
            # Parameter is a pointer to a pointer type - double indirection
            if type(params.type.type) is c_ast.PtrDecl:
                ptype = params.type.type.type.type.names ###Decl/PtrDecl/PtrDecl/TypeDecl/IdentifierType
            # There is no double indirection
            else:
                # Parameter is a pointer to a function type
                if type(params.type.type) is c_ast.FuncDecl:
                    pname = str(params.type.type.type.type.names) + ' (*' ###Decl/PtrDecl/TypeDecl/IdentifierType
                    pname = pname + params.type.type.type.declname + ')' ###Decl/PtrDecl/FuncDecl/TypeDecl
                    ptype = ''
                    for subparams in params.type.type.args.params: ###Decl/PtrDecl/FuncDecl/ParamList
                        ptype = ptype + str(subparams.type.type.type.names) ###Typename/PtrDecl/TypeDecl/IdentifierType
                # Parameter is a pointer type - single indirection
                else:
                    ptype = params.type.type.type.names ###Decl/PtrDecl/TypeDecl/IdentifierType

        # Parameter is a variable
        elif type(params.type.type) is c_ast.IdentifierType:
            ptype = params.type.type.names

        print "        ", pname, ptype
  FuncDef: 
    Decl: HashPrint, [], [], []
      FuncDecl: 
        ParamList: 
          Decl: hash, [], [], []
            PtrDecl: []
              TypeDecl: hash, []
                IdentifierType: ['Hash']
          Decl: PrintFunc, [], [], []
            PtrDecl: []
              FuncDecl: 
                ParamList: 
                  Typename: None, []
                    PtrDecl: []
                      TypeDecl: None, []
                        IdentifierType: ['char']
                  Typename: None, []
                    PtrDecl: []
                      TypeDecl: None, []
                        IdentifierType: ['char']
                TypeDecl: PrintFunc, []
                  IdentifierType: ['void']
        TypeDecl: HashPrint, []
          IdentifierType: ['void']
    Compound: 
Function name is hash_func at c_files/hash.c:32
    It's parameters name  and type is (are)
         str ['char']
         table_size ['unsigned', 'int']
Function name is HashCreate at c_files/hash.c:44
    It's parameters name  and type is (are)
         hash ['Hash']
         table_size ['unsigned', 'int']
Function name is HashInsert at c_files/hash.c:77
    It's parameters name  and type is (are)
         hash ['Hash']
         entry ['Entry']
Function name is HashFind at c_files/hash.c:100
    It's parameters name  and type is (are)
         hash ['Hash']
         key ['char']
Function name is HashRemove at c_files/hash.c:117
    It's parameters name  and type is (are)
         hash ['Hash']
         key ['char']
Function name is HashPrint at c_files/hash.c:149
    It's parameters name  and type is (are)
         hash ['Hash']
         ['void'] (*PrintFunc) ['char']['char']
Function name is HashDestroy at c_files/hash.c:170
    It's parameters name  and type is (are)
         hash ['Hash']
file = open('ast.txt', 'w')
ast.show(buf=file)
file.close()