開発ターゲットの言語がC++だからといって、それ以外の言語を使わない手はない。いまC++で書いているソースコードの健全性をチェックするために、スクリプト言語を使ってチェックすることができる。
既存のコードを試行錯誤で改造していると、いつの間にか変なコードになっていることがある。ある一式のプログラムに、別のプログラムを切り貼りして機能を強化したようなときに、妙な状況に陥っている可能性がある。
・ヘッダファイルに定義されているのだが、目的のプログラムの範囲では使われていないマクロ定数、マクロ関数が放置されている。
・使われていないextern宣言
・同一名のマクロ定義の存在
「まずは動かすことが先だ」で書いたコードを十分に見直さないままになっていると、このような変なコードになってしまっている。コードの行数が少なければ
grep '#define' *.h *.cpp
とかでも何とかなるだろうけれども、
プログラムの全体の行数が増えて、しかもマクロが不幸にも多く含まれているという状況では、grep以上のツールがほしくなる。
マクロは
#define DATA_SIZE (1000)
#define square(x) ((x) * (x))
などのようにスペースやタブで区切られて記述されており、
最初のフィールドは"#define"であるという規則がある。
このことを利用して、次のようなツールを作ると上記の健全性のチェックツールを作ることができる。
・#defineが含まれている行で、スペース・タブ区切りテキストとしてフィールドに分割する。
・最初のフィールドが"#define"に一致しているときに、次のフィールドをキーワードとして辞書を作る。辞書の値としては、出現箇所のソースコードのファイル名のリストとする。
・そうして一連のソースコードを処理したあとに、辞書の値に複数のソースコードのファイル名が含まれていたら、それを表示する。
そんなツールが、スクリプト言語では簡単に書ける。
スクリプト言語を使って快適なC++生活をしよう。
おまけ:ヘッダファイルでのマクロの重複を見つけるスクリプト
参考のスクリプトを書いてみました。
# -*- 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']
実行結果に使用した入力データ
#ifndef SOURCEB_H
#define SOURCEB_H
#define DATA_SIZE (100)
#define _UNICODE
#define DEBUG_VIEW
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef SOURCEB_H
#define SOURCEB_H
#define DATA_SIZE (100)
#define _UNICODE
#define DEBUG_VIEW
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef SOURCEC_H
#define SOURCEC_H
#define DATA_SIZEC (100)
#define _UNICODE
#define DEBUG_VIEW2
#endif
追記:
快適なC++生活のためにスクリプト言語を使おう2 C++のソースを自動生成させる
快適なC++生活のためにスクリプト言語を使おう3 ーグラフ作成はmatplotlibにまかせようー