使用m4预处理器一次检查多个条件



是否有任何m4语法等同于这个C预处理器?

#if defined A || defined B
do something
#endif

简短的回答是否定的。

长答案:

检查是否定义了宏

define(`defined', `ifelse($1()$1, `$1()$1', ``0'', ``1'')')
ifelse(eval(defined(`A') || defined(`B')),
       1,
       ``At least one is defined'',
       ``Neither are defined'')

在m4中没有合理的方法来检查定义的宏,所以你必须求助于上面的hack。

工作原理

ifelse检查两个字符串是否相等。在defined宏中,我在$1中扩展了两次宏(一次是$1(),一次是$1)。我将它与$1()$1作为字符串进行比较,所以如果它不展开,那么它将比较为真。以两种不同的方式指定宏的原因是因为A可以定义为``A''``A()'',否则在使用此方法检查是否定义时将导致假阴性。

然后,我在eval中使用defined宏来将||逻辑放在顶部。

警告

  • 如果你已经在你的文档中使用了defined这个词,你可能想给宏一个不同的名字。
  • defined将不工作宏定义为扩展为无引号语法标记,如(, ,,或)
  • 如果要检查的宏是无限递归的,defined检查也将永远不会返回。(从本质上讲,要意识到这样的黑客实际上仍然在执行宏。)

虽然最后两点是您期望从宏的ifelse检查中得到的东西,但是期望从一个宏中检查是否定义了另一个宏可能并不直观。

更好的方法

我更愿意建议你先用一些默认值来定义变量,这样就可以避免检查它是否被完全定义的问题了。

这更容易做到:

# Define this right off the bat:
define(`A', ``0'')
# Maybe later this line will come up...
# Quotes around the A are mandatory
define(`A', ``1'')
# Then soon after that, you can check:
ifelse(A, `0', , ``hey, A is nonzero!'')

最新更新