[Rpm-ecosystem] Fwd: [Rpm-maint] Fixing macro scoping

Pascal Terjan pterjan at gmail.com
Fri Feb 3 13:26:19 UTC 2017

On 3 February 2017 at 12:14, Panu Matilainen <pmatilai at laiskiainen.org> wrote:
> Stunned silence on rpm-maint, forwarding to rpm-ecosystem in hopes of a
> larger and livelier audience...
>         - Panu -
> -------- Forwarded Message --------
> Subject: [Rpm-maint] Fixing macro scoping
> Date: Mon, 23 Jan 2017 12:30:21 +0200
> From: Panu Matilainen <pmatilai at laiskiainen.org>
> To: rpm-maint at lists.rpm.org <rpm-maint at lists.rpm.org>
> 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

My first reaction was to prefer this one because '%{!?foo: %define foo
bar} has been used in tens of thousands of packages and sort of worked
But replacing define with global is not very hard so no strong opinion...

> 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

Yes that's indeed very unexpected as I have always considered %n to be
referring to the parameters of current macros
All %n > %# should be cleared at the same time %# is set

> But what about a macro manually %define'd within %foo() - should that be
> visible in %bar()?

I would expect so

More information about the Rpm-ecosystem mailing list