git: bec7b9a21979 - main - sh: introduce a function to iterate over all hashed commands

From: Piotr Pawel Stefaniak <pstef_at_FreeBSD.org>
Date: Tue, 12 Sep 2023 16:42:56 UTC
The branch main has been updated by pstef:

URL: https://cgit.FreeBSD.org/src/commit/?id=bec7b9a219790199c64d11833cc34d1ea505d1f4

commit bec7b9a219790199c64d11833cc34d1ea505d1f4
Author:     Piotr Pawel Stefaniak <pstef@FreeBSD.org>
AuthorDate: 2023-04-30 16:30:56 +0000
Commit:     Piotr Pawel Stefaniak <pstef@FreeBSD.org>
CommitDate: 2023-09-12 16:39:54 +0000

    sh: introduce a function to iterate over all hashed commands
    
    While aliases and built-ins are opportunistically stored in cmdtable, each
    function will be added to it immediately on definition.
    
    Factor out the hashing function, write the iterator function and make it use
    the hashing function.
    
    Add the cmdname pointer to struct cmdentry so that the command name can be
    exposed that way.
    
    Differential Revision:  https://reviews.freebsd.org/D40619
---
 bin/sh/exec.c | 46 +++++++++++++++++++++++++++++++++++++++-------
 bin/sh/exec.h |  2 ++
 2 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index 07ed6d4173ae..a3df254a39dd 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -545,6 +545,19 @@ clearcmdentry(void)
 }
 
 
+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
@@ -559,17 +572,11 @@ static struct tblentry **lastcmdentry;
 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;
@@ -588,6 +595,31 @@ cmdlookup(const char *name, int add)
 	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/exec.h b/bin/sh/exec.h
index 04d1b97d7386..493be0178272 100644
--- a/bin/sh/exec.h
+++ b/bin/sh/exec.h
@@ -53,6 +53,7 @@ struct cmdentry {
 		struct funcdef *func;
 	} u;
 	int special;
+	const char *cmdname;
 };
 
 
@@ -71,3 +72,4 @@ int unsetfunc(const char *);
 int isfunc(const char *);
 int typecmd_impl(int, char **, int, const char *);
 void clearcmdentry(void);
+const void *itercmd(const void *, struct cmdentry *);