LoginSignup
3
8

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-09-25

 開発ターゲットの言語が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統合環境を使おう -

3
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
8