[PATCH] STree_Completions

Fills the caller's stree with all the matching strings from the requested
stree. To be used for more completions work.

diff -urN a/common/shell.c head/common/shell.c
--- a/common/shell.c	2006-02-25 11:30:59.000000000 +1030
+++ head/common/shell.c	2006-02-25 11:17:36.000000000 +1030
@@ -259,10 +259,9 @@
     return 2 * Q_log2(root->entries + 1);
 }
 
-void
-STree_ForEach_Init__(struct stree_root *root, struct stree_node **n)
+static void
+STree_StackInit(struct stree_root *root)
 {
-    /* Allocate the stack */
     root->stack = Z_Malloc(sizeof(struct stree_stack));
     if (root->stack) {
 	struct stree_stack *s = root->stack;
@@ -278,6 +277,13 @@
     if (!root->stack)
 	Sys_Error("%s: not enough mem for stack! (%i)", __func__,
 		  STree_MaxDepth(root));
+}
+
+void
+STree_ForEach_Init__(struct stree_root *root, struct stree_node **n)
+{
+    /* Allocate the stack */
+    STree_StackInit(root);
 
     /* Point to the first node */
     if (root->root.rb_node)
@@ -410,6 +416,54 @@
     }
 }
 
+void
+STree_Completions(struct stree_root *out, struct stree_root *in, const char *s)
+{
+    struct stree_node *n;
+    struct rb_node *rb = NULL;
+    int cmp, len;
+
+    len = strlen(s);
+    rb = in->root.rb_node;
+
+    /* Work our way down to the subtree required */
+    while (rb) {
+	n = stree_entry(rb);
+	cmp = strncasecmp(s, n->string, len);
+	if (cmp < 0)
+	    rb = rb->rb_left;
+	if (cmp > 0)
+	    rb = rb->rb_right;
+	else
+	    break;
+    }
+
+    STree_StackInit(in);
+
+    while (rb) {
+	n = stree_entry(rb);
+	cmp = strncasecmp(s, n->string, len);
+	if (!cmp) {
+	    STree_InsertAlloc(out, n->string, false);
+	    if (rb->rb_left) {
+		if (rb->rb_right)
+		    STree_StackPush(in, rb->rb_right);
+	        rb = rb->rb_left;
+	    } else {
+		rb = rb->rb_right;
+	    }
+	} else if (cmp < 0) {
+	    rb = rb->rb_left;
+	} else {
+	    rb = rb->rb_right;
+	}
+	if (!rb && in->stack->depth > 0)
+	    rb = STree_StackPop(in);
+    }
+
+    STree_ForEach_Cleanup__(in);
+}
+
 const char **completions_list = NULL;
 static int num_completions = 0;
 
diff -urN a/include/shell.h head/include/shell.h
--- a/include/shell.h	2006-02-25 11:30:59.000000000 +1030
+++ head/include/shell.h	2006-02-25 11:16:37.000000000 +1030
@@ -73,6 +73,15 @@
 char *STree_MaxMatch(struct stree_root *root, const char *pfx);
 struct stree_node *STree_Find(struct stree_root *root, const char *s);
 
+/*
+ * Scan the source tree for completions and add them into the into the
+ * destination tree. Caller provides the root, added nodes are
+ * allocated on the temp hunk, so STree_AllocInit needs to be done by
+ * the caller.
+ */
+void STree_Completions(struct stree_root *out, struct stree_root *in,
+		       const char *s);
+
 /* Private helper functions for the STree_ForEach macro */
 void STree_ForEach_Init__(struct stree_root *root, struct stree_node **n);
 void STree_ForEach_After__(struct stree_root *root, struct stree_node **n,
