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
86a88072ab
commit
26b05818fe
@ -249,7 +249,7 @@ Arch_ParseArchive(char **linePtr, Lst *nodeLst, GNode *ctxt)
|
|||||||
|
|
||||||
*cp++ = '\0';
|
*cp++ = '\0';
|
||||||
if (subLibName) {
|
if (subLibName) {
|
||||||
libName = Buf_Peel(Var_Subst(NULL, libName, ctxt, TRUE));
|
libName = Buf_Peel(Var_Subst(libName, ctxt, TRUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -346,7 +346,7 @@ Arch_ParseArchive(char **linePtr, Lst *nodeLst, GNode *ctxt)
|
|||||||
* The results are just placed at the end of the
|
* The results are just placed at the end of the
|
||||||
* nodeLst we're returning.
|
* nodeLst we're returning.
|
||||||
*/
|
*/
|
||||||
buf1 = Var_Subst(NULL, memName, ctxt, TRUE);
|
buf1 = Var_Subst(memName, ctxt, TRUE);
|
||||||
memName = Buf_Data(buf1);
|
memName = Buf_Data(buf1);
|
||||||
|
|
||||||
sz = strlen(memName) + strlen(libName) + 3;
|
sz = strlen(memName) + strlen(libName) + 3;
|
||||||
|
@ -252,7 +252,7 @@ Compat_RunCommand(char *cmd, GNode *gn)
|
|||||||
doit = FALSE;
|
doit = FALSE;
|
||||||
|
|
||||||
cmdNode = Lst_Member(&gn->commands, cmd);
|
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
|
* 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
|
* Make a list with the remaining words
|
||||||
* XXX should use brk_string here.
|
* 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++)
|
for (ptr = sub; *ptr != '\0' && isspace((u_char)*ptr); ptr++)
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ For_Run(int lineno)
|
|||||||
Var_Set(var, val, VAR_GLOBAL);
|
Var_Set(var, val, VAR_GLOBAL);
|
||||||
|
|
||||||
DEBUGF(FOR, ("--- %s = %s\n", var, val));
|
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));
|
VAR_GLOBAL, FALSE));
|
||||||
|
|
||||||
Parse_FromString(str, lineno);
|
Parse_FromString(str, lineno);
|
||||||
|
@ -609,7 +609,7 @@ JobPrintCommand(char *cmd, Job *job)
|
|||||||
*/
|
*/
|
||||||
cmdNode = Lst_Member(&job->node->commands, cmd);
|
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;
|
cmdStart = cmd;
|
||||||
|
|
||||||
Lst_Replace(cmdNode, cmdStart);
|
Lst_Replace(cmdNode, cmdStart);
|
||||||
@ -972,8 +972,8 @@ JobFinish(Job *job, int *status)
|
|||||||
*/
|
*/
|
||||||
for (ln = job->tailCmds; ln != NULL; ln = LST_NEXT(ln)) {
|
for (ln = job->tailCmds; ln != NULL; ln = LST_NEXT(ln)) {
|
||||||
Lst_AtEnd(&postCommands->commands,
|
Lst_AtEnd(&postCommands->commands,
|
||||||
Buf_Peel(Var_Subst(NULL, Lst_Datum(ln),
|
Buf_Peel(
|
||||||
job->node, FALSE)));
|
Var_Subst(Lst_Datum(ln), job->node, FALSE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
job->node->made = MADE;
|
job->node->made = MADE;
|
||||||
@ -1655,8 +1655,8 @@ JobStart(GNode *gn, int flags, Job *previous)
|
|||||||
for (ln = job->tailCmds; ln != NULL;
|
for (ln = job->tailCmds; ln != NULL;
|
||||||
ln = LST_NEXT(ln)) {
|
ln = LST_NEXT(ln)) {
|
||||||
Lst_AtEnd(&postCommands->commands,
|
Lst_AtEnd(&postCommands->commands,
|
||||||
Buf_Peel(Var_Subst(NULL,
|
Buf_Peel(Var_Subst(Lst_Datum(ln),
|
||||||
Lst_Datum(ln), job->node, FALSE)));
|
job->node, FALSE)));
|
||||||
}
|
}
|
||||||
job->node->made = MADE;
|
job->node->made = MADE;
|
||||||
Make_Update(job->node);
|
Make_Update(job->node);
|
||||||
|
@ -901,7 +901,7 @@ main(int argc, char **argv)
|
|||||||
char *ptr;
|
char *ptr;
|
||||||
char savec;
|
char savec;
|
||||||
|
|
||||||
buf = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
|
buf = Var_Subst(VPATH, VAR_CMD, FALSE);
|
||||||
|
|
||||||
vpath = Buf_Data(buf);
|
vpath = Buf_Data(buf);
|
||||||
do {
|
do {
|
||||||
@ -992,7 +992,7 @@ main(int argc, char **argv)
|
|||||||
v = emalloc(strlen(name) + 1 + 3);
|
v = emalloc(strlen(name) + 1 + 3);
|
||||||
sprintf(v, "${%s}", name);
|
sprintf(v, "${%s}", name);
|
||||||
|
|
||||||
value = Buf_Peel(Var_Subst(NULL, v,
|
value = Buf_Peel(Var_Subst(v,
|
||||||
VAR_GLOBAL, FALSE));
|
VAR_GLOBAL, FALSE));
|
||||||
printf("%s\n", value);
|
printf("%s\n", value);
|
||||||
|
|
||||||
|
@ -1493,7 +1493,7 @@ Parse_DoVar(char *line, GNode *ctxt)
|
|||||||
if (!Var_Exists(line, ctxt))
|
if (!Var_Exists(line, ctxt))
|
||||||
Var_Set(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;
|
oldVars = oldOldVars;
|
||||||
|
|
||||||
@ -1516,7 +1516,7 @@ Parse_DoVar(char *line, GNode *ctxt)
|
|||||||
* resulting string will need freeing when we're done,
|
* resulting string will need freeing when we're done,
|
||||||
* so set freeCmd to TRUE.
|
* 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;
|
freeCmd = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1655,7 +1655,7 @@ ParseTraditionalInclude(char *file)
|
|||||||
* Substitute for any variables in the file name before trying to
|
* Substitute for any variables in the file name before trying to
|
||||||
* find the thing.
|
* 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.
|
* 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
|
* Substitute for any variables in the file name before trying to
|
||||||
* find the thing.
|
* 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
|
* 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))
|
while (isspace((u_char)*line))
|
||||||
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);
|
Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line);
|
||||||
free(line);
|
free(line);
|
||||||
|
|
||||||
@ -2254,7 +2254,7 @@ parse_undef(char *line, int code __unused, int lineno __unused)
|
|||||||
}
|
}
|
||||||
*cp = '\0';
|
*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);
|
Var_Delete(cp, VAR_GLOBAL);
|
||||||
free(cp);
|
free(cp);
|
||||||
}
|
}
|
||||||
@ -2468,7 +2468,7 @@ Parse_File(const char *name, FILE *stream)
|
|||||||
|
|
||||||
ParseFinishLine();
|
ParseFinishLine();
|
||||||
|
|
||||||
cp = Buf_Peel(Var_Subst(NULL, line, VAR_CMD, TRUE));
|
cp = Buf_Peel(Var_Subst(line, VAR_CMD, TRUE));
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
line = cp;
|
line = cp;
|
||||||
|
@ -1155,7 +1155,7 @@ SuffExpandVariables(GNode *parent, GNode *child, Lst *members)
|
|||||||
Lst_Init(members);
|
Lst_Init(members);
|
||||||
|
|
||||||
DEBUGF(SUFF, ("Expanding \"%s\"...", child->name));
|
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);
|
cp = Buf_Data(buf);
|
||||||
|
|
||||||
if (child->type & OP_ARCHV) {
|
if (child->type & OP_ARCHV) {
|
||||||
|
@ -222,7 +222,7 @@ VarPossiblyExpand(const char *name, GNode *ctxt)
|
|||||||
Buffer *buf;
|
Buffer *buf;
|
||||||
|
|
||||||
if (strchr(name, '$') != NULL) {
|
if (strchr(name, '$') != NULL) {
|
||||||
buf = Var_Subst(NULL, name, ctxt, 0);
|
buf = Var_Subst(name, ctxt, 0);
|
||||||
return (Buf_Peel(buf));
|
return (Buf_Peel(buf));
|
||||||
} else {
|
} else {
|
||||||
return estrdup(name);
|
return estrdup(name);
|
||||||
@ -882,7 +882,7 @@ VarExpand(Var *v, VarParser *vp)
|
|||||||
} else {
|
} else {
|
||||||
Buffer *buf;
|
Buffer *buf;
|
||||||
|
|
||||||
buf = Var_Subst(NULL, value, vp->ctxt, vp->err);
|
buf = Var_Subst(value, vp->ctxt, vp->err);
|
||||||
result = Buf_Peel(buf);
|
result = Buf_Peel(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1715,9 +1715,9 @@ Var_Parse(const char input[], GNode *ctxt, Boolean err,
|
|||||||
*-----------------------------------------------------------------------
|
*-----------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
Buffer *
|
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 */
|
Buffer *buf; /* Buffer for forming things */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1728,89 +1728,21 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean err)
|
|||||||
errorReported = FALSE;
|
errorReported = FALSE;
|
||||||
|
|
||||||
buf = Buf_Init(0);
|
buf = Buf_Init(0);
|
||||||
while (*str) {
|
while (str[0] != '\0') {
|
||||||
if (var == NULL && (str[0] == '$') && (str[1] == '$')) {
|
if ((str[0] == '$') && (str[1] == '$')) {
|
||||||
/*
|
/*
|
||||||
* A dollar sign may be escaped either with another
|
* A dollar sign may be escaped with another dollar
|
||||||
* dollar sign. In such a case, we skip over the
|
* sign. In such a case, we skip over the escape
|
||||||
* escape character and store the dollar sign into
|
* character and store the dollar sign into the
|
||||||
* the buffer directly.
|
* buffer directly.
|
||||||
*/
|
*/
|
||||||
|
str++;
|
||||||
Buf_AddByte(buf, (Byte)str[0]);
|
Buf_AddByte(buf, (Byte)str[0]);
|
||||||
str += 2;
|
str++;
|
||||||
|
|
||||||
} else if (str[0] == '$') {
|
} else if (str[0] == '$') {
|
||||||
/*
|
/* Variable invocation. */
|
||||||
* Variable invocation.
|
VarParser subvp = {
|
||||||
*/
|
|
||||||
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 = {
|
|
||||||
str,
|
str,
|
||||||
str,
|
str,
|
||||||
ctxt,
|
ctxt,
|
||||||
@ -1849,20 +1781,13 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean err)
|
|||||||
Parse_Error(PARSE_FATAL,
|
Parse_Error(PARSE_FATAL,
|
||||||
"Undefined variable \"%.*s\"", subvp.ptr - subvp.input, str);
|
"Undefined variable \"%.*s\"", subvp.ptr - subvp.input, str);
|
||||||
}
|
}
|
||||||
str = subvp.ptr;
|
|
||||||
errorReported = TRUE;
|
errorReported = TRUE;
|
||||||
|
str = subvp.ptr;
|
||||||
} else {
|
} else {
|
||||||
Buf_AddByte(buf, (Byte)*str);
|
Buf_AddByte(buf, (Byte)str[0]);
|
||||||
str += 1;
|
str++;
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
* Copy all the characters from the variable
|
||||||
* value straight into the new string.
|
* value straight into the new string.
|
||||||
@ -1871,68 +1796,155 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean err)
|
|||||||
if (rfree) {
|
if (rfree) {
|
||||||
free(rval);
|
free(rval);
|
||||||
}
|
}
|
||||||
|
str = subvp.ptr;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
Buf_AddByte(buf, (Byte)str[0]);
|
||||||
* Skip as many characters as possible -- either to
|
str++;
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-
|
static int
|
||||||
*-----------------------------------------------------------------------
|
match_var(const char str[], const char var[])
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-
|
Buffer *
|
||||||
*-----------------------------------------------------------------------
|
Var_SubstOnly(const char *var, const char *str, GNode *ctxt, Boolean err)
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
|
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_Delete(const char *, struct GNode *);
|
||||||
void Var_Dump(const struct GNode *);
|
void Var_Dump(const struct GNode *);
|
||||||
Boolean Var_Exists(const char *, struct GNode *);
|
Boolean Var_Exists(const char *, struct GNode *);
|
||||||
char *Var_GetHead(char *);
|
|
||||||
char *Var_GetTail(char *);
|
|
||||||
void Var_Init(char **);
|
void Var_Init(char **);
|
||||||
char *Var_Parse(const char *, struct GNode *, Boolean, size_t *, Boolean *);
|
char *Var_Parse(const char *, struct GNode *, Boolean, size_t *, Boolean *);
|
||||||
char *Var_Quote(const char *);
|
char *Var_Quote(const char *);
|
||||||
void Var_Set(const char *, const char *, struct GNode *);
|
void Var_Set(const char *, const char *, struct GNode *);
|
||||||
void Var_SetEnv(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 **);
|
char *Var_Value(const char *, struct GNode *, char **);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user