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