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

Panu Matilainen pmatilai at laiskiainen.org
Fri Feb 3 12:14:41 UTC 2017


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

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 -
_______________________________________________
Rpm-maint mailing list
Rpm-maint at lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint


More information about the Rpm-ecosystem mailing list