32 Sapidによるソフトウエア解析技法
関数getFuncCall 関数呼び出しのカウント
アルゴリズム
関数main
1.宣言declarationオブジェクト配列中で、関数宣言であるものを選ぶ 2.1.でもとめたdecralationオブジェクトからoptionaldeclを得る 関数
g
etFuncCalla
各定義関数中のクラスidenti自erのオブジヱクト出現 (ωαlITence)の取得 4取得されたオブジェク卜の中で属性: ω
此が関数(ID̲FUNCTIO問であるものを選ぶ 5関数名を絡納する配列func̲idを調べ、新規の名前かどうかを判断するら新規の関数であった場合は配列白nc̲idに格納し、情報を出力する
#証占fineMAX FUNC SIZE 100 :?o i姐dge仇 ncωCall(S凶O切附刷I凶df向t加伽m叫B
Sp凶dO白 白n即c00凹c; SpdCursor市ncー田町
SpdObjld func̲id[MAX̲FUNC̲SIZE],func̲id 1; int i=Oj=O;
/ / 3 .
名前の出現を求めるfunc":‑cS
' r
= spdGctIItciudedOccInit(funcDecUd, "identifier" ,funcDecUd);while ((func'::'occ = spdGetInc1udedO田(func一 回r)).relationld!= SAPID̲NON̲ID)
/ / 4 .
関数の名前の出現だけ抜き出すif (5pdGetAttrValInt(func̲o田objectld,"50此")== ID]UNCI10N){
/ / 5 .
重複する関数名の出現があった場合は取り除く whi1e(j<=i)if(runc̲id[j++ ]==func̲occ.objectld) goto EXIT2;
//6.新規の場合配列funcーidに格納、情報を出力する func̲id[i]=func̲occ.objectId;
printf(" ealling Function Name %d:%5¥n,'・i++,5pdGetName(funcid[i])); EXlT2
} J=α
SpdFreeCu四or(func̲四r);
4 ‑ 1 ‑ 1
関数getFunc白1 1
の改良上記の関数getFuncCallは、処理対象の関数の数を最大
100
個として配列を 宣言しているが、対象とする関数の数が100
個を超えると処理できなくなる。そのため、構造体を用いてサイズに対応するよう関数を改良する。
関数getFuncCall(改良版)
void getFuncC冶ll(SpdObjldfuncDecUd){
Spdゆ田 func凹c' Spd巴ursor骨自mc田r' int j; / /↓構造体の定義
Struct FUNC{
int func̲size; }
, spdohdId骨func̲id; struct FUNC func; / /↓構造体の初期化 func.funcsize = 0; func.func̲id = NULL;
第2章 ドキュメントの作成 33
func̲csr = spdGetIncludedOccInit(funcDecUd, "identifier",funcDecUd);
whiIe ((func':"occ = spdGetIncludedOcc(func田r)).relationld!= SAPID̲NON̲ID) if(spdGeIAttrValInt(funcoec.objectI ,Ic"sort") == ID̲FUN
Cn
ON){//↓関数の名前の出現だけ抜き出す for(j= 0; jくfunc.funcsize;j++)
if(func.funcid[j]==func←occ.objectld) goto EXIT2;
/ /↓構造体を配列のように使う方法(注参照)
func.func̲id=spdRealloc(func.funcid, sizeof(SpdO均Id)骨(func.funcsize+ 1)); func.funcid[func.釦nc̲size]= funcocc.objectId;
/ /↓結果の面力
prinぜ
r
Calling Function Name %s¥!l",spdGetName(func.func̲id[func.func̲size])); func.func̲size ++;
EXIT2:
}
注func.func̲id=(SpdObjld)malloc(sizeof(SpdObjld)長(func.func̲si配 +1});でも可
4 . 2 関数の呼び出し位置(行数)
呼 び 出 し 位 置 を 行 数 で 求 め る 関 数 を 用 意 す る 。 オ ブ ジ ェ ク ト の 出 現 位 置 は オ フ セ ッ ト よ り 行 数 で 表 現 し た 方 が 便 利 で あ る 。 オ ブ ジ ェ ク ト I d をパラメータ として、該当オブジェクトの出現する先頭の行数を求める関数 spd̲geClineO を作成する。 i d e n t i f i e r な ど は 複 数 の 出 現 を 持 つ の で 、 参 照 関 連 で 対 応 す る ク ラス ( e x p r e s s i o n ) のオブジェクトを関数 spd̲get̲IineO のパラメータとする。
同関数を利用するためには、モデ)レ P‑model が 必 要 で あ り 、 モ デ ル 呼 び 出 し 関 数を用意する。
関数 spd̲geCline 行数を求める
static int spdJ;ecline(SpdObjld id){SpdOcc occ; SpdRegion i̲region; SpdRegion c̲region; int line = MAJCUNE̲SIZE;
int column = MAX̲COLUMN̲SIZE;
occ = spdGetAnOffsetOfObj(id); if(occ.objectld!= SAPID̲NON̲IDl {
34 Sapid
によるソフトウェア解析技法
}
仁元gion=云両面面てー玩T己反扇ーon‑(田c); c̲陀gion= ipdConvRegionItoCbyPIDB(i̲region); if(cregion.fileld != SAPID̲NON̲ID) { }
spdCnvOffsetToLineColumn(c̲region.fileld. c̲region.offset.
&line. &column); return Oine);
関数
openModelーモデル呼び出し
void openModel(SpdDBld dbld){SpdModeUd ImodelId. PmodelId; ImodelId = spdUseModel(&Cmodeり; PmodelId = ipdUseMod旧1(&P
ー
model); spdIt回dDB(TmodelId.dbld); spdIt回dDB(PmodelId.dbld);4 . 3 関数被呼び出しを求める
ある関数が他の関数中で呼び出される情報を求める。プログラム中のすべて の関数定義文における当該関数の出現を求める。
optionaldeclオブジエクト配 列 で 関 数 宣 言 オ ブ ジ ェ ク ト を 順 番 に 求 め 、 そ の 関 数 本 体 中 の
expressionオブ ジ エ ク ト の 出 現 を 求 め る 。 そ れ ら の オ ブ ジ ェ ク ト 中 で
sortが 関 数 呼 び 出 し 式
(EXPR̲SORT̲FUNCCALL)で 、 関 数 名 を 表 す
identifierオブジェクトの
Idが呼び出される関数と同じものを選び、そのオブジェクトに関連する情報を求 める。
関数
getFuncCalled一関数被呼び出しの情報を求める アルゴリズム
関数
getFuncCalled1.クラス
optionaldecJの配列オブジェクトを取得
2.
1.で取得されたオブジェクト中で
SORTが関数宣言であるものを選ぶ
3.式の出現で、
SORTが関数呼び出しであるものを選ぶ
4.3.で得られた式から関数名(i
dentifier)を取り出し、パラメータの
Idと比較 5.該当関数を呼び出す関数の情報(行数など)を出力
void geCfuncCalled(SpdObjld ident.ーid) {
S凶Cu四or・ 白r SpdObjldArray func̲a町'ay; SpdOcc 0田;
SpdObjld decr̲id. fname̲id; int i;
第2章