Edited at

快適なC++生活のためにスクリプト言語を使おう

More than 3 years have passed since last update.

 開発ターゲットの言語がC++だからといって、それ以外の言語を使わない手はない。いまC++で書いているソースコードの健全性をチェックするために、スクリプト言語を使ってチェックすることができる。

 既存のコードを試行錯誤で改造していると、いつの間にか変なコードになっていることがある。ある一式のプログラムに、別のプログラムを切り貼りして機能を強化したようなときに、妙な状況に陥っている可能性がある。

・ヘッダファイルに定義されているのだが、目的のプログラムの範囲では使われていないマクロ定数、マクロ関数が放置されている。

・使われていないextern宣言

・同一名のマクロ定義の存在

 「まずは動かすことが先だ」で書いたコードを十分に見直さないままになっていると、このような変なコードになってしまっている。コードの行数が少なければ

grep '#define' *.h *.cpp

とかでも何とかなるだろうけれども、

プログラムの全体の行数が増えて、しかもマクロが不幸にも多く含まれているという状況では、grep以上のツールがほしくなる。

マクロは

#define DATA_SIZE  (1000)

#define square(x) ((x) * (x))

などのようにスペースやタブで区切られて記述されており、

最初のフィールドは"#define"であるという規則がある。

このことを利用して、次のようなツールを作ると上記の健全性のチェックツールを作ることができる。

・#defineが含まれている行で、スペース・タブ区切りテキストとしてフィールドに分割する。

・最初のフィールドが"#define"に一致しているときに、次のフィールドをキーワードとして辞書を作る。辞書の値としては、出現箇所のソースコードのファイル名のリストとする。

・そうして一連のソースコードを処理したあとに、辞書の値に複数のソースコードのファイル名が含まれていたら、それを表示する。

そんなツールが、スクリプト言語では簡単に書ける。

スクリプト言語を使って快適なC++生活をしよう。


おまけ:ヘッダファイルでのマクロの重複を見つけるスクリプト

参考のスクリプトを書いてみました。


doubledMacro.py

# -*- coding: utf-8 -*-

#pylint: disable=C0103
import os

u"""
ヘッダファイルでのマクロの重複を見つけるスクリプト
"""

def findDoubledMacro(wdir):
d = {}
for root, dirs, files in os.walk(wdir):
files = [p for p in files if os.path.splitext(p)[1] in ('.h', '.hpp')]
for p in files:
fullname = os.path.join(root, p)
for line in open(fullname, "rt"):
oline=line.replace("(", " ")
oline=oline.replace(")", " ")
oline=oline.replace(",", " ")

f = oline.strip().split()
if len(f) >= 2 and f[0] == "#define":
if not d.has_key(f[1]):
d[f[1]] = []
d[f[1]].append(p)

for k in d.keys():
if len(d[k]) > 1:
print k, d[k]

if __name__ == "__main__":
wdir = "."
findDoubledMacro(wdir)


実行結果の例

max ['sourceA.h', 'sourceB.h']

_UNICODE ['sourceB.h', 'sourceC.h']
DATA_SIZE ['sourceA.h', 'sourceB.h']

実行結果に使用した入力データ


sourceA.h

#ifndef SOURCEB_H

#define SOURCEB_H

#define DATA_SIZE (100)
#define _UNICODE
#define DEBUG_VIEW
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif


sourceB.h

#ifndef SOURCEB_H

#define SOURCEB_H

#define DATA_SIZE (100)
#define _UNICODE
#define DEBUG_VIEW
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif


subDir/sourceC.h

#ifndef SOURCEC_H

#define SOURCEC_H

#define DATA_SIZEC (100)
#define _UNICODE
#define DEBUG_VIEW2
#endif

追記:

快適なC++生活のためにスクリプト言語を使おう2 C++のソースを自動生成させる

快適なC++生活のためにスクリプト言語を使おう3 ーグラフ作成はmatplotlibにまかせようー

快適なC++生活のためにスクリプト言語を使おう4 - C++の自作ライブラリをスクリプト言語から使おう -

快適なC++生活のためにスクリプト言語を使おう5 - 数値データの確認にはSpyder統合環境を使おう -