【问题标题】:Extracting C / C++ function prototypes提取 C/C++ 函数原型
【发布时间】:2010-12-06 22:54:45
【问题描述】:

我想这样做:

extract_prototypes file1.c file2.cpp file3.c

并让任何脚本/程序为给定的 C / C++ 文件中定义的所有函数打印一个很好的函数原型列表。它必须很好地处理多行声明。

有没有可以完成这项工作的程序?越简单越好。

编辑:在尝试编译两个 C 程序后,使用 {perl, python, ruby​​} 的东西的奖励积分。

【问题讨论】:

    标签: c++ c function-prototypes


    【解决方案1】:

    我用ctags

    # p = function declaration, f = function definition
    ctags -x --c-kinds=fp /usr/include/hal/libhal.h
    

    也适用于 C++

    ctags -x --c++-kinds=pf --language-force=c++ /usr/include/c++/4.4.1/bits/deque.tcc
    

    注意,您可能需要添加包含路径,请使用 -I /path/to/includes

    【讨论】:

    • 很遗憾您需要过滤结果。否则它将是完美的。结果的形式为
    • 当我使用 try this 时,我收到错误“ctags: unrocognized option '--c-kinds=fp'。我在 Windows 上使用 ctags.exe。知道为什么会出现此错误吗?
    • 这只有在声明没有被打破的情况下才有效,至少在 Exuberant Ctags 5.8 中是这样。
    【解决方案2】:

    cproto 工具可以满足您的需求,并可以根据您的要求调整输出。

    注意:此工具也仅适用于 C 文件。

    【讨论】:

    • 啊,今晚编译东西似乎有问题(在 Mac 上)。不过看起来不错……
    • 不是一个独立的工具。它需要安装 gcc(在 windows 上尝试)。
    • 请注意,由于 gcc 处理丢失的头文件的方式发生了变化,cproto 不再在 gcc 4.5 或更高版本上正常工作。 (gcc.gnu.org/bugzilla/show_bug.cgi?id=55115)
    【解决方案3】:

    我使用ctagsjq

    ctags --output-format=json --totals=no --extras=-F --fields=nP file1.c |
    jq -sr 'sort_by(.line) | .[].pattern | ltrimstr("/^") | rtrimstr("$/") | . + ";"'
    

    【讨论】:

      【解决方案4】:

      http://cfunctions.sourceforge.net

      (这只适用于 C 和 C++ 的有限子集。免责声明:这是我的程序。)

      【讨论】:

      • 这里有一条更有用的信息,以防万一……pastie.org/655762
      • 谢谢。我已经修复了该错误并已将新版本上传到 sourceforge。我在使用 sourceforge 的管理界面时遇到问题,所以我不确定它是否会是默认下载。但是,文件应该在那里。
      • 新版本现在似乎出现在 sourceforge 上。如果您有时间和耐心再试一次,如果您发现任何问题,请告诉我。谷歌群组是groups.google.com/group/cfunctions
      • 不幸的是,仍然无法让它与 c++ 一起工作。
      • 这个项目似乎已经死了。有人知道在哪里可以找到吗?
      【解决方案5】:

      如果您有 Universal-ctags (https://ctags.io),尽管您需要 sed 和 tr 命令来获得所需的内容,但 --_xformat 选项可能很有用。

      $ cat input.c 
      struct object *new_object (struct
                                 /* COMMENT */
                                 param
                                 /* IGNORE ME */
                                 *p)
      {
          return NULL;
      }
      int main (void)
      {
          return 0;
      }
      $ ./ctags -o - --kinds-C=f --kinds-C++=f -x --_xformat='%{typeref} %{name} %{signature};' input.c | tr ':' ' ' | sed -e 's/^typename //'
      struct object * new_object (struct param * p);
      int main (void);
      $
      

      这类似于 Steve Ward 发布的答案,但这个需要 sed,并且需要 tr 而不是 jq。

      【讨论】:

        【解决方案6】:

        我曾经使用 doxygen 为我的 C++ 代码生成文档。我不是专家,但我认为您可以使用 doxygen 生成某种函数原型的索引文件。

        这是一个thread,有人问了类似的问题

        【讨论】:

        • 呸,被打败了。不过我同意:-)
        【解决方案7】:

        gccxml 很有趣,但它会打印一个 xml 树。您需要提取有关类、函数、类型,甚至是类和函数的专门模板的信息。 gccxml 使用 GCC 的解析器,因此您不需要做最糟糕的工作,即解析 C++ 文件,并且您 100% 确定这可能是最好的编译器理解的内容。

        【讨论】:

          【解决方案8】:

          如果你的 cmets 格式合适,你可以试试DOxygen。事实上,如果你在我推荐之前没有尝试过它——它会生成继承图以及完整的成员函数列表和描述(来自你的 cmets)。

          【讨论】:

          • 是的,已经走上了 doxygen 的道路,我正在为这项任务寻找更简单的东西。 (我将把关于 doxygen 优点的讨论留到另一个线程。)
          • 您实际上不必发表任何评论。只需确保您的 Doxyfile 具有为所有成员生成文档的选项已打开。但同意,这是一项相当复杂的工作,尽管 IIRC 有一个 XML 输出选项,您可以尝试解析。
          【解决方案9】:

          gcc-xml 可能会有所帮助,尽管它只完成了你想要的一半工作。您需要对 XML 输出进行一些处理

          【讨论】:

          • rbgccxml 似乎完成了剩下的工作。它使用另一个名为 nokogiri 的 ruby​​ gem 来解析 XML。
          【解决方案10】:

          你可以通过这个程序运行源文件:

          /* cproto_parser.c */
          #include <stdio.h>                           
          int main (void)                              
          {                                            
              int c;                                   
              int infundef = 0;                        
              int nb = 0,                              
                  np = 0;                              
              while((c=getc(stdin))!=EOF){             
                  if(c=='{'){                          
                      if((np==0)&&(nb==0)){infundef=1;}
                      nb++;                            
                  }                                    
                  if (infundef==0) {putc(c,stdout);}   
                  if(c=='}'){                          
                      if((np==0)&&(nb==1)){infundef=0;}
                      nb--;                            
                  }                                    
                  if(c=='('){np++;}                    
                  if(c==')'){np--;}                    
              }                                        
              return 0;                                
          }                    
          

          运行预处理器以摆脱 cmets。如果由于#ifdefs 而导致大括号不匹配,则必须设置定义,请包含文件以使其不如此。

          例如,cc cproto_parser.c -o cproto_parser; cc -E your_source_file.c|./cproto_parser

          【讨论】:

          • 随意将其移植到更合适的语言。
          【解决方案11】:

          在更现代的 GCC 版本中,您还可以在编写 C 代码时使用-aux-info 来获取此信息。见here

          以下是输出的示例:

          /* src/main.c:30:NC */ static void usage (const char *);
          /* src/main.c:32:NF */ extern int main (int argc, char **argv); /* (argc, argv) int argc; char **argv; */
          /* src/main.c:57:NF */ static void usage (const char *prog_name); /* (prog_name) const char *prog_name; */
          

          【讨论】:

            猜你喜欢
            • 2011-06-22
            • 1970-01-01
            • 1970-01-01
            • 2012-07-15
            • 2016-02-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多