C/C++コメント抜き出し

C/C++のソースファイルからコメントアウトを除去するとか、xxコマンド(or スクリプト)ならone lineでできるよ、yyエディタならzz操作でできるよ、とかありそうですが、昔お世話になったlexで。
せっかくなので、メモしておきます。

%{
#include <stdio.h>
static int cmt;
%}
%start CMT CMT2
%%
<CMT>"*/"           { fputs( cmt? yytext:"  ", yyout ); BEGIN INITIAL; }
<CMT>"\n"           { fputs( yytext, yyout ); }
<CMT>.              { fputs( cmt? yytext:" ", yyout ); }
<CMT2>"\n"          { fputs( yytext, yyout ); BEGIN INITIAL; }
<CMT2>.             { fputs( cmt? yytext:" ", yyout ); }
<INITIAL>"/*"       { fputs( cmt? yytext:"  ", yyout ); BEGIN CMT; }
<INITIAL>"//"       { fputs( cmt? yytext:"  ", yyout ); BEGIN CMT2;}
<INITIAL>"\t"       { fputs( yytext, yyout ); }
<INITIAL>"\n"       { fputs( yytext, yyout ); }
<INITIAL>.          { fputs( cmt? " ":yytext, yyout ); }
%%
int yywrap(void)
{
    return 1;
}
int main( int ac, char *av[])
{
    register int idx = 1;
    if ( ac < 2 ) {
        fprintf(stderr,"usage: %s [-c] FILE ", av[0]);
        return 1;
    }
    switch (getopt(ac, av, "c")) {
    case 'c':
       cmt = 1;
       idx++;
       break;
    default:
       break; 
    }
    yyin = fopen(av[idx], "r");
    if ( NULL == yyin ) {
        fprintf(stderr,"Can't open \"%s\" "., av[idx]);
        return 1;
    }
    yyout = stdout;
    yylex();
    return fclose(yyin);
}

-c オプション指定の場合はコメントアウト文のみ抽出するようにしてみました。
ルール部はもう少し考えればもっとカッコよくできるのかな。