aboutsummaryrefslogtreecommitdiff
path: root/fallback.c
diff options
context:
space:
mode:
Diffstat (limited to 'fallback.c')
-rw-r--r--fallback.c369
1 files changed, 225 insertions, 144 deletions
diff --git a/fallback.c b/fallback.c
index b0bf8fae..a451f60a 100644
--- a/fallback.c
+++ b/fallback.c
@@ -3,11 +3,12 @@
3** TecCGraf - PUC-Rio 3** TecCGraf - PUC-Rio
4*/ 4*/
5 5
6char *rcs_fallback="$Id: fallback.c,v 1.26 1997/02/26 17:38:41 roberto Unstable roberto $"; 6char *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
20static void errorFB (void);
21static void indexFB (void);
22static void gettableFB (void);
23static void arithFB (void);
24static void concatFB (void);
25static void orderFB (void);
26static void GDFB (void);
27static void funcFB (void);
28
29
30/*
31** Warning: This list must be in the same order as the #define's
32*/
33struct 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
50static 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
62void 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
75static 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
85static void indexFB (void)
86{
87 lua_pushnil();
88}
89
90
91static void gettableFB (void)
92{
93 lua_error("indexed expression not a table");
94}
95
96
97static void arithFB (void)
98{
99 lua_error("unexpected type at conversion to number");
100}
101
102static void concatFB (void)
103{
104 lua_error("unexpected type at conversion to string");
105}
106
107
108static void orderFB (void)
109{
110 lua_error("unexpected type at comparison");
111}
112
113static void GDFB (void) { }
114
115static 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
190char *luaI_travfallbacks (int (*fn)(Object *)) 92
93/* -------------------------------------------
94* Internal Methods
95*/
96
97char *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
110char *geventname[] = {
111 "error", /* GIM_ERROR */
112 "getglobal", /* GIM_GETGLOBAL */
113 "setglobal", /* GIM_SETGLOBAL */
114 NULL
115};
116
117static 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
127static 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
205static struct IM { 136static 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
209static int IMtable_size = 0; 141static int IMtable_size = 0;
210static int last_tag = BASE_TAG-1; 142static int last_tag = LUA_T_NIL;
143
144static 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
212int lua_newtag (char *t) 164
165static 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
176static 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
183void 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
194int 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
230static 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
235static void checktag (int tag) 214static 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
220lua_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
241void luaI_settag (int tag, Object *o) 229void 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
262Object *luaI_getim (int tag, int event) 249Object *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; 256Object *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
276void luaI_setintmethod (void) 261void 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
274static Object gmethod[GIM_N] = {
275 {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}
276};
277
278Object *luaI_getgim (int event)
279{
280 return &gmethod[event];
281}
282
283void 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
292char *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
308static 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
318static void nilFB (void) { }
319
320
321static void typeFB (void)
322{
323 lua_error("unexpected type");
324}
325
326
327void 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