tech-userlevel archive

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

Re: make(1): is this a bug or PEBKAC?



Am 22.02.2023 um 05:54 schrieb Mouse:
     121	$(x:C;^.*\.([0-9].*)$$;$(INSTMANDIR)/cat\1;):

So, I'm wondering, is this a bug in 9.1's make, or am I doing
something wrong here?

TL;DR: There are several cases in which make silently ignores parse
errors, such as '$$' in variable modifiers.  In other cases, it has
become stricter over time, or the accepted syntax just changed.

:-(

The crucial part in your example is the '$$'.

Actually, they were initially single $s.  I changed them in an attempt
to fix it after seeing the 9.1 manpage note that the pattern and
replacement were subject to variable expansion; I wasn't sure what a
trailing single $ would do, so I doubled it.

Completely understandable. For a very long time, I had been confused by
these escaping rules as well. That's why in 2020 I started refactoring
usr.bin/make and added several new tests in usr.bin/make/unit-tests.
Nothing of this work is available in NetBSD 9, it's all for NetBSD 10.

The unit tests contain about 12000 lines of commented examples, many of
them explaining how basic features and their edge cases work. I don't
want to add these to the manual page though, as I consider most of them
implementation details that should be eliminated one day, to avoid
further surprises.

In normal strings, '$$' is used to escape a '$'.  But in variable
modifiers such as ':C', '\$' is used instead to escape a '$'.

Hm, is that documented somewhere?  The only place I see \$ in the 9.1
manpage is in an example in the description of :q.

I restructured and rewrote make.1 in NetBSD 10, so have a look at
https://man.netbsd.org/make.1. Between NetBSD 9 and NetBSD 10, the code
changed a lot, but the functionality mostly stayed the same.

In netbsd-9:usr.bin/make/var.c, the parser looks at
'$(x:...(...)$$)', trying to figure out which parentheses match, see
the comment "Attempt to avoid ';' inside substitution patterns" in
parse.c.  In this case, the parser fails.  It counts the '$(' as
starting a subexpression, then ignores the following '(', and when it
sees the first ')', it considers the expression completed, leaving
the '$$)' for a syntax error.

I don't see $$) anywhere in my lie above - nor anywhere else in
local-prog, for that matter.  I'd have to go read the code, because
your description doesn't seem to match the results I see.

I extracted the '$$)' from your line 121 and minified it to the parts
necessary to understand the parentheses counting parts.

In case you want to build old versions of make, you can have a look at
https://ftp.netbsd.org/pub/pkgsrc/misc/rillig/make-archive/, which I use
for local testing to see in which commit some behavior changed.

Roland



Home | Main Index | Thread Index | Old Index