When substituting interpreter variables, allow '$' to be part of

the variable expresstion only within '[]' or '()'. That lets
forms like "$a$b" to be treated as two substitutions, not one.
This commit is contained in:
Giles Atkinson
2023-11-27 15:13:31 +00:00
parent 3ba314d4bc
commit 89851872ed
+15 -4
View File
@@ -789,7 +789,7 @@ cp_getvar(char *name, enum cp_types type, void *retval, size_t rsize)
* isset is TRUE if the variable is being set, FALSE if unset. Also * isset is TRUE if the variable is being set, FALSE if unset. Also
* required is a routine cp_enqvar(name) which returns a struct * required is a routine cp_enqvar(name) which returns a struct
* variable *, which allows the host program to provide values for * variable *, which allows the host program to provide values for
* non-cshpar variables. See line 855 */ * non-cshpar variables. */
/* Non-alphanumeric characters that may appear in variable names. < is very /* Non-alphanumeric characters that may appear in variable names. < is very
* special... * special...
@@ -806,10 +806,11 @@ cp_getvar(char *name, enum cp_types type, void *retval, size_t rsize)
* Return value * Return value
* Address of the first character after the variable name. * Address of the first character after the variable name.
*/ */
char *span_var_expr(char *t) char *span_var_expr(char *s)
{ {
int parenthesis = 0; char *t = s;
int brackets = 0; int parenthesis = 0;
int brackets = 0;
while (*t && (isalnum_c(*t) || strchr(VALIDCHARS, *t))) while (*t && (isalnum_c(*t) || strchr(VALIDCHARS, *t)))
switch (*t++) switch (*t++)
@@ -832,6 +833,14 @@ char *span_var_expr(char *t)
if (--parenthesis <= 0) if (--parenthesis <= 0)
return t; return t;
break; break;
case '$':
if (brackets <= 0 && parenthesis <= 0) {
if (t == s + 1) // Special case: "$$".
return t;
else
return t-1;
}
break;
default: default:
break; break;
} }
@@ -1000,6 +1009,8 @@ wordlist *vareval(/* NOT const */ char *string)
if (eq(v->va_name, string)) if (eq(v->va_name, string))
break; break;
if (!v && isdigit_c(*string)) { if (!v && isdigit_c(*string)) {
/* Treat $i for some integer i as argv[i] - positional parameters. */
for (v = variables; v; v = v->va_next) { for (v = variables; v; v = v->va_next) {
if (eq(v->va_name, "argv")) { if (eq(v->va_name, "argv")) {
break; break;