Imported from ../lua-3.0.tar.gz.
[lua.git] / src / table.c
blob6f24ca9b6e3ebdbf3e7b3d27b27f113cde3b961e
1 /*
2 ** table.c
3 ** Module to control static tables
4 */
6 char *rcs_table="$Id: table.c,v 2.72 1997/06/17 18:09:31 roberto Exp $";
8 #include "luamem.h"
9 #include "auxlib.h"
10 #include "func.h"
11 #include "opcode.h"
12 #include "tree.h"
13 #include "hash.h"
14 #include "table.h"
15 #include "inout.h"
16 #include "lua.h"
17 #include "fallback.h"
18 #include "luadebug.h"
21 #define BUFFER_BLOCK 256
23 Symbol *lua_table = NULL;
24 Word lua_ntable = 0;
25 static Long lua_maxsymbol = 0;
27 TaggedString **lua_constant = NULL;
28 Word lua_nconstant = 0;
29 static Long lua_maxconstant = 0;
32 #define GARBAGE_BLOCK 100
35 void luaI_initsymbol (void)
37 lua_maxsymbol = BUFFER_BLOCK;
38 lua_table = newvector(lua_maxsymbol, Symbol);
39 luaI_predefine();
44 ** Initialise constant table with pre-defined constants
46 void luaI_initconstant (void)
48 lua_maxconstant = BUFFER_BLOCK;
49 lua_constant = newvector(lua_maxconstant, TaggedString *);
50 /* pre-register mem error messages, to avoid loop when error arises */
51 luaI_findconstantbyname(tableEM);
52 luaI_findconstantbyname(memEM);
57 ** Given a name, search it at symbol table and return its index. If not
58 ** found, allocate it.
60 Word luaI_findsymbol (TaggedString *t)
62 if (t->u.s.varindex == NOT_USED)
64 if (lua_ntable == lua_maxsymbol)
65 lua_maxsymbol = growvector(&lua_table, lua_maxsymbol, Symbol,
66 symbolEM, MAX_WORD);
67 t->u.s.varindex = lua_ntable;
68 lua_table[lua_ntable].varname = t;
69 s_ttype(lua_ntable) = LUA_T_NIL;
70 lua_ntable++;
72 return t->u.s.varindex;
76 Word luaI_findsymbolbyname (char *name)
78 return luaI_findsymbol(luaI_createfixedstring(name));
83 ** Given a tree node, check it is has a correspondent constant index. If not,
84 ** allocate it.
86 Word luaI_findconstant (TaggedString *t)
88 if (t->u.s.constindex == NOT_USED)
90 if (lua_nconstant == lua_maxconstant)
91 lua_maxconstant = growvector(&lua_constant, lua_maxconstant, TaggedString *,
92 constantEM, MAX_WORD);
93 t->u.s.constindex = lua_nconstant;
94 lua_constant[lua_nconstant] = t;
95 lua_nconstant++;
97 return t->u.s.constindex;
101 Word luaI_findconstantbyname (char *name)
103 return luaI_findconstant(luaI_createfixedstring(name));
106 TaggedString *luaI_createfixedstring (char *name)
108 TaggedString *ts = lua_createstring(name);
109 if (!ts->marked)
110 ts->marked = 2; /* avoid GC */
111 return ts;
115 int luaI_globaldefined (char *name)
117 return ttype(&lua_table[luaI_findsymbolbyname(name)].object) != LUA_T_NIL;
122 ** Traverse symbol table objects
124 static char *lua_travsymbol (int (*fn)(TObject *))
126 Word i;
127 for (i=0; i<lua_ntable; i++)
128 if (fn(&s_object(i)))
129 return lua_table[i].varname->str;
130 return NULL;
135 ** Mark an object if it is a string or a unmarked array.
137 int lua_markobject (TObject *o)
138 {/* if already marked, does not change mark value */
139 if (ttype(o) == LUA_T_USERDATA ||
140 (ttype(o) == LUA_T_STRING && !tsvalue(o)->marked))
141 tsvalue(o)->marked = 1;
142 else if (ttype(o) == LUA_T_ARRAY)
143 lua_hashmark (avalue(o));
144 else if ((o->ttype == LUA_T_FUNCTION || o->ttype == LUA_T_MARK)
145 && !o->value.tf->marked)
146 o->value.tf->marked = 1;
147 return 0;
151 * returns 0 if the object is going to be (garbage) collected
153 int luaI_ismarked (TObject *o)
155 switch (o->ttype)
157 case LUA_T_STRING: case LUA_T_USERDATA:
158 return o->value.ts->marked;
159 case LUA_T_FUNCTION:
160 return o->value.tf->marked;
161 case LUA_T_ARRAY:
162 return o->value.a->mark;
163 default: /* nil, number, cfunction, or user data */
164 return 1;
169 static void call_nilIM (void)
170 { /* signals end of garbage collection */
171 TObject t;
172 ttype(&t) = LUA_T_NIL;
173 luaI_gcIM(&t); /* end of list */
177 ** Garbage collection.
178 ** Delete all unused strings and arrays.
180 static long gc_block = GARBAGE_BLOCK;
181 static long gc_nentity = 0; /* total of strings, arrays, etc */
183 static void markall (void)
185 lua_travstack(lua_markobject); /* mark stack objects */
186 lua_travsymbol(lua_markobject); /* mark symbol table objects */
187 luaI_travlock(lua_markobject); /* mark locked objects */
188 luaI_travfallbacks(lua_markobject); /* mark fallbacks */
192 long lua_collectgarbage (long limit)
194 long recovered = 0;
195 Hash *freetable;
196 TaggedString *freestr;
197 TFunc *freefunc;
198 markall();
199 luaI_invalidaterefs();
200 freetable = luaI_hashcollector(&recovered);
201 freestr = luaI_strcollector(&recovered);
202 freefunc = luaI_funccollector(&recovered);
203 gc_nentity -= recovered;
204 gc_block = (limit == 0) ? 2*(gc_block-recovered) : gc_nentity+limit;
205 luaI_hashcallIM(freetable);
206 luaI_strcallIM(freestr);
207 call_nilIM();
208 luaI_hashfree(freetable);
209 luaI_strfree(freestr);
210 luaI_funcfree(freefunc);
211 return recovered;
215 void lua_pack (void)
217 if (++gc_nentity >= gc_block)
218 lua_collectgarbage(0);
223 ** Internal function: return next global variable
225 void luaI_nextvar (void)
227 Word next;
228 if (lua_isnil(lua_getparam(1)))
229 next = 0;
230 else
231 next = luaI_findsymbolbyname(luaL_check_string(1)) + 1;
232 while (next < lua_ntable && s_ttype(next) == LUA_T_NIL)
233 next++;
234 if (next < lua_ntable) {
235 lua_pushstring(lua_table[next].varname->str);
236 luaI_pushobject(&s_object(next));
241 static TObject *functofind;
242 static int checkfunc (TObject *o)
244 if (o->ttype == LUA_T_FUNCTION)
245 return
246 ((functofind->ttype == LUA_T_FUNCTION || functofind->ttype == LUA_T_MARK)
247 && (functofind->value.tf == o->value.tf));
248 if (o->ttype == LUA_T_CFUNCTION)
249 return
250 ((functofind->ttype == LUA_T_CFUNCTION ||
251 functofind->ttype == LUA_T_CMARK) &&
252 (functofind->value.f == o->value.f));
253 return 0;
257 char *lua_getobjname (lua_Object o, char **name)
258 { /* try to find a name for given function */
259 functofind = luaI_Address(o);
260 if ((*name = luaI_travfallbacks(checkfunc)) != NULL)
261 return "tag-method";
262 else if ((*name = lua_travsymbol(checkfunc)) != NULL)
263 return "global";
264 else return "";