/* ** fallback.c ** TecCGraf - PUC-Rio */ char *rcs_fallback="$Id: fallback.c,v 2.7 1997/06/16 18:43:19 roberto Exp roberto $"; #include #include #include "auxlib.h" #include "luamem.h" #include "fallback.h" #include "opcode.h" #include "lua.h" #include "table.h" #include "tree.h" #include "hash.h" /* ------------------------------------------- ** 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); } init_entry(last_tag); return last_tag; } static void checktag (int tag) { if (!(last_tag <= tag && tag <= 0)) luaL_verror("%d is not a valid tag", tag); } void luaI_realtag (int tag) { if (!(last_tag <= tag && tag < LUA_T_NIL)) luaL_verror("tag %d is not result of `newtag'", tag); } void luaI_settag (int tag, TObject *o) { luaI_realtag(tag); switch (ttype(o)) { case LUA_T_ARRAY: o->value.a->htag = tag; break; case LUA_T_USERDATA: o->value.ts->tag = tag; break; default: luaL_verror("cannot change the tag of a %s", luaI_typenames[-ttype(o)]); } } int luaI_efectivetag (TObject *o) { lua_Type t = ttype(o); if (t == LUA_T_USERDATA) { int tag = o->value.ts->tag; return (tag >= 0) ? LUA_T_USERDATA : tag; } else if (t == LUA_T_ARRAY) return o->value.a->htag; else return t; } void luaI_gettagmethod (void) { int t = (int)luaL_check_number(1); int e = luaI_checkevent(luaL_check_string(2), luaI_eventname); checktag(t); if (validevent(t, e)) luaI_pushobject(luaI_getim(t,e)); } void luaI_settagmethod (void) { int t = (int)luaL_check_number(1); int e = luaI_checkevent(luaL_check_string(2), luaI_eventname); lua_Object func = lua_getparam(3); checktag(t); if (!validevent(t, e)) luaL_verror("cannot change internal method `%s' for tag %d", luaI_eventname[e], t); luaL_arg_check(lua_isnil(func) || lua_isfunction(func), 3, "function expected"); luaI_pushobject(luaI_getim(t,e)); *luaI_getim(t, e) = *luaI_Address(func); } static void stderrorim (void) { lua_Object s = lua_getparam(1); if (lua_isstring(s)) fprintf(stderr, "lua: %s\n", lua_getstring(s)); } static TObject errorim = {LUA_T_CFUNCTION, {stderrorim}}; TObject *luaI_geterrorim (void) { return &errorim; } void luaI_seterrormethod (void) { lua_Object func = lua_getparam(1); luaL_arg_check(lua_isnil(func) || lua_isfunction(func), 1, "function expected"); luaI_pushobject(&errorim); errorim = *luaI_Address(func); } char *luaI_travfallbacks (int (*fn)(TObject *)) { int e; if (fn(&errorim)) return "error"; for (e=IM_GETTABLE; e<=IM_FUNCTION; e++) { /* ORDER IM */ int t; for (t=0; t>=last_tag; t--) if (fn(luaI_getim(t,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_getim(t, e) = *func; } void luaI_setfallback (void) { static char *oldnames [] = {"error", "getglobal", "arith", "order", NULL}; TObject oldfunc; lua_CFunction replace; char *name = luaL_check_string(1); lua_Object func = lua_getparam(2); luaI_initfallbacks(); luaL_arg_check(lua_isfunction(func), 2, "function expected"); switch (luaI_findstring(name, oldnames)) { case 0: /* old error fallback */ oldfunc = errorim; errorim = *luaI_Address(func); replace = errorFB; break; case 1: /* old getglobal fallback */ oldfunc = *luaI_getim(LUA_T_NIL, IM_GETGLOBAL); *luaI_getim(LUA_T_NIL, IM_GETGLOBAL) = *luaI_Address(func); replace = nilFB; break; case 2: { /* old arith fallback */ int i; oldfunc = *luaI_getim(LUA_T_NUMBER, IM_POW); for (i=IM_ADD; i<=IM_UNM; i++) /* ORDER IM */ fillvalids(i, luaI_Address(func)); replace = typeFB; break; } case 3: { /* old order fallback */ int i; oldfunc = *luaI_getim(LUA_T_LINE, IM_LT); for (i=IM_LT; i<=IM_GE; i++) /* ORDER IM */ fillvalids(i, luaI_Address(func)); replace = typeFB; break; } default: { int e; if ((e = luaI_findstring(name, luaI_eventname)) >= 0) { oldfunc = *luaI_getim(LUA_T_LINE, e); fillvalids(e, luaI_Address(func)); replace = (e == IM_GC || e == IM_INDEX) ? nilFB : typeFB; } else { luaL_verror("`%s' is not a valid fallback name", name); replace = NULL; /* to avoid warnings */ } } } if (oldfunc.ttype != LUA_T_NIL) luaI_pushobject(&oldfunc); else lua_pushcfunction(replace); }