Проверка нескольких условий одновременно с помощью препроцессора m4

Есть ли какой-либо синтаксис m4, который эквивалентен этому препроцессору C?

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

person xor76rox    schedule 15.09.2015    source источник


Ответы (1)


Короткий ответ: нет.

Длинный ответ:

Проверка, определены ли макросы

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, поэтому вам придется прибегнуть к хакам, подобным приведенным выше.

Как это работает

ifelse проверяет равенство двух строк. В макросе defined я дважды расширил макрос в $1 (один раз как $1(), один раз как $1). Я сравниваю его с $1()$1 как строку, поэтому, если он не расширяется, он будет сравниваться с правдой. Причина указания макросов двумя разными способами заключается в том, что A может быть определено как ``A'' или ``A()'', что в противном случае привело бы к ложным отрицательным результатам при использовании этого метода для проверки того, определен ли он.

Затем я использую этот макрос defined в eval, чтобы добавить логику || сверху.

Предостережения

  • Если вы уже используете слово defined в своем документе, вы можете дать макросу другое имя.
  • Макрос defined не будет работать в макросах, определенных для расширения до синтаксических маркеров без кавычек, таких как (, , или ).
  • Если проверяемый макрос бесконечно рекурсивен, проверка defined также никогда не вернется. (По сути, поймите, что подобный хак все еще фактически выполняет макрос.)

Хотя последние 2 пункта - это то, что вы ожидаете от любой 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!'')
person Score_Under    schedule 01.08.2016