MEDIUM: pattern: add prune function

This path add specific pointer to each expression to point on prune
function. Now, each pattern expression embed his own prune function.
diff --git a/include/proto/pattern.h b/include/proto/pattern.h
index 63e02e7..1424820 100644
--- a/include/proto/pattern.h
+++ b/include/proto/pattern.h
@@ -89,6 +89,16 @@
 
 /*
  *
+ * The following functions clean all entries of a pattern expression and
+ * reset the tree and list root.
+ *
+ */
+void pat_prune_val(struct pattern_expr *expr);
+void pat_prune_ptr(struct pattern_expr *expr);
+void pat_prune_reg(struct pattern_expr *expr);
+
+/*
+ *
  * The following functions are general purpose pattern matching functions.
  *
  */
@@ -172,11 +182,10 @@
 struct pattern *pat_match_reg(struct sample *smp, struct pattern_expr *expr, int fill);
 
 int pattern_read_from_file(struct pattern_expr *expr, const char *filename, int patflags, char **err);
-void pattern_free(struct pattern_list *pat);
-void pattern_prune_expr(struct pattern_expr *expr);
 void pattern_init_expr(struct pattern_expr *expr);
 int pattern_lookup(const char *args, struct pattern_expr *expr, struct pattern_list **pat_elt, struct pattern_tree **idx_elt, char **err);
 int pattern_delete(const char *key, struct pattern_expr *expr, char **err);
+void pattern_prune(struct pattern_expr *expr);
 
 
 #endif
diff --git a/include/types/acl.h b/include/types/acl.h
index 96b30bd..0a89c99 100644
--- a/include/types/acl.h
+++ b/include/types/acl.h
@@ -95,6 +95,7 @@
 	int (*parse)(const char *text, struct pattern *pattern, char **err);
 	int (*index)(struct pattern_expr *expr, struct pattern *pattern, char **err);
 	void (*delete)(struct pattern_expr *expr, struct pattern *pattern);
+	void (*prune)(struct pattern_expr *expr);
 	struct pattern *(*match)(struct sample *smp, struct pattern_expr *expr, int fill);
 	/* must be after the config params */
 	struct sample_fetch *smp; /* the sample fetch we depend on */
diff --git a/include/types/pattern.h b/include/types/pattern.h
index 2224e4c..966c83e 100644
--- a/include/types/pattern.h
+++ b/include/types/pattern.h
@@ -135,7 +135,6 @@
 		char *str;              /* any string  */
 		struct my_regex *reg;   /* a compiled regex */
 	} ptr;                          /* indirect values, allocated */
-	void(*freeptrbuf)(void *ptr);	/* a destructor able to free objects from the ptr */
 	int len;                        /* data length when required  */
 	int flags;                      /* expr or pattern flags. */
 	struct sample_storage *smp;     /* used to store a pointer to sample value associated
@@ -158,6 +157,7 @@
 	int (*parse)(const char *text, struct pattern *pattern, char **err);
 	int (*index)(struct pattern_expr *, struct pattern *, char **);
 	void (*delete)(struct pattern_expr *, struct pattern *);
+	void (*prune)(struct pattern_expr *);
 	struct pattern *(*match)(struct sample *, struct pattern_expr *, int);
 	struct list patterns;         /* list of acl_patterns */
 	struct eb_root pattern_tree;  /* may be used for lookup in large datasets */
@@ -168,6 +168,7 @@
 extern int (*pat_parse_fcts[PAT_MATCH_NUM])(const char *, struct pattern *, char **);
 extern int (*pat_index_fcts[PAT_MATCH_NUM])(struct pattern_expr *, struct pattern *, char **);
 extern void (*pat_delete_fcts[PAT_MATCH_NUM])(struct pattern_expr *, struct pattern *);
+void (*pat_prune_fcts[PAT_MATCH_NUM])(struct pattern_expr *);
 extern struct pattern *(*pat_match_fcts[PAT_MATCH_NUM])(struct sample *, struct pattern_expr *, int);
 extern int pat_match_types[PAT_MATCH_NUM];
 
