version 1.22, 1999/12/16 16:52:11 |
version 1.23, 1999/12/16 17:02:45 |
|
|
|
|
typedef struct Var { |
typedef struct Var { |
char *name; /* the variable's name */ |
char *name; /* the variable's name */ |
Buffer val; /* its value */ |
BUFFER val; /* its value */ |
int flags; /* miscellaneous status flags */ |
int flags; /* miscellaneous status flags */ |
#define VAR_IN_USE 1 /* Variable's value currently being used. |
#define VAR_IN_USE 1 /* Variable's value currently being used. |
* Used to avoid recursion */ |
* Used to avoid recursion */ |
|
|
} VarREPattern; |
} VarREPattern; |
#endif |
#endif |
|
|
|
#define VarValue(v) Buf_Retrieve(&((v)->val)) |
static int VarCmp __P((ClientData, ClientData)); |
static int VarCmp __P((ClientData, ClientData)); |
static Var *VarFind __P((char *, GNode *, int)); |
static Var *VarFind __P((char *, GNode *, int)); |
static Var *VarAdd __P((char *, char *, GNode *)); |
static Var *VarAdd __P((char *, char *, GNode *)); |
|
|
v->name = estrdup (name); |
v->name = estrdup (name); |
|
|
len = val ? strlen(val) : 0; |
len = val ? strlen(val) : 0; |
v->val = Buf_Init(len+1); |
Buf_Init(&(v->val), len+1); |
Buf_AddChars(v->val, len, val); |
Buf_AddChars(&(v->val), len, val); |
|
|
v->flags = 0; |
v->flags = 0; |
|
|
|
|
{ |
{ |
Var *v = (Var *) vp; |
Var *v = (Var *) vp; |
free(v->name); |
free(v->name); |
Buf_Destroy(v->val, TRUE); |
Buf_Destroy(&(v->val)); |
free((Address) v); |
free(v); |
} |
} |
|
|
|
|
|
|
if (v == (Var *) NIL) { |
if (v == (Var *) NIL) { |
(void)VarAdd(name, val, ctxt); |
(void)VarAdd(name, val, ctxt); |
} else { |
} else { |
Buf_Reset(v->val); |
Buf_Reset(&(v->val)); |
Buf_AddString(v->val, val); |
Buf_AddString(&(v->val), val); |
|
|
if (DEBUG(VAR)) { |
if (DEBUG(VAR)) { |
printf("%s:%s = %s\n", ctxt->name, name, val); |
printf("%s:%s = %s\n", ctxt->name, name, val); |
|
|
if (v == (Var *) NIL) { |
if (v == (Var *) NIL) { |
(void)VarAdd(name, val, ctxt); |
(void)VarAdd(name, val, ctxt); |
} else { |
} else { |
Buf_AddSpace(v->val); |
Buf_AddSpace(&(v->val)); |
Buf_AddString(v->val, val); |
Buf_AddString(&(v->val), val); |
|
|
if (DEBUG(VAR)) { |
if (DEBUG(VAR)) { |
printf("%s:%s = %s\n", ctxt->name, name, |
printf("%s:%s = %s\n", ctxt->name, name, VarValue(v)); |
Buf_Retrieve(v->val)); |
|
} |
} |
|
|
} |
} |
|
|
Var *v; |
Var *v; |
|
|
v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); |
v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); |
if (v != NULL) |
if (v != (Var *)NIL) |
return Buf_Retrieve(v->val); |
return VarValue(v); |
else |
else |
return NULL; |
return NULL; |
} |
} |
|
|
Boolean (*modProc) __P((char *, Boolean, Buffer, ClientData)); |
Boolean (*modProc) __P((char *, Boolean, Buffer, ClientData)); |
ClientData datum; /* Datum to pass it */ |
ClientData datum; /* Datum to pass it */ |
{ |
{ |
Buffer buf; /* Buffer for the new string */ |
BUFFER buf; /* Buffer for the new string */ |
Boolean addSpace; /* TRUE if need to add a space to the |
Boolean addSpace; /* TRUE if need to add a space to the |
* buffer before adding the trimmed |
* buffer before adding the trimmed |
* word */ |
* word */ |
|
|
char *as; /* word list memory */ |
char *as; /* word list memory */ |
int ac, i; |
int ac, i; |
|
|
buf = Buf_Init(0); |
Buf_Init(&buf, 0); |
addSpace = FALSE; |
addSpace = FALSE; |
|
|
av = brk_string(str, &ac, FALSE, &as); |
av = brk_string(str, &ac, FALSE, &as); |
|
|
for (i = 0; i < ac; i++) |
for (i = 0; i < ac; i++) |
addSpace = (*modProc)(av[i], addSpace, buf, datum); |
addSpace = (*modProc)(av[i], addSpace, &buf, datum); |
|
|
free(as); |
free(as); |
free(av); |
free(av); |
str = Buf_Retrieve(buf); |
return Buf_Retrieve(&buf); |
Buf_Destroy(buf, FALSE); |
|
return (str); |
|
} |
} |
|
|
/*- |
/*- |
|
|
VarPattern *pattern; |
VarPattern *pattern; |
{ |
{ |
char *cp; |
char *cp; |
Buffer buf = Buf_Init(0); |
BUFFER buf; |
int junk; |
int junk; |
|
|
|
Buf_Init(&buf, 0); |
if (length == NULL) |
if (length == NULL) |
length = &junk; |
length = &junk; |
|
|
|
|
*/ |
*/ |
for (cp = *tstr; *cp && (*cp != delim); cp++) { |
for (cp = *tstr; *cp && (*cp != delim); cp++) { |
if (IS_A_MATCH(cp, delim)) { |
if (IS_A_MATCH(cp, delim)) { |
Buf_AddChar(buf, cp[1]); |
Buf_AddChar(&buf, cp[1]); |
cp++; |
cp++; |
} else if (*cp == '$') { |
} else if (*cp == '$') { |
if (cp[1] == delim) { |
if (cp[1] == delim) { |
if (flags == NULL) |
if (flags == NULL) |
Buf_AddChar(buf, *cp); |
Buf_AddChar(&buf, *cp); |
else |
else |
/* |
/* |
* Unescaped $ at end of pattern => anchor |
* Unescaped $ at end of pattern => anchor |
|
|
* substitution and recurse. |
* substitution and recurse. |
*/ |
*/ |
cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt); |
cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt); |
Buf_AddString(buf, cp2); |
Buf_AddString(&buf, cp2); |
if (freeIt) |
if (freeIt) |
free(cp2); |
free(cp2); |
cp += len - 1; |
cp += len - 1; |
} |
} |
} |
} |
else if (pattern && *cp == '&') |
else if (pattern && *cp == '&') |
Buf_AddChars(buf, pattern->leftLen, pattern->lhs); |
Buf_AddChars(&buf, pattern->leftLen, pattern->lhs); |
else |
else |
Buf_AddChar(buf, *cp); |
Buf_AddChar(&buf, *cp); |
} |
} |
|
|
if (*cp != delim) { |
if (*cp != delim) { |
|
|
} |
} |
else { |
else { |
*tstr = ++cp; |
*tstr = ++cp; |
cp = Buf_Retrieve(buf); |
*length = Buf_Size(&buf); |
*length = Buf_Size(buf); |
return Buf_Retrieve(&buf); |
Buf_Destroy(buf, FALSE); |
|
return cp; |
|
} |
} |
} |
} |
|
|
|
|
char *str; |
char *str; |
{ |
{ |
|
|
Buffer buf; |
BUFFER buf; |
/* This should cover most shells :-( */ |
/* This should cover most shells :-( */ |
static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~"; |
static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~"; |
|
|
buf = Buf_Init(MAKE_BSIZE); |
Buf_Init(&buf, MAKE_BSIZE); |
for (; *str; str++) { |
for (; *str; str++) { |
if (strchr(meta, *str) != NULL) |
if (strchr(meta, *str) != NULL) |
Buf_AddChar(buf, '\\'); |
Buf_AddChar(&buf, '\\'); |
Buf_AddChar(buf, *str); |
Buf_AddChar(&buf, *str); |
} |
} |
str = Buf_Retrieve(buf); |
return Buf_Retrieve(&buf); |
Buf_Destroy(buf, FALSE); |
|
return str; |
|
} |
} |
|
|
/*- |
/*- |
|
|
* the only one who sets these things and we sure don't |
* the only one who sets these things and we sure don't |
* but nested invocations in them... |
* but nested invocations in them... |
*/ |
*/ |
val = Buf_Retrieve(v->val); |
val = VarValue(v); |
|
|
if (str[3] == 'D') { |
if (str[3] == 'D') { |
val = VarModify(val, VarHead, (ClientData)0); |
val = VarModify(val, VarHead, (ClientData)0); |
|
|
*/ |
*/ |
v = (Var *) emalloc(sizeof(Var)); |
v = (Var *) emalloc(sizeof(Var)); |
v->name = &str[1]; |
v->name = &str[1]; |
v->val = Buf_Init(1); |
Buf_Init(&(v->val), 1); |
v->flags = VAR_JUNK; |
v->flags = VAR_JUNK; |
} |
} |
} |
} |
|
|
* been dynamically-allocated, so it will need freeing when we |
* been dynamically-allocated, so it will need freeing when we |
* return. |
* return. |
*/ |
*/ |
str = Buf_Retrieve(v->val); |
str = VarValue(v); |
if (strchr (str, '$') != (char *)NULL) { |
if (strchr (str, '$') != (char *)NULL) { |
str = Var_Subst(NULL, str, ctxt, err); |
str = Var_Subst(NULL, str, ctxt, err); |
*freePtr = TRUE; |
*freePtr = TRUE; |
|
|
free(str); |
free(str); |
} |
} |
*freePtr = FALSE; |
*freePtr = FALSE; |
Buf_Destroy(v->val, TRUE); |
Buf_Destroy(&(v->val)); |
free((Address)v); |
free(v); |
if (dynamic) { |
if (dynamic) { |
str = emalloc(*lengthPtr + 1); |
str = emalloc(*lengthPtr + 1); |
strncpy(str, start, *lengthPtr); |
strncpy(str, start, *lengthPtr); |
|
|
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 */ |
char *val; /* Value to substitute for a variable */ |
int length; /* Length of the variable invocation */ |
int length; /* Length of the variable invocation */ |
Boolean doFree; /* Set true if val should be freed */ |
Boolean doFree; /* Set true if val should be freed */ |
|
|
* been reported to prevent a plethora |
* been reported to prevent a plethora |
* of messages when recursing */ |
* of messages when recursing */ |
|
|
buf = Buf_Init(MAKE_BSIZE); |
Buf_Init(&buf, MAKE_BSIZE); |
errorReported = FALSE; |
errorReported = FALSE; |
|
|
while (*str) { |
while (*str) { |
|
|
* dollar sign into the buffer directly. |
* dollar sign into the buffer directly. |
*/ |
*/ |
str++; |
str++; |
Buf_AddChar(buf, *str); |
Buf_AddChar(&buf, *str); |
str++; |
str++; |
} else if (*str != '$') { |
} else if (*str != '$') { |
/* |
/* |
|
|
|
|
for (cp = str++; *str != '$' && *str != '\0'; str++) |
for (cp = str++; *str != '$' && *str != '\0'; str++) |
continue; |
continue; |
Buf_AddInterval(buf, cp, str); |
Buf_AddInterval(&buf, cp, str); |
} else { |
} else { |
if (var != NULL) { |
if (var != NULL) { |
int expand; |
int expand; |
for (;;) { |
for (;;) { |
if (str[1] != '(' && str[1] != '{') { |
if (str[1] != '(' && str[1] != '{') { |
if (str[1] != *var || var[1] != '\0') { |
if (str[1] != *var || var[1] != '\0') { |
Buf_AddChars(buf, 2, str); |
Buf_AddChars(&buf, 2, str); |
str += 2; |
str += 2; |
expand = FALSE; |
expand = FALSE; |
} |
} |
|
|
* the nested one |
* the nested one |
*/ |
*/ |
if (*p == '$') { |
if (*p == '$') { |
Buf_AddInterval(buf, str, p); |
Buf_AddInterval(&buf, str, p); |
str = p; |
str = p; |
continue; |
continue; |
} |
} |
|
|
*/ |
*/ |
for (;*p != '$' && *p != '\0'; p++) |
for (;*p != '$' && *p != '\0'; p++) |
continue; |
continue; |
Buf_AddInterval(buf, str, p); |
Buf_AddInterval(&buf, str, p); |
str = p; |
str = p; |
expand = FALSE; |
expand = FALSE; |
} |
} |
|
|
str += length; |
str += length; |
errorReported = TRUE; |
errorReported = TRUE; |
} else { |
} else { |
Buf_AddChar(buf, *str); |
Buf_AddChar(&buf, *str); |
str += 1; |
str += 1; |
} |
} |
} else { |
} else { |
|
|
* Copy all the characters from the variable value straight |
* Copy all the characters from the variable value straight |
* into the new string. |
* into the new string. |
*/ |
*/ |
Buf_AddString(buf, val); |
Buf_AddString(&buf, val); |
if (doFree) { |
if (doFree) |
free ((Address)val); |
free(val); |
} |
|
} |
} |
} |
} |
} |
} |
|
|
str = Buf_Retrieve(buf); |
return Buf_Retrieve(&buf); |
Buf_Destroy(buf, FALSE); |
|
return (str); |
|
} |
} |
|
|
/*- |
/*- |
|
|
|
|
/****************** PRINT DEBUGGING INFO *****************/ |
/****************** PRINT DEBUGGING INFO *****************/ |
static int |
static int |
VarPrintVar (vp, dummy) |
VarPrintVar(vp, dummy) |
ClientData vp; |
ClientData vp; |
ClientData dummy; |
ClientData dummy; |
{ |
{ |
Var *v = (Var *) vp; |
Var *v = (Var *) vp; |
printf ("%-16s = %s\n", v->name, Buf_Retrieve(v->val)); |
printf("%-16s = %s\n", v->name, VarValue(v)); |
return (dummy ? 0 : 0); |
return (dummy ? 0 : 0); |
} |
} |
|
|