如何在源代码

时间:2016-02-29 12:58:09

标签: c++ c grep

我正在寻找一种在项目的C / C ++代码中搜索给定术语的方法,同时忽略注释和字符串中的任何出现。

由于代码库相当大,我正在寻找一种方法自动识别与我的搜索词匹配的代码行,因为它们需要手动检查。

如果可能,我想在我的linux系统上执行搜索。

背景

有问题的代码库是一个带有大量第三方插件的实时信号处理引擎。插件是用各种语言实现的(主要是C语言,还有C ++和其他语言;目前我只关心这两种语言),没有执行任何标准。

我们的代码库目前使用内置类型float作为浮点数,我们希望将其替换为允许我们使用双精度的typedef。 我们希望在实际代码中找到float的所有匹配项(忽略评论和打印输出中的合法用法)。

更进一步的是,在代码有效负载中有float的某些(虽然很少)合法使用(所以我们真的在寻找一种方法来识别所有的地方需要手动检查,而不是运行一些自动搜索和替换。)

代码还包含到(float)的C样式静态强制转换,因此依靠编译器警告来识别类型不匹配通常不是一种选择。

代码库包含超过3000个(C和C ++)文件,累积约750000行代码。

代码是跨平台的(linux,osx,w32是主要目标;但也是freebsd和类似的),并使用各种本机编译器(gcc / g ++,clang / clang ++,VisualStudio,...)进行编译

到目前为止......

到目前为止,我正在使用丑陋的东西:

 grep "\bfloat\b" | sed -e 's|//.*||' -e 's|"[^"]*"||g' | grep "\bfloat\b"

但我认为必须是搜索有效负载代码的更好方法。

3 个答案:

答案 0 :(得分:5)

恕我直言,在“Unix& Linux”上的类似问题上有一个很好的答案:

  

grep适用于纯文本,并且对此没有任何了解   C程序的基础语法。因此,为了不搜索   在评论中你有几个选择:

     
      
  1. 在搜索之前删除C-comments,您可以使用gcc执行此操作   -fpreprocessed -dD -E yourfile.c有关详细信息,请参阅Remove comments from C/C++ code

  2.   
  3. 编写/使用您已经找到的一些hacky半工作脚本   (例如,他们通过跳过以//或/ *开头的行来工作)   处理所有可能的C / C ++注释的细节(再次,请参阅   一些可怕的测试用例的上一个链接)。然后你仍然可能有假   积极的,但你不必预先处理任何事情。

  4.   
  5. 使用更高级的工具在代码中进行“语义搜索”。一世   找到了“coccigrep”:http://home.regit.org/software/coccigrep/这个   一种工具允许搜索某些特定的语言语句   (即更新具有给定名称的结构),当然也就是他们   删除评论。

  6.   

https://unix.stackexchange.com/a/33136/158220

虽然它并没有完全涵盖你的“不在字符串”的要求。

答案 1 :(得分:3)

它实际上可能取决于代码库的大小,也可能取决于您通常使用的编辑器。我建议使用GNU emacs(如果可能的话,在Linux上使用最近的GCC编译器...)

对于中小型代码(例如小于300KLOC),我建议使用Emacs的grep mode。然后(假设您已将next-error Emacs函数绑定到某个键,可能是(global-set-key [f10] 'next-error)中的~/.emacs ...),您可以快速扫描float的每次出现(偶数)在字符串或注释中,但你会很快跳过这样的事情......)。几个小时后,您将完成中等大小的源代码(这比学习如何使用新工具更快)。

对于大型代码(数百万行),可能需要自定义一些静态分析工具或编译器。您可以使用GCC MELT在Linux上自定义GCC编译器。其findgimple mode可能具有启发性,甚至可能非常有用(您可能希望找到针对float的所有Gimple分配)

顺便说一下,你可能不想用float取代double类型的所有次出现 - 但只有大多数}(可能适当{{} 1}} - ed ...),因为很可能你正在使用一些外部(或标准)函数需要一个typedef

CADNA工具可能也很有用,可以帮助您估算结果的精确度(这样可以帮助您决定何时使用float是合理的)。

使用GCC MELT中提到的CADNACoccinelleFrama-CFluctuat(或许Coccigrepg0hl1n's answer等语义工具}}会给出更精确或相关的结果,代价是花费更多时间(可能是几天!)来学习和定制工具。

答案 2 :(得分:1)

执行此操作的有效方法应该是EMP_ID FIRSTNAME LASTNAME SALARY ADDRESS_ID START_DATE END_DATE 1 Bob Way 55000 6 2010-06-10-12:00 2010-06-10-12:03 null Bob Way 50000 6 2010-06-10-12:03 null http://cscope.sourceforge.net/)使用cscope选项的面向行的模式,但我还没有在各种各样的C标准,如果这对您不起作用,或者如果您无法获得find this C symbol,请执行以下操作:

cscope

第一个find . -type f -print | while IFS= read -r file do sed 's/a/aA/g;s/__/aB/g;s/#/aC/g' "$file" | gcc -P -E - | sed 's/aC/#/g;s/aB/__/g;s/aA/a/g' | awk -v file="$file" -v OFS=': ' '/\<float\>/{print file, $0}' done 替换所有带有唯一标识符字符串的哈希(sed)和#符号,以便预处理器不会对#include进行任何扩展等。但我们可以在预处理后恢复它们。

__预处理输出以删除注释。

第二个gcc替换了我们之前使用实际哈希符号添加的哈希标识符字符串。

sed实际上在单词边界内搜索awk,如果找到则打印文件名加上找到的行。这使用GNU awk作为单词边界float\<

第二个sed的工作可以作为awk命令的一部分完成,但我喜欢2个seds的对称性。

与使用\>不同,这种sed / gcc / sed / awk方法不会避免在字符串中找到错误的匹配,但希望其中只有很少一些,你可以将它们排除在后无论如何都要手动处理。

它不适用于包含换行符的文件名 - 如果你有那些你可以但脚本中的正文,并将其作为cscope执行。

通过添加您正在使用的任何C或C ++版本来修改gcc命令行,例如: find .. -print0 | xargs -0 script