[Rpm-maint] Fixing macro scoping
Panu Matilainen
pmatilai at laiskiainen.org
Mon Jan 23 10:30:21 UTC 2017
Consider the following snippet, originating from
https://bugzilla.redhat.com/show_bug.cgi?id=552944:
%{!?foo: %define foo bar}
%define dofoo() true
echo 1: %{foo}
%dofoo
echo 2: %{foo}
I'd assume everybody agrees both %{foo}'s should evaluate to the same
value, but that is not the case currently. Using a cli-variant of the above:
[pmatilai at sopuli rpm]$ rpm --define 'dofoo() true' --eval '%{!?foo:
%define foo bar}' --eval '%foo' --eval '%dofoo' --eval '%foo'
warning: Macro %foo defined but not used within scope
bar
true
%foo
The flaw here is that rpm supposedly implements block level scoping for
macros (so in the above example, "foo" would only exist in the
{!?foo:...} block), but doesn't actually enforce that, unless a
parametric macro is "called". Current rpm warns about it, but warnings
or not this behavior doesn't make the slightest sense.
The question is, what do you think %{foo} should evaluate to in this case?
Fixing it to honor the strict "block scoping" concept is not hard, now
that the scoping level is honored from Lua too (see
https://github.com/rpm-software-management/rpm/commit/1767bc4fd82bfacee622e698f9f0ae42c02126fa).
In this case the above reproducer would emit
%foo
true
%foo
Another option is slightly changing the whole scoping notion: parametric
macros require locally scoped macros for the automatic argument macros
like %#, %* and %1 anyway (it's flawed too currently, see below). So
perhaps the macro scoping should follow the current "call level", ie a
macro defined inside a parametric macro body is local to that macro, and
everything else is global. In this case the reproducer would emit
bar
true
bar
I have implementations for both and also a personal opinion, but I'd
like to hear what others think.
The related flaw is whether locally scoped macros should be visible to
deeper nesting levels. Currently everything is, including those
automatic macros:
$ rpm --define '%bar() Bar %#: %{?1} %{?2}' --define '%foo() Foo %#:
%{?1} %{?2} %bar a' --eval '%foo 1 2'
Foo 2: 1 2 Bar 1: a 2
I'd consider this a bug, %2 should not be defined within %bar() since it
did not receive two arguments. So IMO the correct output in the above
should be:
Foo 2: 1 2 Bar 1: a
But what about a macro manually %define'd within %foo() - should that be
visible in %bar()?
- Panu -
More information about the Rpm-maint
mailing list