#!/usr/bin/perl
#use encoding 'shift-jis';
#use strict;
use warnings;
use Win32::OLE qw(in with);
use Win32::OLE::Const 'Microsoft Excel .* Object Library';
#ヘルプメッセージの表示
if (($#ARGV < 0) || ($ARGV[0] =~ /^¥-+help/)) {
&helpExit();
}
# エクセルオブジェクトを取得
my $excel = Win32::OLE->GetActiveObject('Excel.Application')
|| die "cannot get active excel!";
# ブックを追加する
my $book = $excel->Workbooks->add();
# モノを書き込む
my $sheet = $book->ActiveSheet;
#全体行の設定
my $allLen = 1;
####################################################
my $programVer = "ver4.1.0";
my $programName = "単体試験項目自動作成ツール『おじどうくんDR4』";
####################################################
# output file name
my $outputFileName = "ut.csv";
# warning number
my $maxLineNumber = 3000;
# todo word
my $todo = "TODO";
# header details
my $paramHeader2 = "フォルダ名,項番,項番,関数名(ファイル名),項番,Line,試験項目";
#
# %%1%% file number
# %%2%% file folder
# %%3%% fine name
# %%4%% function number
# %%5%% function name
# %%6%% function test index number
# %%7%% line number
# %%8%% details
my $paramFileName = "%%2%%,%%1%%,%%4%%,%%3%%,%%6%%,%%7%%," .
"%%8%% ファイルの試験を実施する";
my $paramIfdef = ",,,,%%6%%,%%7%%," .
"%%8%% の妥当性を検討すること(必要なければ削除する)";
my $paramClassStart = ",,%%4%%,%%5%%,%%6%%,%%7%%," .
"Class %%8%% が起動できることを確認する";
my $paramInterfaceStart = ",,%%4%%,%%5%%,%%6%%,%%7%%," .
"Interface %%8%% が使用されることを確認する";
my $paramFuncStart = ",,%%4%%,%%5%%,%%6%%,%%7%%," .
"関数%%5%% が呼ばれたときに引数が正しく渡されていること" .
"(パラメタ数、パラメタ順序、実体orポインタ)" .
"(引数に最大値最小値を与えてそれぞれチェックすること)";
my $paramMethodStart = ",,%%4%%,%%5%%,%%6%%,%%7%%," .
"Method %%5%% が呼ばれたときに引数が正しく渡されていること" .
"(パラメタ数、パラメタ順序、実体orポインタ)" .
"(引数に最大値最小値を与えてそれぞれチェックすること)";
my $paramConstMethodStart = ",,%%4%%,%%5%%,%%6%%,%%7%%," .
"コンストラクタが呼ばれたときに引数が正しく渡されていること" .
"(パラメタ数、パラメタ順序、実体orポインタ)" .
"(引数に最大値最小値を与えてそれぞれチェックすること)";
my $paramReturnCall = ",,,,%%6%%,%%7%%," .
"処理のreturnにおいて、戻り値が正しく返ること";
my $paramLoopStart = ",,,,%%6%%,%%7%%," .
"%%8%% が正しい範囲でループされること";
my $paramIfMess = ",,,,%%6%%,%%7%%," .
"if(真)の場合にこの処理が起動されること";
my $paramIfElseMess =
",,,,%%6%%,%%7%%," .
"if(偽/else)の場合にこの処理が起動され*ない*こと";
my $paramElseIfMess = ",,,,%%6%%,%%7%%," .
"else if(真)の場合にこの処理が起動されること";
my $paramElseMess = ",,,,%%6%%,%%7%%," .
"else の場合にこの処理が起動されること";
my $paramSwitch = ",,,,%%6%%,%%7%%," .
"switch()内のパラメタの妥当性を考慮すること";
my $paramCase = ",,,,%%6%%,%%7%%," .
"case %%8%%: を発生させこの処理が起動されること";
my $paramDefault = ",,,,%%6%%,%%7%%," .
"default: を発生させこの処理が起動されること";
my $paramFancCall = ",,,,%%6%%,%%7%%," .
"関数%%8%%において、関数呼び出し時に引数を正しく渡していること" .
"(パラメータ数、パラメータ順序、実体orポインタ)" .
"(戻り値が正しく処理されていること)";
my $paramMethodCall = ",,,,%%6%%,%%7%%," .
"Method %%8%% がコールされることを確認すること" .
"(戻り値が正しく処理されていること)";
my $paramTodo = ",,,,%%6%%,%%7%%," .
"%%7%%行にある TODO 項目の内容を確認すること";
#
my $paramMaxLine = ",,,,,%%7%%," .
"line数が%%7%%行と多いので、" .
"分割することを検討すること";
####################################################
#一行目を表示する
my $cellRange = "A" . $allLen;
$sheet->Range($cellRange)->{Value} = $programName . "/" . $programVer ;
$allLen++;
#縦列の幅を変える
$sheet->Columns("A:A")->{ColumnWidth} = 14.50;
$sheet->Columns("B:B")->{ColumnWidth} = 3.88;
$sheet->Columns("C:C")->{ColumnWidth} = 3.88;
$sheet->Columns("D:D")->{ColumnWidth} = 16.75;
$sheet->Columns("E:E")->{ColumnWidth} = 3.88;
$sheet->Columns("F:F")->{ColumnWidth} = 6.00;
$sheet->Columns("G:G")->{ColumnWidth} = 50.00;
#カラムを出力する
&pcall($paramHeader2);
$sheet->Range("A2:G2")->Interior->{ColorIndex} = 33;
$sheet->Range("A2:G2")->Borders(xlEdgeBottom)->{LineStyle} = 1;
my $fileNumber = 0;
my $oldFolder = "";
my $file = "";
my $fn;
my $fl;
my $pos = 1;
my $forJava = 0;
foreach(@ARGV) {
$fileNumber++;
print "open:" . $_ . "¥r¥n";
if (/¥.[Jj][Aa][Vv][Aa]$/) {
$forJava = 1;
}
$file = $_;
open(IN,"<" . $file);
s/^src¥
$file = $_;
if (/[^¥¥¥/]+$/) {
$fn = $&;
/^.*[¥¥¥/]/;
$fl = $&;
if ($fl ne $oldFolder) {
$oldFolder = $fl;
} else {
$fl = "";
}
}
#
$pos = 1;
my $line = 0;
my $funcNum = 1;
my $className = $fl;
my $funcName = "";
my $workout = "";
&pcall($paramFileName,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,$file);
foreach(<IN>) {
$line++;
s/¥/¥[¥s¥S]*$
s/¥s+$
s/(^|[^¥*])¥/¥/.*$/$1/; # Cut of "// ...".
s/¥/¥*.*¥*¥
if (/^[a-zA-Z_][^;¥(¥{]/) {
$workout = $workout . $_;
} else {
if ($workout ne "") {
($funcNum,$funcName) =
&work1Line($funcNum,$funcName,$line -1,$workout . $_);
$workout = "";
} else {
($funcNum,$funcName) =
&work1Line($funcNum,$funcName,$line,$_);
}
}
}
if ($maxLineNumber <= $line) {
$funcNum = 1;
$funcName = "";
$pos = 1;
&pcall($paramMaxLine,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,$maxLineNumber);
}
close(IN);
}
$cellRange = "A" . $allLen . ":G" . $allLen;
$sheet->Range($cellRange)->Borders(xlEdgeTop)->{LineStyle} = 1;
exit(0);
sub work1Line {
local($funcNum,$funcName,$line,$work) = @_;
$_ = $work;
if (/¥s*¥#(if|else)/) {
&pcall($paramIfdef,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,$_);
} elsif (($forJava == 1) && /^¥s*(public|protected|private|final)*¥s*class¥s+([A-Z][a-zA-Z_0-9]*)/) {
$pos = 1;
$funcNum++;
$className = "$2";
$funcName = $className;
&pcall($paramClassStart,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,$className);
} elsif (($forJava == 1) && /^¥s*(public|protected|private|final)*¥s*interface¥s+([A-Z][a-zA-Z_0-9]*)/) {
$pos = 1;
$funcNum++;
$className = "$2";
$funcName = $className;
&pcall($paramInterfaceStart,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,$className);
} elsif (($forJava == 1) && /^¥s*(public|protected|private|final)*¥s*$className¥s*¥(/) {
$pos = 1;
$funcNum++;
$funcName = $className;
&pcall($paramConstMethodStart,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,$className);
} elsif (($forJava == 1) && /^¥s+(public|protected|private|final|static)+¥s+[a-zA-Z_][.a-zA-Z_0-9]*(<[^>]>¥s*)?(¥[¥s*¥]¥s*)*¥s+([a-zA-Z_][a-zA-Z_0-9]*)¥s*¥(/) {
$pos = 1;
$funcNum++;
$funcName = "$4()";
&pcall($paramMethodStart,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line);
} elsif (($forJava == 0) && /^([a-zA-Z_][a-zA-Z_0-9]*(¥**¥s+)?¥s+)*(¥*(¥*|¥s)*)?([a-zA-Z][a-zA-Z_0-9]*::)?([a-zA-Z_][a-zA-Z_0-9]*)¥s*¥(/) {
$pos = 1;
$funcNum++;
$funcName = "$6()";
&pcall($paramFuncStart,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line);
} elsif (/^¥s+return¥s/) {
&pcall($paramReturnCall,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line);
} elsif (/^¥s+(for|while)(¥s|¥()/) {
my $selectName = "$1()";
&pcall($paramLoopStart,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,
$selectName);
} elsif (/^¥s+do$/) {
&pcall($paramLoopStart,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,
"do");
} elsif (/^¥s+do(¥s|¥{)/) {
&pcall($paramLoopStart,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,
"do");
} elsif (/^¥s+if(¥s|¥()/) {
&pcall($paramIfMess,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,"if");
&pcall($paramIfElseMess,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,"if");
} elsif (/^¥s+(¥}¥s*)?else¥s+if(¥s|¥()/) {
&pcall($paramElseIfMess,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,"else if");
} elsif (/^¥s+(¥}¥s*)?else¥s+/) {
&pcall($paramElseMess,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,"else");
} elsif (/^¥s+case¥s+([^:]+)¥s*:/) {
my $caseName = $1;
&pcall($paramCase,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,$caseName);
} elsif (/^¥s+default¥s+([^:]+)¥s*:/) {
&pcall($paramDefault,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,"default");
} elsif (/¥s*switch¥s*¥(/) {
&pcall($paramSwitch,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,"switch");
} elsif (($forJava == 0) && /([a-zA-Z][:_a-zA-Z0-9]*)¥s*¥(/) {
my $functionName = $1 . "()";
if (!/^¥s*[¥/]?¥*/) { #except document
&pcall($paramFancCall,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,
$functionName);
}
} elsif (($forJava == 1) && /([a-zA-Z][._a-zA-Z0-9]*)¥s*¥(/) {
my $functionName = $1 . "()";
if (!/^¥s*[¥/]?¥*/) { #except document
&pcall($paramMethodCall,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line,
$functionName);
}
}
if (/$todo/) {
&pcall($paramTodo,$fileNumber,$fl,$fn,$funcNum,$funcName,$pos,$line);
}
return($funcNum,$funcName);
}
sub pcall {
local($data,@work) = @_;
local($i,$target) = (0,"");
local(@abc) = ("a","b","c","d","e","f","g","h","i","j","k","l");
local(@splitConnma,$speed);
$speed = 0.02;
$i = 1;
foreach(@work) {
$target = "%%" . $i . "%%";
if ($data =~ /$target/) {
$data =~ s/$target/$_/g;
}
$i++;
}
#print OUT $data;
@splitConnma = split(/,/,$data);
$i = 0;
#
sleep $speed;#ときどき空白が出力されるのでその対策
#
print " allLen=" , $allLen . " target=" . $work[4] . "¥r¥n";
foreach (@splitConnma) {
#
#
$sheet->Range($abc[$i] . $allLen)->{Value} = $_;
sleep $speed;#ときどき空白が出力されるのでその対策
#if ($_ ne $sheet->Range($abc[$i] . $allLen)->{Value}) {
# print "error(" . $_ . ")¥r¥n";
#}
$sheet->Range($abc[$i] . $allLen)->Borders(xlEdgeLeft)->{LineStyle} = 1;
sleep $speed;#ときどき空白が出力されるのでその対策
$sheet->Range($abc[$i] . $allLen)->Borders(xlEdgeRight)->{LineStyle} = 1;
sleep $speed;#ときどき空白が出力されるのでその対策
if (/¥S/) {
$sheet->Range($abc[$i] . $allLen)->Borders(xlEdgeTop)->{LineStyle} = 1;
sleep $speed;#ときどき空白が出力されるのでその対策
}
if ($i == 0) {
$sheet->Range($abc[$i] . $allLen)->{WrapText} = 1;
sleep $speed;#ときどき空白が出力されるのでその対策
$sheet->Range($abc[$i] . $allLen)->Interior->{ColorIndex} = 35;
sleep $speed;#ときどき空白が出力されるのでその対策
} elsif ($i == 1) {
$sheet->Range($abc[$i] . $allLen)->Interior->{ColorIndex} = 36;
sleep $speed;#ときどき空白が出力されるのでその対策
} elsif ($i == 2) {
$sheet->Range($abc[$i] . $allLen)->Interior->{ColorIndex} = 34;
sleep $speed;#ときどき空白が出力されるのでその対策
} elsif ($i == 3) {
$sheet->Range($abc[$i] . $allLen)->{WrapText} = 1;
sleep $speed;#ときどき空白が出力されるのでその対策
$sheet->Range($abc[$i] . $allLen)->Interior->{ColorIndex} = 34;
sleep $speed;#ときどき空白が出力されるのでその対策
} elsif ($i == 6) {
$sheet->Range($abc[$i] . $allLen)->{WrapText} = 1;
sleep $speed;#ときどき空白が出力されるのでその対策
}
$i++;
}
$allLen++;
$pos++;
}
#
# ヘルプを出力して終了
sub helpExit {
print "usage:¥r¥n";
print "ut4.pl [OPTION] filename.c [filename.c ...]¥r¥n";
print "¥r¥n";
print "[OPTION]¥r¥n";
print "¥t-help : Help message (this).¥r¥n";
exit(0);
}
#;