autoconf
[Top][All Lists]
Advanced

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

Re: m4/autoconf quoting difference in include()


From: Eric Blake
Subject: Re: m4/autoconf quoting difference in include()
Date: Wed, 16 Jul 2014 10:25:16 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.6.0

On 07/16/2014 09:17 AM, Roman Neuhauser wrote:
> (this is a resend with a proper subject, sorry)
> 
> i had some trouble figuring out how to get the include macro inside
> another (parameterized) macro.

I think your problem is not with include, per se, but rather with the
more generic question of "How do I write a macro which in turn defines
another macro that contains parameterization".

> 
> this works in m4:
> 
>   changequote(`[', `]')
> 
>   define([nodot], [[\([_0-9a-zA-Z]+\)]])
>   define([reversion], [^nodot\.nodot\.nodot$])
>   define([getver], [regexp($1, reversion, $2)])
>   define([readver], [getver(include($1), [\&])])

Insufficiently quoted.  You probably meant include([$1]), to include the
file literally named "VERSION" and not the file that happens to be
whatever the macro $1 expands to.

> 
>   readver([VERSION])

but you got away with it, because your m4 example did not define a macro
named VERSION.  But that's unrelated to your actual problem.

> 
> this fails in configure.ac (autoconf 2.69):
> 
>   m4_define([nodot], [[\([_0-9a-zA-Z]+\)]])
>   m4_define([reversion], [^nodot\.nodot\.nodot$])
>   m4_define([getver], [regexp($1, reversion, $2)])

Why not use m4_bregexp here?

>   m4_define([readver], [getver(m4_include($1), [\&])])
>   m4_define([ver], readver([VERSION]))
> 

You aren't showing enough context here.  My guess is that you are trying
to do something even bigger; maybe along the lines of:

AC_DEFUN([my_macro], [
  ... existing m4_define calls...
])

right?  Here's why I think that:

> messages:
> 
>   aclocal: error: configure.ac:7: file '$1' does not exist
>   autoreconf: aclocal failed with exit status: 1

Your message is not reproduced if I do things at the top level:

$ cat > configure.ac <<\EOF
  m4_define([nodot], [[\([_0-9a-zA-Z]+\)]])
  m4_define([reversion], [^nodot\.nodot\.nodot$])
  m4_define([getver], [regexp($1, reversion, $2)])
  m4_define([readver], [getver(m4_include($1), [\&])])
  m4_define([ver], readver([VERSION]))
AC_INIT
witness string
ver
EOF
$ echo 1.2.3 > VERSION
$ autoconf
$ grep -A1 'witness string' configure
witness string
1.2.3
$

But if I try to write a macro whose expansion defines macros, then I see
a similar issue:

$ cat configure.ac
AC_DEFUN([my_macro], [
  m4_define([nodot], [[\([_0-9a-zA-Z]+\)]])
  m4_define([reversion], [^nodot\.nodot\.nodot$])
  m4_define([getver], [regexp($1, reversion, $2)])
  m4_define([readver], [getver(m4_include($1), [\&])])
  m4_define([ver], readver([VERSION]))
])
AC_INIT
witness string
my_macro
ver
$ autoconf
/usr/bin/m4:configure.ac:10: cannot open `': No such file or directory
autom4te: /usr/bin/m4 failed with exit status: 1
$

So - what's going on?  The answer is that $1 is getting substituted too
early.  In my example, it was getting substituted at the time I called
my_macro, with whatever $1 was in the argument to my_macro.  That is, as
written, my_macro called without arguments includes this expansion text:

  m4_define([readver], [getver(m4_include(), [\&])])

after $1 was prematurely expanded.

But my error message mentions `', not `$1', as the failed file name, so
I can't fathom the full context of your example that seems to be causing
$1 to be treated as a literal file name.

> 
> i can get it to work by quoting the m4_include macro name:
> 
>   m4_define([readver], [getver([m4_include]($1), [\&])])

Without seeing the full context of where you are trying to add this
text, I'm not sure why it (seems to) work for you.  In my example, that
is not the right workaround:

$ cat configure.ac
AC_DEFUN([my_macro], [
  m4_define([nodot], [[\([_0-9a-zA-Z]+\)]])
  m4_define([reversion], [^nodot\.nodot\.nodot$])
  m4_define([getver], [regexp($1, reversion, $2)])
  m4_define([readver], [getver([m4_include]($1), [\&])])
  m4_define([ver], readver([VERSION]))
])
AC_INIT
witness string1
my_macro
ver
witness string2
$ autoconf
$ sed -n '/witness string1/,/witness string2/p' configure | cat -s
witness string1

witness string2
$

which means that I ended up defining 'ver' to the empty string.  But
THIS works:

$ cat configure.ac
AC_DEFUN([my_macro], [
  m4_define([nodot], [[\([_0-9a-zA-Z]+\)]])
  m4_define([reversion], [^nodot\.nodot\.nodot$])
  m4_define([getver], [regexp($][1, reversion, $][2)])
  m4_define([readver], [getver(m4_include($[]1), [\&])])
  m4_define([ver], readver([VERSION]))
])
AC_INIT
witness string1
my_macro
ver
witness string2
$ autoconf
$ sed -n '/witness string1/,/witness string2/p' configure | cat -s
witness string1

1.2.3
witness string2
$

Notice that I used the construct define([name], [...($][1)...]) to get
the $1 to not be concatenated at the expansion of the outer macro, but
to wait until the inner m4_define is actually used.

> 
> why is this?  can you point me to the relevant passages in the manual?

https://www.gnu.org/software/autoconf/manual/autoconf.html#Quoting-and-Parameters

> i admit i haven't read it all (yet).
> 

Other ideas.  Do you really need to wait to define your helper macros
until the time that my_macro is expanded?  Or can you hoist them to the
top level, outside of the AC_DEFUN, where you don't have to worry about
deferred concatenation of $ and 1?

Also, what are the contents of your VERSION file?  Is the whole point of
your regexp to try and strip the trailing newline away?  If so, why not
go with the simpler:

m4_define([ver], m4_esyscmd_s([cat VERSION]))

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]