/* ** fallback.c ** TecCGraf - PUC-Rio */ char *rcs_fallback="$Id: fallback.c,v 1.28 1997/03/19 19:41:10 roberto Exp roberto $"; #include #include #include "auxlib.h" #include "mem.h" #include "fallback.h" #include "opcode.h" #include "lua.h" #include "table.h" #include "tree.h" #include "hash.h" /* ------------------------------------------- ** Reference routines */ static struct ref { Object o; enum {LOCK, HOLD, FREE, COLLECTED} status; } *refArray = NULL; static int refSize = 0; int luaI_ref (Object *object, int lock) { int i; int oldSize; if (ttype(object) == LUA_T_NIL) return -1; /* special ref for nil */ for (i=0; i= 0 && ref < refSize) refArray[ref].status = FREE; } Object *luaI_getref (int ref) { static Object nul = {LUA_T_NIL, {0}}; if (ref == -1) return &nul; if (ref >= 0 && ref < refSize && (refArray[ref].status == LOCK || refArray[ref].status == HOLD)) return &refArray[ref].o; else return NULL; } void luaI_travlock (int (*fn)(Object *)) { int i; for (i=0; i= IMtable_size) IMtable_size = growvector(&luaI_IMtable, IMtable_size, struct IM, memEM, MAX_INT); if (strcmp(t, "table") == 0) luaI_IMtable[-last_tag].tp = LUA_T_ARRAY; else if (strcmp(t, "userdata") == 0) luaI_IMtable[-last_tag].tp = LUA_T_USERDATA; else lua_error("invalid type for new tag"); init_entry(last_tag); return last_tag; } #define validtag(tag) (last_tag <= (tag) && (tag) <= 0) static void checktag (int tag) { if (!validtag(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) { 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; else /* must be userdata */ o->value.ts->tag = tag; } int luaI_tag (Object *o) { lua_Type t = ttype(o); if (t == LUA_T_USERDATA) return o->value.ts->tag; else if (t == LUA_T_ARRAY) return o->value.a->htag; else return t; } Object *luaI_getim (int tag, int event) { 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) { 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 (!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_pushobject(&luaI_IMtable[-t].int_method[e]); 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"); luaI_pushobject(&gmethod[e]); gmethod[e] = *luaI_Address(func); } char *luaI_travfallbacks (int (*fn)(Object *)) { /* ?????????? int i; for (i=0; i= 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; } } } }