Module Name:    src
Committed By:   rillig
Date:           Sat Oct  3 22:25:05 UTC 2020

Modified Files:
        src/usr.bin/make: hash.c

Log Message:
make(1): clean up hash table implementation

Having the hash function potentially redefined is a bit too much
flexibility.  If actually needed, this should be done using a patch, not
using the C preprocessor.

Converting the macro to a function made the control flow easier to
understand.  It also revealed that the variable p was unnecessary in
both Hash_FindEntry and Hash_CreateEntry.


To generate a diff of this commit:
cvs rdiff -u -r1.35 -r1.36 src/usr.bin/make/hash.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/hash.c
diff -u src/usr.bin/make/hash.c:1.35 src/usr.bin/make/hash.c:1.36
--- src/usr.bin/make/hash.c:1.35	Mon Sep 28 20:46:11 2020
+++ src/usr.bin/make/hash.c	Sat Oct  3 22:25:04 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: hash.c,v 1.35 2020/09/28 20:46:11 rillig Exp $	*/
+/*	$NetBSD: hash.c,v 1.36 2020/10/03 22:25:04 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -79,7 +79,7 @@
 #include "make.h"
 
 /*	"@(#)hash.c	8.1 (Berkeley) 6/6/93"	*/
-MAKE_RCSID("$NetBSD: hash.c,v 1.35 2020/09/28 20:46:11 rillig Exp $");
+MAKE_RCSID("$NetBSD: hash.c,v 1.36 2020/10/03 22:25:04 rillig Exp $");
 
 /*
  * Forward references to local procedures that are used before they're
@@ -95,22 +95,20 @@ static void RebuildTable(Hash_Table *);
 
 #define rebuildLimit 3
 
-/* The hash function(s) */
-
-#ifndef HASH
-/* The default: this one matches Gosling's emacs */
-#define HASH(h, key, p) do { \
-	for (h = 0, p = key; *p;) \
-		h = (h << 5) - h + (unsigned char)*p++; \
-	} while (0)
-
-#endif
+/* This hash function matches Gosling's emacs. */
+static unsigned int
+hash(const char *key, size_t *out_keylen)
+{
+	unsigned h = 0;
+	const char *p = key;
+	while (*p != '\0')
+		h = (h << 5) - h + (unsigned char)*p++;
+	if (out_keylen != NULL)
+		*out_keylen = (size_t)(p - key);
+	return h;
+}
 
-/* Sets up the hash table.
- *
- * Input:
- *	t		Structure to to hold the table.
- */
+/* Sets up the hash table. */
 void
 Hash_InitTable(Hash_Table *t)
 {
@@ -164,21 +162,19 @@ Hash_FindEntry(Hash_Table *t, const char
 {
 	Hash_Entry *e;
 	unsigned h;
-	const char *p;
 	int chainlen;
 
-	if (t == NULL || t->buckets == NULL) {
+	if (t == NULL || t->buckets == NULL)
 	    return NULL;
-	}
-	HASH(h, key, p);
-	p = key;
+
+	h = hash(key, NULL);
 	chainlen = 0;
 #ifdef DEBUG_HASH_LOOKUP
 	DEBUG4(HASH, "%s: %p h=%x key=%s\n", __func__, t, h, key);
 #endif
 	for (e = t->buckets[h & t->bucketsMask]; e != NULL; e = e->next) {
 		chainlen++;
-		if (e->namehash == h && strcmp(e->name, p) == 0)
+		if (e->namehash == h && strcmp(e->name, key) == 0)
 			break;
 	}
 	if (chainlen > t->maxchain)
@@ -207,8 +203,7 @@ Hash_CreateEntry(Hash_Table *t, const ch
 {
 	Hash_Entry *e;
 	unsigned h;
-	const char *p;
-	int keylen;
+	size_t keylen;
 	int chainlen;
 	struct Hash_Entry **hp;
 
@@ -216,16 +211,14 @@ Hash_CreateEntry(Hash_Table *t, const ch
 	 * Hash the key.  As a side effect, save the length (strlen) of the
 	 * key in case we need to create the entry.
 	 */
-	HASH(h, key, p);
-	keylen = p - key;
-	p = key;
+	h = hash(key, &keylen);
 	chainlen = 0;
 #ifdef DEBUG_HASH_LOOKUP
 	DEBUG4(HASH, "%s: %p h=%x key=%s\n", __func__, t, h, key);
 #endif
 	for (e = t->buckets[h & t->bucketsMask]; e != NULL; e = e->next) {
 		chainlen++;
-		if (e->namehash == h && strcmp(e->name, p) == 0) {
+		if (e->namehash == h && strcmp(e->name, key) == 0) {
 			if (newPtr != NULL)
 				*newPtr = FALSE;
 			break;
@@ -243,13 +236,14 @@ Hash_CreateEntry(Hash_Table *t, const ch
 	 */
 	if (t->numEntries >= rebuildLimit * t->bucketsSize)
 		RebuildTable(t);
+
 	e = bmake_malloc(sizeof(*e) + keylen);
 	hp = &t->buckets[h & t->bucketsMask];
 	e->next = *hp;
 	*hp = e;
 	Hash_SetValue(e, NULL);
 	e->namehash = h;
-	(void)strcpy(e->name, p);
+	(void)strcpy(e->name, key);
 	t->numEntries++;
 
 	if (newPtr != NULL)

Reply via email to