Cプリプロセサを使い、#includeディレクティブにマクロで生成したファイル名を読ませる

タイトルのとおりだが、難しいぞ。

例えば、こういうのなら簡単だ:

#define _CONCAT(X,Y) X ## Y
#define CONCAT(X,Y) _CONCAT(X, Y)
#define HEY(X) CONCAT(X, X)
#define YO yo

int HEY(YO);

int yoyo;になるはず。

この、一段プリプロセサの命令を使う前に展開させるためのクッションを入れるテクを使うと、例えば、

#include CONFIGFILE(def)

が、

#include "defconfig"

になってほしいなら、

#define QUOTE(X) # X
#define QUOTIFY(X) QUOTE(X)
#define _CONCAT(X,Y) X ## Y
#define CONCAT(X,Y) _CONCAT(X, Y)
#define _CONFIGFILE(X) _CONCAT(X,config)

#define CONFIGFILE(X) QUOTIFY(_CONFIGFILE(X))

#include CONFIGFILE(def)

とすればいい。

では、次に

#include CONFIGFILE(def)

が、

#include "../defconfig"

となるにはどうすればいいだろうか。

#define UPDIR ../
#define __CONFIGFILE(X) CONCAT(UPDIR, _CONFIGFILE(X))

を足すと、 error: pasting "/" and "defconfig" does not give a valid preprocessing token と言われて怒られる。なぜならドットやスラッシュはC言語では一つのトークンをなすからだ。しかし、これを文字列として扱うと、""../""と"defconfig"の連結となってしまい、意図したものとは違うものになってしまう(と言うか以下でも怒られる):

#define _UPDIR ../
#define UPDIR # _UPDIR

しかし、この場合は、文字列連結ではなく、トークンの連接で解決できる、すなわち以下のとおり。

#define QUOTE(X) # X
#define QUOTIFY(X) QUOTE(X)
#define _CONCAT(X,Y) X ## Y
#define CONCAT(X,Y) _CONCAT(X, Y)
#define _CONFIGFILE(X) _CONCAT(X,config)

#define CONFIGFILE(X) QUOTIFY(../_CONFIGFILE(X))

#include CONFIGFILE(def)

やったぜ