| /* |
| ** table.c |
| ** Module to control static tables |
| */ |
| |
| char *rcs_table="$Id: table.c,v 2.37 1995/10/26 14:21:56 roberto Exp roberto $"; |
| |
| /*#include <string.h>*/ |
| |
| #include "mem.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; |
| static Word lua_ntable = 0; |
| static Long lua_maxsymbol = 0; |
| |
| TaggedString **lua_constant = NULL; |
| static Word lua_nconstant = 0; |
| static Long lua_maxconstant = 0; |
| |
| |
| #define GARBAGE_BLOCK 1024 |
| #define MIN_GARBAGE_BLOCK (GARBAGE_BLOCK/2) |
| |
| static void lua_nextvar (void); |
| static void setglobal (void); |
| static void getglobal (void); |
| |
| /* |
| ** Initialise symbol table with internal functions |
| */ |
| static void lua_initsymbol (void) |
| { |
| Word n; |
| lua_maxsymbol = BUFFER_BLOCK; |
| lua_table = newvector(lua_maxsymbol, Symbol); |
| n = luaI_findsymbolbyname("next"); |
| s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_next; |
| n = luaI_findsymbolbyname("dofile"); |
| s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_internaldofile; |
| n = luaI_findsymbolbyname("setglobal"); |
| s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = setglobal; |
| n = luaI_findsymbolbyname("getglobal"); |
| s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = getglobal; |
| n = luaI_findsymbolbyname("nextvar"); |
| s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_nextvar; |
| n = luaI_findsymbolbyname("type"); |
| s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = luaI_type; |
| n = luaI_findsymbolbyname("tonumber"); |
| s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_obj2number; |
| n = luaI_findsymbolbyname("print"); |
| s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_print; |
| n = luaI_findsymbolbyname("dostring"); |
| s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_internaldostring; |
| n = luaI_findsymbolbyname("setfallback"); |
| s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = luaI_setfallback; |
| n = luaI_findsymbolbyname("error"); |
| s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = luaI_error; |
| } |
| |
| |
| /* |
| ** Initialise constant table with pre-defined constants |
| */ |
| void lua_initconstant (void) |
| { |
| lua_maxconstant = BUFFER_BLOCK; |
| lua_constant = newvector(lua_maxconstant, TaggedString *); |
| } |
| |
| |
| /* |
| ** Given a name, search it at symbol table and return its index. If not |
| ** found, allocate it. |
| */ |
| Word luaI_findsymbol (TreeNode *t) |
| { |
| if (lua_table == NULL) |
| lua_initsymbol(); |
| if (t->varindex == NOT_USED) |
| { |
| if (lua_ntable == lua_maxsymbol) |
| { |
| if (lua_maxsymbol >= MAX_WORD) |
| lua_error("symbol table overflow"); |
| lua_maxsymbol *= 2; |
| if (lua_maxsymbol >= MAX_WORD) |
| lua_maxsymbol = MAX_WORD; |
| lua_table = growvector(lua_table, lua_maxsymbol, Symbol); |
| } |
| t->varindex = lua_ntable; |
| s_tag(lua_ntable) = LUA_T_NIL; |
| lua_ntable++; |
| } |
| return t->varindex; |
| } |
| |
| |
| Word luaI_findsymbolbyname (char *name) |
| { |
| return luaI_findsymbol(lua_constcreate(name)); |
| } |
| |
| |
| /* |
| ** Given a tree node, check it is has a correspondent constant index. If not, |
| ** allocate it. |
| */ |
| Word luaI_findconstant (TreeNode *t) |
| { |
| if (lua_constant == NULL) |
| lua_initconstant(); |
| if (t->constindex == NOT_USED) |
| { |
| if (lua_nconstant == lua_maxconstant) |
| { |
| if (lua_maxconstant >= MAX_WORD) |
| lua_error("constant table overflow"); |
| lua_maxconstant *= 2; |
| if (lua_maxconstant >= MAX_WORD) |
| lua_maxconstant = MAX_WORD; |
| lua_constant = growvector(lua_constant, lua_maxconstant, TaggedString *); |
| } |
| t->constindex = lua_nconstant; |
| lua_constant[lua_nconstant] = &(t->ts); |
| lua_nconstant++; |
| } |
| return t->constindex; |
| } |
| |
| |
| Word luaI_findconstantbyname (char *name) |
| { |
| return luaI_findconstant(lua_constcreate(name)); |
| } |
| |
| |
| /* |
| ** Traverse symbol table objects |
| */ |
| static char *lua_travsymbol (int (*fn)(Object *)) |
| { |
| Word i; |
| for (i=0; i<lua_ntable; i++) |
| if (fn(&s_object(i))) |
| return luaI_nodebysymbol(i)->ts.str; |
| return NULL; |
| } |
| |
| |
| /* |
| ** Mark an object if it is a string or a unmarked array. |
| */ |
| int lua_markobject (Object *o) |
| { |
| if (tag(o) == LUA_T_STRING && !tsvalue(o)->marked) |
| tsvalue(o)->marked = 1; |
| else if (tag(o) == LUA_T_ARRAY) |
| lua_hashmark (avalue(o)); |
| else if ((o->tag == LUA_T_FUNCTION || o->tag == LUA_T_MARK) |
| && !o->value.tf->marked) |
| o->value.tf->marked = 1; |
| return 0; |
| } |
| |
| |
| /* |
| ** Garbage collection. |
| ** Delete all unused strings and arrays. |
| */ |
| void lua_pack (void) |
| { |
| static Long block = GARBAGE_BLOCK; /* when garbage collector will be called */ |
| static Long nentity = 0; /* counter of new entities (strings and arrays) */ |
| Long recovered = 0; |
| if (nentity++ < block) return; |
| 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 */ |
| recovered += lua_strcollector(); |
| recovered += lua_hashcollector(); |
| recovered += luaI_funccollector(); |
| nentity = 0; /* reset counter */ |
| block=(16*block-7*recovered)/12; /* adapt block size */ |
| if (block < MIN_GARBAGE_BLOCK) block = MIN_GARBAGE_BLOCK; |
| } |
| |
| |
| /* |
| ** Internal function: return next global variable |
| */ |
| static void lua_nextvar (void) |
| { |
| Word next; |
| lua_Object o = lua_getparam(1); |
| if (o == LUA_NOOBJECT) |
| lua_error("too few arguments to function `nextvar'"); |
| if (lua_getparam(2) != LUA_NOOBJECT) |
| lua_error("too many arguments to function `nextvar'"); |
| if (lua_isnil(o)) |
| next = 0; |
| else if (!lua_isstring(o)) |
| { |
| lua_error("incorrect argument to function `nextvar'"); |
| return; /* to avoid warnings */ |
| } |
| else |
| next = luaI_findsymbolbyname(lua_getstring(o)) + 1; |
| while (next < lua_ntable && s_tag(next) == LUA_T_NIL) next++; |
| if (next >= lua_ntable) |
| { |
| lua_pushnil(); |
| lua_pushnil(); |
| } |
| else |
| { |
| TreeNode *t = luaI_nodebysymbol(next); |
| Object name; |
| tag(&name) = LUA_T_STRING; |
| tsvalue(&name) = &(t->ts); |
| luaI_pushobject(&name); |
| luaI_pushobject(&s_object(next)); |
| } |
| } |
| |
| |
| static void setglobal (void) |
| { |
| lua_Object name = lua_getparam(1); |
| lua_Object value = lua_getparam(2); |
| if (!lua_isstring(name)) |
| lua_error("incorrect argument to function `setglobal'"); |
| lua_pushobject(value); |
| lua_storeglobal(lua_getstring(name)); |
| } |
| |
| |
| static void getglobal (void) |
| { |
| lua_Object name = lua_getparam(1); |
| if (!lua_isstring(name)) |
| lua_error("incorrect argument to function `getglobal'"); |
| lua_pushobject(lua_getglobal(lua_getstring(name))); |
| } |
| |
| |
| static Object *functofind; |
| static int checkfunc (Object *o) |
| { |
| if (o->tag == LUA_T_FUNCTION) |
| return |
| ((functofind->tag == LUA_T_FUNCTION || functofind->tag == LUA_T_MARK) |
| && (functofind->value.tf == o->value.tf)); |
| if (o->tag == LUA_T_CFUNCTION) |
| return |
| ((functofind->tag == LUA_T_CFUNCTION || functofind->tag == LUA_T_CMARK) |
| && (functofind->value.f == o->value.f)); |
| return 0; |
| } |
| |
| |
| char *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 "fallback"; |
| else if ((*name = lua_travsymbol(checkfunc)) != NULL) |
| return "global"; |
| else return ""; |
| } |
| |