diff --git a/src/acl.c b/src/acl.c
index 0356ca0..c424189 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -106,7 +106,7 @@
 {
 	struct arg *arg;
 
-	pattern_prune_expr(&expr->pat);
+	pattern_prune(&expr->pat);
 
 	for (arg = expr->smp->arg_p; arg; arg++) {
 		if (arg->type == ARGT_STOP)
@@ -355,6 +355,7 @@
 	expr->pat.index = aclkw ? aclkw->index : NULL;
 	expr->pat.match = aclkw ? aclkw->match : NULL;
 	expr->pat.delete = aclkw ? aclkw->delete : NULL;
+	expr->pat.prune = aclkw ? aclkw->prune : NULL;
 	expr->smp = smp;
 	smp = NULL;
 
@@ -367,6 +368,7 @@
 			expr->pat.index = pat_index_fcts[PAT_MATCH_BOOL];
 			expr->pat.match = pat_match_fcts[PAT_MATCH_BOOL];
 			expr->pat.delete = pat_delete_fcts[PAT_MATCH_BOOL];
+			expr->pat.prune = pat_prune_fcts[PAT_MATCH_BOOL];
 			break;
 		case SMP_T_SINT:
 		case SMP_T_UINT:
@@ -374,6 +376,7 @@
 			expr->pat.index = pat_index_fcts[PAT_MATCH_INT];
 			expr->pat.match = pat_match_fcts[PAT_MATCH_INT];
 			expr->pat.delete = pat_delete_fcts[PAT_MATCH_INT];
+			expr->pat.prune = pat_prune_fcts[PAT_MATCH_INT];
 			break;
 		case SMP_T_IPV4:
 		case SMP_T_IPV6:
@@ -381,6 +384,7 @@
 			expr->pat.index = pat_index_fcts[PAT_MATCH_IP];
 			expr->pat.match = pat_match_fcts[PAT_MATCH_IP];
 			expr->pat.delete = pat_delete_fcts[PAT_MATCH_IP];
+			expr->pat.prune = pat_prune_fcts[PAT_MATCH_IP];
 			break;
 		}
 	}
@@ -442,6 +446,7 @@
 			expr->pat.index = pat_index_fcts[idx];
 			expr->pat.match = pat_match_fcts[idx];
 			expr->pat.delete = pat_delete_fcts[idx];
