diff options
Diffstat (limited to 'contrib/bmake/parse.c')
-rw-r--r-- | contrib/bmake/parse.c | 111 |
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 |