}
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);
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)
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);
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");
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");
/*--------------------------------------------------------------------*/
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);
Expect(tl, ',');
vcc_NextToken(tl);
- Expect(tl, CSTR);
if (!vcc_StringVal(tl)) {
vcc_ExpectedStringval(tl);
return (0);
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)
.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 .
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 .