【问题标题】:Are there any tools for parsing a c header file and extract a function protoype from a c header file是否有任何工具可以解析c头文件并从c头文件中提取函数原型
【发布时间】:2011-09-11 12:12:33
【问题描述】:

特别是获取函数的返回类型(如果可能,是否为指针类型)。

(我正在尝试编写 ioctl/dlsym 包装器库的自动生成(被 LD_PRELOAD 编辑))。首选 python 或 ruby​​ 库,但欢迎任何可行的解决方案。

【问题讨论】:

  • Doxygen 能够生成 XML 文件,而 IIRC 函数的返回类型本身就是一个字段。如果您没有得到更有用的答案,您可以对此进行调查。
  • Doxygen 如何知道返回类型是否为指针,尤其是。如果返回类型简单地命名为其他地方声明的 typedef?

标签: c parsing code-generation


【解决方案1】:

我们的DMS Software Reengineering Toolkit 及其C Front End 很容易做到这一点。

DMS 使用语言定义(在本例中为 C 语言)来解析源代码、构建抽象语法树、确定表达式类型并构建完整的符号表。它还可以将 AST 漂亮地打印回有效的语言文本(例如 C 代码)。您可以轻松找到函数声明,并从符号表条目中收集您想要的任何内容(“返回类型是指针吗?”),和/或将声明打印为原型。如果您想打印一个实际上不依赖于实际文件中其他定义的原型,您可能会发现您需要规范化符号;这需要为各种类型声明构建 AST 并将它们相互替换。我们过去曾为其他客户这样做过,并且这种机器可用于 C 前端。

【讨论】:

    【解决方案2】:

    cproto 程序执行此操作。请注意,有两个不同的版本:

    直到最近,GCC 还包含一个程序 protoize 可以完成这项工作(并将 K&R 函数定义转换为 ISO 原型函数定义);不过,它不再是 GCC 发行版的一部分。

    【讨论】:

      【解决方案3】:

      我已经成功地使用来自 hackage 的 Haskells Language.C 包(Haskells 对 CPAN 的回答)来做类似的事情。它将为您提供 C(或头文件)文件的完整解析树,然后可以遍历该文件以提取所需的信息。它应该也适用于#includes #defines 等等。

      恐怕我没有安装相关的软件来测试它,但它会是这样的:

      handler (DeclEvent (Declaration d)) =
      do
      let (VarDecl varName declAttr t) = getVarDecl d
      case t of 
           (FunctionType (FunType returnType params isVaradic attrs)) -> 
              do {- varName RETURNS returnType .... -}
               _ -> do return ()
          return ()
      handler _ = 
          do return ()
      
      main = do    
          let compiler = newGCC "gcc"
          ast <- parseCFile compiler Nothing opts cFileName
          case (runTrav newState (withExtDeclHandler (analyseAST ast) handler)) of
              ...
      

      上面的内容可能看起来很吓人,但您可能不需要那么多行的 Haskell 来做您想做的事!如果有帮助的话,我很乐意分享我使用的完整源代码(约 200 行)。

      【讨论】:

      • 安装有帮助吗?即使在 cabal install happy 工作之后,cabal install language-c 也会给出“cabal:happy is required but it could not be found”。
      • 我现在正在尝试将 language.c 用于项目。如果您的答案中仍然有 sn-p 的完整源代码,那可能会对我有很大帮助。
      • @dohaqatar7:给你:pastebin.com/7ihKY0KV我对质量不做任何声明。它是在 2009 年为大学作业写的,所以它可能不是一流的 haskell :)
      • 感谢您分享您的作品!该代码对理解 Language.C 有很大帮助。我已经完成了解析,只需要处理代码生成,但这可能要等到决赛之后。
      【解决方案4】:

      您正在寻找的似乎是一种轻松生成任意 c 代码的Abstract Syntax Tree 的方法。为此(如果你熟悉 python),我建议使用pycparser:

      parser = CParser()
      
      buf = '''
        static void foo(int k)
        {
            j = p && r || q;
            return j;
        }
      '''
      
      t = parser.parse(buf, 'x.c')
      t.show()
      

      生成:

      FileAST:
        FuncDef:
          Decl: foo, [], ['static']
            FuncDecl:
              ParamList:
                Decl: k, [], []
                  TypeDecl: k, []
                    IdentifierType: ['int']
              TypeDecl: foo, []
                IdentifierType: ['void']
          Compound:
            Assignment: =
              ID: j
              BinaryOp: ||
                BinaryOp: &&
                  ID: p
                  ID: r
                ID: q
            Return:
              ID: j
      

      每个编译器都会这样做,并且大多数编译器都提供了一个 api 来访问它们的各种解析/语义检查例程。此外,任何常用的解析器生成器都应该具有可用于解析 c 的语法。如果您担心性能和/或希望保持在 c 范围内,我建议您查看:

      • clang:在 llvm 架构上相当完整的 C 实现,支持大多数 gcc 扩展。从 C 代码生成 AST 非常容易。您可以在 clang 中编译为 lib 并直接使用 AST,或者让 clang 二进制文件将它们转储到标准输出。
      • gcc(我个人会选择 clang;更干净)。
      • Antlr(解析器生成器;许多现有的 c 解决方案在互联网上流传)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-04
        • 2019-04-23
        • 1970-01-01
        • 2020-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-29
        相关资源
        最近更新 更多