如何创建一个只包含C模块使用过的输入的列表

wbrvyc0a  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(98)

我有一个很大的模块,它使用一个非常大的输入缓冲区,由许多结构组成,这些结构又包含其他结构,最后每个结构都有几个变量。
在这数百个输入变量中,我的模块(独立的C实体)只使用了一小部分。
我想知道是否有一种方法可以制作一个只包含我的模块中使用的变量的列表(如果它包含变量类型并链接到包含它的结构,那就太完美了)。
我尝试了Doxygen(1.8.5),但我只能用所有输入变量生成一个文档。

**[稍后编辑]**我添加了一个示例代码和所需的结果:

#include <stdio.h>

typedef struct subS1{
    unsigned char bIn1;
    unsigned char bIn2;
} subS1;

typedef struct S1{
    struct subS1 stMySubStruct1;
    struct subS1 stMySubStruct2;
    struct subS1 stMySubStruct3;
} MyInputStruct_t;

void Foo1(MyInputStruct_t *Input);
void Foo2(MyInputStruct_t *Input);

MyInputStruct_t stMyInputStruct = {{1, 2}, {0, 0}, {9, 6}}; // large input buffer

int main() {
    Foo1(&stMyInputStruct); // call to my Module 'main' function
    return 0;
}

void Foo1(MyInputStruct_t *Input)
{
    if(Input->stMySubStruct1.bIn1 == 1)
    {
        printf("bIn1 = %d\n", Input->stMySubStruct1.bIn1); // stMySubStruct1.bIn1 is used (read or write)
    }
    Foo2(Input);
    return;
}

void Foo2(MyInputStruct_t *Input)
{
    if(Input->stMySubStruct3.bIn2 == 0)
    {
        printf("bIn2 = %d\n", Input->stMySubStruct3.bIn2); // stMySubStruct3.bIn2 is used (read or write)
    }
    return;
}

仅包含Foo 1()所用输入的列表:例如,

  • 在Foo 1()中使用了stMyInputStruct.stMySubStruct1.bIn1 -〉
  • 未使用stMyInputStruct.stMySubStruct1.bIn2 -〉
  • ...
  • 在Foo 2()中使用了stMyInputStruct.stMySubStruct3.bIn2 -〉
jtjikinw

jtjikinw1#

这只是一个五分钟的黑客来演示我的意思,所以带着一粒盐和它是什么。
首先我从https://github.com/eliben/pycparser/下载了pycparser
然后编辑https://github.com/eliben/pycparser/blob/master/pycparser/c_generator.py中的C生成器
...向构造函数代码添加两行(添加两个变量struct_refs + struct_ref):

class CGenerator(object):
    """ Uses the same visitor pattern as c_ast.NodeVisitor, but modified to
        return a value from each visit method, using string accumulation in
        generic_visit.
    """
    def __init__(self, reduce_parentheses=False):
        """ Constructs C-code generator
            reduce_parentheses:
                if True, eliminates needless parentheses on binary operators
        """
        # Statements start with indentation of self.indent_level spaces, using
        # the _make_indent method.
        self.indent_level = 0
        self.reduce_parentheses = reduce_parentheses

        # newly added variables here
        self.struct_refs = set()
        self.struct_ref = None

然后我编辑了两个访问者函数,让它们保存关于它们解析的结构引用的信息:

def visit_ID(self, n):
        if self.struct_ref:
            self.struct_refs.add(self.struct_ref + "->" + n.name)
        return n.name

    def visit_StructRef(self, n):
        sref = self._parenthesize_unless_simple(n.name)
        self.struct_ref = sref
        self.struct_refs.add(sref)
        res = sref + n.type + self.visit(n.field)
        self.struct_ref = None
        return res

在示例代码上运行这段修改后的Python脚本,可收集以下信息:

>>> cgen.struct_refs
{'Input',
 'Input->stMySubStruct1',
 'Input->stMySubStruct1->bIn1',
 'Input->stMySubStruct3',
 'Input->stMySubStruct3->bIn2'}

所以再多做一点工作,它应该能够更普遍地完成这项工作。
当然,这在memcpy、结构成员通过指针访问等情况下会被破坏。
你也可以尝试在你的代码中利用结构。例如,如果你总是把你的输入结构称为“Input”,事情会变得更容易。

相关问题