39f065bb59d9ab6118427e0f85744f16ea3d58a1
[sbcl.git] / src / runtime / vars.c
1 /*
2  * This software is part of the SBCL system. See the README file for
3  * more information.
4  *
5  * This software is derived from the CMU CL system, which was
6  * written at Carnegie Mellon University and released into the
7  * public domain. The software is in the public domain and is
8  * provided with absolutely no warranty. See the COPYING and CREDITS
9  * files for more information.
10  */
11
12 #include <stdio.h>
13 #include <sys/types.h>
14 #include <stdlib.h>
15
16 #include "runtime.h"
17 #include "vars.h"
18 #include "os.h"
19
20 #define NAME_BUCKETS 31
21 #define OBJ_BUCKETS 31
22
23 static struct var *NameHash[NAME_BUCKETS], *ObjHash[OBJ_BUCKETS];
24 static int tempcntr = 1;
25
26 struct var {
27     lispobj obj;
28     lispobj (*update_fn)(struct var *var);
29     char *name;
30     long clock;
31     boolean map_back, permanent;
32
33     struct var *nnext; /* Next in name list */
34     struct var *onext; /* Next in object list */
35 };
36
37 static int hash_name(char *name)
38 {
39     unsigned long value = 0;
40
41     while (*name != '\0') {
42         value = (value << 1) ^ *(unsigned char *)(name++);
43         value = (value & (1-(1<<24))) ^ (value >> 24);
44     }
45
46     return value % NAME_BUCKETS;
47 }
48
49 static int hash_obj(lispobj obj)
50 {
51     return (unsigned long)obj % OBJ_BUCKETS;
52 }
53
54 void flush_vars()
55 {
56     int index;
57     struct var *var, *next, *perm = NULL;
58
59     /* Note: all vars in the object hash table also appear in the name hash
60      * table, so if we free everything in the name hash table, we free
61      * everything in the object hash table. */
62
63     for (index = 0; index < NAME_BUCKETS; index++)
64         for (var = NameHash[index]; var != NULL; var = next) {
65             next = var->nnext;
66             if (var->permanent) {
67                 var->nnext = perm;
68                 perm = var;
69             }
70             else {
71                 free(var->name);
72                 free(var);
73             }
74         }
75     bzero(NameHash, sizeof(NameHash));
76     bzero(ObjHash, sizeof(ObjHash));
77     tempcntr = 1;
78
79     for (var = perm; var != NULL; var = next) {
80         next = var->nnext;
81         index = hash_name(var->name);
82         var->nnext = NameHash[index];
83         NameHash[index] = var;
84         if (var->map_back) {
85             index = hash_obj(var->obj);
86             var->onext = ObjHash[index];
87             ObjHash[index] = var;
88         }
89     }
90 }
91
92 struct var *lookup_by_name(name)
93 char *name;
94 {
95     struct var *var;
96
97     for (var = NameHash[hash_name(name)]; var != NULL; var = var->nnext)
98         if (strcmp(var->name, name) == 0)
99             return var;
100     return NULL;
101 }
102
103 struct var *lookup_by_obj(obj)
104 lispobj obj;
105 {
106     struct var *var;
107
108     for (var = ObjHash[hash_obj(obj)]; var != NULL; var = var->onext)
109         if (var->obj == obj)
110             return var;
111     return NULL;
112 }
113
114 static struct var *make_var(char *name, boolean perm)
115 {
116     struct var *var = (struct var *)malloc(sizeof(struct var));
117     char buffer[256];
118     int index;
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 = 0;
129
130     index = hash_name(name);
131     var->nnext = NameHash[index];
132     NameHash[index] = var;
133
134     return var;
135 }
136
137 struct var *define_var(char *name, lispobj obj, boolean perm)
138 {
139     struct var *var = make_var(name, perm);
140     int index;
141
142     var->obj = obj;
143     var->update_fn = NULL;
144
145     if (lookup_by_obj(obj) == NULL) {
146         var->map_back = 1;
147         index = hash_obj(obj);
148         var->onext = ObjHash[index];
149         ObjHash[index] = var;
150     }
151
152     return var;
153 }
154
155 struct var *define_dynamic_var(char *name, lispobj updatefn(struct var *),
156                                boolean perm)
157 {
158     struct var *var = make_var(name, perm);
159
160     var->update_fn = updatefn;
161
162     return var;
163 }
164
165 char *var_name(struct var *var)
166 {
167     return var->name;
168 }
169
170 lispobj var_value(struct var *var)
171 {
172     if (var->update_fn != NULL)
173         var->obj = (*var->update_fn)(var);
174     return var->obj;
175 }
176
177 long var_clock(struct var *var)
178 {
179     return var->clock;
180 }
181
182 void var_setclock(struct var *var, long val)
183 {
184     var->clock = val;
185 }