デフォルトyyout
では に設定されており、ストリームstdout
にリダイレクトできます。FILE*
にリダイレクトする方法はありyyout
ますchar*
か?
1 に答える
それを行うにはいくつかの方法があります。yyout を使用しようとしている場所にスキャナー コードを少し投稿すると、より具体的な回答が得られる可能性があります。
通常、これを行うのはアクションです。ECHO
したがって、 orを使用する代わりに、次のfprintf(yyout...
ようなものを使用します
<token> { snprintf(buf, sizeof(buf), "%s", yytext); }
以前は次のように宣言していたはずです:
char buf[BUFSIZE];
補遺 I - 別のアプローチ
この状況に対処する巧妙な方法はありますが、それらは「賢い」ため、長期的にはメンテナンスの問題が発生する傾向があります。(賢さが添付された警告とともに十分に文書化されていない限り)
int yyprintf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
if ( some_flag & FLAG_OUTFILE ) {
vfprintf(yyout, fmt, ap);
}
else {
sprintf(buf, fmt, ap);
}
va_end(ap);
}
ここで、buf はグローバル バッファです。
ただし、物事を少しローカルにしたい場合:
アプローチ 2: いつどこに行くかをきめ細かく制御する
途中で物事がどこに行くかを細かく制御したい。ファイルへの出力が必要な場合もあれば、文字列への出力が必要な場合もあり、次のようなものをいつどこで使用できるかが常にわからない場合があります。
int myvprintf(void *here, size_t len, const char *fmt, va_list ap)
__attribute__((format (gnu_printf, 3, 4), nonnull(1, 3))) {
int rv;
if ( len > 0 ) {
rv = vsnprintf((char *), len, fmt, ap);
}
else {
rv = vfprintf((FILE *)here, fmt, ap);
}
return rv;
}
int myprintf(void *here, size_t len, const char *fmt, ... )
__attribute__((format (gnu_printf, 3, 4), nonnull(1, 3))) {
int rv;
va_list ap;
va_start(ap, fmt);
rv = myvprintf(here, len, fmt, ap);
va_end(ap);
return rv;
}
途中で myprintf を使用すると、常に何があるかを制御できますhere
。
楽しみのために
家でこれを試さないでください。しかし、すべての yy* 識別子と ECHO は単純な変数ではなく、#define です。したがって、巧妙なマクロの書き換えを行うことができます。
たとえば、どこでも ECHO を使用している場合は、上部のセクションで好きなように (#undef と #define だけで) 再定義できます。
%{
#undef ECHO
#define ECHO snprintf(buf, sizeof(buf), "%s", yytext)
%}
%%
<token> ECHO;
%%
複雑なヘッダーにすべてを隠して、嫌いなプログラマーにとって後でデバッグが地獄になるような他の巧妙さを実行してください。これには、独自の報酬とクスクスがあります。