3

For C header files, you can prevent multiple inclusion of a header file like:

#ifndef MY_FOO_H
#define MY_FOO_H

[...]

#endif

How can I do the same thing in m4 such that multiple include() macro calls to the same file will only cause the contents to be included once?

Specifically, I want to do an ifdef guard that involves using macro changequote ( I'll not clutter my code with dnl's):

Originally, when I do the following, multiple inclusions still corrupts the quotes:

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'

Invoked with m4 changequote_invocation.m4 yields:

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'
Ross Rogers
  • 23,523
  • 27
  • 108
  • 164

2 Answers2

7

The most straightforward way is an almost-literal translation of the cpp version:

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

So if my_foo_m4 is defined, the file expands to nothing, otherwise its contents are evaluated.

edA-qa mort-ora-y
  • 30,295
  • 39
  • 137
  • 267
geekosaur
  • 59,309
  • 11
  • 123
  • 114
  • I think that does work, under normal circumstances ( and answers my question, so thanks!). The kicker is that I'm doing something a little crazy since we can't have m4 interpret and ' as quotes since the next tool uses those characters as valid input and we don't want users to have to do yet another string escape. I'm trying to import a file that does a `changequote` command, but only have `changequote` execute once, regardless of how many times that include is executed. Anyways, I'll post another question and make you dredge up some really crazy old m4 hackery. – Ross Rogers Mar 18 '11 at 20:46
  • So use the above in your changequote file. – geekosaur Mar 18 '11 at 20:48
  • Ah, you've thrown down the gauntlet. Let me post the code and see if you can ravage it :-) – Ross Rogers Mar 18 '11 at 21:16
  • Ah, I get it, if the quotes are changed that won't fly. Start the lines with a sequence starting with your language/program's comment character (say, `--!` for comment sequence `--`), then do ``changecom(`--!')`` so on later inclusions `m4` will ignore the commands. – geekosaur Mar 18 '11 at 21:22
  • Ah, a little bit of SQL injection attack for the betterment of the world, eh? Ok. I think I can figure that out. – Ross Rogers Mar 18 '11 at 21:25
  • 2
    In fact, better: ``dnl @@@@ changecom(`@@@@') changequote(`%<',`%>')`` as the file, substituting your quotes and possibly changing the comment token to suit your project. Note that `changecom` only affects `m4`'s comment character, and it's usually not so good to have it be the same as the underlying tool's comment character. (Switched comment sequence out of paranoia over where `m4` accepts the default `#`.) – geekosaur Mar 18 '11 at 21:26
2

I think there are in fact 2 question in yours : - How to do it - why it doesn't work in my case.

The way to do it is almost as you've done, but you need to quote everything

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

The problem is the second time you include the file, the quote have been changed, so you should in theory include the following file (you've change the quote to [,] so all the files you include from now should use [,] shouldn't they ?):

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

but you include the same file with the original quote therefore Youw ifdef is on the symbol `my_foo_m4' (which is probably invalid) not my_foo_m4 and the else bit

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

is not quoted (not between []) and so evaluated whatever the result of the test is, meaning it call changequote with , , ie it calls

changequote(,)

Which disable the quote.

mb14
  • 22,276
  • 7
  • 60
  • 102