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

Mike Frysinger
2010-12-08T11:26:05Z

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(-)

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)
{
--
1.7.3.3