Хочу реализовать include guard на m4. Чтобы если я сделаю m4_include несколько раз одного и того же файла, это не привело к генерации нескольких копий текста.
Гугление выдало следующую инструкцию - http://stackoverflow.com/questions/5346397/how-can-you-do-an-ifdef-guard-for-.... То есть по сути дела советуют сделать аналог того, что делают при использовании сишного препроцессора.
Я, конечно, не против, но и в CPP меня раздражала необходимость писать целых 3 строчки, да ещё и 2 раза писать одно и то же название guard-переменной. Одна опечатка и имеем глюк. Но в CPP иначе нельзя - ведь макроопределение не способно породить новый макрос. А вот M4 такое умеет.
Пишем:
m4_define(`REMOVE_QUOTES', $*)
m4_define(`DEFINE_ONCE', `m4_ifdef(`$1',,`
m4_define(`$1',1)
REMOVE_QUOTES(m4_shift($@))
')')
А затем в файлах я буду писать:
DEFINE_ONCE(__MY_COOL_FILE_H__, `
... тут идёт содержимое файла, возможно, с другими макроопределениями ...
')
Чтобы проще было экспериментировать запускал M4 без аргументов и печатал туда всякие разные команды и смотрел, что получается.
Для начала я выполнил такое объявление, как указано выше. А затем использую его:
DEFINE_ONCE(T,A)
A
DEFINE_ONCE(T,A)
A
DEFINE_ONCE(T,A)
Можно заметить, что M4 почему-то дал мне описать одно и то же второй раз (хотя T становится defined уже после первого вызова DEFINE_ONCE), а третий (и последующие) уже не даёт. Если я попытаюсь затем сделать новое описание (с другой guard-переменной), то такой проблемы уже не будет (даже второй раз ничего не объявиться).
Что я не так понял в синтаксисе M4?