xref: /onnv-gate/usr/src/cmd/sh/hash.c (revision 527:cb400a149efa)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
22*527Schin 
23*527Schin /*
24*527Schin  * Copyright 1990 Sun Microsystems, Inc.  All rights reserved.
25*527Schin  * Use is subject to license terms.
26*527Schin  */
27*527Schin 
280Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
290Sstevel@tonic-gate /*	  All Rights Reserved  	*/
300Sstevel@tonic-gate 
310Sstevel@tonic-gate 
32*527Schin #pragma ident	"%Z%%M%	%I%	%E% SMI"
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include	"hash.h"
350Sstevel@tonic-gate #include	"defs.h"
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #define STRCMP(A, B)	(cf(A, B) != 0)
380Sstevel@tonic-gate #define FACTOR 	 		035761254233	/* Magic multiplication factor */
390Sstevel@tonic-gate #define TABLENGTH		64				/* must be multiple of 2 */
400Sstevel@tonic-gate #define LOG2LEN			6				/* log2 of TABLENGTH */
410Sstevel@tonic-gate 
420Sstevel@tonic-gate /*
430Sstevel@tonic-gate     NOTE: The following algorithm only works on machines where
440Sstevel@tonic-gate     the results of multiplying two integers is the least
450Sstevel@tonic-gate     significant part of the double word integer required to hold
460Sstevel@tonic-gate     the result.  It is adapted from Knuth, Volume 3, section 6.4.
470Sstevel@tonic-gate */
480Sstevel@tonic-gate 
490Sstevel@tonic-gate #define hash(str)		(int)(((unsigned)(crunch(str) * FACTOR)) >> shift)
500Sstevel@tonic-gate struct node
510Sstevel@tonic-gate {
520Sstevel@tonic-gate 	ENTRY item;
530Sstevel@tonic-gate 	struct node *next;
540Sstevel@tonic-gate };
550Sstevel@tonic-gate 
560Sstevel@tonic-gate static struct node	**last;
570Sstevel@tonic-gate static struct node	*next;
580Sstevel@tonic-gate static struct node 	**table;
590Sstevel@tonic-gate 
600Sstevel@tonic-gate static unsigned int 	bitsper;		/* Bits per byte */
610Sstevel@tonic-gate static unsigned int	shift;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate static unsigned int crunch();
640Sstevel@tonic-gate 
65*527Schin void
hcreate(void)66*527Schin hcreate(void)
670Sstevel@tonic-gate {
680Sstevel@tonic-gate 	unsigned char c = (unsigned char)~0;			/* A byte full of 1's */
690Sstevel@tonic-gate 	int j;
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 	table = (struct node **)alloc(TABLENGTH * sizeof(struct node *));
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 	for (j=0; j < TABLENGTH; ++j)
740Sstevel@tonic-gate 	{
750Sstevel@tonic-gate 		table[j] = 0;
760Sstevel@tonic-gate 	}
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	bitsper = 0;
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	while (c)
810Sstevel@tonic-gate 	{
820Sstevel@tonic-gate 		c = (unsigned int)c >> 1;
830Sstevel@tonic-gate 		bitsper++;
840Sstevel@tonic-gate 	}
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	shift = (bitsper * sizeof(int)) - LOG2LEN;
870Sstevel@tonic-gate }
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 
900Sstevel@tonic-gate void hscan(uscan)
910Sstevel@tonic-gate 	void	(*uscan)();
920Sstevel@tonic-gate {
930Sstevel@tonic-gate 	struct node		*p, *nxt;
940Sstevel@tonic-gate 	int				j;
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	for (j=0; j < TABLENGTH; ++j)
970Sstevel@tonic-gate 	{
980Sstevel@tonic-gate 		p = table[j];
990Sstevel@tonic-gate 		while (p)
1000Sstevel@tonic-gate 		{
1010Sstevel@tonic-gate 			nxt = p->next;
1020Sstevel@tonic-gate 			(*uscan)(&p->item);
1030Sstevel@tonic-gate 			p = nxt;
1040Sstevel@tonic-gate 		}
1050Sstevel@tonic-gate 	}
1060Sstevel@tonic-gate }
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate ENTRY *
hfind(str)1110Sstevel@tonic-gate hfind(str)
1120Sstevel@tonic-gate 	unsigned char	*str;
1130Sstevel@tonic-gate {
1140Sstevel@tonic-gate 	struct node 	*p;
1150Sstevel@tonic-gate 	struct node 	**q;
1160Sstevel@tonic-gate 	unsigned int 	i;
1170Sstevel@tonic-gate 	int 			res;
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	i = hash(str);
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	if(table[i] == 0)
1220Sstevel@tonic-gate 	{
1230Sstevel@tonic-gate 		last = &table[i];
1240Sstevel@tonic-gate 		next = 0;
1250Sstevel@tonic-gate 		return(0);
1260Sstevel@tonic-gate 	}
1270Sstevel@tonic-gate 	else
1280Sstevel@tonic-gate 	{
1290Sstevel@tonic-gate 		q = &table[i];
1300Sstevel@tonic-gate 		p = table[i];
1310Sstevel@tonic-gate 		while (p != 0 && (res = STRCMP(str, p->item.key)))
1320Sstevel@tonic-gate 		{
1330Sstevel@tonic-gate 			q = &(p->next);
1340Sstevel@tonic-gate 			p = p->next;
1350Sstevel@tonic-gate 		}
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 		if (p != 0 && res == 0)
1380Sstevel@tonic-gate 			return(&(p->item));
1390Sstevel@tonic-gate 		else
1400Sstevel@tonic-gate 		{
1410Sstevel@tonic-gate 			last = q;
1420Sstevel@tonic-gate 			next = p;
1430Sstevel@tonic-gate 			return(0);
1440Sstevel@tonic-gate 		}
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate ENTRY *
henter(item)1490Sstevel@tonic-gate henter(item)
1500Sstevel@tonic-gate 	ENTRY item;
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate 	struct node	*p = (struct node *)alloc(sizeof(struct node));
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	p->item = item;
1550Sstevel@tonic-gate 	*last = p;
1560Sstevel@tonic-gate 	p->next = next;
1570Sstevel@tonic-gate 	return(&(p->item));
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate static unsigned int
crunch(key)1620Sstevel@tonic-gate crunch(key)
1630Sstevel@tonic-gate 	unsigned char	*key;
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate 	unsigned int 	sum = 0;
1660Sstevel@tonic-gate 	int s;
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	for (s = 0; *key; s++)				/* Simply add up the bytes */
1690Sstevel@tonic-gate 		sum += *key++;
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	return(sum + s);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate 
174