2010-11-27 140 views
1

是否有一些用于从免费的Fortran代码中删除未使用的局部变量的好工具?在Fortran代码中删除未使用的局部变量的工具

背景是,我们有一个非常大的代码库,在过去的20年中未使用的警告已被禁用,所以有相当多的警告被手动修复。

我知道Photran有这种重构,但我尝试过并遇到问题。出于某种原因,它要求可以对整个源代码进行解析(它无法处理我们的代码库)来进行重构,但对于这种重构,它应该足以让IMO检查单个文件。

+1

当您启用它们时,编译器警告输出的格式是什么?我认为你最好的选择是用Python或类似的脚本语言创建一个脚本,去掉编译器标记为声明未使用的局部变量的行。 – TZHX 2010-11-27 10:55:50

+0

我使用英特尔Fortran编译器格式获得它们,并在行上添加了行号和位置,所以可以这样做。但是,如果有一些现有的工具用于此目的,则会更快。 – 2010-11-27 11:15:17

+0

你能否详述一下最后一段(关于重构和单个文件)?我感兴趣的是你所做的一切。 – Rook 2010-11-27 15:05:22

回答

2

我已经根据编译器消息手动完成了这个工作。一个可能的自动工具:用于SPAG/plusFORT的新手必看说:

SPAG标识以及可选删除(这已宣告但从未变量或参数使用)死代码(报表可能不会被执行)和混乱。

我已经使用了免费的简化功能版本,但不记得该版本是否删除了未使用的变量。

0

这将会作为一个答案,因为它无法在评论框适合 - 不要把它作为一个答案不过,更多的为注释

除此之外,对不起,但我不认为这样的工具存在。 TZXH询问你使用的是什么编译器 - 并不是因为它带来了很大的差异,而是(我认为),因为他可能在分析编译器警告以获取变量列表,然后通过Fortran文件,手动删除这些变量。

我从来没有做过这样的事情,但它是一个可以工作的过程。有一些潜在的缺点,但它可以工作。

除此之外,对于Fortran源代码的分析(和编写新的IDE,它确实是一个非常好的IDE),我发现它是一个非常有用的工具。不确定它是否有一个功能可以完成你所要求的功能,但它可能会有所帮助。

-1

PlusFORT是你唯一的选择,它不便宜。但它已经用于数百万条旧Fortran(77)代码,并且已经相当成熟。对于意见请尝试comp.lang.fortran

0

有一个“美化”Python脚本作为GPL CP2K工具链的一部分。你可以在in the CP2K project source repository找到它。您将需要prettify.py和normalizeFortranFile.py脚本。既然它也试图“美化”文件,如果你真的只想删除局部变量,你将不得不编辑脚本。

0

对于gfortran您可以使用此perl脚本,参数“build_log”应该是gfortran -Wunused的输出(或任何让你不使用的变量警告):

#!/usr/bin/perl 

use strict; 

my $build_log = shift; 

open my $build_filehandle, "<", $build_log; 

my $file; 
my $line_to_edit; 
my $col_to_edit; 
my $word_to_remove; 

my @files; 
my @line_nums; 
my @unused_variables; 
my $line; 

my $line_number = 0; 
while($line = <$build_filehandle>) 
{ 
    $line_number++; 
    chomp($line); 
    if($line =~ m/([^:]*):(\d+)\.(\d+):/) 
    { 
     $file = $1; 
     $line_to_edit = $2; 
     $col_to_edit = $3; 
    } 
    elsif($line =~ m/Warning: Unused variable '([^']*)'/) 
    { 
     $word_to_remove = $1; 
     push(@files, $file); 
     push(@line_nums, $line_to_edit); 
     push(@unused_variables, $word_to_remove); 
    } 
} 

close($build_filehandle); 

# sort [file, line_num, word_to_remove] by files then line_nums then word_to_remove 
my @merged_columns; 
for(my $i = 0; $i < scalar(@files); $i++) # loop over all the replacements to be made 
{ 
    push(@merged_columns, [$files[$i],$line_nums[$i],$unused_variables[$i]]); 
} 

# if sort is stable, sort by line_nums, then files 
sub by_file_then_line 
{ 
    $a->[0] cmp $b->[0] || # by file 
    $a->[1] <=> $b->[1]; 
} 

my @sorted_by_line_nums = sort by_file_then_line @merged_columns; 

for(my $i = 0; $i < scalar(@files); $i++) # loop over all the replacements to be made 
{ 
    $files[$i] = $sorted_by_line_nums[$i][0]; 
    $line_nums[$i] = $sorted_by_line_nums[$i][1]; 
    $unused_variables[$i] = $sorted_by_line_nums[$i][2]; 
} 

my $print_line = 0; 
my $last_file = 'null'; 
my $replacement_filehandle; 
for(my $i = 0; $i < scalar(@files); $i++) # loop over all the replacements to be made 
{ 
    if($files[$i] ne $last_file) 
    { 
     if(defined($replacement_filehandle)) 
     { 
      # dump the line we were working on 
      if($print_line == 1) # print the line that we were processing 
      { 
       print("$line\n"); 
       $print_line = 0; 
      } 

      # dump the rest of the file 
      while($line = <$replacement_filehandle>) 
      { 
       chomp($line); 
       print("$line\n"); 
      } 
      # then close it 
      close($replacement_filehandle); 
     } 
     open $replacement_filehandle, "+<", $files[$i]; 
     $line_number = 0; 
    } 
    $last_file = $files[$i]; 

# here we are on the right file, but might need to advance to the correct location 
    while($line_number < $line_nums[$i]) # might not even enter 
    { 
     if($print_line == 1) # print the line that we were processing 
     { 
      print("$line\n"); 
      $print_line = 0; 
     } 
     $line = <$replacement_filehandle>; 
     $line_number++; 
     chomp($line); 

     if($line_number < $line_nums[$i]) 
     { 
      print("$line\n"); 
     } 
    } 
    $print_line = 1; 

    if($line =~ m/^\s+type/i) # don't bother with types, their naming and form is too messed up to make it worth the effort, and there aren't that many 
    { 
     next; 
    } 

    $line =~ s/,/, /g; # add spaces after commas 
    $line =~ s/,\s+/, /g; # collapse double commas 

# case followed by stuff in parens 
    $line =~ s/ ${unused_variables[$i]}\([^\)]*\),?//i; 

# case followed by comma 
    $line =~ s/ ${unused_variables[$i]},//i; 

# case end of line 
    $line =~ s/ ${unused_variables[$i]}\s*$//i; 

# remove trailing commas 
    $line =~ s/,\s*$//; 

# collapse double commas 
    $line =~ s/,\s*,/,/; 

# remove empty memory declaration lines 
# ie, if it does not have two sets of word characters kill it off 
    if(! ($line =~ m/\w[^A-Za-z\*]+\w/)) 
    { 
     $line = ''; 
    } 
} 


if(defined($replacement_filehandle)) 
{ 
    # dump the line we were working on 
    if($print_line == 1) # print the line that we were processing 
    { 
     print("$line\n"); 
     $print_line = 0; 
    } 

    # dump the rest of the file 
    while($line = <$replacement_filehandle>) 
    { 
     chomp($line); 
     print("$line\n"); 
    } 
    # then close it 
    close($replacement_filehandle); 
} 

很显然,你应该看看源并检查它是否做你想做的事情。但粗略地说,它读取编译器输出并删除编译器在其投诉的行上抱怨的变量。

相关问题