/*************************************************************************** * Copyright (C) 2013 by Chris Mitchell * * * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "LuaInterface.h" #include "TVar.h" #include "VarUnit.h" #include static jmp_buf buf; LuaInterface::LuaInterface(Host * pH) :mpHost(pH) { interpreter = mpHost->getLuaInterpreter(); mHostID = mpHost->getHostID(); varUnit = new VarUnit(); //set our panic function lua_atpanic( interpreter->pGlobalLua, &onPanic ); } int LuaInterface::onPanic( lua_State * L ) { QString error = "Lua Panic, No error information"; if ( lua_isstring( L, -1 ) ) { error = lua_tostring( L, -1 ); //there's never anything but the error on the stack // qDebug()<<"stack dump:"; // for (int j=1;j<=lua_gettop(L);j++){ // int ltype = lua_type(L, j*-1); // QString value; // if (ltype == LUA_TNUMBER || ltype == LUA_TSTRING || // ltype == LUA_TBOOLEAN) // value = lua_tostring(L, j*-1); // qDebug()<<"index"<getName() == "_G"){ names << ""; return names; } names << var->getName(); TVar * p = var->getParent(); while (p && p->getName() != "_G"){ names.insert(0,p->getName()); p = p->getParent(); } return names; } bool LuaInterface::validMove(QTreeWidgetItem * p){ TVar * newParent = varUnit->getWVar(p); if (newParent && newParent->getValueType() != LUA_TTABLE) return false; return true; } void LuaInterface::getAllChildren( TVar * var, QList * list){ QListIterator it(var->getChildren()); if (varUnit->isSaved(var) || var->saved) list->append(var); else qDebug()<<"t"<getName()<<"not saved"; while (it.hasNext()){ TVar * child = it.next(); if (child->getValueType() == LUA_TTABLE) getAllChildren( child, list); else if (varUnit->isSaved(child) || var->saved) list->append(child); else qDebug()<getName()<<"not saved"; } } bool LuaInterface::loadKey(lua_State * L, TVar * var){ if (setjmp(buf) == 0){ int kType = var->getKeyType(); if ( var->isReference() ){ lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt()); } else{ if ( kType == LUA_TNUMBER ){ lua_pushnumber(L, var->getName().toInt()); } else if ( kType == LUA_TTABLE ){ } else if ( kType == LUA_TBOOLEAN ){ lua_pushboolean(L, var->getName().toLower() == "true" ? 1 : 0 ); } else{ lua_pushstring(L, var->getName().toLatin1().data()); } } qDebug()<<"key"<getName()<getName()<getValueType(); return lua_type(L, -1) == var->getValueType(); } qDebug()<<"panic error in loadValue"; return false; } //bool LuaInterface::reparentCVariable(TVar * from , TVar * to, TVar * curVar){ // //get the old parent on the stack // if (setjmp(buf) == 0){ // int startSize = lua_gettop(L); // bool isSaved = varUnit->isSaved(curVar); // if (isSaved){ // QList list; // getAllChildren(curVar, &list); // QListIterator it(list); // while (it.hasNext()){ // TVar * t = it.next(); // varUnit->removeSavedVar(t); // } // } // qDebug()<<"stack before we start"; // for (int j=1;j<=lua_gettop(L);j++){ // qDebug()< vars = varOrder(curVar); // lua_getglobal(L, (vars[0]->getName()).toLatin1().data()); // int i=1; // int kType; // for( ; igetKeyType(); // if ( kType == LUA_TNUMBER ){ // lua_pushnumber(L, QString(vars[i]->getName()).toInt()); // } // else if ( kType == LUA_TTABLE ){ // lua_rawgeti(L, LUA_REGISTRYINDEX, vars[i]->getName().toInt()); // } // else{ // lua_pushstring(L, QString(vars[i]->getName()).toLatin1().data()); // } // lua_gettable(L, -2); // if (lua_isnil(L, -1)) // return false; // } // //at this point we have the value we want to put under // //a new parent at the -1 position of the stack, we want // //just this value, so we move it to the bottom and pop // //everything else // lua_insert(L,lua_gettop(L)); // lua_pop(L, lua_gettop(L)-1); // //push the key back // kType = curVar->getKeyType(); // if ( kType == LUA_TNUMBER ){ // lua_pushnumber(L, QString(curVar->getName()).toInt()); // } // else if ( kType == LUA_TTABLE ){ // lua_rawgeti(L, LUA_REGISTRYINDEX, curVar->getName().toInt()); // } // else{ // lua_pushstring(L, QString(curVar->getName()).toLatin1().data()); // } // //swap the key and value positions // lua_insert(L, -2); // qDebug()<<"old parent with value on stack"; // for (int j=1;j<=lua_gettop(L);j++){ // qDebug()<getName(); // from->removeChild(curVar); // curVar->setParent(to); // to->addChild(curVar); // vars = varOrder(curVar); // qDebug()<<"new vars"<getName()).toLatin1().data()); // i=1; // int pushCount=0; // for( ; igetKeyType(); // qDebug()<getName(); // if ( kType == LUA_TNUMBER ){ // lua_pushnumber(L, QString(vars[i]->getName()).toInt()); // lua_pushnumber(L, QString(vars[i]->getName()).toInt()); // } // else if ( kType == LUA_TTABLE ){ // lua_rawgeti(L, LUA_REGISTRYINDEX, vars[i]->getName().toInt()); // lua_rawgeti(L, LUA_REGISTRYINDEX, vars[i]->getName().toInt()); // } // else{ // lua_pushstring(L, QString(vars[i]->getName()).toLatin1().data()); // lua_pushstring(L, QString(vars[i]->getName()).toLatin1().data()); // } // lua_gettable(L, -3); // pushCount+=1; // if (lua_isnil(L, -1)){ // //value didn't exist, make it // lua_pop(L, 2); // if ( kType == LUA_TNUMBER ){ // lua_pushnumber(L, QString(vars[i]->getName()).toInt()); // } // else if ( kType == LUA_TTABLE ){ // lua_rawgeti(L, LUA_REGISTRYINDEX, vars[i]->getName().toInt()); // } // else{ // lua_pushstring(L, QString(vars[i]->getName()).toLatin1().data()); // } // lua_newtable(L); // lua_settable(L, -3); // i--;//decrement since we want to reput this table on the stack on next iteration // } // } // qDebug()<<"new stack fully loaded"; // for (int j=1;j<=lua_gettop(L);j++){ // qDebug()<getName().toLatin1().data()); // for (int j=1;j<=lua_gettop(L);j++){ // qDebug()< list; // list.append(to); // getAllChildren(curVar, &list); // QListIterator it(list); // while (it.hasNext()){ // TVar * t = it.next(); // qDebug()<getName(); // varUnit->addSavedVar(t); // } // } // lua_settop(L, startSize); // return true; // } // else{ // qDebug()<<"panic in reparentCVariable"; // return false; // } //} bool LuaInterface::reparentCVariable(TVar * from , TVar * to, TVar * curVar){ //get the old parent on the stack if (setjmp(buf) == 0){ if ((!from && !to) || (from==to))//moving from global to global or nowhere return true; int stackSize = lua_gettop(L); bool isSaved = varUnit->isSaved(curVar); if (isSaved){ QList list; getAllChildren(curVar, &list); QListIterator it(list); while (it.hasNext()){ TVar * t = it.next(); varUnit->removeSavedVar(t); } } QList vars = varOrder(curVar); lua_getglobal(L, (vars[0]->getName()).toLatin1().data()); qDebug()<removeChild(curVar); curVar->setParent(to); to->addChild(curVar); vars = varOrder(curVar); //do the actual reparenting part if (to == varUnit->getBase()){ //we're going global lua_setglobal(L, curVar->getName().toLatin1().data()); } else{ lua_getglobal(L, (vars[0]->getName()).toLatin1().data()); i=1; for( ; igetBase()){ lua_pushnil(L); lua_setglobal(L, curVar->getName().toLatin1().data()); } else{ if (!loadKey(L, curVar)){ lua_settop(L, stackSize); return false; } lua_pushnil(L); if (!lua_istable(L,-3)){ lua_settop(L, stackSize); return false; } lua_settable(L, -3); } if (isSaved){ QList list; list.append(to); getAllChildren(curVar, &list); QListIterator it(list); while (it.hasNext()){ TVar * t = it.next(); varUnit->addSavedVar(t); } } for (int j=1;j<=lua_gettop(L);j++){ qDebug()<pGlobalLua; TVar * newParent = varUnit->getWVar(newP); TVar * curVar = varUnit->getWVar(cItem); TVar * oldParent = varUnit->getWVar(oldP); qDebug()<getValueType() != LUA_TTABLE ){ qDebug()<<"attempt to move to a non-table"; return false; } if ( !newParent && !oldParent ){ //happens when we move from _G to _G return false; } else if ( !oldParent ){ from = varUnit->getBase(); to = newParent; } else if ( !newParent ){ from = oldParent; to = varUnit->getBase(); } if ( !from && !to ) return false; return reparentCVariable( from, to, curVar); bool isSaved = varUnit->isSaved(curVar); if (isSaved){ QList list; getAllChildren(curVar, &list); QListIterator it(list); while (it.hasNext()){ TVar * t = it.next(); qDebug()<getName(); varUnit->removeSavedVar(t); } } QList vars = varOrder(curVar); QString oldName = vars[0]->getName(); for(int i=1;iisReference()) return reparentCVariable( from, to, curVar); if (vars[i]->getKeyType() == LUA_TNUMBER){ oldName.append("["+vars[i]->getName()+"]"); } else{ oldName.append("[\""+vars[i]->getName()+"\"]"); } } from->removeChild(curVar); curVar->setParent(to); to->addChild(curVar); vars = varOrder(curVar); QString newName = vars[0]->getName(); for(int i=1;iisReference()) return reparentCVariable( from, to, curVar); if (vars[i]->getKeyType() == LUA_TNUMBER){ newName.append("["+vars[i]->getName()+"]"); } else{ newName.append("[\""+vars[i]->getName()+"\"]"); } } QString addString = QString(newName+" = "+oldName); qDebug()< list; list.append(to); getAllChildren(curVar, &list); QListIterator it(list); while (it.hasNext()){ TVar * t = it.next(); qDebug()<getName(); varUnit->addSavedVar(t); } } return true; } QList LuaInterface::varOrder(TVar * var){ QList vars; if (var->getName() == "_G"){ return vars; } vars << var; TVar * p = var->getParent(); while (p && p->getName() != "_G"){ vars.insert(0,p); p = p->getParent(); } return vars; } void LuaInterface::createVar( TVar * var ){ setValue( var ); } bool LuaInterface::setCValue( QList vars ){ //make the new stack TVar * var = vars.back(); if (setjmp(buf) == 0){ int stackSize = lua_gettop(L); lua_getglobal(L, (vars[0]->getName()).toLatin1().data()); int i=1; for( ; igetValueType() ){ case LUA_TSTRING: lua_pushstring(L, var->getValue().toLatin1().data()); break; case LUA_TNUMBER: lua_pushnumber(L, var->getValue().toInt()); break; case LUA_TBOOLEAN: lua_pushboolean(L, var->getValue().toLower() == "true" ? 1 : 0); break; case LUA_TTABLE: lua_newtable(L); break; default: lua_settop(L, stackSize); return false; } //set it up if (lua_type(L, -1) != var->getValueType()){ lua_settop(L, stackSize); return false; } lua_settable(L, -3); } else{ qDebug()<<"panic in setCValue"; return false; } return true; } bool LuaInterface::setValue( TVar * var ){ //This function assumes the var has been modified and then called L = interpreter->pGlobalLua; // QStringList names = varName( var ); //if our outer most name is a number, we need to use [] notation // QString toDo; QList vars = varOrder(var); QString newName = vars[0]->getName(); for(int i=1;iisReference()) return setCValue( vars ); if (vars[i]->getKeyType() == LUA_TNUMBER){ newName.append("["+vars[i]->getName()+"]"); } else{ newName.append("[\""+vars[i]->getName()+"\"]"); } } switch ( var->getValueType() ){ case LUA_TSTRING: newName.append(QString(" = [["+var->getValue()+"]]")); break; case LUA_TNUMBER: newName.append(QString(" = "+var->getValue())); break; case LUA_TBOOLEAN: newName.append(QString(" = "+var->getValue())); break; case LUA_TTABLE: newName.append(QString(" = {}")); break; default: return false; } luaL_loadstring(L, newName.toLatin1().data()); qDebug()<pGlobalLua; QList vars = varOrder(var); QString oldName = vars[0]->getName(); for(int i=1;igetKeyType() == LUA_TNUMBER){ oldName.append("["+vars[i]->getName()+"]"); } else{ oldName.append("[\""+vars[i]->getName()+"\"]"); } } //delete it oldName.append(QString(" = nil")); luaL_loadstring(L, oldName.toLatin1().data()); int error = lua_pcall(L, 0, LUA_MULTRET, 0); if (error){ QString emsg = lua_tostring(L, -1); qDebug()< vars ){ //uses C Api to rename a variable. //dangerous function since you can get an api panic //and trash the stack L = interpreter->pGlobalLua; TVar * var = vars.back(); //make the new stack lua_getglobal(L, (vars[0]->getName()).toLatin1().data()); if (setjmp(buf) == 0){ int i=1; int pushCount=0; int kType; for( ; igetKeyType(); if ( kType == LUA_TNUMBER ){ lua_pushnumber(L, QString(vars[i]->getName()).toInt()); } else if ( kType == LUA_TTABLE ){ lua_rawgeti(L, LUA_REGISTRYINDEX, vars[i]->getName().toInt()); } else{ lua_pushstring(L, QString(vars[i]->getName()).toLatin1().data()); } lua_gettable(L, -2); if (lua_isnil(L, -1)){ //value didn't exist, make it lua_pop(L, -1); if ( kType == LUA_TNUMBER ){ lua_pushnumber(L, QString(vars[i]->getName()).toInt()); } else if ( kType == LUA_TTABLE || kType == LUA_TFUNCTION){ lua_rawgeti(L, LUA_REGISTRYINDEX, vars[i]->getName().toInt()); } else{ lua_pushstring(L, QString(vars[i]->getName()).toLatin1().data()); } lua_newtable(L); lua_settable(L, -3); i--;//decrement since we want to reput this table on the stack on next iteration } } kType = var->getKeyType(); if ( kType == LUA_TSTRING ){ lua_pushstring(L, QString(var->getNewName()).toLatin1().data()); } else if ( kType == LUA_TNUMBER ){ lua_pushnumber(L, var->getNewName().toInt()); } else if ( kType == LUA_TTABLE ){ lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt()); } else{ qDebug()<<"unknown key type"<getKeyType(); //lua_pop(L,pCount); return; } qDebug()<<"new stack fully loaded"; for (int j=1;j<=lua_gettop(L);j++){ qDebug()<getName()).toLatin1().data()); i=1; for( ; igetKeyType(); if ( kType == LUA_TNUMBER ){ lua_pushnumber(L, QString(vars[i]->getName()).toInt()); } else if ( kType == LUA_TTABLE || kType == LUA_TFUNCTION){ lua_rawgeti(L, LUA_REGISTRYINDEX, vars[i]->getName().toInt()); } else{ lua_pushstring(L, QString(vars[i]->getName()).toLatin1().data()); } lua_gettable(L, -2); pushCount++; } kType = var->getKeyType(); if ( kType == LUA_TSTRING ){ lua_pushstring(L, QString(var->getName()).toLatin1().data()); } else if ( kType == LUA_TNUMBER ){ lua_pushnumber(L, var->getName().toInt()); } else if ( kType == LUA_TTABLE || kType == LUA_TFUNCTION ){ lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt()); } else{ qDebug()<<"unknown key type"<getKeyType(); //lua_pop(L,pCount); return; } lua_gettable(L, -2); pushCount++; qDebug()<<"old value fully loaded"; for (int j=1;j<=lua_gettop(L);j++){ qDebug()<getKeyType(); if ( kType == LUA_TSTRING ){ qDebug()<getNewName(); lua_pushstring(L, QString(var->getNewName()).toLatin1().data()); } else if ( kType == LUA_TNUMBER ){ lua_pushnumber(L, var->getNewName().toInt()); } else if ( kType == LUA_TTABLE ){ lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt()); } else{ qDebug()<<"unknown key type"<getKeyType(); //lua_pop(L,pCount); return; } pushCount++; lua_insert(L, -2); qDebug()<getKeyType(); qDebug()<getName(); if ( kType == LUA_TSTRING ){ lua_pushstring(L, QString(var->getName()).toLatin1().data()); } else if ( kType == LUA_TNUMBER ){ lua_pushnumber(L, var->getName().toInt()); } else if ( kType == LUA_TTABLE || kType == LUA_TFUNCTION ){ lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt()); } else{ qDebug()<<"unknown key type"<getKeyType(); //lua_pop(L,pCount); return; } lua_pushnil(L); for (int j=1;j<=lua_gettop(L);j++){ qDebug()<clearNewName(); } else{ qDebug()<<"panic in renameCVar"; } } bool LuaInterface::loadVar( TVar* var ){ //puts the value of a variable on the -1 position of the stack if (setjmp(buf) == 0){ L = interpreter->pGlobalLua; int kType = var->getKeyType(); int vType = var->getValueType(); if (vType == LUA_TTABLE){ if ( kType == LUA_TNUMBER ){ lua_pushnumber(L, QString(var->getName()).toInt()); } else if ( kType == LUA_TTABLE ){ lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt()); } else{ lua_pushstring(L, QString(var->getName()).toLatin1().data()); } if (lua_istable(L,-2)){ lua_gettable(L, -2); return true; } else{ lua_pop(L,1); return false; } } else if ( vType == LUA_TNUMBER ) lua_pushnumber(L, QString(var->getValue()).toInt()); else if ( vType == LUA_TBOOLEAN ) lua_pushboolean(L, var->getValue().toLower() == "true" ? 1 : 0); else if ( vType == LUA_TSTRING ) lua_pushstring(L, QString(var->getName()).toLatin1().data()); else return false; } else{ qDebug()<<"panic in loadVar"; return false; } return true; } void LuaInterface::renameVar( TVar * var ){ //this assumes anything like reparenting has been done L = interpreter->pGlobalLua; QList vars = varOrder(var); QString oldName = vars[0]->getName(); QString newName; qDebug()< 1) newName = vars[0]->getName(); for(int i=1;igetKeyType(); if (kType == LUA_TNUMBER){ oldName.append("["+vars[i]->getName()+"]"); if (i < vars.size()-1 ) newName.append("["+vars[i]->getName()+"]"); } else if (kType == LUA_TTABLE){ renameCVar(vars); return; } else{ oldName.append("[\""+vars[i]->getName()+"\"]"); if (i < vars.size()-1 ) newName.append("[\""+vars[i]->getName()+"\"]"); } } if (var->getNewKeyType() == LUA_TNUMBER) newName.append("["+vars.back()->getNewName()+"]"); else newName.append("[\""+vars.back()->getNewName()+"\"]"); QString addString = QString(newName+" = "+oldName); qDebug()<getName()<<"to"<getNewName()<<"with error"<clearNewName(); return; } //delete it oldName.append(QString(" = nil")); luaL_loadstring(L, oldName.toLatin1().data()); error = lua_pcall(L, 0, LUA_MULTRET, 0); if (error){ QString emsg = lua_tostring(L, -1); qDebug()<clearNewName(); } //QString LuaInterface::getValue( TVar * var ){ // //let's find it. // L = interpreter->pGlobalLua; // QList vars = varOrder(var); // //QStringList names = varName(var); // if (vars.empty()) // return ""; // int pCount = vars.size();//how many things we need to pop at the end // lua_getglobal(L, (vars[0]->getName()).toLatin1().data()); // int i=1; // for( ; igetName()<getKeyType(); // int kType = vars[i]->getKeyType(); // if ( kType == LUA_TNUMBER ){ // lua_pushnumber(L, QString(vars[i]->getName()).toInt()); // } // else if ( kType == LUA_TTABLE ){ // lua_rawgeti(L, LUA_REGISTRYINDEX, vars[i]->getName().toInt()); // } // else{ // lua_pushstring(L, QString(vars[i]->getName()).toLatin1().data()); // } // lua_gettable(L, -2); // } // if (vars.size()>1){ //// for (int i=1;i<=lua_gettop(L);i++){ //// qDebug()<getKeyType(); // if ( kType == LUA_TSTRING ){ // lua_pushstring(L, QString(var->getName()).toLatin1().data()); // } // else if ( kType == LUA_TNUMBER ){ // lua_pushnumber(L, var->getName().toInt()); // } // else if ( kType == LUA_TTABLE || kType == LUA_TFUNCTION ){ // lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt()); // } // else{ // qDebug()<<"unknown key type"<getKeyType(); // lua_pop(L,pCount); // return ""; // } // lua_gettable(L, -2); // } // int vType = lua_type(L, -1); // QString value = ""; // if (vType == LUA_TBOOLEAN) // value = lua_toboolean(L, -1) == 0 ? "false" : "true"; // else if (vType == LUA_TNUMBER || vType == LUA_TSTRING) // value = lua_tostring(L, -1); // lua_pop(L,pCount); // return value; //} QString LuaInterface::getValue( TVar * var ){ qDebug()<<"attempting getValue"; if (setjmp(buf) == 0){ L = interpreter->pGlobalLua; QList vars = varOrder(var); if (vars.empty()) return ""; int pCount = vars.size();//how many things we need to pop at the end //load from _G first lua_getglobal(L, (vars[0]->getName()).toLatin1().data()); for(int i=1; isetReference(true); } else{ keyName = lua_tostring(L, -1); if ( kType == LUA_TFUNCTION && keyName.isEmpty() ){ //we lost the reference keyName = QString::number(luaL_ref(L, LUA_REGISTRYINDEX)); lrefs.append(keyName.toInt()); var->setReference(true); } else lua_pop(L, 1); } // qDebug()<<"key type/value:"<removeChild(var); delete var; continue; } var->setName(keyName, kType); var->setValueType(vType); var->setParent(tVar); var->hidden = hide; tVar->addChild(var); const void* kp = lua_topointer(L, -1); var->kpointer = kp; const void* vp = lua_topointer(L, -2); var->vpointer = vp; if ( varUnit->varExists(var) || keyName == "_G" ){ lua_pop(L, 1); // qDebug()<<"removing dup"<removeChild(var); delete var; continue; } varUnit->addVariable(var); //lua_pushvalue(L, -1); varUnit->addPointer(kp); // lua_pop(L, 1); // lua_pushvalue(L, -2); varUnit->addPointer(vp); // lua_pop(L, 1); if (vType == LUA_TTABLE){ if (depth<=99 && lua_checkstack(L,3)){//depth is historical now //put the table on top lua_pushnil(L); var->setValue("{}", LUA_TTABLE); // qDebug()<<"entering table"<varExists(var); // for (int i=1;i<=lua_gettop(L);i++){ // qDebug()<setValue(valueName); lua_pop(L,1); } else if (vType == LUA_TBOOLEAN){ valueName = lua_toboolean(L, -1) == 0 ? "false" : "true"; var->setValue(valueName); } else if (vType == LUA_TFUNCTION && (!keyName.toLower().startsWith("alias") && !keyName.toLower().startsWith("trigger") && !keyName.toLower().startsWith("action") && !keyName.toLower().startsWith("timer") && !keyName.toLower().startsWith("key"))){ //functions are compiled to bytecode so there is no reference // lua_pushvalue(L,-1); // valueName = lua_tostring(L,-1); var->setValue("function"); // lua_pop(L,1); } else{ tVar->removeChild(var); varUnit->removeVariable(var); delete var; } // qDebug()<<"var added"<getName(); lua_pop(L, 1); } } void LuaInterface::getVars( bool hide ){ //returns the base item QTime t; t.start(); L = interpreter->pGlobalLua; lua_pushnil(L); depth = 0; TVar * g = new TVar(); g->setName("_G", LUA_TSTRING); g->setValue("{}", LUA_TTABLE); QListIterator it(lrefs); while(it.hasNext()){ int ref = it.next(); luaL_unref(L, LUA_REGISTRYINDEX, ref); } varUnit->clear(); varUnit->setBase(g); varUnit->addVariable(g); iterateTable( L, LUA_GLOBALSINDEX, g, hide ); qDebug()<<"took"<