linux: Count Lines of Code

来源:互联网 发布:mac地址过滤怎么设置 编辑:程序博客网 时间:2024/06/09 19:31

cloc是一个基于perl的、十分好用的代码统计工具(http://cloc.sourceforge.net/),它所支持的语言还算十分丰富。不过,还是有很多用的较少的语言是不支持的。

项目中的一些功能模块用到re2c来实现字符匹配,因此,这些.re文件是cloc无法统计的。

不过还好,cloc提供了用户定制功能,使得我们还是可以实现对.re文件进行代码行统计。

定制方法很简单,基本有步骤如下:

1. 导出默认支持语言类型相关配置到一个文件中,命令:

[plain] view plaincopy
  1. cloc.pl --write-lang-def=langs.txt  

2. 参考其他语言的格式,修改langs.txt,添加所要统计语言源码文件的后缀名(这里参考了C语言):

[plain] view plaincopy
  1. re2c  
  2.     filter remove_matches ^\s*//  
  3.     filter call_regexp_common C  
  4.     filter remove_inline //.*$  
  5.     extension re  

3. 使用新定义的语言文件langs.txt运行cloc:

[plain] view plaincopy
  1. cloc.pl --read-lang-def=langs.txt [源文件|目录]  


但是还是有问题,用过re2c的人都知道,re2c是以/*!re2c [代码] */的形式将代码嵌在C代码中,这与C语言的注释相冲突,因此,上面操作后,cloc依然区分不开re2c内嵌代码和注释,因此,会把这部分代码识别为注释,而与实际不符。

对于这个问题,我一开始也是在尝试通过修改langs.txt文件的方法来进行支持,很遗憾,一直到现在没能找到。所以,我参考cloc.pl中python对于docstring的处理方式以及处理函数docstrings_to_C,也在cloc.pl中添加了一个新函数re_to_C,将/*!re2c [代码]*/的形式改成!re2c[代码]!re2c,这样就与C语言的注释语句格式区分开了,再修改langs.txt文件,让cloc.pl在统计前,先进行re_to_C处理,再按C语言的方式进行处理,最终,实现了对re2c文件的正确统计(呵呵,至少目前来看是正确的)。


最终langs.txt中re2c的内容如下:

[plain] view plaincopy
  1. re2c  
  2.     filter re_to_C  
  3.     filter remove_matches ^\s*//  
  4.     filter call_regexp_common C  
  5.     filter remove_inline //.*$  
  6.     extension re  


新增的re_to_C代码如下(呵呵,没学习perl,完全是照猫画虎呀):

[plain] view plaincopy
  1. sub re_to_C {                         # {{{1  
  2.     my ($ra_lines, ) = @_;  
  3.     # Converts Python docstrings to C comments.  
  4.     print "-> re_to_C()\n" if $opt_v > 2;  
  5.     my $in_re = 0;  
  6.     foreach (@{$ra_lines}) {  
  7.         if (!$in_re) {  
  8.             while (/\/\*!re2c/) {  
  9.                 s{\/\*!re2c}{!re2c};  
  10.                 $in_re = 1;  
  11.             }  
  12.         }  
  13.         else {  
  14.             while (/\*\//) {  
  15.                 s{\*\/}{!re2c};  
  16.                 $in_re = 0;  
  17.             }  
  18.         }  
  19.     }  
  20.     print "<- re_to_C\n" if $opt_v > 2;  
  21.     return @{$ra_lines};  
  22. } # 1}}}  


其他的语言应该也可以通过类似的方法定制吧。

0 0