是否有一些用于从免费的Fortran代码中删除未使用的局部变量的好工具?在Fortran代码中删除未使用的局部变量的工具
背景是,我们有一个非常大的代码库,在过去的20年中未使用的警告已被禁用,所以有相当多的警告被手动修复。
我知道Photran有这种重构,但我尝试过并遇到问题。出于某种原因,它要求可以对整个源代码进行解析(它无法处理我们的代码库)来进行重构,但对于这种重构,它应该足以让IMO检查单个文件。
是否有一些用于从免费的Fortran代码中删除未使用的局部变量的好工具?在Fortran代码中删除未使用的局部变量的工具
背景是,我们有一个非常大的代码库,在过去的20年中未使用的警告已被禁用,所以有相当多的警告被手动修复。
我知道Photran有这种重构,但我尝试过并遇到问题。出于某种原因,它要求可以对整个源代码进行解析(它无法处理我们的代码库)来进行重构,但对于这种重构,它应该足以让IMO检查单个文件。
我已经根据编译器消息手动完成了这个工作。一个可能的自动工具:用于SPAG/plusFORT的新手必看说:
SPAG标识以及可选删除(这已宣告但从未变量或参数使用)死代码(报表可能不会被执行)和混乱。
我已经使用了免费的简化功能版本,但不记得该版本是否删除了未使用的变量。
这将会作为一个答案,因为它无法在评论框适合 - 不要把它作为一个答案不过,更多的为注释
从除此之外,对不起,但我不认为这样的工具存在。 TZXH询问你使用的是什么编译器 - 并不是因为它带来了很大的差异,而是(我认为),因为他可能在分析编译器警告以获取变量列表,然后通过Fortran文件,手动删除这些变量。
我从来没有做过这样的事情,但它是一个可以工作的过程。有一些潜在的缺点,但它可以工作。
除此之外,对于Fortran源代码的分析(和编写新的IDE,它确实是一个非常好的IDE),我发现它是一个非常有用的工具。不确定它是否有一个功能可以完成你所要求的功能,但它可能会有所帮助。
PlusFORT是你唯一的选择,它不便宜。但它已经用于数百万条旧Fortran(77)代码,并且已经相当成熟。对于意见请尝试comp.lang.fortran
有一个“美化”Python脚本作为GPL CP2K工具链的一部分。你可以在in the CP2K project source repository找到它。您将需要prettify.py和normalizeFortranFile.py脚本。既然它也试图“美化”文件,如果你真的只想删除局部变量,你将不得不编辑脚本。
对于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);
}
很显然,你应该看看源并检查它是否做你想做的事情。但粗略地说,它读取编译器输出并删除编译器在其投诉的行上抱怨的变量。
当您启用它们时,编译器警告输出的格式是什么?我认为你最好的选择是用Python或类似的脚本语言创建一个脚本,去掉编译器标记为声明未使用的局部变量的行。 – TZHX 2010-11-27 10:55:50
我使用英特尔Fortran编译器格式获得它们,并在行上添加了行号和位置,所以可以这样做。但是,如果有一些现有的工具用于此目的,则会更快。 – 2010-11-27 11:15:17
你能否详述一下最后一段(关于重构和单个文件)?我感兴趣的是你所做的一切。 – Rook 2010-11-27 15:05:22