379a8865a4694944ec5f78f354996723fc350797
[projects/cmucl/cmucl.git] / src / lisp / vars.c
1 /* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/vars.c,v 1.7 2008/03/19 09:17:13 cshapiro Rel $ */
2 #include <stdio.h>
3 #include <sys/types.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "lisp.h"
8 #include "vars.h"
9 #include "os.h"
10
11 #define NAME_BUCKETS 31
12 #define OBJ_BUCKETS 31
13
14 static struct var *NameHash[NAME_BUCKETS], *ObjHash[OBJ_BUCKETS];
15 static int tempcntr = 1;
16
17 struct var {
18     lispobj obj;
19       lispobj(*update_fn) (struct var * var);
20     char *name;
21     long clock;
22     boolean map_back, permanent;
23
24     struct var *nnext;          /* Next in name list */
25     struct var *onext;          /* Next in object list */
26 };
27
28 static int
29 hash_name(char *name)
30 {
31     unsigned long value = 0;
32
33     while (*name != '\0') {
34         value = (value << 1) ^ *(unsigned char *) (name++);
35         value = (value & (1 - (1 << 24))) ^ (value >> 24);
36     }
37
38     return value % NAME_BUCKETS;
39 }
40
41 static int
42 hash_obj(lispobj obj)
43 {
44     return (unsigned long) obj % OBJ_BUCKETS;
45 }
46
47
48 void
49 flush_vars(void)
50 {
51     int index;
52     struct var *var, *next, *perm = NULL;
53
54     /* Note: all vars in the object hash table also appear in the name hash table, so if we free everything in the name hash table, we free everything in the object hash table. */
55
56     for (index = 0; index < NAME_BUCKETS; index++)
57         for (var = NameHash[index]; var != NULL; var = next) {
58             next = var->nnext;
59             if (var->permanent) {
60                 var->nnext = perm;
61                 perm = var;
62             } else {
63                 free(var->name);
64                 free(var);
65             }
66         }
67     memset(NameHash, 0, sizeof(NameHash));
68     memset(ObjHash, 0, sizeof(ObjHash));
69     tempcntr = 1;
70
71     for (var = perm; var != NULL; var = next) {
72         next = var->nnext;
73         index = hash_name(var->name);
74         var->nnext = NameHash[index];
75         NameHash[index] = var;
76         if (var->map_back) {
77             index = hash_obj(var->obj);
78             var->onext = ObjHash[index];
79             ObjHash[index] = var;
80         }
81     }
82 }
83
84 struct var *
85 lookup_by_name(char *name)
86 {
87     struct var *var;
88
89     for (var = NameHash[hash_name(name)]; var != NULL; var = var->nnext)
90         if (strcmp(var->name, name) == 0)
91             return var;
92     return NULL;
93 }
94
95 struct var *
96 lookup_by_obj(lispobj obj)
97 {
98     struct var *var;
99
100     for (var = ObjHash[hash_obj(obj)]; var != NULL; var = var->onext)
101         if (var->obj == obj)
102             return var;
103     return NULL;
104 }
105
106 static struct var *
107 make_var(char *name, boolean perm)
108 {
109     struct var *var;
110     char buffer[256];
111     int index;
112
113     var = (struct var *) malloc(sizeof(struct var));
114
115     if (var == NULL) {
116         perror("malloc");
117         exit(1);
118     }
119
120     if (name == NULL) {
121         sprintf(buffer, "%d", tempcntr++);
122         name = buffer;
123     }
124     var->name = (char *) malloc(strlen(name) + 1);
125     strcpy(var->name, name);
126     var->clock = 0;
127     var->permanent = perm;
128     var->map_back = FALSE;
129
130     index = hash_name(name);
131     var->nnext = NameHash[index];
132     NameHash[index] = var;
133
134     return var;
135 }
136
137 struct var *
138 define_var(char *name, lispobj obj, boolean perm)
139 {
140     struct var *var = make_var(name, perm);
141     int index;
142
143     var->obj = obj;
144     var->update_fn = NULL;
145
146     if (lookup_by_obj(obj) == NULL) {
147         var->map_back = TRUE;
148         index = hash_obj(obj);
149         var->onext = ObjHash[index];
150         ObjHash[index] = var;
151     }
152
153     return var;
154 }
155
156 struct var *
157 define_dynamic_var(char *name, lispobj updatefn(struct var *), boolean perm)
158 {
159     struct var *var = make_var(name, perm);
160
161     var->update_fn = updatefn;
162
163     return var;
164 }
165
166 char *
167 var_name(struct var *var)
168 {
169     return var->name;
170 }
171
172 lispobj
173 var_value(struct var * var)
174 {
175     if (var->update_fn != NULL)
176         var->obj = (*var->update_fn) (var);
177     return var->obj;
178 }
179
180 long
181 var_clock(struct var *var)
182 {
183     return var->clock;
184 }
185
186 void
187 var_setclock(struct var *var, long val)
188 {
189     var->clock = val;
190 }