From 560d424b6d7cd4205b062ad95f1b104bd4f8bcc3 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 17 Dec 2010 16:51:59 -0500 Subject: [PATCH] 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 --- common/command.c | 3 +-- common/env_common.c | 40 +++++++++++++++------------------------- include/common.h | 1 + include/search.h | 7 +++++++ lib/hashtable.c | 20 ++++++++++++++++++++ lib/qsort.c | 6 ++++++ 6 files changed, 50 insertions(+), 27 deletions(-) diff --git a/common/command.c b/common/command.c index ef4a081..b3ec510 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..c3e6388 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 0d1c872..d8c912d 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 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) { diff --git a/lib/qsort.c b/lib/qsort.c index e771dcf..1cc0d31 100644 --- a/lib/qsort.c +++ b/lib/qsort.c @@ -16,6 +16,7 @@ * bcc and gcc. */ #include +#include #if 0 #include #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); +} -- 2.7.4