[PATCH] Cmd STree

Replace the linked list for the cmd_function struct with an STree. All uses of
this list were to find a specific function, so they've all been replaced by
Cmd_FindCommand. This means I was able to rip out the ->next member straight
away.

Also, constified stree_node->string in the process.

diff -urN a/NQ/cmd.c head/NQ/cmd.c
--- a/NQ/cmd.c	2006-02-19 18:44:38.000000000 +1030
+++ head/NQ/cmd.c	2006-02-19 19:23:42.000000000 +1030
@@ -409,15 +409,16 @@
 */
 
 typedef struct cmd_function_s {
-    struct cmd_function_s *next;
     const char *name;
     xcommand_t function;
     cmd_arg_f completion;
+    struct stree_node stree;
 } cmd_function_t;
 
+#define cmd_entry(ptr) container_of(ptr, struct cmd_function_s, stree)
+static DECLARE_STREE_ROOT(cmd_tree);
 
 #define	MAX_ARGS		80
-
 static int cmd_argc;
 static char *cmd_argv[MAX_ARGS];
 static char *cmd_null_string = "";
@@ -425,7 +426,6 @@
 
 cmd_source_t cmd_source;
 
-static cmd_function_t *cmd_functions;	// possible commands to execute
 
 /*
 ============
@@ -536,7 +536,18 @@
 
 }
 
-// ---------------------------------------------------------------------------
+static struct cmd_function_s *
+Cmd_FindCommand(const char *name)
+{
+    struct cmd_function_s *ret = NULL;
+    struct stree_node *n;
+
+    n = STree_Find(&cmd_tree, name);
+    if (n)
+	ret = cmd_entry(n);
+
+    return ret;
+}
 
 /*
 ============
@@ -557,19 +568,18 @@
 	return;
     }
 // fail if the command already exists
-    for (cmd = cmd_functions; cmd; cmd = cmd->next) {
-	if (!strcmp(cmd_name, cmd->name)) {
-	    Con_Printf("%s: %s already defined\n", __func__, cmd_name);
-	    return;
-	}
+    cmd = Cmd_FindCommand(cmd_name);
+    if (cmd) {
+	Con_Printf("%s: %s already defined\n", __func__, cmd_name);
+	return;
     }
 
     cmd = Hunk_Alloc(sizeof(cmd_function_t));
     cmd->name = cmd_name;
     cmd->function = function;
     cmd->completion = NULL;
-    cmd->next = cmd_functions;
-    cmd_functions = cmd;
+    cmd->stree.string = cmd->name;
+    STree_Insert(&cmd_tree, &cmd->stree);
 
     insert_command_completion(cmd_name);
 }
@@ -579,12 +589,10 @@
 {
     cmd_function_t *cmd;
 
-    for (cmd = cmd_functions; cmd; cmd = cmd->next)
-	if (!strcmp(cmd_name, cmd->name)) {
-	    cmd->completion = completion;
-	    break;
-	}
-    if (!cmd)
+    cmd = Cmd_FindCommand(cmd_name);
+    if (cmd)
+	cmd->completion = completion;
+    else
 	Sys_Error("%s: no such command - %s", __func__, cmd_name);
 }
 
@@ -596,14 +604,7 @@
 qboolean
 Cmd_Exists(char *cmd_name)
 {
-    cmd_function_t *cmd;
-
-    for (cmd = cmd_functions; cmd; cmd = cmd->next) {
-	if (!strcmp(cmd_name, cmd->name))
-	    return true;
-    }
-
-    return false;
+    return Cmd_FindCommand(cmd_name) != NULL;
 }
 
 
@@ -660,11 +661,10 @@
 	return;			// no tokens
 
 // check functions
-    for (cmd = cmd_functions; cmd; cmd = cmd->next) {
-	if (!strcasecmp(cmd_argv[0], cmd->name)) {
-	    cmd->function();
-	    return;
-	}
+    cmd = Cmd_FindCommand(cmd_argv[0]);
+    if (cmd) {
+	cmd->function();
+	return;
     }
 
 // check alias
@@ -689,13 +689,9 @@
     cmd_function_t *cmd;
     struct stree_root *root = NULL;
 
-    for (cmd = cmd_functions; cmd; cmd = cmd->next) {
-	if (!strcasecmp(name, cmd->name) && cmd->completion) {
-	    /* FIXME - STree_AllocInit? */
-	    root = cmd->completion(buf);
-	    break;
-	}
-    }
+    cmd = Cmd_FindCommand(name);
+    if (cmd)
+	root = cmd->completion(buf);
 
     return root;
 }
diff -urN a/QW/common/cmd.c head/QW/common/cmd.c
--- a/QW/common/cmd.c	2006-02-19 18:44:38.000000000 +1030
+++ head/QW/common/cmd.c	2006-02-19 19:23:52.000000000 +1030
@@ -419,22 +419,21 @@
 */
 
 typedef struct cmd_function_s {
-    struct cmd_function_s *next;
     const char *name;
     xcommand_t function;
     cmd_arg_f completion;
+    struct stree_node stree;
 } cmd_function_t;
 
