2010-11-27 17 views
1

未使用のローカル変数をフリーフォームのFortranコードから削除するためのツールがありますか?Fortranコードで未使用のローカル変数を削除するツール

バックグラウンドでは、コードベースが非常に大きく、過去20年間は未使用の警告が無効になっているため、手動で修正するには多すぎます。

私はPhotranにそのようなリファクタリングがあることを知っていますが、私はそれを試して問題に遭遇しました。何らかの理由で、リファクタリングのためにIMOが単一のファイルをチェックするのに十分であるにもかかわらず、リファクタリングを行うために、ソースコード全体を解析することができます(私たちのコードベースとは関係ありません)。

+1

コンパイラの警告出力を有効にしたときの出力形式は何ですか?私はあなたの最善の策は、Pythonやそれに類するスクリプト言語で、コンパイラが未使用のローカル変数を宣言している行を空白にするスクリプトを作成することだと思います。 – TZHX

+0

私はインテルFortranコンパイラ形式で、行番号と行の位置を取得します。そうすれば、そうすることができます。しかし、それを使用するための既存のツールがあれば、それは速くなります。 –

+0

最後の段落(リファクタリングと単一ファイルに関する)を少し詳しく説明できますか?私は興味を持っています。 – Rook

答えて

2

私はコンパイラのメッセージに基づいてこれを手作業で行っています。一つの可能​​な自動ツール:

SPAGを識別し、必要に応じてデッドコード(実行されない可能性が文)と乱雑(宣言されていないが、決して使用されている変数やパラメータ)を削除します。SPAG/plusFORTための過去記事は言います。

フリーで機能低下したバージョンを使用しましたが、そのバージョンが未使用の変数を削除したかどうかは覚えていません。

+0

私はこれをチェックしなければなりません、ありがとう! –

0

それはコメント欄に収まらない原因これは、答えとして起こっている - しかし答えとしてそれを考えていませんが、コメントとは別に

などの多くを、申し訳ありませんが、私はそのようなツールが存在するとは思わない。 TZXHはコンパイラが何を使っているかを尋ねました。それは違いがあるからではなく、おそらく変数のリストを得るためにコンパイラの警告を解析し、次にFortranファイルを調べ、これらの変数を手動で削除します。

私はこれほどのことは一度もしていませんが、それはうまくいくプロセスです。いくつかの潜在的な欠点がありますが、うまくいく可能性があります。

これ以外にも、Fortranのソースコードの解析(新しいものを書くことは本当に素晴らしいIDEです)のために、私はSciTools Understandという非常に有用なツールを見つけました。あなたが求めていることをする機能を持っているかどうかは分かりませんが、それは助けになるかもしれません。

-1

PlusFORTが唯一のオプションで、安くはありません。しかし、それは数百万行の旧Fortran(77)コードで使用されており、かなり成熟しています。ご意見は、comp.lang.fortranを試してみてください。

+0

私たちはPlusFortの仕事場でのライセンスを持っていましたが、プリプロセッサの#include文にはいくつかの問題があります。 1つの#includeファイルに#includeを含む別のファイルが含まれていると、SPAGはクラッタ除去を行いません。 –

0

GPL CP2Kツールチェーンの一部として、「prettify」Pythonスクリプトがあります。 in the CP2K project source repositoryで見つけることができます。 prettify.pyとnormalizeFortranFile.pyスクリプトが必要です。それはまた、ファイルを "prettify"しようとするので、あなたは本当にローカル変数を削除したい場合は、スクリプトを編集する必要があります。

0

あなたはこのperlスクリプトを使用することができるのgfortranに関しては、引数「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); 
} 

明らかにあなたがソースをご覧くださいそれがあなたがしたいことをしていることを確認してください。しかし、おおまかに言えば、コンパイラの出力を読み込み、コンパイラが不平を言っている行で文句を言う変数を削除します。

関連する問題