Как вы можете включить защиту ifdef для файла макроса m4?

Для файлов заголовков C вы можете предотвратить многократное включение файла заголовка, например:

#ifndef MY_FOO_H
#define MY_FOO_H

[...]

#endif

Как я могу сделать то же самое в m4, чтобы несколько вызовов макросов include() для одного и того же файла приводили к включению содержимого только один раз?

В частности, я хочу сделать защиту ifdef, которая включает использование макроса changequote (я не буду загромождать свой код dnl):

Первоначально, когда я делаю следующее, множественные включения все еще портят кавычки:

changequote_file.m4:

ifdef(my_foo_m4,,define(my_foo_m4,1)
changequote([,])
)

changequote_invocation.m4:

include(changequote_file.m4)
After first include invocation:
[I should not have brackets around me]
`I should have normal m4 quotes around me'
include(changequote_file.m4)
After second include invocation:
[I should not have brackets around me]
`I should have normal m4 quotes around me'

Вызывается с m4 changequote_invocation.m4 дает:

After first include invocation:
I should not have brackets around me
`I should have normal m4 quotes around me'


After second include invocation:
[I should not have brackets around me]
`I should have normal m4 quotes around me'

m4
person Ross Rogers    schedule 17.03.2011    source источник


Ответы (2)


Самый простой способ — почти дословный перевод версии cpp:

ifdef(`my_foo_m4',,`define(`my_foo_m4',1)dnl
(rest of file here)
')dnl

Таким образом, если my_foo_m4 определено, файл расширяется до нуля, в противном случае оценивается его содержимое.

person geekosaur    schedule 17.03.2011
comment
Я думаю, что это работает при нормальных обстоятельствах (и отвечает на мой вопрос, так что спасибо!). Суть в том, что я делаю что-то немного сумасшедшее, поскольку мы не можем заставить m4 интерпретировать ‹обратную кавычку› и ' как кавычки, поскольку следующий инструмент использует эти символы в качестве допустимого ввода, и мы не хотим, чтобы пользователям приходилось делать еще один побег строки. Я пытаюсь импортировать файл, который выполняет команду changequote, но changequote выполняется только один раз, независимо от того, сколько раз выполняется это включение. В любом случае, я отправлю еще один вопрос и заставлю вас выкопать действительно сумасшедший старый хакерский m4. - person Ross Rogers; 18.03.2011
comment
Поэтому используйте приведенное выше в файле changequote. - person geekosaur; 18.03.2011
comment
Ах, вы бросили перчатку. Позвольте мне опубликовать код и посмотреть, сможете ли вы его разорить :-) - person Ross Rogers; 19.03.2011
comment
Ах, я понимаю, если изменить кавычки, это не сработает. Начните строки с последовательности, начинающейся с символа комментария вашего языка/программы (скажем, --! для последовательности комментариев --), затем выполните changecom(`--!'), чтобы при более поздних включениях m4 команды игнорировались. - person geekosaur; 19.03.2011
comment
Ах, немного атаки SQL-инъекцией для улучшения мира, а? Ok. Думаю, я могу это понять. - person Ross Rogers; 19.03.2011
comment
На самом деле, лучше: dnl @@@@ changecom(`@@@@') changequote(`%<',`%>') как файл, подставив свои кавычки и, возможно, изменив токен комментария в соответствии с вашим проектом. Обратите внимание, что changecom влияет только на символ комментария m4, и обычно не так хорошо, чтобы он совпадал с символом комментария базового инструмента. (Последовательность комментариев изменена из-за паранойи по поводу того, где m4 принимает значение по умолчанию #.) - person geekosaur; 19.03.2011

Я думаю, что на самом деле в вашем вопросе 2: - Как это сделать - почему это не работает в моем случае.

Способ сделать это почти так же, как вы сделали, но вам нужно все процитировать

ifdef(`my_foo_m4',,`define(`my_foo_m4',1)
  changequote([,])
')

Проблема заключается в том, что во второй раз, когда вы включаете файл, цитата была изменена, поэтому теоретически вы должны включить следующий файл (вы изменили цитату на [,], поэтому все файлы, которые вы включаете с этого момента, должны использовать [,] не должны?):

ifdef([my_foo_m4],,[define([my_foo_m4],1)
  changequote([[],])
])

но вы включаете тот же файл с исходной цитатой, поэтому Youw ifdef находится на символе `my_foo_m4' (что, вероятно, недопустимо), а не на my_foo_m4, а бит else

define(`my_foo_m4',1)
  changequote([,])

не заключен в кавычки (не между []) и поэтому оценивается независимо от результата теста, что означает вызов changequote с , , т. е. вызов

changequote(,)

Которые отключают цитату.

person mb14    schedule 10.10.2013