|
@@ -3,11 +3,12 @@
|
|
|
** TecCGraf - PUC-Rio
|
|
|
*/
|
|
|
|
|
|
-char *rcs_fallback="$Id: fallback.c,v 1.26 1997/02/26 17:38:41 roberto Unstable roberto $";
|
|
|
+char *rcs_fallback="$Id: fallback.c,v 1.27 1997/03/11 18:44:28 roberto Exp roberto $";
|
|
|
|
|
|
#include <stdio.h>
|
|
|
#include <string.h>
|
|
|
|
|
|
+#include "auxlib.h"
|
|
|
#include "mem.h"
|
|
|
#include "fallback.h"
|
|
|
#include "opcode.h"
|
|
@@ -17,105 +18,6 @@ char *rcs_fallback="$Id: fallback.c,v 1.26 1997/02/26 17:38:41 roberto Unstable
|
|
|
#include "hash.h"
|
|
|
|
|
|
|
|
|
-static void errorFB (void);
|
|
|
-static void indexFB (void);
|
|
|
-static void gettableFB (void);
|
|
|
-static void arithFB (void);
|
|
|
-static void concatFB (void);
|
|
|
-static void orderFB (void);
|
|
|
-static void GDFB (void);
|
|
|
-static void funcFB (void);
|
|
|
-
|
|
|
-
|
|
|
-/*
|
|
|
-** Warning: This list must be in the same order as the #define's
|
|
|
-*/
|
|
|
-struct FB luaI_fallBacks[] = {
|
|
|
-{"gettable", {LUA_T_CFUNCTION, {gettableFB}}, 2, 1},
|
|
|
-{"arith", {LUA_T_CFUNCTION, {arithFB}}, 3, 1},
|
|
|
-{"order", {LUA_T_CFUNCTION, {orderFB}}, 3, 1},
|
|
|
-{"concat", {LUA_T_CFUNCTION, {concatFB}}, 2, 1},
|
|
|
-{"settable", {LUA_T_CFUNCTION, {gettableFB}}, 3, 0},
|
|
|
-{"gc", {LUA_T_CFUNCTION, {GDFB}}, 1, 0},
|
|
|
-{"function", {LUA_T_CFUNCTION, {funcFB}}, -1, -1},
|
|
|
- /* no fixed number of params or results */
|
|
|
-{"getglobal", {LUA_T_CFUNCTION, {indexFB}}, 1, 1},
|
|
|
- /* same default behavior of index FB */
|
|
|
-{"index", {LUA_T_CFUNCTION, {indexFB}}, 2, 1},
|
|
|
-{"error", {LUA_T_CFUNCTION, {errorFB}}, 1, 0}
|
|
|
-};
|
|
|
-
|
|
|
-#define N_FB (sizeof(luaI_fallBacks)/sizeof(struct FB))
|
|
|
-
|
|
|
-static int luaI_findevent (char *name)
|
|
|
-{
|
|
|
- int i;
|
|
|
- for (i=0; i<N_FB; i++)
|
|
|
- if (strcmp(luaI_fallBacks[i].kind, name) == 0)
|
|
|
- return i;
|
|
|
- /* name not found */
|
|
|
- lua_error("invalid event name");
|
|
|
- return 0; /* to avoid warnings */
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-void luaI_setfallback (void)
|
|
|
-{
|
|
|
- int i;
|
|
|
- char *name = lua_getstring(lua_getparam(1));
|
|
|
- lua_Object func = lua_getparam(2);
|
|
|
- if (name == NULL || !lua_isfunction(func))
|
|
|
- lua_error("incorrect argument to function `setfallback'");
|
|
|
- i = luaI_findevent(name);
|
|
|
- luaI_pushobject(&luaI_fallBacks[i].function);
|
|
|
- luaI_fallBacks[i].function = *luaI_Address(func);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static void errorFB (void)
|
|
|
-{
|
|
|
- lua_Object o = lua_getparam(1);
|
|
|
- if (lua_isstring(o))
|
|
|
- fprintf (stderr, "lua: %s\n", lua_getstring(o));
|
|
|
- else
|
|
|
- fprintf(stderr, "lua: unknown error\n");
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static void indexFB (void)
|
|
|
-{
|
|
|
- lua_pushnil();
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static void gettableFB (void)
|
|
|
-{
|
|
|
- lua_error("indexed expression not a table");
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static void arithFB (void)
|
|
|
-{
|
|
|
- lua_error("unexpected type at conversion to number");
|
|
|
-}
|
|
|
-
|
|
|
-static void concatFB (void)
|
|
|
-{
|
|
|
- lua_error("unexpected type at conversion to string");
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static void orderFB (void)
|
|
|
-{
|
|
|
- lua_error("unexpected type at comparison");
|
|
|
-}
|
|
|
-
|
|
|
-static void GDFB (void) { }
|
|
|
-
|
|
|
-static void funcFB (void)
|
|
|
-{
|
|
|
- lua_error("call expression not a function");
|
|
|
-}
|
|
|
|
|
|
|
|
|
/* -------------------------------------------
|
|
@@ -187,50 +89,127 @@ void luaI_invalidaterefs (void)
|
|
|
refArray[i].status = COLLECTED;
|
|
|
}
|
|
|
|
|
|
-char *luaI_travfallbacks (int (*fn)(Object *))
|
|
|
+
|
|
|
+/* -------------------------------------------
|
|
|
+* Internal Methods
|
|
|
+*/
|
|
|
+
|
|
|
+char *eventname[] = {
|
|
|
+ "gettable", /* IM_GETTABLE */
|
|
|
+ "arith", /* IM_ARITH */
|
|
|
+ "order", /* IM_ORDER */
|
|
|
+ "concat", /* IM_CONCAT */
|
|
|
+ "settable", /* IM_SETTABLE */
|
|
|
+ "gc", /* IM_GC */
|
|
|
+ "function", /* IM_FUNCTION */
|
|
|
+ "index", /* IM_INDEX */
|
|
|
+ NULL
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+char *geventname[] = {
|
|
|
+ "error", /* GIM_ERROR */
|
|
|
+ "getglobal", /* GIM_GETGLOBAL */
|
|
|
+ "setglobal", /* GIM_SETGLOBAL */
|
|
|
+ NULL
|
|
|
+};
|
|
|
+
|
|
|
+static int luaI_findevent (char *name, char *list[])
|
|
|
{
|
|
|
int i;
|
|
|
- for (i=0; i<N_FB; i++)
|
|
|
- if (fn(&luaI_fallBacks[i].function))
|
|
|
- return luaI_fallBacks[i].kind;
|
|
|
- return NULL;
|
|
|
+ for (i=0; list[i]; i++)
|
|
|
+ if (strcmp(list[i], name) == 0)
|
|
|
+ return i;
|
|
|
+ /* name not found */
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
+static int luaI_checkevent (char *name, char *list[])
|
|
|
+{
|
|
|
+ int e = luaI_findevent(name, list);
|
|
|
+ if (e < 0)
|
|
|
+ lua_error("invalid event name");
|
|
|
+ return e;
|
|
|
+}
|
|
|
|
|
|
-/* -------------------------------------------
|
|
|
-* Internal Methods
|
|
|
-*/
|
|
|
-#define BASE_TAG 1000
|
|
|
|
|
|
static struct IM {
|
|
|
lua_Type tp;
|
|
|
- Object int_method[FB_N];
|
|
|
- } *luaI_IMtable = NULL;
|
|
|
+ Object int_method[IM_N];
|
|
|
+} *luaI_IMtable = NULL;
|
|
|
+
|
|
|
static int IMtable_size = 0;
|
|
|
-static int last_tag = BASE_TAG-1;
|
|
|
+static int last_tag = LUA_T_NIL;
|
|
|
+
|
|
|
+static struct {
|
|
|
+ lua_Type t;
|
|
|
+ int event;
|
|
|
+} exceptions[] = { /* list of events that cannot be modified */
|
|
|
+ {LUA_T_NUMBER, IM_ARITH},
|
|
|
+ {LUA_T_NUMBER, IM_ORDER},
|
|
|
+ {LUA_T_NUMBER, IM_GC},
|
|
|
+ {LUA_T_STRING, IM_ARITH},
|
|
|
+ {LUA_T_STRING, IM_ORDER},
|
|
|
+ {LUA_T_STRING, IM_CONCAT},
|
|
|
+ {LUA_T_STRING, IM_GC},
|
|
|
+ {LUA_T_ARRAY, IM_GETTABLE},
|
|
|
+ {LUA_T_ARRAY, IM_SETTABLE},
|
|
|
+ {LUA_T_FUNCTION, IM_FUNCTION},
|
|
|
+ {LUA_T_FUNCTION, IM_GC},
|
|
|
+ {LUA_T_CFUNCTION, IM_FUNCTION},
|
|
|
+ {LUA_T_CFUNCTION, IM_GC},
|
|
|
+ {LUA_T_NIL, 0} /* flag end of list */
|
|
|
+};
|
|
|
|
|
|
-int lua_newtag (char *t)
|
|
|
+
|
|
|
+static int validevent (int t, int event)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ if (t == LUA_T_NIL) /* cannot modify any event for nil */
|
|
|
+ return 0;
|
|
|
+ for (i=0; exceptions[i].t != LUA_T_NIL; i++)
|
|
|
+ if (exceptions[i].t == t && exceptions[i].event == event)
|
|
|
+ return 0;
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+static void init_entry (int tag)
|
|
|
{
|
|
|
int i;
|
|
|
- ++last_tag;
|
|
|
- if ((last_tag-BASE_TAG) >= IMtable_size)
|
|
|
+ for (i=0; i<IM_N; i++)
|
|
|
+ luaI_IMtable[-tag].int_method[i].ttype = LUA_T_NIL;
|
|
|
+}
|
|
|
+
|
|
|
+void luaI_initfallbacks (void)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ IMtable_size = NUM_TYPES+10;
|
|
|
+ luaI_IMtable = newvector(IMtable_size, struct IM);
|
|
|
+ for (i=LUA_T_NIL; i<=LUA_T_USERDATA; i++) {
|
|
|
+ luaI_IMtable[-i].tp = (lua_Type)i;
|
|
|
+ init_entry(i);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int lua_newtag (char *t)
|
|
|
+{
|
|
|
+ --last_tag;
|
|
|
+ if ((-last_tag) >= IMtable_size)
|
|
|
IMtable_size = growvector(&luaI_IMtable, IMtable_size,
|
|
|
struct IM, memEM, MAX_INT);
|
|
|
if (strcmp(t, "table") == 0)
|
|
|
- luaI_IMtable[last_tag-BASE_TAG].tp = LUA_T_ARRAY;
|
|
|
+ luaI_IMtable[-last_tag].tp = LUA_T_ARRAY;
|
|
|
else if (strcmp(t, "userdata") == 0)
|
|
|
- luaI_IMtable[last_tag-BASE_TAG].tp = LUA_T_USERDATA;
|
|
|
+ luaI_IMtable[-last_tag].tp = LUA_T_USERDATA;
|
|
|
else
|
|
|
lua_error("invalid type for new tag");
|
|
|
- for (i=0; i<FB_N; i++)
|
|
|
- luaI_IMtable[last_tag-BASE_TAG].int_method[i].ttype = LUA_T_NIL;
|
|
|
+ init_entry(last_tag);
|
|
|
return last_tag;
|
|
|
}
|
|
|
|
|
|
-static int validtag (int tag)
|
|
|
-{
|
|
|
- return (BASE_TAG <= tag && tag <= last_tag);
|
|
|
-}
|
|
|
+
|
|
|
+#define validtag(tag) (last_tag <= (tag) && (tag) <= 0)
|
|
|
+
|
|
|
|
|
|
static void checktag (int tag)
|
|
|
{
|
|
@@ -238,10 +217,18 @@ static void checktag (int tag)
|
|
|
lua_error("invalid tag");
|
|
|
}
|
|
|
|
|
|
+lua_Type luaI_typetag (int tag)
|
|
|
+{
|
|
|
+ if (tag >= 0) return LUA_T_USERDATA;
|
|
|
+ else {
|
|
|
+ checktag(tag);
|
|
|
+ return luaI_IMtable[-tag].tp;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void luaI_settag (int tag, Object *o)
|
|
|
{
|
|
|
- checktag(tag);
|
|
|
- if (ttype(o) != luaI_IMtable[tag-BASE_TAG].tp)
|
|
|
+ if (ttype(o) != luaI_typetag(tag))
|
|
|
lua_error("Tag is not compatible with this type");
|
|
|
if (o->ttype == LUA_T_ARRAY)
|
|
|
o->value.a->htag = tag;
|
|
@@ -261,29 +248,123 @@ int luaI_tag (Object *o)
|
|
|
|
|
|
Object *luaI_getim (int tag, int event)
|
|
|
{
|
|
|
- if (tag == 0)
|
|
|
- return &luaI_fallBacks[event].function;
|
|
|
- else if (validtag(tag)) {
|
|
|
- Object *func = &luaI_IMtable[tag-BASE_TAG].int_method[event];
|
|
|
- if (func->ttype == LUA_T_NIL)
|
|
|
- return NULL;
|
|
|
- else
|
|
|
- return func;
|
|
|
- }
|
|
|
- else return NULL;
|
|
|
+ if (tag > LUA_T_USERDATA)
|
|
|
+ tag = LUA_T_USERDATA; /* default for non-registered tags */
|
|
|
+ return &luaI_IMtable[-tag].int_method[event];
|
|
|
+}
|
|
|
+
|
|
|
+Object *luaI_getimbyObj (Object *o, int event)
|
|
|
+{
|
|
|
+ return luaI_getim(luaI_tag(o), event);
|
|
|
}
|
|
|
|
|
|
void luaI_setintmethod (void)
|
|
|
{
|
|
|
- lua_Object tag = lua_getparam(1);
|
|
|
- lua_Object event = lua_getparam(2);
|
|
|
+ int t = (int)luaL_check_number(1, "setintmethod");
|
|
|
+ int e = luaI_checkevent(luaL_check_string(2, "setintmethod"), eventname);
|
|
|
lua_Object func = lua_getparam(3);
|
|
|
- if (!(lua_isnumber(tag) && lua_isstring(event) && lua_isfunction(func)))
|
|
|
- lua_error("incorrect arguments to function `setintmethod'");
|
|
|
- else {
|
|
|
- int i = luaI_findevent(lua_getstring(event));
|
|
|
- int t = lua_getnumber(tag);
|
|
|
- checktag(t);
|
|
|
- luaI_IMtable[t-BASE_TAG].int_method[i] = *luaI_Address(func);
|
|
|
+ if (!validevent(t, e))
|
|
|
+ lua_error("cannot change this internal method");
|
|
|
+ luaL_arg_check(lua_isnil(func) || lua_isfunction(func), "setintmethod",
|
|
|
+ 3, "function expected");
|
|
|
+ checktag(t);
|
|
|
+ luaI_IMtable[-t].int_method[e] = *luaI_Address(func);
|
|
|
+}
|
|
|
+
|
|
|
+static Object gmethod[GIM_N] = {
|
|
|
+ {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}
|
|
|
+};
|
|
|
+
|
|
|
+Object *luaI_getgim (int event)
|
|
|
+{
|
|
|
+ return &gmethod[event];
|
|
|
+}
|
|
|
+
|
|
|
+void luaI_setglobalmethod (void)
|
|
|
+{
|
|
|
+ int e = luaI_checkevent(luaL_check_string(1, "setintmethod"), geventname);
|
|
|
+ lua_Object func = lua_getparam(2);
|
|
|
+ luaL_arg_check(lua_isnil(func) || lua_isfunction(func), "setintmethod",
|
|
|
+ 2, "function expected");
|
|
|
+ gmethod[e] = *luaI_Address(func);
|
|
|
+}
|
|
|
+
|
|
|
+char *luaI_travfallbacks (int (*fn)(Object *))
|
|
|
+{ /* ??????????
|
|
|
+ int i;
|
|
|
+ for (i=0; i<N_FB; i++)
|
|
|
+ if (fn(&luaI_fallBacks[i].function))
|
|
|
+ return luaI_fallBacks[i].kind; */
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+* ===================================================================
|
|
|
+* compatibility with old fallback system
|
|
|
+*/
|
|
|
+
|
|
|
+
|
|
|
+static void errorFB (void)
|
|
|
+{
|
|
|
+ lua_Object o = lua_getparam(1);
|
|
|
+ if (lua_isstring(o))
|
|
|
+ fprintf (stderr, "lua: %s\n", lua_getstring(o));
|
|
|
+ else
|
|
|
+ fprintf(stderr, "lua: unknown error\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void nilFB (void) { }
|
|
|
+
|
|
|
+
|
|
|
+static void typeFB (void)
|
|
|
+{
|
|
|
+ lua_error("unexpected type");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void luaI_setfallback (void)
|
|
|
+{
|
|
|
+ int e;
|
|
|
+ char *name = luaL_check_string(1, "setfallback");
|
|
|
+ lua_Object func = lua_getparam(2);
|
|
|
+ luaL_arg_check(lua_isfunction(func), "setfallback", 2, "function expected");
|
|
|
+ e = luaI_findevent(name, geventname);
|
|
|
+ if (e >= 0) { /* global event */
|
|
|
+ switch (e) {
|
|
|
+ case GIM_ERROR:
|
|
|
+ gmethod[e] = *luaI_Address(func);
|
|
|
+ lua_pushcfunction(errorFB);
|
|
|
+ break;
|
|
|
+ case GIM_GETGLOBAL: /* goes through */
|
|
|
+ case GIM_SETGLOBAL:
|
|
|
+ gmethod[e] = *luaI_Address(func);
|
|
|
+ lua_pushcfunction(nilFB);
|
|
|
+ break;
|
|
|
+ default: lua_error("internal error");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else { /* tagged name? */
|
|
|
+ int t;
|
|
|
+ Object oldfunc;
|
|
|
+ e = luaI_checkevent(name, eventname);
|
|
|
+ oldfunc = luaI_IMtable[LUA_T_USERDATA].int_method[e];
|
|
|
+ for (t=LUA_T_NIL; t<=LUA_T_USERDATA; t++)
|
|
|
+ if (validevent(t, e))
|
|
|
+ luaI_IMtable[-t].int_method[e] = *luaI_Address(func);
|
|
|
+ if (oldfunc.ttype != LUA_T_NIL)
|
|
|
+ luaI_pushobject(&oldfunc);
|
|
|
+ else {
|
|
|
+ switch (e) {
|
|
|
+ case IM_GC: case IM_INDEX:
|
|
|
+ lua_pushcfunction(nilFB);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ lua_pushcfunction(typeFB);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+
|