home *** CD-ROM | disk | FTP | other *** search
- /*
- l_name.c
- */
- /* Copyright (c) 1994 Christian F. Tschudin. All rights reserved.
-
- Distributed under the terms of the GNU General Public License
- version 2 of june 1991 as published by the Free Software
- Foundation, Inc.
-
- This file is part of M0.
-
- M0 is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY. No author or distributor accepts responsibility to anyone for
- the consequences of using it or for whether it serves any particular
- purpose or works at all, unless he says so in writing. Refer to the GNU
- General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute M0, but
- only under the conditions described in the GNU General Public License.
- A copy of this license is supposed to have been given to you along with
- M0 so you can know your rights and responsibilities. It should be in a
- file named LICENSE. Among other things, the copyright notice and this
- notice must be preserved on all copies. */
-
- #include "l_proto.h"
-
-
- #define HASHTABSIZE 401
-
- static eindex hash_tab[HASHTABSIZE];
- static eindex one_char_name['~' - ' '];
-
- ushort hash(byteptr s, uint len)
- {
- ushort h = 0;
-
- while (len>0) {
- if (len--%2)
- h ^= *s++ << 8;
- else
- h ^= *s++;
- }
- return h % HASHTABSIZE;
- }
-
-
- /*
- always increments the ref count, even if the name already existed
- */
- eindex
- name_add(byteptr s, uint len, byte attr)
- {
- eindex ei;
- eptr ep;
- ushort h;
-
- if (len == 1) {
- ei = one_char_name[*s - ' ' - 1];
- if (!ei) {
- ei = new_element(0, T_NAME);
- ep = gaddr(ei);
-
- eplen(ep) = 1;
- epattr(ep) = attr;
- ep->V.nam.u.n[0] = *s;
- one_char_name[*s - ' ' - 1] = ei;
- } else
- increfp(gaddr(ei));
- return ei;
- }
- h = hash(s, len);
- ei = hash_tab[h];
- while (ei) {
- ep = gaddr(ei);
- if (eplen(ep) == len && eptype(ep) == T_NAME) {
- byteptr cp = (len<=SHORTNAMELEN) ? ep->V.nam.u.n : ep->V.nam.u.s;
- if (memcmp((char*)cp,(char*)s,len) == 0) {
- increfp(ep);
- return ei;
- }
- }
- ei = ep->V.nam.next;
- }
- ei = new_element(0, T_NAME);
- ep = gaddr(ei);
- eplen(ep) = len;
- epattr(ep) = attr;
- ep->V.nam.next = hash_tab[h];
- hash_tab[h] = ei;
- if (len <= SHORTNAMELEN)
- memcpy((char*)(ep->V.nam.u.n), (char*)s, len);
- else {
- ep->V.nam.u.s = (byteptr) malloc(len);
- memcpy((char*)(ep->V.nam.u.s), (char*)s, len);
- }
- TRACE(4,printf("adding name %d\n", ei))
-
- return ei;
- }
-
-
- int
- name_eq(eindex n1, eindex n2)
- {
-
- return desub(0, n1) == desub(0, n2) ? 1 : 0;
- }
-
-
- eindex
- key_add(byteptr k)
- {
- eindex ei;
- eptr ep;
- ushort h;
-
- h = hash(k, 8);
- ei = hash_tab[h];
- while (ei) {
- ep = gaddr(ei);
- if (eptype(ep) == T_KEY) {
- if (memcmp((char*)(ep->V.nam.u.s), (char*)k, 8) == 0) {
- increfp(ep);
- return ei;
- }
- }
- ei = ep->V.nam.next;
- }
- ei = new_element(0, T_KEY);
- ep = gaddr(ei);
- eplen(ep) = 8;
- ep->V.nam.next = hash_tab[h];
- hash_tab[h] = ei;
- ep->V.nam.u.s = (byteptr) malloc(8);
- memcpy((char*)(ep->V.nam.u.s), (char*)k, 8);
-
- TRACE(4, printf("adding key %d\n", ei))
-
- return ei;
- }
-
-
- int
- key_eq(eindex k1, eindex k2)
- {
-
- return desub(0, k1) == desub(0, k2) ? 1 : 0;
- }
-
-
- void
- free_name(eindex ei)
- {
- eptr ep = gaddr(ei);
- ushort h;
-
- TRACE(4, printf("freeing name %d (%d)\n", ei, eplen(ep)))
-
- if (eplen(ep) == 1) {
- one_char_name[ep->V.nam.u.n[0] - ' ' - 1] = 0;
- eptype(ep) = T_EMPTY;
- return;
- }
-
- if (eplen(ep) > SHORTNAMELEN) {
- h = hash(ep->V.nam.u.s, eplen(ep));
- free((char*)(ep->V.nam.u.s));
- } else
- h = hash(ep->V.nam.u.n, eplen(ep));
- if (hash_tab[h] == ei)
- hash_tab[h] = ep->V.nam.next;
- else {
- eindex e = hash_tab[h];
- while (e && gaddr(e)->V.nam.next!=ei)
- e = gaddr(e)->V.nam.next;
- if (!e)
- fprintf(stderr,
- " ## *** internal error: empty hash chain while freeing name %d (%d)\n",
- ei, eplen(ep));
- else
- gaddr(e)->V.nam.next = ep->V.nam.next;
- }
- eptype(ep) = T_EMPTY;
- return;
- }
-