From 26b05818fe664b6f089a5b78892bd7dd84d8cadc Mon Sep 17 00:00:00 2001 From: harti Date: Mon, 9 May 2005 14:06:04 +0000 Subject: [PATCH] Split Var_Subst() into two functions: Var_SubstOnly() which substitutes only one variable and Var_Subst() which substitutes all. Split out the test whether a variable should not be expanded into match_var(). Make access to the input string consistently using str[]. Remove two unused functions: Var_GetTail() and Var_GetHead(). Patches: 7.184-7.189 Submitted by: Max Okumoto --- usr.bin/make/arch.c | 4 +- usr.bin/make/compat.c | 2 +- usr.bin/make/for.c | 4 +- usr.bin/make/job.c | 10 +- usr.bin/make/main.c | 4 +- usr.bin/make/parse.c | 14 +- usr.bin/make/suff.c | 2 +- usr.bin/make/var.c | 292 ++++++++++++++++++++++-------------------- usr.bin/make/var.h | 5 +- 9 files changed, 174 insertions(+), 163 deletions(-) diff --git a/usr.bin/make/arch.c b/usr.bin/make/arch.c index e9e93978d41f..4898a87bab67 100644 --- a/usr.bin/make/arch.c +++ b/usr.bin/make/arch.c @@ -249,7 +249,7 @@ Arch_ParseArchive(char **linePtr, Lst *nodeLst, GNode *ctxt) *cp++ = '\0'; if (subLibName) { - libName = Buf_Peel(Var_Subst(NULL, libName, ctxt, TRUE)); + libName = Buf_Peel(Var_Subst(libName, ctxt, TRUE)); } for (;;) { @@ -346,7 +346,7 @@ Arch_ParseArchive(char **linePtr, Lst *nodeLst, GNode *ctxt) * The results are just placed at the end of the * nodeLst we're returning. */ - buf1 = Var_Subst(NULL, memName, ctxt, TRUE); + buf1 = Var_Subst(memName, ctxt, TRUE); memName = Buf_Data(buf1); sz = strlen(memName) + strlen(libName) + 3; diff --git a/usr.bin/make/compat.c b/usr.bin/make/compat.c index 2ab841622c49..d57b8039ae4c 100644 --- a/usr.bin/make/compat.c +++ b/usr.bin/make/compat.c @@ -252,7 +252,7 @@ Compat_RunCommand(char *cmd, GNode *gn) doit = FALSE; cmdNode = Lst_Member(&gn->commands, cmd); - cmdStart = Buf_Peel(Var_Subst(NULL, cmd, gn, FALSE)); + cmdStart = Buf_Peel(Var_Subst(cmd, gn, FALSE)); /* * brk_string will return an argv with a NULL in av[0], thus causing diff --git a/usr.bin/make/for.c b/usr.bin/make/for.c index 823a7cc69830..f0e0b4eecee3 100644 --- a/usr.bin/make/for.c +++ b/usr.bin/make/for.c @@ -150,7 +150,7 @@ For_For(char *line) * Make a list with the remaining words * XXX should use brk_string here. */ - sub = Buf_Peel(Var_Subst(NULL, ptr, VAR_CMD, FALSE)); + sub = Buf_Peel(Var_Subst(ptr, VAR_CMD, FALSE)); for (ptr = sub; *ptr != '\0' && isspace((u_char)*ptr); ptr++) ; @@ -271,7 +271,7 @@ For_Run(int lineno) Var_Set(var, val, VAR_GLOBAL); DEBUGF(FOR, ("--- %s = %s\n", var, val)); - str = Buf_Peel(Var_Subst(var, Buf_Data(buf), + str = Buf_Peel(Var_SubstOnly(var, Buf_Data(buf), VAR_GLOBAL, FALSE)); Parse_FromString(str, lineno); diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c index 07ac2b477432..ba2af7857285 100644 --- a/usr.bin/make/job.c +++ b/usr.bin/make/job.c @@ -609,7 +609,7 @@ JobPrintCommand(char *cmd, Job *job) */ cmdNode = Lst_Member(&job->node->commands, cmd); - cmd = Buf_Peel(Var_Subst(NULL, cmd, job->node, FALSE)); + cmd = Buf_Peel(Var_Subst(cmd, job->node, FALSE)); cmdStart = cmd; Lst_Replace(cmdNode, cmdStart); @@ -972,8 +972,8 @@ JobFinish(Job *job, int *status) */ for (ln = job->tailCmds; ln != NULL; ln = LST_NEXT(ln)) { Lst_AtEnd(&postCommands->commands, - Buf_Peel(Var_Subst(NULL, Lst_Datum(ln), - job->node, FALSE))); + Buf_Peel( + Var_Subst(Lst_Datum(ln), job->node, FALSE))); } job->node->made = MADE; @@ -1655,8 +1655,8 @@ JobStart(GNode *gn, int flags, Job *previous) for (ln = job->tailCmds; ln != NULL; ln = LST_NEXT(ln)) { Lst_AtEnd(&postCommands->commands, - Buf_Peel(Var_Subst(NULL, - Lst_Datum(ln), job->node, FALSE))); + Buf_Peel(Var_Subst(Lst_Datum(ln), + job->node, FALSE))); } job->node->made = MADE; Make_Update(job->node); diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c index 2b8fd8a992d9..d93628a4cf75 100644 --- a/usr.bin/make/main.c +++ b/usr.bin/make/main.c @@ -901,7 +901,7 @@ main(int argc, char **argv) char *ptr; char savec; - buf = Var_Subst(NULL, VPATH, VAR_CMD, FALSE); + buf = Var_Subst(VPATH, VAR_CMD, FALSE); vpath = Buf_Data(buf); do { @@ -992,7 +992,7 @@ main(int argc, char **argv) v = emalloc(strlen(name) + 1 + 3); sprintf(v, "${%s}", name); - value = Buf_Peel(Var_Subst(NULL, v, + value = Buf_Peel(Var_Subst(v, VAR_GLOBAL, FALSE)); printf("%s\n", value); diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c index fb48a77e73e5..3defe1d2b09a 100644 --- a/usr.bin/make/parse.c +++ b/usr.bin/make/parse.c @@ -1493,7 +1493,7 @@ Parse_DoVar(char *line, GNode *ctxt) if (!Var_Exists(line, ctxt)) Var_Set(line, "", ctxt); - cp = Buf_Peel(Var_Subst(NULL, cp, ctxt, FALSE)); + cp = Buf_Peel(Var_Subst(cp, ctxt, FALSE)); oldVars = oldOldVars; @@ -1516,7 +1516,7 @@ Parse_DoVar(char *line, GNode *ctxt) * resulting string will need freeing when we're done, * so set freeCmd to TRUE. */ - cp = Buf_Peel(Var_Subst(NULL, cp, VAR_CMD, TRUE)); + cp = Buf_Peel(Var_Subst(cp, VAR_CMD, TRUE)); freeCmd = TRUE; } @@ -1655,7 +1655,7 @@ ParseTraditionalInclude(char *file) * Substitute for any variables in the file name before trying to * find the thing. */ - file = Buf_Peel(Var_Subst(NULL, file, VAR_CMD, FALSE)); + file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); /* * Now we know the file's name, we attempt to find the durn thing. @@ -2127,7 +2127,7 @@ parse_include(char *file, int code __unused, int lineno __unused) * Substitute for any variables in the file name before trying to * find the thing. */ - file = Buf_Peel(Var_Subst(NULL, file, VAR_CMD, FALSE)); + file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE)); /* * Now we know the file's name and its search path, we attempt to @@ -2227,7 +2227,7 @@ parse_message(char *line, int iserror, int lineno __unused) while (isspace((u_char)*line)) line++; - line = Buf_Peel(Var_Subst(NULL, line, VAR_GLOBAL, FALSE)); + line = Buf_Peel(Var_Subst(line, VAR_GLOBAL, FALSE)); Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line); free(line); @@ -2254,7 +2254,7 @@ parse_undef(char *line, int code __unused, int lineno __unused) } *cp = '\0'; - cp = Buf_Peel(Var_Subst(NULL, line, VAR_CMD, FALSE)); + cp = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE)); Var_Delete(cp, VAR_GLOBAL); free(cp); } @@ -2468,7 +2468,7 @@ Parse_File(const char *name, FILE *stream) ParseFinishLine(); - cp = Buf_Peel(Var_Subst(NULL, line, VAR_CMD, TRUE)); + cp = Buf_Peel(Var_Subst(line, VAR_CMD, TRUE)); free(line); line = cp; diff --git a/usr.bin/make/suff.c b/usr.bin/make/suff.c index 94277d8aace9..4ef59b696846 100644 --- a/usr.bin/make/suff.c +++ b/usr.bin/make/suff.c @@ -1155,7 +1155,7 @@ SuffExpandVariables(GNode *parent, GNode *child, Lst *members) Lst_Init(members); DEBUGF(SUFF, ("Expanding \"%s\"...", child->name)); - buf = Var_Subst(NULL, child->name, parent, TRUE); + buf = Var_Subst(child->name, parent, TRUE); cp = Buf_Data(buf); if (child->type & OP_ARCHV) { diff --git a/usr.bin/make/var.c b/usr.bin/make/var.c index 6be737ce9920..cb62da790e82 100644 --- a/usr.bin/make/var.c +++ b/usr.bin/make/var.c @@ -222,7 +222,7 @@ VarPossiblyExpand(const char *name, GNode *ctxt) Buffer *buf; if (strchr(name, '$') != NULL) { - buf = Var_Subst(NULL, name, ctxt, 0); + buf = Var_Subst(name, ctxt, 0); return (Buf_Peel(buf)); } else { return estrdup(name); @@ -882,7 +882,7 @@ VarExpand(Var *v, VarParser *vp) } else { Buffer *buf; - buf = Var_Subst(NULL, value, vp->ctxt, vp->err); + buf = Var_Subst(value, vp->ctxt, vp->err); result = Buf_Peel(buf); } @@ -1715,9 +1715,9 @@ Var_Parse(const char input[], GNode *ctxt, Boolean err, *----------------------------------------------------------------------- */ Buffer * -Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean err) +Var_Subst(const char *str, GNode *ctxt, Boolean err) { - Boolean errorReported; + Boolean errorReported; Buffer *buf; /* Buffer for forming things */ /* @@ -1728,89 +1728,21 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean err) errorReported = FALSE; buf = Buf_Init(0); - while (*str) { - if (var == NULL && (str[0] == '$') && (str[1] == '$')) { + while (str[0] != '\0') { + if ((str[0] == '$') && (str[1] == '$')) { /* - * A dollar sign may be escaped either with another - * dollar sign. In such a case, we skip over the - * escape character and store the dollar sign into - * the buffer directly. + * A dollar sign may be escaped with another dollar + * sign. In such a case, we skip over the escape + * character and store the dollar sign into the + * buffer directly. */ + str++; Buf_AddByte(buf, (Byte)str[0]); - str += 2; + str++; } else if (str[0] == '$') { - /* - * Variable invocation. - */ - if (var != NULL) { - int expand; - for (;;) { - if (str[1] == OPEN_PAREN || str[1] == OPEN_BRACE) { - size_t ln; - const char *p = str + 2; - - /* - * Scan up to the end of the - * variable name. - */ - while (*p != '\0' && - *p != ':' && - *p != CLOSE_PAREN && - *p != CLOSE_BRACE && - *p != '$') { - ++p; - } - - /* - * A variable inside the - * variable. We cannot expand - * the external variable yet, - * so we try again with the - * nested one - */ - if (*p == '$') { - Buf_AppendRange(buf, str, p); - str = p; - continue; - } - ln = p - (str + 2); - if (var[ln] == '\0' && strncmp(var, str + 2, ln) == 0) { - expand = TRUE; - } else { - /* - * Not the variable - * we want to expand, - * scan until the - * next variable - */ - while (*p != '$' && *p != '\0') - p++; - - Buf_AppendRange(buf, str, p); - str = p; - expand = FALSE; - } - } else { - /* - * Single letter variable - * name - */ - if (var[1] == '\0' && var[0] == str[1]) { - expand = TRUE; - } else { - Buf_AddBytes(buf, 2, (const Byte *) str); - str += 2; - expand = FALSE; - } - } - break; - } - if (!expand) - continue; - } - { - VarParser subvp = { + /* Variable invocation. */ + VarParser subvp = { str, str, ctxt, @@ -1849,20 +1781,13 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean err) Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"", subvp.ptr - subvp.input, str); } - str = subvp.ptr; errorReported = TRUE; + str = subvp.ptr; } else { - Buf_AddByte(buf, (Byte)*str); - str += 1; + Buf_AddByte(buf, (Byte)str[0]); + str++; } } else { - /* - * We've now got a variable structure to - * store in. But first, advance the string - * pointer. - */ - str = subvp.ptr; - /* * Copy all the characters from the variable * value straight into the new string. @@ -1871,68 +1796,155 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean err) if (rfree) { free(rval); } + str = subvp.ptr; } - } } else { - /* - * Skip as many characters as possible -- either to - * the end of the string or to the next dollar sign - * (variable invocation). - */ - const char *cp = str; - - do { - str++; - } while (str[0] != '$' && str[0] != '\0'); - - Buf_AppendRange(buf, cp, str); + Buf_AddByte(buf, (Byte)str[0]); + str++; } } return (buf); } -/*- - *----------------------------------------------------------------------- - * Var_GetTail -- - * Return the tail from each of a list of words. Used to set the - * System V local variables. - * - * Results: - * The resulting string. - * - * Side Effects: - * None. - * - *----------------------------------------------------------------------- - */ -char * -Var_GetTail(char *file) +static int +match_var(const char str[], const char var[]) { + const char *start = str; + size_t len; - return (VarModify(file, VarTail, (void *)NULL)); + str++; /* consume '$' */ + + if (str[0] == OPEN_PAREN || str[0] == OPEN_BRACE) { + str++; /* consume opening paren or brace */ + + while (str[0] != '\0') { + if (str[0] == '$') { + /* + * A variable inside the variable. We cannot + * expand the external variable yet. + */ + return (str - start); + } else if (str[0] == ':' || + str[0] == CLOSE_PAREN || + str[0] == CLOSE_BRACE) { + len = str - (start + 2); + + if (var[len] == '\0' && strncmp(var, start + 2, len) == 0) { + return (0); /* match */ + } else { + /* + * Not the variable we want to + * expand. + */ + return (str - start); + } + } else { + ++str; + } + } + return (str - start); + } else { + /* Single letter variable name */ + if (var[1] == '\0' && var[0] == str[0]) { + return (0); /* match */ + } else { + str++; /* consume variable name */ + return (str - start); + } + } } -/*- - *----------------------------------------------------------------------- - * Var_GetHead -- - * Find the leading components of a (list of) filename(s). - * XXX: VarHead does not replace foo by ., as (sun) System V make - * does. - * - * Results: - * The leading components. - * - * Side Effects: - * None. - * - *----------------------------------------------------------------------- - */ -char * -Var_GetHead(char *file) +Buffer * +Var_SubstOnly(const char *var, const char *str, GNode *ctxt, Boolean err) { + Boolean errorReported; + Buffer *buf; /* Buffer for forming things */ - return (VarModify(file, VarHead, (void *)NULL)); + /* + * Set TRUE if an error has already been reported to prevent a + * plethora of messages when recursing. XXXHB this comment sounds + * wrong. + */ + errorReported = FALSE; + + buf = Buf_Init(0); + while (str[0] != '\0') { + if (str[0] == '$') { + int skip; + + skip = match_var(str, var); + if (skip > 0) { + Buf_AddBytes(buf, skip, str); + str += skip; + } else { + /* Variable invocation. */ + VarParser subvp = { + str, + str, + ctxt, + err + }; + char *rval; + Boolean rfree; + + rval = VarParse(&subvp, &rfree); + + /* + * When we get down here, rval should either + * point to the value of this variable, or be + * NULL. + */ + if (rval == var_Error || rval == varNoError) { + /* + * If performing old-time variable + * substitution, skip over the + * variable and continue with the + * substitution. Otherwise, store the + * dollar sign and advance str so we + * continue with the string... + */ + if (oldVars) { + str = subvp.ptr; + } else if (err) { + /* + * If variable is undefined, + * complain and skip the + * variable. The complaint + * will stop us from doing + * anything when the file is + * parsed. + */ + if (!errorReported) { + Parse_Error(PARSE_FATAL, + "Undefined variable \"%.*s\"", subvp.ptr - subvp.input, str); + } + errorReported = TRUE; + str = subvp.ptr; + } else { + Buf_AddByte(buf, (Byte)str[0]); + str++; + } + } else { + /* + * Copy all the characters from the + * variable value straight into the + * new string. + */ + Buf_Append(buf, rval); + if (rfree) { + free(rval); + } + str = subvp.ptr; + } + } + } else { + Buf_AddByte(buf, (Byte)str[0]); + str++; + } + } + + return (buf); } /*- diff --git a/usr.bin/make/var.h b/usr.bin/make/var.h index f5fb9c6898f2..a81e74345a3c 100644 --- a/usr.bin/make/var.h +++ b/usr.bin/make/var.h @@ -93,14 +93,13 @@ void Var_Append(const char *, const char *, struct GNode *); void Var_Delete(const char *, struct GNode *); void Var_Dump(const struct GNode *); Boolean Var_Exists(const char *, struct GNode *); -char *Var_GetHead(char *); -char *Var_GetTail(char *); void Var_Init(char **); char *Var_Parse(const char *, struct GNode *, Boolean, size_t *, Boolean *); char *Var_Quote(const char *); void Var_Set(const char *, const char *, struct GNode *); void Var_SetEnv(const char *, struct GNode *); -struct Buffer *Var_Subst(const char *, const char *, struct GNode *, Boolean); +struct Buffer *Var_Subst(const char *, struct GNode *, Boolean); +struct Buffer *Var_SubstOnly(const char *, const char *, struct GNode *, Boolean); char *Var_Value(const char *, struct GNode *, char **); /*