#!/usr/bin/perl

=pod

=head1 NAME

ratioPxDep2dev - output block-point from ratio and depth of callstack.

=head1 SYNOPSIS

  perl ratioPxDep2dev.pl [-np] [-s scope] [-t threshold ] ratio.log

=head1 DESCRIPTION

更新頻度とコールスタックの深さから，ブロック分割点列を出力する．

=head1 OPTIONS

=over 4

=item -n
  各フェイズの開始イベント列を出力した後，次の行にフェイズの個数を出力する

=item -p
  各フェイズの始点イベント番号と，そのイベントの実行履歴ファイル上のファイルポインタ位置を
  コンマ区切りで交互に出力する

=item -s
  コールスタックの谷をさかのぼる範囲をイベント個数で指定する．

=item -t
  更新頻度をブロック境界反応として検出する閾値を指定する．（0〜1）

=back

=cut


use strict;
use Getopt::Std;

# コマンドラインオプション
my %options;
getopts('s:t:np', \%options);

# コールスタックを遡る範囲
my $scope = 1;
if ($options{"s"}) {
	$scope = $options{"s"};
}

my $threshold = "";
if( $options{"t"} ) { $threshold = $options{"t"}; }

my $phasecount = 0;
if( $options{'n'} ){ $phasecount = 1; }

my $filepointer = 0;
if( $options{'p'} ){ $filepointer = 1; }

# 引数不正
if ( @ARGV >= 4) {
#    &print_usage();
	exit(1);
}

#-----------------------------------------------#
# main
#-----------------------------------------------#



# コールスタックスタック
my @depthindex = ();           #スコープ範囲にあるindexを格納する配列
my @depthfp = ();              #スコープ範囲にあるindexのfilepointerを格納する配列
my @depthstack = ();           #上記に対応するコールスタック深を格納する配列
my $deepest = 0;	       #（上記２配列中の）一番深い谷の位置

my $before = "";               #１つ前の値
my $upflag = 0;                #上昇／下降フラグ

my @devideIndex = ();          #区切りとして検出したindex値
my @devideFp = ();              #↑のファイルポインタ値
while( <> ){
	chomp;
	if( /^#/ ) { next; }

	my @data = split(/\s+/);
	my $num = @data;
	if( $num < 3 ) { die " file format error \n" ; }


	#スタック初期化
	if( $before eq "" ){
		$before = $data[1];
		push(@depthindex, $data[0]);
		push(@depthstack, $data[2]);
		push(@depthfp, $data[3]);
		push(@devideIndex, $data[0]);
		push(@devideFp, $data[3]);
		$deepest = 0;
		next;
	}

	my $diff = $data[1]-$before;
	$before = $data[1];

	#上昇中
	if( $upflag == 1 ){
		if( $diff < 0 ){
			$upflag = 0;
			if((($threshold ne "")and($threshold < $data[1])) or ($threshold eq "")){
				if( $depthindex[$deepest] > $devideIndex[@devideIndex-1] ){
					push( @devideIndex, $depthindex[$deepest] );
					push( @devideFp, $depthfp[$deepest] );
				}
			}
		}
	} else {
		if( $diff > 0 ){
			$upflag = 1;
		}
	}

# 配列更新
	my $numS = @depthstack;
	if( $numS >= $options{"s"} ){
		shift( @depthindex );
		shift( @depthfp );
		shift( @depthstack );
		$deepest--;
	}
	push( @depthindex, $data[0] );
	push( @depthstack, $data[2] );
	push( @depthfp, $data[3] );
	# 谷を更新する
	if( $deepest == -1 ){	# 谷がscopeから抜けたとき（至近の谷の再探索）
		my $min = $depthstack[0];
		$deepest = 0;
		for( my $i = 1; $i < $numS; $i++ ){
			if( ($min >= $depthstack[$i]) and ($depthstack[$i] != $depthstack[$i-1])){
				$deepest = $i;
				$min = $depthstack[$i];
			}
		}
	} else {		# 谷がScope内にあるとき（新しい部分と現谷の比較）
		if( ($depthstack[$numS-1] <= $depthstack[$deepest]) and ($depthstack[$numS-1] != $depthstack[$numS-2]) ){
			$deepest = $numS-1;
		}
	}
}
my $phasecount = @devideIndex;
if( $filepointer > 0 ){
	for(my $i = 0; $i < $phasecount ; $i++ ){
		print "$devideIndex[$i], $devideFp[$i], ";
	}
	print "\n";
}else{
	print "@devideIndex";
}
if( $phasecount > 0 ){
	print "\n$phasecount\n";
}
exit(0);
