|
|
1
rici
7 年前
实际上
m4
(当前版本使用的宏处理器
flex
)哪个在扩大
__unix__
到空字符串。
m4的GNU实现将某些符号定义为空宏,以便使用
ifdef
当然,这是一个弹性的缺陷。flex不应允许从扫描仪定义文件复制的用户内容中展开宏
m4,而flex的当前版本正确地安排了要引用的扫描仪描述文件中包含的文本,以便它将通过
m4
unmodified,即使它碰巧包含一个可以集成的字符串rpreted by
m4
as a macro expansion.
flex的v2.5.39和v2.6.1中肯定存在这个bug。我没有测试所有以前的版本,但我认为它是在flex修改为使用
m4时引入的,根据新闻文件,它是v2.5.30版。
这个特别的引用问题在2.6.2版中得到了修复,但是当前版本的flex(2.6.4)包含了各种其他的错误修复,所以我建议您升级到最新版本。
如果您真的需要一个可以同时使用Buggy和最新版本的Flex的版本,那么您可以使用以下两种黑客中的一种:
-
找到其他方法来编写
uuunix_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu一种可能性是:
#define C(x,y) x##y
#define UNIX_ C(__un,ix__)
#if !defined(__linux__) && !UNIX_
那个黑客不适合
defined
,因为
defined(UNIX_)
测试是否
UNIX_
是定义的,而不是它扩展到的内容是否被定义。但通常内置符号,如
uuunix_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
#if
指令将未定义d的任何标识符视为0,这意味着您通常可以不使用
x
而不是
defined(x)
. (但是,如果
#define x 0
实际上,它不是一个完美的替代品。)
-
与许多M4应用程序一样,flex将M4的引号重新定义为
[[
和
]]
. BuggyFlex和修正后的版本都用一个相当复杂的序列来替换这些引号,该序列有效地引用了引号。但是,错误版本没有引用用户定义的文本,因此宏替换将在用户文本中执行。(如前所述,这就是为什么
Unix>变成空字符串的原因。
在不引用用户定义文本的flex版本中,可以调用定义引号的M4宏。然后,可以使用这些新的引号引用
if
行,以防止宏替换
unix_uuuuuuuuuuuux>。但是,必须恢复引用定义,否则将完全破坏文件其余部分的宏处理。这有点棘手,因为它不可能写入
[.
。(flex将用不同的字符串替换它。)
下面的内容似乎起到了作用。注意,宏调用放在C注释中。changequote宏将展开为空字符串(如果展开)。但是在2.6.2版以后的flex版本中,用户提供的文本被引用,因此changequote宏将不会被扩展。将它们放在注释中会从C编译器中隐藏它们。
%{
/*m4_changequote(<<,>>)<<*/
#if !defined(__linux__) && !defined(__unix__)
/*>>m4_changequote(<<[>><<[>>,<<]>><<]>>)*/
/* Maybe on windows */
#endif
(更改引号的M4宏是
changequote
但flex调用
-P
标记更改内置项,如
changeQuote
to
m4_changequote
. 在第二个changeQuote调用中,这两个调用
[
哪个组成了
[[
sign are individually quoted with the temporary
<<
引号,它将它们隐藏在flex中的代码中,而flex则修改了
[.
的用法。
我不知道这个黑客有多可靠,但它在我在我的机器上玩过的flex版本上起作用,包括2.5.4(pre-m4)2.5.39(Buggy)、2.6.1(Buggy)、2.6.2(稍微调试过)和2.6.4(更多调试过)。
|