From b228ff91b857158933dd2162bdf872749a6b9cb8 Mon Sep 17 00:00:00 2001
From: Niels Provos <provos@gmail.com>
Date: Sat, 25 Apr 2009 00:15:31 +0000
Subject: [PATCH] remove vararg macros for accessing evrpc structs

svn:r1243
---
 ChangeLog                   |  1 +
 event_rpcgen.py             | 13 +------
 include/event2/rpc.h        | 75 +++++++++++++++++++++++++++++++++++--
 include/event2/rpc_struct.h |  4 +-
 test/regress_rpc.c          | 35 +++++++++--------
 5 files changed, 96 insertions(+), 32 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3a2384b8..edde2f3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,6 +10,7 @@ Changes in 2.0.2-alpha:
  o Make sure that an event_config's flags field is always initialized to 0. [Bug report from Victor Goya]
  o Avoid data corruption when reading data entirely into the second-to-last chain of an evbuffer. [Bug report from Victor Goya]
  o Make sendfile work on FreeBSD
+ o Do not use vararg macros for accessing evrpc structures; this is not backwards compatible, but we did not promise any backwards compatibility for the rpc code.
 
 Changes in 2.0.1-alpha:
  o free minheap on event_base_free(); from Christopher Layne
diff --git a/event_rpcgen.py b/event_rpcgen.py
index f8c7c006..cf3da6b8 100755
--- a/event_rpcgen.py
+++ b/event_rpcgen.py
@@ -1539,18 +1539,7 @@ class CCodeGenerator:
         if headerdirect:
             pre += '\n'
 
-        pre += (
-            '#define EVTAG_HAS(msg, member) ((msg)->member##_set == 1)\n'
-            '#ifdef __GNUC__\n'
-            '#define EVTAG_ASSIGN(msg, member, args...) '
-            '(*(msg)->base->member##_assign)(msg, ## args)\n'
-            '#define EVTAG_GET(msg, member, args...) '
-            '(*(msg)->base->member##_get)(msg, ## args)\n'
-            '#define EVTAG_ADD(msg, member, args...) '
-            '(*(msg)->base->member##_add)(msg, ## args)\n'
-            '#endif\n'
-            '#define EVTAG_LEN(msg, member) ((msg)->member##_length)\n'
-            )
+        pre += '#include <event2/rpc.h>'
 
         return pre
 
