From: phk Date: Tue, 27 May 2008 07:10:22 +0000 (+0000) Subject: Add a new vcl function regsuball() X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=424835697c21beca22d757e59ea775c8048e9b4c;p=varnish Add a new vcl function regsuball() It works just like regsub(), but replaces all occurrences of the regexp. regsub("1foofoofoo2", "foo", "bar") -> "1barfoofoo2" regsuball("1foofoofoo2", "foo", "bar") -> "1barbarbar2" Fixes ticket 238 git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@2640 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/cache_vrt_re.c b/varnish-cache/bin/varnishd/cache_vrt_re.c index c3c84d46..538e1a4b 100644 --- a/varnish-cache/bin/varnishd/cache_vrt_re.c +++ b/varnish-cache/bin/varnishd/cache_vrt_re.c @@ -104,12 +104,13 @@ VRT_re_test(struct vsb *sb, const char *re, int sub) } const char * -VRT_regsub(const struct sess *sp, const char *str, void *re, const char *sub) +VRT_regsub(const struct sess *sp, int all, const char *str, void *re, const char *sub) { regmatch_t pm[10]; regex_t *t; int i, l; char *b, *p, *e; + const char *s; unsigned u, x; AN(re); @@ -124,42 +125,48 @@ VRT_regsub(const struct sess *sp, const char *str, void *re, const char *sub) e = p = b = sp->http->ws->f; e += u; - /* Copy prefix to match */ - if (pm[0].rm_so > 0) { - if (p + pm[0].rm_so < e) - memcpy(p, str, pm[0].rm_so); - p += pm[0].rm_so; - } + do { + /* Copy prefix to match */ + if (pm[0].rm_so > 0) { + if (p + pm[0].rm_so < e) + memcpy(p, str, pm[0].rm_so); + p += pm[0].rm_so; + } - for ( ; *sub != '\0'; sub++ ) { - if (*sub == '&') { - l = pm[0].rm_eo - pm[0].rm_so; - if (l > 0) { - if (p + l < e) - memcpy(p, str + pm[0].rm_so, l); - p += l; + for (s = sub ; *s != '\0'; s++ ) { + if (*s == '&') { + l = pm[0].rm_eo - pm[0].rm_so; + if (l > 0) { + if (p + l < e) + memcpy(p, str + pm[0].rm_so, l); + p += l; + } + } else if (*s == '$' && isdigit(s[1])) { + x = sub[1] - '0'; + sub++; + l = pm[x].rm_eo - pm[x].rm_so; + if (l > 0) { + if (p + l < e) + memcpy(p, str + pm[x].rm_so, l); + p += l; + } + } else { + if (p + 1 < e) + *p = *s; + p++; } - } else if (*sub == '$' && isdigit(sub[1])) { - x = sub[1] - '0'; - sub++; - l = pm[x].rm_eo - pm[x].rm_so; - if (l > 0) { - if (p + l < e) - memcpy(p, str + pm[x].rm_so, l); - p += l; - } - } else { - if (p + 1 < e) - *p = *sub; - p++; } - } + str += pm[0].rm_eo; + if (!all) + break; + i = regexec(t, str, 10, pm, 0); + } while (i != REG_NOMATCH); /* Copy suffix to match */ - l = strlen(str + pm[0].rm_eo); + l = strlen(str); if (l > 0) { if (p + l < e) - memcpy(p, str + pm[0].rm_eo, l); + memcpy(p, str, l); p += l; } if (p + 1 < e) diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h index 7048f8dc..24c086e1 100644 --- a/varnish-cache/include/vrt.h +++ b/varnish-cache/include/vrt.h @@ -108,7 +108,7 @@ void VRT_re_init(void **, const char *, int sub); void VRT_re_fini(void *); int VRT_re_match(const char *, void *re); int VRT_re_test(struct vsb *, const char *, int sub); -const char *VRT_regsub(const struct sess *sp, const char *, void *, const char *); +const char *VRT_regsub(const struct sess *sp, int all, const char *, void *, const char *); void VRT_purge(const char *, int hash); diff --git a/varnish-cache/lib/libvcl/vcc_fixed_token.c b/varnish-cache/lib/libvcl/vcc_fixed_token.c index de54d69f..9232c3b0 100644 --- a/varnish-cache/lib/libvcl/vcc_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcc_fixed_token.c @@ -462,7 +462,7 @@ vcl_output_lang_h(struct vsb *sb) vsb_cat(sb, "void VRT_re_fini(void *);\n"); vsb_cat(sb, "int VRT_re_match(const char *, void *re);\n"); vsb_cat(sb, "int VRT_re_test(struct vsb *, const char *, int sub);\n"); - vsb_cat(sb, "const char *VRT_regsub(const struct sess *sp, const char *, void *, const char *);\n"); + vsb_cat(sb, "const char *VRT_regsub(const struct sess *sp, int all, const char *, void *, const char *);\n"); vsb_cat(sb, "\n"); vsb_cat(sb, "void VRT_purge(const char *, int hash);\n"); vsb_cat(sb, "\n"); @@ -541,7 +541,7 @@ vcl_output_lang_h(struct vsb *sb) vsb_cat(sb, "double VRT_r_obj_prefetch(const struct sess *);\n"); vsb_cat(sb, "void VRT_l_obj_prefetch(const struct sess *, double);\n"); vsb_cat(sb, "double VRT_r_obj_lastuse(const struct sess *);\n"); - vsb_cat(sb, "const char *VRT_r_obj_hash(struct sess *sp);\n"); + vsb_cat(sb, "const char * VRT_r_obj_hash(const struct sess *);\n"); vsb_cat(sb, "const char * VRT_r_resp_proto(const struct sess *);\n"); vsb_cat(sb, "void VRT_l_resp_proto(const struct sess *, const char *, ...);\n"); vsb_cat(sb, "int VRT_r_resp_status(const struct sess *);\n"); diff --git a/varnish-cache/lib/libvcl/vcc_string.c b/varnish-cache/lib/libvcl/vcc_string.c index 082bbd71..d7614977 100644 --- a/varnish-cache/lib/libvcl/vcc_string.c +++ b/varnish-cache/lib/libvcl/vcc_string.c @@ -69,13 +69,13 @@ vcc_regexp(struct tokenlist *tl, int sub) /*--------------------------------------------------------------------*/ static int -vcc_regsub(struct tokenlist *tl) +vcc_regsub(struct tokenlist *tl, int all) { char *p; vcc_NextToken(tl); - Fb(tl, 0, "VRT_regsub(sp, "); + Fb(tl, 0, "VRT_regsub(sp, %d, ", all); Expect(tl, '('); vcc_NextToken(tl); @@ -96,7 +96,6 @@ vcc_regsub(struct tokenlist *tl) Expect(tl, ','); vcc_NextToken(tl); - Expect(tl, CSTR); if (!vcc_StringVal(tl)) { vcc_ExpectedStringval(tl); return (0); @@ -129,7 +128,9 @@ vcc_StringVal(struct tokenlist *tl) return (1); } if (tl->t->tok == ID && vcc_IdIs(tl->t, "regsub")) - return (vcc_regsub(tl)); + return (vcc_regsub(tl, 0)); + if (tl->t->tok == ID && vcc_IdIs(tl->t, "regsuball")) + return (vcc_regsub(tl, 1)); if (tl->t->tok == VAR) { vp = vcc_FindVar(tl, tl->t, vcc_vars); if (tl->err) diff --git a/varnish-cache/man/vcl.7 b/varnish-cache/man/vcl.7 index 414c865e..387b23a8 100644 --- a/varnish-cache/man/vcl.7 +++ b/varnish-cache/man/vcl.7 @@ -122,7 +122,7 @@ The following built-in functions are available: .It Fn regsub "str" "regex" "sub" Returns a copy of .Fa str -with all occurrences of the regular expression +with the first occurrence of the regular expression .Fa regex replaced with .Fa sub . @@ -136,6 +136,10 @@ is replaced with the entire matched string, and is replaced with the contents of subgroup .Ar n in the matched string. +.It Fn regsuball "str" "regex" "sub" +As +.Fn regsuball +but this replaces all occurrences. .It Fn purge_hash "regex" Purge all objects in cache whose hash strings match .Fa regex .