summaryrefslogtreecommitdiffstats
path: root/contrib/bmake/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bmake/parse.c')
-rw-r--r--contrib/bmake/parse.c111
1 files changed, 95 insertions, 16 deletions
diff --git a/contrib/bmake/parse.c b/contrib/bmake/parse.c
index 0f9a8fc..7f3afbd 100644
--- a/contrib/bmake/parse.c
+++ b/contrib/bmake/parse.c
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.194 2014/02/15 00:17:17 christos Exp $ */
+/* $NetBSD: parse.c,v 1.206 2015/11/26 00:23:04 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: parse.c,v 1.194 2014/02/15 00:17:17 christos Exp $";
+static char rcsid[] = "$NetBSD: parse.c,v 1.206 2015/11/26 00:23:04 sjg Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: parse.c,v 1.194 2014/02/15 00:17:17 christos Exp $");
+__RCSID("$NetBSD: parse.c,v 1.206 2015/11/26 00:23:04 sjg Exp $");
#endif
#endif /* not lint */
#endif
@@ -508,7 +508,11 @@ loadfile(const char *path, int fd)
#ifdef HAVE_MMAP
if (load_getsize(fd, &lf->len) == SUCCESS) {
/* found a size, try mmap */
+#ifdef _SC_PAGESIZE
pagesize = sysconf(_SC_PAGESIZE);
+#else
+ pagesize = 0;
+#endif
if (pagesize <= 0) {
pagesize = 0x1000;
}
@@ -812,7 +816,7 @@ ParseMessage(char *line)
while (isspace((u_char)*line))
line++;
- line = Var_Subst(NULL, line, VAR_CMD, 0);
+ line = Var_Subst(NULL, line, VAR_CMD, FALSE, TRUE);
Parse_Error(mtype, "%s", line);
free(line);
@@ -1203,7 +1207,17 @@ ParseDoDependency(char *line)
curTargs = Lst_Init(FALSE);
+ /*
+ * First, grind through the targets.
+ */
+
do {
+ /*
+ * Here LINE points to the beginning of the next word, and
+ * LSTART points to the actual beginning of the line.
+ */
+
+ /* Find the end of the next word. */
for (cp = line; *cp && (ParseIsEscaped(lstart, cp) ||
!(isspace((unsigned char)*cp) ||
*cp == '!' || *cp == ':' || *cp == LPAREN));
@@ -1219,13 +1233,17 @@ ParseDoDependency(char *line)
int length;
void *freeIt;
- (void)Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
+ (void)Var_Parse(cp, VAR_CMD, TRUE, TRUE, &length, &freeIt);
if (freeIt)
free(freeIt);
cp += length-1;
}
}
+ /*
+ * If the word is followed by a left parenthesis, it's the
+ * name of an object file inside an archive (ar file).
+ */
if (!ParseIsEscaped(lstart, cp) && *cp == LPAREN) {
/*
* Archives must be handled specially to make sure the OP_ARCHV
@@ -1242,13 +1260,16 @@ ParseDoDependency(char *line)
"Error in archive specification: \"%s\"", line);
goto out;
} else {
+ /* Done with this word; on to the next. */
continue;
}
}
- savec = *cp;
if (!*cp) {
/*
+ * We got to the end of the line while we were still
+ * looking at targets.
+ *
* Ending a dependency line without an operator is a Bozo
* no-no. As a heuristic, this is also often triggered by
* undetected conflicts from cvs/rcs merges.
@@ -1263,10 +1284,13 @@ ParseDoDependency(char *line)
: "Need an operator");
goto out;
}
+
+ /* Insert a null terminator. */
+ savec = *cp;
*cp = '\0';
/*
- * Have a word in line. See if it's a special target and set
+ * Got the word. See if it's a special target and if so set
* specType to match it.
*/
if (*line == '.' && isupper ((unsigned char)line[1])) {
@@ -1405,6 +1429,8 @@ ParseDoDependency(char *line)
(void)Lst_AtEnd(curTargs, line);
}
+ /* Apply the targets. */
+
while(!Lst_IsEmpty(curTargs)) {
char *targName = (char *)Lst_DeQueue(curTargs);
@@ -1422,7 +1448,9 @@ ParseDoDependency(char *line)
Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
}
+ /* Don't need the inserted null terminator any more. */
*cp = savec;
+
/*
* If it is a special type and not .PATH, it's the only target we
* allow on this line...
@@ -1498,12 +1526,21 @@ ParseDoDependency(char *line)
goto out;
}
- cp++; /* Advance beyond operator */
+ /* Advance beyond the operator */
+ cp++;
+ /*
+ * Apply the operator to the target. This is how we remember which
+ * operator a target was defined with. It fails if the operator
+ * used isn't consistent across all references.
+ */
Lst_ForEach(targets, ParseDoOp, &op);
/*
- * Get to the first source
+ * Onward to the sources.
+ *
+ * LINE will now point to the first source word, if any, or the
+ * end of the string if not.
*/
while (*cp && isspace ((unsigned char)*cp)) {
cp++;
@@ -1911,7 +1948,7 @@ Parse_DoVar(char *line, GNode *ctxt)
if (!Var_Exists(line, ctxt))
Var_Set(line, "", ctxt, 0);
- cp = Var_Subst(NULL, cp, ctxt, FALSE);
+ cp = Var_Subst(NULL, cp, ctxt, FALSE, TRUE);
oldVars = oldOldVars;
freeCp = TRUE;
@@ -1926,7 +1963,7 @@ Parse_DoVar(char *line, GNode *ctxt)
* expansion on the whole thing. The resulting string will need
* freeing when we're done, so set freeCmd to TRUE.
*/
- cp = Var_Subst(NULL, cp, VAR_CMD, TRUE);
+ cp = Var_Subst(NULL, cp, VAR_CMD, TRUE, TRUE);
freeCp = TRUE;
}
@@ -1962,6 +1999,40 @@ Parse_DoVar(char *line, GNode *ctxt)
}
+/*
+ * ParseMaybeSubMake --
+ * Scan the command string to see if it a possible submake node
+ * Input:
+ * cmd the command to scan
+ * Results:
+ * TRUE if the command is possibly a submake, FALSE if not.
+ */
+static Boolean
+ParseMaybeSubMake(const char *cmd)
+{
+ size_t i;
+ static struct {
+ const char *name;
+ size_t len;
+ } vals[] = {
+#define MKV(A) { A, sizeof(A) - 1 }
+ MKV("${MAKE}"),
+ MKV("${.MAKE}"),
+ MKV("$(MAKE)"),
+ MKV("$(.MAKE)"),
+ MKV("make"),
+ };
+ for (i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) {
+ char *ptr;
+ if ((ptr = strstr(cmd, vals[i].name)) == NULL)
+ continue;
+ if ((ptr == cmd || !isalnum((unsigned char)ptr[-1]))
+ && !isalnum((unsigned char)ptr[vals[i].len]))
+ return TRUE;
+ }
+ return FALSE;
+}
+
/*-
* ParseAddCmd --
* Lst_ForEach function to add a command line to all targets
@@ -1974,7 +2045,9 @@ Parse_DoVar(char *line, GNode *ctxt)
* Always 0
*
* Side Effects:
- * A new element is added to the commands list of the node.
+ * A new element is added to the commands list of the node,
+ * and the node can be marked as a submake node if the command is
+ * determined to be that.
*/
static int
ParseAddCmd(void *gnp, void *cmd)
@@ -1988,6 +2061,8 @@ ParseAddCmd(void *gnp, void *cmd)
/* if target already supplied, ignore commands */
if (!(gn->type & OP_HAS_COMMANDS)) {
(void)Lst_AtEnd(gn->commands, cmd);
+ if (ParseMaybeSubMake(cmd))
+ gn->type |= OP_SUBMAKE;
ParseMark(gn);
} else {
#ifdef notyet
@@ -2227,7 +2302,7 @@ ParseDoInclude(char *line)
* Substitute for any variables in the file name before trying to
* find the thing.
*/
- file = Var_Subst(NULL, file, VAR_CMD, FALSE);
+ file = Var_Subst(NULL, file, VAR_CMD, FALSE, TRUE);
Parse_include_file(file, endc == '>', silent);
free(file);
@@ -2319,15 +2394,19 @@ static void
ParseTrackInput(const char *name)
{
char *old;
+ char *ep;
char *fp = NULL;
size_t name_len = strlen(name);
old = Var_Value(MAKE_MAKEFILES, VAR_GLOBAL, &fp);
if (old) {
+ ep = old + strlen(old) - name_len;
/* does it contain name? */
for (; old != NULL; old = strchr(old, ' ')) {
if (*old == ' ')
old++;
+ if (old >= ep)
+ break; /* cannot contain name */
if (memcmp(old, name, name_len) == 0
&& (old[name_len] == 0 || old[name_len] == ' '))
goto cleanup;
@@ -2453,7 +2532,7 @@ ParseTraditionalInclude(char *line)
* Substitute for any variables in the file name before trying to
* find the thing.
*/
- all_files = Var_Subst(NULL, file, VAR_CMD, FALSE);
+ all_files = Var_Subst(NULL, file, VAR_CMD, FALSE, TRUE);
if (*file == '\0') {
Parse_Error(PARSE_FATAL,
@@ -2521,7 +2600,7 @@ ParseGmakeExport(char *line)
/*
* Expand the value before putting it in the environment.
*/
- value = Var_Subst(NULL, value, VAR_CMD, FALSE);
+ value = Var_Subst(NULL, value, VAR_CMD, FALSE, TRUE);
setenv(variable, value, 1);
}
#endif
@@ -3070,7 +3149,7 @@ Parse_File(const char *name, int fd)
* variables expanded before being parsed. Tell the variable
* module to complain if some variable is undefined...
*/
- line = Var_Subst(NULL, line, VAR_CMD, TRUE);
+ line = Var_Subst(NULL, line, VAR_CMD, TRUE, TRUE);
/*
* Need a non-circular list for the target nodes
OpenPOWER on IntegriCloud