0.7.2.6:
[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 <strings.h>
14 #include <sys/types.h>
15 #include <stdlib.h>
16
17 #include "runtime.h"
18 #include "vars.h"
19 #include "os.h"
20
21 #define NAME_BUCKETS 31
22 #define OBJ_BUCKETS 31
23
24 static struct var *NameHash[NAME_BUCKETS], *ObjHash[OBJ_BUCKETS];
25 static int tempcntr = 1;
26
27 struct var {
28     lispobj obj;
29     lispobj (*update_fn)(struct var *var);
30     char *name;
31     long clock;
32     boolean map_back, permanent;
33
34     struct var *nnext; /* Next in name list */
35     struct var *onext; /* Next in object list */
36 };
37
38 static int hash_name(char *name)
39 {
40     unsigned long value = 0;
41
42     while (*name != '\0') {
43         value = (value << 1) ^ *(unsigned char *)(name++);
44         value = (value & (1-(1<<24))) ^ (value >> 24);
45     }
46
47     return value % NAME_BUCKETS;
48 }
49
50 static int hash_obj(lispobj obj)
51 {
52     return (unsigned long)obj % OBJ_BUCKETS;
53 }
54
55 void flush_vars()
56 {
57     int index;
58     struct var *var, *next, *perm = NULL;
59
60     /* Note: all vars in the object hash table also appear in the name hash
61      * table, so if we free everything in the name hash table, we free
62      * everything in the object hash table. */
63
64     for (index = 0; index < NAME_BUCKETS; index++)
65         for (var = NameHash[index]; var != NULL; var = next) {
66             next = var->nnext;
67             if (var->permanent) {
68                 var->nnext = perm;
69                 perm = var;
70             }
71             else {
72                 free(var->name);
73                 free(var);
74             }
75         }
76     bzero(NameHash, sizeof(NameHash));
77     bzero(ObjHash, sizeof(ObjHash));
78     tempcntr = 1;
79
80     for (var = perm; var != NULL; var = next) {
81         next = var->nnext;
82         index = hash_name(var->name);
83         var->nnext = NameHash[index];
84         NameHash[index] = var;
85         if (var->map_back) {
86             index = hash_obj(var->obj);
87             var->onext = ObjHash[index];
88             ObjHash[index] = var;
89         }
90     }
91 }
92
93 struct var *lookup_by_name(name)
94 char *name;
95 {
96     struct var *var;
97
98     for (var = NameHash[hash_name(name)]; var != NULL; var = var->nnext)
99         if (strcmp(var->name, name) == 0)
100             return var;
101     return NULL;
102 }
103
104 struct var *lookup_by_obj(obj)
105 lispobj obj;
106 {
107     struct var *var;
108
109     for (var = ObjHash[hash_obj(obj)]; var != NULL; var = var->onext)
110         if (var->obj == obj)
111             return var;
112     return NULL;
113 }
114
115 static struct var *make_var(char *name, boolean perm)
116 {
117     struct var *var = (struct var *)malloc(sizeof(struct var));
118     char buffer[256];
119     int index;
120
121     if (name == NULL) {
122         sprintf(buffer, "%d", tempcntr++);
123         name = buffer;
124     }
125     var->name = (char *)malloc(strlen(name)+1);
126     strcpy(var->name, name);
127     var->clock = 0;
128     var->permanent = perm;
129     var->map_back = 0;
130
131     index = hash_name(name);
132     var->nnext = NameHash[index];
133     NameHash[index] = var;
134
135     return var;
136 }
137
138 struct var *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 = 1;
148         index = hash_obj(obj);
149         var->onext = ObjHash[index];
150         ObjHash[index] = var;
151     }
152
153     return var;
154 }
155
156 struct var *define_dynamic_var(char *name, lispobj updatefn(struct var *),
157                                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 *var_name(struct var *var)
167 {
168     return var->name;
169 }
170
171 lispobj var_value(struct var *var)
172 {
173     if (var->update_fn != NULL)
174         var->obj = (*var->update_fn)(var);
175     return var->obj;
176 }
177
178 long var_clock(struct var *var)
179 {
180     return var->clock;
181 }
182
183 void var_setclock(struct var *var, long val)
184 {
185     var->clock = val;
186 }