diff --git a/bin/sh/alias.h b/bin/sh/alias.h --- a/bin/sh/alias.h +++ b/bin/sh/alias.h @@ -43,3 +43,4 @@ }; struct alias *lookupalias(const char *, int); +const struct alias *iteralias(const struct alias *); diff --git a/bin/sh/alias.c b/bin/sh/alias.c --- a/bin/sh/alias.c +++ b/bin/sh/alias.c @@ -55,7 +55,7 @@ static void setalias(const char *, const char *); static int unalias(const char *); -static struct alias **hashalias(const char *); +static size_t hashalias(const char *); static void @@ -64,7 +64,7 @@ struct alias *ap, **app; unalias(name); - app = hashalias(name); + app = &atab[hashalias(name)]; INTOFF; ap = ckmalloc(sizeof (struct alias)); ap->name = savestr(name); @@ -89,7 +89,7 @@ { struct alias *ap, **app; - app = hashalias(name); + app = &atab[hashalias(name)]; for (ap = *app; ap; app = &(ap->next), ap = ap->next) { if (equal(name, ap->name)) { @@ -147,7 +147,7 @@ if (aliases == 0) return (NULL); - for (ap = *hashalias(name); ap; ap = ap->next) { + for (ap = atab[hashalias(name)]; ap; ap = ap->next) { if (equal(name, ap->name)) { if (check && (ap->flag & ALIASINUSE)) return (NULL); @@ -244,7 +244,7 @@ return (i); } -static struct alias ** +static size_t hashalias(const char *p) { unsigned int hashval; @@ -252,5 +252,22 @@ hashval = (unsigned char)*p << 4; while (*p) hashval+= *p++; - return &atab[hashval % ATABSIZE]; + return (hashval % ATABSIZE); +} + +const struct alias * +iteralias(const struct alias *index) +{ + size_t i = 0; + + if (index != NULL) { + if (index->next != NULL) + return (index->next); + i = hashalias(index->name) + 1; + } + for (; i < ATABSIZE; i++) + if (atab[i] != NULL) + return (atab[i]); + + return (NULL); } diff --git a/bin/sh/exec.h b/bin/sh/exec.h --- a/bin/sh/exec.h +++ b/bin/sh/exec.h @@ -54,6 +54,7 @@ struct funcdef *func; } u; int special; + const char *cmdname; }; @@ -72,3 +73,4 @@ int isfunc(const char *); int typecmd_impl(int, char **, int, const char *); void clearcmdentry(void); +const void *itercmd(const void *, struct cmdentry *); diff --git a/bin/sh/exec.c b/bin/sh/exec.c --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -547,6 +547,19 @@ } +static unsigned int +hashname(const char *p) +{ + unsigned int hashval; + + hashval = (unsigned char)*p << 4; + while (*p) + hashval += *p++; + + return (hashval % CMDTABLESIZE); +} + + /* * Locate a command in the command hash table. If "add" is nonzero, * add the command to the table if it is not already present. The @@ -561,17 +574,11 @@ static struct tblentry * cmdlookup(const char *name, int add) { - unsigned int hashval; - const char *p; struct tblentry *cmdp; struct tblentry **pp; size_t len; - p = name; - hashval = (unsigned char)*p << 4; - while (*p) - hashval += *p++; - pp = &cmdtable[hashval % CMDTABLESIZE]; + pp = &cmdtable[hashname(name)]; for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { if (equal(cmdp->cmdname, name)) break; @@ -590,6 +597,31 @@ return cmdp; } +const void * +itercmd(const void *entry, struct cmdentry *result) +{ + const struct tblentry *e = entry; + size_t i = 0; + + if (e != NULL) { + if (e->next != NULL) { + e = e->next; + goto success; + } + i = hashname(e->cmdname) + 1; + } + for (; i < CMDTABLESIZE; i++) + if ((e = cmdtable[i]) != NULL) + goto success; + + return (NULL); +success: + result->cmdtype = e->cmdtype; + result->cmdname = e->cmdname; + + return (e); +} + /* * Delete the command entry returned on the last lookup. */ diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c --- a/bin/sh/histedit.c +++ b/bin/sh/histedit.c @@ -52,6 +52,8 @@ /* * Editline and history functions (and glue). */ +#include "alias.h" +#include "exec.h" #include "shell.h" #include "parser.h" #include "var.h" @@ -623,6 +625,7 @@ char **matches = NULL, **rmatches; size_t i = 0, size = 16, uniq; size_t curpos = end - start, lcstring = -1; + struct cmdentry e; in_command_completion = false; if (start > 0 || memchr("/.~", text[0], 3) != NULL) @@ -674,6 +677,24 @@ goto out; matches = rmatches; } + for (const struct alias *ap = NULL; (ap = iteralias(ap)) != NULL;) { + if (strncmp(ap->name, text, curpos) != 0) + continue; + rmatches = add_match(matches, ++i, &size, strdup(ap->name)); + if (rmatches == NULL) + goto out; + matches = rmatches; + } + for (const void *a = NULL; (a = itercmd(a, &e)) != NULL;) { + if (e.cmdtype != CMDFUNCTION) + continue; + if (strncmp(e.cmdname, text, curpos) != 0) + continue; + rmatches = add_match(matches, ++i, &size, strdup(e.cmdname)); + if (rmatches == NULL) + goto out; + matches = rmatches; + } out: free(free_path); if (i == 0) {