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)
}
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)
......
......@@ -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);
......
......@@ -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");
......
......@@ -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)
......
......@@ -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 .
......
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