Commit 1e4eb1ea authored by Geoff Simmons's avatar Geoff Simmons

Consolidate common code for .backref() and .namedref().

parent 8bdce4b5
......@@ -153,20 +153,20 @@ client c1 -repeat 2 {
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod pcre2 error: barbaz.backref.0. called without prior match$"
expect * = VCL_Error "^vmod pcre2 error: in barbaz.backref.3.: unknown substring$"
expect * = VCL_Error "^vmod pcre2 error: barbaz.backref.. called without prior match$"
expect * = VCL_Error "^vmod pcre2 error: in barbaz.backref..: unknown substring$"
expect * = VCL_Error "^vmod pcre2 error: ref .-1. out of range in barbaz.backref.. .must be >= 0 and <= 4294967295.$"
expect * = VCL_Error "^vmod pcre2 error: ref .4294967296. out of range in barbaz.backref.. .must be >= 0 and <= 4294967295.$"
expect * = VCL_Error "^vmod pcre2 error: in barbaz.backref.0.: fallback is undefined$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref.0.: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref.1.: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref.2.: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref.0.: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref.1.: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref.2.: no match$"
expect * = VCL_Error "^vmod pcre2 error: in azbc.backref.2.: requested value is not set$"
expect * = VCL_Error "^vmod pcre2 error: in foo.backref.1.: unknown substring$"
expect * = VCL_Error "^vmod pcre2 error: in foo.backref.2.: unknown substring$"
expect * = VCL_Error "^vmod pcre2 error: in foo.backref.3.: unknown substring$"
expect * = VCL_Error "^vmod pcre2 error: in barbaz.backref..: fallback is undefined$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref..: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref..: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref..: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref..: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref..: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.backref..: no match$"
expect * = VCL_Error "^vmod pcre2 error: in azbc.backref..: requested value is not set$"
expect * = VCL_Error "^vmod pcre2 error: in foo.backref..: unknown substring$"
expect * = VCL_Error "^vmod pcre2 error: in foo.backref..: unknown substring$"
expect * = VCL_Error "^vmod pcre2 error: in foo.backref..: unknown substring$"
expect * = End
} -run
......@@ -158,14 +158,14 @@ client c1 -repeat 2 {
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod pcre2 error: barbaz.namedref.bar. called without prior match$"
expect * = VCL_Error "^vmod pcre2 error: in barbaz.namedref.quux.: unknown substring$"
expect * = VCL_Error "^vmod pcre2 error: barbaz.namedref.. called without prior match$"
expect * = VCL_Error "^vmod pcre2 error: in barbaz.namedref..: unknown substring$"
expect * = VCL_Error "^vmod pcre2 error: in barbaz.namedref..: fallback is undefined$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.namedref.frob.: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.namedref.nitz.: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.namedref.frob.: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.namedref.nitz.: no match$"
expect * = VCL_Error "^vmod pcre2 error: in azbc.namedref.z.: requested value is not set$"
expect * = VCL_Error "^vmod pcre2 error: in foo.backref.3.: unknown substring$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.namedref..: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.namedref..: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.namedref..: no match$"
expect * = VCL_Error "^vmod pcre2 error: in frobnitz.namedref..: no match$"
expect * = VCL_Error "^vmod pcre2 error: in azbc.namedref..: requested value is not set$"
expect * = VCL_Error "^vmod pcre2 error: in foo.backref..: unknown substring$"
expect * = End
} -run
......@@ -86,6 +86,11 @@ struct match_call {
uint32_t options;
};
enum ref_e {
NUMBERED = 0,
NAMED = 1,
};
static int have_jit = 0;
void
......@@ -196,6 +201,69 @@ match_call_free(void *priv)
FREE_OBJ(mctx_call);
}
static inline VCL_STRING
refer(VRT_CTX, VCL_INT ref, VCL_STRING restrict const name,
VCL_STRING restrict const fallback, const enum ref_e reftype,
const struct vmod_priv * restrict const match_task,
const char * restrict const context, const char * restrict const caller,
const char * restrict const default_fallback)
{
pcre2_match_data *mdata;
PCRE2_UCHAR *buf;
PCRE2_SIZE len;
int ret = PCRE2_ERROR_UNAVAILABLE;
char *msg = NULL;
uintptr_t snap;
AN(match_task);
if (fallback == NULL) {
VERR(ctx, "in %s.%s(): fallback is undefined", context, caller);
return default_fallback;
}
if (match_task->priv == NULL) {
VERR(ctx, "%s.%s() called without prior match", context,
caller);
return fallback;
}
WS_Assert_Allocated(ctx->ws, match_task->priv, 0);
mdata = match_task->priv;
switch (reftype) {
case NUMBERED:
CHECK_UINT32_RANGE(ref, context, ".backref()", fallback);
ret = pcre2_substring_get_bynumber(mdata, (uint32_t)ref, &buf,
&len);
break;
case NAMED:
if (name == NULL) {
VERR(ctx, "in %s.%s(<undefined>): name is undefined",
context, caller);
return fallback;
}
ret = pcre2_substring_get_byname(mdata, (PCRE2_SPTR)name, &buf,
&len);
}
if (ret == 0) {
WS_Assert_Allocated(ctx->ws, buf, len + 1);
return (VCL_STRING)buf;
}
/*
* This error is returned when the ovector was too small, cannot
* happen after using pcre2_match_data_create_from_pattern() to
* get the match data block.
*/
assert(ret != PCRE2_ERROR_UNAVAILABLE);
snap = WS_Snapshot(ctx->ws);
if ((msg = WS_Printf(ctx->ws, "in %s.%s()", context, caller)) == NULL)
msg = "";
report_pcre2_err(ctx, ret, msg, "");
WS_Reset(ctx->ws, snap);
return fallback;
}
VCL_VOID
vmod_regex__init(VRT_CTX, struct vmod_pcre2_regex **regexp,
const char *vcl_name, VCL_STRING pattern,
......@@ -523,110 +591,23 @@ VCL_STRING
vmod_regex_backref(VRT_CTX, struct vmod_pcre2_regex *regex, VCL_INT ref,
VCL_STRING fallback)
{
struct vmod_priv *match_task;
pcre2_match_data *mdata;
PCRE2_UCHAR *buf;
PCRE2_SIZE len;
int ret;
char *msg;
uintptr_t snap;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(regex, VMOD_PCRE2_REGEX_MAGIC);
if (fallback == NULL) {
VERR(ctx, "in %s.backref(%ld): fallback is undefined",
regex->vcl_name, ref);
return "**BACKREF METHOD FAILED**";
}
CHECK_UINT32_RANGE(ref, regex->vcl_name, ".backref()", fallback);
match_task = VRT_priv_task(ctx, regex);
AN(match_task);
if (match_task->priv == NULL) {
VERR(ctx, "%s.backref(%ld) called without prior match",
regex->vcl_name, ref);
return fallback;
}
WS_Assert_Allocated(ctx->ws, match_task->priv, 0);
mdata = match_task->priv;
if ((ret = pcre2_substring_get_bynumber(mdata, (uint32_t)ref, &buf,
&len)) == 0) {
WS_Assert_Allocated(ctx->ws, buf, len + 1);
return (VCL_STRING)buf;
}
/*
* This error is returned when the ovector was too small, cannot
* happen after using pcre2_match_data_create_from_pattern() to
* get the match data block.
*/
assert(ret != PCRE2_ERROR_UNAVAILABLE);
snap = WS_Snapshot(ctx->ws);
if ((msg = WS_Printf(ctx->ws, "in %s.backref(%ld)", regex->vcl_name,
ref)) == NULL)
msg = "";
report_pcre2_err(ctx, ret, msg, "");
WS_Reset(ctx->ws, snap);
return fallback;
return refer(ctx, ref, NULL, fallback, NUMBERED,
VRT_priv_task(ctx, regex), regex->vcl_name, "backref",
"**BACKREF METHOD FAILED**");
}
VCL_STRING
vmod_regex_namedref(VRT_CTX, struct vmod_pcre2_regex *regex, VCL_STRING name,
VCL_STRING fallback)
{
struct vmod_priv *match_task;
pcre2_match_data *mdata;
PCRE2_UCHAR *buf;
PCRE2_SIZE len;
int ret;
char *msg;
uintptr_t snap;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(regex, VMOD_PCRE2_REGEX_MAGIC);
if (fallback == NULL) {
VERR(ctx, "in %s.namedref(): fallback is undefined",
regex->vcl_name);
return "**NAMEDREF METHOD FAILED**";
}
if (name == NULL) {
VERR(ctx, "in %s.namedref(<undefined>): name is undefined",
regex->vcl_name);
return fallback;
}
match_task = VRT_priv_task(ctx, regex);
AN(match_task);
if (match_task->priv == NULL) {
VERR(ctx, "%s.namedref(%s) called without prior match",
regex->vcl_name, name);
return fallback;
}
WS_Assert_Allocated(ctx->ws, match_task->priv, 0);
mdata = match_task->priv;
if ((ret = pcre2_substring_get_byname(mdata, (PCRE2_SPTR)name, &buf,
&len)) == 0) {
WS_Assert_Allocated(ctx->ws, buf, len + 1);
return (VCL_STRING)buf;
}
/*
* This error is returned when the ovector was too small, cannot
* happen after using pcre2_match_data_create_from_pattern() to
* get the match data block.
*/
assert(ret != PCRE2_ERROR_UNAVAILABLE);
snap = WS_Snapshot(ctx->ws);
if ((msg = WS_Printf(ctx->ws, "in %s.namedref(%s)", regex->vcl_name,
name)) == NULL)
msg = "";
report_pcre2_err(ctx, ret, msg, "");
WS_Reset(ctx->ws, snap);
return fallback;
return refer(ctx, -1, name, fallback, NAMED, VRT_priv_task(ctx, regex),
regex->vcl_name, "namedref", "**NAMEDREF METHOD FAILED**");
}
/* Functions */
......
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