Convert Var_Parse to a wrapper function.
Reduce the number of arguments passed between these functions by creating a special-purpose struct. Patch: 7.120,7.121 Submitted by: Max Okumoto <okumoto@ucsd.edu>
This commit is contained in:
parent
5b2a5b84de
commit
f00fcf68ef
@ -100,6 +100,16 @@ __FBSDID("$FreeBSD$");
|
||||
#include "util.h"
|
||||
#include "var.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
typedef struct VarParser {
|
||||
const char *const input; /* pointer to input string */
|
||||
GNode *ctxt;
|
||||
Boolean err;
|
||||
} VarParser;
|
||||
static char *VarParse(const char [], VarParser *, size_t *, Boolean *);
|
||||
|
||||
/*
|
||||
* This is a harmless return value for Var_Parse that can be used by Var_Subst
|
||||
* to determine if there was an error in parsing -- easier than returning
|
||||
@ -689,7 +699,7 @@ SortIncreasing(const void *l, const void *r)
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static char *
|
||||
VarGetPattern(GNode *ctxt, int err, const char **tstr, int delim, int *flags,
|
||||
VarGetPattern(VarParser *vp, const char **tstr, int delim, int *flags,
|
||||
size_t *length, VarPattern *pattern)
|
||||
{
|
||||
const char *cp;
|
||||
@ -735,7 +745,7 @@ VarGetPattern(GNode *ctxt, int err, const char **tstr, int delim, int *flags,
|
||||
* substitution and recurse.
|
||||
*/
|
||||
len = 0;
|
||||
cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
|
||||
cp2 = Var_Parse(cp, vp->ctxt, vp->err, &len, &freeIt);
|
||||
Buf_Append(buf, cp2);
|
||||
if (freeIt)
|
||||
free(cp2);
|
||||
@ -849,11 +859,11 @@ VarREError(int err, regex_t *pat, const char *str)
|
||||
free(errbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Make sure this variable is fully expanded.
|
||||
*/
|
||||
static char *
|
||||
VarExpand(Var *v, GNode *ctxt, Boolean err)
|
||||
VarExpand(Var *v, VarParser *vp)
|
||||
{
|
||||
char *value;
|
||||
char *result;
|
||||
@ -881,7 +891,7 @@ VarExpand(Var *v, GNode *ctxt, Boolean err)
|
||||
} else {
|
||||
Buffer *buf;
|
||||
|
||||
buf = Var_Subst(NULL, value, ctxt, err);
|
||||
buf = Var_Subst(NULL, value, vp->ctxt, vp->err);
|
||||
result = Buf_GetAll(buf, NULL);
|
||||
Buf_Destroy(buf, FALSE);
|
||||
}
|
||||
@ -939,7 +949,7 @@ modifier_M(const char mod[], const char value[], char endc, size_t *consumed)
|
||||
}
|
||||
|
||||
static char *
|
||||
modifier_S(const char mod[], const char value[], Var *v, GNode *ctxt, Boolean err, size_t *consumed)
|
||||
modifier_S(const char mod[], const char value[], Var *v, VarParser *vp, size_t *consumed)
|
||||
{
|
||||
VarPattern pattern;
|
||||
Buffer *buf; /* Buffer for patterns */
|
||||
@ -1004,7 +1014,7 @@ modifier_S(const char mod[], const char value[], Var *v, GNode *ctxt, Boolean er
|
||||
Boolean freeIt;
|
||||
|
||||
len = 0;
|
||||
cp2 = Var_Parse(cur, ctxt, err, &len, &freeIt);
|
||||
cp2 = Var_Parse(cur, vp->ctxt, vp->err, &len, &freeIt);
|
||||
cur += len;
|
||||
Buf_Append(buf, cp2);
|
||||
if (freeIt) {
|
||||
@ -1061,7 +1071,7 @@ modifier_S(const char mod[], const char value[], Var *v, GNode *ctxt, Boolean er
|
||||
Boolean freeIt;
|
||||
|
||||
len = 0;
|
||||
cp2 = Var_Parse(cur, ctxt, err, &len, &freeIt);
|
||||
cp2 = Var_Parse(cur, vp->ctxt, vp->err, &len, &freeIt);
|
||||
cur += len;
|
||||
Buf_Append(buf, cp2);
|
||||
if (freeIt) {
|
||||
@ -1145,13 +1155,13 @@ modifier_S(const char mod[], const char value[], Var *v, GNode *ctxt, Boolean er
|
||||
static char *
|
||||
ParseModifier(const char input[], const char tstr[],
|
||||
char startc, char endc, Boolean dynamic, Var *v,
|
||||
GNode *ctxt, Boolean err, size_t *lengthPtr, Boolean *freePtr)
|
||||
VarParser *vp, size_t *lengthPtr, Boolean *freePtr)
|
||||
{
|
||||
char *value;
|
||||
const char *cp;
|
||||
size_t used;
|
||||
|
||||
value = VarExpand(v, ctxt, err);
|
||||
value = VarExpand(v, vp);
|
||||
*freePtr = TRUE;
|
||||
|
||||
tstr++;
|
||||
@ -1174,7 +1184,7 @@ ParseModifier(const char input[], const char tstr[],
|
||||
|
||||
readonly = TRUE; /* tstr isn't modified here */
|
||||
|
||||
newStr = modifier_S(tstr, value, v, ctxt, err, &consumed);
|
||||
newStr = modifier_S(tstr, value, v, vp, &consumed);
|
||||
tstr += consumed;
|
||||
break;
|
||||
case 'C':
|
||||
@ -1190,7 +1200,7 @@ ParseModifier(const char input[], const char tstr[],
|
||||
|
||||
cp = tstr;
|
||||
|
||||
if ((re = VarGetPattern(ctxt, err, &cp, delim, NULL,
|
||||
if ((re = VarGetPattern(vp, &cp, delim, NULL,
|
||||
NULL, NULL)) == NULL) {
|
||||
*lengthPtr = cp - input + 1;
|
||||
if (*freePtr)
|
||||
@ -1201,7 +1211,7 @@ ParseModifier(const char input[], const char tstr[],
|
||||
return (var_Error);
|
||||
}
|
||||
|
||||
if ((pattern.replace = VarGetPattern(ctxt, err, &cp,
|
||||
if ((pattern.replace = VarGetPattern(vp, &cp,
|
||||
delim, NULL, NULL, NULL)) == NULL){
|
||||
free(re);
|
||||
|
||||
@ -1393,8 +1403,8 @@ ParseModifier(const char input[], const char tstr[],
|
||||
cp = tstr;
|
||||
|
||||
delim = '=';
|
||||
if ((pattern.lhs = VarGetPattern(ctxt,
|
||||
err, &cp, delim, &pattern.flags, &pattern.leftLen,
|
||||
if ((pattern.lhs = VarGetPattern(vp,
|
||||
&cp, delim, &pattern.flags, &pattern.leftLen,
|
||||
NULL)) == NULL) {
|
||||
/* was: goto cleanup */
|
||||
*lengthPtr = cp - input + 1;
|
||||
@ -1407,8 +1417,8 @@ ParseModifier(const char input[], const char tstr[],
|
||||
}
|
||||
|
||||
delim = endc;
|
||||
if ((pattern.rhs = VarGetPattern(ctxt,
|
||||
err, &cp, delim, NULL, &pattern.rightLen,
|
||||
if ((pattern.rhs = VarGetPattern(vp,
|
||||
&cp, delim, NULL, &pattern.rightLen,
|
||||
&pattern)) == NULL) {
|
||||
/* was: goto cleanup */
|
||||
*lengthPtr = cp - input + 1;
|
||||
@ -1504,7 +1514,7 @@ ParseModifier(const char input[], const char tstr[],
|
||||
VarDestroy(v, TRUE);
|
||||
|
||||
*freePtr = FALSE;
|
||||
return (err ? var_Error : varNoError);
|
||||
return (vp->err ? var_Error : varNoError);
|
||||
}
|
||||
} else {
|
||||
return (value);
|
||||
@ -1512,7 +1522,7 @@ ParseModifier(const char input[], const char tstr[],
|
||||
}
|
||||
|
||||
static char *
|
||||
ParseRestModifier(const char input[], const char ptr[], char startc, char endc, Buffer *buf, GNode *ctxt, Boolean err, size_t *lengthPtr, Boolean *freePtr)
|
||||
ParseRestModifier(const char input[], const char ptr[], char startc, char endc, Buffer *buf, VarParser *vp, size_t *lengthPtr, Boolean *freePtr)
|
||||
{
|
||||
const char *vname;
|
||||
size_t vlen;
|
||||
@ -1526,14 +1536,14 @@ ParseRestModifier(const char input[], const char ptr[], char startc, char endc,
|
||||
|
||||
dynamic = FALSE;
|
||||
|
||||
v = VarFind(vname, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
|
||||
v = VarFind(vname, vp->ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
|
||||
if (v != NULL) {
|
||||
return (ParseModifier(input, ptr,
|
||||
startc, endc, dynamic, v,
|
||||
ctxt, err, lengthPtr, freePtr));
|
||||
vp, lengthPtr, freePtr));
|
||||
}
|
||||
|
||||
if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
|
||||
if ((vp->ctxt == VAR_CMD) || (vp->ctxt == VAR_GLOBAL)) {
|
||||
if ((vlen == 1) ||
|
||||
((vlen == 2) && (vname[1] == 'F' || vname[1] == 'D'))) {
|
||||
/*
|
||||
@ -1568,7 +1578,7 @@ ParseRestModifier(const char input[], const char ptr[], char startc, char endc,
|
||||
v = VarCreate(vname, NULL, VAR_JUNK);
|
||||
return (ParseModifier(input, ptr,
|
||||
startc, endc, dynamic, v,
|
||||
ctxt, err, lengthPtr, freePtr));
|
||||
vp, lengthPtr, freePtr));
|
||||
} else {
|
||||
/*
|
||||
* Check for D and F forms of local variables since we're in
|
||||
@ -1585,11 +1595,11 @@ ParseRestModifier(const char input[], const char ptr[], char startc, char endc,
|
||||
name[0] = vname[0];
|
||||
name[1] = '\0';
|
||||
|
||||
v = VarFind(name, ctxt, 0);
|
||||
v = VarFind(name, vp->ctxt, 0);
|
||||
if (v != NULL) {
|
||||
return (ParseModifier(input, ptr,
|
||||
startc, endc, dynamic, v,
|
||||
ctxt, err, lengthPtr, freePtr));
|
||||
vp, lengthPtr, freePtr));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1601,13 +1611,13 @@ ParseRestModifier(const char input[], const char ptr[], char startc, char endc,
|
||||
v = VarCreate(vname, NULL, VAR_JUNK);
|
||||
return (ParseModifier(input, ptr,
|
||||
startc, endc, dynamic, v,
|
||||
ctxt, err, lengthPtr, freePtr));
|
||||
vp, lengthPtr, freePtr));
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
ParseRestEnd(const char input[], Buffer *buf,
|
||||
GNode *ctxt, Boolean err, size_t *consumed, Boolean *freePtr)
|
||||
VarParser *vp, size_t *consumed, Boolean *freePtr)
|
||||
{
|
||||
const char *vname;
|
||||
size_t vlen;
|
||||
@ -1616,9 +1626,9 @@ ParseRestEnd(const char input[], Buffer *buf,
|
||||
|
||||
vname = Buf_GetAll(buf, &vlen);
|
||||
|
||||
v = VarFind(vname, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
|
||||
v = VarFind(vname, vp->ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
|
||||
if (v != NULL) {
|
||||
value = VarExpand(v, ctxt, err);
|
||||
value = VarExpand(v, vp);
|
||||
|
||||
if (v->flags & VAR_FROM_ENV) {
|
||||
VarDestroy(v, TRUE);
|
||||
@ -1628,7 +1638,7 @@ ParseRestEnd(const char input[], Buffer *buf,
|
||||
return (value);
|
||||
}
|
||||
|
||||
if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
|
||||
if ((vp->ctxt == VAR_CMD) || (vp->ctxt == VAR_GLOBAL)) {
|
||||
/*
|
||||
* If substituting a local variable in a non-local
|
||||
* context, assume it's for dynamic source stuff. We
|
||||
@ -1667,7 +1677,7 @@ ParseRestEnd(const char input[], Buffer *buf,
|
||||
}
|
||||
|
||||
*freePtr = FALSE;
|
||||
return (err ? var_Error : varNoError);
|
||||
return (vp->err ? var_Error : varNoError);
|
||||
} else {
|
||||
/*
|
||||
* Check for D and F forms of local variables since we're in
|
||||
@ -1681,7 +1691,7 @@ ParseRestEnd(const char input[], Buffer *buf,
|
||||
name[0] = vname[0];
|
||||
name[1] = '\0';
|
||||
|
||||
v = VarFind(name, ctxt, 0);
|
||||
v = VarFind(name, vp->ctxt, 0);
|
||||
if (v != NULL) {
|
||||
char *val;
|
||||
/*
|
||||
@ -1705,7 +1715,7 @@ ParseRestEnd(const char input[], Buffer *buf,
|
||||
}
|
||||
|
||||
*freePtr = FALSE;
|
||||
return (err ? var_Error : varNoError);
|
||||
return (vp->err ? var_Error : varNoError);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1713,7 +1723,7 @@ ParseRestEnd(const char input[], Buffer *buf,
|
||||
* Parse a multi letter variable name, and return it's value.
|
||||
*/
|
||||
static char *
|
||||
VarParseLong(const char input[], GNode *ctxt, Boolean err,
|
||||
VarParseLong(const char input[], VarParser *vp,
|
||||
size_t *consumed, Boolean *freePtr)
|
||||
{
|
||||
Buffer *buf;
|
||||
@ -1750,7 +1760,7 @@ VarParseLong(const char input[], GNode *ctxt, Boolean err,
|
||||
} else if (*ptr == ':') {
|
||||
result = ParseRestModifier(input - 2, ptr,
|
||||
startc, endc, buf,
|
||||
ctxt, err, consumed, freePtr);
|
||||
vp, consumed, freePtr);
|
||||
Buf_Destroy(buf, TRUE);
|
||||
return (result);
|
||||
|
||||
@ -1760,7 +1770,7 @@ VarParseLong(const char input[], GNode *ctxt, Boolean err,
|
||||
char *rval;
|
||||
|
||||
rlen = 0;
|
||||
rval = Var_Parse(ptr, ctxt, err, &rlen, &rfree);
|
||||
rval = Var_Parse(ptr, vp->ctxt, vp->err, &rlen, &rfree);
|
||||
if (rval == var_Error) {
|
||||
Fatal("Error expanding embedded variable.");
|
||||
}
|
||||
@ -1779,7 +1789,7 @@ VarParseLong(const char input[], GNode *ctxt, Boolean err,
|
||||
|
||||
*consumed += 1; /* consume closing paren or brace */
|
||||
|
||||
result = ParseRestEnd(input - 2, buf, ctxt, err, consumed, freePtr);
|
||||
result = ParseRestEnd(input - 2, buf, vp, consumed, freePtr);
|
||||
|
||||
Buf_Destroy(buf, TRUE);
|
||||
return (result);
|
||||
@ -1789,7 +1799,7 @@ VarParseLong(const char input[], GNode *ctxt, Boolean err,
|
||||
* Parse a single letter variable name, and return it's value.
|
||||
*/
|
||||
static char *
|
||||
VarParseShort(const char input[], GNode *ctxt, Boolean err,
|
||||
VarParseShort(const char input[], VarParser *vp,
|
||||
size_t *consumed, Boolean *freeResult)
|
||||
{
|
||||
char vname[2];
|
||||
@ -1801,9 +1811,9 @@ VarParseShort(const char input[], GNode *ctxt, Boolean err,
|
||||
|
||||
*consumed += 1; /* consume single letter */
|
||||
|
||||
v = VarFind(vname, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
|
||||
v = VarFind(vname, vp->ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
|
||||
if (v != NULL) {
|
||||
value = VarExpand(v, ctxt, err);
|
||||
value = VarExpand(v, vp);
|
||||
|
||||
if (v->flags & VAR_FROM_ENV) {
|
||||
VarDestroy(v, TRUE);
|
||||
@ -1821,7 +1831,7 @@ VarParseShort(const char input[], GNode *ctxt, Boolean err,
|
||||
* variables are treated specially as they are the only four that
|
||||
* will be set when dynamic sources are expanded.
|
||||
*/
|
||||
if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
|
||||
if ((vp->ctxt == VAR_CMD) || (vp->ctxt == VAR_GLOBAL)) {
|
||||
|
||||
/* XXX: It looks like $% and $! are reversed here */
|
||||
switch (vname[0]) {
|
||||
@ -1839,7 +1849,7 @@ VarParseShort(const char input[], GNode *ctxt, Boolean err,
|
||||
return (estrdup("$(.MEMBER)"));
|
||||
default:
|
||||
*freeResult = FALSE;
|
||||
return (err ? var_Error : varNoError);
|
||||
return (vp->err ? var_Error : varNoError);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1847,7 +1857,30 @@ VarParseShort(const char input[], GNode *ctxt, Boolean err,
|
||||
* Variable name was not found.
|
||||
*/
|
||||
*freeResult = FALSE;
|
||||
return (err ? var_Error : varNoError);
|
||||
return (vp->err ? var_Error : varNoError);
|
||||
}
|
||||
|
||||
static char *
|
||||
VarParse(const char input[], VarParser *vp, size_t *consumed, Boolean *freeResult)
|
||||
{
|
||||
/* assert(input[0] == '$'); */
|
||||
|
||||
*consumed += 1; /* consume '$' */
|
||||
input += 1;
|
||||
|
||||
if (input[0] == '\0') {
|
||||
/* Error, there is only a dollar sign in the input string. */
|
||||
*freeResult = FALSE;
|
||||
return (vp->err ? var_Error : varNoError);
|
||||
|
||||
} else if (input[0] == OPEN_PAREN || input[0] == OPEN_BRACE) {
|
||||
/* multi letter variable name */
|
||||
return (VarParseLong(input, vp, consumed, freeResult));
|
||||
|
||||
} else {
|
||||
/* single letter variable name */
|
||||
return (VarParseShort(input, vp, consumed, freeResult));
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
@ -1878,24 +1911,13 @@ char *
|
||||
Var_Parse(const char input[], GNode *ctxt, Boolean err,
|
||||
size_t *consumed, Boolean *freeResult)
|
||||
{
|
||||
/* assert(input[0] == '$'); */
|
||||
VarParser vp = {
|
||||
input,
|
||||
ctxt,
|
||||
err
|
||||
};
|
||||
|
||||
*consumed += 1; /* consume '$' */
|
||||
input += 1;
|
||||
|
||||
if (input[0] == '\0') {
|
||||
/* Error, there is only a dollar sign in the input string. */
|
||||
*freeResult = FALSE;
|
||||
return (err ? var_Error : varNoError);
|
||||
|
||||
} else if (input[0] == OPEN_PAREN || input[0] == OPEN_BRACE) {
|
||||
/* multi letter variable name */
|
||||
return (VarParseLong(input, ctxt, err, consumed, freeResult));
|
||||
|
||||
} else {
|
||||
/* single letter variable name */
|
||||
return (VarParseShort(input, ctxt, err, consumed, freeResult));
|
||||
}
|
||||
return VarParse(input, &vp, consumed, freeResult);
|
||||
}
|
||||
|
||||
/*-
|
||||
|
Loading…
Reference in New Issue
Block a user