Re: m4 macro expansion problem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2021-08-23, Sébastien Hinderer <Sebastien.Hinderer@xxxxxxxx> 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





[Index of Archives]     [GCC Help]     [Kernel Discussion]     [RPM Discussion]     [Red Hat Development]     [Yosemite News]     [Linux USB]     [Samba]

  Powered by Linux