關於php_trace.pl
我知道,一年貼一篇是有點誇張啦,不過我真的很忙....呵呵~~~
下面是我最近在忙的東西,是一個perl的小程式,還沒寫好,算是草稿,先給大家一賭為快囉~~~
啊~~~這是蝦米?
底下是他會產生的東西:

看不懂?
其實這是一個簡單的小程式,可以用來分析使用php所寫成的系統,當檔案間彼此有引入關係時,就被程式鎖定為分析的目標,然後產生用來畫圖的.dot文件。這時候使用GraphViz就可以順利完成這張圖~~~~
不過這個程式雖然完成了,卻有怪怪的問題,第121行老是會跟我說我使用未初始化的數值(Use of uninitialized value in numeric eq (==) at php_trace.pl line 121.)......
我也不知道為什麼.....@@
總之這個程式可以用了...^^
下面是我最近在忙的東西,是一個perl的小程式,還沒寫好,算是草稿,先給大家一賭為快囉~~~
#!/usr/bin/perl -w
#下面這一行表示如果要使用變數前一定要先定義。
use strict;
#使用my來定義變數
my($GraphName, @DirArray, $TmpDirName);
#取得命令列參數, $ARGV[0]為起始被追蹤目錄, $ARGV[1]為寫入的dot檔
$GraphName = $ARGV[1];
#如果參數數目有錯,列出使用方法。
if ($#ARGV != 1){
die "usage: php_trace.pl directory_you_want_to_trace name_of_GraphViz_file\n";
}
#去掉手動輸入的換行符號。
chomp($ARGV[0]);
chomp($GraphName);
#開GraphViz描述檔。
open(GvFile, ">$GraphName") || die "不好意思,開檔失敗了....:P";
#寫入GraphViz檔的檔頭
print GvFile "digraph $ARGV[0] {\n\t";
#加上&是為了避免perl解譯器對函式的簽名(聽說是參數列)進行檢查。
#因為我把函式的定義放在程式最後面。
#這裡做目錄的recursion,並把找到的所有目錄push到@DirArray中
push(@DirArray, $ARGV[0], DirRecursion($ARGV[0]));
#找到所有陣列以後,將陣列名稱代進去作所有檔案的關連性分析
foreach $TmpDirName (@DirArray){
Analyze_relation($TmpDirName);
}
#寫入GraphViz檔的結尾
print GvFile "\n}";
#關閉GrpahViz檔案的handle
close(GvFile);
#------------------------------------函式區-----------------------------------------
#目錄recursion函式
sub DirRecursion{
# 首先設定兩個陣列一個變數
# @TempDirName:暫時將搜尋到的目錄名稱存入這個陣列
# $Temp:用來暫存目錄名稱的字串變數
# @DirName:真正傳回去有用的目錄名字陣列
my(@TempDirName, $Temp, @DirName);
while(defined($Temp = <$_[0]/*>)){
if (-d $Temp){
push(@TempDirName,$Temp);
}
}
push(@DirName, @TempDirName);
$Temp = "";
#使用recursion的方式讀取子目錄的名稱
if ($#TempDirName >= 0){
foreach $Temp (@TempDirName){
push(@DirName,DirRecursion($Temp));
}
}
#傳回所有搜尋到的子目錄
return @DirName;
}
#檔案關聯性分析函式主體
sub Analyze_relation{
# $ParName:父節點字串
my($ParName);
#取得目標目錄下的所有php檔
while(defined($ParName = <$_[0]/*.php>)){
open (Target_file,"./$ParName");
# $TempStr:暫存從檔案讀進來的join字串,並且做各種暫存字串用。
# @NoRepeatArray:從DetectRepeat函式中回傳的字串陣列,用於製造子節點。
# $ChiName:子節點字串
my($TempStr, @NoRepeatArray, $ChiName);
#把檔案讀進來的字串join成一個大字串
$TempStr = join("",);
#下面的RE用於除掉註解
$TempStr =~ s#/\*[^*]*\*+([^/*][^*]*\*+)*/|//[^\n]*|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $2 ? $2 : ""#gse;
close(Target_file);
#呼叫DetectRepeat函式,並且把去掉註解的程式碼帶進去處理,
#會回傳出沒重複的字串陣列
@NoRepeatArray = DetectRepeat($TempStr);
#現在已經產生這個檔案的@NoRepeatArray,可以開始寫入GvFile
$TempStr = "";
foreach $TempStr (@NoRepeatArray){
$ChiName = $TempStr;
WriteToFile($ParName, $ChiName);
}
}
}
#輸入join後的整個大檔字串,分析後傳回想要的@NoRepeatArray
sub DetectRepeat {
# @TempContent:用於暫存資料用的字串陣列, 因為一開始把字串合併成一個檔案後,
# 經過"挑註解"RE的挑選後,剩下的字串再依照"\n"分解成一段段,然後存入
# @TempContent中
# $TempStr:給這個函式中所有用到foreach的控制結構使用的暫存變數
# @RepeatArray:挑出來的檔名先存入這個字串陣列中
# %NotRepeat:用於挑出陣列@RepeatArray中重複部分所使用的Hash
# @NoRepeatArray:從@RepeatArray中取出的字串元素,先判斷在@NoRepeatArray中有沒有重複,
# 如果沒有,則push進@NoRepeatArray中;
# 如果重複,則用next進行下一個iteration
my(@TempContent, $TempStr, @RepeatArray, %NotRepeat, @NoRepeatArray);
@TempContent = split(/\n/, $_[0]);
foreach $TempStr (@TempContent){
#如果遇到目標就挑出檔名
if ($TempStr =~ m%(require_once|include_once|require|include)([^;]+\b)% and $2 =~ m%(\.{1,2}\/{1}.*)%){
push(@RepeatArray,$1);
}
}
#跳出上一個foreach後,現在應該已經把全文濾完了。
#接下來要挑出在@NoRepeatArray中沒有重複的部份
$TempStr = "";
%NotRepeat = ("","");
#檢查@RepeatArray中的每個元素是否有重複,同時製造出沒重複元素的@NoRepeatArray
foreach $TempStr (@RepeatArray){
#如果在%NotRepeat中有發現,表示在@NoRepeatArray中也有這個元素。
next if $NotRepeat{$TempStr} == 1;
push (@NoRepeatArray, $TempStr);
#把@NoRepaetArray中的每個值存到%NotRepeat中
for (@NoRepeatArray){
$NotRepeat{$_} = 1;
}
}
return @NoRepeatArray;
}
#很明顯的,這是寫入內容的函式
sub WriteToFile {
$_[0] =~ s/^$ARGV[0]/\./;
print GvFile "\"".$_[0]."\" -> \"".$_[1]."\";\n\t";
}
啊~~~這是蝦米?
底下是他會產生的東西:
看不懂?
其實這是一個簡單的小程式,可以用來分析使用php所寫成的系統,當檔案間彼此有引入關係時,就被程式鎖定為分析的目標,然後產生用來畫圖的.dot文件。這時候使用GraphViz就可以順利完成這張圖~~~~
不過這個程式雖然完成了,卻有怪怪的問題,第121行老是會跟我說我使用未初始化的數值(Use of uninitialized value in numeric eq (==) at php_trace.pl line 121.)......
我也不知道為什麼.....@@
總之這個程式可以用了...^^
留言