diff mbox

[U-Boot,RFC,2/2] env: re-add support for auto-completion

Message ID 1291807565-4831-2-git-send-email-vapier@gentoo.org
State Superseded
Headers show

Commit Message

Mike Frysinger Dec. 8, 2010, 11:26 a.m. UTC
Currently, only basic completion is supported (no globs), but this is what
we had previously.  The downside is that the results are not returned in
any sorted order.  The upside is that we get any results at all.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
 common/command.c    |    3 +--
 common/env_common.c |   34 +++++++++++-----------------------
 include/search.h    |    7 +++++++
 lib/hashtable.c     |   20 ++++++++++++++++++++
 4 files changed, 39 insertions(+), 25 deletions(-)

Comments

Wolfgang Denk Dec. 17, 2010, 8:10 p.m. UTC | #1
Dear Mike Frysinger,

In message <1291807565-4831-2-git-send-email-vapier@gentoo.org> you wrote:
> Currently, only basic completion is supported (no globs), but this is what
> we had previously.  The downside is that the results are not returned in
> any sorted order.  The upside is that we get any results at all.

Why can we not collect the results and sort them like we do for "env
print" ?

Best regards,

Wolfgang Denk
Mike Frysinger Dec. 17, 2010, 8:35 p.m. UTC | #2
On Friday, December 17, 2010 15:10:14 Wolfgang Denk wrote:
> Mike Frysinger wrote:
> > Currently, only basic completion is supported (no globs), but this is
> > what we had previously.  The downside is that the results are not
> > returned in any sorted order.  The upside is that we get any results at
> > all.
> 
> Why can we not collect the results and sort them like we do for "env
> print" ?

hmm, i dont think the previous code did do any sorting.  it just relied on the 
results of the env code being sorted already.  i also dont think there is any 
support in u-boot today for sorting ?  so i'd basically have to import 
qsort(), and i didnt think the size trade off was worth while.
-mike
Wolfgang Denk Dec. 17, 2010, 8:51 p.m. UTC | #3
Dear Mike Frysinger,

In message <201012171535.08619.vapier@gentoo.org> you wrote:
>
> > Why can we not collect the results and sort them like we do for "env
> > print" ?
> 
> hmm, i dont think the previous code did do any sorting.  it just relied on the 
> results of the env code being sorted already.  i also dont think there is any 

The old code did not sort the output of pirntenv either - but the now
code does.

> support in u-boot today for sorting ?  so i'd basically have to import 
> qsort(), and i didnt think the size trade off was worth while.

Guess how printenv sorts the entries?

See lib/qsort.c

Best regards,

Wolfgang Denk
diff mbox

Patch

diff --git a/common/command.c b/common/command.c
index 0b1a3fb..aaebaca 100644
--- a/common/command.c
+++ b/common/command.c
@@ -162,7 +162,6 @@  int cmd_usage(cmd_tbl_t *cmdtp)
 
 int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[])
 {
-#if 0 /* need to reimplement */
 	static char tmp_buf[512];
 	int space;
 
@@ -173,7 +172,7 @@  int var_complete(int argc, char * const argv[], char last_char, int maxv, char *
 
 	if (!space && argc == 2)
 		return env_complete(argv[1], maxv, cmdv, sizeof(tmp_buf), tmp_buf);
-#endif
+
 	return 0;
 }
 
diff --git a/common/env_common.c b/common/env_common.c
index ae710e5..6c694c5 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -246,40 +246,28 @@  void env_relocate (void)
 	}
 }
 
-#if 0 /* need to reimplement - def CONFIG_AUTO_COMPLETE */
+#ifdef CONFIG_AUTO_COMPLETE
 int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
 {
-	int i, nxt, len, vallen, found;
-	const char *lval, *rval;
+	ENTRY *match;
+	int found, idx;
 
+	idx = 0;
 	found = 0;
 	cmdv[0] = NULL;
 
-	len = strlen(var);
-	/* now iterate over the variables and select those that match */
-	for (i=0; env_get_char(i) != '\0'; i=nxt+1) {
+	while ((idx = hmatch_r(var, idx, &match, &env_htab))) {
+		int vallen = strlen(match->key) + 1;
 
-		for (nxt=i; env_get_char(nxt) != '\0'; ++nxt)
-			;
-
-		lval = (char *)env_get_addr(i);
-		rval = strchr(lval, '=');
-		if (rval != NULL) {
-			vallen = rval - lval;
-			rval++;
-		} else
-			vallen = strlen(lval);
-
-		if (len > 0 && (vallen < len || memcmp(lval, var, len) != 0))
-			continue;
-
-		if (found >= maxv - 2 || bufsz < vallen + 1) {
+		if (found >= maxv - 2 || bufsz < vallen) {
 			cmdv[found++] = "...";
 			break;
 		}
+
 		cmdv[found++] = buf;
-		memcpy(buf, lval, vallen); buf += vallen; bufsz -= vallen;
-		*buf++ = '\0'; bufsz--;
+		memcpy(buf, match->key, vallen);
+		buf += vallen;
+		bufsz -= vallen;
 	}
 
 	cmdv[found] = NULL;
diff --git a/include/search.h b/include/search.h
index 81ced7f..a7c1293 100644
--- a/include/search.h
+++ b/include/search.h
@@ -74,6 +74,13 @@  extern void hdestroy_r(struct hsearch_data *__htab);
 extern int hsearch_r(ENTRY __item, ACTION __action, ENTRY ** __retval,
 		     struct hsearch_data *__htab);
 
+/*
+ * Search for an entry matching `MATCH'.  Otherwise, Same semantics
+ * as hsearch_r().
+ */
+extern int hmatch_r(const char *__match, int __last_idx, ENTRY ** __retval,
+		    struct hsearch_data *__htab);
+
 /* Search and delete entry matching ITEM.key in internal hash table. */
 extern int hdelete_r(const char *__key, struct hsearch_data *__htab);
 
diff --git a/lib/hashtable.c b/lib/hashtable.c
index b47f3b6..9f069c0 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -202,6 +202,26 @@  void hdestroy_r(struct hsearch_data *htab)
  *   example for functions like hdelete().
  */
 
+int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
+	     struct hsearch_data *htab)
+{
+	unsigned int idx;
+	size_t key_len = strlen(match);
+
+	for (idx = last_idx + 1; idx < htab->size; ++idx) {
+		if (!htab->table[idx].used)
+			continue;
+		if (!strncmp(match, htab->table[idx].entry.key, key_len)) {
+			*retval = &htab->table[idx].entry;
+			return idx;
+		}
+	}
+
+	__set_errno(ESRCH);
+	*retval = NULL;
+	return 0;
+}
+
 int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
 	      struct hsearch_data *htab)
 {