diff --git a/ChangeLog b/ChangeLog index c8b5d9215..9aa28d6a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-08-18 Peter Stephenson + + * 21655: Src/glob.c, Test/D04parameter.ztst: replacing multiple + matches where the replacement string itself came from a match + could get confused. + 2005-08-17 Wayne Davison * 21654: Src/string.c, Src/utils.c: Marked some ifdef/endif lines diff --git a/Src/glob.c b/Src/glob.c index 723745774..0c836bd7d 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -2000,15 +2000,6 @@ struct repldata { }; typedef struct repldata *Repldata; -/* - * List of bits of matches to concatenate with replacement string. - * The data is a struct repldata. It is not used in cases like - * ${...//#foo/bar} even though SUB_GLOBAL is set, since the match - * is anchored. It goes on the heap. - */ - -static LinkList repllist; - /* Having found a match in getmatch, decide what part of string * to return. The matched part starts b characters into string s * and finishes e characters in: 0 <= b <= e <= strlen(s) @@ -2020,7 +2011,8 @@ static LinkList repllist; /**/ static char * -get_match_ret(char *s, int b, int e, int fl, char *replstr) +get_match_ret(char *s, int b, int e, int fl, char *replstr, + LinkList repllist) { char buf[80], *r, *p, *rr; int ll = 0, l = strlen(s), bl = 0, t = 0, i; @@ -2230,8 +2222,13 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) * lengths. */ int ioff, l = strlen(*sp), uml = ztrlen(*sp), matched = 1, umlen; - - repllist = NULL; + /* + * List of bits of matches to concatenate with replacement string. + * The data is a struct repldata. It is not used in cases like + * ${...//#foo/bar} even though SUB_GLOBAL is set, since the match + * is anchored. It goes on the heap. + */ + static LinkList repllist = NULL; /* perform must-match test for complex closures */ if (p->mustoff) @@ -2254,7 +2251,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) if (fl & SUB_ALL) { int i = matched && pattry(p, s); - *sp = get_match_ret(*sp, 0, i ? l : 0, fl, i ? replstr : 0); + *sp = get_match_ret(*sp, 0, i ? l : 0, fl, i ? replstr : 0, repllist); if (! **sp && (((fl & SUB_MATCH) && !i) || ((fl & SUB_REST) && i))) return 0; return 1; @@ -2283,7 +2280,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) } } } - *sp = get_match_ret(*sp, 0, mlen, fl, replstr); + *sp = get_match_ret(*sp, 0, mlen, fl, replstr, repllist); return 1; } break; @@ -2298,7 +2295,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) t--; set_pat_start(p, t-s); if (pattrylen(p, t, s + l - t, umlen, ioff)) { - *sp = get_match_ret(*sp, t - s, l, fl, replstr); + *sp = get_match_ret(*sp, t - s, l, fl, replstr, repllist); return 1; } if (t > s+1 && t[-2] == Meta) @@ -2314,7 +2311,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) ioff++, METAINC(t), umlen--) { set_pat_start(p, t-s); if (pattrylen(p, t, s + l - t, umlen, ioff)) { - *sp = get_match_ret(*sp, t-s, l, fl, replstr); + *sp = get_match_ret(*sp, t-s, l, fl, replstr, repllist); return 1; } if (*t == Meta) @@ -2326,7 +2323,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) /* Smallest at start, but matching substrings. */ set_pat_start(p, l); if (!(fl & SUB_GLOBAL) && pattry(p, s + l) && !--n) { - *sp = get_match_ret(*sp, 0, 0, fl, replstr); + *sp = get_match_ret(*sp, 0, 0, fl, replstr, repllist); return 1; } /* fall through */ case (SUB_SUBSTR|SUB_LONG): @@ -2357,7 +2354,8 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) } } if (!--n || (n <= 0 && (fl & SUB_GLOBAL))) { - *sp = get_match_ret(*sp, t-s, mpos-s, fl, replstr); + *sp = get_match_ret(*sp, t-s, mpos-s, fl, + replstr, repllist); if (mpos == t) METAINC(mpos); } @@ -2396,7 +2394,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) set_pat_start(p, l); if ((fl & (SUB_LONG|SUB_GLOBAL)) == SUB_LONG && pattry(p, s + l) && !--n) { - *sp = get_match_ret(*sp, 0, 0, fl, replstr); + *sp = get_match_ret(*sp, 0, 0, fl, replstr, repllist); return 1; } break; @@ -2407,7 +2405,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) if (!(fl & SUB_LONG)) { set_pat_start(p, l); if (pattrylen(p, s + l, 0, 0, uml) && !--n) { - *sp = get_match_ret(*sp, l, l, fl, replstr); + *sp = get_match_ret(*sp, l, l, fl, replstr, repllist); return 1; } } @@ -2431,13 +2429,14 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) } } } - *sp = get_match_ret(*sp, t-s, mpos-s, fl, replstr); + *sp = get_match_ret(*sp, t-s, mpos-s, fl, + replstr, repllist); return 1; } } set_pat_start(p, l); if ((fl & SUB_LONG) && pattrylen(p, s + l, 0, 0, uml) && !--n) { - *sp = get_match_ret(*sp, l, l, fl, replstr); + *sp = get_match_ret(*sp, l, l, fl, replstr, repllist); return 1; } break; @@ -2478,7 +2477,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) } /* munge the whole string: no match, so no replstr */ - *sp = get_match_ret(*sp, 0, 0, fl, 0); + *sp = get_match_ret(*sp, 0, 0, fl, 0, 0); return 1; } diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 7f2ed4670..7a6254300 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -604,3 +604,11 @@ print "${${foo}/?*/replacement}" 0:Quoted zero-length strings are handled properly > + + file=aleftkept + print ${file//(#b)(*)left/${match/a/andsome}} + print ${file//(#b)(*)left/${match//a/andsome}} +0:Substitutions where $match is itself substituted in the replacement +>andsomekept +>andsomekept +