env: re-add support for auto-completion
authorMike Frysinger <vapier@gentoo.org>
Fri, 17 Dec 2010 21:51:59 +0000 (16:51 -0500)
committerWolfgang Denk <wd@denx.de>
Sun, 9 Jan 2011 16:57:37 +0000 (17:57 +0100)
Currently, only basic completion is supported (no globs), but this is
what we had previously.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
common/command.c
common/env_common.c
include/common.h
include/search.h
lib/hashtable.c
lib/qsort.c

index ef4a081..b3ec510 100644 (file)
@@ -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;
 }
 
index ae710e5..c3e6388 100644 (file)
@@ -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;
 }
index 0d1c872..d8c912d 100644 (file)
@@ -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);
index 81ced7f..a7c1293 100644 (file)
@@ -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);
 
index b47f3b6..9f069c0 100644 (file)
@@ -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)
 {
index e771dcf..1cc0d31 100644 (file)
@@ -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);
+}