/* ** fallback.c ** TecCGraf - PUC-Rio */ char *rcs_fallback="$Id: fallback.c,v 1.33 1997/03/24 17:13:22 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" static char *typenames[] = { /* ORDER LUA_T */ "userdata", "line", "cmark", "mark", "function", "function", "table", "string", "number", "nil", NULL }; void luaI_type (void) { lua_Object o = lua_getparam(1); luaL_arg_check(o != LUA_NOOBJECT, "type", 1, "no argument"); lua_pushstring(typenames[-ttype(luaI_Address(o))]); lua_pushnumber(lua_tag(o)); } /* ------------------------------------------- ** Reference routines */ static struct ref { TObject o; enum {LOCK, HOLD, FREE, COLLECTED} status; } *refArray = NULL; static int refSize = 0; int luaI_ref (TObject *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; } TObject *luaI_getref (int ref) { static TObject 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)(TObject *)) { int i; for (i=0; i= IMtable_size) { luaI_initfallbacks(); IMtable_size = growvector(&luaI_IMtable, IMtable_size, struct IM, memEM, MAX_INT); } tp = -findstring(t, typenames); if (tp == LUA_T_ARRAY || tp == LUA_T_USERDATA) luaI_IMtable[-last_tag].tp = tp; else lua_error("invalid type for new tag"); init_entry(last_tag); return last_tag; } static void checktag (int tag) { if (!(last_tag <= (tag) && (tag) <= 0)) 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, TObject *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 (TObject *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; } TObject *luaI_getim (int tag, IMS event) { if (tag > LUA_T_USERDATA) tag = LUA_T_USERDATA; /* default for non-registered tags */ return &luaI_IMtable[-tag].int_method[event]; } void luaI_setintmethod (void) { int t = (int)luaL_check_number(1, "setintmethod"); int e = luaI_checkevent(luaL_check_string(2, "setintmethod"), luaI_eventname); lua_Object func = lua_getparam(3); checktag(t); if (!validevent(t, e)) lua_error("cannot change this internal method"); luaL_arg_check(lua_isnil(func) || lua_isfunction(func), "setintmethod", 3, "function expected"); luaI_pushobject(&luaI_IMtable[-t].int_method[e]); luaI_IMtable[-t].int_method[e] = *luaI_Address(func); } static TObject gmethod[GIM_N] = { {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}} }; TObject *luaI_getgim (IMGS 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)(TObject *)) { int e; for (e=GIM_ERROR; e<=GIM_SETGLOBAL; e++) { /* ORDER GIM */ if (fn(&gmethod[e])) return geventname[e]; } for (e=IM_GETTABLE; e<=IM_FUNCTION; e++) { /* ORDER IM */ int t; for (t=0; t>=last_tag; t--) if (fn(&luaI_IMtable[-t].int_method[e])) return luaI_eventname[e]; } 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"); } static void fillvalids (IMS e, TObject *func) { int t; for (t=LUA_T_NIL; t<=LUA_T_USERDATA; t++) if (validevent(t, e)) luaI_IMtable[-t].int_method[e] = *func; } void luaI_setfallback (void) { int e; TObject oldfunc; lua_CFunction replace; char *name = luaL_check_string(1, "setfallback"); lua_Object func = lua_getparam(2); luaL_arg_check(lua_isfunction(func), "setfallback", 2, "function expected"); e = findstring(name, geventname); if (e >= 0) { /* global event */ oldfunc = gmethod[e]; gmethod[e] = *luaI_Address(func); replace = (e == GIM_ERROR) ? errorFB : nilFB; } else if ((e = findstring(name, luaI_eventname)) >= 0) { oldfunc = luaI_IMtable[LUA_T_USERDATA].int_method[e]; fillvalids(e, luaI_Address(func)); replace = (e == IM_GC || e == IM_INDEX) ? nilFB : typeFB; } else if (strcmp(name, "arith") == 0) { /* old arith fallback */ int i; oldfunc = luaI_IMtable[LUA_T_USERDATA].int_method[IM_POW]; for (i=IM_ADD; i<=IM_UNM; i++) /* ORDER IM */ fillvalids(i, luaI_Address(func)); replace = typeFB; } else if (strcmp(name, "order") == 0) { /* old order fallback */ int i; oldfunc = luaI_IMtable[LUA_T_USERDATA].int_method[IM_LT]; for (i=IM_LT; i<=IM_GE; i++) /* ORDER IM */ fillvalids(i, luaI_Address(func)); replace = typeFB; } else { lua_error("invalid fallback name"); replace = NULL; /* to avoid warnings */ } if (oldfunc.ttype != LUA_T_NIL) luaI_pushobject(&oldfunc); else lua_pushcfunction(replace); }