Fix quoting of the MAKEFLAGS environment variable by only quoting spaces
and tabs. This is still not correct for command line variable values ending in a backslash because this would require a larger effort. Document this limitation in the BUGS section of the man page. The quoting is mostly compatible with that of gmake and smake. Tested by: Max Okumoto and Joerg Sonnenberger from DragonFly BSD Reviewed by: ru (man page, partly)
This commit is contained in:
parent
fb3be370b0
commit
b071ad2dca
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=140870
@ -144,14 +144,21 @@ static char *objdir; /* where we chdir'ed to */
|
||||
static void
|
||||
MFLAGS_append(char *flag, char *arg)
|
||||
{
|
||||
char *str;
|
||||
|
||||
Var_Append(MAKEFLAGS, flag, VAR_GLOBAL);
|
||||
if (arg != NULL)
|
||||
Var_Append(MAKEFLAGS, arg, VAR_GLOBAL);
|
||||
if (arg != NULL) {
|
||||
str = MAKEFLAGS_quote(arg);
|
||||
Var_Append(MAKEFLAGS, str, VAR_GLOBAL);
|
||||
free(str);
|
||||
}
|
||||
|
||||
Var_Append("MFLAGS", flag, VAR_GLOBAL);
|
||||
if (arg != NULL)
|
||||
Var_Append("MFLAGS", arg, VAR_GLOBAL);
|
||||
if (arg != NULL) {
|
||||
str = MAKEFLAGS_quote(arg);
|
||||
Var_Append("MFLAGS", str, VAR_GLOBAL);
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
@ -340,7 +347,7 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) {
|
||||
*/
|
||||
for (argv += optind, argc -= optind; *argv; ++argv, --argc)
|
||||
if (Parse_IsVar(*argv)) {
|
||||
char *ptr = Var_Quote(*argv);
|
||||
char *ptr = MAKEFLAGS_quote(*argv);
|
||||
|
||||
Var_Append(MAKEFLAGS, ptr, VAR_GLOBAL);
|
||||
free(ptr);
|
||||
@ -376,7 +383,7 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) {
|
||||
* Only those that come from the various arguments.
|
||||
*/
|
||||
void
|
||||
Main_ParseArgLine(char *line)
|
||||
Main_ParseArgLine(char *line, int mflags)
|
||||
{
|
||||
char **argv; /* Manufactured argument vector */
|
||||
int argc; /* Number of arguments in argv */
|
||||
@ -388,7 +395,11 @@ Main_ParseArgLine(char *line)
|
||||
if (!*line)
|
||||
return;
|
||||
|
||||
argv = brk_string(line, &argc, TRUE);
|
||||
if (mflags)
|
||||
argv = MAKEFLAGS_break(line, &argc);
|
||||
else
|
||||
argv = brk_string(line, &argc, TRUE);
|
||||
|
||||
MainParseArgs(argc, argv);
|
||||
}
|
||||
|
||||
@ -622,7 +633,7 @@ main(int argc, char **argv)
|
||||
* (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
|
||||
* in a different format).
|
||||
*/
|
||||
Main_ParseArgLine(getenv("MAKEFLAGS"));
|
||||
Main_ParseArgLine(getenv("MAKEFLAGS"), 1);
|
||||
|
||||
MainParseArgs(argc, argv);
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
.\" @(#)make.1 8.8 (Berkeley) 6/13/95
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 2, 2004
|
||||
.Dd January 26, 2005
|
||||
.Dt MAKE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -590,6 +590,20 @@ environment variable made available for all programs which
|
||||
executes; compare with the
|
||||
.Ic .MAKEFLAGS
|
||||
special target below.
|
||||
.Pp
|
||||
When passing macro definitions and flag arguments in the
|
||||
.Ev MAKEFLAGS
|
||||
environment variable,
|
||||
space and tab characters are quoted by preceding them with a backslash.
|
||||
When reading the
|
||||
.Ev MAKEFLAGS
|
||||
variable from the environment,
|
||||
all sequences of a backslash and one of space or tab
|
||||
are replaced just with their second character
|
||||
without causing a word break.
|
||||
Any other occurences of a backslash are retained.
|
||||
Groups of unquoted space, tab and newline characters cause word
|
||||
breaking.
|
||||
.It Va MFLAGS
|
||||
This variable is provided for backward compatibility and
|
||||
contains all the options from the
|
||||
@ -1467,3 +1481,12 @@ all:
|
||||
...
|
||||
\&.endfor
|
||||
.Ed
|
||||
.Pp
|
||||
A trailing backslash in a variable value defined on the command line causes
|
||||
the delimiting space in the
|
||||
.Ev MAKEFLAGS
|
||||
environment variable to be preceeded by that backslash.
|
||||
That causes a submake to not treat that space as a word delimiter.
|
||||
Fixing this requires a larger rewrite of the code handling command line
|
||||
macros and assignments to
|
||||
.Va .MAKEFLAGS .
|
||||
|
@ -62,7 +62,7 @@ int For_Eval(char *);
|
||||
void For_Run(int);
|
||||
|
||||
/* main.c */
|
||||
void Main_ParseArgLine(char *);
|
||||
void Main_ParseArgLine(char *, int);
|
||||
char *Cmd_Exec(char *, char **);
|
||||
void Debug(const char *, ...);
|
||||
void Error(const char *, ...);
|
||||
@ -92,6 +92,8 @@ void Parse_MainName(Lst *);
|
||||
void str_init(void);
|
||||
char *str_concat(const char *, const char *, int);
|
||||
char **brk_string(char *, int *, Boolean);
|
||||
char *MAKEFLAGS_quote(const char *);
|
||||
char **MAKEFLAGS_break(const char *, int *);
|
||||
int Str_Match(const char *, const char *);
|
||||
const char *Str_SYSVMatch(const char *, const char *, int *);
|
||||
void Str_SYSVSubst(Buffer, const char *, const char *, int);
|
||||
|
@ -1033,7 +1033,7 @@ ParseDoDependency (char *line)
|
||||
* set the initial character to a null-character so the loop to
|
||||
* get sources won't get anything
|
||||
*/
|
||||
Main_ParseArgLine(line);
|
||||
Main_ParseArgLine(line, 0);
|
||||
*line = '\0';
|
||||
} else if (specType == ExShell) {
|
||||
if (Job_ParseShell(line) != SUCCESS) {
|
||||
|
@ -222,6 +222,105 @@ done: argv[argc] = NULL;
|
||||
return (argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Quote a string for appending it to MAKEFLAGS. According to Posix the
|
||||
* kind of quoting here is implementation-defined. This quoting must ensure
|
||||
* that the parsing of MAKEFLAGS's contents in a sub-shell yields the same
|
||||
* options, option arguments and macro definitions as in the calling make.
|
||||
* We simply quote all blanks, which according to Posix are space and tab
|
||||
* in the POSIX locale. Don't use isblank because in that case makes with
|
||||
* different locale settings could not communicate. We must also quote
|
||||
* backslashes obviously.
|
||||
*/
|
||||
char *
|
||||
MAKEFLAGS_quote(const char *str)
|
||||
{
|
||||
char *ret, *q;
|
||||
const char *p;
|
||||
|
||||
/* assume worst case - everything has to be quoted */
|
||||
ret = emalloc(strlen(str) * 2 + 1);
|
||||
|
||||
p = str;
|
||||
q = ret;
|
||||
while (*p != '\0') {
|
||||
switch (*p) {
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
*q++ = '\\';
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*q++ = *p++;
|
||||
}
|
||||
*q++ = '\0';
|
||||
return (ret);
|
||||
}
|
||||
|
||||
char **
|
||||
MAKEFLAGS_break(const char *str, int *pargc)
|
||||
{
|
||||
char *q, *start;
|
||||
int len;
|
||||
|
||||
/* allocate room for a copy of the string */
|
||||
if ((len = strlen(str) + 1) > curlen)
|
||||
buffer = erealloc(buffer, curlen = len);
|
||||
|
||||
start = NULL;
|
||||
*pargc = 1;
|
||||
|
||||
for (q = buffer;;) {
|
||||
switch (*str) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
/* word separator */
|
||||
if (start == NULL) {
|
||||
/* not in a word */
|
||||
str++;
|
||||
continue;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case '\0':
|
||||
if (start == NULL)
|
||||
goto done;
|
||||
|
||||
/* finish word */
|
||||
*q++ = '\0';
|
||||
if (argmax == *pargc) {
|
||||
argmax *= 2;
|
||||
argv = erealloc(argv,
|
||||
sizeof(*argv) * (argmax + 1));
|
||||
}
|
||||
argv[(*pargc)++] = start;
|
||||
start = NULL;
|
||||
|
||||
if (*str++ == '\0')
|
||||
goto done;
|
||||
continue;
|
||||
|
||||
case '\\':
|
||||
if (str[1] == ' ' || str[1] == '\t')
|
||||
/* was a quote */
|
||||
str++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (start == NULL)
|
||||
/* start of new word */
|
||||
start = q;
|
||||
*q++ = *str++;
|
||||
}
|
||||
done:
|
||||
argv[(*pargc)] = NULL;
|
||||
return (argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Str_Match --
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user