bin/61673: make(1) word splitting swallows quotes
Oliver Eikemeier
eikemeier at fillmore-labs.com
Wed Jan 21 04:00:42 PST 2004
>Number: 61673
>Category: bin
>Synopsis: make(1) word splitting swallows quotes
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Jan 21 04:00:31 PST 2004
>Closed-Date:
>Last-Modified:
>Originator: Oliver Eikemeier
>Release: FreeBSD 4.9-STABLE i386
>Organization:
Fillmore Labs - http://www.fillmore-labs.com
>Environment:
System: FreeBSD nuuk.fillmore-labs.com 4.9-STABLE
>Description:
Make reduces two (empty) quotes to one if they are not the first word
in a string. This work with :S, :C, :M and others and is true for double
and single quotes.
>How-To-Repeat:
* Makefile:
QUOTETEST1= ""
QUOTETEST2= "" ab
QUOTETEST3= ab ""
QUOTETEST4= ab "" cd
QUOTETEST5= ab "" "cd - ef" "" jk
all:
@echo 'QUOTETEST1: ${QUOTETEST1:M*}'
@echo 'QUOTETEST2: ${QUOTETEST2:M*}'
@echo 'QUOTETEST3: ${QUOTETEST3:M*}'
@echo 'QUOTETEST4: ${QUOTETEST4:M*}'
@echo 'QUOTETEST5a: ${QUOTETEST5:S/^/</:S/$/>/}'
@echo 'QUOTETEST5b: ${QUOTETEST5:S/$/>/:S/^/</}'
* Result:
QUOTETEST1: ""
QUOTETEST2: "" ab
QUOTETEST3: ab "
QUOTETEST4: ab " cd
QUOTETEST5a: <ab> <" <"cd> -> ef" <"> <jk>
QUOTETEST5b: <ab> <"> "cd <- <ef"> "> <jk>
* Expected result:
QUOTETEST1: ""
QUOTETEST2: "" ab
QUOTETEST3: ab ""
QUOTETEST4: ab "" cd
QUOTETEST5a: <ab> <""> <"cd - ef"> <""> <jk>
QUOTETEST5b: <ab> <""> <"cd - ef"> <""> <jk>
>Fix:
It looks like brk_string in src/usr.bin/make/str.c is responsible for that:
inquote = '\0';
for (p = str, start = t = buffer;; ++p) {
switch(ch = *p) {
case '"':
case '\'':
if (inquote) {
if (inquote == ch)
inquote = '\0';
else
break;
} else {
inquote = (char) ch;
/* Don't miss "" or '' */
if (start == NULL && p[1] == inquote) {
start = t + 1;
break;
}
}
if (!expand) {
if (!start)
start = t;
*t++ = ch;
}
continue;
[...]
}
if (!start)
start = t;
*t++ = (char) ch;
}
Essentially the part after /* Don't miss "" or '' */.
Maybe something like this will do the trick:
inquote = '\0';
start = (char *)NULL;
for (p = str, t = buffer;; ++p) {
switch(ch = *p) {
case '"':
case '\'':
if (inquote) {
if (inquote == ch)
inquote = '\0';
else
break;
} else {
inquote = (char) ch;
}
if (!expand) {
if (!start)
start = t;
*t++ = ch;
}
continue;
[...]
}
if (!start)
start = t;
*t++ = (char) ch;
}
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list