diff options
Diffstat (limited to 'fallback.c')
-rw-r--r-- | fallback.c | 353 |
1 files changed, 0 insertions, 353 deletions
diff --git a/fallback.c b/fallback.c deleted file mode 100644 index edec9184..00000000 --- a/fallback.c +++ /dev/null | |||
@@ -1,353 +0,0 @@ | |||
1 | /* | ||
2 | ** fallback.c | ||
3 | ** TecCGraf - PUC-Rio | ||
4 | */ | ||
5 | |||
6 | char *rcs_fallback="$Id: fallback.c,v 2.10 1997/07/03 22:06:06 roberto Exp $"; | ||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <string.h> | ||
10 | |||
11 | #include "auxlib.h" | ||
12 | #include "luamem.h" | ||
13 | #include "fallback.h" | ||
14 | #include "opcode.h" | ||
15 | #include "lua.h" | ||
16 | #include "table.h" | ||
17 | #include "tree.h" | ||
18 | #include "hash.h" | ||
19 | |||
20 | |||
21 | |||
22 | /* ------------------------------------------- | ||
23 | ** Reference routines | ||
24 | */ | ||
25 | |||
26 | static struct ref { | ||
27 | TObject o; | ||
28 | enum {LOCK, HOLD, FREE, COLLECTED} status; | ||
29 | } *refArray = NULL; | ||
30 | static int refSize = 0; | ||
31 | |||
32 | int luaI_ref (TObject *object, int lock) | ||
33 | { | ||
34 | int i; | ||
35 | int oldSize; | ||
36 | if (ttype(object) == LUA_T_NIL) | ||
37 | return -1; /* special ref for nil */ | ||
38 | for (i=0; i<refSize; i++) | ||
39 | if (refArray[i].status == FREE) | ||
40 | goto found; | ||
41 | /* no more empty spaces */ | ||
42 | oldSize = refSize; | ||
43 | refSize = growvector(&refArray, refSize, struct ref, refEM, MAX_WORD); | ||
44 | for (i=oldSize; i<refSize; i++) | ||
45 | refArray[i].status = FREE; | ||
46 | i = oldSize; | ||
47 | found: | ||
48 | refArray[i].o = *object; | ||
49 | refArray[i].status = lock ? LOCK : HOLD; | ||
50 | return i; | ||
51 | } | ||
52 | |||
53 | |||
54 | void lua_unref (int ref) | ||
55 | { | ||
56 | if (ref >= 0 && ref < refSize) | ||
57 | refArray[ref].status = FREE; | ||
58 | } | ||
59 | |||
60 | |||
61 | TObject *luaI_getref (int ref) | ||
62 | { | ||
63 | static TObject nul = {LUA_T_NIL, {0}}; | ||
64 | if (ref == -1) | ||
65 | return &nul; | ||
66 | if (ref >= 0 && ref < refSize && | ||
67 | (refArray[ref].status == LOCK || refArray[ref].status == HOLD)) | ||
68 | return &refArray[ref].o; | ||
69 | else | ||
70 | return NULL; | ||
71 | } | ||
72 | |||
73 | |||
74 | void luaI_travlock (int (*fn)(TObject *)) | ||
75 | { | ||
76 | int i; | ||
77 | for (i=0; i<refSize; i++) | ||
78 | if (refArray[i].status == LOCK) | ||
79 | fn(&refArray[i].o); | ||
80 | } | ||
81 | |||
82 | |||
83 | void luaI_invalidaterefs (void) | ||
84 | { | ||
85 | int i; | ||
86 | for (i=0; i<refSize; i++) | ||
87 | if (refArray[i].status == HOLD && !luaI_ismarked(&refArray[i].o)) | ||
88 | refArray[i].status = COLLECTED; | ||
89 | } | ||
90 | |||
91 | |||
92 | /* ------------------------------------------- | ||
93 | * Internal Methods | ||
94 | */ | ||
95 | |||
96 | char *luaI_eventname[] = { /* ORDER IM */ | ||
97 | "gettable", "settable", "index", "getglobal", "setglobal", "add", | ||
98 | "sub", "mul", "div", "pow", "unm", "lt", "le", "gt", "ge", | ||
99 | "concat", "gc", "function", | ||
100 | NULL | ||
101 | }; | ||
102 | |||
103 | |||
104 | |||
105 | static int luaI_checkevent (char *name, char *list[]) | ||
106 | { | ||
107 | int e = luaI_findstring(name, list); | ||
108 | if (e < 0) | ||
109 | luaL_verror("`%s' is not a valid event name", name); | ||
110 | return e; | ||
111 | } | ||
112 | |||
113 | |||
114 | struct IM *luaI_IMtable = NULL; | ||
115 | |||
116 | static int IMtable_size = 0; | ||
117 | static int last_tag = LUA_T_NIL; /* ORDER LUA_T */ | ||
118 | |||
119 | |||
120 | /* events in LUA_T_LINE are all allowed, since this is used as a | ||
121 | * 'placeholder' for "default" fallbacks | ||
122 | */ | ||
123 | static char validevents[NUM_TYPES][IM_N] = { /* ORDER LUA_T, ORDER IM */ | ||
124 | {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_T_USERDATA */ | ||
125 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_T_LINE */ | ||
126 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* LUA_T_CMARK */ | ||
127 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* LUA_T_MARK */ | ||
128 | {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_CFUNCTION */ | ||
129 | {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_FUNCTION */ | ||
130 | {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_T_ARRAY */ | ||
131 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_STRING */ | ||
132 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_NUMBER */ | ||
133 | {1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} /* LUA_T_NIL */ | ||
134 | }; | ||
135 | |||
136 | static int validevent (lua_Type t, int e) | ||
137 | { /* ORDER LUA_T */ | ||
138 | return (t < LUA_T_NIL) ? 1 : validevents[-t][e]; | ||
139 | } | ||
140 | |||
141 | |||
142 | static void init_entry (int tag) | ||
143 | { | ||
144 | int i; | ||
145 | for (i=0; i<IM_N; i++) | ||
146 | ttype(luaI_getim(tag, i)) = LUA_T_NIL; | ||
147 | } | ||
148 | |||
149 | void luaI_initfallbacks (void) | ||
150 | { | ||
151 | if (luaI_IMtable == NULL) { | ||
152 | int i; | ||
153 | IMtable_size = NUM_TYPES+10; | ||
154 | luaI_IMtable = newvector(IMtable_size, struct IM); | ||
155 | for (i=LUA_T_NIL; i<=LUA_T_USERDATA; i++) | ||
156 | init_entry(i); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | int lua_newtag (void) | ||
161 | { | ||
162 | --last_tag; | ||
163 | if ((-last_tag) >= IMtable_size) { | ||
164 | luaI_initfallbacks(); | ||
165 | IMtable_size = growvector(&luaI_IMtable, IMtable_size, | ||
166 | struct IM, memEM, MAX_INT); | ||
167 | } | ||
168 | init_entry(last_tag); | ||
169 | return last_tag; | ||
170 | } | ||
171 | |||
172 | |||
173 | static void checktag (int tag) | ||
174 | { | ||
175 | if (!(last_tag <= tag && tag <= 0)) | ||
176 | luaL_verror("%d is not a valid tag", tag); | ||
177 | } | ||
178 | |||
179 | void luaI_realtag (int tag) | ||
180 | { | ||
181 | if (!(last_tag <= tag && tag < LUA_T_NIL)) | ||
182 | luaL_verror("tag %d is not result of `newtag'", tag); | ||
183 | } | ||
184 | |||
185 | |||
186 | void luaI_settag (int tag, TObject *o) | ||
187 | { | ||
188 | luaI_realtag(tag); | ||
189 | switch (ttype(o)) { | ||
190 | case LUA_T_ARRAY: | ||
191 | o->value.a->htag = tag; | ||
192 | break; | ||
193 | case LUA_T_USERDATA: | ||
194 | o->value.ts->tag = tag; | ||
195 | break; | ||
196 | default: | ||
197 | luaL_verror("cannot change the tag of a %s", luaI_typenames[-ttype(o)]); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | |||
202 | int luaI_efectivetag (TObject *o) | ||
203 | { | ||
204 | lua_Type t = ttype(o); | ||
205 | if (t == LUA_T_USERDATA) { | ||
206 | int tag = o->value.ts->tag; | ||
207 | return (tag >= 0) ? LUA_T_USERDATA : tag; | ||
208 | } | ||
209 | else if (t == LUA_T_ARRAY) | ||
210 | return o->value.a->htag; | ||
211 | else return t; | ||
212 | } | ||
213 | |||
214 | |||
215 | void luaI_gettagmethod (void) | ||
216 | { | ||
217 | int t = (int)luaL_check_number(1); | ||
218 | int e = luaI_checkevent(luaL_check_string(2), luaI_eventname); | ||
219 | checktag(t); | ||
220 | if (validevent(t, e)) | ||
221 | luaI_pushobject(luaI_getim(t,e)); | ||
222 | } | ||
223 | |||
224 | |||
225 | void luaI_settagmethod (void) | ||
226 | { | ||
227 | int t = (int)luaL_check_number(1); | ||
228 | int e = luaI_checkevent(luaL_check_string(2), luaI_eventname); | ||
229 | lua_Object func = lua_getparam(3); | ||
230 | checktag(t); | ||
231 | if (!validevent(t, e)) | ||
232 | luaL_verror("cannot change internal method `%s' for tag %d", | ||
233 | luaI_eventname[e], t); | ||
234 | luaL_arg_check(lua_isnil(func) || lua_isfunction(func), | ||
235 | 3, "function expected"); | ||
236 | luaI_pushobject(luaI_getim(t,e)); | ||
237 | *luaI_getim(t, e) = *luaI_Address(func); | ||
238 | } | ||
239 | |||
240 | |||
241 | void luaI_seterrormethod (void) | ||
242 | { | ||
243 | lua_Object func = lua_getparam(1); | ||
244 | luaL_arg_check(lua_isnil(func) || lua_isfunction(func), | ||
245 | 1, "function expected"); | ||
246 | luaI_pushobject(&luaI_errorim); | ||
247 | luaI_errorim = *luaI_Address(func); | ||
248 | } | ||
249 | |||
250 | char *luaI_travfallbacks (int (*fn)(TObject *)) | ||
251 | { | ||
252 | int e; | ||
253 | if (fn(&luaI_errorim)) | ||
254 | return "error"; | ||
255 | for (e=IM_GETTABLE; e<=IM_FUNCTION; e++) { /* ORDER IM */ | ||
256 | int t; | ||
257 | for (t=0; t>=last_tag; t--) | ||
258 | if (fn(luaI_getim(t,e))) | ||
259 | return luaI_eventname[e]; | ||
260 | } | ||
261 | return NULL; | ||
262 | } | ||
263 | |||
264 | |||
265 | /* | ||
266 | * =================================================================== | ||
267 | * compatibility with old fallback system | ||
268 | */ | ||
269 | #if LUA_COMPAT2_5 | ||
270 | |||
271 | static void errorFB (void) | ||
272 | { | ||
273 | lua_Object o = lua_getparam(1); | ||
274 | if (lua_isstring(o)) | ||
275 | fprintf (stderr, "lua: %s\n", lua_getstring(o)); | ||
276 | else | ||
277 | fprintf(stderr, "lua: unknown error\n"); | ||
278 | } | ||
279 | |||
280 | |||
281 | static void nilFB (void) { } | ||
282 | |||
283 | |||
284 | static void typeFB (void) | ||
285 | { | ||
286 | lua_error("unexpected type"); | ||
287 | } | ||
288 | |||
289 | |||
290 | static void fillvalids (IMS e, TObject *func) | ||
291 | { | ||
292 | int t; | ||
293 | for (t=LUA_T_NIL; t<=LUA_T_USERDATA; t++) | ||
294 | if (validevent(t, e)) | ||
295 | *luaI_getim(t, e) = *func; | ||
296 | } | ||
297 | |||
298 | |||
299 | void luaI_setfallback (void) | ||
300 | { | ||
301 | static char *oldnames [] = {"error", "getglobal", "arith", "order", NULL}; | ||
302 | TObject oldfunc; | ||
303 | lua_CFunction replace; | ||
304 | char *name = luaL_check_string(1); | ||
305 | lua_Object func = lua_getparam(2); | ||
306 | luaI_initfallbacks(); | ||
307 | luaL_arg_check(lua_isfunction(func), 2, "function expected"); | ||
308 | switch (luaI_findstring(name, oldnames)) { | ||
309 | case 0: /* old error fallback */ | ||
310 | oldfunc = luaI_errorim; | ||
311 | luaI_errorim = *luaI_Address(func); | ||
312 | replace = errorFB; | ||
313 | break; | ||
314 | case 1: /* old getglobal fallback */ | ||
315 | oldfunc = *luaI_getim(LUA_T_NIL, IM_GETGLOBAL); | ||
316 | *luaI_getim(LUA_T_NIL, IM_GETGLOBAL) = *luaI_Address(func); | ||
317 | replace = nilFB; | ||
318 | break; | ||
319 | case 2: { /* old arith fallback */ | ||
320 | int i; | ||
321 | oldfunc = *luaI_getim(LUA_T_NUMBER, IM_POW); | ||
322 | for (i=IM_ADD; i<=IM_UNM; i++) /* ORDER IM */ | ||
323 | fillvalids(i, luaI_Address(func)); | ||
324 | replace = typeFB; | ||
325 | break; | ||
326 | } | ||
327 | case 3: { /* old order fallback */ | ||
328 | int i; | ||
329 | oldfunc = *luaI_getim(LUA_T_LINE, IM_LT); | ||
330 | for (i=IM_LT; i<=IM_GE; i++) /* ORDER IM */ | ||
331 | fillvalids(i, luaI_Address(func)); | ||
332 | replace = typeFB; | ||
333 | break; | ||
334 | } | ||
335 | default: { | ||
336 | int e; | ||
337 | if ((e = luaI_findstring(name, luaI_eventname)) >= 0) { | ||
338 | oldfunc = *luaI_getim(LUA_T_LINE, e); | ||
339 | fillvalids(e, luaI_Address(func)); | ||
340 | replace = (e == IM_GC || e == IM_INDEX) ? nilFB : typeFB; | ||
341 | } | ||
342 | else { | ||
343 | luaL_verror("`%s' is not a valid fallback name", name); | ||
344 | replace = NULL; /* to avoid warnings */ | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | if (oldfunc.ttype != LUA_T_NIL) | ||
349 | luaI_pushobject(&oldfunc); | ||
350 | else | ||
351 | lua_pushcfunction(replace); | ||
352 | } | ||
353 | #endif | ||