| /* |
| ** table.c |
| ** Module to control static tables |
| */ |
| |
| char *rcs_table="$Id: table.c,v 2.73 1997/07/07 16:44:26 roberto Exp roberto $"; |
| |
| #include "luamem.h" |
| #include "auxlib.h" |
| #include "func.h" |
| #include "opcode.h" |
| #include "tree.h" |
| #include "hash.h" |
| #include "table.h" |
| #include "inout.h" |
| #include "lua.h" |
| #include "fallback.h" |
| #include "luadebug.h" |
| |
| |
| #define BUFFER_BLOCK 256 |
| |
| Symbol *lua_table = NULL; |
| Word lua_ntable = 0; |
| static Long lua_maxsymbol = 0; |
| |
| |
| #define GARBAGE_BLOCK 100 |
| |
| |
| static TaggedString *luaI_createfixedstring (char *name) |
| { |
| TaggedString *ts = luaI_createstring(name); |
| luaI_fixstring(ts); |
| return ts; |
| } |
| |
| void luaI_initsymbol (void) |
| { |
| lua_maxsymbol = BUFFER_BLOCK; |
| lua_table = newvector(lua_maxsymbol, Symbol); |
| luaI_predefine(); |
| } |
| |
| |
| void luaI_initconstant (void) |
| { |
| /* pre-register mem error messages, to avoid loop when error arises */ |
| luaI_createfixedstring(tableEM); |
| luaI_createfixedstring(memEM); |
| } |
| |
| |
| /* |
| ** Given a name, search it at symbol table and return its index. If not |
| ** found, allocate it. |
| */ |
| Word luaI_findsymbol (TaggedString *t) |
| { |
| if (t->u.s.varindex == NOT_USED) |
| { |
| if (lua_ntable == lua_maxsymbol) |
| lua_maxsymbol = growvector(&lua_table, lua_maxsymbol, Symbol, |
| symbolEM, MAX_WORD); |
| t->u.s.varindex = lua_ntable; |
| lua_table[lua_ntable].varname = t; |
| s_ttype(lua_ntable) = LUA_T_NIL; |
| lua_ntable++; |
| } |
| return t->u.s.varindex; |
| } |
| |
| |
| Word luaI_findsymbolbyname (char *name) |
| { |
| return luaI_findsymbol(luaI_createfixedstring(name)); |
| } |
| |
| |
| void luaI_releasestring (TaggedString *t) |
| { |
| if (t->marked == 2) /* string has temporary mark? */ |
| t->marked = 0; |
| } |
| |
| |
| void luaI_fixstring (TaggedString *t) |
| { |
| if (t->marked < 3) |
| t->marked = 3; /* avoid GC */ |
| } |
| |
| |
| TaggedString *luaI_createtempstring (char *name) |
| { |
| TaggedString *ts = luaI_createstring(name); |
| if (!ts->marked) |
| ts->marked = 2; /* avoid (temporarily) GC */ |
| return ts; |
| } |
| |
| |
| int luaI_globaldefined (char *name) |
| { |
| return ttype(&lua_table[luaI_findsymbolbyname(name)].object) != LUA_T_NIL; |
| } |
| |
| |
| /* |
| ** Traverse symbol table objects |
| */ |
| static char *lua_travsymbol (int (*fn)(TObject *)) |
| { |
| Word i; |
| for (i=0; i<lua_ntable; i++) |
| if (fn(&s_object(i))) |
| return lua_table[i].varname->str; |
| return NULL; |
| } |
| |
| |
| int lua_markobject (TObject *o) |
| {/* if already marked, does not change mark value */ |
| if (ttype(o) == LUA_T_USERDATA || |
| (ttype(o) == LUA_T_STRING && !tsvalue(o)->marked)) |
| tsvalue(o)->marked = 1; |
| else if (ttype(o) == LUA_T_ARRAY) |
| lua_hashmark (avalue(o)); |
| else if ((o->ttype == LUA_T_FUNCTION || o->ttype == LUA_T_MARK) |
| && !o->value.tf->marked) |
| luaI_funcmark(o->value.tf); |
| return 0; |
| } |
| |
| /* |
| * returns 0 if the object is going to be (garbage) collected |
| */ |
| int luaI_ismarked (TObject *o) |
| { |
| switch (o->ttype) |
| { |
| case LUA_T_STRING: case LUA_T_USERDATA: |
| return o->value.ts->marked; |
| case LUA_T_FUNCTION: |
| return o->value.tf->marked; |
| case LUA_T_ARRAY: |
| return o->value.a->mark; |
| default: /* nil, number, cfunction, or user data */ |
| return 1; |
| } |
| } |
| |
| |
| static void call_nilIM (void) |
| { /* signals end of garbage collection */ |
| TObject t; |
| ttype(&t) = LUA_T_NIL; |
| luaI_gcIM(&t); /* end of list */ |
| } |
| |
| /* |
| ** Garbage collection. |
| ** Delete all unused strings and arrays. |
| */ |
| static long gc_block = GARBAGE_BLOCK; |
| static long gc_nentity = 0; /* total of strings, arrays, etc */ |
| |
| static void markall (void) |
| { |
| lua_travstack(lua_markobject); /* mark stack objects */ |
| lua_travsymbol(lua_markobject); /* mark symbol table objects */ |
| luaI_travlock(lua_markobject); /* mark locked objects */ |
| luaI_travfallbacks(lua_markobject); /* mark fallbacks */ |
| } |
| |
| |
| long lua_collectgarbage (long limit) |
| { |
| long recovered = 0; |
| Hash *freetable; |
| TaggedString *freestr; |
| TFunc *freefunc; |
| markall(); |
| luaI_invalidaterefs(); |
| freetable = luaI_hashcollector(&recovered); |
| freestr = luaI_strcollector(&recovered); |
| freefunc = luaI_funccollector(&recovered); |
| gc_nentity -= recovered; |
| gc_block = (limit == 0) ? 2*(gc_block-recovered) : gc_nentity+limit; |
| luaI_hashcallIM(freetable); |
| luaI_strcallIM(freestr); |
| call_nilIM(); |
| luaI_hashfree(freetable); |
| luaI_strfree(freestr); |
| luaI_funcfree(freefunc); |
| /*printf("total %d coletados %d\n", (int)gc_nentity, (int)recovered);*/ |
| return recovered; |
| } |
| |
| |
| void lua_pack (void) |
| { |
| if (++gc_nentity >= gc_block) |
| lua_collectgarbage(0); |
| } |
| |
| |
| /* |
| ** Internal function: return next global variable |
| */ |
| void luaI_nextvar (void) |
| { |
| Word next = lua_isnil(lua_getparam(1)) ? 0 : |
| luaI_findsymbolbyname(luaL_check_string(1))+1; |
| if (next != 0) |
| luaL_arg_check(s_ttype(next-1)!=LUA_T_NIL, 1, "undefined global name"); |
| while (next < lua_ntable && s_ttype(next) == LUA_T_NIL) |
| next++; |
| if (next < lua_ntable) { |
| lua_pushstring(lua_table[next].varname->str); |
| luaI_pushobject(&s_object(next)); |
| } |
| } |
| |
| |
| static TObject *functofind; |
| static int checkfunc (TObject *o) |
| { |
| if (o->ttype == LUA_T_FUNCTION) |
| return |
| ((functofind->ttype == LUA_T_FUNCTION || functofind->ttype == LUA_T_MARK) |
| && (functofind->value.tf == o->value.tf)); |
| if (o->ttype == LUA_T_CFUNCTION) |
| return |
| ((functofind->ttype == LUA_T_CFUNCTION || |
| functofind->ttype == LUA_T_CMARK) && |
| (functofind->value.f == o->value.f)); |
| return 0; |
| } |
| |
| |
| char *lua_getobjname (lua_Object o, char **name) |
| { /* try to find a name for given function */ |
| functofind = luaI_Address(o); |
| if ((*name = luaI_travfallbacks(checkfunc)) != NULL) |
| return "tag-method"; |
| else if ((*name = lua_travsymbol(checkfunc)) != NULL) |
| return "global"; |
| else return ""; |
| } |
| |