summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorthepish <thepish@FreeBSD.org>1998-06-02 13:11:04 +0000
committerthepish <thepish@FreeBSD.org>1998-06-02 13:11:04 +0000
commit74cae44c57d1800678c42f4cb7cbfe7565d398e9 (patch)
tree2e059b2faf74ae16b40ff3cbc7484ed6d5e023ff /usr.bin
parentb3017dc03deeb2fac873028b486e583df31b84cb (diff)
downloadFreeBSD-src-74cae44c57d1800678c42f4cb7cbfe7565d398e9.zip
FreeBSD-src-74cae44c57d1800678c42f4cb7cbfe7565d398e9.tar.gz
PR: bin/6828
Submitted by: njs3@doc.ic.ac.uk Obtained from: NetBSD Implement embedded variable expansion
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/make/var.c83
1 files changed, 53 insertions, 30 deletions
diff --git a/usr.bin/make/var.c b/usr.bin/make/var.c
index 67ae2bd..0ae601d 100644
--- a/usr.bin/make/var.c
+++ b/usr.bin/make/var.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: var.c,v 1.9 1997/02/22 19:27:25 peter Exp $
+ * $Id: var.c,v 1.10 1997/09/29 03:53:53 imp Exp $
*/
#ifndef lint
@@ -1114,6 +1114,8 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
* expanding it in a non-local context. This
* is done to support dynamic sources. The
* result is just the invocation, unaltered */
+ int vlen; /* length of variable name, after embedded variable
+ * expansion */
*freePtr = FALSE;
dynamic = FALSE;
@@ -1165,23 +1167,34 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
endc = str[1];
}
} else {
+ /* build up expanded variable name in this buffer */
+ Buffer buf = Buf_Init(MAKE_BSIZE);
+
startc = str[1];
endc = startc == '(' ? ')' : '}';
/*
- * Skip to the end character or a colon, whichever comes first.
+ * Skip to the end character or a colon, whichever comes first,
+ * replacing embedded variables as we go.
*/
- for (tstr = str + 2;
- *tstr != '\0' && *tstr != endc && *tstr != ':';
- tstr++)
- {
- continue;
- }
- if (*tstr == ':') {
- haveModifier = TRUE;
- } else if (*tstr != '\0') {
- haveModifier = FALSE;
- } else {
+ for (tstr = str + 2; *tstr != '\0' && *tstr != endc && *tstr != ':'; tstr++)
+ if (*tstr == '$') {
+ int rlen;
+ Boolean rfree;
+ char* rval = Var_Parse(tstr, ctxt, err, &rlen, &rfree);
+
+ if (rval == var_Error) {
+ Fatal("Error expanding embedded variable.");
+ } else if (rval != NULL) {
+ Buf_AddBytes(buf, strlen(rval), (Byte *) rval);
+ if (rfree)
+ free(rval);
+ }
+ tstr += rlen - 1;
+ } else
+ Buf_AddByte(buf, (Byte) *tstr);
+
+ if (*tstr == '\0') {
/*
* If we never did find the end character, return NULL
* right now, setting the length to be the distance to
@@ -1190,17 +1203,23 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
*lengthPtr = tstr - str;
return (var_Error);
}
+
+ haveModifier = (*tstr == ':');
*tstr = '\0';
- v = VarFind (str + 2, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
+ Buf_AddByte(buf, (Byte) '\0');
+ str = Buf_GetAll(buf, NULL);
+ vlen = strlen(str);
+
+ v = VarFind (str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
if ((v == (Var *)NIL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
- ((tstr-str) == 4) && (str[3] == 'F' || str[3] == 'D'))
+ (vlen == 2) && (str[1] == 'F' || str[1] == 'D'))
{
/*
* Check for bogus D and F forms of local variables since we're
* in a local context and the name is the right length.
*/
- switch(str[2]) {
+ switch(str[0]) {
case '@':
case '%':
case '*':
@@ -1214,7 +1233,7 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
/*
* Well, it's local -- go look for it.
*/
- vname[0] = str[2];
+ vname[0] = str[0];
vname[1] = '\0';
v = VarFind(vname, ctxt, 0);
@@ -1222,11 +1241,11 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
/*
* No need for nested expansion or anything, as we're
* the only one who sets these things and we sure don't
- * but nested invocations in them...
+ * put nested invocations in them...
*/
val = (char *)Buf_GetAll(v->val, (int *)NULL);
- if (str[3] == 'D') {
+ if (str[1] == 'D') {
val = VarModify(val, VarHead, (ClientData)0);
} else {
val = VarModify(val, VarTail, (ClientData)0);
@@ -1238,6 +1257,7 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
*freePtr = TRUE;
*lengthPtr = tstr-start+1;
*tstr = endc;
+ Buf_Destroy(buf, TRUE);
return(val);
}
break;
@@ -1246,9 +1266,9 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
}
if (v == (Var *)NIL) {
- if ((((tstr-str) == 3) ||
- ((((tstr-str) == 4) && (str[3] == 'F' ||
- str[3] == 'D')))) &&
+ if (((vlen == 1) ||
+ (((vlen == 2) && (str[1] == 'F' ||
+ str[1] == 'D')))) &&
((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
{
/*
@@ -1260,7 +1280,7 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
* specially as they are the only four that will be set
* when dynamic sources are expanded.
*/
- switch (str[2]) {
+ switch (str[0]) {
case '@':
case '%':
case '*':
@@ -1268,17 +1288,17 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
dynamic = TRUE;
break;
}
- } else if (((tstr-str) > 4) && (str[2] == '.') &&
- isupper((unsigned char) str[3]) &&
+ } else if ((vlen > 2) && (str[0] == '.') &&
+ isupper((unsigned char) str[1]) &&
((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
{
int len;
- len = (tstr-str) - 3;
- if ((strncmp(str+2, ".TARGET", len) == 0) ||
- (strncmp(str+2, ".ARCHIVE", len) == 0) ||
- (strncmp(str+2, ".PREFIX", len) == 0) ||
- (strncmp(str+2, ".MEMBER", len) == 0))
+ len = vlen - 1;
+ if ((strncmp(str, ".TARGET", len) == 0) ||
+ (strncmp(str, ".ARCHIVE", len) == 0) ||
+ (strncmp(str, ".PREFIX", len) == 0) ||
+ (strncmp(str, ".MEMBER", len) == 0))
{
dynamic = TRUE;
}
@@ -1296,8 +1316,10 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
strncpy(str, start, *lengthPtr);
str[*lengthPtr] = '\0';
*freePtr = TRUE;
+ Buf_Destroy(buf, TRUE);
return(str);
} else {
+ Buf_Destroy(buf, TRUE);
return (err ? var_Error : varNoError);
}
} else {
@@ -1311,6 +1333,7 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
v->flags = VAR_JUNK;
}
}
+ Buf_Destroy(buf, TRUE);
}
if (v->flags & VAR_IN_USE) {
OpenPOWER on IntegriCloud