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 <okumoto@ucsd.edu>
This commit is contained in:
parent
18d92cd86c
commit
02c3270da1
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*-
|
||||
|
@ -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 **);
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user