брой непразни аргументи, предадени на макрос

В GNU M4 се опитвам да напиша функция, която определя колко непразни (аргументи, които не са равни на `') са й предадени.

Предполага се, че може да се извика така:

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 и след като опитах няколко различни начина за абстрахиране на части от макроса, почти съм готов да се откажа.


m4
person Alexej Magura    schedule 28.12.2014    source източник


Отговори (1)


Не мисля, че трябва да се опитвате да презапишете $@; можете да видите от предупрежденията, че презаписването на $2 определено не засяга $@. примерът за присъединяване в документите вместо това измества втория аргумент с:

`$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 аргумента не трябва да се проверява независимо, така че това може да е нещо, което да подобрите, ако сте загрижени за DRYness.)

person lossleader    schedule 30.12.2014