diff --git a/include/event2/rpc.h b/include/event2/rpc.h
index 51c38ff4..3d70f08f 100644
--- a/include/event2/rpc.h
+++ b/include/event2/rpc.h
@@ -31,7 +31,7 @@
 extern "C" {
 #endif
 
-/** @file evrpc.h
+/** @file rpc.h
  *
  * This header files provides basic support for an RPC server and client.
  *
@@ -66,6 +66,77 @@ extern "C" {
  * See the regression test for an example.
  */
 
+/**
+   Determines if the member has been set in the message
+   
+   @param msg the message to inspect
+   @param member the member variable to test for presences
+   @return 1 if it's present or 0 otherwise.
+*/
+#define EVTAG_HAS(msg, member) \
+	((msg)->member##_set == 1)
+
+/**
+   Assigns a value to the member in the message.
+
+   @param msg the message to which to assign a value
+   @param member the name of the member variable
+   @param value the value to assign
+*/
+#define EVTAG_ASSIGN(msg, member, value) \
+	(*(msg)->base->member##_assign)(msg, value)
+/**
+   Assigns a value to the member in the message.
+
+   @param msg the message to which to assign a value
+   @param member the name of the member variable
+   @param value the value to assign
+   @param len the length of the value
+*/
+#define EVTAG_ASSIGN_WITH_LEN(msg, member, value, len)	\
+	(*(msg)->base->member##_assign)(msg, value, len)
+/**
+   Returns the value for a member.
+
+   @param msg the message from which to get the value
+   @param member the name of the member variable
+   @param pvalue a pointer to the variable to hold the value
+   @return 0 on success, -1 otherwise.
+*/
+#define EVTAG_GET(msg, member, pvalue) \
+	(*(msg)->base->member##_get)(msg, pvalue)
+/**
+   Returns the value for a member.
+
+   @param msg the message from which to get the value
+   @param member the name of the member variable
+   @param pvalue a pointer to the variable to hold the value
+   @param plen a pointer to the length of the value
+   @return 0 on success, -1 otherwise.
+*/
+#define EVTAG_GET_WITH_LEN(msg, member, pvalue, plen)	\
+	(*(msg)->base->member##_get)(msg, pvalue, plen)
+
+/**
+   Adds a value to an array.
+*/
+#define EVTAG_ARRAY_ADD_VALUE(msg, member, value) \
+	(*(msg)->base->member##_add)(msg, value)
+/**
+   Allocates a new entry in the array and returns it.
+*/
+#define EVTAG_ARRAY_ADD(msg, member) \
+	(*(msg)->base->member##_add)(msg)
+/**
+   Gets a variable at the specified offset from the array.
+*/
+#define EVTAG_ARRAY_GET(msg, member, offset, pvalue)	\
+	(*(msg)->base->member##_get)(msg, offset, pvalue)
+/**
+   Returns the number of entries in the array.
+*/
+#define EVTAG_ARRAY_LEN(msg, member) ((msg)->member##_length)
+
 struct evbuffer;
 struct event_base;
 struct evrpc_req_generic;
@@ -82,8 +153,6 @@ struct evhttp_request;
 struct evrpc_status;
 struct evrpc_hook_meta;
 
-/* the structure below needs to be synchornized with evrpc_req_generic */
-
 /** Creates the definitions and prototypes for an RPC
  *
  * You need to use EVRPC_HEADER to create structures and function prototypes
diff --git a/include/event2/rpc_struct.h b/include/event2/rpc_struct.h
index a400e7ef..d7d3f46f 100644
--- a/include/event2/rpc_struct.h
+++ b/include/event2/rpc_struct.h
@@ -31,11 +31,13 @@
 extern "C" {
 #endif
 
-/** @file evrpc_struct.h
+/** @file rpc_struct.h
  *
  * This header files provides basic support for an RPC server and client.
  */
 
+/* the structure below needs to be synchronized with evrpc_req_generic */
+
 /* Encapsulates a request */
 struct evrpc {
 	TAILQ_ENTRY(evrpc) next;
diff --git a/test/regress_rpc.c b/test/regress_rpc.c
index bc68b1b8..877d227d 100644
--- a/test/regress_rpc.c
+++ b/test/regress_rpc.c
@@ -56,7 +56,8 @@
 #include "event2/event.h"
 #include "evhttp.h"
 #include "log-internal.h"
-#include "evrpc.h"
+#include "event2/rpc.h"
+#include "event2/rpc_struct.h"
 
 #include "regress.gen.h"
 
@@ -733,14 +734,14 @@ rpc_test(void)
 	EVTAG_ASSIGN(attack, weapon, "feather");
 	EVTAG_ASSIGN(attack, action, "tickle");
 	for (i = 0; i < 3; ++i) {
-		if (EVTAG_ADD(attack, how_often, i) == NULL) {
+		if (EVTAG_ARRAY_ADD_VALUE(attack, how_often, i) == NULL) {
 			tt_abort_msg("Failed to add how_often.");
 		}
 	}
 
 	evutil_gettimeofday(&tv_start, NULL);
 	for (i = 0; i < 1000; ++i) {
-		run = EVTAG_ADD(msg, run);
+		run = EVTAG_ARRAY_ADD(msg, run);
 		if (run == NULL) {
 			tt_abort_msg("Failed to add run message.");
 		}
@@ -748,16 +749,17 @@ rpc_test(void)
 		EVTAG_ASSIGN(run, fixed_bytes,
 		    (ev_uint8_t*)"012345678901234567890123");
 
-		if (EVTAG_ADD(run, notes, "this is my note") == NULL) {
+		if (EVTAG_ARRAY_ADD_VALUE(
+			    run, notes, "this is my note") == NULL) {
 			tt_abort_msg("Failed to add note.");
 		}
-		if (EVTAG_ADD(run, notes, "pps") == NULL) {
+		if (EVTAG_ARRAY_ADD_VALUE(run, notes, "pps") == NULL) {
 			tt_abort_msg("Failed to add note");
 		}
 
 		EVTAG_ASSIGN(run, large_number, 0xdead0a0bcafebeefLL);
-		EVTAG_ADD(run, other_numbers, 0xdead0a0b);
-		EVTAG_ADD(run, other_numbers, 0xbeefcafe);
+		EVTAG_ARRAY_ADD_VALUE(run, other_numbers, 0xdead0a0b);
+		EVTAG_ARRAY_ADD_VALUE(run, other_numbers, 0xbeefcafe);
 	}
 
 	if (msg_complete(msg) == -1)
@@ -791,12 +793,12 @@ rpc_test(void)
 		tt_abort_msg("Could not get attack.");
 	}
 
-	if (EVTAG_LEN(msg2, run) != i) {
+	if (EVTAG_ARRAY_LEN(msg2, run) != i) {
                 tt_abort_msg("Wrong number of run messages.");
 	}
 
 	/* get the very first run message */
-	if (EVTAG_GET(msg2, run, 0, &run) == -1) {
+	if (EVTAG_ARRAY_GET(msg2, run, 0, &run) == -1) {
 		tt_abort_msg("Failed to get run msg.");
 	} else {
 		/* verify the notes */
@@ -804,12 +806,12 @@ rpc_test(void)
 		ev_uint64_t large_number;
 		ev_uint32_t short_number;
 
-		if (EVTAG_LEN(run, notes) != 2) {
+		if (EVTAG_ARRAY_LEN(run, notes) != 2) {
 			tt_abort_msg("Wrong number of note strings.");
 		}
 
-		if (EVTAG_GET(run, notes, 0, &note_one) == -1 ||
-		    EVTAG_GET(run, notes, 1, &note_two) == -1) {
+		if (EVTAG_ARRAY_GET(run, notes, 0, &note_one) == -1 ||
+		    EVTAG_ARRAY_GET(run, notes, 1, &note_two) == -1) {
 			tt_abort_msg("Could not get note strings.");
 		}
 
@@ -823,21 +825,22 @@ rpc_test(void)
 			tt_abort_msg("Incorrrect large_number.");
 		}
 
-		if (EVTAG_LEN(run, other_numbers) != 2) {
+		if (EVTAG_ARRAY_LEN(run, other_numbers) != 2) {
 			tt_abort_msg("Wrong number of other_numbers.");
 		}
 
-		if (EVTAG_GET(run, other_numbers, 0, &short_number) == -1) {
+		if (EVTAG_ARRAY_GET(
+			    run, other_numbers, 0, &short_number) == -1) {
 			tt_abort_msg("Could not get short number.");
 		}
 		tt_uint_op(short_number, ==, 0xdead0a0b);
 
 	}
-        tt_int_op(EVTAG_LEN(attack, how_often), ==, 3);
+        tt_int_op(EVTAG_ARRAY_LEN(attack, how_often), ==, 3);
 
 	for (i = 0; i < 3; ++i) {
 		ev_uint32_t res;
-		if (EVTAG_GET(attack, how_often, i, &res) == -1) {
+		if (EVTAG_ARRAY_GET(attack, how_often, i, &res) == -1) {
 			TT_DIE(("Cannot get %dth how_often msg.", i));
 		}
 		if (res != i) {
-- 
2.40.0