Lemon Parser Generatorで生成されるコードには(というよりも、lempar.cによれば)、staticな関数とstaticでない関数がある。ヘッダオンリーで扱いたいのでstaticでない関数にはinlineを付けておきたい。%nameが指定されていない場合のstaticでない関数は下記になる。これらをエクスポートされる関数と呼ぼう。
普通に考えると、lempar.cを変更するのが一番楽だ。あるいは、後処理でinlineを付けてもよい。awkで書くとこんな感じ。
しかしだ。既にマクロが使用されている以上、毒をくらわば皿までである。ちなみに、エクスポートされる関数は、生成されたコードのなかで参照されていないので、こういうことができる。
邪悪すぎる。
そもそものところに立ち返ると、inlineを付けるという発想がよろしくない。それぞれの翻訳単位に、同じ名前の関数の定義がばらまかれてしまうのが問題だった。Cならばともかく、C++には無名名前空間がある。これによって、関数の定義はばらまかれるが、それぞれはお互いに異なる名前を持つことになる。いや、ばらまかれるのは変わらないんだけれども。
void ParseTrace; void *ParseAlloc; void ParseFree; int ParseStackPeak; void ParseFree;
普通に考えると、lempar.cを変更するのが一番楽だ。あるいは、後処理でinlineを付けてもよい。awkで書くとこんな感じ。
awk '/^(void|int)/ { print "inline", $0 }; { print }'
しかしだ。既にマクロが使用されている以上、毒をくらわば皿までである。ちなみに、エクスポートされる関数は、生成されたコードのなかで参照されていないので、こういうことができる。
#define ParseTrace inline ParseTrace #define ParseAlloc inline ParseAlloc #define ParseFree inline ParseFree #define ParseStackPeak inline ParseStackPeak #define ParseFree inline ParseFree
邪悪すぎる。
そもそものところに立ち返ると、inlineを付けるという発想がよろしくない。それぞれの翻訳単位に、同じ名前の関数の定義がばらまかれてしまうのが問題だった。Cならばともかく、C++には無名名前空間がある。これによって、関数の定義はばらまかれるが、それぞれはお互いに異なる名前を持つことになる。いや、ばらまかれるのは変わらないんだけれども。
コメントをかく