From 69e84bcbb047c0de92d2595742d3dfa337a940d3 Mon Sep 17 00:00:00 2001
From: Dan Hirsch <thequux@upstandinghackers.com>
Date: Sat, 23 Nov 2013 13:01:55 -0600
Subject: [PATCH] Added a void* user_data pointer to HPredicate

---
 examples/dns.c          |  4 ++--
 examples/dns_common.c   |  2 +-
 examples/rr.c           |  2 +-
 src/backends/llk.c      |  2 +-
 src/backends/lr.c       |  2 +-
 src/glue.h              | 12 +++++++-----
 src/hammer.h            |  4 ++--
 src/parsers/attr_bool.c | 17 ++++++++++-------
 src/t_parser.c          |  5 +++--
 9 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/examples/dns.c b/examples/dns.c
index 5effb895..63df3a44 100644
--- a/examples/dns.c
+++ b/examples/dns.c
@@ -15,7 +15,7 @@
 // Validations
 ///
 
-bool validate_hdzero(HParseResult *p) {
+bool validate_hdzero(HParseResult *p, void* user_data) {
   if (TT_UINT != p->ast->token_type)
     return false;
   return (0 == p->ast->uint);
@@ -25,7 +25,7 @@ bool validate_hdzero(HParseResult *p) {
  * Every DNS message should have QDCOUNT entries in the question
  * section, and ANCOUNT+NSCOUNT+ARCOUNT resource records.
  */
-bool validate_message(HParseResult *p) {
+bool validate_message(HParseResult *p, void* user_data) {
   if (TT_SEQUENCE != p->ast->token_type)
     return false;
 
diff --git a/examples/dns_common.c b/examples/dns_common.c
index 3cdd04e0..bf934d61 100644
--- a/examples/dns_common.c
+++ b/examples/dns_common.c
@@ -10,7 +10,7 @@ H_ACT_APPLY(act_index0, h_act_index, 0)
 /**
  * A label can't be more than 63 characters.
  */
-bool validate_label(HParseResult *p) {
+bool validate_label(HParseResult *p, void* user_data) {
   if (TT_SEQUENCE != p->ast->token_type)
     return false;
   return (64 > p->ast->seq->used);
diff --git a/examples/rr.c b/examples/rr.c
index 4a7c4be6..c179922d 100644
--- a/examples/rr.c
+++ b/examples/rr.c
@@ -11,7 +11,7 @@
 // Validations and Semantic Actions
 ///
 
-bool validate_null(HParseResult *p) {
+bool validate_null(HParseResult *p, void* user_data) {
   if (TT_SEQUENCE != p->ast->token_type)
     return false;
   return (65536 > p->ast->seq->used);
diff --git a/src/backends/llk.c b/src/backends/llk.c
index 39ac07a6..2bc39daf 100644
--- a/src/backends/llk.c
+++ b/src/backends/llk.c
@@ -375,7 +375,7 @@ HParseResult *h_llk_parse(HAllocator* mm__, const HParser* parser, HInputStream*
       tok = (HParsedToken *)x->reshape(make_result(arena, tok), x->user_data);
 
     // call validation and semantic action, if present
-    if(x->pred && !x->pred(make_result(tarena, tok)))
+    if(x->pred && !x->pred(make_result(tarena, tok), x->user_data))
       goto no_parse;    // validation failed -> no parse
     if(x->action)
       tok = (HParsedToken *)x->action(make_result(arena, tok), x->user_data);
diff --git a/src/backends/lr.c b/src/backends/lr.c
index 3739ec9b..e7f23775 100644
--- a/src/backends/lr.c
+++ b/src/backends/lr.c
@@ -310,7 +310,7 @@ bool h_lrengine_step(HLREngine *engine, const HLRAction *action)
       value = (HParsedToken *)symbol->reshape(make_result(arena, value), symbol->user_data);
 
     // call validation and semantic action, if present
-    if(symbol->pred && !symbol->pred(make_result(tarena, value)))
+    if(symbol->pred && !symbol->pred(make_result(tarena, value), symbol->user_data))
       return false;     // validation failed -> no parse; terminate
     if(symbol->action)
       value = (HParsedToken *)symbol->action(make_result(arena, value), symbol->user_data);
diff --git a/src/glue.h b/src/glue.h
index 7486e46c..74963b06 100644
--- a/src/glue.h
+++ b/src/glue.h
@@ -58,17 +58,19 @@
 #define H_RULE(rule, def)  HParser *rule = def
 #define H_ARULE(rule, def) HParser *rule = h_action(def, act_ ## rule, NULL)
 #define H_VRULE(rule, def) HParser *rule = \
-    h_attr_bool(def, validate_ ## rule)
+    h_attr_bool(def, validate_ ## rule, NULL)
 #define H_VARULE(rule, def) HParser *rule = \
-    h_attr_bool(h_action(def, act_ ## rule, NULL), validate_ ## rule)
+    h_attr_bool(h_action(def, act_ ## rule, NULL), validate_ ## rule, NULL)
 #define H_AVRULE(rule, def) HParser *rule = \
-    h_action(h_attr_bool(def, validate_ ## rule), act_ ## rule, NULL)
+    h_action(h_attr_bool(def, validate_ ## rule, NULL), act_ ## rule, NULL)
 #define H_ADRULE(rule, def, data) HParser *rule =	\
     h_action(def, act_ ## rule, data)
+#define H_VDRULE(rule, def, data) HParser *rule =	\
+    h_attr_bool(def, validate_ ## rule, data)
 #define H_VADRULE(rule, def, data) HParser *rule =		\
-    h_attr_bool(h_action(def, act_ ## rule, data), validate_ ## rule)
+    h_attr_bool(h_action(def, act_ ## rule, data), validate_ ## rule, data)
 #define H_AVDRULE(rule, def, data) HParser *rule =		\
-    h_action(h_attr_bool(def, validate_ ## rule), act_ ## rule, data)
+    h_action(h_attr_bool(def, validate_ ## rule, data), act_ ## rule, data)
 
 
 //
diff --git a/src/hammer.h b/src/hammer.h
index bd3ae022..541e38df 100644
--- a/src/hammer.h
+++ b/src/hammer.h
@@ -120,7 +120,7 @@ typedef HParsedToken* (*HAction)(const HParseResult *p, void* user_data);
  * attr_bool() parser. It can be any (user-defined) function that takes
  * a HParseResult* and returns true or false. 
  */
-typedef bool (*HPredicate)(HParseResult *p);
+typedef bool (*HPredicate)(HParseResult *p, void* user_data);
 
 typedef struct HCFChoice_ HCFChoice;
 typedef struct HRVMProg_ HRVMProg;
@@ -515,7 +515,7 @@ HAMMER_FN_DECL(HParser*, h_length_value, const HParser* length, const HParser* v
  * 
  * Result token type: p's result type if pred succeeded, NULL otherwise.
  */
-HAMMER_FN_DECL(HParser*, h_attr_bool, const HParser* p, HPredicate pred);
+HAMMER_FN_DECL(HParser*, h_attr_bool, const HParser* p, HPredicate pred, void* user_data);
 
 /**
  * The 'and' parser asserts that a conditional syntax is satisfied, 
diff --git a/src/parsers/attr_bool.c b/src/parsers/attr_bool.c
index fc980b24..e8359ab0 100644
--- a/src/parsers/attr_bool.c
+++ b/src/parsers/attr_bool.c
@@ -4,13 +4,14 @@
 typedef struct {
   const HParser *p;
   HPredicate pred;
+  void* user_data;
 } HAttrBool;
 
 static HParseResult* parse_attr_bool(void *env, HParseState *state) {
   HAttrBool *a = (HAttrBool*)env;
   HParseResult *res = h_do_parse(a->p, state);
   if (res && res->ast) {
-    if (a->pred(res))
+    if (a->pred(res, a->user_data))
       return res;
     else
       return NULL;
@@ -42,12 +43,13 @@ static void desugar_ab(HAllocator *mm__, HCFStack *stk__, void *env) {
     } HCFS_END_SEQ();
     HCFS_THIS_CHOICE->pred = a->pred;
     HCFS_THIS_CHOICE->reshape = h_act_first;
+    HCFS_THIS_CHOICE->user_data = a->user_data;
   } HCFS_END_CHOICE();
 }
 
 static bool h_svm_action_attr_bool(HArena *arena, HSVMContext *ctx, void* arg) {
   HParseResult res;
-  HPredicate pred = arg;
+  HAttrBool *ab = arg;
   assert(ctx->stack_count >= 1);
   if (ctx->stack[ctx->stack_count-1]->token_type != TT_MARK) {
     assert(ctx->stack_count >= 2 && ctx->stack[ctx->stack_count-2]->token_type == TT_MARK);
@@ -59,7 +61,7 @@ static bool h_svm_action_attr_bool(HArena *arena, HSVMContext *ctx, void* arg) {
     res.ast = NULL;
   }
   res.arena = arena;
-  return pred(&res);
+  return ab->pred(&res, ab->user_data);
 }
 
 static bool ab_ctrvm(HRVMProg *prog, void *env) {
@@ -67,7 +69,7 @@ static bool ab_ctrvm(HRVMProg *prog, void *env) {
   h_rvm_insert_insn(prog, RVM_PUSH, 0);
   if (!h_compile_regex(prog, ab->p))
     return false;
-  h_rvm_insert_insn(prog, RVM_ACTION, h_rvm_create_action(prog, h_svm_action_attr_bool, ab->pred));
+  h_rvm_insert_insn(prog, RVM_ACTION, h_rvm_create_action(prog, h_svm_action_attr_bool, ab));
   return true;
 }
 
@@ -80,12 +82,13 @@ static const HParserVtable attr_bool_vt = {
 };
 
 
-HParser* h_attr_bool(const HParser* p, HPredicate pred) {
-  return h_attr_bool__m(&system_allocator, p, pred);
+HParser* h_attr_bool(const HParser* p, HPredicate pred, void* user_data) {
+  return h_attr_bool__m(&system_allocator, p, pred, user_data);
 }
-HParser* h_attr_bool__m(HAllocator* mm__, const HParser* p, HPredicate pred) { 
+HParser* h_attr_bool__m(HAllocator* mm__, const HParser* p, HPredicate pred, void* user_data) { 
   HAttrBool *env = h_new(HAttrBool, 1);
   env->p = p;
   env->pred = pred;
+  env->user_data = user_data;
   return h_new_parser(mm__, &attr_bool_vt, env);
 }
diff --git a/src/t_parser.c b/src/t_parser.c
index 292d1c45..12edba93 100644
--- a/src/t_parser.c
+++ b/src/t_parser.c
@@ -365,7 +365,7 @@ static void test_epsilon_p(gconstpointer backend) {
   g_check_parse_match(epsilon_p_3, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1, "(u0x61)");
 }
 
-bool validate_test_ab(HParseResult *p) {
+bool validate_test_ab(HParseResult *p, void* user_data) {
   if (TT_SEQUENCE != p->ast->token_type) 
     return false;
   if (TT_UINT != p->ast->seq->elements[0]->token_type)
@@ -377,7 +377,8 @@ bool validate_test_ab(HParseResult *p) {
 
 static void test_attr_bool(gconstpointer backend) {
   const HParser *ab_ = h_attr_bool(h_many1(h_choice(h_ch('a'), h_ch('b'), NULL)),
-				   validate_test_ab);
+				   validate_test_ab,
+				   NULL);
 
   g_check_parse_match(ab_, (HParserBackend)GPOINTER_TO_INT(backend), "aa", 2, "(u0x61 u0x61)");
   g_check_parse_match(ab_, (HParserBackend)GPOINTER_TO_INT(backend), "bb", 2, "(u0x62 u0x62)");
-- 
GitLab