diff options
Diffstat (limited to 'parse.c')
-rw-r--r-- | parse.c | 87 |
1 files changed, 79 insertions, 8 deletions
@@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.194 2014/02/15 00:17:17 christos Exp $ */ +/* $NetBSD: parse.c,v 1.204 2014/09/18 08:06:13 dholland 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.204 2014/09/18 08:06:13 dholland 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.204 2014/09/18 08:06:13 dholland Exp $"); #endif #endif /* not lint */ #endif @@ -1203,7 +1203,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)); @@ -1226,6 +1236,10 @@ ParseDoDependency(char *line) } } + /* + * 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 +1256,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 +1280,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 +1425,8 @@ ParseDoDependency(char *line) (void)Lst_AtEnd(curTargs, line); } + /* Apply the targets. */ + while(!Lst_IsEmpty(curTargs)) { char *targName = (char *)Lst_DeQueue(curTargs); @@ -1422,7 +1444,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 +1522,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++; @@ -1962,6 +1995,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 +2041,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 +2057,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 |