aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2010-12-17 16:51:59 -0500
committerWolfgang Denk <wd@denx.de>2011-01-09 17:57:37 +0100
commit560d424b6d7cd4205b062ad95f1b104bd4f8bcc3 (patch)
tree5a429e36ad18a8fa2e0b026d143c38d7f3d493af
parent42df1e1618f2bcae308ad193a136b72b82103bea (diff)
env: re-add support for auto-completion
Currently, only basic completion is supported (no globs), but this is what we had previously. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r--common/command.c3
-rw-r--r--common/env_common.c40
-rw-r--r--include/common.h1
-rw-r--r--include/search.h7
-rw-r--r--lib/hashtable.c20
-rw-r--r--lib/qsort.c6
6 files changed, 50 insertions, 27 deletions
diff --git a/common/command.c b/common/command.c
index ef4a08110..b3ec510a2 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 ae710e5e6..c3e6388ac 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -246,42 +246,32 @@ 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) {
- cmdv[found++] = "...";
+ if (found >= maxv - 2 || bufsz < vallen)
break;
- }
+
cmdv[found++] = buf;
- memcpy(buf, lval, vallen); buf += vallen; bufsz -= vallen;
- *buf++ = '\0'; bufsz--;
+ memcpy(buf, match->key, vallen);
+ buf += vallen;
+ bufsz -= vallen;
}
+ qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar);
+
+ if (idx)
+ cmdv[found++] = "...";
cmdv[found] = NULL;
return found;
}
diff --git a/include/common.h b/include/common.h
index 0d1c8724a..d8c912d09 100644
--- a/include/common.h
+++ b/include/common.h
@@ -632,6 +632,7 @@ static inline IPaddr_t getenv_IPaddr (char *var)
/* lib/qsort.c */
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
+int strcmp_compar(const void *, const void *);
/* lib/time.c */
void udelay (unsigned long);
diff --git a/include/search.h b/include/search.h
index 81ced7f48..a7c129377 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 b47f3b69b..9f069c076 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)
{
diff --git a/lib/qsort.c b/lib/qsort.c
index e771dcfcf..1cc0d31c9 100644
--- a/lib/qsort.c
+++ b/lib/qsort.c
@@ -16,6 +16,7 @@
* bcc and gcc. */
#include <linux/types.h>
+#include <exports.h>
#if 0
#include <assert.h>
#else
@@ -67,3 +68,8 @@ void qsort(void *base,
} while (wgap);
}
}
+
+int strcmp_compar(const void *p1, const void *p2)
+{
+ return strcmp(*(const char **)p1, *(const char **)p2);
+}