static int mark_root_table(lua_State* L, lua_State* dL, int type) { int len = 0; lua_pushnil(L); while (lua_next(L, -2) != 0) { ++len; if (LUA_TTABLE == lua_type(L, -1)) { lua_pushvalue(L, -2); make_root(dL, lua_topointer(L, -2), lua_tostring(L, -1), type, NULL, 1); lua_pop(L, 1); mark_table(L, dL); lua_pop(dL, 1); } else { make_root(dL, lua_topointer(L, -1), "FUNCTION", type, NULL, 0); mark_object(L, dL); lua_pop(dL, 1); } lua_pop(L, 1); make_root(dL, lua_topointer(L, -1), "[KEY]", type, NULL, LUA_TTABLE == lua_type(L, -1)); mark_object(L, dL); lua_pop(dL, 1); } return len; }
static void mark_userdata(lua_State *L, lua_State *dL, const void * parent, const char *desc) { const void * t = readobject(L, dL, parent, desc); if (t == NULL) return; if (lua_getmetatable(L, -1)) { mark_table(L, dL, t, "[metatable]"); } lua_getuservalue(L,-1); if (lua_isnil(L,-1)) { lua_pop(L,2); } else { mark_table(L, dL, t, "[uservalue]"); lua_pop(L,1); } }
void gncTaxTableSetChild (GncTaxTable *table, GncTaxTable *child) { if (!table) return; gncTaxTableBeginEdit (table); table->child = child; mark_table (table); gncTaxTableCommitEdit (table); }
void gncTaxTableSetName (GncTaxTable *table, const char *name) { if (!table || !name) return; SET_STR (table, table->name, name); mark_table (table); maybe_resort_list (table); gncTaxTableCommitEdit (table); }
void gncTaxTableSetRefcount (GncTaxTable *table, gint64 refcount) { if (!table) return; g_return_if_fail (refcount >= 0); gncTaxTableBeginEdit (table); table->refcount = refcount; mark_table (table); gncTaxTableCommitEdit (table); }
void gncTaxTableIncRef (GncTaxTable *table) { if (!table) return; if (table->parent || table->invisible) return; /* children dont need refcounts */ gncTaxTableBeginEdit (table); table->refcount++; mark_table (table); gncTaxTableCommitEdit (table); }
void gncTaxTableRemoveEntry (GncTaxTable *table, GncTaxTableEntry *entry) { if (!table || !entry) return; gncTaxTableBeginEdit (table); entry->table = NULL; table->entries = g_list_remove (table->entries, entry); mark_table (table); mod_table (table); gncTaxTableCommitEdit (table); }
void gncTaxTableDecRef (GncTaxTable *table) { if (!table) return; if (table->parent || table->invisible) return; /* children dont need refcounts */ g_return_if_fail (table->refcount > 0); gncTaxTableBeginEdit (table); table->refcount--; mark_table (table); gncTaxTableCommitEdit (table); }
void gncTaxTableEntrySetAmount (GncTaxTableEntry *entry, gnc_numeric amount) { if (!entry) return; if (gnc_numeric_eq (entry->amount, amount)) return; entry->amount = amount; if (entry->table) { mark_table (entry->table); mod_table (entry->table); } }
void gncTaxTableEntrySetType (GncTaxTableEntry *entry, GncAmountType type) { if (!entry) return; if (entry->type == type) return; entry->type = type; if (entry->table) { mark_table (entry->table); mod_table (entry->table); } }
void gncTaxTableEntrySetAccount (GncTaxTableEntry *entry, Account *account) { if (!entry || !account) return; if (entry->account == account) return; entry->account = account; if (entry->table) { mark_table (entry->table); mod_table (entry->table); } }
static void mark_object(lua_State *L, lua_State *dL) { switch (lua_type(L, -1)) { case LUA_TTABLE: mark_table(L, dL); break; case LUA_TFUNCTION: mark_function(L, dL); break; default: break; } }
void gncTaxTableSetParent (GncTaxTable *table, GncTaxTable *parent) { if (!table) return; gncTaxTableBeginEdit (table); if (table->parent) gncTaxTableRemoveChild(table->parent, table); table->parent = parent; if (parent) gncTaxTableAddChild(parent, table); table->refcount = 0; gncTaxTableMakeInvisible (table); mark_table (table); gncTaxTableCommitEdit (table); }
void gncTaxTableAddEntry (GncTaxTable *table, GncTaxTableEntry *entry) { if (!table || !entry) return; if (entry->table == table) return; /* already mine */ gncTaxTableBeginEdit (table); if (entry->table) gncTaxTableRemoveEntry (entry->table, entry); entry->table = table; table->entries = g_list_insert_sorted (table->entries, entry, (GCompareFunc)gncTaxTableEntryCompare); mark_table (table); mod_table (table); gncTaxTableCommitEdit (table); }
static void mark_table(lua_State *L, lua_State *dL, const void * parent, const char * desc) { const void * t = readobject(L, dL, parent, desc); if (t == NULL) return; bool weakk = false; bool weakv = false; if (lua_getmetatable(L, -1)) { lua_pushliteral(L, "__mode"); lua_rawget(L, -2); if (lua_isstring(L,-1)) { const char *mode = lua_tostring(L, -1); if (strchr(mode, 'k')) { weakk = true; } if (strchr(mode, 'v')) { weakv = true; } } lua_pop(L,1); luaL_checkstack(L, LUA_MINSTACK, NULL); mark_table(L, dL, t, "[metatable]"); } lua_pushnil(L); while (lua_next(L, -2) != 0) { if (weakv) { lua_pop(L,1); } else { char temp[32]; const char * desc = keystring(L, -2, temp); mark_object(L, dL, t , desc); } if (!weakk) { lua_pushvalue(L,-1); mark_object(L, dL, t , "[key]"); } } lua_pop(L,1); }
static void mark_object(lua_State *L, lua_State *dL, const void * parent, const char *desc) { int t = lua_type(L, -1); switch (t) { case LUA_TTABLE: mark_table(L, dL, parent, desc); break; case LUA_TUSERDATA: mark_userdata(L, dL, parent, desc); break; case LUA_TFUNCTION: mark_function(L, dL, parent, desc); break; case LUA_TTHREAD: mark_thread(L, dL, parent, desc); break; default: lua_pop(L,1); break; } }