[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: m4 macro expansion problem
From: |
Nick Bowler |
Subject: |
Re: m4 macro expansion problem |
Date: |
Mon, 23 Aug 2021 14:15:04 -0400 |
On 2021-08-23, Sébastien Hinderer <Sebastien.Hinderer@inria.fr> wrote:
> I would like to express all this in m4, more precisely in aclocal.m4, so
> that the configure script has proper version information.
>
> At the moment I don't manage to do so and failed to find an exemple of a
> macro whose body can take several lines but with the spaces at the begin
> of the lines (except the first one) being ignored. So I resorted to
> format but I didn't manage to make that work either and it any way feels
> too complex to be correct.
>
> Here is how the code looks like at the moment:
>
> # Package version
> define(`PKG_VERSION_MAJOR', `4')dnl
> define(`PKG_VERSION_MINOR', `14')dnl
> define(`PKG_VERSION_PATCH_LEVEL', `0')dnl
> define(`PKG_VERSION_EXTRA', `dev0-2021-06-03')dnl
> define(`PKG_VERSION_EXTRA_PREFIX', `+')dnl could also be `~'
> define(`PKG_VERSION',
> ``format(dnl
> PKG_VERSION_MAJOR.PKG_VERSION_MINOR`%s%s',dnl
> ifelse(PKG_VERSION_PATCH_LEVEL,`',`',.PKG_VERSION_PATCH_LEVEL),dnl
> ifelse(PKG_VERSION_PATCH_LEVEL,`',`',dnl
> PKG_VERSION_EXTRA_PREFIX`'PKG_VERSION_EXTRA)dnl
> )''dnl
> )dnl
First, a couple things:
- Autoconf renames most builtin M4 macros to have an m4_ prefix. So
in the context of aclocal.m4, you must use m4_define and m4_format.
(ifelse and dnl are not renamed, but m4_if is defined as an alias
for ifelse).
- Autoconf changes the M4 open quotation mark to [ and the close
quotation mark to ]. The ` and ' characters cease to have
special meaning.
So almost certainly none of the text you wrote in aclocal.m4
does anything, because 'define' will not be recognized as a macro
in Autoconf. However, you might not notice that this text went
unexpanded in Autoconf (which is in effect while processing
aclocal.m4) is KILL, so all resulting text is simply discarded.
(For this reason it is uncommon to use "dnl" at the top level here to
suppress unwanted blank lines in the output, as they will not be output
in any case).
Now, it is important to have a basic understand of how M4 collects
arguments. M4 roughly works like this:
- When the ( that begins a macro argument list is identified, the
first thing that M4 does is delete all subsequent whitespace
characters until it finds the first non-whitespace character.
- Then, M4 will look for the (unquoted) , or ) characters that
indicate the end of this argument: while it does this it expands any
unquoted macros found and this procedure continues until such an
unquoted comma or closing parenthesis is found (or the end of the
input, which would cause M4 to fail with an error).
- This process repeats (including the removal of whitespace) for each
macro argument until all arguments have been collected, quotation is
deleted (just one level) and the macro body is substituted.
Next, you should note that "dnl" is not very much like a comment you
might find in other languages. It is a macro, and its side effect of
deleting input text occurs only when it is expanded.
This can cause some surprising results when 'dnl' is used in macro
arguments. In your example, its use will interfere with the usual
removal of whitespace at the beginning of the arguments to 'format'.
Now you should hopefully have enough information to fix your macro
definition (bonus hint: it also looks overquoted).
Finally, I will note that Autoconf provides the macro m4_do which
simply expands to the text of all of its arguments. And m4_join
does the same with a separator between the arguments. Since M4
deletes whitespace at the beginning of each argument, these macros
can be useful for code formatting purposes.
Hope that helps!
Cheers,
Nick
Re: m4 macro expansion problem, Peter Johansson, 2021/08/23