[PATCH] Introduce container_of macro

Introduce a new macro "container_of" to convert a member point to a point to
the containing struct with relative type saftey. Stolen from Linux. I'd rather
this was in a different header to "qtypes.h", but that's the best place for it
at the moment, without creating a new header.

Replace the cvar_for_completion macro and add helper functions stree_entry and
completion_entry to remove the rb_entry macro. This ends up looking a bit
neater.

diff -urN a/common/console.c head/common/console.c
--- a/common/console.c	2006-02-19 12:33:24.000000000 +1030
+++ head/common/console.c	2006-02-19 15:23:22.000000000 +1030
@@ -714,13 +714,8 @@
 Con_ShowTree_Populate(struct rb_node *n)
 {
     if (n) {
-	struct stree_node *sn;
-
 	Con_ShowTree_Populate(n->rb_left);
-
-	sn = rb_entry(n, struct stree_node, node);
-	showtree_list[showtree_idx++] = sn->string;
-
+	showtree_list[showtree_idx++] = stree_entry(n)->string;
 	Con_ShowTree_Populate(n->rb_right);
     }
 }
diff -urN a/common/shell.c head/common/shell.c
--- a/common/shell.c	2006-02-19 12:33:24.000000000 +1030
+++ head/common/shell.c	2006-02-19 15:32:53.000000000 +1030
@@ -26,6 +26,8 @@
 #include <string.h>
 
 #include "console.h"
+#include "cvar.h"
+#include "mathlib.h"
 #include "rb_tree.h"
 #include "shell.h"
 #include "sys.h"
