aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/mk/symtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/mk/symtab.c')
-rw-r--r--src/cmd/mk/symtab.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/cmd/mk/symtab.c b/src/cmd/mk/symtab.c
new file mode 100644
index 00000000..6f7b8886
--- /dev/null
+++ b/src/cmd/mk/symtab.c
@@ -0,0 +1,95 @@
+#include "mk.h"
+
+#define NHASH 4099
+#define HASHMUL 79L /* this is a good value */
+static Symtab *hash[NHASH];
+
+void
+syminit(void)
+{
+ Symtab **s, *ss;
+
+ for(s = hash; s < &hash[NHASH]; s++){
+ for(ss = *s; ss; ss = ss->next)
+ free((char *)ss);
+ *s = 0;
+ }
+}
+
+Symtab *
+symlook(char *sym, int space, void *install)
+{
+ long h;
+ char *p;
+ Symtab *s;
+
+ for(p = sym, h = space; *p; h += *p++)
+ h *= HASHMUL;
+ if(h < 0)
+ h = ~h;
+ h %= NHASH;
+ for(s = hash[h]; s; s = s->next)
+ if((s->space == space) && (strcmp(s->name, sym) == 0))
+ return(s);
+ if(install == 0)
+ return(0);
+ s = (Symtab *)Malloc(sizeof(Symtab));
+ s->space = space;
+ s->name = sym;
+ s->value = install;
+ s->next = hash[h];
+ hash[h] = s;
+ return(s);
+}
+
+void
+symdel(char *sym, int space)
+{
+ long h;
+ char *p;
+ Symtab *s, *ls;
+
+ /* multiple memory leaks */
+
+ for(p = sym, h = space; *p; h += *p++)
+ h *= HASHMUL;
+ if(h < 0)
+ h = ~h;
+ h %= NHASH;
+ for(s = hash[h], ls = 0; s; ls = s, s = s->next)
+ if((s->space == space) && (strcmp(s->name, sym) == 0)){
+ if(ls)
+ ls->next = s->next;
+ else
+ hash[h] = s->next;
+ free((char *)s);
+ }
+}
+
+void
+symtraverse(int space, void (*fn)(Symtab*))
+{
+ Symtab **s, *ss;
+
+ for(s = hash; s < &hash[NHASH]; s++)
+ for(ss = *s; ss; ss = ss->next)
+ if(ss->space == space)
+ (*fn)(ss);
+}
+
+void
+symstat(void)
+{
+ Symtab **s, *ss;
+ int n;
+ int l[1000];
+
+ memset((char *)l, 0, sizeof(l));
+ for(s = hash; s < &hash[NHASH]; s++){
+ for(ss = *s, n = 0; ss; ss = ss->next)
+ n++;
+ l[n]++;
+ }
+ for(n = 0; n < 1000; n++)
+ if(l[n]) Bprint(&bout, "%ld of length %d\n", l[n], n);
+}