version 1.23, 1999/12/16 17:02:45 |
version 1.24, 1999/12/16 17:27:18 |
|
|
*/ |
*/ |
str = VarValue(v); |
str = VarValue(v); |
if (strchr (str, '$') != (char *)NULL) { |
if (strchr (str, '$') != (char *)NULL) { |
str = Var_Subst(NULL, str, ctxt, err); |
str = Var_Subst(str, ctxt, err); |
*freePtr = TRUE; |
*freePtr = TRUE; |
} |
} |
|
|
|
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* Var_Subst -- |
* Var_Subst -- |
* Substitute for all variables in the given string in the given context |
* Substitute for all variables in a string in a context |
* If undefErr is TRUE, Parse_Error will be called when an undefined |
* If undefErr is TRUE, Parse_Error will be called when an undefined |
* variable is encountered. |
* variable is encountered. |
* |
* |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
char * |
char * |
Var_Subst (var, str, ctxt, undefErr) |
Var_Subst(str, ctxt, undefErr) |
char *var; /* Named variable || NULL for all */ |
|
char *str; /* the string in which to substitute */ |
char *str; /* the string in which to substitute */ |
GNode *ctxt; /* the context wherein to find variables */ |
GNode *ctxt; /* the context wherein to find variables */ |
Boolean undefErr; /* TRUE if undefineds are an error */ |
Boolean undefErr; /* TRUE if undefineds are an error */ |
{ |
{ |
BUFFER buf; /* Buffer for forming things */ |
BUFFER buf; /* Buffer for forming things */ |
char *val; /* Value to substitute for a variable */ |
|
int length; /* Length of the variable invocation */ |
|
Boolean doFree; /* Set true if val should be freed */ |
|
static Boolean errorReported; /* Set true if an error has already |
static Boolean errorReported; /* Set true if an error has already |
* been reported to prevent a plethora |
* been reported to prevent a plethora |
* of messages when recursing */ |
* of messages when recursing */ |
|
|
Buf_Init(&buf, MAKE_BSIZE); |
Buf_Init(&buf, MAKE_BSIZE); |
errorReported = FALSE; |
errorReported = FALSE; |
|
|
while (*str) { |
for (;;) { |
if (var == NULL && (*str == '$') && (str[1] == '$')) { |
char *val; /* Value to substitute for a variable */ |
/* |
size_t length; /* Length of the variable invocation */ |
* A dollar sign may be escaped either with another dollar sign. |
Boolean doFree; /* Set true if val should be freed */ |
* In such a case, we skip over the escape character and store the |
const char *cp; |
* dollar sign into the buffer directly. |
|
*/ |
|
str++; |
|
Buf_AddChar(&buf, *str); |
|
str++; |
|
} else if (*str != '$') { |
|
/* |
|
* Skip as many characters as possible -- either to the end of |
|
* the string or to the next dollar sign (variable invocation). |
|
*/ |
|
char *cp; |
|
|
|
for (cp = str++; *str != '$' && *str != '\0'; str++) |
/* copy uninteresting stuff */ |
continue; |
for (cp = str; *str != '\0' && *str != '$'; str++) |
Buf_AddInterval(&buf, cp, str); |
; |
|
Buf_AddInterval(&buf, cp, str); |
|
if (*str == '\0') |
|
break; |
|
if (str[1] == '$') { |
|
/* A dollar sign may be escaped with another dollar sign. */ |
|
Buf_AddChar(&buf, '$'); |
|
str += 2; |
|
continue; |
|
} |
|
val = Var_Parse(str, ctxt, undefErr, &length, &doFree); |
|
/* When we come down here, val should either point to the |
|
* value of this variable, suitably modified, or be NULL. |
|
* Length should be the total length of the potential |
|
* variable invocation (from $ to end character...) */ |
|
if (val == var_Error || val == 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 += length; |
|
} else if (undefErr) { |
|
/* 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\"",length,str); |
|
} |
|
str += length; |
|
errorReported = TRUE; |
|
} else { |
|
Buf_AddChar(&buf, *str); |
|
str += 1; |
|
} |
} else { |
} else { |
if (var != NULL) { |
/* We've now got a variable structure to store in. But first, |
int expand; |
* advance the string pointer. */ |
for (;;) { |
str += length; |
if (str[1] != '(' && str[1] != '{') { |
|
if (str[1] != *var || var[1] != '\0') { |
|
Buf_AddChars(&buf, 2, str); |
|
str += 2; |
|
expand = FALSE; |
|
} |
|
else |
|
expand = TRUE; |
|
break; |
|
} |
|
else { |
|
char *p; |
|
|
|
/* |
/* Copy all the characters from the variable value straight |
* Scan up to the end of the variable name. |
* into the new string. */ |
*/ |
Buf_AddString(&buf, val); |
for (p = &str[2]; *p && |
if (doFree) |
*p != ':' && *p != ')' && *p != '}'; p++) |
free(val); |
if (*p == '$') |
} |
break; |
} |
/* |
return Buf_Retrieve(&buf); |
* A variable inside the variable. We cannot expand |
} |
* the external variable yet, so we try again with |
|
* the nested one |
|
*/ |
|
if (*p == '$') { |
|
Buf_AddInterval(&buf, str, p); |
|
str = p; |
|
continue; |
|
} |
|
|
|
if (strncmp(var, str + 2, p - str - 2) != 0 || |
/*- |
var[p - str - 2] != '\0') { |
*----------------------------------------------------------------------- |
/* |
* Var_SubstVar -- |
* Not the variable we want to expand, scan |
* Substitute for one variable in the given string in the given context |
* until the next variable |
* If undefErr is TRUE, Parse_Error will be called when an undefined |
*/ |
* variable is encountered. |
for (;*p != '$' && *p != '\0'; p++) |
* |
continue; |
* Side Effects: |
Buf_AddInterval(&buf, str, p); |
* Append the result to the buffer |
str = p; |
*----------------------------------------------------------------------- |
expand = FALSE; |
*/ |
} |
void |
else |
Var_SubstVar(buf, str, var, ctxt) |
expand = TRUE; |
Buffer buf; /* Where to store the result */ |
break; |
char *str; /* The string in which to substitute */ |
} |
const char *var; /* Named variable */ |
} |
GNode *ctxt; /* The context wherein to find variables */ |
if (!expand) |
{ |
continue; |
char *val; /* Value substituted for a variable */ |
|
size_t length; /* Length of the variable invocation */ |
|
Boolean doFree; /* Set true if val should be freed */ |
|
|
|
for (;;) { |
|
const char *cp; |
|
/* copy uninteresting stuff */ |
|
for (cp = str; *str != '\0' && *str != '$'; str++) |
|
; |
|
Buf_AddInterval(buf, cp, str); |
|
if (*str == '\0') |
|
break; |
|
if (str[1] == '$') { |
|
Buf_AddString(buf, "$$"); |
|
str += 2; |
|
continue; |
|
} |
|
if (str[1] != '(' && str[1] != '{') { |
|
if (str[1] != *var || var[1] != '\0') { |
|
Buf_AddChars(buf, 2, str); |
|
str += 2; |
|
continue; |
} |
} |
|
} else { |
|
char *p; |
|
char endc; |
|
|
val = Var_Parse (str, ctxt, undefErr, &length, &doFree); |
if (str[1] == '(') |
|
endc = ')'; |
|
else if (str[1] == '{') |
|
endc = '}'; |
|
|
/* |
/* Find the end of the variable specification. */ |
* When we come down here, val should either point to the |
p = str+2; |
* value of this variable, suitably modified, or be NULL. |
while (*p != '\0' && *p != ':' && *p != endc && *p != '$') |
* Length should be the total length of the potential |
p++; |
* variable invocation (from $ to end character...) |
/* A variable inside the variable. We don't know how to |
*/ |
* expand the external variable at this point, so we try |
if (val == var_Error || val == varNoError) { |
* again with the nested variable. */ |
/* |
if (*p == '$') { |
* If performing old-time variable substitution, skip over |
Buf_AddInterval(buf, str, p); |
* the variable and continue with the substitution. Otherwise, |
str = p; |
* store the dollar sign and advance str so we continue with |
continue; |
* the string... |
|
*/ |
|
if (oldVars) { |
|
str += length; |
|
} else if (undefErr) { |
|
/* |
|
* 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\"",length,str); |
|
} |
|
str += length; |
|
errorReported = TRUE; |
|
} else { |
|
Buf_AddChar(&buf, *str); |
|
str += 1; |
|
} |
|
} else { |
|
/* |
|
* We've now got a variable structure to store in. But first, |
|
* advance the string pointer. |
|
*/ |
|
str += length; |
|
|
|
/* |
|
* Copy all the characters from the variable value straight |
|
* into the new string. |
|
*/ |
|
Buf_AddString(&buf, val); |
|
if (doFree) |
|
free(val); |
|
} |
} |
|
|
|
if (strncmp(var, str + 2, p - str - 2) != 0 || |
|
var[p - str - 2] != '\0') { |
|
/* Not the variable we want to expand. */ |
|
Buf_AddInterval(buf, str, p); |
|
str = p; |
|
continue; |
|
} |
} |
} |
} |
/* okay, so we've found the variable we want to expand. */ |
|
val = Var_Parse(str, ctxt, FALSE, &length, &doFree); |
|
/* We've now got a variable structure to store in. But first, |
|
* advance the string pointer. */ |
|
str += length; |
|
|
return Buf_Retrieve(&buf); |
/* Copy all the characters from the variable value straight |
|
* into the new string. */ |
|
Buf_AddString(buf, val); |
|
if (doFree) |
|
free(val); |
|
} |
} |
} |
|
|
/*- |
/*- |