#!/usr/bin/perl
#
#   .F ファイル用の f77
#
#                                           薮 哲郎
#  ＜ 動作概要 ＞
#
#  .F ファイルは以下のような過程で整形された後、f77 に
#  引き渡されます。
#
#       cpp            
#  *.F  ---> .debug/*.f
#
#  ＜ 注意 ＞ 
#
#    ・ 中間ファイル .debug/*.f について
#
#                              エラー発生     エラー無し
#
#       -[gG] オプションあり      残す          残す
#       -[gG] オプションなし      残す          残さない
#
#    ・ cpp が思うように動作しない場合は、$cpp_option ="-traditional" を
#       つけてみて下さい。
#
#    ・ 本スクリプトは無保証です。各自の責任でお使い下さい。
#
#  ＜ 製作履歴 ＞
#
#   ver 1.0   2000.1.25   xy77 を簡略化して作成
#

$f_compiler  = "f77";

$clean_flag  = 1;
$out_message = 0;

$tmpdir = ".debug";

$cpp_option  = "";
@f77list = ("");

$ENV{"PATH"} = $ENV{"PATH"}.":/lib:/usr/lib:/usr/ccs/lib";

$| = 1;  # print の直後にバッファをフラッシュする
         # system 文によるエラーとの順番を正しく表示するため

if ( @ARGV == 0 ) {
	&usage();
	exit 1;
}

#       ----- 作業用ディレクトリの作成 -----

if ( -d $tmpdir ){    # 既に存在するときは何もしない

} elsif ( -f $tmpdir ) {
	print STDERR "file $tmpdir already exist.  Stop.\n";
	exit 1;
} else {
	$ret = mkdir($tmpdir,0755);  # $ret=0 のときエラーなのに注意
	if ( $ret == 0 ) {
		print STDERR "Cannot mkdir '$tmpdir'.  Stop.\n";
		exit 1;
	}
}

#       ------ オプションの解析 ------

while(1){
	$_ = shift(@ARGV);
#	print "input list |$_|\n";
	if ( $_ eq "" ) { last; }

	if ( m/^-/ ){              # オプションの場合の処理
		if ( m/^-g/i ){
			push(@f77list,"-g");
			$clean_flag = 0;
		} elsif( m/^(-[DI])(.*)/ ){
			if ( $2 eq "" ){
				$opt = $1.shift(@ARGV);
			} else {
				$opt = $1.$2;
			}
			$cpp_option = $cpp_option." $opt";
			push(@f77list,$opt);
		} elsif( m/^-v/ ) {
			$out_message = 1;
		} else {
			push(@f77list,$_);  # -c -L -lcalcomp -o など
		}
	} else {    # それ以外の指定  .F .f .o -o a.out  など

		if ( m/([^\/]+)\.F$/ ) {  # .F ファイルの場合

			$fbody = $1;
			$orgfile = $_;
			$ffile = "$tmpdir/$1.f";

			$command = "cpp $cpp_option $orgfile > $ffile";
			&execute($command);
			push(@clean_flist,$ffile);

			push(@f77list,$ffile);
			
		} else {    # .f  .c  .o  -o a.out などの場合
			push(@f77list,$_);
		}
	}

}

$f77list2 = join(' ',@f77list);
$command = "$f_compiler $f77list2";

&execute($command);

#       ---- 中間ファイルの消去 ---

if ( $clean_flag == 1 && @clean_flist > 0 ){
	$clean_flist2 = join(' ',@clean_flist);
	$command = "rm -f $clean_flist2";
#	print STDERR "$command\n";
	&execute($command);
}

exit 0;

#------------- コマンドの実行 -------------

sub execute {
	local($command) = @_;
	if ( $out_message == 1 ) {
		print STDERR "$command\n";
	}
	$ret = system($command);
	if ( $ret != 0 ){
		print STDERR "Error occur in command '$command'.  Stop.\n";
		exit 1;
	}
}

#-------------- usage -------------

sub usage{
	print STDERR "\n";
	print STDERR "ff77 は cpp を通す f77 コマンドです。\n";
	print STDERR ".F ファイルはプリプロセスされた後 f77 に渡されます\n";
	print STDERR "-v オプションをつけると動作が理解できます。\n";
	print STDERR "\n";
	print STDERR "(例1) % ff77 -c -v -g file1.F\n";
	print STDERR "(例2) % ff77 -v file1.F file2.f file3.o \n";
	print STDERR "\n";
	print STDERR "options\n";
	print STDERR " -v    : 確認モード\n";	
	print STDERR " -[gG] : -g オプションでコンパイル。中間ファイルを残します。\n";	
	print STDERR " -[DI] : オプションを cpp にも渡します\n";
	print STDERR " other : f77 に渡します\n";
	print STDERR "\n";
}

