| #include <string.h> |
| |
| #include "luadebug.h" |
| #include "table.h" |
| #include "luamem.h" |
| #include "func.h" |
| #include "opcode.h" |
| |
| |
| static TFunc *function_root = NULL; |
| static LocVar *currvars = NULL; |
| static int numcurrvars = 0; |
| static int maxcurrvars = 0; |
| |
| |
| /* |
| ** Initialize TFunc struct |
| */ |
| void luaI_initTFunc (TFunc *f) |
| { |
| f->next = NULL; |
| f->marked = 0; |
| f->size = 0; |
| f->code = NULL; |
| f->lineDefined = 0; |
| f->fileName = NULL; |
| f->locvars = NULL; |
| } |
| |
| /* |
| ** Insert function in list for GC |
| */ |
| void luaI_insertfunction (TFunc *f) |
| { |
| lua_pack(); |
| f->next = function_root; |
| function_root = f; |
| f->marked = 0; |
| } |
| |
| |
| /* |
| ** Free function |
| */ |
| void luaI_freefunc (TFunc *f) |
| { |
| luaI_free (f->code); |
| luaI_free (f->locvars); |
| luaI_free (f); |
| } |
| |
| /* |
| ** Garbage collection function. |
| ** This function traverse the function list freeing unindexed functions |
| */ |
| Long luaI_funccollector (void) |
| { |
| TFunc *curr = function_root; |
| TFunc *prev = NULL; |
| Long counter = 0; |
| while (curr) |
| { |
| TFunc *next = curr->next; |
| if (!curr->marked) |
| { |
| if (prev == NULL) |
| function_root = next; |
| else |
| prev->next = next; |
| luaI_freefunc (curr); |
| ++counter; |
| } |
| else |
| { |
| curr->marked = 0; |
| prev = curr; |
| } |
| curr = next; |
| } |
| return counter; |
| } |
| |
| |
| void lua_funcinfo (lua_Object func, char **filename, int *linedefined) |
| { |
| TObject *f = luaI_Address(func); |
| if (f->ttype == LUA_T_MARK || f->ttype == LUA_T_FUNCTION) |
| { |
| *filename = f->value.tf->fileName; |
| *linedefined = f->value.tf->lineDefined; |
| } |
| else if (f->ttype == LUA_T_CMARK || f->ttype == LUA_T_CFUNCTION) |
| { |
| *filename = "(C)"; |
| *linedefined = -1; |
| } |
| } |
| |
| /* |
| ** Stores information to know that variable has been declared in given line |
| */ |
| void luaI_registerlocalvar (TaggedString *varname, int line) |
| { |
| if (numcurrvars >= maxcurrvars) |
| maxcurrvars = growvector(&currvars, maxcurrvars, LocVar, "", MAX_WORD); |
| currvars[numcurrvars].varname = varname; |
| currvars[numcurrvars].line = line; |
| numcurrvars++; |
| } |
| |
| /* |
| ** Stores information to know that variable has been out of scope in given line |
| */ |
| void luaI_unregisterlocalvar (int line) |
| { |
| luaI_registerlocalvar(NULL, line); |
| } |
| |
| /* |
| ** Copies "currvars" into a new area and store it in function header. |
| ** The values (varname = NULL, line = -1) signal the end of vector. |
| */ |
| void luaI_closelocalvars (TFunc *func) |
| { |
| func->locvars = newvector (numcurrvars+1, LocVar); |
| memcpy (func->locvars, currvars, numcurrvars*sizeof(LocVar)); |
| func->locvars[numcurrvars].varname = NULL; |
| func->locvars[numcurrvars].line = -1; |
| numcurrvars = 0; /* prepares for next function */ |
| } |
| |
| /* |
| ** Look for n-esim local variable at line "line" in function "func". |
| ** Returns NULL if not found. |
| */ |
| char *luaI_getlocalname (TFunc *func, int local_number, int line) |
| { |
| int count = 0; |
| char *varname = NULL; |
| LocVar *lv = func->locvars; |
| if (lv == NULL) |
| return NULL; |
| for (; lv->line != -1 && lv->line < line; lv++) |
| { |
| if (lv->varname) /* register */ |
| { |
| if (++count == local_number) |
| varname = lv->varname->str; |
| } |
| else /* unregister */ |
| if (--count < local_number) |
| varname = NULL; |
| } |
| return varname; |
| } |
| |