+			expr->pat.prune = pat_prune_fcts[idx];
 			args++;
 		}
 		else if ((*args)[1] == '-') {
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 836ad30..ddba615 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -1208,7 +1208,7 @@
 			/* clear all maps */
 			list_for_each_entry(mdesc, &mref->maps, list)
 				if (mdesc->do_free)
-					pattern_prune_expr(mdesc->pat);
+					mdesc->pat->prune(mdesc->pat);
 
 			/* clear map reference */
 			list_for_each_entry_safe(ent, nent, &mref->entries, list) {
diff --git a/src/map.c b/src/map.c
index 25052fd..0f2db28 100644
--- a/src/map.c
+++ b/src/map.c
@@ -413,6 +413,7 @@
 		desc->pat->parse = pat_parse_fcts[conv->private];
 		desc->pat->index = pat_index_fcts[conv->private];
 		desc->pat->delete = pat_delete_fcts[conv->private];
+		desc->pat->prune = pat_prune_fcts[conv->private];
 
 		/* parse each line of the file */
 		list_for_each_entry(ent, &ref->entries, list)
diff --git a/src/pattern.c b/src/pattern.c
index 796384d..170955f 100644
--- a/src/pattern.c
+++ b/src/pattern.c
@@ -88,6 +88,22 @@
 	[PAT_MATCH_REG]   = pat_del_list_reg,
 };
 
+void (*pat_prune_fcts[PAT_MATCH_NUM])(struct pattern_expr *) = {
+	[PAT_MATCH_FOUND] = pat_prune_val,
+	[PAT_MATCH_BOOL]  = pat_prune_val,
+	[PAT_MATCH_INT]   = pat_prune_val,
+	[PAT_MATCH_IP]    = pat_prune_val,
+	[PAT_MATCH_BIN]   = pat_prune_ptr,
+	[PAT_MATCH_LEN]   = pat_prune_val,
+	[PAT_MATCH_STR]   = pat_prune_ptr,
+	[PAT_MATCH_BEG]   = pat_prune_ptr,
+	[PAT_MATCH_SUB]   = pat_prune_ptr,
+	[PAT_MATCH_DIR]   = pat_prune_ptr,
+	[PAT_MATCH_DOM]   = pat_prune_ptr,
+	[PAT_MATCH_END]   = pat_prune_ptr,
+	[PAT_MATCH_REG]   = pat_prune_reg,
+};
+
 struct pattern *(*pat_match_fcts[PAT_MATCH_NUM])(struct sample *, struct pattern_expr *, int) = {
 	[PAT_MATCH_FOUND] = NULL,
 	[PAT_MATCH_BOOL]  = pat_match_nothing,
@@ -131,12 +147,6 @@
  *
  */
 
-/* Free data allocated by pat_parse_reg */
-static void pat_free_reg(void *ptr)
-{
-	regex_free(ptr);
-}
-
 /* Background: Fast way to find a zero byte in a word
  * http://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
  * hasZeroByte = (v - 0x01010101UL) & ~v & 0x80808080UL;
@@ -222,7 +232,6 @@
 
 	pattern->ptr.reg = (struct my_regex *)trash->str;
 	pattern->ptr.reg->regstr = (char *)text;
-	pattern->freeptrbuf = NULL;
 
 	pattern->expect_type = SMP_T_STR;
 	return 1;
@@ -914,30 +923,6 @@
 	return NULL;
 }
 
-/* NB: does nothing if <pat> is NULL */
-void pattern_free(struct pattern_list *pat)
-{
-	if (!pat)
-		return;
-
-	if (pat->pat.ptr.ptr) {
-		if (pat->pat.freeptrbuf)
-			pat->pat.freeptrbuf(pat->pat.ptr.ptr);
-
-		free(pat->pat.ptr.ptr);
-	}
-
-	free(pat->pat.smp);
-	free(pat);
-}
-
-void free_pattern_list(struct list *head)
-{
-	struct pattern_list *pat, *tmp;
-	list_for_each_entry_safe(pat, tmp, head, list)
-		pattern_free(pat);
-}
-
 void free_pattern_tree(struct eb_root *root)
 {
 	struct eb_node *node, *next;
@@ -954,14 +939,50 @@
 	}
 }
 
-void pattern_prune_expr(struct pattern_expr *expr)
+void pat_prune_val(struct pattern_expr *expr)
 {
-	free_pattern_list(&expr->patterns);
+	struct pattern_list *pat, *tmp;
+
+	list_for_each_entry_safe(pat, tmp, &expr->patterns, list) {
+		free(pat->pat.smp);
+		free(pat);
+	}
+
 	free_pattern_tree(&expr->pattern_tree);
 	free_pattern_tree(&expr->pattern_tree_2);
 	LIST_INIT(&expr->patterns);
 }
 
+void pat_prune_ptr(struct pattern_expr *expr)
+{
+	struct pattern_list *pat, *tmp;
+
+	list_for_each_entry_safe(pat, tmp, &expr->patterns, list) {
+		free(pat->pat.ptr.ptr);
+		free(pat->pat.smp);
+		free(pat);
+	}
+
+	free_pattern_tree(&expr->pattern_tree);
+	free_pattern_tree(&expr->pattern_tree_2);
+	LIST_INIT(&expr->patterns);
+}
+
+void pat_prune_reg(struct pattern_expr *expr)
+{
+	struct pattern_list *pat, *tmp;
+
+	list_for_each_entry_safe(pat, tmp, &expr->patterns, list) {
+		regex_free(pat->pat.ptr.ptr);
+		free(pat->pat.smp);
+		free(pat);
+	}
+
+	free_pattern_tree(&expr->pattern_tree);
+	free_pattern_tree(&expr->pattern_tree_2);
+	LIST_INIT(&expr->patterns);
+}
+
 void pattern_init_expr(struct pattern_expr *expr)
 {
 	LIST_INIT(&expr->patterns);
@@ -1080,9 +1101,6 @@
 		return 0;
 	}
 
-	/* free pattern method */
-	patl->pat.freeptrbuf = &pat_free_reg;
-
 	/* chain pattern in the expression */
 	LIST_ADDQ(&expr->patterns, &patl->list);
 
@@ -1502,6 +1520,12 @@
 	return expr->match(smp, expr, fill);
 }
 
