Commit 9636296d authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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: http://www.varnish-cache.org/svn/trunk/varnish-cache@2640 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 9aff164d
...@@ -104,12 +104,13 @@ VRT_re_test(struct vsb *sb, const char *re, int sub) ...@@ -104,12 +104,13 @@ VRT_re_test(struct vsb *sb, const char *re, int sub)
} }
const char * 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]; regmatch_t pm[10];
regex_t *t; regex_t *t;
int i, l; int i, l;
char *b, *p, *e; char *b, *p, *e;
const char *s;
unsigned u, x; unsigned u, x;
AN(re); AN(re);
...@@ -124,42 +125,48 @@ VRT_regsub(const struct sess *sp, const char *str, void *re, const char *sub) ...@@ -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 = p = b = sp->http->ws->f;
e += u; e += u;
/* Copy prefix to match */ do {
if (pm[0].rm_so > 0) { /* Copy prefix to match */
if (p + pm[0].rm_so < e) if (pm[0].rm_so > 0) {
memcpy(p, str, pm[0].rm_so); if (p + pm[0].rm_so < e)
p += pm[0].rm_so; memcpy(p, str, pm[0].rm_so);
} p += pm[0].rm_so;
}
for ( ; *sub != '\0'; sub++ ) { for (s = sub ; *s != '\0'; s++ ) {
if (*sub == '&') { if (*s == '&') {
l = pm[0].rm_eo - pm[0].rm_so; l = pm[0].rm_eo - pm[0].rm_so;
if (l > 0) { if (l > 0) {
if (p + l < e) if (p + l < e)
memcpy(p, str + pm[0].rm_so, l); memcpy(p, str + pm[0].rm_so, l);
p += 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 */ /* Copy suffix to match */
l = strlen(str + pm[0].rm_eo); l = strlen(str);
if (l > 0) { if (l > 0) {
if (p + l < e) if (p + l < e)
memcpy(p, str + pm[0].rm_eo, l); memcpy(p, str, l);
p += l; p += l;
} }
if (p + 1 < e) if (p + 1 < e)
......
...@@ -108,7 +108,7 @@ void VRT_re_init(void **, const char *, int sub); ...@@ -108,7 +108,7 @@ void VRT_re_init(void **, const char *, int sub);
void VRT_re_fini(void *); void VRT_re_fini(void *);
int VRT_re_match(const char *, void *re); int VRT_re_match(const char *, void *re);
int VRT_re_test(struct vsb *, const char *, int sub); 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); void VRT_purge(const char *, int hash);
......
...@@ -462,7 +462,7 @@ vcl_output_lang_h(struct vsb *sb) ...@@ -462,7 +462,7 @@ vcl_output_lang_h(struct vsb *sb)
vsb_cat(sb, "void VRT_re_fini(void *);\n"); 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_match(const char *, void *re);\n");
vsb_cat(sb, "int VRT_re_test(struct vsb *, const char *, int sub);\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, "\n");
vsb_cat(sb, "void VRT_purge(const char *, int hash);\n"); vsb_cat(sb, "void VRT_purge(const char *, int hash);\n");
vsb_cat(sb, "\n"); vsb_cat(sb, "\n");
...@@ -541,7 +541,7 @@ vcl_output_lang_h(struct vsb *sb) ...@@ -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, "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, "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, "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, "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, "void VRT_l_resp_proto(const struct sess *, const char *, ...);\n");
vsb_cat(sb, "int VRT_r_resp_status(const struct sess *);\n"); vsb_cat(sb, "int VRT_r_resp_status(const struct sess *);\n");
......
...@@ -69,13 +69,13 @@ vcc_regexp(struct tokenlist *tl, int sub) ...@@ -69,13 +69,13 @@ vcc_regexp(struct tokenlist *tl, int sub)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static int static int
vcc_regsub(struct tokenlist *tl) vcc_regsub(struct tokenlist *tl, int all)
{ {
char *p; char *p;
vcc_NextToken(tl); vcc_NextToken(tl);
Fb(tl, 0, "VRT_regsub(sp, "); Fb(tl, 0, "VRT_regsub(sp, %d, ", all);
Expect(tl, '('); Expect(tl, '(');
vcc_NextToken(tl); vcc_NextToken(tl);
...@@ -96,7 +96,6 @@ vcc_regsub(struct tokenlist *tl) ...@@ -96,7 +96,6 @@ vcc_regsub(struct tokenlist *tl)
Expect(tl, ','); Expect(tl, ',');
vcc_NextToken(tl); vcc_NextToken(tl);
Expect(tl, CSTR);
if (!vcc_StringVal(tl)) { if (!vcc_StringVal(tl)) {
vcc_ExpectedStringval(tl); vcc_ExpectedStringval(tl);
return (0); return (0);
...@@ -129,7 +128,9 @@ vcc_StringVal(struct tokenlist *tl) ...@@ -129,7 +128,9 @@ vcc_StringVal(struct tokenlist *tl)
return (1); return (1);
} }
if (tl->t->tok == ID && vcc_IdIs(tl->t, "regsub")) 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) { if (tl->t->tok == VAR) {
vp = vcc_FindVar(tl, tl->t, vcc_vars); vp = vcc_FindVar(tl, tl->t, vcc_vars);
if (tl->err) if (tl->err)
......
...@@ -122,7 +122,7 @@ The following built-in functions are available: ...@@ -122,7 +122,7 @@ The following built-in functions are available:
.It Fn regsub "str" "regex" "sub" .It Fn regsub "str" "regex" "sub"
Returns a copy of Returns a copy of
.Fa str .Fa str
with all occurrences of the regular expression with the first occurrence of the regular expression
.Fa regex .Fa regex
replaced with replaced with
.Fa sub . .Fa sub .
...@@ -136,6 +136,10 @@ is replaced with the entire matched string, and ...@@ -136,6 +136,10 @@ is replaced with the entire matched string, and
is replaced with the contents of subgroup is replaced with the contents of subgroup
.Ar n .Ar n
in the matched string. in the matched string.
.It Fn regsuball "str" "regex" "sub"
As
.Fn regsuball
but this replaces all occurrences.
.It Fn purge_hash "regex" .It Fn purge_hash "regex"
Purge all objects in cache whose hash strings match Purge all objects in cache whose hash strings match
.Fa regex . .Fa regex .
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment