pkgsrc-Users archive

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

Re: Surprising make behavior

On 12.09.2020 17:44, Martin Husemann wrote:
> On Sat, Sep 12, 2020 at 04:35:48PM +0200, Roland Illig wrote:
>> If you want to know a (good) reason why NetBSD make behaves like this: I
>> have no idea.
> It clearly is a bug. Either in the man page:
>    Additional built-in variables
>      In addition, make sets or knows about the following variables:
>      $               A single dollar sign `$', i.e.  `$$' expands to a single
>                      dollar sign.

That same manual page also says:

> Variable expansion occurs in the normal fashion inside both
> old_string and new_string with the single exception that a
> backslash is used to prevent the expansion of a dollar sign
> (‘$’), not a preceding dollar sign as is usual.

Unfortunately, this paragraph in the manual page only applies to the :S
and :C variable modifiers, and it does not contain the keyword "escape".

The code in usr.bin/make/var.c is different though, since the function
ParseModifierPart that implements this escaping is also used by several
other variable modifiers, which are :@var@...@, :!cmd!, :?then:else,
:from=to, :[...].

In the :D and :U modifiers, only \$ works, but not $$, but that is
implemented independently in ApplyModifier_Defined.

To make things even more interesting, in the :M and :N variable
modifiers, the correct escaping is $$, and \$ does not work at all; see
ApplyModifier_Match for the code.

To detect these edge cases, you can use the attached patch, which
already forced me to fix pkgsrc/mk/misc/ since it had used $$ in
an undocumented way.

Even though the code in the patch says PARSE_FATAL, this does not mean
that make really quits when it encounters such an error.  It only quits
when it is still in the parsing phase.  Errors in any later phase are
still printed but otherwise ignored.  But Parse_Error is the only error
reporting function that prints the error location, that's why I am using it.

In summary, it's a big chaos.
Index: usr.bin/make/var.c
RCS file: /cvsroot/src/usr.bin/make/var.c,v
retrieving revision 1.504
diff -u -r1.504 var.c
--- usr.bin/make/var.c	12 Sep 2020 20:03:37 -0000	1.504
+++ usr.bin/make/var.c	12 Sep 2020 21:50:59 -0000
@@ -3456,6 +3456,16 @@
 	/* Error out some really stupid names */
 	if (startc == '\0' || strchr(")}:$", startc)) {
+	    if (startc == '$')
+		Parse_Error(PARSE_FATAL,
+			    "To escape a dollar, use \\$, not $$, at \"%s\"",
+			    start);
+	    else if (startc == '\0')
+		Parse_Error(PARSE_FATAL, "Dollar followed by nothing");
+	    else
+		Parse_Error(PARSE_FATAL,
+			    "Invalid variable name '%c', at \"%s\"",
+			    startc, start);
 	    return var_Error;

Home | Main Index | Thread Index | Old Index