Date: Wed, 21 Jan 2004 12:58:06 +0100 From: Oliver Eikemeier <eikemeier@fillmore-labs.com> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/61673: make(1) word splitting swallows quotes Message-ID: <400E694E.3000405@fillmore-labs.com> Resent-Message-ID: <200401211200.i0LC0Vcr080156@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?400E694E.3000405>