+/* This function prune the pattern expression. */
+void pattern_prune(struct pattern_expr *expr)
+{
+	expr->prune(expr);
+}
+
 /* This function search all the pattern matching the <key> and delete it.
  * If the parsing of the input key fails, the function returns 0 and the
  * <err> is filled, else return 1;
diff --git a/src/payload.c b/src/payload.c
index 42468ec..82efe95 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -681,13 +681,13 @@
  * Please take care of keeping this list alphabetically sorted.
  */
 static struct acl_kw_list acl_kws = {ILH, {
-	{ "payload",            "req.payload",        pat_parse_bin,        pat_idx_list_ptr, pat_del_list_ptr, pat_match_bin },
-	{ "payload_lv",         "req.payload_lv",     pat_parse_bin,        pat_idx_list_ptr, pat_del_list_ptr, pat_match_bin },
-	{ "req_rdp_cookie",     "req.rdp_cookie",     pat_parse_str,        pat_idx_tree_str, pat_del_tree_str, pat_match_str },
-	{ "req_rdp_cookie_cnt", "req.rdp_cookie_cnt", pat_parse_int,        pat_idx_list_val, pat_del_list_val, pat_match_int },
-	{ "req_ssl_sni",        "req.ssl_sni",        pat_parse_str,        pat_idx_tree_str, pat_del_tree_str, pat_match_str },
-	{ "req_ssl_ver",        "req.ssl_ver",        pat_parse_dotted_ver, pat_idx_list_val, pat_del_list_val, pat_match_int },
-	{ "req.ssl_ver",        "req.ssl_ver",        pat_parse_dotted_ver, pat_idx_list_val, pat_del_list_val, pat_match_int },
+	{ "payload",            "req.payload",        pat_parse_bin,        pat_idx_list_ptr, pat_del_list_ptr, pat_prune_ptr, pat_match_bin },
+	{ "payload_lv",         "req.payload_lv",     pat_parse_bin,        pat_idx_list_ptr, pat_del_list_ptr, pat_prune_ptr, pat_match_bin },
+	{ "req_rdp_cookie",     "req.rdp_cookie",     pat_parse_str,        pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str },
+	{ "req_rdp_cookie_cnt", "req.rdp_cookie_cnt", pat_parse_int,        pat_idx_list_val, pat_del_list_val, pat_prune_val, pat_match_int },
+	{ "req_ssl_sni",        "req.ssl_sni",        pat_parse_str,        pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str },
+	{ "req_ssl_ver",        "req.ssl_ver",        pat_parse_dotted_ver, pat_idx_list_val, pat_del_list_val, pat_prune_val, pat_match_int },
+	{ "req.ssl_ver",        "req.ssl_ver",        pat_parse_dotted_ver, pat_idx_list_val, pat_del_list_val, pat_prune_val, pat_match_int },
 	{ /* END */ },
 }};
 
