|
|
1.1 root 1: static char *RCSid = "$Header: table.c,v 3.1 88/11/03 09:17:53 egisin Exp $";
2:
3: /*
4: * dynamic hashed associative table for commands and variables
5: */
6:
7: #include <stddef.h>
8: #include <stdlib.h>
9: #include <errno.h>
10: #include <setjmp.h>
11: #include "sh.h"
12: #include "table.h"
13:
14: #define INIT_TBLS 8 /* initial table size (power of 2) */
15:
16: static struct tstate {
17: int left;
18: struct tbl **next;
19: } tstate;
20:
21: static void texpand();
22:
23: unsigned int
24: hash(n)
25: register char * n;
26: {
27: register unsigned int h = 0;
28:
29: while (*n != '\0')
30: h = 2*h + *n++;
31: return h * (unsigned)32821L; /* scatter bits */
32: }
33:
34: #if 0
35: phash(s) char *s; {
36: printf("%2d: %s\n", hash(s)%32, s);
37: }
38: #endif
39:
40: void
41: tinit(tp, ap)
42: register struct table *tp;
43: register Area *ap;
44: {
45: tp->areap = ap;
46: tp->size = tp->free = 0;
47: tp->tbls = NULL;
48: }
49:
50: static void
51: texpand(tp, nsize)
52: register struct table *tp;
53: int nsize;
54: {
55: register int i;
56: register struct tbl *tblp, **p;
57: register struct tbl **ntblp, **otblp = tp->tbls;
58: int osize = tp->size;
59:
60: ntblp = alloc(sizeofN(struct tbl *, nsize), tp->areap);
61: for (i = 0; i < nsize; i++)
62: ntblp[i] = NULL;
63: tp->size = nsize;
64: tp->free = 8*nsize/10; /* table can get 80% full */
65: tp->tbls = ntblp;
66: if (otblp == NULL)
67: return;
68: for (i = 0; i < osize; i++)
69: if ((tblp = otblp[i]) != NULL)
70: if ((tblp->flag&DEFINED)) {
71: for (p = &ntblp[hash(tblp->name) & tp->size-1];
72: *p != NULL; p--)
73: if (p == ntblp) /* wrap */
74: p += tp->size;
75: *p = tblp;
76: tp->free--;
77: } else {
78: afree((Void*)tblp, tp->areap);
79: }
80: afree((Void*)otblp, tp->areap);
81: }
82:
83: struct tbl *
84: tsearch(tp, n, h)
85: register struct table *tp; /* table */
86: register char *n; /* name to enter */
87: unsigned int h; /* hash(n) */
88: {
89: register struct tbl **pp, *p;
90:
91: if (tp->size == 0)
92: return NULL;
93:
94: /* search for name in hashed table */
95: for (pp = &tp->tbls[h & tp->size-1]; (p = *pp) != NULL; pp--) {
96: if (*p->name == *n && strcmp(p->name, n) == 0
97: && (p->flag&DEFINED))
98: return p;
99: if (pp == tp->tbls) /* wrap */
100: pp += tp->size;
101: }
102:
103: return NULL;
104: }
105:
106: struct tbl *
107: tenter(tp, n, h)
108: register struct table *tp; /* table */
109: register char *n; /* name to enter */
110: unsigned int h; /* hash(n) */
111: {
112: register struct tbl **pp, *p;
113: register char *cp;
114:
115: if (tp->size == 0)
116: texpand(tp, INIT_TBLS);
117: Search:
118: /* search for name in hashed table */
119: for (pp = &tp->tbls[h & tp->size-1]; (p = *pp) != NULL; pp--) {
120: if (*p->name == *n && strcmp(p->name, n) == 0)
121: return p; /* found */
122: if (pp == tp->tbls) /* wrap */
123: pp += tp->size;
124: }
125:
126: if (tp->free <= 0) { /* too full */
127: texpand(tp, 2*tp->size);
128: goto Search;
129: }
130:
131: /* create new tbl entry */
132: for (cp = n; *cp != '\0'; cp++)
133: ;
134: p = (struct tbl *) alloc(offsetof(struct tbl, name[(cp-n)+1]), tp->areap);
135: p->flag = 0;
136: p->type = 0;
137: for (cp = p->name; *n != '\0';)
138: *cp++ = *n++;
139: *cp = '\0';
140:
141: /* enter in tp->tbls */
142: tp->free--;
143: *pp = p;
144: return p;
145: }
146:
147: void
148: tdelete(p)
149: register struct tbl *p;
150: {
151: p->flag = 0;
152: }
153:
154: void
155: twalk(tp)
156: register struct table *tp;
157: {
158: tstate.left = tp->size;
159: tstate.next = tp->tbls;
160: }
161:
162: struct tbl *
163: tnext()
164: {
165: while (--tstate.left >= 0) {
166: struct tbl *p = *tstate.next++;
167: if (p != NULL && (p->flag&DEFINED))
168: return p;
169: }
170: return NULL;
171: }
172:
173: static int
174: tnamecmp(p1, p2)
175: Void *p1, *p2;
176: {
177: return strcmp(((struct tbl *)p1)->name, ((struct tbl *)p2)->name);
178: }
179:
180: struct tbl **
181: tsort(tp)
182: register struct table *tp;
183: {
184: register int i;
185: register struct tbl **p, **sp, **dp;
186:
187: p = (struct tbl **)alloc(sizeofN(struct tbl *, tp->size+1), ATEMP);
188: sp = tp->tbls; /* source */
189: dp = p; /* dest */
190: for (i = 0; i < tp->size; i++)
191: if ((*dp = *sp++) != NULL && ((*dp)->flag&DEFINED))
192: dp++;
193: i = dp - p;
194: qsortp((Void**)p, (size_t)i, tnamecmp);
195: p[i] = NULL;
196: return p;
197: }
198:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.