5d110ab8b5c46ec5c77e071eb7b9516dda46f08e
* Copyright (c) 1992 The Regents of the University of California.
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratories.
* %sccs.include.redist.c%
* @(#)hash.c 5.1 (Berkeley) %G%
* from: $Header: hash.c,v 1.2 93/01/12 03:57:57 torek Exp $
* Interned strings are kept in a hash table. By making each string
* unique, the program can compare strings by comparing pointers.
struct hashent
*h_next
; /* hash buckets are chained */
const char *h_name
; /* the string */
u_int h_hash
; /* its hash value */
void *h_value
; /* other values (for name=value) */
size_t ht_size
; /* size (power of 2) */
u_int ht_mask
; /* == ht_size - 1 */
u_int ht_used
; /* number of entries used */
u_int ht_lim
; /* when to expand */
struct hashent
**ht_tab
; /* base of table */
static struct hashtab strings
;
* HASHFRACTION controls ht_lim, which in turn controls the average chain
* length. We allow a few entries, on average, as comparing them is usually
* cheap (the h_hash values prevent a strcmp).
#define HASHFRACTION(sz) ((sz) * 3 / 2)
/* round up to next multiple of y, where y is a power of 2 */
#define ROUND(x, y) (((x) + (y) - 1) & ~((y) - 1))
* Allocate space that will never be freed.
* Compute a `good' size to allocate via malloc.
* 16384 is a guess at a good page size for malloc;
* 32 is a guess at malloc's overhead.
alloc
= ROUND(size
+ 32, 16384) - 32;
* Initialize a new hash table. The size must be a power of 2.
register struct hashtab
*ht
;
register struct hashent
**h
;
h
= emalloc(sz
* sizeof *h
);
ht
->ht_lim
= HASHFRACTION(sz
);
* Expand an existing hash table.
register struct hashtab
*ht
;
register struct hashent
*p
, **h
, **oldh
, *q
;
h
= emalloc(n
* sizeof *h
);
for (i
= ht
->ht_size
; i
!= 0; i
--) {
for (p
= *oldh
++; p
!= NULL
; p
= q
) {
p
->h_next
= h
[p
->h_hash
& n
];
ht
->ht_lim
= HASHFRACTION(n
);
* Make a new hash entry, setting its h_next to NULL.
static inline struct hashent
*
register struct hashent
*hp
;
m
= poolalloc(sizeof(*hp
) + ALIGNBYTES
);
hp
= (struct hashent
*)ALIGN(m
);
register const char *str
;
h
= (h
<< 5) + h
+ *str
++;
* Generate a single unique copy of the given string. We expect this
* function to be used frequently, so it should be fast.
register struct hashtab
*ht
;
register struct hashent
*hp
, **hpp
;
hpp
= &ht
->ht_tab
[h
& ht
->ht_mask
];
for (; (hp
= *hpp
) != NULL
; hpp
= &hp
->h_next
)
if (hp
->h_hash
== h
&& strcmp(hp
->h_name
, s
) == 0)
if (++ht
->ht_used
> ht
->ht_lim
)
register struct hashtab
*ht
;
ht
= emalloc(sizeof *ht
);
ht_insrep(ht
, nam
, val
, replace
)
register struct hashtab
*ht
;
register const char *nam
;
register struct hashent
*hp
, **hpp
;
hpp
= &ht
->ht_tab
[h
& ht
->ht_mask
];
for (; (hp
= *hpp
) != NULL
; hpp
= &hp
->h_next
) {
*hpp
= hp
= newhashent(nam
, h
);
register struct hashtab
*ht
;
register const char *nam
;
register struct hashent
*hp
, **hpp
;
hpp
= &ht
->ht_tab
[h
& ht
->ht_mask
];
for (; (hp
= *hpp
) != NULL
; hpp
= &hp
->h_next
)