传递给宏的非空args的数量

时间:2014-12-28 04:02:03

标签: m4

在GNU M4中,我一直在尝试编写一个函数来确定传递给它的非空(不等于`'的args)。

它应该像这样可以调用:

ne_nargs(0, `1', `')
# 1

ne_nargs(0, `')
# 0

ne_nargs(0, `1')
# 1

请注意,第一个参数应始终为0

这是我到目前为止的代码:

define(`ne_nargs', `ifelse(`$#', `1`, $1,
   `ifelse(`$2', `', `pushdef(`$2', $1)ne_nargs(shift($@))',
     `pushdef(`$2', incr($1))ne_nargs(shift($@))')')')

这里是伪代码:

if (number_of_args == 1); then
  return first_arg; // which is `0` by default.
else if (second_arg == ''); then
  second_arg = first_arg;
  return ne_nargs(shift(all_args));
else
  second_arg = (++first_arg);
  return ne_nargs(shift(all_args));

ne_nargs(`0', `', `1', `i', `', `l')

# what I get
m4:test.m4:8: empty string treated as 0 in builtin `incr'
m4:test.m4:8: empty string treated as 0 in builtin `incr'
1

# what I expect
3

我无法弄清楚我在ne_nargs的定义中做错了什么,在尝试了几种不同的方法来抽象部分宏之后,我就准备好了放弃。

1 个答案:

答案 0 :(得分:1)

我认为你不应该试图覆盖$@;你可以从警告中看到,覆盖$ 2肯定不会影响$@。文档中的join example改为将第二个参数移出:

`$0(`$1', shift(shift($@)))'

以下是有效的:

define(`ne_nargs', `ifelse(`$#', `2', `ifelse(`$2', `', `$1', incr(`$1'))',
  `ifelse(`$2', `', `$0(`$1', shift(shift($@)))',
    `$0(incr($1), shift(shift($@)))')')')
ne_nargs(`0', `', `1', `i', `', `l')

(我不知道清理递归调用的好方法,因此不必独立检查2参数调用,因此如果您担心干燥,可能需要改进。)