+#define cmd_entry(ptr) container_of(ptr, struct cmd_function_s, stree)
+static DECLARE_STREE_ROOT(cmd_tree);
 
 #define	MAX_ARGS		80
-
 static int cmd_argc;
 static char *cmd_argv[MAX_ARGS];
 static char *cmd_null_string = "";
 static char *cmd_args = NULL;
 
-static cmd_function_t *cmd_functions;	// possible commands to execute
-
 
 /*
 ============
@@ -547,6 +546,18 @@
 
 }
 
+static struct cmd_function_s *
+Cmd_FindCommand(const char *name)
+{
+    struct cmd_function_s *ret = NULL;
+    struct stree_node *n;
+
+    n = STree_Find(&cmd_tree, name);
+    if (n)
+	ret = cmd_entry(n);
+
+    return ret;
+}
 
 /*
 ============
@@ -567,19 +578,18 @@
 	return;
     }
 // fail if the command already exists
-    for (cmd = cmd_functions; cmd; cmd = cmd->next) {
-	if (!strcmp(cmd_name, cmd->name)) {
-	    Con_Printf("%s: %s already defined\n", __func__, cmd_name);
-	    return;
-	}
+    cmd = Cmd_FindCommand(cmd_name);
+    if (cmd) {
+	Con_Printf("%s: %s already defined\n", __func__, cmd_name);
+	return;
     }
 
     cmd = Hunk_Alloc(sizeof(cmd_function_t));
     cmd->name = cmd_name;
     cmd->function = function;
     cmd->completion = NULL;
-    cmd->next = cmd_functions;
-    cmd_functions = cmd;
+    cmd->stree.string = cmd->name;
+    STree_Insert(&cmd_tree, &cmd->stree);
 
     insert_command_completion(cmd_name);
 }
@@ -589,12 +599,10 @@
 {
     cmd_function_t *cmd;
 
-    for (cmd = cmd_functions; cmd; cmd = cmd->next)
-	if (!strcmp(cmd_name, cmd->name)) {
-	    cmd->completion = completion;
-	    break;
-	}
-    if (!cmd)
+    cmd = Cmd_FindCommand(cmd_name);
+    if (cmd)
+	cmd->completion = completion;
+    else
 	Sys_Error("%s: no such command - %s", __func__, cmd_name);
 }
 
@@ -606,14 +614,7 @@
 qboolean
 Cmd_Exists(char *cmd_name)
 {
-    cmd_function_t *cmd;
-
-    for (cmd = cmd_functions; cmd; cmd = cmd->next) {
-	if (!strcmp(cmd_name, cmd->name))
-	    return true;
-    }
-
-    return false;
+    return Cmd_FindCommand(cmd_name) != NULL;
 }
 
 
@@ -696,14 +697,13 @@
 	return;			// no tokens
 
 // check functions
-    for (cmd = cmd_functions; cmd; cmd = cmd->next) {
-	if (!strcasecmp(cmd_argv[0], cmd->name)) {
-	    if (!cmd->function)
-		Cmd_ForwardToServer();
-	    else
-		cmd->function();
-	    return;
-	}
+    cmd = Cmd_FindCommand(cmd_argv[0]);
+    if (cmd) {
+	if (!cmd->function)
+	    Cmd_ForwardToServer();
+	else
+	    cmd->function();
+	return;
     }
 
 // check alias
@@ -729,13 +729,9 @@
     cmd_function_t *cmd;
     struct stree_root *root = NULL;
 
-    for (cmd = cmd_functions; cmd; cmd = cmd->next) {
-	if (!strcasecmp(name, cmd->name) && cmd->completion) {
-	    /* FIXME - STree_AllocInit? */
-	    root = cmd->completion(buf);
-	    break;
-	}
-    }
+    cmd = Cmd_FindCommand(name);
+    if (cmd)
+	root = cmd->completion(buf);
 
     return root;
 }
diff -urN a/common/shell.c head/common/shell.c
--- a/common/shell.c	2006-02-19 17:14:46.000000000 +1030
+++ head/common/shell.c	2006-02-19 19:19:10.000000000 +1030
@@ -144,14 +144,17 @@
 		  struct stree_node *n)
 {
     qboolean ret = false;
+    char *tmp;
 
     if (!n)
 	n = STree_AllocNode();
-    if (n)
-	n->string = STree_AllocString(strlen(s) + 1);
-    if (n && n->string) {
-	strcpy(n->string, s);
-	ret = STree_Insert(root, n);
+    if (n) {
+	tmp = STree_AllocString(strlen(s) + 1);
+	if (tmp) {
+	    strcpy(tmp, s);
+	    n->string = tmp;
+	    ret = STree_Insert(root, n);
+	}
     }
 
     return ret;
diff -urN a/include/shell.h head/include/shell.h
--- a/include/shell.h	2006-02-19 17:14:46.000000000 +1030
+++ head/include/shell.h	2006-02-19 19:15:10.000000000 +1030
@@ -49,7 +49,7 @@
  * the only data as well).
  */
 struct stree_node {
-    char *string;
+    const char *string;
     struct rb_node node;
 };
 
