C でヒアドキュメントごっこ

C 言語 マクロ講座 # ## 編に触発されて、もうすこし悪戯を。(例によってcygwin+gcc)

htmlでは、” (ダブルクォート)が多用されているので、cgiプログラムでは、文字列として定義するときにエスケープする必要があり面倒です。<h1 id=”title”>hello</h1> は、”<h1 id=\”title\”>hello</h1>” として定義しなければなりません。このおかげで、Starbug1のソースは大変なことになってます。普通ならテンプレートエンジン書け!ってことになるんでしょうが、Starbug1の性質上余分なことはしたくないので、現在htmlをエスケープしながら直書きしてます。

プリプロセッサで処理する方式で、エスケープせずにhtmlを記述できるようになると非常に嬉しいので、# を使ってヒアドキュメント風なものを試してみました。最初試したのは、↓のような感じ。普通に動きました。

#include <stdio.h>
#define D(body) #body "\n";
 
int main(int argc, char** argv)
{
    char* html = D(
        <html>
        <body>
        <h1 id="title">hello</h1>
        </body>
        </html>
    );
    printf("%s", html);
    return 0;
}

Dというマクロの引数を文字列として展開することでソース中ではエスケープしなくていいようになっています。

http://d.hatena.ne.jp/smeghead/20071130/withmacro で見付けた複数の文でも渡せてしまう性質も利用してます。

実行結果

$ gcc sharp.c
$ ./a.exe
<html> <body> <h1 id="title">hello</h1> </body> </html>

途中の改行が消えてるけど、htmlだから問題ないです。

で次は、ヒアドキュメント(と呼んでいいか迷いますが)の中に、 , があるとマクロの次の引数が指定されたことになってしまい、コンパイルエラーが発生しました。このままでは、「hello, world.」という文字列をヒアドキュメント中に含めることができませんので、__VA_ARGS__ で回避してみました。

#define D(...) #__VA_ARGS__ "\n";
$ gcc sharp.c
$ ./a.exe
<html> <body> <h1 id="title">hello, world.</h1> </body> </html>

めでたしめでたし。


ヒアドキュメント部分にいろんな記号を入れてみました。

#include <stdio.h>
#define D(...) #__VA_ARGS__ "\n";
int main(int argc, char** argv)
{
char* html = D(
<html>
<body>
<h1 id="title">hello, world.</h1>
!@#$%^&*()_+|~`\=-[]{}'");:<>
 </body>
</html>
    );
    printf("%s", html);
    return 0;
}

ここまで来るとvimやHatenaの syntaxhilight も役立たずです。

実行結果

$ gcc sharp.c
sharp.c:14:5: warning: unknown escape sequence &#39;&#92;=&#39;
$ ./a.exe
<html> <body> <h1 id="title">hello, world.</h1> !@#$%^&*()_+|~`=-[]{}'");:<> </body> </html>

いろんな記号を入れてみましたが動いてくれていました。(警告は出ていますが、回避するのも問題ないと思う)

ヒアドキュメント中に、「);」が出てきても大丈夫ってのは、gccはどこまで賢いんだろう?逆に不安になるという考え方もある。

これもStarbug1に取り込んでしまおうかな。

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.