diff --git a/src/proto_http.c b/src/proto_http.c
index 38c0fc8..421a186 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -10391,84 +10391,84 @@
  * Please take care of keeping this list alphabetically sorted.
  */
 static struct acl_kw_list acl_kws = {ILH, {
-	{ "base",            "base",     pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_match_str  },
-	{ "base_beg",        "base",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_beg  },
-	{ "base_dir",        "base",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dir  },
-	{ "base_dom",        "base",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dom  },
-	{ "base_end",        "base",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_end  },
-	{ "base_len",        "base",     pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_match_len  },
-	{ "base_reg",        "base",     pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_match_reg  },
-	{ "base_sub",        "base",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_sub  },
+	{ "base",            "base",     pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str  },
+	{ "base_beg",        "base",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_beg  },
+	{ "base_dir",        "base",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dir  },
+	{ "base_dom",        "base",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dom  },
+	{ "base_end",        "base",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_end  },
+	{ "base_len",        "base",     pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_prune_val, pat_match_len  },
+	{ "base_reg",        "base",     pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_prune_reg, pat_match_reg  },
+	{ "base_sub",        "base",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_sub  },
 
-	{ "cook",            "req.cook", pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_match_str  },
-	{ "cook_beg",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_beg  },
-	{ "cook_dir",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dir  },
-	{ "cook_dom",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dom  },
-	{ "cook_end",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_end  },
-	{ "cook_len",        "req.cook", pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_match_len  },
-	{ "cook_reg",        "req.cook", pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_match_reg  },
-	{ "cook_sub",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_sub  },
+	{ "cook",            "req.cook", pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str  },
+	{ "cook_beg",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_beg  },
+	{ "cook_dir",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dir  },
+	{ "cook_dom",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dom  },
+	{ "cook_end",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_end  },
+	{ "cook_len",        "req.cook", pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_prune_val, pat_match_len  },
+	{ "cook_reg",        "req.cook", pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_prune_reg, pat_match_reg  },
+	{ "cook_sub",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_sub  },
 
-	{ "hdr",             "req.hdr",  pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_match_str  },
-	{ "hdr_beg",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_beg  },
-	{ "hdr_dir",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dir  },
-	{ "hdr_dom",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dom  },
-	{ "hdr_end",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_end  },
-	{ "hdr_len",         "req.hdr",  pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_match_len  },
-	{ "hdr_reg",         "req.hdr",  pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_match_reg  },
-	{ "hdr_sub",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_sub  },
+	{ "hdr",             "req.hdr",  pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str  },
+	{ "hdr_beg",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_beg  },
+	{ "hdr_dir",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dir  },
+	{ "hdr_dom",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dom  },
+	{ "hdr_end",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_end  },
+	{ "hdr_len",         "req.hdr",  pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_prune_val, pat_match_len  },
+	{ "hdr_reg",         "req.hdr",  pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_prune_reg, pat_match_reg  },
+	{ "hdr_sub",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_sub  },
 
-	{ "http_auth_group", NULL,       pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_auth },
+	{ "http_auth_group", NULL,       pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_auth },
 
-	{ "method",          NULL,       pat_parse_meth, pat_idx_list_str, pat_del_meth,   pat_match_meth },
+	{ "method",          NULL,       pat_parse_meth, pat_idx_list_str, pat_del_meth,   pat_prune_ptr, pat_match_meth },
 
-	{ "path",            "path",     pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_match_str  },
-	{ "path_beg",        "path",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_beg  },
-	{ "path_dir",        "path",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dir  },
-	{ "path_dom",        "path",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dom  },
-	{ "path_end",        "path",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_end  },
-	{ "path_len",        "path",     pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_match_len  },
-	{ "path_reg",        "path",     pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_match_reg  },
-	{ "path_sub",        "path",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_sub  },
+	{ "path",            "path",     pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str  },
+	{ "path_beg",        "path",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_beg  },
+	{ "path_dir",        "path",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dir  },
+	{ "path_dom",        "path",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dom  },
+	{ "path_end",        "path",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_end  },
+	{ "path_len",        "path",     pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_prune_val, pat_match_len  },
+	{ "path_reg",        "path",     pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_prune_reg, pat_match_reg  },
+	{ "path_sub",        "path",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_sub  },
 
-	{ "req_ver",         "req.ver",  pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_match_str  },
-	{ "resp_ver",        "res.ver",  pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_match_str  },
+	{ "req_ver",         "req.ver",  pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str  },
+	{ "resp_ver",        "res.ver",  pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str  },
 
-	{ "scook",           "res.cook", pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_match_str  },
-	{ "scook_beg",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_beg  },
-	{ "scook_dir",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dir  },
-	{ "scook_dom",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dom  },
-	{ "scook_end",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_end  },
-	{ "scook_len",       "res.cook", pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_match_len  },
-	{ "scook_reg",       "res.cook", pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_match_reg  },
-	{ "scook_sub",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_sub  },
+	{ "scook",           "res.cook", pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str  },
+	{ "scook_beg",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_beg  },
+	{ "scook_dir",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dir  },
+	{ "scook_dom",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dom  },
+	{ "scook_end",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_end  },
+	{ "scook_len",       "res.cook", pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_prune_val, pat_match_len  },
+	{ "scook_reg",       "res.cook", pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_prune_reg, pat_match_reg  },
+	{ "scook_sub",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_sub  },
 
-	{ "shdr",            "res.hdr",  pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_match_str  },
-	{ "shdr_beg",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_beg  },
-	{ "shdr_dir",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dir  },
-	{ "shdr_dom",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dom  },
-	{ "shdr_end",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_end  },
-	{ "shdr_len",        "res.hdr",  pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_match_len  },
-	{ "shdr_reg",        "res.hdr",  pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_match_reg  },
-	{ "shdr_sub",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_sub  },
+	{ "shdr",            "res.hdr",  pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str  },
+	{ "shdr_beg",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_beg  },
+	{ "shdr_dir",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dir  },
+	{ "shdr_dom",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dom  },
+	{ "shdr_end",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_end  },
+	{ "shdr_len",        "res.hdr",  pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_prune_val, pat_match_len  },
+	{ "shdr_reg",        "res.hdr",  pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_prune_reg, pat_match_reg  },
+	{ "shdr_sub",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_sub  },
 
-	{ "url",             "url",      pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_match_str  },
-	{ "url_beg",         "url",      pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_beg  },
-	{ "url_dir",         "url",      pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dir  },
-	{ "url_dom",         "url",      pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dom  },
-	{ "url_end",         "url",      pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_end  },
-	{ "url_len",         "url",      pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_match_len  },
-	{ "url_reg",         "url",      pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_match_reg  },
-	{ "url_sub",         "url",      pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_sub  },
+	{ "url",             "url",      pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str  },
+	{ "url_beg",         "url",      pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_beg  },
+	{ "url_dir",         "url",      pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dir  },
+	{ "url_dom",         "url",      pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dom  },
+	{ "url_end",         "url",      pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_end  },
+	{ "url_len",         "url",      pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_prune_val, pat_match_len  },
+	{ "url_reg",         "url",      pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_prune_reg, pat_match_reg  },
+	{ "url_sub",         "url",      pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_sub  },
 
-	{ "urlp",            "urlp",     pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_match_str  },
-	{ "urlp_beg",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_beg  },
-	{ "urlp_dir",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dir  },
-	{ "urlp_dom",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_dom  },
-	{ "urlp_end",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_end  },
-	{ "urlp_len",        "urlp",     pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_match_len  },
-	{ "urlp_reg",        "urlp",     pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_match_reg  },
-	{ "urlp_sub",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_match_sub  },
+	{ "urlp",            "urlp",     pat_parse_str,  pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str  },
+	{ "urlp_beg",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_beg  },
+	{ "urlp_dir",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dir  },
+	{ "urlp_dom",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_dom  },
+	{ "urlp_end",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_end  },
+	{ "urlp_len",        "urlp",     pat_parse_int,  pat_idx_list_val, pat_del_list_val, pat_prune_val, pat_match_len  },
+	{ "urlp_reg",        "urlp",     pat_parse_reg,  pat_idx_list_reg, pat_del_list_reg, pat_prune_reg, pat_match_reg  },
+	{ "urlp_sub",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_sub  },
 
 	{ /* END */ },
 }};
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index d71ed95..fedcb46 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -3546,31 +3546,31 @@
  * Please take care of keeping this list alphabetically sorted.
  */
 static struct acl_kw_list acl_kws = {ILH, {
-	{ "ssl_c_i_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_c_key_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_c_notafter",         NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_c_notbefore",        NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_c_sig_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_c_s_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_c_serial",           NULL,         pat_parse_bin, pat_idx_list_ptr, pat_del_list_ptr, pat_match_bin     },
-	{ "ssl_f_i_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_f_key_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_f_notafter",         NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_f_notbefore",        NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_f_sig_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_f_s_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_f_serial",           NULL,         pat_parse_bin, pat_idx_list_ptr, pat_del_list_ptr, pat_match_bin     },
-	{ "ssl_fc_cipher",          NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
+	{ "ssl_c_i_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_c_key_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_c_notafter",         NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_c_notbefore",        NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_c_sig_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_c_s_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_c_serial",           NULL,         pat_parse_bin, pat_idx_list_ptr, pat_del_list_ptr, pat_prune_ptr, pat_match_bin     },
+	{ "ssl_f_i_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_f_key_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_f_notafter",         NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_f_notbefore",        NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_f_sig_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_f_s_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_f_serial",           NULL,         pat_parse_bin, pat_idx_list_ptr, pat_del_list_ptr, pat_prune_ptr, pat_match_bin     },
+	{ "ssl_fc_cipher",          NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
 #ifdef OPENSSL_NPN_NEGOTIATED
-	{ "ssl_fc_npn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
+	{ "ssl_fc_npn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
 #endif
 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
-	{ "ssl_fc_alpn",            NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
+	{ "ssl_fc_alpn",            NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
 #endif
-	{ "ssl_fc_protocol",        NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_fc_sni",             "ssl_fc_sni", pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_match_str     },
-	{ "ssl_fc_sni_end",         "ssl_fc_sni", pat_parse_str, pat_idx_list_str, pat_del_list_str, pat_match_end     },
-	{ "ssl_fc_sni_reg",         "ssl_fc_sni", pat_parse_reg, pat_idx_list_reg, pat_del_list_reg, pat_match_reg     },
+	{ "ssl_fc_protocol",        NULL,         pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_fc_sni",             "ssl_fc_sni", pat_parse_str, pat_idx_tree_str, pat_del_tree_str, pat_prune_ptr, pat_match_str     },
+	{ "ssl_fc_sni_end",         "ssl_fc_sni", pat_parse_str, pat_idx_list_str, pat_del_list_str, pat_prune_ptr, pat_match_end     },
+	{ "ssl_fc_sni_reg",         "ssl_fc_sni", pat_parse_reg, pat_idx_list_reg, pat_del_list_reg, pat_prune_reg, pat_match_reg     },
 	{ /* END */ },
 }};