@@ -107,14 +109,12 @@
 {
     struct rb_node **p = &root->root.rb_node;
     struct rb_node *parent = NULL;
-    struct stree_node *sn;
     unsigned int len;
     int cmp;
 
     while (*p) {
 	parent = *p;
-	sn = rb_entry(parent, struct stree_node, node);
-	cmp = strcasecmp(node->string, sn->string);
+	cmp = strcasecmp(node->string, stree_entry(parent)->string);
 	if (cmp < 0)
 	    p = &(*p)->rb_left;
 	else if (cmp > 0)
@@ -161,19 +161,15 @@
 static int
 ST_node_match(struct rb_node *n, const char *str, int min_match, int max_match)
 {
-    struct stree_node *sn;
-
     if (n) {
 	max_match = ST_node_match(n->rb_left, str, min_match, max_match);
 
 	/* How much does this node match */
-	sn = rb_entry(n, struct stree_node, node);
 	while (max_match > min_match) {
-	    if (!strncasecmp(str, sn->string, max_match))
+	    if (!strncasecmp(str, stree_entry(n)->string, max_match))
 		break;
 	    max_match--;
 	}
-
 	max_match = ST_node_match(n->rb_right, str, min_match, max_match);
     }
 
@@ -197,7 +193,7 @@
     min_match = strlen(pfx);
 
     n = root->root.rb_node;
-    sn = rb_entry(n, struct stree_node, node);
+    sn = stree_entry(n);
 
     if (root->entries == 1) {
 	match = strlen(sn->string);
@@ -233,7 +229,7 @@
     if (n) {
 	struct completion *c, *ret = NULL; /* FIXME - null right here? */
 
-	c = rb_entry(n, struct completion, rb_cmd_cache);
+	c = completion_entry(n);
 	if (!strcasecmp(str, c->string)) {
 	    ret = rb_find_exact_r(n->rb_left, str, type);
 	    if (!ret && (c->cmd_type & type))
@@ -259,7 +255,7 @@
 
     /* Do the first part iteratively */
     while (n) {
-	c = rb_entry(n, struct completion, rb_cmd_cache);
+	c = completion_entry(n);
 	cmp = strcasecmp(str, c->string);
 	if (cmp < 0)
 	    n = n->rb_left;
@@ -289,8 +285,7 @@
 
     while (*p) {
 	parent = *p;
-	c = rb_entry(parent, struct completion, rb_cmd_cache);
-
+	c = completion_entry(parent);
 	cmp = strcasecmp(str, c->string);
 	if (cmp < 0)
 	    p = &(*p)->rb_left;
@@ -337,7 +332,7 @@
     unsigned cnt = 0;
 
     if (n) {
-	struct completion *c = rb_entry(n, struct completion, rb_cmd_cache);
+	struct completion *c = completion_entry(n);
 	int cmp = strncasecmp(str, c->string, strlen(str));
 	if (cmp <= 0)
 	    cnt += rb_count_completions_r(n->rb_left, str, type);
@@ -354,7 +349,7 @@
 {
     /* do the first part iteratively */
     while (n) {
-	struct completion *c = rb_entry(n, struct completion, rb_cmd_cache);
+	struct completion *c = completion_entry(n);
 	int cmp = strncasecmp(str, c->string, strlen(str));
 	if (cmp < 0)
 	    n = n->rb_left;
@@ -370,7 +365,7 @@
 rb_find_completions_r(struct rb_node *n, const char *str, unsigned long type)
 {
     if (n) {
-	struct completion *c = rb_entry(n, struct completion, rb_cmd_cache);
+	struct completion *c = completion_entry(n);
 	int cmp = strncasecmp(str, c->string, strlen(str));
 	if (cmp <= 0)
 	    rb_find_completions_r(n->rb_left, str, type);
@@ -535,7 +530,7 @@
 int
 cvar_exists(const char *str)
 {
-    return rb_find_exact(str, CMD_CVAR, &completions);
+    return Cvar_FindVar(str) != NULL;
 }
 
 /* ------------------------------------------------------------------------ */
diff -urN a/include/cvar.h head/include/cvar.h
--- a/include/cvar.h	2006-02-19 15:16:34.000000000 +1030
+++ head/include/cvar.h	2006-02-19 14:09:18.000000000 +1030
@@ -100,8 +100,7 @@
 #define CVAR_OBSOLETE  (1U << 1) /* cvar has no effect; basically removed */
 
 /* Get a pointer to the cvar from the completion pointer */
-#define cvar_for_completion(ptr) \
-    ((cvar *)((char *)(ptr)-(unsigned long)(&((cvar *)0)->index)))
+#define cvar_for_completion(ptr) container_of(ptr, struct cvar_s, index)
 
 /*
  * register a cvar that already has the name, string, and optionally the
diff -urN a/include/qtypes.h head/include/qtypes.h
--- a/include/qtypes.h	2004-07-25 16:00:00.000000000 +0930
+++ head/include/qtypes.h	2006-02-19 13:47:33.000000000 +1030
@@ -29,4 +29,15 @@
 
 typedef enum { false, true } qboolean;
 
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:        the pointer to the member.
+ * @type:       the type of the container struct this is embedded in.
+ * @member:     the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                      \
+        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+        (type *)( (char *)__mptr - offsetof(type,member) );})
+
 #endif /* QTYPES_H */
diff -urN a/include/rb_tree.h head/include/rb_tree.h
--- a/include/rb_tree.h	2004-07-25 16:00:01.000000000 +0930
+++ head/include/rb_tree.h	2006-02-19 15:34:34.000000000 +1030
@@ -31,78 +31,6 @@
   not trivial work to rebalance the rbtree if necessary.
 
 -----------------------------------------------------------------------
-
-// FIXME - use own example here:
-
-// TYR - comments:
-//  offset - the search key
-//  inode  - the (sub)tree to search
-static inline struct page *
-rb_search_page_cache(struct inode *inode, unsigned long offset)
-{
-    struct rb_node *n = inode->i_rb_page_cache.rb_node;
-    struct page *page;
-
-    while (n) {
-        page = rb_entry(n, struct page, rb_page_cache);
-
-	if (offset < page->offset)
-	    n = n->rb_left;
-	else if (offset > page->offset)
-	    n = n->rb_right;
-	else
-	    return page;
-    }
-    return NULL;
-}
-
-// TYR - comments
-//  node - pointer to rb_node structure being inserted
-//
-/ *
- * inode  - holds root of tree, tree is a page cache
- * offset - the insertion key (maybe could have got it from:
- *            rb_entry(node, struct page, rb_page_cache)->offset (?)
- * node   - rb_node being inserted
- * /
-static inline struct page *
-__rb_insert_page_cache(struct inode *inode, unsigned long offset,
-		       struct rb_node * node)
-{
-    struct rb_node **p = &inode->i_rb_page_cache.rb_node;
-    struct rb_node *parent = NULL;
-    struct page *page;
-
-    while (*p) {
-	parent = *p;
-	page = rb_entry(parent, struct page, rb_page_cache);
-
-	if (offset < page->offset)
-	    p = &(*p)->rb_left;
-	else if (offset > page->offset)
-	    p = &(*p)->rb_right;
-	else
-	    return page;
-    }
-
-    rb_link_node(node, parent, p);
-
-    return NULL;
-}
-
-static inline struct page *
-rb_insert_page_cache(struct inode *inode, unsigned long offset,
-		     struct rb_node *node)
-{
-    struct page *ret;
-    if ((ret = __rb_insert_page_cache(inode, offset, node)))
-	goto out;
-    rb_insert_color(node, &inode->i_rb_page_cache);
- out:
-    return ret;
-}
-
------------------------------------------------------------------------
 */
 
 #ifndef	RB_TREE_H
@@ -124,8 +52,6 @@
 };
 
 #define RB_ROOT	(struct rb_root) { NULL, }
-#define	rb_entry(ptr, type, member) \
-	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
 
 /*
  *
diff -urN a/include/shell.h head/include/shell.h
--- a/include/shell.h	2006-02-19 12:33:24.000000000 +1030
+++ head/include/shell.h	2006-02-19 15:30:38.000000000 +1030
@@ -46,6 +46,9 @@
     struct rb_node node;
 };
 
+/* stree_entry - Gets the stree_node ptr from the internal rb_node ptr */
+#define stree_entry(ptr) container_of(ptr, struct stree_node, node)
+
 void STree_AllocInit(void);
 qboolean STree_Insert(struct stree_root *root, struct stree_node *node);
 qboolean STree_InsertAlloc(struct stree_root *root, const char *s,
@@ -64,6 +67,10 @@
     struct rb_node rb_cmd_cache;
 };
 
+/* completion_entry - Gets the completion ptr from the internal rb_node ptr */
+#define completion_entry(ptr) \
+	container_of(ptr, struct completion, rb_cmd_cache)
+
 /*
  * Command types
  *
