diff options
Diffstat (limited to 'fallback.c')
-rw-r--r-- | fallback.c | 369 |
1 files changed, 225 insertions, 144 deletions
@@ -3,11 +3,12 @@ | |||
3 | ** TecCGraf - PUC-Rio | 3 | ** TecCGraf - PUC-Rio |
4 | */ | 4 | */ |
5 | 5 | ||
6 | char *rcs_fallback="$Id: fallback.c,v 1.26 1997/02/26 17:38:41 roberto Unstable roberto $"; | 6 | char *rcs_fallback="$Id: fallback.c,v 1.27 1997/03/11 18:44:28 roberto Exp roberto $"; |
7 | 7 | ||
8 | #include <stdio.h> | 8 | #include <stdio.h> |
9 | #include <string.h> | 9 | #include <string.h> |
10 | 10 | ||
11 | #include "auxlib.h" | ||
11 | #include "mem.h" | 12 | #include "mem.h" |
12 | #include "fallback.h" | 13 | #include "fallback.h" |
13 | #include "opcode.h" | 14 | #include "opcode.h" |
@@ -17,105 +18,6 @@ char *rcs_fallback="$Id: fallback.c,v 1.26 1997/02/26 17:38:41 roberto Unstable | |||
17 | #include "hash.h" | 18 | #include "hash.h" |
18 | 19 | ||
19 | 20 | ||
20 | static void errorFB (void); | ||
21 | static void indexFB (void); | ||
22 | static void gettableFB (void); | ||
23 | static void arithFB (void); | ||
24 | static void concatFB (void); | ||
25 | static void orderFB (void); | ||
26 | static void GDFB (void); | ||
27 | static void funcFB (void); | ||
28 | |||
29 | |||
30 | /* | ||
31 | ** Warning: This list must be in the same order as the #define's | ||
32 | */ | ||
33 | struct FB luaI_fallBacks[] = { | ||
34 | {"gettable", {LUA_T_CFUNCTION, {gettableFB}}, 2, 1}, | ||
35 | {"arith", {LUA_T_CFUNCTION, {arithFB}}, 3, 1}, | ||
36 | {"order", {LUA_T_CFUNCTION, {orderFB}}, 3, 1}, | ||
37 | {"concat", {LUA_T_CFUNCTION, {concatFB}}, 2, 1}, | ||
38 | {"settable", {LUA_T_CFUNCTION, {gettableFB}}, 3, 0}, | ||
39 | {"gc", {LUA_T_CFUNCTION, {GDFB}}, 1, 0}, | ||
40 | {"function", {LUA_T_CFUNCTION, {funcFB}}, -1, -1}, | ||
41 | /* no fixed number of params or results */ | ||
42 | {"getglobal", {LUA_T_CFUNCTION, {indexFB}}, 1, 1}, | ||
43 | /* same default behavior of index FB */ | ||
44 | {"index", {LUA_T_CFUNCTION, {indexFB}}, 2, 1}, | ||
45 | {"error", {LUA_T_CFUNCTION, {errorFB}}, 1, 0} | ||
46 | }; | ||
47 | |||
48 | #define N_FB (sizeof(luaI_fallBacks)/sizeof(struct FB)) | ||
49 | |||
50 | static int luaI_findevent (char *name) | ||
51 | { | ||
52 | int i; | ||
53 | for (i=0; i<N_FB; i++) | ||
54 | if (strcmp(luaI_fallBacks[i].kind, name) == 0) | ||
55 | return i; | ||
56 | /* name not found */ | ||
57 | lua_error("invalid event name"); | ||
58 | return 0; /* to avoid warnings */ | ||
59 | } | ||
60 | |||
61 | |||
62 | void luaI_setfallback (void) | ||
63 | { | ||
64 | int i; | ||
65 | char *name = lua_getstring(lua_getparam(1)); | ||
66 | lua_Object func = lua_getparam(2); | ||
67 | if (name == NULL || !lua_isfunction(func)) | ||
68 | lua_error("incorrect argument to function `setfallback'"); | ||
69 | i = luaI_findevent(name); | ||
70 | luaI_pushobject(&luaI_fallBacks[i].function); | ||
71 | luaI_fallBacks[i].function = *luaI_Address(func); | ||
72 | } | ||
73 | |||
74 | |||
75 | static void errorFB (void) | ||
76 | { | ||
77 | lua_Object o = lua_getparam(1); | ||
78 | if (lua_isstring(o)) | ||
79 | fprintf (stderr, "lua: %s\n", lua_getstring(o)); | ||
80 | else | ||
81 | fprintf(stderr, "lua: unknown error\n"); | ||
82 | } | ||
83 | |||
84 | |||
85 | static void indexFB (void) | ||
86 | { | ||
87 | lua_pushnil(); | ||
88 | } | ||
89 | |||
90 | |||
91 | static void gettableFB (void) | ||
92 | { | ||
93 | lua_error("indexed expression not a table"); | ||
94 | } | ||
95 | |||
96 | |||
97 | static void arithFB (void) | ||
98 | { | ||
99 | lua_error("unexpected type at conversion to number"); | ||
100 | } | ||
101 | |||
102 | static void concatFB (void) | ||
103 | { | ||
104 | lua_error("unexpected type at conversion to string"); | ||
105 | } | ||
106 | |||
107 | |||
108 | static void orderFB (void) | ||
109 | { | ||
110 | lua_error("unexpected type at comparison"); | ||
111 | } | ||
112 | |||
113 | static void GDFB (void) { } | ||
114 | |||
115 | static void funcFB (void) | ||
116 | { | ||
117 | lua_error("call expression not a function"); | ||
118 | } | ||
119 | 21 | ||
120 | 22 | ||
121 | /* ------------------------------------------- | 23 | /* ------------------------------------------- |
@@ -187,50 +89,127 @@ void luaI_invalidaterefs (void) | |||
187 | refArray[i].status = COLLECTED; | 89 | refArray[i].status = COLLECTED; |
188 | } | 90 | } |
189 | 91 | ||
190 | char *luaI_travfallbacks (int (*fn)(Object *)) | 92 | |
93 | /* ------------------------------------------- | ||
94 | * Internal Methods | ||
95 | */ | ||
96 | |||
97 | char *eventname[] = { | ||
98 | "gettable", /* IM_GETTABLE */ | ||
99 | "arith", /* IM_ARITH */ | ||
100 | "order", /* IM_ORDER */ | ||
101 | "concat", /* IM_CONCAT */ | ||
102 | "settable", /* IM_SETTABLE */ | ||
103 | "gc", /* IM_GC */ | ||
104 | "function", /* IM_FUNCTION */ | ||
105 | "index", /* IM_INDEX */ | ||
106 | NULL | ||
107 | }; | ||
108 | |||
109 | |||
110 | char *geventname[] = { | ||
111 | "error", /* GIM_ERROR */ | ||
112 | "getglobal", /* GIM_GETGLOBAL */ | ||
113 | "setglobal", /* GIM_SETGLOBAL */ | ||
114 | NULL | ||
115 | }; | ||
116 | |||
117 | static int luaI_findevent (char *name, char *list[]) | ||
191 | { | 118 | { |
192 | int i; | 119 | int i; |
193 | for (i=0; i<N_FB; i++) | 120 | for (i=0; list[i]; i++) |
194 | if (fn(&luaI_fallBacks[i].function)) | 121 | if (strcmp(list[i], name) == 0) |
195 | return luaI_fallBacks[i].kind; | 122 | return i; |
196 | return NULL; | 123 | /* name not found */ |
124 | return -1; | ||
197 | } | 125 | } |
198 | 126 | ||
127 | static int luaI_checkevent (char *name, char *list[]) | ||
128 | { | ||
129 | int e = luaI_findevent(name, list); | ||
130 | if (e < 0) | ||
131 | lua_error("invalid event name"); | ||
132 | return e; | ||
133 | } | ||
199 | 134 | ||
200 | /* ------------------------------------------- | ||
201 | * Internal Methods | ||
202 | */ | ||
203 | #define BASE_TAG 1000 | ||
204 | 135 | ||
205 | static struct IM { | 136 | static struct IM { |
206 | lua_Type tp; | 137 | lua_Type tp; |
207 | Object int_method[FB_N]; | 138 | Object int_method[IM_N]; |
208 | } *luaI_IMtable = NULL; | 139 | } *luaI_IMtable = NULL; |
140 | |||
209 | static int IMtable_size = 0; | 141 | static int IMtable_size = 0; |
210 | static int last_tag = BASE_TAG-1; | 142 | static int last_tag = LUA_T_NIL; |
143 | |||
144 | static struct { | ||
145 | lua_Type t; | ||
146 | int event; | ||
147 | } exceptions[] = { /* list of events that cannot be modified */ | ||
148 | {LUA_T_NUMBER, IM_ARITH}, | ||
149 | {LUA_T_NUMBER, IM_ORDER}, | ||
150 | {LUA_T_NUMBER, IM_GC}, | ||
151 | {LUA_T_STRING, IM_ARITH}, | ||
152 | {LUA_T_STRING, IM_ORDER}, | ||
153 | {LUA_T_STRING, IM_CONCAT}, | ||
154 | {LUA_T_STRING, IM_GC}, | ||
155 | {LUA_T_ARRAY, IM_GETTABLE}, | ||
156 | {LUA_T_ARRAY, IM_SETTABLE}, | ||
157 | {LUA_T_FUNCTION, IM_FUNCTION}, | ||
158 | {LUA_T_FUNCTION, IM_GC}, | ||
159 | {LUA_T_CFUNCTION, IM_FUNCTION}, | ||
160 | {LUA_T_CFUNCTION, IM_GC}, | ||
161 | {LUA_T_NIL, 0} /* flag end of list */ | ||
162 | }; | ||
211 | 163 | ||
212 | int lua_newtag (char *t) | 164 | |
165 | static int validevent (int t, int event) | ||
166 | { | ||
167 | int i; | ||
168 | if (t == LUA_T_NIL) /* cannot modify any event for nil */ | ||
169 | return 0; | ||
170 | for (i=0; exceptions[i].t != LUA_T_NIL; i++) | ||
171 | if (exceptions[i].t == t && exceptions[i].event == event) | ||
172 | return 0; | ||
173 | return 1; | ||
174 | } | ||
175 | |||
176 | static void init_entry (int tag) | ||
213 | { | 177 | { |
214 | int i; | 178 | int i; |
215 | ++last_tag; | 179 | for (i=0; i<IM_N; i++) |
216 | if ((last_tag-BASE_TAG) >= IMtable_size) | 180 | luaI_IMtable[-tag].int_method[i].ttype = LUA_T_NIL; |
181 | } | ||
182 | |||
183 | void luaI_initfallbacks (void) | ||
184 | { | ||
185 | int i; | ||
186 | IMtable_size = NUM_TYPES+10; | ||
187 | luaI_IMtable = newvector(IMtable_size, struct IM); | ||
188 | for (i=LUA_T_NIL; i<=LUA_T_USERDATA; i++) { | ||
189 | luaI_IMtable[-i].tp = (lua_Type)i; | ||
190 | init_entry(i); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | int lua_newtag (char *t) | ||
195 | { | ||
196 | --last_tag; | ||
197 | if ((-last_tag) >= IMtable_size) | ||
217 | IMtable_size = growvector(&luaI_IMtable, IMtable_size, | 198 | IMtable_size = growvector(&luaI_IMtable, IMtable_size, |
218 | struct IM, memEM, MAX_INT); | 199 | struct IM, memEM, MAX_INT); |
219 | if (strcmp(t, "table") == 0) | 200 | if (strcmp(t, "table") == 0) |
220 | luaI_IMtable[last_tag-BASE_TAG].tp = LUA_T_ARRAY; | 201 | luaI_IMtable[-last_tag].tp = LUA_T_ARRAY; |
221 | else if (strcmp(t, "userdata") == 0) | 202 | else if (strcmp(t, "userdata") == 0) |
222 | luaI_IMtable[last_tag-BASE_TAG].tp = LUA_T_USERDATA; | 203 | luaI_IMtable[-last_tag].tp = LUA_T_USERDATA; |
223 | else | 204 | else |
224 | lua_error("invalid type for new tag"); | 205 | lua_error("invalid type for new tag"); |
225 | for (i=0; i<FB_N; i++) | 206 | init_entry(last_tag); |
226 | luaI_IMtable[last_tag-BASE_TAG].int_method[i].ttype = LUA_T_NIL; | ||
227 | return last_tag; | 207 | return last_tag; |
228 | } | 208 | } |
229 | 209 | ||
230 | static int validtag (int tag) | 210 | |
231 | { | 211 | #define validtag(tag) (last_tag <= (tag) && (tag) <= 0) |
232 | return (BASE_TAG <= tag && tag <= last_tag); | 212 | |
233 | } | ||
234 | 213 | ||
235 | static void checktag (int tag) | 214 | static void checktag (int tag) |
236 | { | 215 | { |
@@ -238,10 +217,18 @@ static void checktag (int tag) | |||
238 | lua_error("invalid tag"); | 217 | lua_error("invalid tag"); |
239 | } | 218 | } |
240 | 219 | ||
220 | lua_Type luaI_typetag (int tag) | ||
221 | { | ||
222 | if (tag >= 0) return LUA_T_USERDATA; | ||
223 | else { | ||
224 | checktag(tag); | ||
225 | return luaI_IMtable[-tag].tp; | ||
226 | } | ||
227 | } | ||
228 | |||
241 | void luaI_settag (int tag, Object *o) | 229 | void luaI_settag (int tag, Object *o) |
242 | { | 230 | { |
243 | checktag(tag); | 231 | if (ttype(o) != luaI_typetag(tag)) |
244 | if (ttype(o) != luaI_IMtable[tag-BASE_TAG].tp) | ||
245 | lua_error("Tag is not compatible with this type"); | 232 | lua_error("Tag is not compatible with this type"); |
246 | if (o->ttype == LUA_T_ARRAY) | 233 | if (o->ttype == LUA_T_ARRAY) |
247 | o->value.a->htag = tag; | 234 | o->value.a->htag = tag; |
@@ -261,29 +248,123 @@ int luaI_tag (Object *o) | |||
261 | 248 | ||
262 | Object *luaI_getim (int tag, int event) | 249 | Object *luaI_getim (int tag, int event) |
263 | { | 250 | { |
264 | if (tag == 0) | 251 | if (tag > LUA_T_USERDATA) |
265 | return &luaI_fallBacks[event].function; | 252 | tag = LUA_T_USERDATA; /* default for non-registered tags */ |
266 | else if (validtag(tag)) { | 253 | return &luaI_IMtable[-tag].int_method[event]; |
267 | Object *func = &luaI_IMtable[tag-BASE_TAG].int_method[event]; | 254 | } |
268 | if (func->ttype == LUA_T_NIL) | 255 | |
269 | return NULL; | 256 | Object *luaI_getimbyObj (Object *o, int event) |
270 | else | 257 | { |
271 | return func; | 258 | return luaI_getim(luaI_tag(o), event); |
272 | } | ||
273 | else return NULL; | ||
274 | } | 259 | } |
275 | 260 | ||
276 | void luaI_setintmethod (void) | 261 | void luaI_setintmethod (void) |
277 | { | 262 | { |
278 | lua_Object tag = lua_getparam(1); | 263 | int t = (int)luaL_check_number(1, "setintmethod"); |
279 | lua_Object event = lua_getparam(2); | 264 | int e = luaI_checkevent(luaL_check_string(2, "setintmethod"), eventname); |
280 | lua_Object func = lua_getparam(3); | 265 | lua_Object func = lua_getparam(3); |
281 | if (!(lua_isnumber(tag) && lua_isstring(event) && lua_isfunction(func))) | 266 | if (!validevent(t, e)) |
282 | lua_error("incorrect arguments to function `setintmethod'"); | 267 | lua_error("cannot change this internal method"); |
283 | else { | 268 | luaL_arg_check(lua_isnil(func) || lua_isfunction(func), "setintmethod", |
284 | int i = luaI_findevent(lua_getstring(event)); | 269 | 3, "function expected"); |
285 | int t = lua_getnumber(tag); | 270 | checktag(t); |
286 | checktag(t); | 271 | luaI_IMtable[-t].int_method[e] = *luaI_Address(func); |
287 | luaI_IMtable[t-BASE_TAG].int_method[i] = *luaI_Address(func); | 272 | } |
273 | |||
274 | static Object gmethod[GIM_N] = { | ||
275 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}} | ||
276 | }; | ||
277 | |||
278 | Object *luaI_getgim (int event) | ||
279 | { | ||
280 | return &gmethod[event]; | ||
281 | } | ||
282 | |||
283 | void luaI_setglobalmethod (void) | ||
284 | { | ||
285 | int e = luaI_checkevent(luaL_check_string(1, "setintmethod"), geventname); | ||
286 | lua_Object func = lua_getparam(2); | ||
287 | luaL_arg_check(lua_isnil(func) || lua_isfunction(func), "setintmethod", | ||
288 | 2, "function expected"); | ||
289 | gmethod[e] = *luaI_Address(func); | ||
290 | } | ||
291 | |||
292 | char *luaI_travfallbacks (int (*fn)(Object *)) | ||
293 | { /* ?????????? | ||
294 | int i; | ||
295 | for (i=0; i<N_FB; i++) | ||
296 | if (fn(&luaI_fallBacks[i].function)) | ||
297 | return luaI_fallBacks[i].kind; */ | ||
298 | return NULL; | ||
299 | } | ||
300 | |||
301 | |||
302 | /* | ||
303 | * =================================================================== | ||
304 | * compatibility with old fallback system | ||
305 | */ | ||
306 | |||
307 | |||
308 | static void errorFB (void) | ||
309 | { | ||
310 | lua_Object o = lua_getparam(1); | ||
311 | if (lua_isstring(o)) | ||
312 | fprintf (stderr, "lua: %s\n", lua_getstring(o)); | ||
313 | else | ||
314 | fprintf(stderr, "lua: unknown error\n"); | ||
315 | } | ||
316 | |||
317 | |||
318 | static void nilFB (void) { } | ||
319 | |||
320 | |||
321 | static void typeFB (void) | ||
322 | { | ||
323 | lua_error("unexpected type"); | ||
324 | } | ||
325 | |||
326 | |||
327 | void luaI_setfallback (void) | ||
328 | { | ||
329 | int e; | ||
330 | char *name = luaL_check_string(1, "setfallback"); | ||
331 | lua_Object func = lua_getparam(2); | ||
332 | luaL_arg_check(lua_isfunction(func), "setfallback", 2, "function expected"); | ||
333 | e = luaI_findevent(name, geventname); | ||
334 | if (e >= 0) { /* global event */ | ||
335 | switch (e) { | ||
336 | case GIM_ERROR: | ||
337 | gmethod[e] = *luaI_Address(func); | ||
338 | lua_pushcfunction(errorFB); | ||
339 | break; | ||
340 | case GIM_GETGLOBAL: /* goes through */ | ||
341 | case GIM_SETGLOBAL: | ||
342 | gmethod[e] = *luaI_Address(func); | ||
343 | lua_pushcfunction(nilFB); | ||
344 | break; | ||
345 | default: lua_error("internal error"); | ||
346 | } | ||
347 | } | ||
348 | else { /* tagged name? */ | ||
349 | int t; | ||
350 | Object oldfunc; | ||
351 | e = luaI_checkevent(name, eventname); | ||
352 | oldfunc = luaI_IMtable[LUA_T_USERDATA].int_method[e]; | ||
353 | for (t=LUA_T_NIL; t<=LUA_T_USERDATA; t++) | ||
354 | if (validevent(t, e)) | ||
355 | luaI_IMtable[-t].int_method[e] = *luaI_Address(func); | ||
356 | if (oldfunc.ttype != LUA_T_NIL) | ||
357 | luaI_pushobject(&oldfunc); | ||
358 | else { | ||
359 | switch (e) { | ||
360 | case IM_GC: case IM_INDEX: | ||
361 | lua_pushcfunction(nilFB); | ||
362 | break; | ||
363 | default: | ||
364 | lua_pushcfunction(typeFB); | ||
365 | break; | ||
366 | } | ||
367 | } | ||
288 | } | 368 | } |
289 | } | 369 | } |
370 | |||