summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorharti <harti@FreeBSD.org>2005-01-26 18:19:39 +0000
committerharti <harti@FreeBSD.org>2005-01-26 18:19:39 +0000
commit17159f0f8beae09feea301a55dff93895b79399b (patch)
treec321afb0d87aa82ef737eee5faca7f2adc43af9e /usr.bin
parent2898737c63ae261843285bb83cce473fc8bf7948 (diff)
downloadFreeBSD-src-17159f0f8beae09feea301a55dff93895b79399b.zip
FreeBSD-src-17159f0f8beae09feea301a55dff93895b79399b.tar.gz
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)
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/make/main.c27
-rw-r--r--usr.bin/make/make.125
-rw-r--r--usr.bin/make/nonints.h4
-rw-r--r--usr.bin/make/parse.c2
-rw-r--r--usr.bin/make/str.c99
5 files changed, 146 insertions, 11 deletions
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c
index 2c3ba65..e29df4a 100644
--- a/usr.bin/make/main.c
+++ b/usr.bin/make/main.c
@@ -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);
diff --git a/usr.bin/make/make.1 b/usr.bin/make/make.1
index a846121..b931a97 100644
--- a/usr.bin/make/make.1
+++ b/usr.bin/make/make.1
@@ -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 .
diff --git a/usr.bin/make/nonints.h b/usr.bin/make/nonints.h
index cc64313..561b24c 100644
--- a/usr.bin/make/nonints.h
+++ b/usr.bin/make/nonints.h
@@ -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);
diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c
index b9c8c05..eb1a5d0 100644
--- a/usr.bin/make/parse.c
+++ b/usr.bin/make/parse.c
@@ -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) {
diff --git a/usr.bin/make/str.c b/usr.bin/make/str.c
index 2979906..9903980 100644
--- a/usr.bin/make/str.c
+++ b/usr.bin/make/str.c
@@ -223,6 +223,105 @@ done: argv[argc] = NULL;
}
/*
+ * 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 --
*
* See if a particular string matches a particular pattern.
OpenPOWER on IntegriCloud